1 // SPDX-License-Identifier: Apache-2.0 2 // SPDX-FileCopyrightText: Copyright OpenBMC Authors 3 #pragma once 4 5 #include <boost/asio/ip/address.hpp> 6 #include <boost/asio/ip/address_v4.hpp> 7 #include <boost/asio/ip/address_v6.hpp> 8 9 #include <string> 10 11 namespace redfish 12 { 13 namespace ip_util 14 { 15 16 /** 17 * @brief Converts boost::asio::ip::address to string 18 * Will automatically convert IPv4-mapped IPv6 address back to IPv4. 19 * 20 * @param[in] ipAddr IP address to convert 21 * 22 * @return IP address string 23 */ 24 inline std::string toString(const boost::asio::ip::address& ipAddr) 25 { 26 if (ipAddr.is_v6() && ipAddr.to_v6().is_v4_mapped()) 27 { 28 return boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, 29 ipAddr.to_v6()) 30 .to_string(); 31 } 32 return ipAddr.to_string(); 33 } 34 35 /** 36 * @brief Helper function that verifies IP address to check if it is in 37 * proper format. If bits pointer is provided, also calculates active 38 * bit count for Subnet Mask. 39 * 40 * @param[in] ip IP that will be verified 41 * @param[out] bits Calculated mask in bits notation 42 * 43 * @return true in case of success, false otherwise 44 */ 45 inline bool ipv4VerifyIpAndGetBitcount(const std::string& ip, 46 uint8_t* prefixLength = nullptr) 47 { 48 boost::system::error_code ec; 49 boost::asio::ip::address_v4 addr = boost::asio::ip::make_address_v4(ip, ec); 50 if (ec) 51 { 52 return false; 53 } 54 55 if (prefixLength != nullptr) 56 { 57 uint8_t prefix = 0; 58 boost::asio::ip::address_v4::bytes_type maskBytes = addr.to_bytes(); 59 bool maskFinished = false; 60 for (unsigned char byte : maskBytes) 61 { 62 if (maskFinished) 63 { 64 if (byte != 0U) 65 { 66 return false; 67 } 68 continue; 69 } 70 switch (byte) 71 { 72 case 255: 73 prefix += 8; 74 break; 75 case 254: 76 prefix += 7; 77 maskFinished = true; 78 break; 79 case 252: 80 prefix += 6; 81 maskFinished = true; 82 break; 83 case 248: 84 prefix += 5; 85 maskFinished = true; 86 break; 87 case 240: 88 prefix += 4; 89 maskFinished = true; 90 break; 91 case 224: 92 prefix += 3; 93 maskFinished = true; 94 break; 95 case 192: 96 prefix += 2; 97 maskFinished = true; 98 break; 99 case 128: 100 prefix += 1; 101 maskFinished = true; 102 break; 103 case 0: 104 maskFinished = true; 105 break; 106 default: 107 // Invalid netmask 108 return false; 109 } 110 } 111 *prefixLength = prefix; 112 } 113 114 return true; 115 } 116 117 } // namespace ip_util 118 } // namespace redfish 119