summaryrefslogtreecommitdiffstats
path: root/net/dns/dns_hosts.cc
blob: bfd216cc5b15291f1c4cb783407ed50d5238d532 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/dns/dns_hosts.h"

#include "base/file_util.h"
#include "base/logging.h"
#include "base/string_tokenizer.h"
#include "base/string_util.h"

namespace net {

void ParseHosts(const std::string& contents, DnsHosts* dns_hosts) {
  CHECK(dns_hosts);
  DnsHosts& hosts = *dns_hosts;
  // Split into lines. Accept CR for Windows.
  StringTokenizer contents_lines(contents, "\n\r");
  while (contents_lines.GetNext()) {
    // Ignore comments after '#'.
    std::string line = contents_lines.token();
    StringTokenizer line_parts(line, "#");
    line_parts.set_options(StringTokenizer::RETURN_DELIMS);

    if (line_parts.GetNext() && !line_parts.token_is_delim()) {
      // Split and trim whitespace.
      std::string part = line_parts.token();
      StringTokenizer tokens(part, " \t");

      if (tokens.GetNext()) {
        IPAddressNumber ip;
        // TODO(szym): handle %iface notation on mac
        if (!ParseIPLiteralToNumber(tokens.token(), &ip))
          continue;  // Ignore malformed lines.
        AddressFamily fam = (ip.size() == 4) ? ADDRESS_FAMILY_IPV4 :
                                               ADDRESS_FAMILY_IPV6;
        while (tokens.GetNext()) {
          DnsHostsKey key(tokens.token(), fam);
          StringToLowerASCII(&(key.first));
          IPAddressNumber& mapped_ip = hosts[key];
          if (mapped_ip.empty())
            mapped_ip = ip;
          // else ignore this entry (first hit counts)
        }
      }
    }
  }
}

DnsHostsReader::DnsHostsReader(const FilePath& path,
                               const CallbackType& callback)
    : path_(path),
      callback_(callback),
      success_(false) {
  DCHECK(!callback.is_null());
}

DnsHostsReader::DnsHostsReader(const FilePath& path)
    : path_(path),
      success_(false) {
}

// Reads the contents of the file at |path| into |str| if the total length is
// less than |max_size|.
static bool ReadFile(const FilePath& path, int64 max_size, std::string* str) {
  int64 size;
  if (!file_util::GetFileSize(path, &size) || size > max_size)
    return false;
  return file_util::ReadFileToString(path, str);
}

void DnsHostsReader::DoWork() {
  success_ = false;
  dns_hosts_.clear();

  // Missing file indicates empty HOSTS.
  if (!file_util::PathExists(path_)) {
    success_ = true;
    return;
  }

  std::string contents;
  const int64 kMaxHostsSize = 1 << 16;
  if (ReadFile(path_, kMaxHostsSize, &contents)) {
    success_ = true;
    ParseHosts(contents, &dns_hosts_);
  }
}

void DnsHostsReader::OnWorkFinished() {
  DCHECK(!IsCancelled());
  if (success_)
    callback_.Run(dns_hosts_);
}

DnsHostsReader::~DnsHostsReader() {}

}  // namespace net