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, ToHex)
32 {
33     EXPECT_EQ('E', mac_address::internal::toHex(std::byte(0xfe)));
34     EXPECT_EQ('A', mac_address::internal::toHex(std::byte(10)));
35     EXPECT_EQ('4', mac_address::internal::toHex(std::byte(4)));
36 }
37 
38 TEST_F(TestUtil, MacFromBuf)
39 {
40     std::string tooSmall(1, 'a');
41     std::string tooLarge(24, 'a');
42     std::string buf{'\x00', '\xde', '\xad', '\x00', '\xbe', '\xef'};
43 
44     MacAddr mac = mac_address::fromBuf(buf);
45     EXPECT_EQ(0, memcmp(buf.data(), mac.data(), buf.size()));
46 
47     EXPECT_THROW(mac_address::fromBuf(tooSmall), std::runtime_error);
48     EXPECT_THROW(mac_address::fromBuf(tooLarge), std::runtime_error);
49 }
50 
51 TEST_F(TestUtil, MacToString)
52 {
53     MacAddr mac1{
54         std::byte(0x00), std::byte(0xDE), std::byte(0xAD),
55         std::byte(0x00), std::byte(0xBE), std::byte(0xEF),
56     };
57     EXPECT_EQ("00:DE:AD:00:BE:EF", mac_address::toString(mac1));
58     MacAddr mac2{
59         std::byte(0x70), std::byte(0xFF), std::byte(0x84),
60         std::byte(0x09), std::byte(0x35), std::byte(0x09),
61     };
62     EXPECT_EQ("70:FF:84:09:35:09", mac_address::toString(mac2));
63 }
64 
65 TEST_F(TestUtil, AddrFromBuf)
66 {
67     std::string tooSmall(1, 'a');
68     std::string tooLarge(24, 'a');
69 
70     struct in_addr ip1;
71     EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1));
72     std::string_view buf1(reinterpret_cast<char*>(&ip1), sizeof(ip1));
73     InAddrAny res1 = addrFromBuf(AF_INET, buf1);
74     EXPECT_EQ(0, memcmp(&ip1, &std::get<struct in_addr>(res1), sizeof(ip1)));
75     EXPECT_THROW(addrFromBuf(AF_INET, tooSmall), std::runtime_error);
76     EXPECT_THROW(addrFromBuf(AF_INET, tooLarge), std::runtime_error);
77     EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf1), std::runtime_error);
78 
79     struct in6_addr ip2;
80     EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2));
81     std::string_view buf2(reinterpret_cast<char*>(&ip2), sizeof(ip2));
82     InAddrAny res2 = addrFromBuf(AF_INET6, buf2);
83     EXPECT_EQ(0, memcmp(&ip2, &std::get<struct in6_addr>(res2), sizeof(ip2)));
84     EXPECT_THROW(addrFromBuf(AF_INET6, tooSmall), std::runtime_error);
85     EXPECT_THROW(addrFromBuf(AF_INET6, tooLarge), std::runtime_error);
86     EXPECT_THROW(addrFromBuf(AF_UNSPEC, buf2), std::runtime_error);
87 }
88 
89 TEST_F(TestUtil, IpToString)
90 {
91     struct in_addr ip1;
92     EXPECT_EQ(1, inet_pton(AF_INET, "192.168.10.1", &ip1));
93     EXPECT_EQ("192.168.10.1", toString(InAddrAny(ip1)));
94 
95     struct in6_addr ip2;
96     EXPECT_EQ(1, inet_pton(AF_INET6, "fdd8:b5ad:9d93:94ee::2:1", &ip2));
97     EXPECT_EQ("fdd8:b5ad:9d93:94ee::2:1", toString(InAddrAny(ip2)));
98 }
99 
100 TEST_F(TestUtil, IpValidation)
101 {
102     std::string ipaddress = "0.0.0.0";
103     EXPECT_EQ(true, isValidIP(AF_INET, ipaddress));
104 
105     ipaddress = "9.3.185.83";
106     EXPECT_EQ(true, isValidIP(AF_INET, ipaddress));
107 
108     ipaddress = "9.3.185.a";
109     EXPECT_EQ(false, isValidIP(AF_INET, ipaddress));
110 
111     ipaddress = "9.3.a.83";
112     EXPECT_EQ(false, isValidIP(AF_INET, ipaddress));
113 
114     ipaddress = "x.x.x.x";
115     EXPECT_EQ(false, isValidIP(AF_INET, ipaddress));
116 
117     ipaddress = "0:0:0:0:0:0:0:0";
118     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
119 
120     ipaddress = "1:0:0:0:0:0:0:8";
121     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
122 
123     ipaddress = "1::8";
124     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
125 
126     ipaddress = "0:0:0:0:0:FFFF:204.152.189.116";
127     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
128 
129     ipaddress = "::ffff:204.152.189.116";
130     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
131 
132     ipaddress = "a:0:0:0:0:FFFF:204.152.189.116";
133     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
134 
135     ipaddress = "1::8";
136     EXPECT_EQ(true, isValidIP(AF_INET6, ipaddress));
137 }
138 
139 TEST_F(TestUtil, PrefixValidation)
140 {
141     uint8_t prefixLength = 1;
142     EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength));
143 
144     prefixLength = 32;
145     EXPECT_EQ(true, isValidPrefix(AF_INET, prefixLength));
146 
147     prefixLength = 0;
148     EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength));
149 
150     prefixLength = 33;
151     EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength));
152 
153     prefixLength = 33;
154     EXPECT_EQ(true, isValidPrefix(AF_INET6, prefixLength));
155 
156     prefixLength = 65;
157     EXPECT_EQ(false, isValidPrefix(AF_INET, prefixLength));
158 }
159 
160 TEST_F(TestUtil, MacValidation)
161 {
162     std::string macaddress = "00:00:00:00:00:00";
163     EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
164 
165     macaddress = "F6:C6:E6:6:B0:D3";
166     EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress));
167 
168     macaddress = "F6:C6:E6:06:B0:D3";
169     EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress));
170 
171     macaddress = "hh:HH:HH:hh:HH:yy";
172     EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
173 
174     macaddress = "hhh:GGG:iii:jjj:kkk:lll";
175     EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
176 }
177 
178 TEST_F(TestUtil, ConvertV4MasktoPrefix)
179 {
180     std::string mask = "255.255.255.0";
181     uint8_t prefix = toCidr(AF_INET, mask);
182     EXPECT_EQ(prefix, 24);
183 
184     mask = "255.255.0.0";
185     prefix = toCidr(AF_INET, mask);
186     EXPECT_EQ(prefix, 16);
187 
188     mask = "255.0.0.0";
189     prefix = toCidr(AF_INET, mask);
190     EXPECT_EQ(prefix, 8);
191 
192     mask = "255.224.0.0";
193     prefix = toCidr(AF_INET, mask);
194     EXPECT_EQ(prefix, 11);
195 
196     // Invalid Mask
197     mask = "255.0.255.0";
198     prefix = toCidr(AF_INET, mask);
199     EXPECT_EQ(prefix, 0);
200 }
201 
202 TEST_F(TestUtil, convertV6MasktoPrefix)
203 {
204     std::string mask = "ffff:ffff::";
205     uint8_t prefix = toCidr(AF_INET6, mask);
206     EXPECT_EQ(prefix, 32);
207 
208     mask = "ffff:ffff:ffff::";
209     prefix = toCidr(AF_INET6, mask);
210     EXPECT_EQ(prefix, 48);
211 
212     mask = "ffff:ffff:fc00::";
213     prefix = toCidr(AF_INET6, mask);
214     EXPECT_EQ(prefix, 38);
215 
216     // Invalid Mask
217     mask = "ffff:0fff::";
218     prefix = toCidr(AF_INET6, mask);
219     EXPECT_EQ(prefix, 0);
220 }
221 
222 TEST_F(TestUtil, isLinkLocaladdress)
223 {
224     std::string ipaddress = "fe80:fec0::";
225     EXPECT_TRUE(isLinkLocalIP(ipaddress));
226 
227     ipaddress = "2000:fe80:789::";
228     EXPECT_FALSE(isLinkLocalIP(ipaddress));
229 
230     ipaddress = "2000:fe80::";
231     EXPECT_FALSE(isLinkLocalIP(ipaddress));
232 
233     ipaddress = "169.254.3.3";
234     EXPECT_TRUE(isLinkLocalIP(ipaddress));
235 
236     ipaddress = "3.169.254.3";
237     EXPECT_FALSE(isLinkLocalIP(ipaddress));
238 
239     ipaddress = "3.3.169.254";
240     EXPECT_FALSE(isLinkLocalIP(ipaddress));
241 }
242 
243 TEST_F(TestUtil, convertPrefixToMask)
244 {
245     std::string mask = toMask(AF_INET, 24);
246     EXPECT_EQ(mask, "255.255.255.0");
247 
248     mask = toMask(AF_INET, 8);
249     EXPECT_EQ(mask, "255.0.0.0");
250 
251     mask = toMask(AF_INET, 27);
252     EXPECT_EQ(mask, "255.255.255.224");
253 }
254 
255 TEST_F(TestUtil, getNetworkAddress)
256 {
257     std::string address = getNetworkID(AF_INET, "9.3.23.251", 24);
258     EXPECT_EQ("9.3.23.0", address);
259 
260     address = getNetworkID(AF_INET, "9.3.23.251", 25);
261     EXPECT_EQ("9.3.23.128", address);
262 
263     address = getNetworkID(AF_INET6, "2001:db8:abcd:dd12::0", 64);
264     EXPECT_EQ("2001:db8:abcd:dd12::", address);
265 
266     EXPECT_THROW(getNetworkID(AF_INET, "a.b.c.d", 25), InternalFailure);
267 
268     EXPECT_THROW(getNetworkID(AF_INET6, "2001:db8:gghh:dd12::0", 64),
269                  InternalFailure);
270 
271     address = getNetworkID(AF_INET6, "fe80::201:6cff:fe80:228", 64);
272     EXPECT_EQ("fe80::", address);
273 }
274 
275 TEST_F(TestUtil, CopyFromTooSmall)
276 {
277     constexpr auto expected = "abcde"sv;
278     struct
279     {
280         uint8_t data[10];
281     } data;
282     static_assert(sizeof(data) > expected.size());
283     EXPECT_THROW(copyFrom<decltype(data)>(expected), std::runtime_error);
284 }
285 
286 TEST_F(TestUtil, CopyFromSome)
287 {
288     constexpr auto expected = "abcde"sv;
289     struct
290     {
291         uint8_t data[2];
292     } data;
293     static_assert(sizeof(data) < expected.size());
294     data = copyFrom<decltype(data)>(expected);
295     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
296 }
297 
298 TEST_F(TestUtil, CopyFromAll)
299 {
300     constexpr auto expected = "abcde"sv;
301     struct
302     {
303         uint8_t data[5];
304     } data;
305     static_assert(sizeof(data) == expected.size());
306     data = copyFrom<decltype(data)>(expected);
307     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
308 }
309 
310 TEST_F(TestUtil, ExtractSome)
311 {
312     constexpr auto expected = "abcde"sv;
313     auto buf = expected;
314     struct
315     {
316         uint8_t data[2];
317     } data;
318     static_assert(sizeof(data) < expected.size());
319     data = extract<decltype(data)>(buf);
320     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
321     EXPECT_EQ(3, buf.size());
322     EXPECT_EQ(expected.substr(2), buf);
323 }
324 
325 TEST_F(TestUtil, ExtractAll)
326 {
327     constexpr auto expected = "abcde"sv;
328     auto buf = expected;
329     struct
330     {
331         uint8_t data[5];
332     } data;
333     static_assert(sizeof(data) == expected.size());
334     data = extract<decltype(data)>(buf);
335     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
336     EXPECT_EQ(0, buf.size());
337 }
338 
339 TEST_F(TestUtil, Equal)
340 {
341     struct
342     {
343         int i;
344     } a, b{};
345     a.i = 4;
346     b.i = 4;
347 
348     EXPECT_TRUE(equal(a, b));
349 }
350 
351 TEST_F(TestUtil, NotEqual)
352 {
353     struct
354     {
355         int i;
356     } a, b{};
357     a.i = 2;
358     b.i = 4;
359 
360     EXPECT_FALSE(equal(a, b));
361 }
362 
363 } // namespace network
364 } // namespace phosphor
365