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, 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 
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)));
64 }
65 
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));
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));
124 }
125 
126 TEST_F(TestUtil, MacValidation)
127 {
128     std::string macaddress = "00:00:00:00:00:00";
129     EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
130 
131     macaddress = "F6:C6:E6:6:B0:D3";
132     EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress));
133 
134     macaddress = "F6:C6:E6:06:B0:D3";
135     EXPECT_EQ(true, phosphor::network::mac_address::validate(macaddress));
136 
137     macaddress = "hh:HH:HH:hh:HH:yy";
138     EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
139 
140     macaddress = "hhh:GGG:iii:jjj:kkk:lll";
141     EXPECT_EQ(false, phosphor::network::mac_address::validate(macaddress));
142 }
143 
144 TEST_F(TestUtil, ConvertV4MasktoPrefix)
145 {
146     std::string mask = "255.255.255.0";
147     uint8_t prefix = toCidr(AF_INET, mask);
148     EXPECT_EQ(prefix, 24);
149 
150     mask = "255.255.0.0";
151     prefix = toCidr(AF_INET, mask);
152     EXPECT_EQ(prefix, 16);
153 
154     mask = "255.0.0.0";
155     prefix = toCidr(AF_INET, mask);
156     EXPECT_EQ(prefix, 8);
157 
158     mask = "255.224.0.0";
159     prefix = toCidr(AF_INET, mask);
160     EXPECT_EQ(prefix, 11);
161 
162     // Invalid Mask
163     mask = "255.0.255.0";
164     prefix = toCidr(AF_INET, mask);
165     EXPECT_EQ(prefix, 0);
166 }
167 
168 TEST_F(TestUtil, convertV6MasktoPrefix)
169 {
170     std::string mask = "ffff:ffff::";
171     uint8_t prefix = toCidr(AF_INET6, mask);
172     EXPECT_EQ(prefix, 32);
173 
174     mask = "ffff:ffff:ffff::";
175     prefix = toCidr(AF_INET6, mask);
176     EXPECT_EQ(prefix, 48);
177 
178     mask = "ffff:ffff:fc00::";
179     prefix = toCidr(AF_INET6, mask);
180     EXPECT_EQ(prefix, 38);
181 
182     // Invalid Mask
183     mask = "ffff:0fff::";
184     prefix = toCidr(AF_INET6, mask);
185     EXPECT_EQ(prefix, 0);
186 }
187 
188 TEST_F(TestUtil, isLinkLocaladdress)
189 {
190     std::string ipaddress = "fe80:fec0::";
191     EXPECT_TRUE(isLinkLocalIP(ipaddress));
192 
193     ipaddress = "2000:fe80:789::";
194     EXPECT_FALSE(isLinkLocalIP(ipaddress));
195 
196     ipaddress = "2000:fe80::";
197     EXPECT_FALSE(isLinkLocalIP(ipaddress));
198 
199     ipaddress = "169.254.3.3";
200     EXPECT_TRUE(isLinkLocalIP(ipaddress));
201 
202     ipaddress = "3.169.254.3";
203     EXPECT_FALSE(isLinkLocalIP(ipaddress));
204 
205     ipaddress = "3.3.169.254";
206     EXPECT_FALSE(isLinkLocalIP(ipaddress));
207 }
208 
209 TEST_F(TestUtil, convertPrefixToMask)
210 {
211     std::string mask = toMask(AF_INET, 24);
212     EXPECT_EQ(mask, "255.255.255.0");
213 
214     mask = toMask(AF_INET, 8);
215     EXPECT_EQ(mask, "255.0.0.0");
216 
217     mask = toMask(AF_INET, 27);
218     EXPECT_EQ(mask, "255.255.255.224");
219 }
220 
221 TEST_F(TestUtil, getNetworkAddress)
222 {
223     std::string address = getNetworkID(AF_INET, "9.3.23.251", 24);
224     EXPECT_EQ("9.3.23.0", address);
225 
226     address = getNetworkID(AF_INET, "9.3.23.251", 25);
227     EXPECT_EQ("9.3.23.128", address);
228 
229     address = getNetworkID(AF_INET6, "2001:db8:abcd:dd12::0", 64);
230     EXPECT_EQ("2001:db8:abcd:dd12::", address);
231 
232     EXPECT_THROW(getNetworkID(AF_INET, "a.b.c.d", 25), InternalFailure);
233 
234     EXPECT_THROW(getNetworkID(AF_INET6, "2001:db8:gghh:dd12::0", 64),
235                  InternalFailure);
236 
237     address = getNetworkID(AF_INET6, "fe80::201:6cff:fe80:228", 64);
238     EXPECT_EQ("fe80::", address);
239 }
240 
241 TEST_F(TestUtil, CopyFromTooSmall)
242 {
243     constexpr auto expected = "abcde"sv;
244     struct
245     {
246         uint8_t data[10];
247     } data;
248     static_assert(sizeof(data) > expected.size());
249     EXPECT_THROW(copyFrom<decltype(data)>(expected), std::runtime_error);
250 }
251 
252 TEST_F(TestUtil, CopyFromSome)
253 {
254     constexpr auto expected = "abcde"sv;
255     struct
256     {
257         uint8_t data[2];
258     } data;
259     static_assert(sizeof(data) < expected.size());
260     data = copyFrom<decltype(data)>(expected);
261     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
262 }
263 
264 TEST_F(TestUtil, CopyFromAll)
265 {
266     constexpr auto expected = "abcde"sv;
267     struct
268     {
269         uint8_t data[5];
270     } data;
271     static_assert(sizeof(data) == expected.size());
272     data = copyFrom<decltype(data)>(expected);
273     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
274 }
275 
276 TEST_F(TestUtil, ExtractSome)
277 {
278     constexpr auto expected = "abcde"sv;
279     auto buf = expected;
280     struct
281     {
282         uint8_t data[2];
283     } data;
284     static_assert(sizeof(data) < expected.size());
285     data = extract<decltype(data)>(buf);
286     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
287     EXPECT_EQ(3, buf.size());
288     EXPECT_EQ(expected.substr(2), buf);
289 }
290 
291 TEST_F(TestUtil, ExtractAll)
292 {
293     constexpr auto expected = "abcde"sv;
294     auto buf = expected;
295     struct
296     {
297         uint8_t data[5];
298     } data;
299     static_assert(sizeof(data) == expected.size());
300     data = extract<decltype(data)>(buf);
301     EXPECT_EQ(0, memcmp(&data, expected.data(), sizeof(data)));
302     EXPECT_EQ(0, buf.size());
303 }
304 
305 TEST_F(TestUtil, Equal)
306 {
307     struct
308     {
309         int i;
310     } a, b{};
311     a.i = 4;
312     b.i = 4;
313 
314     EXPECT_TRUE(equal(a, b));
315 }
316 
317 TEST_F(TestUtil, NotEqual)
318 {
319     struct
320     {
321         int i;
322     } a, b{};
323     a.i = 2;
324     b.i = 4;
325 
326     EXPECT_FALSE(equal(a, b));
327 }
328 
329 } // namespace network
330 } // namespace phosphor
331