15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <errno.h>
8116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch#include <string.h>
9c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iterator>
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include <set>
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "build/build_config.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <iphlpapi.h>
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <winsock2.h>
205c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#include <ws2bth.h>
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma comment(lib, "iphlpapi.lib")
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <fcntl.h>
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <netdb.h>
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <netinet/in.h>
260529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch#include <unistd.h>
27a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if !defined(OS_NACL)
28a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <net/if.h>
29a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if !defined(OS_ANDROID)
30a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include <ifaddrs.h>
31a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif  // !defined(OS_NACL)
32a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif  // !defined(OS_ANDROID)
33a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif  // defined(OS_POSIX)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/string_escape.h"
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h"
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
395e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_number_conversions.h"
40c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "base/strings/string_piece.h"
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h"
425e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
435e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
44868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/sys_byteorder.h"
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h"
477dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
487dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_canon.h"
497dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_canon_ip.h"
507dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_parse.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/dns_util.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_module.h"
53a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
5403b57e008b61dfcb1fbad3aea950ae0e001748b0Torne (Richard Coles)#include "net/grit/net_resources.h"
55a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "net/http/http_content_disposition.h"
56a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch
57a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if defined(OS_ANDROID)
58a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#include "net/android/network_library.h"
59a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/winsock_init.h"
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The general list of blocked ports. Will be blocked unless a specific
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// protocol overrides it. (Ex: ftp can use ports 20 and 21)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kRestrictedPorts[] = {
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  1,    // tcpmux
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  7,    // echo
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  9,    // discard
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  11,   // systat
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  13,   // daytime
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  15,   // netstat
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  17,   // qotd
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  19,   // chargen
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  20,   // ftp data
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  21,   // ftp access
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  22,   // ssh
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  23,   // telnet
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  25,   // smtp
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  37,   // time
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  42,   // name
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  43,   // nicname
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  53,   // domain
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  77,   // priv-rjs
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  79,   // finger
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  87,   // ttylink
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  95,   // supdup
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  101,  // hostriame
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  102,  // iso-tsap
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  103,  // gppitnp
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  104,  // acr-nema
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  109,  // pop2
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  110,  // pop3
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  111,  // sunrpc
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  113,  // auth
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  115,  // sftp
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  117,  // uucp-path
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  119,  // nntp
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  123,  // NTP
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  135,  // loc-srv /epmap
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  139,  // netbios
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  143,  // imap2
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  179,  // BGP
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  389,  // ldap
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  465,  // smtp+ssl
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  512,  // print / exec
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  513,  // login
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  514,  // shell
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  515,  // printer
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  526,  // tempo
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  530,  // courier
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  531,  // chat
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  532,  // netnews
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  540,  // uucp
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  556,  // remotefs
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  563,  // nntp+ssl
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  587,  // stmp?
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  601,  // ??
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  636,  // ldap+ssl
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  993,  // ldap+ssl
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  995,  // pop3+ssl
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  2049, // nfs
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  3659, // apple-sasl / PasswordServer
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  4045, // lockd
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  6000, // X11
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  6665, // Alternate IRC [Apple addition]
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  6666, // Alternate IRC [Apple addition]
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  6667, // Standard IRC [Apple addition]
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  6668, // Alternate IRC [Apple addition]
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  6669, // Alternate IRC [Apple addition]
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  0xFFFF, // Used to block all invalid port numbers (see
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // third_party/WebKit/Source/platform/weborigin/KURL.cpp,
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // KURL::port())
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// FTP overrides the following restricted ports.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const int kAllowedFtpPorts[] = {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  21,   // ftp data
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  22,   // ssh
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IPNumberPrefixCheck(const IPAddressNumber& ip_number,
1473551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         const unsigned char* ip_prefix,
1483551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                         size_t prefix_length_in_bits) {
1493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // Compare all the bytes that fall entirely within the prefix.
1503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
1513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (int i = 0; i < num_entire_bytes_in_prefix; ++i) {
1523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (ip_number[i] != ip_prefix[i])
1533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
1543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // In case the prefix was not a multiple of 8, there will be 1 byte
1573551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // which is only partially masked.
1583551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  int remaining_bits = prefix_length_in_bits % 8;
1593551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (remaining_bits != 0) {
1603551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    unsigned char mask = 0xFF << (8 - remaining_bits);
1613551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    int i = num_entire_bytes_in_prefix;
1623551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if ((ip_number[i] & mask) != (ip_prefix[i] & mask))
1633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
1643551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
1653551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return true;
1663551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
1673551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static base::LazyInstance<std::multiset<int> >::Leaky
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_explicitly_allowed_ports = LAZY_INSTANCE_INITIALIZER;
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t GetCountOfExplicitlyAllowedPorts() {
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_explicitly_allowed_ports.Get().size();
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetSpecificHeader(const std::string& headers,
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const std::string& name) {
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We want to grab the Value from the "Key: Value" pairs in the headers,
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // which should look like this (no leading spaces, \n-separated) (we format
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // them this way in url_request_inet.cc):
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    HTTP/1.1 200 OK\n
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    ETag: "6d0b8-947-24f35ec0"\n
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    Content-Length: 2375\n
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    Content-Type: text/html; charset=UTF-8\n
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //    Last-Modified: Sun, 03 Sep 2006 04:34:43 GMT\n
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (headers.empty())
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string match('\n' + name + ':');
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string::const_iterator begin =
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::search(headers.begin(), headers.end(), match.begin(), match.end(),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)             base::CaseInsensitiveCompareASCII<char>());
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (begin == headers.end())
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return std::string();
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  begin += match.length();
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string ret;
202a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  base::TrimWhitespace(std::string(begin,
203a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   std::find(begin, headers.end(), '\n')),
204a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                       base::TRIM_ALL, &ret);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ret;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string CanonicalizeHost(const std::string& host,
2095c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                             url::CanonHostInfo* host_info) {
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try to canonicalize the host.
2115c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const url::Component raw_host_component(0, static_cast<int>(host.length()));
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string canon_host;
2135c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::StdStringCanonOutput canon_host_output(&canon_host);
2145c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::CanonicalizeHostVerbose(host.c_str(), raw_host_component,
2155c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                               &canon_host_output, host_info);
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_info->out_host.is_nonempty() &&
2185c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      host_info->family != url::CanonHostInfo::BROKEN) {
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Success!  Assert that there's no extra garbage.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canon_host_output.Complete();
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_EQ(host_info->out_host.len, static_cast<int>(canon_host.length()));
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Empty host, or canonicalization failed.  We'll return empty.
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    canon_host.clear();
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return canon_host;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
230c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)std::string GetDirectoryListingHeader(const base::string16& title) {
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static const base::StringPiece header(
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NetModule::GetResource(IDR_DIR_HEADER_HTML));
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This can be null in unit tests.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DLOG_IF(WARNING, header.empty()) <<
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "Missing resource: directory listing header";
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!header.empty())
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.assign(header.data(), header.size());
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.append("<script>start(");
2425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  base::EscapeJSONString(title, true, &result);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  result.append(");</script>\n");
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
248558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdochinline bool IsHostCharAlphanumeric(char c) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We can just check lowercase because uppercase characters have already been
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // normalized.
251558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9'));
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsCanonicalizedHostCompliant(const std::string& host,
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                  const std::string& desired_tld) {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host.empty())
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool in_component = false;
260558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  bool most_recent_component_started_alphanumeric = false;
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool last_char_was_underscore = false;
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (std::string::const_iterator i(host.begin()); i != host.end(); ++i) {
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char c = *i;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!in_component) {
266558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c);
267558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      if (!most_recent_component_started_alphanumeric && (c != '-'))
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      in_component = true;
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (c == '.') {
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (last_char_was_underscore)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          return false;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        in_component = false;
275558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      } else if (IsHostCharAlphanumeric(c) || (c == '-')) {
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_char_was_underscore = false;
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else if (c == '_') {
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        last_char_was_underscore = true;
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      } else {
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return false;
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
285558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch  return most_recent_component_started_alphanumeric ||
286558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch      (!desired_tld.empty() && IsHostCharAlphanumeric(desired_tld[0]));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 StripWWW(const base::string16& text) {
2905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const base::string16 www(base::ASCIIToUTF16("www."));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return StartsWith(text, www, true) ? text.substr(www.length()) : text;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
294c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 StripWWWFromHost(const GURL& url) {
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(url.is_valid());
2965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return StripWWW(base::ASCIIToUTF16(url.host()));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsPortAllowedByDefault(int port) {
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int array_size = arraysize(kRestrictedPorts);
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < array_size; i++) {
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kRestrictedPorts[i] == port) {
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsPortAllowedByFtp(int port) {
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int array_size = arraysize(kAllowedFtpPorts);
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = 0; i < array_size; i++) {
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (kAllowedFtpPorts[i] == port) {
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return true;
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Port not explicitly allowed by FTP, so return the default restrictions.
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IsPortAllowedByDefault(port);
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsPortAllowedByOverride(int port) {
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (g_explicitly_allowed_ports.Get().empty())
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return g_explicitly_allowed_ports.Get().count(port) > 0;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int SetNonBlocking(int fd) {
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  unsigned long no_block = 1;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ioctlsocket(fd, FIONBIO, &no_block);
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int flags = fcntl(fd, F_GETFL, 0);
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (-1 == flags)
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return flags;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return fcntl(fd, F_SETFL, flags | O_NONBLOCK);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseHostAndPort(std::string::const_iterator host_and_port_begin,
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string::const_iterator host_and_port_end,
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* host,
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int* port) {
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_and_port_begin >= host_and_port_end)
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  // When using url, we use char*.
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* auth_begin = &(*host_and_port_begin);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int auth_len = host_and_port_end - host_and_port_begin;
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component auth_component(0, auth_len);
3515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component username_component;
3525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component password_component;
3535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component hostname_component;
3545c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component port_component;
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3565c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::ParseAuthority(auth_begin, auth_component, &username_component,
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      &password_component, &hostname_component, &port_component);
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There shouldn't be a username/password.
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (username_component.is_valid() || password_component.is_valid())
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!hostname_component.is_nonempty())
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Failed parsing.
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int parsed_port_number = -1;
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (port_component.is_nonempty()) {
3685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    parsed_port_number = url::ParsePort(auth_begin, port_component);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // If parsing failed, port_number will be either PORT_INVALID or
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // PORT_UNSPECIFIED, both of which are negative.
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (parsed_port_number < 0)
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;  // Failed parsing the port number.
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (port_component.len == 0)
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;  // Reject inputs like "foo:"
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3791320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  unsigned char tmp_ipv6_addr[16];
3801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3811320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // If the hostname starts with a bracket, it is either an IPv6 literal or
3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  // invalid. If it is an IPv6 literal then strip the brackets.
3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  if (hostname_component.len > 0 &&
3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      auth_begin[hostname_component.begin] == '[') {
3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    if (auth_begin[hostname_component.end() - 1] == ']' &&
3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci        url::IPv6AddressToNumber(
3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci            auth_begin, hostname_component, tmp_ipv6_addr)) {
3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      // Strip the brackets.
3891320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      hostname_component.begin++;
3901320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      hostname_component.len -= 2;
3911320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    } else {
3921320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      return false;
3931320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci    }
3941320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  }
3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Pass results back to caller.
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  host->assign(auth_begin + hostname_component.begin, hostname_component.len);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *port = parsed_port_number;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;  // Success.
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseHostAndPort(const std::string& host_and_port,
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      std::string* host,
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                      int* port) {
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ParseHostAndPort(
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host_and_port.begin(), host_and_port.end(), host, port);
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetHostAndPort(const GURL& url) {
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For IPv6 literals, GURL::host() already includes the brackets so it is
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // safe to just append a colon.
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf("%s:%d", url.host().c_str(),
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            url.EffectiveIntPort());
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetHostAndOptionalPort(const GURL& url) {
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // For IPv6 literals, GURL::host() already includes the brackets
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // so it is safe to just append a colon.
4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (url.has_port())
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str());
4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.host();
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)bool IsHostnameNonUnique(const std::string& hostname) {
426a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
427a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  const std::string host_or_ip = hostname.find(':') != std::string::npos ?
428a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)      "[" + hostname + "]" : hostname;
4295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::CanonHostInfo host_info;
430a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info);
431a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
432a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // If canonicalization fails, then the input is truly malformed. However,
433a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // to avoid mis-reporting bad inputs as "non-unique", treat them as unique.
434a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  if (canonical_name.empty())
435a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)    return false;
436a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4373551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // If |hostname| is an IP address, check to see if it's in an IANA-reserved
4383551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  // range.
4393551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (host_info.IsIPAddress()) {
4403551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    IPAddressNumber host_addr;
4413551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin,
4423551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                host_info.out_host.len),
4433551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                &host_addr)) {
4443551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return false;
4453551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
4463551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    switch (host_info.family) {
4475c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case url::CanonHostInfo::IPV4:
4485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case url::CanonHostInfo::IPV6:
4493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return IsIPAddressReserved(host_addr);
4505c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case url::CanonHostInfo::NEUTRAL:
4515c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      case url::CanonHostInfo::BROKEN:
4523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)        return false;
4533551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    }
4543551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
455a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
456a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Check for a registry controlled portion of |hostname|, ignoring private
457a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // registries, as they already chain to ICANN-administered registries,
458a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // and explicitly ignoring unknown registries.
459a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  //
460a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // Note: This means that as new gTLDs are introduced on the Internet, they
461a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // will be treated as non-unique until the registry controlled domain list
462a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // is updated. However, because gTLDs are expected to provide significant
463a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // advance notice to deprecate older versions of this code, this an
464a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  // acceptable tradeoff.
465a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  return 0 == registry_controlled_domains::GetRegistryLength(
466a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  canonical_name,
467a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
468a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)                  registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
469a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
470a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
4713551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Don't compare IPv4 and IPv6 addresses (they have different range
4723551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// reservations). Keep separate reservation arrays for each IP type, and
4733551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// consolidate adjacent reserved ranges within a reservation array when
4743551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// possible.
4753551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// Sources for info:
4763551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
4773551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
4783551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// They're formatted here with the prefix as the last element. For example:
4793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)// 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10.
4803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)bool IsIPAddressReserved(const IPAddressNumber& host_addr) {
4813551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  static const unsigned char kReservedIPv4[][5] = {
4823551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0,0,0,0,8 }, { 10,0,0,0,8 }, { 100,64,0,0,10 }, { 127,0,0,0,8 },
4833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 169,254,0,0,16 }, { 172,16,0,0,12 }, { 192,0,2,0,24 },
4843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 192,88,99,0,24 }, { 192,168,0,0,16 }, { 198,18,0,0,15 },
4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 198,51,100,0,24 }, { 203,0,113,0,24 }, { 224,0,0,0,3 }
4863551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
4873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  static const unsigned char kReservedIPv6[][17] = {
4883551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8 },
4893551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
4903551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
4913551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3 },
4923551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xe0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 },
4933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xf0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 },
4943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xf8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 },
4953551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xfc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7 },
4963551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 },
4973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
4983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      { 0xfe,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
4993551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  };
5003551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  size_t array_size = 0;
5013551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  const unsigned char* array = NULL;
5023551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  switch (host_addr.size()) {
5033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case kIPv4AddressSize:
5043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      array_size = arraysize(kReservedIPv4);
5053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      array = kReservedIPv4[0];
5063551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
5073551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    case kIPv6AddressSize:
5083551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      array_size = arraysize(kReservedIPv6);
5093551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      array = kReservedIPv6[0];
5103551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      break;
5113551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5123551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  if (!array)
5133551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    return false;
5143551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  size_t width = host_addr.size() + 1;
5153551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  for (size_t i = 0; i < array_size; ++i, array += width) {
5163551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)    if (IPNumberPrefixCheck(host_addr, array, array[width-1]))
5173551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      return true;
5183551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  }
5193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return false;
5203551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)}
5213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)
522116680a4aac90f2aa7413d9095a592090648e557Ben MurdochSockaddrStorage::SockaddrStorage(const SockaddrStorage& other)
523116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    : addr_len(other.addr_len),
524116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) {
525116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(addr, other.addr, addr_len);
526116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
527116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
528116680a4aac90f2aa7413d9095a592090648e557Ben Murdochvoid SockaddrStorage::operator=(const SockaddrStorage& other) {
529116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  addr_len = other.addr_len;
530116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // addr is already set to &this->addr_storage by default ctor.
531116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  memcpy(addr, other.addr, addr_len);
532116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch}
533116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts the address and port portions of a sockaddr.
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr,
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              socklen_t sock_addr_len,
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              const uint8** address,
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              size_t* address_len,
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              uint16* port) {
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sock_addr->sa_family == AF_INET) {
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in)))
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct sockaddr_in* addr =
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const struct sockaddr_in*>(sock_addr);
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *address = reinterpret_cast<const uint8*>(&addr->sin_addr);
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *address_len = kIPv4AddressSize;
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (port)
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *port = base::NetToHost16(addr->sin_port);
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (sock_addr->sa_family == AF_INET6) {
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in6)))
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct sockaddr_in6* addr =
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const struct sockaddr_in6*>(sock_addr);
5575c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *address = reinterpret_cast<const uint8*>(&addr->sin6_addr);
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *address_len = kIPv6AddressSize;
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (port)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *port = base::NetToHost16(addr->sin6_port);
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5645c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#if defined(OS_WIN)
5655c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (sock_addr->sa_family == AF_BTH) {
5665c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH)))
5675c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      return false;
5685c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    const SOCKADDR_BTH* addr =
5695c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu        reinterpret_cast<const SOCKADDR_BTH*>(sock_addr);
5705c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *address = reinterpret_cast<const uint8*>(&addr->btAddr);
5715c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    *address_len = kBluetoothAddressSize;
5725c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    if (port)
5735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu      *port = addr->port;
5745c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return true;
5755c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  }
5765c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu#endif
5775c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;  // Unrecognized |sa_family|.
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IPAddressToString(const uint8* address,
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              size_t address_len) {
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string str;
5845c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::StdStringCanonOutput output(&str);
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address_len == kIPv4AddressSize) {
5875c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    url::AppendIPv4Address(address, &output);
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (address_len == kIPv6AddressSize) {
5895c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    url::AppendIPv6Address(address, &output);
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(false) << "Invalid IP address with length: " << address_len;
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  output.Complete();
5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return str;
5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IPAddressToStringWithPort(const uint8* address,
5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      size_t address_len,
6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint16 port) {
6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string address_str = IPAddressToString(address, address_len);
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address_len == kIPv6AddressSize) {
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Need to bracket IPv6 addresses since they contain colons.
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return base::StringPrintf("[%s]:%d", address_str.c_str(), port);
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::StringPrintf("%s:%d", address_str.c_str(), port);
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NetAddressToString(const struct sockaddr* sa,
6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                               socklen_t sock_addr_len) {
6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* address;
6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t address_len;
6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetIPAddressFromSockAddr(sa, sock_addr_len, &address,
6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &address_len, NULL)) {
6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
617c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::string();
6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPAddressToString(address, address_len);
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string NetAddressToStringWithPort(const struct sockaddr* sa,
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       socklen_t sock_addr_len) {
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint8* address;
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t address_len;
6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  uint16 port;
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!GetIPAddressFromSockAddr(sa, sock_addr_len, &address,
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                &address_len, &port)) {
6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
630c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return std::string();
6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPAddressToStringWithPort(address, address_len, port);
6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IPAddressToString(const IPAddressNumber& addr) {
6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPAddressToString(&addr.front(), addr.size());
6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string IPAddressToStringWithPort(const IPAddressNumber& addr,
6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                      uint16 port) {
6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPAddressToStringWithPort(&addr.front(), addr.size(), port);
6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)std::string IPAddressToPackedString(const IPAddressNumber& addr) {
64558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return std::string(reinterpret_cast<const char *>(&addr.front()),
64658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                     addr.size());
64758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
64858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetHostName() {
650a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#if defined(OS_NACL)
651a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  NOTIMPLEMENTED();
652a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return std::string();
653a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#else  // defined(OS_NACL)
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_WIN)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EnsureWinsockInit();
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Host names are limited to 255 bytes.
6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  char buffer[256];
6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int result = gethostname(buffer, sizeof(buffer));
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (result != 0) {
6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "gethostname() failed with " << result;
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    buffer[0] = '\0';
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::string(buffer);
666a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#endif  // !defined(OS_NACL)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetIdentityFromURL(const GURL& url,
670c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        base::string16* username,
671c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                        base::string16* password) {
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  UnescapeRule::Type flags =
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS;
6740529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *username = UnescapeAndDecodeUTF8URLComponent(url.username(), flags);
6750529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch  *password = UnescapeAndDecodeUTF8URLComponent(url.password(), flags);
6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetHostOrSpecFromURL(const GURL& url) {
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.has_host() ? TrimEndingDot(url.host()) : url.spec();
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CanStripTrailingSlash(const GURL& url) {
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Omit the path only for standard, non-file URLs with nothing but "/" after
6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // the hostname.
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.IsStandard() && !url.SchemeIsFile() &&
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      !url.SchemeIsFileSystem() && !url.has_query() && !url.has_ref()
6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      && url.path() == "/";
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)GURL SimplifyUrlForRequest(const GURL& url) {
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(url.is_valid());
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GURL::Replacements replacements;
6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearUsername();
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearPassword();
6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  replacements.ClearRef();
6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return url.ReplaceComponents(replacements);
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Specifies a comma separated list of port numbers that should be accepted
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// despite bans. If the string is invalid no allowed ports are stored.
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SetExplicitlyAllowedPorts(const std::string& allowed_ports) {
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (allowed_ports.empty())
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::multiset<int> ports;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t last = 0;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t size = allowed_ports.size();
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The comma delimiter.
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const std::string::value_type kComma = ',';
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Overflow is still possible for evil user inputs.
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i <= size; ++i) {
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // The string should be composed of only digits and commas.
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i != size && !IsAsciiDigit(allowed_ports[i]) &&
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        (allowed_ports[i] != kComma))
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return;
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i == size || allowed_ports[i] == kComma) {
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (i > last) {
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        int port;
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        base::StringToInt(base::StringPiece(allowed_ports.begin() + last,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                            allowed_ports.begin() + i),
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          &port);
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ports.insert(port);
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      last = i + 1;
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_explicitly_allowed_ports.Get() = ports;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedPortException::ScopedPortException(int port) : port_(port) {
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  g_explicitly_allowed_ports.Get().insert(port);
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ScopedPortException::~ScopedPortException() {
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::multiset<int>::iterator it =
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      g_explicitly_allowed_ports.Get().find(port_);
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (it != g_explicitly_allowed_ports.Get().end())
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    g_explicitly_allowed_ports.Get().erase(it);
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool HaveOnlyLoopbackAddresses() {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return android::HaveOnlyLoopbackAddresses();
747a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch#elif defined(OS_NACL)
748a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  NOTIMPLEMENTED();
749a02191e04bc25c4935f804f2c080ae28663d096dBen Murdoch  return false;
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_POSIX)
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct ifaddrs* interface_addr = NULL;
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = getifaddrs(&interface_addr);
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv != 0) {
7545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DVLOG(1) << "getifaddrs() failed with errno = " << errno;
7555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool result = true;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (struct ifaddrs* interface = interface_addr;
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       interface != NULL;
7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)       interface = interface->ifa_next) {
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!(IFF_UP & interface->ifa_flags))
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (IFF_LOOPBACK & interface->ifa_flags)
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct sockaddr* addr = interface->ifa_addr;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!addr)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (addr->sa_family == AF_INET6) {
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // Safe cast since this is AF_INET6.
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct sockaddr_in6* addr_in6 =
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          reinterpret_cast<const struct sockaddr_in6*>(addr);
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const struct in6_addr* sin6_addr = &addr_in6->sin6_addr;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr))
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        continue;
7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET)
7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = false;
7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    break;
7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  freeifaddrs(interface_addr);
7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#elif defined(OS_WIN)
7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(wtc): implement with the GetAdaptersAddresses function.
7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else
7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTIMPLEMENTED();
7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // defined(various platforms)
7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
79590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)AddressFamily GetAddressFamily(const IPAddressNumber& address) {
79690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  switch (address.size()) {
79790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kIPv4AddressSize:
79890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return ADDRESS_FAMILY_IPV4;
79990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    case kIPv6AddressSize:
80090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return ADDRESS_FAMILY_IPV6;
80190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    default:
80290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)      return ADDRESS_FAMILY_UNSPECIFIED;
80390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  }
80490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)}
80590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)
80658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)int ConvertAddressFamily(AddressFamily address_family) {
80758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  switch (address_family) {
80858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ADDRESS_FAMILY_UNSPECIFIED:
80958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return AF_UNSPEC;
81058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ADDRESS_FAMILY_IPV4:
81158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return AF_INET;
81258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)    case ADDRESS_FAMILY_IPV6:
81358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      return AF_INET6;
81458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  }
81558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  NOTREACHED();
81658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  return AF_UNSPEC;
81758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)}
81858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)
8196e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)bool ParseURLHostnameToNumber(const std::string& hostname,
8206e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                              IPAddressNumber* ip_number) {
8216e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // |hostname| is an already canoncalized hostname, conforming to RFC 3986.
8226e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // For an IP address, this is defined in Section 3.2.2 of RFC 3986, with
8236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // the canonical form for IPv6 addresses defined in Section 4 of RFC 5952.
8246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  url::Component host_comp(0, hostname.size());
8256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
8266e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // If it has a bracket, try parsing it as an IPv6 address.
8276e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  if (hostname[0] == '[') {
8286e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    ip_number->resize(16);  // 128 bits.
8296e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    return url::IPv6AddressToNumber(
8306e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)        hostname.data(), host_comp, &(*ip_number)[0]);
8316e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
8326e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
8336e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  // Otherwise, try IPv4.
8346e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  ip_number->resize(4);  // 32 bits.
8356e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  int num_components;
8366e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
8376e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      hostname.data(), host_comp, &(*ip_number)[0], &num_components);
8386e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  return family == url::CanonHostInfo::IPV4;
8396e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
8406e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseIPLiteralToNumber(const std::string& ip_literal,
8425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            IPAddressNumber* ip_number) {
8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ip_literal| could be either a IPv4 or an IPv6 literal. If it contains
8445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a colon however, it must be an IPv6 address.
8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_literal.find(':') != std::string::npos) {
8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // GURL expects IPv6 hostnames to be surrounded with brackets.
8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string host_brackets = "[" + ip_literal + "]";
8485c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    url::Component host_comp(0, host_brackets.size());
8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Try parsing the hostname as an IPv6 literal.
8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip_number->resize(16);  // 128 bits.
8525c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu    return url::IPv6AddressToNumber(host_brackets.data(), host_comp,
8535c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                                    &(*ip_number)[0]);
8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise the string is an IPv4 address.
8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ip_number->resize(4);  // 32 bits.
8585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::Component host_comp(0, ip_literal.size());
8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int num_components;
8605c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::CanonHostInfo::Family family = url::IPv4AddressToNumber(
8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ip_literal.data(), host_comp, &(*ip_number)[0], &num_components);
8625c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  return family == url::CanonHostInfo::IPV4;
8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const unsigned char kIPv4MappedPrefix[] =
8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF };
8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPAddressNumber ConvertIPv4NumberToIPv6Number(
8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& ipv4_number) {
8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ipv4_number.size() == 4);
8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4-mapped addresses are formed by:
8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // <80 bits of zeros>  + <16 bits of ones> + <32-bit IPv4 address>.
8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ipv6_number;
8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipv6_number.reserve(16);
8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipv6_number.insert(ipv6_number.end(),
8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     kIPv4MappedPrefix,
8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                     kIPv4MappedPrefix + arraysize(kIPv4MappedPrefix));
8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ipv6_number.insert(ipv6_number.end(), ipv4_number.begin(), ipv4_number.end());
8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return ipv6_number;
8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsIPv4Mapped(const IPAddressNumber& address) {
8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.size() != kIPv6AddressSize)
8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return std::equal(address.begin(),
8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    address.begin() + arraysize(kIPv4MappedPrefix),
8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    kIPv4MappedPrefix);
8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)IPAddressNumber ConvertIPv4MappedToIPv4(const IPAddressNumber& address) {
8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsIPv4Mapped(address));
8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPAddressNumber(address.begin() + arraysize(kIPv4MappedPrefix),
8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         address.end());
8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ParseCIDRBlock(const std::string& cidr_literal,
9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    IPAddressNumber* ip_number,
9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    size_t* prefix_length_in_bits) {
9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // We expect CIDR notation to match one of these two templates:
9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   <IPv4-literal> "/" <number of bits>
9055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //   <IPv6-literal> "/" <number of bits>
9065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<std::string> parts;
9085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::SplitString(cidr_literal, '/', &parts);
9095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (parts.size() != 2)
9105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the IP address.
9135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseIPLiteralToNumber(parts[0], ip_number))
9145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Parse the prefix length.
9175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int number_of_bits = -1;
9185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!base::StringToInt(parts[1], &number_of_bits))
9195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Make sure the prefix length is in a valid range.
9225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (number_of_bits < 0 ||
9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      number_of_bits > static_cast<int>(ip_number->size() * 8))
9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *prefix_length_in_bits = static_cast<size_t>(number_of_bits);
9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
9285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number,
9315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           const IPAddressNumber& ip_prefix,
9325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           size_t prefix_length_in_bits) {
9335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both the input IP address and the prefix IP address should be
9345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // either IPv4 or IPv6.
9355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ip_number.size() == 4 || ip_number.size() == 16);
9365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(ip_prefix.size() == 4 || ip_prefix.size() == 16);
9375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK_LE(prefix_length_in_bits, ip_prefix.size() * 8);
9395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // In case we have an IPv6 / IPv4 mismatch, convert the IPv4 addresses to
9415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv6 addresses in order to do the comparison.
9425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_number.size() != ip_prefix.size()) {
9435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ip_number.size() == 4) {
9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return IPNumberMatchesPrefix(ConvertIPv4NumberToIPv6Number(ip_number),
9455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                   ip_prefix, prefix_length_in_bits);
9465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
9475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return IPNumberMatchesPrefix(ip_number,
9485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 ConvertIPv4NumberToIPv6Number(ip_prefix),
9495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 96 + prefix_length_in_bits);
9505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return IPNumberPrefixCheck(ip_number, &ip_prefix[0], prefix_length_in_bits);
9535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address,
9565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                       socklen_t address_len) {
9575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address->sa_family == AF_INET) {
9585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len));
9595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct sockaddr_in* sockaddr =
9605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const struct sockaddr_in*>(address);
9615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &sockaddr->sin_port;
9625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else if (address->sa_family == AF_INET6) {
9635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK_LE(sizeof(sockaddr_in6), static_cast<size_t>(address_len));
9645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const struct sockaddr_in6* sockaddr =
9655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const struct sockaddr_in6*>(address);
9665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return &sockaddr->sin6_port;
9675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
9685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    NOTREACHED();
9695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return NULL;
9705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
9715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) {
9745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const uint16* port_field = GetPortFieldFromSockaddr(address, address_len);
9755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!port_field)
9765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return -1;
9775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return base::NetToHost16(*port_field);
9785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
9795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsLocalhost(const std::string& host) {
9815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host == "localhost" ||
9825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host == "localhost.localdomain" ||
9835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host == "localhost6" ||
9845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      host == "localhost6.localdomain6")
9855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
9865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
9875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ip_number;
9885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ParseIPLiteralToNumber(host, &ip_number)) {
9895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size = ip_number.size();
9905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    switch (size) {
9915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kIPv4AddressSize: {
9925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        IPAddressNumber localhost_prefix;
9935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        localhost_prefix.push_back(127);
9945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (int i = 0; i < 3; ++i) {
9955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          localhost_prefix.push_back(0);
9965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
9975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return IPNumberMatchesPrefix(ip_number, localhost_prefix, 8);
9985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
9995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      case kIPv6AddressSize: {
10015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        struct in6_addr sin6_addr;
10025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        memcpy(&sin6_addr, &ip_number[0], kIPv6AddressSize);
10035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return !!IN6_IS_ADDR_LOOPBACK(&sin6_addr);
10045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
10055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      default:
10075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        NOTREACHED();
10085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
10095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
10105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
10125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1014c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen MurdochNetworkInterface::NetworkInterface()
1015010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    : type(NetworkChangeNotifier::CONNECTION_UNKNOWN),
1016c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      network_prefix(0) {
10175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkInterface::NetworkInterface(const std::string& name,
1020a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)                                   const std::string& friendly_name,
1021a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   uint32 interface_index,
1022010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)                                   NetworkChangeNotifier::ConnectionType type,
102368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                                   const IPAddressNumber& address,
10241320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   uint32 network_prefix,
10251320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                   int ip_address_attributes)
1026a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    : name(name),
1027a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)      friendly_name(friendly_name),
1028a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      interface_index(interface_index),
1029c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      type(type),
1030a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      address(address),
10311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      network_prefix(network_prefix),
10321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      ip_address_attributes(ip_address_attributes) {
10335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)NetworkInterface::~NetworkInterface() {
10365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
10375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
103868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)unsigned CommonPrefixLength(const IPAddressNumber& a1,
103968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)                            const IPAddressNumber& a2) {
104068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  DCHECK_EQ(a1.size(), a2.size());
104168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  for (size_t i = 0; i < a1.size(); ++i) {
104268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    unsigned diff = a1[i] ^ a2[i];
104368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    if (!diff)
104468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      continue;
104568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    for (unsigned j = 0; j < CHAR_BIT; ++j) {
104668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      if (diff & (1 << (CHAR_BIT - 1)))
104768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)        return i * CHAR_BIT + j;
104868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)      diff <<= 1;
104968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    }
105068043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)    NOTREACHED();
105168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  }
105268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return a1.size() * CHAR_BIT;
105368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
105468043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
105568043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)unsigned MaskPrefixLength(const IPAddressNumber& mask) {
105668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  IPAddressNumber all_ones(mask.size(), 0xFF);
105768043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)  return CommonPrefixLength(mask, all_ones);
105868043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)}
105968043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles)
10601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano TucciScopedWifiOptions::~ScopedWifiOptions() {
10611320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci}
10621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci
10635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
1064