1*6777b538SAndroid Build Coastguard Worker // Copyright 2021 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/nsswitch_reader.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <string>
8*6777b538SAndroid Build Coastguard Worker #include <string_view>
9*6777b538SAndroid Build Coastguard Worker #include <utility>
10*6777b538SAndroid Build Coastguard Worker #include <vector>
11*6777b538SAndroid Build Coastguard Worker
12*6777b538SAndroid Build Coastguard Worker #include "base/files/file_path.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/files/file_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/metrics/histogram_macros.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_split.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/strings/string_util.h"
19*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
20*6777b538SAndroid Build Coastguard Worker
21*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_POSIX)
22*6777b538SAndroid Build Coastguard Worker #include <netdb.h>
23*6777b538SAndroid Build Coastguard Worker #endif // defined (OS_POSIX)
24*6777b538SAndroid Build Coastguard Worker
25*6777b538SAndroid Build Coastguard Worker namespace net {
26*6777b538SAndroid Build Coastguard Worker
27*6777b538SAndroid Build Coastguard Worker namespace {
28*6777b538SAndroid Build Coastguard Worker
29*6777b538SAndroid Build Coastguard Worker #ifdef _PATH_NSSWITCH_CONF
30*6777b538SAndroid Build Coastguard Worker constexpr base::FilePath::CharType kNsswitchPath[] =
31*6777b538SAndroid Build Coastguard Worker FILE_PATH_LITERAL(_PATH_NSSWITCH_CONF);
32*6777b538SAndroid Build Coastguard Worker #else
33*6777b538SAndroid Build Coastguard Worker constexpr base::FilePath::CharType kNsswitchPath[] =
34*6777b538SAndroid Build Coastguard Worker FILE_PATH_LITERAL("/etc/nsswitch.conf");
35*6777b538SAndroid Build Coastguard Worker #endif
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker // Choose 1 MiB as the largest handled filesize. Arbitrarily chosen as seeming
38*6777b538SAndroid Build Coastguard Worker // large enough to handle any reasonable file contents and similar to the size
39*6777b538SAndroid Build Coastguard Worker // limit for HOSTS files (32 MiB).
40*6777b538SAndroid Build Coastguard Worker constexpr size_t kMaxFileSize = 1024 * 1024;
41*6777b538SAndroid Build Coastguard Worker
ReadNsswitch()42*6777b538SAndroid Build Coastguard Worker std::string ReadNsswitch() {
43*6777b538SAndroid Build Coastguard Worker std::string file;
44*6777b538SAndroid Build Coastguard Worker bool result = base::ReadFileToStringWithMaxSize(base::FilePath(kNsswitchPath),
45*6777b538SAndroid Build Coastguard Worker &file, kMaxFileSize);
46*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_BOOLEAN("Net.DNS.DnsConfig.Nsswitch.Read",
47*6777b538SAndroid Build Coastguard Worker result || file.size() == kMaxFileSize);
48*6777b538SAndroid Build Coastguard Worker UMA_HISTOGRAM_BOOLEAN("Net.DNS.DnsConfig.Nsswitch.TooLarge",
49*6777b538SAndroid Build Coastguard Worker !result && file.size() == kMaxFileSize);
50*6777b538SAndroid Build Coastguard Worker
51*6777b538SAndroid Build Coastguard Worker if (result)
52*6777b538SAndroid Build Coastguard Worker return file;
53*6777b538SAndroid Build Coastguard Worker
54*6777b538SAndroid Build Coastguard Worker return "";
55*6777b538SAndroid Build Coastguard Worker }
56*6777b538SAndroid Build Coastguard Worker
SkipRestOfLine(std::string_view text)57*6777b538SAndroid Build Coastguard Worker std::string_view SkipRestOfLine(std::string_view text) {
58*6777b538SAndroid Build Coastguard Worker std::string_view::size_type line_end = text.find('\n');
59*6777b538SAndroid Build Coastguard Worker if (line_end == std::string_view::npos) {
60*6777b538SAndroid Build Coastguard Worker return "";
61*6777b538SAndroid Build Coastguard Worker }
62*6777b538SAndroid Build Coastguard Worker return text.substr(line_end);
63*6777b538SAndroid Build Coastguard Worker }
64*6777b538SAndroid Build Coastguard Worker
65*6777b538SAndroid Build Coastguard Worker // In case of multiple entries for `database_name`, finds only the first.
FindDatabase(std::string_view text,std::string_view database_name)66*6777b538SAndroid Build Coastguard Worker std::string_view FindDatabase(std::string_view text,
67*6777b538SAndroid Build Coastguard Worker std::string_view database_name) {
68*6777b538SAndroid Build Coastguard Worker DCHECK(!text.empty());
69*6777b538SAndroid Build Coastguard Worker DCHECK(!database_name.empty());
70*6777b538SAndroid Build Coastguard Worker DCHECK(!database_name.starts_with("#"));
71*6777b538SAndroid Build Coastguard Worker DCHECK(!base::IsAsciiWhitespace(database_name.front()));
72*6777b538SAndroid Build Coastguard Worker DCHECK(database_name.ends_with(":"));
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker while (!text.empty()) {
75*6777b538SAndroid Build Coastguard Worker text = base::TrimWhitespaceASCII(text, base::TrimPositions::TRIM_LEADING);
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker if (base::StartsWith(text, database_name,
78*6777b538SAndroid Build Coastguard Worker base::CompareCase::INSENSITIVE_ASCII)) {
79*6777b538SAndroid Build Coastguard Worker DCHECK(!text.starts_with("#"));
80*6777b538SAndroid Build Coastguard Worker
81*6777b538SAndroid Build Coastguard Worker text = text.substr(database_name.size());
82*6777b538SAndroid Build Coastguard Worker std::string_view::size_type line_end = text.find('\n');
83*6777b538SAndroid Build Coastguard Worker if (line_end != std::string_view::npos) {
84*6777b538SAndroid Build Coastguard Worker text = text.substr(0, line_end);
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker
87*6777b538SAndroid Build Coastguard Worker return base::TrimWhitespaceASCII(text, base::TrimPositions::TRIM_ALL);
88*6777b538SAndroid Build Coastguard Worker }
89*6777b538SAndroid Build Coastguard Worker
90*6777b538SAndroid Build Coastguard Worker text = SkipRestOfLine(text);
91*6777b538SAndroid Build Coastguard Worker }
92*6777b538SAndroid Build Coastguard Worker
93*6777b538SAndroid Build Coastguard Worker return "";
94*6777b538SAndroid Build Coastguard Worker }
95*6777b538SAndroid Build Coastguard Worker
TokenizeAction(std::string_view action_column)96*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceAction TokenizeAction(std::string_view action_column) {
97*6777b538SAndroid Build Coastguard Worker DCHECK(!action_column.empty());
98*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(action_column.find(']'), std::string_view::npos);
99*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(action_column.find_first_of(base::kWhitespaceASCII),
100*6777b538SAndroid Build Coastguard Worker std::string_view::npos);
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceAction result = {/*negated=*/false,
103*6777b538SAndroid Build Coastguard Worker NsswitchReader::Status::kUnknown,
104*6777b538SAndroid Build Coastguard Worker NsswitchReader::Action::kUnknown};
105*6777b538SAndroid Build Coastguard Worker
106*6777b538SAndroid Build Coastguard Worker std::vector<std::string_view> split = base::SplitStringPiece(
107*6777b538SAndroid Build Coastguard Worker action_column, "=", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
108*6777b538SAndroid Build Coastguard Worker if (split.size() != 2)
109*6777b538SAndroid Build Coastguard Worker return result;
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker if (split[0].size() >= 2 && split[0].front() == '!') {
112*6777b538SAndroid Build Coastguard Worker result.negated = true;
113*6777b538SAndroid Build Coastguard Worker split[0] = split[0].substr(1);
114*6777b538SAndroid Build Coastguard Worker }
115*6777b538SAndroid Build Coastguard Worker
116*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(split[0], "SUCCESS")) {
117*6777b538SAndroid Build Coastguard Worker result.status = NsswitchReader::Status::kSuccess;
118*6777b538SAndroid Build Coastguard Worker } else if (base::EqualsCaseInsensitiveASCII(split[0], "NOTFOUND")) {
119*6777b538SAndroid Build Coastguard Worker result.status = NsswitchReader::Status::kNotFound;
120*6777b538SAndroid Build Coastguard Worker } else if (base::EqualsCaseInsensitiveASCII(split[0], "UNAVAIL")) {
121*6777b538SAndroid Build Coastguard Worker result.status = NsswitchReader::Status::kUnavailable;
122*6777b538SAndroid Build Coastguard Worker } else if (base::EqualsCaseInsensitiveASCII(split[0], "TRYAGAIN")) {
123*6777b538SAndroid Build Coastguard Worker result.status = NsswitchReader::Status::kTryAgain;
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker
126*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(split[1], "RETURN")) {
127*6777b538SAndroid Build Coastguard Worker result.action = NsswitchReader::Action::kReturn;
128*6777b538SAndroid Build Coastguard Worker } else if (base::EqualsCaseInsensitiveASCII(split[1], "CONTINUE")) {
129*6777b538SAndroid Build Coastguard Worker result.action = NsswitchReader::Action::kContinue;
130*6777b538SAndroid Build Coastguard Worker } else if (base::EqualsCaseInsensitiveASCII(split[1], "MERGE")) {
131*6777b538SAndroid Build Coastguard Worker result.action = NsswitchReader::Action::kMerge;
132*6777b538SAndroid Build Coastguard Worker }
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker return result;
135*6777b538SAndroid Build Coastguard Worker }
136*6777b538SAndroid Build Coastguard Worker
TokenizeActions(std::string_view actions)137*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceAction> TokenizeActions(
138*6777b538SAndroid Build Coastguard Worker std::string_view actions) {
139*6777b538SAndroid Build Coastguard Worker DCHECK(!actions.empty());
140*6777b538SAndroid Build Coastguard Worker DCHECK_NE(actions.front(), '[');
141*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(actions.find(']'), std::string_view::npos);
142*6777b538SAndroid Build Coastguard Worker DCHECK(!base::IsAsciiWhitespace(actions.front()));
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceAction> result;
145*6777b538SAndroid Build Coastguard Worker
146*6777b538SAndroid Build Coastguard Worker for (const auto& action_column : base::SplitStringPiece(
147*6777b538SAndroid Build Coastguard Worker actions, base::kWhitespaceASCII, base::KEEP_WHITESPACE,
148*6777b538SAndroid Build Coastguard Worker base::SPLIT_WANT_NONEMPTY)) {
149*6777b538SAndroid Build Coastguard Worker DCHECK(!action_column.empty());
150*6777b538SAndroid Build Coastguard Worker result.push_back(TokenizeAction(action_column));
151*6777b538SAndroid Build Coastguard Worker }
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker return result;
154*6777b538SAndroid Build Coastguard Worker }
155*6777b538SAndroid Build Coastguard Worker
TokenizeService(std::string_view service_column)156*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification TokenizeService(
157*6777b538SAndroid Build Coastguard Worker std::string_view service_column) {
158*6777b538SAndroid Build Coastguard Worker DCHECK(!service_column.empty());
159*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(service_column.find_first_of(base::kWhitespaceASCII),
160*6777b538SAndroid Build Coastguard Worker std::string_view::npos);
161*6777b538SAndroid Build Coastguard Worker DCHECK_NE(service_column.front(), '[');
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "files")) {
164*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
165*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kFiles);
166*6777b538SAndroid Build Coastguard Worker }
167*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "dns")) {
168*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(NsswitchReader::Service::kDns);
169*6777b538SAndroid Build Coastguard Worker }
170*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "mdns")) {
171*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(NsswitchReader::Service::kMdns);
172*6777b538SAndroid Build Coastguard Worker }
173*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "mdns4")) {
174*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
175*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kMdns4);
176*6777b538SAndroid Build Coastguard Worker }
177*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "mdns6")) {
178*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
179*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kMdns6);
180*6777b538SAndroid Build Coastguard Worker }
181*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "mdns_minimal")) {
182*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
183*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kMdnsMinimal);
184*6777b538SAndroid Build Coastguard Worker }
185*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "mdns4_minimal")) {
186*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
187*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kMdns4Minimal);
188*6777b538SAndroid Build Coastguard Worker }
189*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "mdns6_minimal")) {
190*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
191*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kMdns6Minimal);
192*6777b538SAndroid Build Coastguard Worker }
193*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "myhostname")) {
194*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
195*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kMyHostname);
196*6777b538SAndroid Build Coastguard Worker }
197*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "resolve")) {
198*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
199*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kResolve);
200*6777b538SAndroid Build Coastguard Worker }
201*6777b538SAndroid Build Coastguard Worker if (base::EqualsCaseInsensitiveASCII(service_column, "nis")) {
202*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(NsswitchReader::Service::kNis);
203*6777b538SAndroid Build Coastguard Worker }
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker return NsswitchReader::ServiceSpecification(
206*6777b538SAndroid Build Coastguard Worker NsswitchReader::Service::kUnknown);
207*6777b538SAndroid Build Coastguard Worker }
208*6777b538SAndroid Build Coastguard Worker
209*6777b538SAndroid Build Coastguard Worker // Returns the actions string without brackets. `out_num_bytes` returns number
210*6777b538SAndroid Build Coastguard Worker // of bytes in the actions including brackets and trailing whitespace.
GetActionsStringAndRemoveBrackets(std::string_view database,size_t & out_num_bytes)211*6777b538SAndroid Build Coastguard Worker std::string_view GetActionsStringAndRemoveBrackets(std::string_view database,
212*6777b538SAndroid Build Coastguard Worker size_t& out_num_bytes) {
213*6777b538SAndroid Build Coastguard Worker DCHECK(!database.empty());
214*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(database.front(), '[');
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker size_t action_end = database.find(']');
217*6777b538SAndroid Build Coastguard Worker
218*6777b538SAndroid Build Coastguard Worker std::string_view actions;
219*6777b538SAndroid Build Coastguard Worker if (action_end == std::string_view::npos) {
220*6777b538SAndroid Build Coastguard Worker actions = database.substr(1);
221*6777b538SAndroid Build Coastguard Worker out_num_bytes = database.size();
222*6777b538SAndroid Build Coastguard Worker } else {
223*6777b538SAndroid Build Coastguard Worker actions = database.substr(1, action_end - 1);
224*6777b538SAndroid Build Coastguard Worker out_num_bytes = action_end;
225*6777b538SAndroid Build Coastguard Worker }
226*6777b538SAndroid Build Coastguard Worker
227*6777b538SAndroid Build Coastguard Worker // Ignore repeated '[' at start of `actions`.
228*6777b538SAndroid Build Coastguard Worker actions =
229*6777b538SAndroid Build Coastguard Worker base::TrimWhitespaceASCII(actions, base::TrimPositions::TRIM_LEADING);
230*6777b538SAndroid Build Coastguard Worker while (!actions.empty() && actions.front() == '[') {
231*6777b538SAndroid Build Coastguard Worker actions = base::TrimWhitespaceASCII(actions.substr(1),
232*6777b538SAndroid Build Coastguard Worker base::TrimPositions::TRIM_LEADING);
233*6777b538SAndroid Build Coastguard Worker }
234*6777b538SAndroid Build Coastguard Worker
235*6777b538SAndroid Build Coastguard Worker // Include any trailing ']' and whitespace in `out_num_bytes`.
236*6777b538SAndroid Build Coastguard Worker while (out_num_bytes < database.size() &&
237*6777b538SAndroid Build Coastguard Worker (database[out_num_bytes] == ']' ||
238*6777b538SAndroid Build Coastguard Worker base::IsAsciiWhitespace(database[out_num_bytes]))) {
239*6777b538SAndroid Build Coastguard Worker ++out_num_bytes;
240*6777b538SAndroid Build Coastguard Worker }
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Worker return actions;
243*6777b538SAndroid Build Coastguard Worker }
244*6777b538SAndroid Build Coastguard Worker
TokenizeDatabase(std::string_view database)245*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceSpecification> TokenizeDatabase(
246*6777b538SAndroid Build Coastguard Worker std::string_view database) {
247*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceSpecification> tokenized;
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker while (!database.empty()) {
250*6777b538SAndroid Build Coastguard Worker DCHECK(!base::IsAsciiWhitespace(database.front()));
251*6777b538SAndroid Build Coastguard Worker
252*6777b538SAndroid Build Coastguard Worker // Note: Assuming comments are not recognized mid-action or mid-service.
253*6777b538SAndroid Build Coastguard Worker if (database.front() == '#') {
254*6777b538SAndroid Build Coastguard Worker // Once a comment is hit, the rest of the database is comment.
255*6777b538SAndroid Build Coastguard Worker return tokenized;
256*6777b538SAndroid Build Coastguard Worker }
257*6777b538SAndroid Build Coastguard Worker
258*6777b538SAndroid Build Coastguard Worker if (database.front() == '[') {
259*6777b538SAndroid Build Coastguard Worker // Actions are expected to come after a service.
260*6777b538SAndroid Build Coastguard Worker if (tokenized.empty()) {
261*6777b538SAndroid Build Coastguard Worker tokenized.emplace_back(NsswitchReader::Service::kUnknown);
262*6777b538SAndroid Build Coastguard Worker }
263*6777b538SAndroid Build Coastguard Worker
264*6777b538SAndroid Build Coastguard Worker size_t num_actions_bytes = 0;
265*6777b538SAndroid Build Coastguard Worker std::string_view actions =
266*6777b538SAndroid Build Coastguard Worker GetActionsStringAndRemoveBrackets(database, num_actions_bytes);
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker if (num_actions_bytes == database.size()) {
269*6777b538SAndroid Build Coastguard Worker database = "";
270*6777b538SAndroid Build Coastguard Worker } else {
271*6777b538SAndroid Build Coastguard Worker database = database.substr(num_actions_bytes);
272*6777b538SAndroid Build Coastguard Worker }
273*6777b538SAndroid Build Coastguard Worker
274*6777b538SAndroid Build Coastguard Worker if (!actions.empty()) {
275*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceAction> tokenized_actions =
276*6777b538SAndroid Build Coastguard Worker TokenizeActions(actions);
277*6777b538SAndroid Build Coastguard Worker tokenized.back().actions.insert(tokenized.back().actions.end(),
278*6777b538SAndroid Build Coastguard Worker tokenized_actions.begin(),
279*6777b538SAndroid Build Coastguard Worker tokenized_actions.end());
280*6777b538SAndroid Build Coastguard Worker }
281*6777b538SAndroid Build Coastguard Worker } else {
282*6777b538SAndroid Build Coastguard Worker size_t column_end = database.find_first_of(base::kWhitespaceASCII);
283*6777b538SAndroid Build Coastguard Worker
284*6777b538SAndroid Build Coastguard Worker std::string_view service_column;
285*6777b538SAndroid Build Coastguard Worker if (column_end == std::string_view::npos) {
286*6777b538SAndroid Build Coastguard Worker service_column = database;
287*6777b538SAndroid Build Coastguard Worker database = "";
288*6777b538SAndroid Build Coastguard Worker } else {
289*6777b538SAndroid Build Coastguard Worker service_column = database.substr(0, column_end);
290*6777b538SAndroid Build Coastguard Worker database = database.substr(column_end);
291*6777b538SAndroid Build Coastguard Worker }
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker tokenized.push_back(TokenizeService(service_column));
294*6777b538SAndroid Build Coastguard Worker }
295*6777b538SAndroid Build Coastguard Worker
296*6777b538SAndroid Build Coastguard Worker database =
297*6777b538SAndroid Build Coastguard Worker base::TrimWhitespaceASCII(database, base::TrimPositions::TRIM_LEADING);
298*6777b538SAndroid Build Coastguard Worker }
299*6777b538SAndroid Build Coastguard Worker
300*6777b538SAndroid Build Coastguard Worker return tokenized;
301*6777b538SAndroid Build Coastguard Worker }
302*6777b538SAndroid Build Coastguard Worker
GetDefaultHosts()303*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceSpecification> GetDefaultHosts() {
304*6777b538SAndroid Build Coastguard Worker return {NsswitchReader::ServiceSpecification(NsswitchReader::Service::kFiles),
305*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification(NsswitchReader::Service::kDns)};
306*6777b538SAndroid Build Coastguard Worker }
307*6777b538SAndroid Build Coastguard Worker
308*6777b538SAndroid Build Coastguard Worker } // namespace
309*6777b538SAndroid Build Coastguard Worker
ServiceSpecification(Service service,std::vector<ServiceAction> actions)310*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification::ServiceSpecification(
311*6777b538SAndroid Build Coastguard Worker Service service,
312*6777b538SAndroid Build Coastguard Worker std::vector<ServiceAction> actions)
313*6777b538SAndroid Build Coastguard Worker : service(service), actions(std::move(actions)) {}
314*6777b538SAndroid Build Coastguard Worker
315*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification::~ServiceSpecification() = default;
316*6777b538SAndroid Build Coastguard Worker
317*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification::ServiceSpecification(
318*6777b538SAndroid Build Coastguard Worker const ServiceSpecification&) = default;
319*6777b538SAndroid Build Coastguard Worker
320*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification&
321*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification::operator=(const ServiceSpecification&) =
322*6777b538SAndroid Build Coastguard Worker default;
323*6777b538SAndroid Build Coastguard Worker
324*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification::ServiceSpecification(
325*6777b538SAndroid Build Coastguard Worker ServiceSpecification&&) = default;
326*6777b538SAndroid Build Coastguard Worker
327*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification&
328*6777b538SAndroid Build Coastguard Worker NsswitchReader::ServiceSpecification::operator=(ServiceSpecification&&) =
329*6777b538SAndroid Build Coastguard Worker default;
330*6777b538SAndroid Build Coastguard Worker
NsswitchReader()331*6777b538SAndroid Build Coastguard Worker NsswitchReader::NsswitchReader()
332*6777b538SAndroid Build Coastguard Worker : file_read_call_(base::BindRepeating(&ReadNsswitch)) {}
333*6777b538SAndroid Build Coastguard Worker
334*6777b538SAndroid Build Coastguard Worker NsswitchReader::~NsswitchReader() = default;
335*6777b538SAndroid Build Coastguard Worker
336*6777b538SAndroid Build Coastguard Worker std::vector<NsswitchReader::ServiceSpecification>
ReadAndParseHosts()337*6777b538SAndroid Build Coastguard Worker NsswitchReader::ReadAndParseHosts() {
338*6777b538SAndroid Build Coastguard Worker std::string file = file_read_call_.Run();
339*6777b538SAndroid Build Coastguard Worker if (file.empty())
340*6777b538SAndroid Build Coastguard Worker return GetDefaultHosts();
341*6777b538SAndroid Build Coastguard Worker
342*6777b538SAndroid Build Coastguard Worker std::string_view hosts = FindDatabase(file, "hosts:");
343*6777b538SAndroid Build Coastguard Worker if (hosts.empty())
344*6777b538SAndroid Build Coastguard Worker return GetDefaultHosts();
345*6777b538SAndroid Build Coastguard Worker
346*6777b538SAndroid Build Coastguard Worker return TokenizeDatabase(hosts);
347*6777b538SAndroid Build Coastguard Worker }
348*6777b538SAndroid Build Coastguard Worker
349*6777b538SAndroid Build Coastguard Worker } // namespace net
350