| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 1 | #include "util.hpp" | 
|  | 2 |  | 
| William A. Kennington III | 5058f57 | 2019-01-30 17:18:14 -0800 | [diff] [blame] | 3 | #include <arpa/inet.h> | 
| Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 4 | #include <netinet/in.h> | 
|  | 5 |  | 
| William A. Kennington III | d27410f | 2019-01-30 17:15:43 -0800 | [diff] [blame] | 6 | #include <cstddef> | 
| William A. Kennington III | c920bdb | 2019-04-19 14:23:06 -0700 | [diff] [blame] | 7 | #include <cstring> | 
|  | 8 | #include <string> | 
|  | 9 | #include <string_view> | 
| Ratan Gupta | 3529717 | 2018-11-28 18:40:16 +0530 | [diff] [blame] | 10 | #include <xyz/openbmc_project/Common/error.hpp> | 
|  | 11 |  | 
| Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 12 | #include <gtest/gtest.h> | 
|  | 13 |  | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 14 | namespace phosphor | 
|  | 15 | { | 
|  | 16 | namespace network | 
|  | 17 | { | 
|  | 18 |  | 
| William A. Kennington III | c920bdb | 2019-04-19 14:23:06 -0700 | [diff] [blame] | 19 | using namespace std::literals; | 
| Ratan Gupta | 3529717 | 2018-11-28 18:40:16 +0530 | [diff] [blame] | 20 | using InternalFailure = | 
|  | 21 | sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 22 | class TestUtil : public testing::Test | 
|  | 23 | { | 
| Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 24 | public: | 
|  | 25 | TestUtil() | 
|  | 26 | { | 
|  | 27 | // Empty | 
|  | 28 | } | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 29 | }; | 
|  | 30 |  | 
| William A. Kennington III | a00b1c3 | 2019-02-01 18:57:17 -0800 | [diff] [blame] | 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 |  | 
| William A. Kennington III | 5058f57 | 2019-01-30 17:18:14 -0800 | [diff] [blame] | 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))); | 
| William A. Kennington III | 5058f57 | 2019-01-30 17:18:14 -0800 | [diff] [blame] | 64 | } | 
|  | 65 |  | 
| Nagaraju Goruganti | 067ca2d | 2018-01-17 01:12:00 -0600 | [diff] [blame] | 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)); | 
| Nagaraju Goruganti | 067ca2d | 2018-01-17 01:12:00 -0600 | [diff] [blame] | 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)); | 
| Nagaraju Goruganti | 067ca2d | 2018-01-17 01:12:00 -0600 | [diff] [blame] | 124 | } | 
|  | 125 |  | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 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 |  | 
| Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 144 | // Invalid Mask | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 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 |  | 
| Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 164 | // Invalid Mask | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 165 | mask = "ffff:0fff::"; | 
|  | 166 | prefix = toCidr(AF_INET6, mask); | 
|  | 167 | EXPECT_EQ(prefix, 0); | 
|  | 168 | } | 
|  | 169 |  | 
| Ratan Gupta | 11cef80 | 2017-05-29 08:41:48 +0530 | [diff] [blame] | 170 | TEST_F(TestUtil, isLinkLocaladdress) | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 171 | { | 
|  | 172 | std::string ipaddress = "fe80:fec0::"; | 
| Nagaraju Goruganti | 66b974d | 2017-10-03 08:43:08 -0500 | [diff] [blame] | 173 | EXPECT_TRUE(isLinkLocalIP(ipaddress)); | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 174 |  | 
| Nagaraju Goruganti | 66b974d | 2017-10-03 08:43:08 -0500 | [diff] [blame] | 175 | ipaddress = "2000:fe80:789::"; | 
|  | 176 | EXPECT_FALSE(isLinkLocalIP(ipaddress)); | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 177 |  | 
|  | 178 | ipaddress = "2000:fe80::"; | 
| Nagaraju Goruganti | 66b974d | 2017-10-03 08:43:08 -0500 | [diff] [blame] | 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)); | 
| Ratan Gupta | 594123d | 2017-05-16 22:48:35 +0530 | [diff] [blame] | 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 |  | 
| William A. Kennington III | c920bdb | 2019-04-19 14:23:06 -0700 | [diff] [blame] | 203 | TEST_F(TestUtil, CopyFromTooSmall) | 
|  | 204 | { | 
|  | 205 | constexpr auto expected = "abcde"sv; | 
|  | 206 | struct | 
|  | 207 | { | 
|  | 208 | uint8_t data[10]; | 
|  | 209 | } data; | 
|  | 210 | static_assert(sizeof(data) > expected.size()); | 
|  | 211 | EXPECT_THROW(copyFrom<decltype(data)>(expected), std::runtime_error); | 
|  | 212 | } | 
|  | 213 |  | 
|  | 214 | TEST_F(TestUtil, CopyFromSome) | 
|  | 215 | { | 
|  | 216 | constexpr auto expected = "abcde"sv; | 
|  | 217 | struct | 
|  | 218 | { | 
|  | 219 | uint8_t data[2]; | 
|  | 220 | } data; | 
|  | 221 | static_assert(sizeof(data) < expected.size()); | 
|  | 222 | data = copyFrom<decltype(data)>(expected); | 
|  | 223 | EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); | 
|  | 224 | } | 
|  | 225 |  | 
|  | 226 | TEST_F(TestUtil, CopyFromAll) | 
|  | 227 | { | 
|  | 228 | constexpr auto expected = "abcde"sv; | 
|  | 229 | struct | 
|  | 230 | { | 
|  | 231 | uint8_t data[5]; | 
|  | 232 | } data; | 
|  | 233 | static_assert(sizeof(data) == expected.size()); | 
|  | 234 | data = copyFrom<decltype(data)>(expected); | 
|  | 235 | EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); | 
|  | 236 | } | 
|  | 237 |  | 
|  | 238 | TEST_F(TestUtil, ExtractSome) | 
|  | 239 | { | 
|  | 240 | constexpr auto expected = "abcde"sv; | 
|  | 241 | auto buf = expected; | 
|  | 242 | struct | 
|  | 243 | { | 
|  | 244 | uint8_t data[2]; | 
|  | 245 | } data; | 
|  | 246 | static_assert(sizeof(data) < expected.size()); | 
|  | 247 | data = extract<decltype(data)>(buf); | 
|  | 248 | EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); | 
|  | 249 | EXPECT_EQ(3, buf.size()); | 
|  | 250 | EXPECT_EQ(expected.substr(2), buf); | 
|  | 251 | } | 
|  | 252 |  | 
|  | 253 | TEST_F(TestUtil, ExtractAll) | 
|  | 254 | { | 
|  | 255 | constexpr auto expected = "abcde"sv; | 
|  | 256 | auto buf = expected; | 
|  | 257 | struct | 
|  | 258 | { | 
|  | 259 | uint8_t data[5]; | 
|  | 260 | } data; | 
|  | 261 | static_assert(sizeof(data) == expected.size()); | 
|  | 262 | data = extract<decltype(data)>(buf); | 
|  | 263 | EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data))); | 
|  | 264 | EXPECT_EQ(0, buf.size()); | 
|  | 265 | } | 
|  | 266 |  | 
|  | 267 | TEST_F(TestUtil, Equal) | 
|  | 268 | { | 
|  | 269 | struct | 
|  | 270 | { | 
|  | 271 | int i; | 
|  | 272 | } a, b{}; | 
|  | 273 | a.i = 4; | 
|  | 274 | b.i = 4; | 
|  | 275 |  | 
|  | 276 | EXPECT_TRUE(equal(a, b)); | 
|  | 277 | } | 
|  | 278 |  | 
|  | 279 | TEST_F(TestUtil, NotEqual) | 
|  | 280 | { | 
|  | 281 | struct | 
|  | 282 | { | 
|  | 283 | int i; | 
|  | 284 | } a, b{}; | 
|  | 285 | a.i = 2; | 
|  | 286 | b.i = 4; | 
|  | 287 |  | 
|  | 288 | EXPECT_FALSE(equal(a, b)); | 
|  | 289 | } | 
|  | 290 |  | 
| William A. Kennington III | 1137a97 | 2019-04-20 20:49:58 -0700 | [diff] [blame] | 291 | namespace mac_address | 
|  | 292 | { | 
|  | 293 |  | 
|  | 294 | TEST(MacFromString, Bad) | 
|  | 295 | { | 
|  | 296 | EXPECT_THROW(fromString("0x:00:00:00:00:00"), std::runtime_error); | 
|  | 297 | EXPECT_THROW(fromString("00:00:00:00:00"), std::runtime_error); | 
|  | 298 | EXPECT_THROW(fromString(""), std::runtime_error); | 
|  | 299 | } | 
|  | 300 |  | 
|  | 301 | TEST(MacFromString, Valid) | 
|  | 302 | { | 
|  | 303 | EXPECT_TRUE(equal(ether_addr{}, fromString("00:00:00:00:00:00"))); | 
|  | 304 | EXPECT_TRUE(equal(ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}, | 
|  | 305 | fromString("FF:EE:DD:cc:bb:aa"))); | 
|  | 306 | EXPECT_TRUE(equal(ether_addr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, | 
|  | 307 | fromString("0:1:2:3:4:5"))); | 
|  | 308 | } | 
|  | 309 |  | 
|  | 310 | TEST(MacToString, Valid) | 
|  | 311 | { | 
|  | 312 | EXPECT_EQ("11:22:33:44:55:66", | 
|  | 313 | toString({0x11, 0x22, 0x33, 0x44, 0x55, 0x66})); | 
|  | 314 | } | 
|  | 315 |  | 
|  | 316 | TEST(MacIsEmpty, True) | 
|  | 317 | { | 
|  | 318 | EXPECT_TRUE(isEmpty({})); | 
|  | 319 | } | 
|  | 320 |  | 
|  | 321 | TEST(MacIsEmpty, False) | 
|  | 322 | { | 
|  | 323 | EXPECT_FALSE(isEmpty(fromString("01:00:00:00:00:00"))); | 
|  | 324 | EXPECT_FALSE(isEmpty(fromString("00:00:00:10:00:00"))); | 
|  | 325 | EXPECT_FALSE(isEmpty(fromString("00:00:00:00:00:01"))); | 
|  | 326 | } | 
|  | 327 |  | 
|  | 328 | TEST(MacIsMulticast, True) | 
|  | 329 | { | 
|  | 330 | EXPECT_TRUE(isMulticast(fromString("ff:ff:ff:ff:ff:ff"))); | 
|  | 331 | EXPECT_TRUE(isMulticast(fromString("01:00:00:00:00:00"))); | 
|  | 332 | } | 
|  | 333 |  | 
|  | 334 | TEST(MacIsMulticast, False) | 
|  | 335 | { | 
|  | 336 | EXPECT_FALSE(isMulticast(fromString("00:11:22:33:44:55"))); | 
|  | 337 | EXPECT_FALSE(isMulticast(fromString("FE:11:22:33:44:55"))); | 
|  | 338 | } | 
|  | 339 |  | 
|  | 340 | TEST(MacIsUnicast, True) | 
|  | 341 | { | 
|  | 342 | EXPECT_TRUE(isUnicast(fromString("00:11:22:33:44:55"))); | 
|  | 343 | EXPECT_TRUE(isUnicast(fromString("FE:11:22:33:44:55"))); | 
|  | 344 | } | 
|  | 345 |  | 
|  | 346 | TEST(MacIsUnicast, False) | 
|  | 347 | { | 
|  | 348 | EXPECT_FALSE(isUnicast(fromString("00:00:00:00:00:00"))); | 
|  | 349 | EXPECT_FALSE(isUnicast(fromString("01:00:00:00:00:00"))); | 
|  | 350 | EXPECT_FALSE(isUnicast(fromString("ff:ff:ff:ff:ff:ff"))); | 
|  | 351 | } | 
|  | 352 |  | 
|  | 353 | TEST(MacIsLocalAdmin, True) | 
|  | 354 | { | 
|  | 355 | EXPECT_TRUE(isLocalAdmin(fromString("02:11:22:33:44:55"))); | 
|  | 356 | EXPECT_TRUE(isLocalAdmin(fromString("FE:11:22:33:44:55"))); | 
|  | 357 | } | 
|  | 358 |  | 
|  | 359 | TEST(MacIsLocalAdmin, False) | 
|  | 360 | { | 
|  | 361 | EXPECT_FALSE(isLocalAdmin(fromString("00:00:00:00:00:00"))); | 
|  | 362 | EXPECT_FALSE(isLocalAdmin(fromString("01:00:00:00:00:00"))); | 
|  | 363 | EXPECT_FALSE(isLocalAdmin(fromString("fd:ff:ff:ff:ff:ff"))); | 
|  | 364 | } | 
|  | 365 |  | 
|  | 366 | } // namespace mac_address | 
| Gunnar Mills | 57d9c50 | 2018-09-14 14:42:34 -0500 | [diff] [blame] | 367 | } // namespace network | 
|  | 368 | } // namespace phosphor |