1 #include "util.hpp" 2 3 #include <arpa/inet.h> 4 #include <fmt/chrono.h> 5 #include <netinet/in.h> 6 7 #include <charconv> 8 #include <cstddef> 9 #include <cstring> 10 #include <stdexcept> 11 #include <string> 12 #include <string_view> 13 #include <xyz/openbmc_project/Common/error.hpp> 14 15 #include <gmock/gmock.h> 16 #include <gtest/gtest.h> 17 18 namespace phosphor 19 { 20 namespace network 21 { 22 23 using namespace std::literals; 24 using InternalFailure = 25 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 26 class TestUtil : public testing::Test 27 { 28 public: 29 TestUtil() 30 { 31 // Empty 32 } 33 }; 34 35 TEST_F(TestUtil, AddrFromBuf) 36 { 37 std::string tooSmall(1, 'a'); 38 std::string tooLarge(24, 'a'); 39 40 struct in_addr ip1; 41 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 42 std::string_view buf1(reinterpret_cast<char*>(&ip1), sizeof(ip1)); 43 InAddrAny res1 = addrFromBuf(AF_INET, buf1); 44 EXPECT_EQ(0, memcmp(&ip1, &std::get<struct in_addr>(res1), sizeof(ip1))); 45 EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error); 46 EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error); 47 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::invalid_argument); 48 49 struct in6_addr ip2; 50 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 51 std::string_view buf2(reinterpret_cast<char*>(&ip2), sizeof(ip2)); 52 InAddrAny res2 = addrFromBuf(AF_INET6, buf2); 53 EXPECT_EQ(0, memcmp(&ip2, &std::get<struct in6_addr>(res2), sizeof(ip2))); 54 EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error); 55 EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error); 56 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::invalid_argument); 57 } 58 59 TEST_F(TestUtil, IpValidation) 60 { 61 EXPECT_TRUE(isValidIP(AF_INET, "0.0.0.0")); 62 EXPECT_TRUE(isValidIP("0.0.0.0")); 63 64 EXPECT_TRUE(isValidIP(AF_INET, "9.3.185.83")); 65 66 EXPECT_FALSE(isValidIP(AF_INET, "9.3.185.a")); 67 EXPECT_FALSE(isValidIP("9.3.185.a")); 68 69 EXPECT_FALSE(isValidIP(AF_INET, "9.3.a.83")); 70 71 EXPECT_FALSE(isValidIP(AF_INET, "x.x.x.x")); 72 73 EXPECT_TRUE(isValidIP(AF_INET6, "0:0:0:0:0:0:0:0")); 74 EXPECT_TRUE(isValidIP("0:0:0:0:0:0:0:0")); 75 76 EXPECT_TRUE(isValidIP(AF_INET6, "1:0:0:0:0:0:0:8")); 77 78 EXPECT_TRUE(isValidIP(AF_INET6, "1::8")); 79 80 EXPECT_TRUE(isValidIP(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116")); 81 82 EXPECT_TRUE(isValidIP(AF_INET6, "::ffff:204.152.189.116")); 83 84 EXPECT_TRUE(isValidIP(AF_INET6, "a:0:0:0:0:FFFF:204.152.189.116")); 85 86 EXPECT_TRUE(isValidIP(AF_INET6, "1::8")); 87 } 88 89 TEST_F(TestUtil, PrefixValidation) 90 { 91 EXPECT_TRUE(isValidPrefix(AF_INET, 0)); 92 EXPECT_TRUE(isValidPrefix(AF_INET, 1)); 93 EXPECT_TRUE(isValidPrefix(AF_INET, 32)); 94 EXPECT_FALSE(isValidPrefix(AF_INET, 33)); 95 EXPECT_FALSE(isValidPrefix(AF_INET, 64)); 96 97 EXPECT_TRUE(isValidPrefix(AF_INET6, 0)); 98 EXPECT_TRUE(isValidPrefix(AF_INET6, 1)); 99 EXPECT_TRUE(isValidPrefix(AF_INET6, 53)); 100 EXPECT_TRUE(isValidPrefix(AF_INET6, 64)); 101 EXPECT_TRUE(isValidPrefix(AF_INET6, 128)); 102 EXPECT_FALSE(isValidPrefix(AF_INET6, 129)); 103 EXPECT_FALSE(isValidPrefix(AF_INET6, 177)); 104 105 EXPECT_THROW(isValidPrefix(AF_UNSPEC, 1), std::invalid_argument); 106 } 107 108 TEST_F(TestUtil, InterfaceToUbootEthAddr) 109 { 110 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("et")); 111 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("eth")); 112 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("sit0")); 113 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("ethh0")); 114 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("eth0h")); 115 EXPECT_EQ("ethaddr", interfaceToUbootEthAddr("eth0")); 116 EXPECT_EQ("eth1addr", interfaceToUbootEthAddr("eth1")); 117 EXPECT_EQ("eth5addr", interfaceToUbootEthAddr("eth5")); 118 EXPECT_EQ("eth28addr", interfaceToUbootEthAddr("eth28")); 119 } 120 121 namespace mac_address 122 { 123 124 TEST(MacIsEmpty, True) 125 { 126 EXPECT_TRUE(isEmpty({})); 127 } 128 129 TEST(MacIsEmpty, False) 130 { 131 EXPECT_FALSE(isEmpty({1})); 132 EXPECT_FALSE(isEmpty({0, 0, 0, 1})); 133 EXPECT_FALSE(isEmpty({0, 0, 0, 0, 0, 1})); 134 } 135 136 TEST(MacIsMulticast, True) 137 { 138 EXPECT_TRUE(isMulticast({255, 255, 255, 255, 255, 255})); 139 EXPECT_TRUE(isMulticast({1})); 140 } 141 142 TEST(MacIsMulticast, False) 143 { 144 EXPECT_FALSE(isMulticast({0, 1, 2, 3, 4, 5})); 145 EXPECT_FALSE(isMulticast({0xfe, 255, 255, 255, 255, 255})); 146 } 147 148 TEST(MacIsUnicast, True) 149 { 150 EXPECT_TRUE(isUnicast({0, 1, 2, 3, 4, 5})); 151 EXPECT_TRUE(isUnicast({0xfe, 255, 255, 255, 255, 255})); 152 } 153 154 TEST(MacIsUnicast, False) 155 { 156 EXPECT_FALSE(isUnicast({})); 157 EXPECT_FALSE(isUnicast({1})); 158 EXPECT_FALSE(isUnicast({255, 255, 255, 255, 255, 255})); 159 } 160 161 TEST(IgnoredInterfaces, Empty) 162 { 163 auto ret = internal::parseInterfaces({}); 164 EXPECT_TRUE(ret.empty()); 165 166 ret = internal::parseInterfaces(" , ,, "); 167 EXPECT_TRUE(ret.empty()); 168 } 169 170 TEST(IgnoredInterfaces, NotEmpty) 171 { 172 using ::testing::ContainerEq; 173 std::unordered_set<std::string_view> expected = {"eth0"}; 174 auto ret = internal::parseInterfaces("eth0"); 175 EXPECT_THAT(ret, ContainerEq(expected)); 176 177 expected = {"eth0", "eth1", "bond1", "usb0"}; 178 ret = internal::parseInterfaces(" ,eth0, eth1 ,bond1, usb0,,"); 179 EXPECT_THAT(ret, ContainerEq(expected)); 180 } 181 182 } // namespace mac_address 183 } // namespace network 184 } // namespace phosphor 185