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