xref: /openbmc/bmcweb/redfish-core/include/utils/ip_utils.hpp (revision d78572018fc2022091ff8b8eb5a7fef2172ba3d6)
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 <cstdint>
10 #include <string>
11 
12 namespace redfish
13 {
14 namespace ip_util
15 {
16 
17 /**
18  * @brief Converts boost::asio::ip::address to string
19  * Will automatically convert IPv4-mapped IPv6 address back to IPv4.
20  *
21  * @param[in] ipAddr IP address to convert
22  *
23  * @return IP address string
24  */
toString(const boost::asio::ip::address & ipAddr)25 inline std::string toString(const boost::asio::ip::address& ipAddr)
26 {
27     if (ipAddr.is_v6() && ipAddr.to_v6().is_v4_mapped())
28     {
29         return boost::asio::ip::make_address_v4(boost::asio::ip::v4_mapped,
30                                                 ipAddr.to_v6())
31             .to_string();
32     }
33     return ipAddr.to_string();
34 }
35 
36 /**
37  * @brief Helper function that verifies IP address to check if it is in
38  *        proper format. If bits pointer is provided, also calculates active
39  *        bit count for Subnet Mask.
40  *
41  * @param[in]  ip     IP that will be verified
42  * @param[out] bits   Calculated mask in bits notation
43  *
44  * @return true in case of success, false otherwise
45  */
ipv4VerifyIpAndGetBitcount(const std::string & ip,uint8_t * prefixLength=nullptr)46 inline bool ipv4VerifyIpAndGetBitcount(const std::string& ip,
47                                        uint8_t* prefixLength = nullptr)
48 {
49     boost::system::error_code ec;
50     boost::asio::ip::address_v4 addr = boost::asio::ip::make_address_v4(ip, ec);
51     if (ec)
52     {
53         return false;
54     }
55 
56     if (prefixLength != nullptr)
57     {
58         uint8_t prefix = 0;
59         boost::asio::ip::address_v4::bytes_type maskBytes = addr.to_bytes();
60         bool maskFinished = false;
61         for (unsigned char byte : maskBytes)
62         {
63             if (maskFinished)
64             {
65                 if (byte != 0U)
66                 {
67                     return false;
68                 }
69                 continue;
70             }
71             switch (byte)
72             {
73                 case 255:
74                     prefix += 8;
75                     break;
76                 case 254:
77                     prefix += 7;
78                     maskFinished = true;
79                     break;
80                 case 252:
81                     prefix += 6;
82                     maskFinished = true;
83                     break;
84                 case 248:
85                     prefix += 5;
86                     maskFinished = true;
87                     break;
88                 case 240:
89                     prefix += 4;
90                     maskFinished = true;
91                     break;
92                 case 224:
93                     prefix += 3;
94                     maskFinished = true;
95                     break;
96                 case 192:
97                     prefix += 2;
98                     maskFinished = true;
99                     break;
100                 case 128:
101                     prefix += 1;
102                     maskFinished = true;
103                     break;
104                 case 0:
105                     maskFinished = true;
106                     break;
107                 default:
108                     // Invalid netmask
109                     return false;
110             }
111         }
112         *prefixLength = prefix;
113     }
114 
115     return true;
116 }
117 
118 } // namespace ip_util
119 } // namespace redfish
120