1*40e9b92eSEd Tanous // SPDX-License-Identifier: Apache-2.0 2*40e9b92eSEd 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 941d61c82SJiaqing Zhao #include <string> 1041d61c82SJiaqing Zhao 1141d61c82SJiaqing Zhao namespace redfish 1241d61c82SJiaqing Zhao { 1341d61c82SJiaqing Zhao namespace ip_util 1441d61c82SJiaqing Zhao { 1541d61c82SJiaqing Zhao 1641d61c82SJiaqing Zhao /** 1741d61c82SJiaqing Zhao * @brief Converts boost::asio::ip::address to string 1841d61c82SJiaqing Zhao * Will automatically convert IPv4-mapped IPv6 address back to IPv4. 1941d61c82SJiaqing Zhao * 2041d61c82SJiaqing Zhao * @param[in] ipAddr IP address to convert 2141d61c82SJiaqing Zhao * 2241d61c82SJiaqing Zhao * @return IP address string 2341d61c82SJiaqing Zhao */ 2441d61c82SJiaqing Zhao inline std::string toString(const boost::asio::ip::address& ipAddr) 2541d61c82SJiaqing Zhao { 2641d61c82SJiaqing Zhao if (ipAddr.is_v6() && ipAddr.to_v6().is_v4_mapped()) 2741d61c82SJiaqing Zhao { 2841d61c82SJiaqing Zhao return boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped, 2941d61c82SJiaqing Zhao ipAddr.to_v6()) 3041d61c82SJiaqing Zhao .to_string(); 3141d61c82SJiaqing Zhao } 3241d61c82SJiaqing Zhao return ipAddr.to_string(); 3341d61c82SJiaqing Zhao } 3441d61c82SJiaqing Zhao 35033f1e4dSEd Tanous /** 36033f1e4dSEd Tanous * @brief Helper function that verifies IP address to check if it is in 37033f1e4dSEd Tanous * proper format. If bits pointer is provided, also calculates active 38033f1e4dSEd Tanous * bit count for Subnet Mask. 39033f1e4dSEd Tanous * 40033f1e4dSEd Tanous * @param[in] ip IP that will be verified 41033f1e4dSEd Tanous * @param[out] bits Calculated mask in bits notation 42033f1e4dSEd Tanous * 43033f1e4dSEd Tanous * @return true in case of success, false otherwise 44033f1e4dSEd Tanous */ 45033f1e4dSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string& ip, 463a4ad5d9SEd Tanous uint8_t* prefixLength = nullptr) 47033f1e4dSEd Tanous { 483a4ad5d9SEd Tanous boost::system::error_code ec; 493a4ad5d9SEd Tanous boost::asio::ip::address_v4 addr = boost::asio::ip::make_address_v4(ip, ec); 503a4ad5d9SEd Tanous if (ec) 51033f1e4dSEd Tanous { 52033f1e4dSEd Tanous return false; 53033f1e4dSEd Tanous } 54033f1e4dSEd Tanous 553a4ad5d9SEd Tanous if (prefixLength != nullptr) 56033f1e4dSEd Tanous { 573a4ad5d9SEd Tanous uint8_t prefix = 0; 583a4ad5d9SEd Tanous boost::asio::ip::address_v4::bytes_type maskBytes = addr.to_bytes(); 593a4ad5d9SEd Tanous bool maskFinished = false; 603a4ad5d9SEd Tanous for (unsigned char byte : maskBytes) 61033f1e4dSEd Tanous { 623a4ad5d9SEd Tanous if (maskFinished) 633a4ad5d9SEd Tanous { 643a4ad5d9SEd Tanous if (byte != 0U) 65033f1e4dSEd Tanous { 66033f1e4dSEd Tanous return false; 67033f1e4dSEd Tanous } 683a4ad5d9SEd Tanous continue; 693a4ad5d9SEd Tanous } 703a4ad5d9SEd Tanous switch (byte) 71033f1e4dSEd Tanous { 723a4ad5d9SEd Tanous case 255: 733a4ad5d9SEd Tanous prefix += 8; 743a4ad5d9SEd Tanous break; 753a4ad5d9SEd Tanous case 254: 763a4ad5d9SEd Tanous prefix += 7; 773a4ad5d9SEd Tanous maskFinished = true; 783a4ad5d9SEd Tanous break; 793a4ad5d9SEd Tanous case 252: 803a4ad5d9SEd Tanous prefix += 6; 813a4ad5d9SEd Tanous maskFinished = true; 823a4ad5d9SEd Tanous break; 833a4ad5d9SEd Tanous case 248: 843a4ad5d9SEd Tanous prefix += 5; 853a4ad5d9SEd Tanous maskFinished = true; 863a4ad5d9SEd Tanous break; 873a4ad5d9SEd Tanous case 240: 883a4ad5d9SEd Tanous prefix += 4; 893a4ad5d9SEd Tanous maskFinished = true; 903a4ad5d9SEd Tanous break; 913a4ad5d9SEd Tanous case 224: 923a4ad5d9SEd Tanous prefix += 3; 933a4ad5d9SEd Tanous maskFinished = true; 943a4ad5d9SEd Tanous break; 953a4ad5d9SEd Tanous case 192: 963a4ad5d9SEd Tanous prefix += 2; 973a4ad5d9SEd Tanous maskFinished = true; 983a4ad5d9SEd Tanous break; 993a4ad5d9SEd Tanous case 128: 1003a4ad5d9SEd Tanous prefix += 1; 1013a4ad5d9SEd Tanous maskFinished = true; 1023a4ad5d9SEd Tanous break; 1033a4ad5d9SEd Tanous case 0: 1043a4ad5d9SEd Tanous maskFinished = true; 1053a4ad5d9SEd Tanous break; 1063a4ad5d9SEd Tanous default: 1073a4ad5d9SEd Tanous // Invalid netmask 108033f1e4dSEd Tanous return false; 109033f1e4dSEd Tanous } 110033f1e4dSEd Tanous } 1113a4ad5d9SEd Tanous *prefixLength = prefix; 112033f1e4dSEd Tanous } 113033f1e4dSEd Tanous 114033f1e4dSEd Tanous return true; 115033f1e4dSEd Tanous } 116033f1e4dSEd Tanous 11741d61c82SJiaqing Zhao } // namespace ip_util 11841d61c82SJiaqing Zhao } // namespace redfish 119