1 #include "util.hpp" 2 3 #include <arpa/inet.h> 4 #include <netinet/in.h> 5 6 #include <cstddef> 7 #include <cstring> 8 #include <stdplus/raw.hpp> 9 #include <string> 10 #include <string_view> 11 #include <xyz/openbmc_project/Common/error.hpp> 12 13 #include <gmock/gmock.h> 14 #include <gtest/gtest.h> 15 16 namespace phosphor 17 { 18 namespace network 19 { 20 21 using namespace std::literals; 22 using InternalFailure = 23 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 24 class TestUtil : public testing::Test 25 { 26 public: 27 TestUtil() 28 { 29 // Empty 30 } 31 }; 32 33 TEST_F(TestUtil, AddrFromBuf) 34 { 35 std::string tooSmall(1, 'a'); 36 std::string tooLarge(24, 'a'); 37 38 struct in_addr ip1; 39 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 40 std::string_view buf1(reinterpret_cast<char*>(&ip1), sizeof(ip1)); 41 InAddrAny res1 = addrFromBuf(AF_INET, buf1); 42 EXPECT_EQ(0, memcmp(&ip1, &std::get<struct in_addr>(res1), sizeof(ip1))); 43 EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error); 44 EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error); 45 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::runtime_error); 46 47 struct in6_addr ip2; 48 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 49 std::string_view buf2(reinterpret_cast<char*>(&ip2), sizeof(ip2)); 50 InAddrAny res2 = addrFromBuf(AF_INET6, buf2); 51 EXPECT_EQ(0, memcmp(&ip2, &std::get<struct in6_addr>(res2), sizeof(ip2))); 52 EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error); 53 EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error); 54 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::runtime_error); 55 } 56 57 TEST_F(TestUtil, IpToString) 58 { 59 struct in_addr ip1; 60 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 61 EXPECT_EQ("192.168.10.1", toString(ip1)); 62 EXPECT_EQ("192.168.10.1", toString(InAddrAny(ip1))); 63 64 struct in6_addr ip2; 65 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 66 EXPECT_EQ("fdd8:b5ad:9d93:94ee::2:1", toString(ip2)); 67 EXPECT_EQ("fdd8:b5ad:9d93:94ee::2:1", toString(InAddrAny(ip2))); 68 } 69 70 TEST_F(TestUtil, IpValidation) 71 { 72 std::string ipaddress = "0.0.0.0"; 73 EXPECT_EQ(true, isValidIP(AF_INET, ipaddress)); 74 75 ipaddress = "9.3.185.83"; 76 EXPECT_EQ(true, isValidIP(AF_INET, ipaddress)); 77 78 ipaddress = "9.3.185.a"; 79 EXPECT_EQ(false, isValidIP(AF_INET, ipaddress)); 80 81 ipaddress = "9.3.a.83"; 82 EXPECT_EQ(false, isValidIP(AF_INET, ipaddress)); 83 84 ipaddress = "x.x.x.x"; 85 EXPECT_EQ(false, isValidIP(AF_INET, ipaddress)); 86 87 ipaddress = "0:0:0:0:0:0:0:0"; 88 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 89 90 ipaddress = "1:0:0:0:0:0:0:8"; 91 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 92 93 ipaddress = "1::8"; 94 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 95 96 ipaddress = "0:0:0:0:0:FFFF:204.152.189.116"; 97 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 98 99 ipaddress = "::ffff:204.152.189.116"; 100 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 101 102 ipaddress = "a:0:0:0:0:FFFF:204.152.189.116"; 103 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 104 105 ipaddress = "1::8"; 106 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 107 } 108 109 TEST_F(TestUtil, PrefixValidation) 110 { 111 uint8_t prefixLength = 1; 112 EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength)); 113 114 prefixLength = 32; 115 EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength)); 116 117 prefixLength = 0; 118 EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength)); 119 120 prefixLength = 33; 121 EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength)); 122 123 prefixLength = 33; 124 EXPECT_EQ(true, isValidPrefix(AF_INET6, prefixLength)); 125 126 prefixLength = 65; 127 EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength)); 128 } 129 130 TEST_F(TestUtil, ConvertV4MasktoPrefix) 131 { 132 std::string mask = "255.255.255.0"; 133 uint8_t prefix = toCidr(AF_INET, mask); 134 EXPECT_EQ(prefix, 24); 135 136 mask = "255.255.255.255"; 137 prefix = toCidr(AF_INET, mask); 138 EXPECT_EQ(prefix, 32); 139 140 mask = "255.255.0.0"; 141 prefix = toCidr(AF_INET, mask); 142 EXPECT_EQ(prefix, 16); 143 144 mask = "255.0.0.0"; 145 prefix = toCidr(AF_INET, mask); 146 EXPECT_EQ(prefix, 8); 147 148 mask = "255.224.0.0"; 149 prefix = toCidr(AF_INET, mask); 150 EXPECT_EQ(prefix, 11); 151 152 // Invalid Mask 153 mask = "255.0.255.0"; 154 prefix = toCidr(AF_INET, mask); 155 EXPECT_EQ(prefix, 0); 156 } 157 158 TEST_F(TestUtil, convertV6MasktoPrefix) 159 { 160 std::string mask = "ffff:ffff::"; 161 uint8_t prefix = toCidr(AF_INET6, mask); 162 EXPECT_EQ(prefix, 32); 163 164 mask = "::"; 165 prefix = toCidr(AF_INET6, mask); 166 EXPECT_EQ(prefix, 0); 167 168 mask = "ffff:ffff:ffff::"; 169 prefix = toCidr(AF_INET6, mask); 170 EXPECT_EQ(prefix, 48); 171 172 mask = "ffff:ffff:fc00::"; 173 prefix = toCidr(AF_INET6, mask); 174 EXPECT_EQ(prefix, 38); 175 176 mask = "ffff:0:0:0:0:0:0:0"; 177 prefix = toCidr(AF_INET6, mask); 178 EXPECT_EQ(prefix, 16); 179 180 mask = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"; 181 prefix = toCidr(AF_INET6, mask); 182 EXPECT_EQ(prefix, 128); 183 184 mask = "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fffc"; 185 prefix = toCidr(AF_INET6, mask); 186 EXPECT_EQ(prefix, 126); 187 188 mask = "ffff:ffff:ffff:ffff::"; 189 prefix = toCidr(AF_INET6, mask); 190 EXPECT_EQ(prefix, 64); 191 192 // Invalid Masks 193 mask = "ffff:0fff::"; 194 prefix = toCidr(AF_INET6, mask); 195 EXPECT_EQ(prefix, 0); 196 197 mask = "ffff:fgff::"; 198 prefix = toCidr(AF_INET6, mask); 199 EXPECT_EQ(prefix, 0); 200 201 mask = "ffff:0:0:6:0:0:0:0"; 202 prefix = toCidr(AF_INET6, mask); 203 EXPECT_EQ(prefix, 0); 204 205 mask = ":"; 206 prefix = toCidr(AF_INET6, mask); 207 EXPECT_EQ(prefix, 0); 208 209 mask = "abcd:efgh:ijkl:mnop:pqrs:tuvw:xyz:abcd"; 210 prefix = toCidr(AF_INET6, mask); 211 EXPECT_EQ(prefix, 0); 212 213 mask = "ffff:0:0:0:0:0:0"; 214 prefix = toCidr(AF_INET6, mask); 215 EXPECT_EQ(prefix, 0); 216 } 217 218 TEST_F(TestUtil, isLinkLocaladdress) 219 { 220 std::string ipaddress = "fe80:fec0::"; 221 EXPECT_TRUE(isLinkLocalIP(ipaddress)); 222 223 ipaddress = "2000:fe80:789::"; 224 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 225 226 ipaddress = "2000:fe80::"; 227 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 228 229 ipaddress = "169.254.3.3"; 230 EXPECT_TRUE(isLinkLocalIP(ipaddress)); 231 232 ipaddress = "3.169.254.3"; 233 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 234 235 ipaddress = "3.3.169.254"; 236 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 237 } 238 239 TEST_F(TestUtil, convertPrefixToMask) 240 { 241 std::string mask = toMask(AF_INET, 24); 242 EXPECT_EQ(mask, "255.255.255.0"); 243 244 mask = toMask(AF_INET, 8); 245 EXPECT_EQ(mask, "255.0.0.0"); 246 247 mask = toMask(AF_INET, 27); 248 EXPECT_EQ(mask, "255.255.255.224"); 249 } 250 251 TEST_F(TestUtil, InterfaceToUbootEthAddr) 252 { 253 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("et")); 254 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("eth")); 255 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("sit0")); 256 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("ethh0")); 257 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("eth0h")); 258 EXPECT_EQ("ethaddr", interfaceToUbootEthAddr("eth0")); 259 EXPECT_EQ("eth1addr", interfaceToUbootEthAddr("eth1")); 260 EXPECT_EQ("eth5addr", interfaceToUbootEthAddr("eth5")); 261 EXPECT_EQ("eth28addr", interfaceToUbootEthAddr("eth28")); 262 } 263 264 namespace mac_address 265 { 266 267 TEST(MacFromString, Bad) 268 { 269 EXPECT_THROW(fromString("0x:00:00:00:00:00"), std::invalid_argument); 270 EXPECT_THROW(fromString("00:00:00:00:00"), std::invalid_argument); 271 EXPECT_THROW(fromString(""), std::invalid_argument); 272 EXPECT_THROW(fromString("123456789XYZ"), std::invalid_argument); 273 EXPECT_THROW(fromString("123456789AB"), std::invalid_argument); 274 EXPECT_THROW(fromString("123456789ABCD"), std::invalid_argument); 275 } 276 277 TEST(MacFromString, Valid) 278 { 279 EXPECT_TRUE( 280 stdplus::raw::equal(ether_addr{}, fromString("00:00:00:00:00:00"))); 281 EXPECT_TRUE( 282 stdplus::raw::equal(ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}, 283 fromString("FF:EE:DD:cc:bb:aa"))); 284 EXPECT_TRUE( 285 stdplus::raw::equal(ether_addr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, 286 fromString("0:1:2:3:4:5"))); 287 EXPECT_TRUE( 288 stdplus::raw::equal(ether_addr{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}, 289 fromString("0123456789AB"))); 290 EXPECT_TRUE( 291 stdplus::raw::equal(ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}, 292 fromString("FFEEDDccbbaa"))); 293 } 294 295 TEST(MacToString, Valid) 296 { 297 EXPECT_EQ("11:22:33:44:55:66", 298 toString({0x11, 0x22, 0x33, 0x44, 0x55, 0x66})); 299 EXPECT_EQ("01:02:03:04:05:67", 300 toString({0x01, 0x02, 0x03, 0x04, 0x05, 0x67})); 301 EXPECT_EQ("00:00:00:00:00:00", 302 toString({0x00, 0x00, 0x00, 0x00, 0x00, 0x00})); 303 } 304 305 TEST(MacIsEmpty, True) 306 { 307 EXPECT_TRUE(isEmpty({})); 308 } 309 310 TEST(MacIsEmpty, False) 311 { 312 EXPECT_FALSE(isEmpty(fromString("01:00:00:00:00:00"))); 313 EXPECT_FALSE(isEmpty(fromString("00:00:00:10:00:00"))); 314 EXPECT_FALSE(isEmpty(fromString("00:00:00:00:00:01"))); 315 } 316 317 TEST(MacIsMulticast, True) 318 { 319 EXPECT_TRUE(isMulticast(fromString("ff:ff:ff:ff:ff:ff"))); 320 EXPECT_TRUE(isMulticast(fromString("01:00:00:00:00:00"))); 321 } 322 323 TEST(MacIsMulticast, False) 324 { 325 EXPECT_FALSE(isMulticast(fromString("00:11:22:33:44:55"))); 326 EXPECT_FALSE(isMulticast(fromString("FE:11:22:33:44:55"))); 327 } 328 329 TEST(MacIsUnicast, True) 330 { 331 EXPECT_TRUE(isUnicast(fromString("00:11:22:33:44:55"))); 332 EXPECT_TRUE(isUnicast(fromString("FE:11:22:33:44:55"))); 333 } 334 335 TEST(MacIsUnicast, False) 336 { 337 EXPECT_FALSE(isUnicast(fromString("00:00:00:00:00:00"))); 338 EXPECT_FALSE(isUnicast(fromString("01:00:00:00:00:00"))); 339 EXPECT_FALSE(isUnicast(fromString("ff:ff:ff:ff:ff:ff"))); 340 } 341 342 TEST(IgnoredInterfaces, Empty) 343 { 344 auto ret = internal::parseInterfaces({}); 345 EXPECT_TRUE(ret.empty()); 346 347 ret = internal::parseInterfaces(" , ,, "); 348 EXPECT_TRUE(ret.empty()); 349 } 350 351 TEST(IgnoredInterfaces, NotEmpty) 352 { 353 using ::testing::ContainerEq; 354 std::set<std::string_view> expected = {"eth0"}; 355 auto ret = internal::parseInterfaces("eth0"); 356 EXPECT_THAT(ret, ContainerEq(expected)); 357 358 expected = {"eth0", "eth1", "bond1", "usb0"}; 359 ret = internal::parseInterfaces(" ,eth0, eth1 ,bond1, usb0,,"); 360 EXPECT_THAT(ret, ContainerEq(expected)); 361 } 362 363 } // namespace mac_address 364 } // namespace network 365 } // namespace phosphor 366