xref: /openbmc/bmcweb/features/redfish/include/utils/ip_utils.hpp (revision 3a4ad5d9dba5ebbb92e8663c3177a326e920cd71)
141d61c82SJiaqing Zhao #pragma once
241d61c82SJiaqing Zhao 
341d61c82SJiaqing Zhao #include <boost/asio/ip/address.hpp>
4d5c80ad9SNan Zhou #include <boost/asio/ip/address_v4.hpp>
5d5c80ad9SNan Zhou #include <boost/asio/ip/address_v6.hpp>
641d61c82SJiaqing Zhao 
741d61c82SJiaqing Zhao #include <string>
841d61c82SJiaqing Zhao 
941d61c82SJiaqing Zhao namespace redfish
1041d61c82SJiaqing Zhao {
1141d61c82SJiaqing Zhao namespace ip_util
1241d61c82SJiaqing Zhao {
1341d61c82SJiaqing Zhao 
1441d61c82SJiaqing Zhao /**
1541d61c82SJiaqing Zhao  * @brief Converts boost::asio::ip::address to string
1641d61c82SJiaqing Zhao  * Will automatically convert IPv4-mapped IPv6 address back to IPv4.
1741d61c82SJiaqing Zhao  *
1841d61c82SJiaqing Zhao  * @param[in] ipAddr IP address to convert
1941d61c82SJiaqing Zhao  *
2041d61c82SJiaqing Zhao  * @return IP address string
2141d61c82SJiaqing Zhao  */
2241d61c82SJiaqing Zhao inline std::string toString(const boost::asio::ip::address& ipAddr)
2341d61c82SJiaqing Zhao {
2441d61c82SJiaqing Zhao     if (ipAddr.is_v6() && ipAddr.to_v6().is_v4_mapped())
2541d61c82SJiaqing Zhao     {
2641d61c82SJiaqing Zhao         return boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped,
2741d61c82SJiaqing Zhao                                                 ipAddr.to_v6())
2841d61c82SJiaqing Zhao             .to_string();
2941d61c82SJiaqing Zhao     }
3041d61c82SJiaqing Zhao     return ipAddr.to_string();
3141d61c82SJiaqing Zhao }
3241d61c82SJiaqing Zhao 
33033f1e4dSEd Tanous /**
34033f1e4dSEd Tanous  * @brief Helper function that verifies IP address to check if it is in
35033f1e4dSEd Tanous  *        proper format. If bits pointer is provided, also calculates active
36033f1e4dSEd Tanous  *        bit count for Subnet Mask.
37033f1e4dSEd Tanous  *
38033f1e4dSEd Tanous  * @param[in]  ip     IP that will be verified
39033f1e4dSEd Tanous  * @param[out] bits   Calculated mask in bits notation
40033f1e4dSEd Tanous  *
41033f1e4dSEd Tanous  * @return true in case of success, false otherwise
42033f1e4dSEd Tanous  */
43033f1e4dSEd Tanous inline bool ipv4VerifyIpAndGetBitcount(const std::string& ip,
44*3a4ad5d9SEd Tanous                                        uint8_t* prefixLength = nullptr)
45033f1e4dSEd Tanous {
46*3a4ad5d9SEd Tanous     boost::system::error_code ec;
47*3a4ad5d9SEd Tanous     boost::asio::ip::address_v4 addr = boost::asio::ip::make_address_v4(ip, ec);
48*3a4ad5d9SEd Tanous     if (ec)
49033f1e4dSEd Tanous     {
50033f1e4dSEd Tanous         return false;
51033f1e4dSEd Tanous     }
52033f1e4dSEd Tanous 
53*3a4ad5d9SEd Tanous     if (prefixLength != nullptr)
54033f1e4dSEd Tanous     {
55*3a4ad5d9SEd Tanous         uint8_t prefix = 0;
56*3a4ad5d9SEd Tanous         boost::asio::ip::address_v4::bytes_type maskBytes = addr.to_bytes();
57*3a4ad5d9SEd Tanous         bool maskFinished = false;
58*3a4ad5d9SEd Tanous         for (unsigned char byte : maskBytes)
59033f1e4dSEd Tanous         {
60*3a4ad5d9SEd Tanous             if (maskFinished)
61*3a4ad5d9SEd Tanous             {
62*3a4ad5d9SEd Tanous                 if (byte != 0U)
63033f1e4dSEd Tanous                 {
64033f1e4dSEd Tanous                     return false;
65033f1e4dSEd Tanous                 }
66*3a4ad5d9SEd Tanous                 continue;
67*3a4ad5d9SEd Tanous             }
68*3a4ad5d9SEd Tanous             switch (byte)
69033f1e4dSEd Tanous             {
70*3a4ad5d9SEd Tanous                 case 255:
71*3a4ad5d9SEd Tanous                     prefix += 8;
72*3a4ad5d9SEd Tanous                     break;
73*3a4ad5d9SEd Tanous                 case 254:
74*3a4ad5d9SEd Tanous                     prefix += 7;
75*3a4ad5d9SEd Tanous                     maskFinished = true;
76*3a4ad5d9SEd Tanous                     break;
77*3a4ad5d9SEd Tanous                 case 252:
78*3a4ad5d9SEd Tanous                     prefix += 6;
79*3a4ad5d9SEd Tanous                     maskFinished = true;
80*3a4ad5d9SEd Tanous                     break;
81*3a4ad5d9SEd Tanous                 case 248:
82*3a4ad5d9SEd Tanous                     prefix += 5;
83*3a4ad5d9SEd Tanous                     maskFinished = true;
84*3a4ad5d9SEd Tanous                     break;
85*3a4ad5d9SEd Tanous                 case 240:
86*3a4ad5d9SEd Tanous                     prefix += 4;
87*3a4ad5d9SEd Tanous                     maskFinished = true;
88*3a4ad5d9SEd Tanous                     break;
89*3a4ad5d9SEd Tanous                 case 224:
90*3a4ad5d9SEd Tanous                     prefix += 3;
91*3a4ad5d9SEd Tanous                     maskFinished = true;
92*3a4ad5d9SEd Tanous                     break;
93*3a4ad5d9SEd Tanous                 case 192:
94*3a4ad5d9SEd Tanous                     prefix += 2;
95*3a4ad5d9SEd Tanous                     maskFinished = true;
96*3a4ad5d9SEd Tanous                     break;
97*3a4ad5d9SEd Tanous                 case 128:
98*3a4ad5d9SEd Tanous                     prefix += 1;
99*3a4ad5d9SEd Tanous                     maskFinished = true;
100*3a4ad5d9SEd Tanous                     break;
101*3a4ad5d9SEd Tanous                 case 0:
102*3a4ad5d9SEd Tanous                     maskFinished = true;
103*3a4ad5d9SEd Tanous                     break;
104*3a4ad5d9SEd Tanous                 default:
105*3a4ad5d9SEd Tanous                     // Invalid netmask
106033f1e4dSEd Tanous                     return false;
107033f1e4dSEd Tanous             }
108033f1e4dSEd Tanous         }
109*3a4ad5d9SEd Tanous         *prefixLength = prefix;
110033f1e4dSEd Tanous     }
111033f1e4dSEd Tanous 
112033f1e4dSEd Tanous     return true;
113033f1e4dSEd Tanous }
114033f1e4dSEd Tanous 
11541d61c82SJiaqing Zhao } // namespace ip_util
11641d61c82SJiaqing Zhao } // namespace redfish
117