xref: /openbmc/bmcweb/features/redfish/include/utils/ip_utils.hpp (revision d78572018fc2022091ff8b8eb5a7fef2172ba3d6)
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