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