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