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