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 #ifdef UNSAFE_BUFFERS_BUILD
6 // TODO(crbug.com/40284755): Remove this and spanify to fix the errors.
7 #pragma allow_unsafe_buffers
8 #endif
9
10 #include "net/base/address_list.h"
11
12 #include <algorithm>
13
14 #include "base/strings/string_util.h"
15 #include "base/sys_byteorder.h"
16 #include "net/base/ip_address.h"
17 #include "net/base/sockaddr_storage.h"
18 #include "net/base/sys_addrinfo.h"
19 #include "testing/gmock/include/gmock/gmock.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21
22 using ::testing::ElementsAre;
23 using ::testing::UnorderedElementsAre;
24
25 namespace net {
26 namespace {
27
28 const char kCanonicalHostname[] = "canonical.bar.com";
29
TEST(AddressListTest,Canonical)30 TEST(AddressListTest, Canonical) {
31 // Create an addrinfo with a canonical name.
32 struct sockaddr_in address;
33 // The contents of address do not matter for this test,
34 // so just zero-ing them out for consistency.
35 memset(&address, 0x0, sizeof(address));
36 // But we need to set the family.
37 address.sin_family = AF_INET;
38 struct addrinfo ai;
39 memset(&ai, 0x0, sizeof(ai));
40 ai.ai_family = AF_INET;
41 ai.ai_socktype = SOCK_STREAM;
42 ai.ai_addrlen = sizeof(address);
43 ai.ai_addr = reinterpret_cast<sockaddr*>(&address);
44 ai.ai_canonname = const_cast<char *>(kCanonicalHostname);
45
46 // Copy the addrinfo struct into an AddressList object and
47 // make sure it seems correct.
48 AddressList addrlist1 = AddressList::CreateFromAddrinfo(&ai);
49 EXPECT_THAT(addrlist1.dns_aliases(),
50 UnorderedElementsAre("canonical.bar.com"));
51
52 // Copy the AddressList to another one.
53 AddressList addrlist2 = addrlist1;
54 EXPECT_THAT(addrlist2.dns_aliases(),
55 UnorderedElementsAre("canonical.bar.com"));
56 }
57
TEST(AddressListTest,CreateFromAddrinfo)58 TEST(AddressListTest, CreateFromAddrinfo) {
59 // Create an 4-element addrinfo.
60 const unsigned kNumElements = 4;
61 SockaddrStorage storage[kNumElements];
62 struct addrinfo ai[kNumElements];
63 for (unsigned i = 0; i < kNumElements; ++i) {
64 struct sockaddr_in* addr =
65 reinterpret_cast<struct sockaddr_in*>(storage[i].addr);
66 storage[i].addr_len = sizeof(struct sockaddr_in);
67 // Populating the address with { i, i, i, i }.
68 memset(&addr->sin_addr, i, IPAddress::kIPv4AddressSize);
69 addr->sin_family = AF_INET;
70 // Set port to i << 2;
71 addr->sin_port = base::HostToNet16(static_cast<uint16_t>(i << 2));
72 memset(&ai[i], 0x0, sizeof(ai[i]));
73 ai[i].ai_family = addr->sin_family;
74 ai[i].ai_socktype = SOCK_STREAM;
75 ai[i].ai_addrlen = storage[i].addr_len;
76 ai[i].ai_addr = storage[i].addr;
77 if (i + 1 < kNumElements)
78 ai[i].ai_next = &ai[i + 1];
79 }
80
81 AddressList list = AddressList::CreateFromAddrinfo(&ai[0]);
82
83 ASSERT_EQ(kNumElements, list.size());
84 for (size_t i = 0; i < list.size(); ++i) {
85 EXPECT_EQ(ADDRESS_FAMILY_IPV4, list[i].GetFamily());
86 // Only check the first byte of the address.
87 EXPECT_EQ(i, list[i].address().bytes()[0]);
88 EXPECT_EQ(static_cast<int>(i << 2), list[i].port());
89 }
90
91 // Check if operator= works.
92 AddressList copy;
93 copy = list;
94 ASSERT_EQ(kNumElements, copy.size());
95
96 // Check if copy is independent.
97 copy[1] = IPEndPoint(copy[2].address(), 0xBEEF);
98 // Original should be unchanged.
99 EXPECT_EQ(1u, list[1].address().bytes()[0]);
100 EXPECT_EQ(1 << 2, list[1].port());
101 }
102
TEST(AddressListTest,CreateFromIPAddressList)103 TEST(AddressListTest, CreateFromIPAddressList) {
104 struct TestData {
105 std::string ip_address;
106 const char* in_addr;
107 int ai_family;
108 size_t ai_addrlen;
109 size_t in_addr_offset;
110 size_t in_addr_size;
111 } tests[] = {
112 { "127.0.0.1",
113 "\x7f\x00\x00\x01",
114 AF_INET,
115 sizeof(struct sockaddr_in),
116 offsetof(struct sockaddr_in, sin_addr),
117 sizeof(struct in_addr),
118 },
119 { "2001:db8:0::42",
120 "\x20\x01\x0d\xb8\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x42",
121 AF_INET6,
122 sizeof(struct sockaddr_in6),
123 offsetof(struct sockaddr_in6, sin6_addr),
124 sizeof(struct in6_addr),
125 },
126 { "192.168.1.1",
127 "\xc0\xa8\x01\x01",
128 AF_INET,
129 sizeof(struct sockaddr_in),
130 offsetof(struct sockaddr_in, sin_addr),
131 sizeof(struct in_addr),
132 },
133 };
134 const std::string kCanonicalName = "canonical.example.com";
135
136 // Construct a list of ip addresses.
137 IPAddressList ip_list;
138 for (const auto& test : tests) {
139 IPAddress ip_address;
140 ASSERT_TRUE(ip_address.AssignFromIPLiteral(test.ip_address));
141 ip_list.push_back(ip_address);
142 }
143
144 // Wrap the canonical name in an alias vector.
145 std::vector<std::string> aliases({kCanonicalName});
146
147 AddressList test_list =
148 AddressList::CreateFromIPAddressList(ip_list, std::move(aliases));
149 std::string canonical_name;
150 EXPECT_THAT(test_list.dns_aliases(), UnorderedElementsAre(kCanonicalName));
151 EXPECT_EQ(std::size(tests), test_list.size());
152 }
153
TEST(AddressListTest,GetCanonicalNameWhenUnset)154 TEST(AddressListTest, GetCanonicalNameWhenUnset) {
155 const IPAddress kAddress(1, 2, 3, 4);
156 const IPEndPoint kEndpoint(kAddress, 0);
157 AddressList addrlist(kEndpoint);
158
159 EXPECT_TRUE(addrlist.dns_aliases().empty());
160 }
161
TEST(AddressListTest,SetDefaultCanonicalNameThenSetDnsAliases)162 TEST(AddressListTest, SetDefaultCanonicalNameThenSetDnsAliases) {
163 const IPAddress kAddress(1, 2, 3, 4);
164 const IPEndPoint kEndpoint(kAddress, 0);
165 AddressList addrlist(kEndpoint);
166
167 addrlist.SetDefaultCanonicalName();
168
169 EXPECT_THAT(addrlist.dns_aliases(), UnorderedElementsAre("1.2.3.4"));
170
171 std::vector<std::string> aliases({"alias1", "alias2", "alias3"});
172 addrlist.SetDnsAliases(std::move(aliases));
173
174 // Setting the aliases after setting the default canonical name
175 // replaces the default canonical name.
176 EXPECT_THAT(addrlist.dns_aliases(),
177 UnorderedElementsAre("alias1", "alias2", "alias3"));
178 }
179
TEST(AddressListTest,SetDefaultCanonicalNameThenAppendDnsAliases)180 TEST(AddressListTest, SetDefaultCanonicalNameThenAppendDnsAliases) {
181 const IPAddress kAddress(1, 2, 3, 4);
182 const IPEndPoint kEndpoint(kAddress, 0);
183 AddressList addrlist(kEndpoint);
184
185 addrlist.SetDefaultCanonicalName();
186
187 EXPECT_THAT(addrlist.dns_aliases(), UnorderedElementsAre("1.2.3.4"));
188
189 std::vector<std::string> aliases({"alias1", "alias2", "alias3"});
190 addrlist.AppendDnsAliases(std::move(aliases));
191
192 // Appending the aliases after setting the default canonical name
193 // does not replace the default canonical name.
194 EXPECT_THAT(addrlist.dns_aliases(),
195 UnorderedElementsAre("1.2.3.4", "alias1", "alias2", "alias3"));
196 }
197
TEST(AddressListTest,DnsAliases)198 TEST(AddressListTest, DnsAliases) {
199 const IPAddress kAddress(1, 2, 3, 4);
200 const IPEndPoint kEndpoint(kAddress, 0);
201 std::vector<std::string> aliases({"alias1", "alias2", "alias3"});
202 AddressList addrlist(kEndpoint, std::move(aliases));
203
204 EXPECT_THAT(addrlist.dns_aliases(),
205 UnorderedElementsAre("alias1", "alias2", "alias3"));
206
207 std::vector<std::string> more_aliases({"alias4", "alias5", "alias6"});
208 addrlist.AppendDnsAliases(std::move(more_aliases));
209
210 EXPECT_THAT(addrlist.dns_aliases(),
211 UnorderedElementsAre("alias1", "alias2", "alias3", "alias4",
212 "alias5", "alias6"));
213
214 std::vector<std::string> new_aliases({"alias7", "alias8", "alias9"});
215 addrlist.SetDnsAliases(std::move(new_aliases));
216
217 EXPECT_THAT(addrlist.dns_aliases(),
218 UnorderedElementsAre("alias7", "alias8", "alias9"));
219 }
220
TEST(AddressListTest,DeduplicatesEmptyAddressList)221 TEST(AddressListTest, DeduplicatesEmptyAddressList) {
222 AddressList empty;
223 empty.Deduplicate();
224 EXPECT_EQ(empty.size(), 0u);
225 }
226
TEST(AddressListTest,DeduplicatesSingletonAddressList)227 TEST(AddressListTest, DeduplicatesSingletonAddressList) {
228 AddressList singleton;
229 singleton.push_back(IPEndPoint());
230 singleton.Deduplicate();
231 EXPECT_THAT(singleton.endpoints(), ElementsAre(IPEndPoint()));
232 }
233
TEST(AddressListTest,DeduplicatesLongerAddressList)234 TEST(AddressListTest, DeduplicatesLongerAddressList) {
235 AddressList several;
236 several.endpoints() = {IPEndPoint(IPAddress(0, 0, 0, 1), 0),
237 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
238 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
239 IPEndPoint(IPAddress(0, 0, 0, 3), 0),
240 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
241 IPEndPoint(IPAddress(0, 0, 0, 1), 0),
242 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
243 IPEndPoint(IPAddress(0, 0, 0, 3), 0),
244 IPEndPoint(IPAddress(0, 0, 0, 2), 0)};
245 several.Deduplicate();
246
247 // Deduplication should preserve the order of the first instances
248 // of the unique addresses.
249 EXPECT_THAT(several.endpoints(),
250 ElementsAre(IPEndPoint(IPAddress(0, 0, 0, 1), 0),
251 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
252 IPEndPoint(IPAddress(0, 0, 0, 3), 0)));
253 }
254
255 // Test that, for every permutation of a list of endpoints, deduplication
256 // produces the same results as a naive reference implementation.
TEST(AddressListTest,DeduplicatePreservesOrder)257 TEST(AddressListTest, DeduplicatePreservesOrder) {
258 std::vector<IPEndPoint> permutation = {IPEndPoint(IPAddress(0, 0, 0, 1), 0),
259 IPEndPoint(IPAddress(0, 0, 0, 1), 0),
260 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
261 IPEndPoint(IPAddress(0, 0, 0, 2), 0),
262 IPEndPoint(IPAddress(0, 0, 0, 3), 0)};
263 ASSERT_TRUE(std::is_sorted(permutation.begin(), permutation.end()));
264
265 do {
266 std::vector<IPEndPoint> expected;
267 std::set<IPEndPoint> set;
268 for (const IPEndPoint& endpoint : permutation) {
269 if (set.insert(endpoint).second)
270 expected.push_back(endpoint);
271 }
272 EXPECT_EQ(expected.size(), 3u);
273
274 AddressList address_list;
275 address_list.endpoints() = permutation;
276 address_list.Deduplicate();
277 EXPECT_EQ(address_list.endpoints(), expected);
278 } while (std::next_permutation(permutation.begin(), permutation.end()));
279 }
280
281 } // namespace
282 } // namespace net
283