• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2011 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/dns/dns_util.h"
6 
7 #include <errno.h>
8 #include <limits.h>
9 #include <stdint.h>
10 
11 #include <cstring>
12 #include <string>
13 #include <unordered_map>
14 #include <vector>
15 
16 #include "base/big_endian.h"
17 #include "base/check_op.h"
18 #include "base/containers/contains.h"
19 #include "base/feature_list.h"
20 #include "base/metrics/field_trial.h"
21 #include "base/metrics/histogram_macros.h"
22 #include "base/ranges/algorithm.h"
23 #include "base/strings/string_number_conversions.h"
24 #include "base/strings/string_piece.h"
25 #include "base/strings/string_split.h"
26 #include "build/build_config.h"
27 #include "net/dns/public/dns_protocol.h"
28 #include "net/dns/public/doh_provider_entry.h"
29 #include "net/dns/public/util.h"
30 #include "net/third_party/uri_template/uri_template.h"
31 
32 #if BUILDFLAG(IS_POSIX)
33 #include <net/if.h>
34 #include <netinet/in.h>
35 #if !BUILDFLAG(IS_ANDROID)
36 #include <ifaddrs.h>
37 #endif  // !BUILDFLAG(IS_ANDROID)
38 #endif  // BUILDFLAG(IS_POSIX)
39 
40 #if BUILDFLAG(IS_ANDROID)
41 #include "net/android/network_library.h"
42 #endif
43 
44 namespace net {
45 namespace {
46 
GetDohProviderEntriesFromNameservers(const std::vector<IPEndPoint> & dns_servers)47 DohProviderEntry::List GetDohProviderEntriesFromNameservers(
48     const std::vector<IPEndPoint>& dns_servers) {
49   const DohProviderEntry::List& providers = DohProviderEntry::GetList();
50   DohProviderEntry::List entries;
51 
52   for (const auto& server : dns_servers) {
53     for (const auto* entry : providers) {
54       // DoH servers should only be added once.
55       // Note: Check whether the provider is enabled *after* we've determined
56       // that the IP addresses match so that if we are doing experimentation via
57       // Finch, the experiment only includes possible users of the
58       // corresponding DoH provider (since the client will be included in the
59       // experiment if the provider feature flag is checked).
60       if (base::Contains(entry->ip_addresses, server.address()) &&
61           base::FeatureList::IsEnabled(entry->feature) &&
62           !base::Contains(entries, entry)) {
63         entries.push_back(entry);
64       }
65     }
66   }
67   return entries;
68 }
69 
70 }  // namespace
71 
GetURLFromTemplateWithoutParameters(const string & server_template)72 std::string GetURLFromTemplateWithoutParameters(const string& server_template) {
73   std::string url_string;
74   std::unordered_map<string, string> parameters;
75   uri_template::Expand(server_template, parameters, &url_string);
76   return url_string;
77 }
78 
79 namespace {
80 
GetTimeDeltaForConnectionTypeFromFieldTrial(const char * field_trial,NetworkChangeNotifier::ConnectionType type,base::TimeDelta * out)81 bool GetTimeDeltaForConnectionTypeFromFieldTrial(
82     const char* field_trial,
83     NetworkChangeNotifier::ConnectionType type,
84     base::TimeDelta* out) {
85   std::string group = base::FieldTrialList::FindFullName(field_trial);
86   if (group.empty())
87     return false;
88   std::vector<base::StringPiece> group_parts = base::SplitStringPiece(
89       group, ":", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
90   if (type < 0)
91     return false;
92   size_t type_size = static_cast<size_t>(type);
93   if (type_size >= group_parts.size())
94     return false;
95   int64_t ms;
96   if (!base::StringToInt64(group_parts[type_size], &ms))
97     return false;
98   *out = base::Milliseconds(ms);
99   return true;
100 }
101 
102 }  // namespace
103 
GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(const char * field_trial,base::TimeDelta default_delta,NetworkChangeNotifier::ConnectionType type)104 base::TimeDelta GetTimeDeltaForConnectionTypeFromFieldTrialOrDefault(
105     const char* field_trial,
106     base::TimeDelta default_delta,
107     NetworkChangeNotifier::ConnectionType type) {
108   base::TimeDelta out;
109   if (!GetTimeDeltaForConnectionTypeFromFieldTrial(field_trial, type, &out))
110     out = default_delta;
111   return out;
112 }
113 
CreateNamePointer(uint16_t offset)114 std::string CreateNamePointer(uint16_t offset) {
115   DCHECK_EQ(offset & ~dns_protocol::kOffsetMask, 0);
116   char buf[2];
117   base::WriteBigEndian(buf, offset);
118   buf[0] |= dns_protocol::kLabelPointer;
119   return std::string(buf, sizeof(buf));
120 }
121 
DnsQueryTypeToQtype(DnsQueryType dns_query_type)122 uint16_t DnsQueryTypeToQtype(DnsQueryType dns_query_type) {
123   switch (dns_query_type) {
124     case DnsQueryType::UNSPECIFIED:
125       NOTREACHED();
126       return 0;
127     case DnsQueryType::A:
128       return dns_protocol::kTypeA;
129     case DnsQueryType::AAAA:
130       return dns_protocol::kTypeAAAA;
131     case DnsQueryType::TXT:
132       return dns_protocol::kTypeTXT;
133     case DnsQueryType::PTR:
134       return dns_protocol::kTypePTR;
135     case DnsQueryType::SRV:
136       return dns_protocol::kTypeSRV;
137     case DnsQueryType::HTTPS:
138       return dns_protocol::kTypeHttps;
139   }
140 }
141 
AddressFamilyToDnsQueryType(AddressFamily address_family)142 DnsQueryType AddressFamilyToDnsQueryType(AddressFamily address_family) {
143   switch (address_family) {
144     case ADDRESS_FAMILY_UNSPECIFIED:
145       return DnsQueryType::UNSPECIFIED;
146     case ADDRESS_FAMILY_IPV4:
147       return DnsQueryType::A;
148     case ADDRESS_FAMILY_IPV6:
149       return DnsQueryType::AAAA;
150     default:
151       NOTREACHED();
152       return DnsQueryType::UNSPECIFIED;
153   }
154 }
155 
GetDohUpgradeServersFromDotHostname(const std::string & dot_server)156 std::vector<DnsOverHttpsServerConfig> GetDohUpgradeServersFromDotHostname(
157     const std::string& dot_server) {
158   std::vector<DnsOverHttpsServerConfig> doh_servers;
159 
160   if (dot_server.empty())
161     return doh_servers;
162 
163   for (const auto* entry : DohProviderEntry::GetList()) {
164     // Note: Check whether the provider is enabled *after* we've determined that
165     // the hostnames match so that if we are doing experimentation via Finch,
166     // the experiment only includes possible users of the corresponding DoH
167     // provider (since the client will be included in the experiment if the
168     // provider feature flag is checked).
169     if (base::Contains(entry->dns_over_tls_hostnames, dot_server) &&
170         base::FeatureList::IsEnabled(entry->feature)) {
171       doh_servers.push_back(entry->doh_server_config);
172     }
173   }
174   return doh_servers;
175 }
176 
GetDohUpgradeServersFromNameservers(const std::vector<IPEndPoint> & dns_servers)177 std::vector<DnsOverHttpsServerConfig> GetDohUpgradeServersFromNameservers(
178     const std::vector<IPEndPoint>& dns_servers) {
179   const auto entries = GetDohProviderEntriesFromNameservers(dns_servers);
180   std::vector<DnsOverHttpsServerConfig> doh_servers;
181   doh_servers.reserve(entries.size());
182   base::ranges::transform(entries, std::back_inserter(doh_servers),
183                           &DohProviderEntry::doh_server_config);
184   return doh_servers;
185 }
186 
GetDohProviderIdForHistogramFromServerConfig(const DnsOverHttpsServerConfig & doh_server)187 std::string GetDohProviderIdForHistogramFromServerConfig(
188     const DnsOverHttpsServerConfig& doh_server) {
189   const auto& entries = DohProviderEntry::GetList();
190   const auto it = base::ranges::find(entries, doh_server,
191                                      &DohProviderEntry::doh_server_config);
192   return it != entries.end() ? (*it)->provider : "Other";
193 }
194 
GetDohProviderIdForHistogramFromNameserver(const IPEndPoint & nameserver)195 std::string GetDohProviderIdForHistogramFromNameserver(
196     const IPEndPoint& nameserver) {
197   const auto entries = GetDohProviderEntriesFromNameservers({nameserver});
198   return entries.empty() ? "Other" : entries[0]->provider;
199 }
200 
SecureDnsModeToString(const SecureDnsMode secure_dns_mode)201 std::string SecureDnsModeToString(const SecureDnsMode secure_dns_mode) {
202   switch (secure_dns_mode) {
203     case SecureDnsMode::kOff:
204       return "Off";
205     case SecureDnsMode::kAutomatic:
206       return "Automatic";
207     case SecureDnsMode::kSecure:
208       return "Secure";
209   }
210 }
211 
212 }  // namespace net
213