140e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 240e9b92eSEd Tanous // SPDX-FileCopyrightText: Copyright OpenBMC Authors 341d61c82SJiaqing Zhao #pragma once 441d61c82SJiaqing Zhao 541d61c82SJiaqing Zhao #include <boost/asio/ip/address.hpp> 6d5c80ad9SNan Zhou #include <boost/asio/ip/address_v4.hpp> 7d5c80ad9SNan Zhou #include <boost/asio/ip/address_v6.hpp> 841d61c82SJiaqing Zhao 9*d7857201SEd Tanous #include <cstdint> 1041d61c82SJiaqing Zhao #include <string> 1141d61c82SJiaqing Zhao 1241d61c82SJiaqing Zhao namespace redfish 1341d61c82SJiaqing Zhao { 1441d61c82SJiaqing Zhao namespace ip_util 1541d61c82SJiaqing Zhao { 1641d61c82SJiaqing Zhao 1741d61c82SJiaqing Zhao /** 1841d61c82SJiaqing Zhao * @brief Converts boost::asio::ip::address to string 1941d61c82SJiaqing Zhao * Will automatically convert IPv4-mapped IPv6 address back to IPv4. 2041d61c82SJiaqing Zhao * 2141d61c82SJiaqing Zhao * @param[in] ipAddr IP address to convert 2241d61c82SJiaqing Zhao * 2341d61c82SJiaqing Zhao * @return IP address string 2441d61c82SJiaqing Zhao */ 2541d61c82SJiaqing Zhao inline std::string toString(const boost::asio::ip::address& ipAddr) 2641d61c82SJiaqing Zhao { 2741d61c82SJiaqing Zhao if (ipAddr.is_v6() && ipAddr.to_v6().is_v4_mapped()) 2841d61c82SJiaqing Zhao { 2941d61c82SJiaqing Zhao return boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, 3041d61c82SJiaqing Zhao ipAddr.to_v6()) 3141d61c82SJiaqing Zhao .to_string(); 3241d61c82SJiaqing Zhao } 3341d61c82SJiaqing Zhao return ipAddr.to_string(); 3441d61c82SJiaqing Zhao } 3541d61c82SJiaqing Zhao 36033f1e4dSEd Tanous /** 37033f1e4dSEd Tanous * @brief Helper function that verifies IP address to check if it is in 38033f1e4dSEd Tanous * proper format. If bits pointer is provided, also calculates active 39033f1e4dSEd Tanous * bit count for Subnet Mask. 40033f1e4dSEd Tanous * 41033f1e4dSEd Tanous * @param[in] ip IP that will be verified 42033f1e4dSEd Tanous * @param[out] bits Calculated mask in bits notation 43033f1e4dSEd Tanous * 44033f1e4dSEd Tanous * @return true in case of success, false otherwise 45033f1e4dSEd Tanous */ 46033f1e4dSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string& ip, 473a4ad5d9SEd Tanous uint8_t* prefixLength = nullptr) 48033f1e4dSEd Tanous { 493a4ad5d9SEd Tanous boost::system::error_code ec; 503a4ad5d9SEd Tanous boost::asio::ip::address_v4 addr = boost::asio::ip::make_address_v4(ip, ec); 513a4ad5d9SEd Tanous if (ec) 52033f1e4dSEd Tanous { 53033f1e4dSEd Tanous return false; 54033f1e4dSEd Tanous } 55033f1e4dSEd Tanous 563a4ad5d9SEd Tanous if (prefixLength != nullptr) 57033f1e4dSEd Tanous { 583a4ad5d9SEd Tanous uint8_t prefix = 0; 593a4ad5d9SEd Tanous boost::asio::ip::address_v4::bytes_type maskBytes = addr.to_bytes(); 603a4ad5d9SEd Tanous bool maskFinished = false; 613a4ad5d9SEd Tanous for (unsigned char byte : maskBytes) 62033f1e4dSEd Tanous { 633a4ad5d9SEd Tanous if (maskFinished) 643a4ad5d9SEd Tanous { 653a4ad5d9SEd Tanous if (byte != 0U) 66033f1e4dSEd Tanous { 67033f1e4dSEd Tanous return false; 68033f1e4dSEd Tanous } 693a4ad5d9SEd Tanous continue; 703a4ad5d9SEd Tanous } 713a4ad5d9SEd Tanous switch (byte) 72033f1e4dSEd Tanous { 733a4ad5d9SEd Tanous case 255: 743a4ad5d9SEd Tanous prefix += 8; 753a4ad5d9SEd Tanous break; 763a4ad5d9SEd Tanous case 254: 773a4ad5d9SEd Tanous prefix += 7; 783a4ad5d9SEd Tanous maskFinished = true; 793a4ad5d9SEd Tanous break; 803a4ad5d9SEd Tanous case 252: 813a4ad5d9SEd Tanous prefix += 6; 823a4ad5d9SEd Tanous maskFinished = true; 833a4ad5d9SEd Tanous break; 843a4ad5d9SEd Tanous case 248: 853a4ad5d9SEd Tanous prefix += 5; 863a4ad5d9SEd Tanous maskFinished = true; 873a4ad5d9SEd Tanous break; 883a4ad5d9SEd Tanous case 240: 893a4ad5d9SEd Tanous prefix += 4; 903a4ad5d9SEd Tanous maskFinished = true; 913a4ad5d9SEd Tanous break; 923a4ad5d9SEd Tanous case 224: 933a4ad5d9SEd Tanous prefix += 3; 943a4ad5d9SEd Tanous maskFinished = true; 953a4ad5d9SEd Tanous break; 963a4ad5d9SEd Tanous case 192: 973a4ad5d9SEd Tanous prefix += 2; 983a4ad5d9SEd Tanous maskFinished = true; 993a4ad5d9SEd Tanous break; 1003a4ad5d9SEd Tanous case 128: 1013a4ad5d9SEd Tanous prefix += 1; 1023a4ad5d9SEd Tanous maskFinished = true; 1033a4ad5d9SEd Tanous break; 1043a4ad5d9SEd Tanous case 0: 1053a4ad5d9SEd Tanous maskFinished = true; 1063a4ad5d9SEd Tanous break; 1073a4ad5d9SEd Tanous default: 1083a4ad5d9SEd Tanous // Invalid netmask 109033f1e4dSEd Tanous return false; 110033f1e4dSEd Tanous } 111033f1e4dSEd Tanous } 1123a4ad5d9SEd Tanous *prefixLength = prefix; 113033f1e4dSEd Tanous } 114033f1e4dSEd Tanous 115033f1e4dSEd Tanous return true; 116033f1e4dSEd Tanous } 117033f1e4dSEd Tanous 11841d61c82SJiaqing Zhao } // namespace ip_util 11941d61c82SJiaqing Zhao } // namespace redfish 120