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, MacValidation) 127 { 128 std::string macaddress = "00:00:00:00:00:00"; 129 EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress)); 130 131 macaddress = "F6:C6:E6:6:B0:D3"; 132 EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress)); 133 134 macaddress = "F6:C6:E6:06:B0:D3"; 135 EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress)); 136 137 macaddress = "hh:HH:HH:hh:HH:yy"; 138 EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress)); 139 140 macaddress = "hhh:GGG:iii:jjj:kkk:lll"; 141 EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress)); 142 } 143 144 TEST_F(TestUtil, ConvertV4MasktoPrefix) 145 { 146 std::string mask = "255.255.255.0"; 147 uint8_t prefix = toCidr(AF_INET, mask); 148 EXPECT_EQ(prefix, 24); 149 150 mask = "255.255.0.0"; 151 prefix = toCidr(AF_INET, mask); 152 EXPECT_EQ(prefix, 16); 153 154 mask = "255.0.0.0"; 155 prefix = toCidr(AF_INET, mask); 156 EXPECT_EQ(prefix, 8); 157 158 mask = "255.224.0.0"; 159 prefix = toCidr(AF_INET, mask); 160 EXPECT_EQ(prefix, 11); 161 162 // Invalid Mask 163 mask = "255.0.255.0"; 164 prefix = toCidr(AF_INET, mask); 165 EXPECT_EQ(prefix, 0); 166 } 167 168 TEST_F(TestUtil, convertV6MasktoPrefix) 169 { 170 std::string mask = "ffff:ffff::"; 171 uint8_t prefix = toCidr(AF_INET6, mask); 172 EXPECT_EQ(prefix, 32); 173 174 mask = "ffff:ffff:ffff::"; 175 prefix = toCidr(AF_INET6, mask); 176 EXPECT_EQ(prefix, 48); 177 178 mask = "ffff:ffff:fc00::"; 179 prefix = toCidr(AF_INET6, mask); 180 EXPECT_EQ(prefix, 38); 181 182 // Invalid Mask 183 mask = "ffff:0fff::"; 184 prefix = toCidr(AF_INET6, mask); 185 EXPECT_EQ(prefix, 0); 186 } 187 188 TEST_F(TestUtil, isLinkLocaladdress) 189 { 190 std::string ipaddress = "fe80:fec0::"; 191 EXPECT_TRUE(isLinkLocalIP(ipaddress)); 192 193 ipaddress = "2000:fe80:789::"; 194 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 195 196 ipaddress = "2000:fe80::"; 197 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 198 199 ipaddress = "169.254.3.3"; 200 EXPECT_TRUE(isLinkLocalIP(ipaddress)); 201 202 ipaddress = "3.169.254.3"; 203 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 204 205 ipaddress = "3.3.169.254"; 206 EXPECT_FALSE(isLinkLocalIP(ipaddress)); 207 } 208 209 TEST_F(TestUtil, convertPrefixToMask) 210 { 211 std::string mask = toMask(AF_INET, 24); 212 EXPECT_EQ(mask, "255.255.255.0"); 213 214 mask = toMask(AF_INET, 8); 215 EXPECT_EQ(mask, "255.0.0.0"); 216 217 mask = toMask(AF_INET, 27); 218 EXPECT_EQ(mask, "255.255.255.224"); 219 } 220 221 TEST_F(TestUtil, getNetworkAddress) 222 { 223 std::string address = getNetworkID(AF_INET, "9.3.23.251", 24); 224 EXPECT_EQ("9.3.23.0", address); 225 226 address = getNetworkID(AF_INET, "9.3.23.251", 25); 227 EXPECT_EQ("9.3.23.128", address); 228 229 address = getNetworkID(AF_INET6, "2001:db8:abcd:dd12::0", 64); 230 EXPECT_EQ("2001:db8:abcd:dd12::", address); 231 232 EXPECT_THROW(getNetworkID(AF_INET, "a.b.c.d", 25), InternalFailure); 233 234 EXPECT_THROW(getNetworkID(AF_INET6, "2001:db8:gghh:dd12::0", 64), 235 InternalFailure); 236 237 address = getNetworkID(AF_INET6, "fe80::201:6cff:fe80:228", 64); 238 EXPECT_EQ("fe80::", address); 239 } 240 241 TEST_F(TestUtil, CopyFromTooSmall) 242 { 243 constexpr auto expected = "abcde"sv; 244 struct 245 { 246 uint8_t data[10]; 247 } data; 248 static_assert(sizeof(data) > expected.size()); 249 EXPECT_THROW(copyFrom<decltype(data)>(expected), std::runtime_error); 250 } 251 252 TEST_F(TestUtil, CopyFromSome) 253 { 254 constexpr auto expected = "abcde"sv; 255 struct 256 { 257 uint8_t data[2]; 258 } data; 259 static_assert(sizeof(data) < expected.size()); 260 data = copyFrom<decltype(data)>(expected); 261 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 262 } 263 264 TEST_F(TestUtil, CopyFromAll) 265 { 266 constexpr auto expected = "abcde"sv; 267 struct 268 { 269 uint8_t data[5]; 270 } data; 271 static_assert(sizeof(data) == expected.size()); 272 data = copyFrom<decltype(data)>(expected); 273 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 274 } 275 276 TEST_F(TestUtil, ExtractSome) 277 { 278 constexpr auto expected = "abcde"sv; 279 auto buf = expected; 280 struct 281 { 282 uint8_t data[2]; 283 } data; 284 static_assert(sizeof(data) < expected.size()); 285 data = extract<decltype(data)>(buf); 286 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 287 EXPECT_EQ(3, buf.size()); 288 EXPECT_EQ(expected.substr(2), buf); 289 } 290 291 TEST_F(TestUtil, ExtractAll) 292 { 293 constexpr auto expected = "abcde"sv; 294 auto buf = expected; 295 struct 296 { 297 uint8_t data[5]; 298 } data; 299 static_assert(sizeof(data) == expected.size()); 300 data = extract<decltype(data)>(buf); 301 EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); 302 EXPECT_EQ(0, buf.size()); 303 } 304 305 TEST_F(TestUtil, Equal) 306 { 307 struct 308 { 309 int i; 310 } a, b{}; 311 a.i = 4; 312 b.i = 4; 313 314 EXPECT_TRUE(equal(a, b)); 315 } 316 317 TEST_F(TestUtil, NotEqual) 318 { 319 struct 320 { 321 int i; 322 } a, b{}; 323 a.i = 2; 324 b.i = 4; 325 326 EXPECT_FALSE(equal(a, b)); 327 } 328 329 } // namespace network 330 } // namespace phosphor 331