1 #include "util.hpp" 2 3 #include <arpa/inet.h> 4 #include <netinet/in.h> 5 6 #include <cstddef> 7 #include <cstring> 8 #include <stdexcept> 9 #include <stdplus/raw.hpp> 10 #include <string> 11 #include <string_view> 12 #include <xyz/openbmc_project/Common/error.hpp> 13 14 #include <gmock/gmock.h> 15 #include <gtest/gtest.h> 16 17 namespace phosphor 18 { 19 namespace network 20 { 21 22 using namespace std::literals; 23 using InternalFailure = 24 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 25 class TestUtil : public testing::Test 26 { 27 public: 28 TestUtil() 29 { 30 // Empty 31 } 32 }; 33 34 TEST_F(TestUtil, AddrFromBuf) 35 { 36 std::string tooSmall(1, 'a'); 37 std::string tooLarge(24, 'a'); 38 39 struct in_addr ip1; 40 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 41 std::string_view buf1(reinterpret_cast<char*>(&ip1), sizeof(ip1)); 42 InAddrAny res1 = addrFromBuf(AF_INET, buf1); 43 EXPECT_EQ(0, memcmp(&ip1, &std::get<struct in_addr>(res1), sizeof(ip1))); 44 EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error); 45 EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error); 46 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::invalid_argument); 47 48 struct in6_addr ip2; 49 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 50 std::string_view buf2(reinterpret_cast<char*>(&ip2), sizeof(ip2)); 51 InAddrAny res2 = addrFromBuf(AF_INET6, buf2); 52 EXPECT_EQ(0, memcmp(&ip2, &std::get<struct in6_addr>(res2), sizeof(ip2))); 53 EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error); 54 EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error); 55 EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::invalid_argument); 56 } 57 58 TEST_F(TestUtil, IpToString) 59 { 60 struct in_addr ip1; 61 EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1)); 62 EXPECT_EQ("192.168.10.1", toString(ip1)); 63 EXPECT_EQ("192.168.10.1", toString(InAddrAny(ip1))); 64 65 struct in6_addr ip2; 66 EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2)); 67 EXPECT_EQ("fdd8:b5ad:9d93:94ee::2:1", toString(ip2)); 68 EXPECT_EQ("fdd8:b5ad:9d93:94ee::2:1", toString(InAddrAny(ip2))); 69 } 70 71 TEST_F(TestUtil, IpValidation) 72 { 73 EXPECT_TRUE(isValidIP(AF_INET, "0.0.0.0")); 74 EXPECT_TRUE(isValidIP("0.0.0.0")); 75 76 EXPECT_TRUE(isValidIP(AF_INET, "9.3.185.83")); 77 78 EXPECT_FALSE(isValidIP(AF_INET, "9.3.185.a")); 79 EXPECT_FALSE(isValidIP("9.3.185.a")); 80 81 EXPECT_FALSE(isValidIP(AF_INET, "9.3.a.83")); 82 83 EXPECT_FALSE(isValidIP(AF_INET, "x.x.x.x")); 84 85 EXPECT_TRUE(isValidIP(AF_INET6, "0:0:0:0:0:0:0:0")); 86 EXPECT_TRUE(isValidIP("0:0:0:0:0:0:0:0")); 87 88 EXPECT_TRUE(isValidIP(AF_INET6, "1:0:0:0:0:0:0:8")); 89 90 EXPECT_TRUE(isValidIP(AF_INET6, "1::8")); 91 92 EXPECT_TRUE(isValidIP(AF_INET6, "0:0:0:0:0:FFFF:204.152.189.116")); 93 94 EXPECT_TRUE(isValidIP(AF_INET6, "::ffff:204.152.189.116")); 95 96 EXPECT_TRUE(isValidIP(AF_INET6, "a:0:0:0:0:FFFF:204.152.189.116")); 97 98 EXPECT_TRUE(isValidIP(AF_INET6, "1::8")); 99 } 100 101 TEST_F(TestUtil, PrefixValidation) 102 { 103 EXPECT_TRUE(isValidPrefix(AF_INET, 0)); 104 EXPECT_TRUE(isValidPrefix(AF_INET, 1)); 105 EXPECT_TRUE(isValidPrefix(AF_INET, 32)); 106 EXPECT_FALSE(isValidPrefix(AF_INET, 33)); 107 EXPECT_FALSE(isValidPrefix(AF_INET, 64)); 108 109 EXPECT_TRUE(isValidPrefix(AF_INET6, 0)); 110 EXPECT_TRUE(isValidPrefix(AF_INET6, 1)); 111 EXPECT_TRUE(isValidPrefix(AF_INET6, 53)); 112 EXPECT_TRUE(isValidPrefix(AF_INET6, 64)); 113 EXPECT_TRUE(isValidPrefix(AF_INET6, 128)); 114 EXPECT_FALSE(isValidPrefix(AF_INET6, 129)); 115 EXPECT_FALSE(isValidPrefix(AF_INET6, 177)); 116 117 EXPECT_THROW(isValidPrefix(AF_UNSPEC, 1), std::invalid_argument); 118 } 119 120 TEST_F(TestUtil, InterfaceToUbootEthAddr) 121 { 122 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("et")); 123 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("eth")); 124 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("sit0")); 125 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("ethh0")); 126 EXPECT_EQ(std::nullopt, interfaceToUbootEthAddr("eth0h")); 127 EXPECT_EQ("ethaddr", interfaceToUbootEthAddr("eth0")); 128 EXPECT_EQ("eth1addr", interfaceToUbootEthAddr("eth1")); 129 EXPECT_EQ("eth5addr", interfaceToUbootEthAddr("eth5")); 130 EXPECT_EQ("eth28addr", interfaceToUbootEthAddr("eth28")); 131 } 132 133 namespace mac_address 134 { 135 136 TEST(MacFromString, Bad) 137 { 138 EXPECT_THROW(fromString("0x:00:00:00:00:00"), std::invalid_argument); 139 EXPECT_THROW(fromString("00:00:00:00:00"), std::invalid_argument); 140 EXPECT_THROW(fromString("00:00:00:00:00:"), std::invalid_argument); 141 EXPECT_THROW(fromString("00:00:00:00::00"), std::invalid_argument); 142 EXPECT_THROW(fromString(":00:00:00:00:00"), std::invalid_argument); 143 EXPECT_THROW(fromString("00::00:00:00:00"), std::invalid_argument); 144 EXPECT_THROW(fromString(":::::"), std::invalid_argument); 145 EXPECT_THROW(fromString("00:0:0:0:0"), std::invalid_argument); 146 EXPECT_THROW(fromString("00:00:00:00:00:00:00"), std::invalid_argument); 147 EXPECT_THROW(fromString(""), std::invalid_argument); 148 EXPECT_THROW(fromString("123456789XYZ"), std::invalid_argument); 149 EXPECT_THROW(fromString("123456789AB"), std::invalid_argument); 150 EXPECT_THROW(fromString("123456789ABCD"), std::invalid_argument); 151 } 152 153 TEST(MacFromString, Valid) 154 { 155 EXPECT_TRUE( 156 stdplus::raw::equal(ether_addr{}, fromString("00:00:00:00:00:00"))); 157 EXPECT_TRUE( 158 stdplus::raw::equal(ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}, 159 fromString("FF:EE:DD:cc:bb:aa"))); 160 EXPECT_TRUE( 161 stdplus::raw::equal(ether_addr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05}, 162 fromString("0:1:2:3:4:5"))); 163 EXPECT_TRUE( 164 stdplus::raw::equal(ether_addr{0x01, 0x23, 0x45, 0x67, 0x89, 0xab}, 165 fromString("0123456789AB"))); 166 EXPECT_TRUE( 167 stdplus::raw::equal(ether_addr{0xff, 0xee, 0xdd, 0xcc, 0xbb, 0xaa}, 168 fromString("FFEEDDccbbaa"))); 169 } 170 171 TEST(MacToString, Valid) 172 { 173 EXPECT_EQ("11:22:33:44:55:66", 174 toString({0x11, 0x22, 0x33, 0x44, 0x55, 0x66})); 175 EXPECT_EQ("01:02:03:04:05:67", 176 toString({0x01, 0x02, 0x03, 0x04, 0x05, 0x67})); 177 EXPECT_EQ("00:00:00:00:00:00", 178 toString({0x00, 0x00, 0x00, 0x00, 0x00, 0x00})); 179 } 180 181 TEST(MacIsEmpty, True) 182 { 183 EXPECT_TRUE(isEmpty({})); 184 } 185 186 TEST(MacIsEmpty, False) 187 { 188 EXPECT_FALSE(isEmpty(fromString("01:00:00:00:00:00"))); 189 EXPECT_FALSE(isEmpty(fromString("00:00:00:10:00:00"))); 190 EXPECT_FALSE(isEmpty(fromString("00:00:00:00:00:01"))); 191 } 192 193 TEST(MacIsMulticast, True) 194 { 195 EXPECT_TRUE(isMulticast(fromString("ff:ff:ff:ff:ff:ff"))); 196 EXPECT_TRUE(isMulticast(fromString("01:00:00:00:00:00"))); 197 } 198 199 TEST(MacIsMulticast, False) 200 { 201 EXPECT_FALSE(isMulticast(fromString("00:11:22:33:44:55"))); 202 EXPECT_FALSE(isMulticast(fromString("FE:11:22:33:44:55"))); 203 } 204 205 TEST(MacIsUnicast, True) 206 { 207 EXPECT_TRUE(isUnicast(fromString("00:11:22:33:44:55"))); 208 EXPECT_TRUE(isUnicast(fromString("FE:11:22:33:44:55"))); 209 } 210 211 TEST(MacIsUnicast, False) 212 { 213 EXPECT_FALSE(isUnicast(fromString("00:00:00:00:00:00"))); 214 EXPECT_FALSE(isUnicast(fromString("01:00:00:00:00:00"))); 215 EXPECT_FALSE(isUnicast(fromString("ff:ff:ff:ff:ff:ff"))); 216 } 217 218 TEST(IgnoredInterfaces, Empty) 219 { 220 auto ret = internal::parseInterfaces({}); 221 EXPECT_TRUE(ret.empty()); 222 223 ret = internal::parseInterfaces(" , ,, "); 224 EXPECT_TRUE(ret.empty()); 225 } 226 227 TEST(IgnoredInterfaces, NotEmpty) 228 { 229 using ::testing::ContainerEq; 230 std::unordered_set<std::string_view> expected = {"eth0"}; 231 auto ret = internal::parseInterfaces("eth0"); 232 EXPECT_THAT(ret, ContainerEq(expected)); 233 234 expected = {"eth0", "eth1", "bond1", "usb0"}; 235 ret = internal::parseInterfaces(" ,eth0, eth1 ,bond1, usb0,,"); 236 EXPECT_THAT(ret, ContainerEq(expected)); 237 } 238 239 } // namespace mac_address 240 } // namespace network 241 } // namespace phosphor 242