diff options
Diffstat (limited to 'redfish-core/include/utils/ip_utils.hpp')
-rw-r--r-- | redfish-core/include/utils/ip_utils.hpp | 92 |
1 files changed, 92 insertions, 0 deletions
diff --git a/redfish-core/include/utils/ip_utils.hpp b/redfish-core/include/utils/ip_utils.hpp index 815243eb1d..2d9b138400 100644 --- a/redfish-core/include/utils/ip_utils.hpp +++ b/redfish-core/include/utils/ip_utils.hpp @@ -1,5 +1,7 @@ #pragma once +#include <boost/algorithm/string/classification.hpp> +#include <boost/algorithm/string/split.hpp> #include <boost/asio/ip/address.hpp> #include <boost/asio/ip/address_v4.hpp> #include <boost/asio/ip/address_v6.hpp> @@ -30,5 +32,95 @@ inline std::string toString(const boost::asio::ip::address& ipAddr) return ipAddr.to_string(); } +/** + * @brief Helper function that verifies IP address to check if it is in + * proper format. If bits pointer is provided, also calculates active + * bit count for Subnet Mask. + * + * @param[in] ip IP that will be verified + * @param[out] bits Calculated mask in bits notation + * + * @return true in case of success, false otherwise + */ +inline bool ipv4VerifyIpAndGetBitcount(const std::string& ip, + uint8_t* bits = nullptr) +{ + std::vector<std::string> bytesInMask; + + boost::split(bytesInMask, ip, boost::is_any_of(".")); + + static const constexpr int ipV4AddressSectionsCount = 4; + if (bytesInMask.size() != ipV4AddressSectionsCount) + { + return false; + } + + if (bits != nullptr) + { + *bits = 0; + } + + char* endPtr = nullptr; + long previousValue = 255; + bool firstZeroInByteHit = false; + for (const std::string& byte : bytesInMask) + { + if (byte.empty()) + { + return false; + } + + // Use strtol instead of stroi to avoid exceptions + long value = std::strtol(byte.c_str(), &endPtr, 10); + + // endPtr should point to the end of the string, otherwise given string + // is not 100% number + if (*endPtr != '\0') + { + return false; + } + + // Value should be contained in byte + if (value < 0 || value > 255) + { + return false; + } + + if (bits != nullptr) + { + // Mask has to be continuous between bytes + if (previousValue != 255 && value != 0) + { + return false; + } + + // Mask has to be continuous inside bytes + firstZeroInByteHit = false; + + // Count bits + for (long bitIdx = 7; bitIdx >= 0; bitIdx--) + { + if ((value & (1L << bitIdx)) != 0) + { + if (firstZeroInByteHit) + { + // Continuity not preserved + return false; + } + (*bits)++; + } + else + { + firstZeroInByteHit = true; + } + } + } + + previousValue = value; + } + + return true; +} + } // namespace ip_util } // namespace redfish |