• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2019 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/dns/public/resolv_reader.h"
11 
12 #include <arpa/inet.h>
13 #include <resolv.h>
14 
15 #include <memory>
16 #include <optional>
17 #include <utility>
18 #include <vector>
19 
20 #include "base/cancelable_callback.h"
21 #include "base/check.h"
22 #include "base/functional/bind.h"
23 #include "base/run_loop.h"
24 #include "base/sys_byteorder.h"
25 #include "base/task/sequenced_task_runner.h"
26 #include "base/task/task_traits.h"
27 #include "base/task/thread_pool.h"
28 #include "build/build_config.h"
29 #include "net/base/ip_address.h"
30 #include "net/dns/public/dns_protocol.h"
31 #include "testing/gtest/include/gtest/gtest.h"
32 
33 namespace net {
34 
35 namespace {
36 
37 // MAXNS is normally 3, but let's test 4 if possible.
38 const char* const kNameserversIPv4[] = {
39     "8.8.8.8",
40     "192.168.1.1",
41     "63.1.2.4",
42     "1.0.0.1",
43 };
44 
45 #if BUILDFLAG(IS_LINUX)
46 const char* const kNameserversIPv6[] = {
47     nullptr,
48     "2001:db8::42",
49     nullptr,
50     "::FFFF:129.144.52.38",
51 };
52 #endif
53 
54 // Fills in |res| with sane configuration.
InitializeResState(res_state res)55 void InitializeResState(res_state res) {
56   memset(res, 0, sizeof(*res));
57   res->options = RES_INIT;
58 
59   for (unsigned i = 0; i < std::size(kNameserversIPv4) && i < MAXNS; ++i) {
60     struct sockaddr_in sa;
61     sa.sin_family = AF_INET;
62     sa.sin_port = base::HostToNet16(NS_DEFAULTPORT + i);
63     inet_pton(AF_INET, kNameserversIPv4[i], &sa.sin_addr);
64     res->nsaddr_list[i] = sa;
65     ++res->nscount;
66   }
67 
68 #if BUILDFLAG(IS_LINUX)
69   // Install IPv6 addresses, replacing the corresponding IPv4 addresses.
70   unsigned nscount6 = 0;
71   for (unsigned i = 0; i < std::size(kNameserversIPv6) && i < MAXNS; ++i) {
72     if (!kNameserversIPv6[i])
73       continue;
74     // Must use malloc to mimic res_ninit. Expect to be freed in
75     // `TestResolvReader::CloseResState()`.
76     struct sockaddr_in6* sa6;
77     sa6 = static_cast<sockaddr_in6*>(malloc(sizeof(*sa6)));
78     sa6->sin6_family = AF_INET6;
79     sa6->sin6_port = base::HostToNet16(NS_DEFAULTPORT - i);
80     inet_pton(AF_INET6, kNameserversIPv6[i], &sa6->sin6_addr);
81     res->_u._ext.nsaddrs[i] = sa6;
82     memset(&res->nsaddr_list[i], 0, sizeof res->nsaddr_list[i]);
83     ++nscount6;
84   }
85   res->_u._ext.nscount6 = nscount6;
86 #endif
87 }
88 
FreeResState(struct __res_state * res)89 void FreeResState(struct __res_state* res) {
90 #if BUILDFLAG(IS_LINUX)
91   for (int i = 0; i < res->nscount; ++i) {
92     if (res->_u._ext.nsaddrs[i] != nullptr)
93       free(res->_u._ext.nsaddrs[i]);
94   }
95 #endif
96 }
97 
TEST(ResolvReaderTest,GetNameservers)98 TEST(ResolvReaderTest, GetNameservers) {
99   auto res = std::make_unique<struct __res_state>();
100   InitializeResState(res.get());
101 
102   std::optional<std::vector<IPEndPoint>> nameservers =
103       GetNameservers(*res.get());
104   EXPECT_TRUE(nameservers.has_value());
105 
106 #if BUILDFLAG(IS_LINUX)
107   EXPECT_EQ(kNameserversIPv4[0], nameservers->at(0).ToStringWithoutPort());
108   EXPECT_EQ(kNameserversIPv6[1], nameservers->at(1).ToStringWithoutPort());
109   EXPECT_EQ(kNameserversIPv4[2], nameservers->at(2).ToStringWithoutPort());
110 #else
111   EXPECT_EQ(kNameserversIPv4[0], nameservers->at(0).ToStringWithoutPort());
112   EXPECT_EQ(kNameserversIPv4[1], nameservers->at(1).ToStringWithoutPort());
113   EXPECT_EQ(kNameserversIPv4[2], nameservers->at(2).ToStringWithoutPort());
114 #endif
115 
116   FreeResState(res.get());
117 }
118 
119 }  // namespace
120 
121 }  // namespace net
122