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