xref: /aosp_15_r20/external/cronet/net/base/ip_endpoint_unittest.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "net/base/ip_endpoint.h"
6 
7 #include <string.h>
8 
9 #include <optional>
10 #include <string>
11 #include <tuple>
12 
13 #include "base/check_op.h"
14 #include "base/notreached.h"
15 #include "base/numerics/safe_conversions.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/sys_byteorder.h"
18 #include "base/values.h"
19 #include "build/build_config.h"
20 #include "net/base/ip_address.h"
21 #include "net/base/sockaddr_storage.h"
22 #include "net/base/sys_addrinfo.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "testing/platform_test.h"
26 
27 #if BUILDFLAG(IS_WIN)
28 #include <winsock2.h>
29 
30 #include <ws2bth.h>
31 
32 #include "base/test/gtest_util.h"   // For EXPECT_DCHECK_DEATH
33 #include "net/base/winsock_util.h"  // For kBluetoothAddressSize
34 #elif BUILDFLAG(IS_POSIX)
35 #include <netinet/in.h>
36 #endif
37 
38 using testing::Optional;
39 
40 namespace net {
41 
42 namespace {
43 
44 // Retuns the port field of the |sockaddr|.
GetPortFieldFromSockaddr(const struct sockaddr * address,socklen_t address_len)45 const uint16_t* GetPortFieldFromSockaddr(const struct sockaddr* address,
46                                          socklen_t address_len) {
47   if (address->sa_family == AF_INET) {
48     DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len));
49     const struct sockaddr_in* sockaddr =
50         reinterpret_cast<const struct sockaddr_in*>(address);
51     return &sockaddr->sin_port;
52   } else if (address->sa_family == AF_INET6) {
53     DCHECK_LE(sizeof(sockaddr_in6), static_cast<size_t>(address_len));
54     const struct sockaddr_in6* sockaddr =
55         reinterpret_cast<const struct sockaddr_in6*>(address);
56     return &sockaddr->sin6_port;
57   } else {
58     NOTREACHED();
59     return nullptr;
60   }
61 }
62 
63 // Returns the value of port in |sockaddr| (in host byte ordering).
GetPortFromSockaddr(const struct sockaddr * address,socklen_t address_len)64 int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) {
65   const uint16_t* port_field = GetPortFieldFromSockaddr(address, address_len);
66   if (!port_field)
67     return -1;
68   return base::NetToHost16(*port_field);
69 }
70 
71 struct TestData {
72   std::string host;
73   std::string host_normalized;
74   bool ipv6;
75   IPAddress ip_address;
76 } tests[] = {
77     {"127.0.00.1", "127.0.0.1", false},
78     {"192.168.1.1", "192.168.1.1", false},
79     {"::1", "[::1]", true},
80     {"2001:db8:0::42", "[2001:db8::42]", true},
81 };
82 
83 class IPEndPointTest : public PlatformTest {
84  public:
SetUp()85   void SetUp() override {
86     // This is where we populate the TestData.
87     for (auto& test : tests) {
88       EXPECT_TRUE(test.ip_address.AssignFromIPLiteral(test.host));
89     }
90   }
91 };
92 
TEST_F(IPEndPointTest,Constructor)93 TEST_F(IPEndPointTest, Constructor) {
94   {
95     IPEndPoint endpoint;
96     EXPECT_EQ(0, endpoint.port());
97   }
98 
99   for (const auto& test : tests) {
100     IPEndPoint endpoint(test.ip_address, 80);
101     EXPECT_EQ(80, endpoint.port());
102     EXPECT_EQ(test.ip_address, endpoint.address());
103   }
104 }
105 
TEST_F(IPEndPointTest,Assignment)106 TEST_F(IPEndPointTest, Assignment) {
107   uint16_t port = 0;
108   for (const auto& test : tests) {
109     IPEndPoint src(test.ip_address, ++port);
110     IPEndPoint dest = src;
111 
112     EXPECT_EQ(src.port(), dest.port());
113     EXPECT_EQ(src.address(), dest.address());
114   }
115 }
116 
TEST_F(IPEndPointTest,Copy)117 TEST_F(IPEndPointTest, Copy) {
118   uint16_t port = 0;
119   for (const auto& test : tests) {
120     IPEndPoint src(test.ip_address, ++port);
121     IPEndPoint dest(src);
122 
123     EXPECT_EQ(src.port(), dest.port());
124     EXPECT_EQ(src.address(), dest.address());
125   }
126 }
127 
TEST_F(IPEndPointTest,ToFromSockAddr)128 TEST_F(IPEndPointTest, ToFromSockAddr) {
129   uint16_t port = 0;
130   for (const auto& test : tests) {
131     IPEndPoint ip_endpoint(test.ip_address, ++port);
132 
133     // Convert to a sockaddr.
134     SockaddrStorage storage;
135     EXPECT_TRUE(ip_endpoint.ToSockAddr(storage.addr, &storage.addr_len));
136 
137     // Basic verification.
138     socklen_t expected_size =
139         test.ipv6 ? sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in);
140     EXPECT_EQ(expected_size, storage.addr_len);
141     EXPECT_EQ(ip_endpoint.port(),
142               GetPortFromSockaddr(storage.addr, storage.addr_len));
143     // And convert back to an IPEndPoint.
144     IPEndPoint ip_endpoint2;
145     EXPECT_TRUE(ip_endpoint2.FromSockAddr(storage.addr, storage.addr_len));
146     EXPECT_EQ(ip_endpoint.port(), ip_endpoint2.port());
147     EXPECT_EQ(ip_endpoint.address(), ip_endpoint2.address());
148   }
149 }
150 
TEST_F(IPEndPointTest,ToSockAddrBufTooSmall)151 TEST_F(IPEndPointTest, ToSockAddrBufTooSmall) {
152   uint16_t port = 0;
153   for (const auto& test : tests) {
154     IPEndPoint ip_endpoint(test.ip_address, port);
155 
156     SockaddrStorage storage;
157     storage.addr_len = 3;  // size is too small!
158     EXPECT_FALSE(ip_endpoint.ToSockAddr(storage.addr, &storage.addr_len));
159   }
160 }
161 
TEST_F(IPEndPointTest,FromSockAddrBufTooSmall)162 TEST_F(IPEndPointTest, FromSockAddrBufTooSmall) {
163   struct sockaddr_in addr;
164   memset(&addr, 0, sizeof(addr));
165   addr.sin_family = AF_INET;
166   IPEndPoint ip_endpoint;
167   struct sockaddr* sockaddr = reinterpret_cast<struct sockaddr*>(&addr);
168   EXPECT_FALSE(ip_endpoint.FromSockAddr(sockaddr, sizeof(addr) - 1));
169 }
170 
171 #if BUILDFLAG(IS_WIN)
172 
173 namespace {
174 constexpr uint8_t kBluetoothAddrBytes[kBluetoothAddressSize] = {1, 2, 3,
175                                                                 4, 5, 6};
176 constexpr uint8_t kBluetoothAddrBytes2[kBluetoothAddressSize] = {1, 2, 3,
177                                                                  4, 5, 7};
178 const IPAddress kBluetoothAddress(kBluetoothAddrBytes);
179 const IPAddress kBluetoothAddress2(kBluetoothAddrBytes2);
180 
181 // Select a Bluetooth port that does not fit in a uint16_t.
182 constexpr uint32_t kBluetoothPort = std::numeric_limits<uint16_t>::max() + 1;
183 
BuildBluetoothSockAddr(const IPAddress & ip_address,uint32_t port)184 SOCKADDR_BTH BuildBluetoothSockAddr(const IPAddress& ip_address,
185                                     uint32_t port) {
186   SOCKADDR_BTH addr = {};
187   addr.addressFamily = AF_BTH;
188   DCHECK_LE(ip_address.bytes().size(), sizeof(addr.btAddr));
189   memcpy(&addr.btAddr, ip_address.bytes().data(), ip_address.bytes().size());
190   addr.port = port;
191   return addr;
192 }
193 }  // namespace
194 
TEST_F(IPEndPointTest,WinBluetoothSockAddrCompareWithSelf)195 TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithSelf) {
196   IPEndPoint bt_endpoint;
197   SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
198   EXPECT_TRUE(bt_endpoint.FromSockAddr(
199       reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
200   EXPECT_EQ(bt_endpoint.address(), kBluetoothAddress);
201   EXPECT_EQ(bt_endpoint.GetFamily(), AddressFamily::ADDRESS_FAMILY_UNSPECIFIED);
202   EXPECT_EQ(bt_endpoint.GetSockAddrFamily(), AF_BTH);
203   // Comparison functions should agree that `bt_endpoint` equals itself.
204   EXPECT_FALSE(bt_endpoint < bt_endpoint);
205   EXPECT_FALSE(bt_endpoint != bt_endpoint);
206   EXPECT_TRUE(bt_endpoint == bt_endpoint);
207   // Test that IPv4/IPv6-only methods crash.
208   EXPECT_DCHECK_DEATH(bt_endpoint.port());
209   SockaddrStorage storage;
210   EXPECT_DCHECK_DEATH(
211       std::ignore = bt_endpoint.ToSockAddr(storage.addr, &storage.addr_len));
212   EXPECT_DCHECK_DEATH(bt_endpoint.ToString());
213   EXPECT_DCHECK_DEATH(bt_endpoint.ToStringWithoutPort());
214 }
215 
TEST_F(IPEndPointTest,WinBluetoothSockAddrCompareWithNonBluetooth)216 TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithNonBluetooth) {
217   IPEndPoint bt_endpoint;
218   SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
219   EXPECT_TRUE(bt_endpoint.FromSockAddr(
220       reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
221 
222   // Compare `bt_endpoint` with non-Bluetooth endpoints.
223   for (const auto& test : tests) {
224     IPEndPoint endpoint(test.ip_address, 80);
225     if (test.ip_address.IsIPv4()) {
226       EXPECT_FALSE(bt_endpoint < endpoint);
227     } else {
228       EXPECT_TRUE(test.ip_address.IsIPv6());
229       EXPECT_TRUE(bt_endpoint < endpoint);
230     }
231     EXPECT_TRUE(bt_endpoint != endpoint);
232     EXPECT_FALSE(bt_endpoint == endpoint);
233   }
234 }
235 
TEST_F(IPEndPointTest,WinBluetoothSockAddrCompareWithCopy)236 TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithCopy) {
237   IPEndPoint bt_endpoint;
238   SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
239   EXPECT_TRUE(bt_endpoint.FromSockAddr(
240       reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
241 
242   // Verify that a copy's accessors return the same values as the original's.
243   IPEndPoint bt_endpoint_other(bt_endpoint);
244   EXPECT_EQ(bt_endpoint.address(), bt_endpoint_other.address());
245   EXPECT_EQ(bt_endpoint.GetFamily(), bt_endpoint_other.GetFamily());
246   EXPECT_EQ(bt_endpoint.GetSockAddrFamily(),
247             bt_endpoint_other.GetSockAddrFamily());
248   // Comparison functions should agree that the endpoints are equal.
249   EXPECT_FALSE(bt_endpoint < bt_endpoint_other);
250   EXPECT_FALSE(bt_endpoint != bt_endpoint_other);
251   EXPECT_TRUE(bt_endpoint == bt_endpoint_other);
252   // Test that IPv4/IPv6-only methods crash.
253   EXPECT_DCHECK_DEATH(bt_endpoint_other.port());
254   SockaddrStorage storage;
255   EXPECT_DCHECK_DEATH(std::ignore = bt_endpoint_other.ToSockAddr(
256                           storage.addr, &storage.addr_len));
257   EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString());
258   EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort());
259 }
260 
TEST_F(IPEndPointTest,WinBluetoothSockAddrCompareWithDifferentPort)261 TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithDifferentPort) {
262   IPEndPoint bt_endpoint;
263   SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
264   EXPECT_TRUE(bt_endpoint.FromSockAddr(
265       reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
266 
267   // Compare with another IPEndPoint that has a different port.
268   IPEndPoint bt_endpoint_other;
269   SOCKADDR_BTH addr2 =
270       BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort + 1);
271   EXPECT_TRUE(bt_endpoint_other.FromSockAddr(
272       reinterpret_cast<const struct sockaddr*>(&addr2), sizeof(addr2)));
273   EXPECT_EQ(bt_endpoint.address(), bt_endpoint_other.address());
274   EXPECT_EQ(bt_endpoint.GetFamily(), bt_endpoint_other.GetFamily());
275   EXPECT_EQ(bt_endpoint.GetSockAddrFamily(),
276             bt_endpoint_other.GetSockAddrFamily());
277   // Comparison functions should agree that `bt_endpoint == bt_endpoint_other`
278   // because they have the same address and Bluetooth ports are not considered
279   // by comparison functions.
280   EXPECT_FALSE(bt_endpoint < bt_endpoint_other);
281   EXPECT_FALSE(bt_endpoint != bt_endpoint_other);
282   EXPECT_TRUE(bt_endpoint == bt_endpoint_other);
283   // Test that IPv4/IPv6-only methods crash.
284   EXPECT_DCHECK_DEATH(bt_endpoint_other.port());
285   SockaddrStorage storage;
286   EXPECT_DCHECK_DEATH(std::ignore = bt_endpoint_other.ToSockAddr(
287                           storage.addr, &storage.addr_len));
288   EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString());
289   EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort());
290 }
291 
TEST_F(IPEndPointTest,WinBluetoothSockAddrCompareWithDifferentAddress)292 TEST_F(IPEndPointTest, WinBluetoothSockAddrCompareWithDifferentAddress) {
293   IPEndPoint bt_endpoint;
294   SOCKADDR_BTH addr = BuildBluetoothSockAddr(kBluetoothAddress, kBluetoothPort);
295   EXPECT_TRUE(bt_endpoint.FromSockAddr(
296       reinterpret_cast<const struct sockaddr*>(&addr), sizeof(addr)));
297 
298   // Compare with another IPEndPoint that has a different address.
299   IPEndPoint bt_endpoint_other;
300   SOCKADDR_BTH addr2 =
301       BuildBluetoothSockAddr(kBluetoothAddress2, kBluetoothPort);
302   EXPECT_TRUE(bt_endpoint_other.FromSockAddr(
303       reinterpret_cast<const struct sockaddr*>(&addr2), sizeof(addr2)));
304   EXPECT_LT(bt_endpoint.address(), bt_endpoint_other.address());
305   EXPECT_EQ(bt_endpoint.GetFamily(), bt_endpoint_other.GetFamily());
306   EXPECT_EQ(bt_endpoint.GetSockAddrFamily(),
307             bt_endpoint_other.GetSockAddrFamily());
308   // Comparison functions should agree that `bt_endpoint < bt_endpoint_other`
309   // due to lexicographic comparison of the address bytes.
310   EXPECT_TRUE(bt_endpoint < bt_endpoint_other);
311   EXPECT_TRUE(bt_endpoint != bt_endpoint_other);
312   EXPECT_FALSE(bt_endpoint == bt_endpoint_other);
313   // Test that IPv4/IPv6-only methods crash.
314   EXPECT_DCHECK_DEATH(bt_endpoint_other.port());
315   SockaddrStorage storage;
316   EXPECT_DCHECK_DEATH(std::ignore = bt_endpoint_other.ToSockAddr(
317                           storage.addr, &storage.addr_len));
318   EXPECT_DCHECK_DEATH(bt_endpoint_other.ToString());
319   EXPECT_DCHECK_DEATH(bt_endpoint_other.ToStringWithoutPort());
320 }
321 #endif
322 
TEST_F(IPEndPointTest,Equality)323 TEST_F(IPEndPointTest, Equality) {
324   uint16_t port = 0;
325   for (const auto& test : tests) {
326     IPEndPoint src(test.ip_address, ++port);
327     IPEndPoint dest(src);
328     EXPECT_TRUE(src == dest);
329   }
330 }
331 
TEST_F(IPEndPointTest,LessThan)332 TEST_F(IPEndPointTest, LessThan) {
333   // Vary by port.
334   IPEndPoint ip_endpoint1(tests[0].ip_address, 100);
335   IPEndPoint ip_endpoint2(tests[0].ip_address, 1000);
336   EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
337   EXPECT_FALSE(ip_endpoint2 < ip_endpoint1);
338 
339   // IPv4 vs IPv6
340   ip_endpoint1 = IPEndPoint(tests[0].ip_address, 81);
341   ip_endpoint2 = IPEndPoint(tests[2].ip_address, 80);
342   EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
343   EXPECT_FALSE(ip_endpoint2 < ip_endpoint1);
344 
345   // IPv4 vs IPv4
346   ip_endpoint1 = IPEndPoint(tests[0].ip_address, 81);
347   ip_endpoint2 = IPEndPoint(tests[1].ip_address, 80);
348   EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
349   EXPECT_FALSE(ip_endpoint2 < ip_endpoint1);
350 
351   // IPv6 vs IPv6
352   ip_endpoint1 = IPEndPoint(tests[2].ip_address, 81);
353   ip_endpoint2 = IPEndPoint(tests[3].ip_address, 80);
354   EXPECT_TRUE(ip_endpoint1 < ip_endpoint2);
355   EXPECT_FALSE(ip_endpoint2 < ip_endpoint1);
356 
357   // Compare equivalent endpoints.
358   ip_endpoint1 = IPEndPoint(tests[0].ip_address, 80);
359   ip_endpoint2 = IPEndPoint(tests[0].ip_address, 80);
360   EXPECT_FALSE(ip_endpoint1 < ip_endpoint2);
361   EXPECT_FALSE(ip_endpoint2 < ip_endpoint1);
362 }
363 
TEST_F(IPEndPointTest,ToString)364 TEST_F(IPEndPointTest, ToString) {
365   {
366     IPEndPoint endpoint;
367     EXPECT_EQ(0, endpoint.port());
368   }
369 
370   uint16_t port = 100;
371   for (const auto& test : tests) {
372     ++port;
373     IPEndPoint endpoint(test.ip_address, port);
374     const std::string result = endpoint.ToString();
375     EXPECT_EQ(test.host_normalized + ":" + base::NumberToString(port), result);
376   }
377 
378   // ToString() shouldn't crash on invalid addresses.
379   IPAddress invalid_address;
380   IPEndPoint invalid_endpoint(invalid_address, 8080);
381   EXPECT_EQ("", invalid_endpoint.ToString());
382   EXPECT_EQ("", invalid_endpoint.ToStringWithoutPort());
383 }
384 
TEST_F(IPEndPointTest,RoundtripThroughValue)385 TEST_F(IPEndPointTest, RoundtripThroughValue) {
386   for (const auto& test : tests) {
387     IPEndPoint endpoint(test.ip_address, 1645);
388     base::Value value = endpoint.ToValue();
389 
390     EXPECT_THAT(IPEndPoint::FromValue(value), Optional(endpoint));
391   }
392 }
393 
TEST_F(IPEndPointTest,FromGarbageValue)394 TEST_F(IPEndPointTest, FromGarbageValue) {
395   base::Value value(123);
396   EXPECT_FALSE(IPEndPoint::FromValue(value).has_value());
397 }
398 
TEST_F(IPEndPointTest,FromMalformedValues)399 TEST_F(IPEndPointTest, FromMalformedValues) {
400   for (const auto& test : tests) {
401     base::Value valid_value = IPEndPoint(test.ip_address, 1111).ToValue();
402     ASSERT_TRUE(IPEndPoint::FromValue(valid_value).has_value());
403 
404     base::Value missing_address = valid_value.Clone();
405     ASSERT_TRUE(missing_address.GetDict().Remove("address"));
406     EXPECT_FALSE(IPEndPoint::FromValue(missing_address).has_value());
407 
408     base::Value missing_port = valid_value.Clone();
409     ASSERT_TRUE(missing_port.GetDict().Remove("port"));
410     EXPECT_FALSE(IPEndPoint::FromValue(missing_port).has_value());
411 
412     base::Value invalid_address = valid_value.Clone();
413     *invalid_address.GetDict().Find("address") = base::Value("1.2.3.4.5");
414     EXPECT_FALSE(IPEndPoint::FromValue(invalid_address).has_value());
415 
416     base::Value negative_port = valid_value.Clone();
417     *negative_port.GetDict().Find("port") = base::Value(-1);
418     EXPECT_FALSE(IPEndPoint::FromValue(negative_port).has_value());
419 
420     base::Value large_port = valid_value.Clone();
421     *large_port.GetDict().Find("port") = base::Value(66000);
422     EXPECT_FALSE(IPEndPoint::FromValue(large_port).has_value());
423   }
424 }
425 
426 }  // namespace
427 
428 }  // namespace net
429