1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 <resolv.h> 6 7 #include "base/sys_byteorder.h" 8 #include "net/dns/dns_config_service_posix.h" 9 10 #include "testing/gtest/include/gtest/gtest.h" 11 12 #if !defined(OS_ANDROID) 13 14 namespace net { 15 namespace { 16 17 // MAXNS is normally 3, but let's test 4 if possible. 18 const char* kNameserversIPv4[] = { 19 "8.8.8.8", 20 "192.168.1.1", 21 "63.1.2.4", 22 "1.0.0.1", 23 }; 24 25 #if defined(OS_LINUX) 26 const char* kNameserversIPv6[] = { 27 NULL, 28 "2001:DB8:0::42", 29 NULL, 30 "::FFFF:129.144.52.38", 31 }; 32 #endif 33 34 // Fills in |res| with sane configuration. 35 void InitializeResState(res_state res) { 36 memset(res, 0, sizeof(*res)); 37 res->options = RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH | 38 RES_ROTATE; 39 res->ndots = 2; 40 res->retrans = 4; 41 res->retry = 7; 42 43 const char kDnsrch[] = "chromium.org" "\0" "example.com"; 44 memcpy(res->defdname, kDnsrch, sizeof(kDnsrch)); 45 res->dnsrch[0] = res->defdname; 46 res->dnsrch[1] = res->defdname + sizeof("chromium.org"); 47 48 for (unsigned i = 0; i < arraysize(kNameserversIPv4) && i < MAXNS; ++i) { 49 struct sockaddr_in sa; 50 sa.sin_family = AF_INET; 51 sa.sin_port = base::HostToNet16(NS_DEFAULTPORT + i); 52 inet_pton(AF_INET, kNameserversIPv4[i], &sa.sin_addr); 53 res->nsaddr_list[i] = sa; 54 ++res->nscount; 55 } 56 57 #if defined(OS_LINUX) 58 // Install IPv6 addresses, replacing the corresponding IPv4 addresses. 59 unsigned nscount6 = 0; 60 for (unsigned i = 0; i < arraysize(kNameserversIPv6) && i < MAXNS; ++i) { 61 if (!kNameserversIPv6[i]) 62 continue; 63 // Must use malloc to mimick res_ninit. 64 struct sockaddr_in6 *sa6; 65 sa6 = (struct sockaddr_in6 *)malloc(sizeof(*sa6)); 66 sa6->sin6_family = AF_INET6; 67 sa6->sin6_port = base::HostToNet16(NS_DEFAULTPORT - i); 68 inet_pton(AF_INET6, kNameserversIPv6[i], &sa6->sin6_addr); 69 res->_u._ext.nsaddrs[i] = sa6; 70 memset(&res->nsaddr_list[i], 0, sizeof res->nsaddr_list[i]); 71 ++nscount6; 72 } 73 res->_u._ext.nscount6 = nscount6; 74 #endif 75 } 76 77 void CloseResState(res_state res) { 78 #if defined(OS_LINUX) 79 for (int i = 0; i < res->nscount; ++i) { 80 if (res->_u._ext.nsaddrs[i] != NULL) 81 free(res->_u._ext.nsaddrs[i]); 82 } 83 #endif 84 } 85 86 void InitializeExpectedConfig(DnsConfig* config) { 87 config->ndots = 2; 88 config->timeout = base::TimeDelta::FromSeconds(4); 89 config->attempts = 7; 90 config->rotate = true; 91 config->edns0 = false; 92 config->append_to_multi_label_name = true; 93 config->search.clear(); 94 config->search.push_back("chromium.org"); 95 config->search.push_back("example.com"); 96 97 config->nameservers.clear(); 98 for (unsigned i = 0; i < arraysize(kNameserversIPv4) && i < MAXNS; ++i) { 99 IPAddressNumber ip; 100 ParseIPLiteralToNumber(kNameserversIPv4[i], &ip); 101 config->nameservers.push_back(IPEndPoint(ip, NS_DEFAULTPORT + i)); 102 } 103 104 #if defined(OS_LINUX) 105 for (unsigned i = 0; i < arraysize(kNameserversIPv6) && i < MAXNS; ++i) { 106 if (!kNameserversIPv6[i]) 107 continue; 108 IPAddressNumber ip; 109 ParseIPLiteralToNumber(kNameserversIPv6[i], &ip); 110 config->nameservers[i] = IPEndPoint(ip, NS_DEFAULTPORT - i); 111 } 112 #endif 113 } 114 115 TEST(DnsConfigServicePosixTest, ConvertResStateToDnsConfig) { 116 struct __res_state res; 117 DnsConfig config; 118 EXPECT_FALSE(config.IsValid()); 119 InitializeResState(&res); 120 ASSERT_EQ(internal::CONFIG_PARSE_POSIX_OK, 121 internal::ConvertResStateToDnsConfig(res, &config)); 122 CloseResState(&res); 123 EXPECT_TRUE(config.IsValid()); 124 125 DnsConfig expected_config; 126 EXPECT_FALSE(expected_config.EqualsIgnoreHosts(config)); 127 InitializeExpectedConfig(&expected_config); 128 EXPECT_TRUE(expected_config.EqualsIgnoreHosts(config)); 129 } 130 131 TEST(DnsConfigServicePosixTest, RejectEmptyNameserver) { 132 struct __res_state res = {}; 133 res.options = RES_INIT | RES_RECURSE | RES_DEFNAMES | RES_DNSRCH; 134 const char kDnsrch[] = "chromium.org"; 135 memcpy(res.defdname, kDnsrch, sizeof(kDnsrch)); 136 res.dnsrch[0] = res.defdname; 137 138 struct sockaddr_in sa = {}; 139 sa.sin_family = AF_INET; 140 sa.sin_port = base::HostToNet16(NS_DEFAULTPORT); 141 sa.sin_addr.s_addr = INADDR_ANY; 142 res.nsaddr_list[0] = sa; 143 sa.sin_addr.s_addr = 0xCAFE1337; 144 res.nsaddr_list[1] = sa; 145 res.nscount = 2; 146 147 DnsConfig config; 148 EXPECT_EQ(internal::CONFIG_PARSE_POSIX_NULL_ADDRESS, 149 internal::ConvertResStateToDnsConfig(res, &config)); 150 151 sa.sin_addr.s_addr = 0xDEADBEEF; 152 res.nsaddr_list[0] = sa; 153 EXPECT_EQ(internal::CONFIG_PARSE_POSIX_OK, 154 internal::ConvertResStateToDnsConfig(res, &config)); 155 } 156 157 } // namespace 158 } // namespace net 159 160 #endif // !OS_ANDROID 161