xref: /aosp_15_r20/external/cronet/net/dns/dns_hosts.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2012 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 #ifndef NET_DNS_DNS_HOSTS_H_
6 #define NET_DNS_DNS_HOSTS_H_
7 
8 #include <stddef.h>
9 
10 #include <string>
11 #include <string_view>
12 #include <unordered_map>
13 #include <utility>
14 
15 #include "base/files/file_path.h"
16 #include "net/base/address_family.h"
17 #include "net/base/ip_address.h"
18 #include "net/base/net_export.h"
19 
20 namespace net {
21 
22 using DnsHostsKey = std::pair<std::string, AddressFamily>;
23 
24 struct DnsHostsKeyHash {
operatorDnsHostsKeyHash25   std::size_t operator()(const DnsHostsKey& key) const {
26     return std::hash<std::string_view>()(key.first) + key.second;
27   }
28 };
29 
30 // There are OS-specific variations in how commas in the hosts file behave.
31 enum ParseHostsCommaMode {
32   // Comma is treated as part of a hostname:
33   // "127.0.0.1 foo,bar" parses as "foo,bar" mapping to "127.0.0.1".
34   PARSE_HOSTS_COMMA_IS_TOKEN,
35 
36   // Comma is treated as a hostname separator:
37   // "127.0.0.1 foo,bar" parses as "foo" and "bar" both mapping to "127.0.0.1".
38   PARSE_HOSTS_COMMA_IS_WHITESPACE,
39 };
40 
41 // Parsed results of a Hosts file.
42 //
43 // Although Hosts files map IP address to a list of domain names, for name
44 // resolution the desired mapping direction is: domain name to IP address.
45 // When parsing Hosts, we apply the "first hit" rule as Windows and glibc do.
46 // With a Hosts file of:
47 // 300.300.300.300 localhost # bad ip
48 // 127.0.0.1 localhost
49 // 10.0.0.1 localhost
50 // The expected resolution of localhost is 127.0.0.1.
51 using DnsHosts = std::unordered_map<DnsHostsKey, IPAddress, DnsHostsKeyHash>;
52 
53 // Parses |contents| (as read from /etc/hosts or equivalent) and stores results
54 // in |dns_hosts|. Invalid lines are ignored (as in most implementations).
55 // Overrides the OS-specific default handling of commas, so unittests can test
56 // both modes.
57 void NET_EXPORT_PRIVATE ParseHostsWithCommaModeForTesting(
58     const std::string& contents,
59     DnsHosts* dns_hosts,
60     ParseHostsCommaMode comma_mode);
61 
62 // Parses |contents| (as read from /etc/hosts or equivalent) and stores results
63 // in |dns_hosts|. Invalid lines are ignored (as in most implementations).
64 void NET_EXPORT_PRIVATE ParseHosts(const std::string& contents,
65                                    DnsHosts* dns_hosts);
66 
67 // Test-injectable HOSTS parser.
68 class NET_EXPORT_PRIVATE DnsHostsParser {
69  public:
70   virtual ~DnsHostsParser();
71 
72   // Parses HOSTS and stores results in `dns_hosts`, with addresses in the order
73   // in which they were read. Invalid lines are ignored (as in most
74   // implementations).
75   virtual bool ParseHosts(DnsHosts* hosts) const = 0;
76 };
77 
78 // Implementation of `DnsHostsParser` that reads HOSTS from a given file.
79 class NET_EXPORT_PRIVATE DnsHostsFileParser : public DnsHostsParser {
80  public:
81   explicit DnsHostsFileParser(base::FilePath hosts_file_path);
82   ~DnsHostsFileParser() override;
83 
84   DnsHostsFileParser(const DnsHostsFileParser&) = delete;
85   DnsHostsFileParser& operator=(const DnsHostsFileParser&) = delete;
86 
87   // DnsHostsParser:
88   bool ParseHosts(DnsHosts* dns_hosts) const override;
89 
90  private:
91   const base::FilePath hosts_file_path_;
92 };
93 
94 }  // namespace net
95 
96 #endif  // NET_DNS_DNS_HOSTS_H_
97