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, ToHex) 32 { 33 EXPECT_EQ('E', mac_address::internal::toHex(std::byte(0xfe))); 34 EXPECT_EQ('A', mac_address::internal::toHex(std::byte(10))); 35 EXPECT_EQ('4', mac_address::internal::toHex(std::byte(4))); 36 } 37 38 TEST_F(TestUtil, MacFromBuf) 39 { 40 std::string tooSmall(1, 'a'); 41 std::string tooLarge(24, 'a'); 42 std::string buf{'\x00', '\xde', '\xad', '\x00', '\xbe', '\xef'}; 43 44 MacAddr mac = mac_address::fromBuf(buf); 45 EXPECT_EQ(0, memcmp(buf.data(), mac.data(), buf.size())); 46 47 EXPECT_THROW(mac_address::fromBuf(tooSmall), std::runtime_error); 48 EXPECT_THROW(mac_address::fromBuf(tooLarge), std::runtime_error); 49 } 50 51 TEST_F(TestUtil, MacToString) 52 { 53 MacAddr mac1{ 54 std::byte(0x00), std::byte(0xDE), std::byte(0xAD), 55 std::byte(0x00), std::byte(0xBE), std::byte(0xEF), 56 }; 57 EXPECT_EQ("00:DE:AD:00:BE:EF", mac_address::toString(mac1)); 58 MacAddr mac2{ 59 std::byte(0x70), std::byte(0xFF), std::byte(0x84), 60 std::byte(0x09), std::byte(0x35), std::byte(0x09), 61 }; 62 EXPECT_EQ("70:FF:84:09:35:09", mac_address::toString(mac2)); 63 } 64 65 TEST_F(TestUtil, AddrFromBuf) 66 { 67 std::string tooSmall(1, 'a'); 68 std::string tooLarge(24, 'a'); 69 70 struct in_addr ip1; 71 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 72 std::string_view buf1(reinterpret_cast<char*>(&ip1), sizeof(ip1)); 73 InAddrAny res1 = addrFromBuf(AF_INET, buf1); 74 EXPECT_EQ(0, memcmp(&ip1, &std::get<struct in_addr>(res1), sizeof(ip1))); 75 EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error); 76 EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error); 77 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::runtime_error); 78 79 struct in6_addr ip2; 80 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 81 std::string_view buf2(reinterpret_cast<char*>(&ip2), sizeof(ip2)); 82 InAddrAny res2 = addrFromBuf(AF_INET6, buf2); 83 EXPECT_EQ(0, memcmp(&ip2, &std::get<struct in6_addr>(res2), sizeof(ip2))); 84 EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error); 85 EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error); 86 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::runtime_error); 87 } 88 89 TEST_F(TestUtil, IpToString) 90 { 91 struct in_addr ip1; 92 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 93 EXPECT_EQ("192.168.10.1", toString(InAddrAny(ip1))); 94 95 struct in6_addr ip2; 96 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 97 EXPECT_EQ("fdd8:b5ad:9d93:94ee::2:1", toString(InAddrAny(ip2))); 98 } 99 100 TEST_F(TestUtil, IpValidation) 101 { 102 std::string ipaddress = "0.0.0.0"; 103 EXPECT_EQ(true, isValidIP(AF_INET, ipaddress)); 104 105 ipaddress = "9.3.185.83"; 106 EXPECT_EQ(true, isValidIP(AF_INET, ipaddress)); 107 108 ipaddress = "9.3.185.a"; 109 EXPECT_EQ(false, isValidIP(AF_INET, ipaddress)); 110 111 ipaddress = "9.3.a.83"; 112 EXPECT_EQ(false, isValidIP(AF_INET, ipaddress)); 113 114 ipaddress = "x.x.x.x"; 115 EXPECT_EQ(false, isValidIP(AF_INET, ipaddress)); 116 117 ipaddress = "0:0:0:0:0:0:0:0"; 118 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 119 120 ipaddress = "1:0:0:0:0:0:0:8"; 121 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 122 123 ipaddress = "1::8"; 124 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 125 126 ipaddress = "0:0:0:0:0:FFFF:204.152.189.116"; 127 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 128 129 ipaddress = "::ffff:204.152.189.116"; 130 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 131 132 ipaddress = "a:0:0:0:0:FFFF:204.152.189.116"; 133 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 134 135 ipaddress = "1::8"; 136 EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress)); 137 } 138 139 TEST_F(TestUtil, PrefixValidation) 140 { 141 uint8_t prefixLength = 1; 142 EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength)); 143 144 prefixLength = 32; 145 EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength)); 146 147 prefixLength = 0; 148 EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength)); 149 150 prefixLength = 33; 151 EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength)); 152 153 prefixLength = 33; 154 EXPECT_EQ(true, isValidPrefix(AF_INET6, prefixLength)); 155 156 prefixLength = 65; 157 EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength)); 158 } 159 160 TEST_F(TestUtil, MacValidation) 161 { 162 std::string macaddress = "00:00:00:00:00:00"; 163 EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress)); 164 165 macaddress = "F6:C6:E6:6:B0:D3"; 166 EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress)); 167 168 macaddress = "F6:C6:E6:06:B0:D3"; 169 EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress)); 170 171 macaddress = "hh:HH:HH:hh:HH:yy"; 172 EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress)); 173 174 macaddress = "hhh:GGG:iii:jjj:kkk:lll"; 175 EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress)); 176 } 177 178 TEST_F(TestUtil, ConvertV4MasktoPrefix) 179 { 180 std::string mask = "255.255.255.0"; 181 uint8_t prefix = toCidr(AF_INET, mask); 182 EXPECT_EQ(prefix, 24); 183 184 mask = "255.255.0.0"; 185 prefix = toCidr(AF_INET, mask); 186 EXPECT_EQ(prefix, 16); 187 188 mask = "255.0.0.0"; 189 prefix = toCidr(AF_INET, mask); 190 EXPECT_EQ(prefix, 8); 191 192 mask = "255.224.0.0"; 193 prefix = toCidr(AF_INET, mask); 194 EXPECT_EQ(prefix, 11); 195 196 // Invalid Mask 197 mask = "255.0.255.0"; 198 prefix = toCidr(AF_INET, mask); 199 EXPECT_EQ(prefix, 0); 200 } 201 202 TEST_F(TestUtil, convertV6MasktoPrefix) 203 { 204 std::string mask = "ffff:ffff::"; 205 uint8_t prefix = toCidr(AF_INET6, mask); 206 EXPECT_EQ(prefix, 32); 207 208 mask = "ffff:ffff:ffff::"; 209 prefix = toCidr(AF_INET6, mask); 210 EXPECT_EQ(prefix, 48); 211 212 mask = "ffff:ffff:fc00::"; 213 prefix = toCidr(AF_INET6, mask); 214 EXPECT_EQ(prefix, 38); 215 216 // Invalid Mask 217 mask = "ffff:0fff::"; 218 prefix = toCidr(AF_INET6, mask); 219 EXPECT_EQ(prefix, 0); 220 } 221 222 TEST_F(TestUtil, isLinkLocaladdress) 223 { 224 std::string ipaddress = "fe80:fec0::"; 225 EXPECT_TRUE(isLinkLocalIP(ipaddress)); 226 227 ipaddress = "2000:fe80:789::"; 228 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 229 230 ipaddress = "2000:fe80::"; 231 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 232 233 ipaddress = "169.254.3.3"; 234 EXPECT_TRUE(isLinkLocalIP(ipaddress)); 235 236 ipaddress = "3.169.254.3"; 237 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 238 239 ipaddress = "3.3.169.254"; 240 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 241 } 242 243 TEST_F(TestUtil, convertPrefixToMask) 244 { 245 std::string mask = toMask(AF_INET, 24); 246 EXPECT_EQ(mask, "255.255.255.0"); 247 248 mask = toMask(AF_INET, 8); 249 EXPECT_EQ(mask, "255.0.0.0"); 250 251 mask = toMask(AF_INET, 27); 252 EXPECT_EQ(mask, "255.255.255.224"); 253 } 254 255 TEST_F(TestUtil, getNetworkAddress) 256 { 257 std::string address = getNetworkID(AF_INET, "9.3.23.251", 24); 258 EXPECT_EQ("9.3.23.0", address); 259 260 address = getNetworkID(AF_INET, "9.3.23.251", 25); 261 EXPECT_EQ("9.3.23.128", address); 262 263 address = getNetworkID(AF_INET6, "2001:db8:abcd:dd12::0", 64); 264 EXPECT_EQ("2001:db8:abcd:dd12::", address); 265 266 EXPECT_THROW(getNetworkID(AF_INET, "a.b.c.d", 25), InternalFailure); 267 268 EXPECT_THROW(getNetworkID(AF_INET6, "2001:db8:gghh:dd12::0", 64), 269 InternalFailure); 270 271 address = getNetworkID(AF_INET6, "fe80::201:6cff:fe80:228", 64); 272 EXPECT_EQ("fe80::", address); 273 } 274 275 TEST_F(TestUtil, CopyFromTooSmall) 276 { 277 constexpr auto expected = "abcde"sv; 278 struct 279 { 280 uint8_t data[10]; 281 } data; 282 static_assert(sizeof(data) > expected.size()); 283 EXPECT_THROW(copyFrom<decltype(data)>(expected), std::runtime_error); 284 } 285 286 TEST_F(TestUtil, CopyFromSome) 287 { 288 constexpr auto expected = "abcde"sv; 289 struct 290 { 291 uint8_t data[2]; 292 } data; 293 static_assert(sizeof(data) < expected.size()); 294 data = copyFrom<decltype(data)>(expected); 295 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 296 } 297 298 TEST_F(TestUtil, CopyFromAll) 299 { 300 constexpr auto expected = "abcde"sv; 301 struct 302 { 303 uint8_t data[5]; 304 } data; 305 static_assert(sizeof(data) == expected.size()); 306 data = copyFrom<decltype(data)>(expected); 307 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 308 } 309 310 TEST_F(TestUtil, ExtractSome) 311 { 312 constexpr auto expected = "abcde"sv; 313 auto buf = expected; 314 struct 315 { 316 uint8_t data[2]; 317 } data; 318 static_assert(sizeof(data) < expected.size()); 319 data = extract<decltype(data)>(buf); 320 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 321 EXPECT_EQ(3, buf.size()); 322 EXPECT_EQ(expected.substr(2), buf); 323 } 324 325 TEST_F(TestUtil, ExtractAll) 326 { 327 constexpr auto expected = "abcde"sv; 328 auto buf = expected; 329 struct 330 { 331 uint8_t data[5]; 332 } data; 333 static_assert(sizeof(data) == expected.size()); 334 data = extract<decltype(data)>(buf); 335 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 336 EXPECT_EQ(0, buf.size()); 337 } 338 339 TEST_F(TestUtil, Equal) 340 { 341 struct 342 { 343 int i; 344 } a, b{}; 345 a.i = 4; 346 b.i = 4; 347 348 EXPECT_TRUE(equal(a, b)); 349 } 350 351 TEST_F(TestUtil, NotEqual) 352 { 353 struct 354 { 355 int i; 356 } a, b{}; 357 a.i = 2; 358 b.i = 4; 359 360 EXPECT_FALSE(equal(a, b)); 361 } 362 363 } // namespace network 364 } // namespace phosphor 365