Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/net_util.h" | 5 #include "net/base/port_util.h" |
| 6 | 6 |
| 7 #include <errno.h> | |
| 8 #include <string.h> | |
| 9 | |
| 10 #include <algorithm> | |
| 11 #include <iterator> | 7 #include <iterator> |
|
mmenke
2015/07/16 15:07:57
Do we ever explicitly include iterator? Worth not
eroman
2015/07/21 01:04:04
Removed.
(I had pruned the headers manually, and
| |
| 12 #include <limits> | |
| 13 #include <set> | 8 #include <set> |
| 14 | 9 |
| 15 #include "build/build_config.h" | |
| 16 | |
| 17 #if defined(OS_WIN) | |
| 18 #include <windows.h> | |
| 19 #include <iphlpapi.h> | |
| 20 #include <winsock2.h> | |
| 21 #include <ws2bth.h> | |
| 22 #pragma comment(lib, "iphlpapi.lib") | |
| 23 #elif defined(OS_POSIX) | |
| 24 #include <fcntl.h> | |
| 25 #include <netdb.h> | |
| 26 #include <netinet/in.h> | |
| 27 #include <unistd.h> | |
| 28 #if !defined(OS_NACL) | |
| 29 #include <net/if.h> | |
| 30 #if !defined(OS_ANDROID) | |
| 31 #include <ifaddrs.h> | |
| 32 #endif // !defined(OS_NACL) | |
| 33 #endif // !defined(OS_ANDROID) | |
| 34 #endif // defined(OS_POSIX) | |
| 35 | |
| 36 #include "base/basictypes.h" | |
| 37 #include "base/json/string_escape.h" | |
| 38 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| 39 #include "base/logging.h" | 11 #include "base/logging.h" |
| 40 #include "base/strings/string_number_conversions.h" | 12 #include "base/strings/string_number_conversions.h" |
| 41 #include "base/strings/string_piece.h" | |
| 42 #include "base/strings/string_split.h" | |
| 43 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 44 #include "base/strings/stringprintf.h" | |
| 45 #include "base/strings/utf_string_conversions.h" | |
| 46 #include "base/sys_byteorder.h" | |
| 47 #include "base/values.h" | |
| 48 #include "net/base/address_list.h" | |
| 49 #include "net/base/dns_util.h" | |
| 50 #include "net/base/ip_address_number.h" | |
| 51 #include "net/base/net_module.h" | |
| 52 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | |
| 53 #include "net/grit/net_resources.h" | |
| 54 #include "net/http/http_content_disposition.h" | |
| 55 #include "url/gurl.h" | |
| 56 #include "url/third_party/mozilla/url_parse.h" | |
| 57 #include "url/url_canon.h" | |
| 58 #include "url/url_canon_ip.h" | |
| 59 #include "url/url_constants.h" | 14 #include "url/url_constants.h" |
| 60 | 15 |
| 61 #if defined(OS_ANDROID) | |
| 62 #include "net/android/network_library.h" | |
| 63 #endif | |
| 64 #if defined(OS_WIN) | |
| 65 #include "net/base/winsock_init.h" | |
| 66 #endif | |
| 67 | |
| 68 namespace net { | 16 namespace net { |
| 69 | 17 |
| 70 namespace { | 18 namespace { |
| 71 | 19 |
| 72 // The general list of blocked ports. Will be blocked unless a specific | 20 // The general list of blocked ports. Will be blocked unless a specific |
| 73 // protocol overrides it. (Ex: ftp can use ports 20 and 21) | 21 // protocol overrides it. (Ex: ftp can use ports 20 and 21) |
| 74 static const int kRestrictedPorts[] = { | 22 static const int kRestrictedPorts[] = { |
|
mmenke
2015/07/16 15:07:57
Optional: Could remove this static and the next w
eroman
2015/07/21 01:04:04
Done.
| |
| 75 1, // tcpmux | 23 1, // tcpmux |
| 76 7, // echo | 24 7, // echo |
| 77 9, // discard | 25 9, // discard |
| 78 11, // systat | 26 11, // systat |
| 79 13, // daytime | 27 13, // daytime |
| 80 15, // netstat | 28 15, // netstat |
| 81 17, // qotd | 29 17, // qotd |
| 82 19, // chargen | 30 19, // chargen |
| 83 20, // ftp data | 31 20, // ftp data |
| 84 21, // ftp access | 32 21, // ftp access |
| 85 22, // ssh | 33 22, // ssh |
| 86 23, // telnet | 34 23, // telnet |
| 87 25, // smtp | 35 25, // smtp |
| 88 37, // time | 36 37, // time |
| 89 42, // name | 37 42, // name |
| 90 43, // nicname | 38 43, // nicname |
| 91 53, // domain | 39 53, // domain |
| 92 77, // priv-rjs | 40 77, // priv-rjs |
| 93 79, // finger | 41 79, // finger |
| 94 87, // ttylink | 42 87, // ttylink |
| 95 95, // supdup | 43 95, // supdup |
| 96 101, // hostriame | 44 101, // hostriame |
| 97 102, // iso-tsap | 45 102, // iso-tsap |
| 98 103, // gppitnp | 46 103, // gppitnp |
| 99 104, // acr-nema | 47 104, // acr-nema |
| 100 109, // pop2 | 48 109, // pop2 |
| 101 110, // pop3 | 49 110, // pop3 |
| 102 111, // sunrpc | 50 111, // sunrpc |
| 103 113, // auth | 51 113, // auth |
| 104 115, // sftp | 52 115, // sftp |
| 105 117, // uucp-path | 53 117, // uucp-path |
| 106 119, // nntp | 54 119, // nntp |
| 107 123, // NTP | 55 123, // NTP |
| 108 135, // loc-srv /epmap | 56 135, // loc-srv /epmap |
| 109 139, // netbios | 57 139, // netbios |
| 110 143, // imap2 | 58 143, // imap2 |
| 111 179, // BGP | 59 179, // BGP |
| 112 389, // ldap | 60 389, // ldap |
| 113 465, // smtp+ssl | 61 465, // smtp+ssl |
| 114 512, // print / exec | 62 512, // print / exec |
| 115 513, // login | 63 513, // login |
| 116 514, // shell | 64 514, // shell |
| 117 515, // printer | 65 515, // printer |
| 118 526, // tempo | 66 526, // tempo |
| 119 530, // courier | 67 530, // courier |
| 120 531, // chat | 68 531, // chat |
| 121 532, // netnews | 69 532, // netnews |
| 122 540, // uucp | 70 540, // uucp |
| 123 556, // remotefs | 71 556, // remotefs |
| 124 563, // nntp+ssl | 72 563, // nntp+ssl |
| 125 587, // stmp? | 73 587, // stmp? |
| 126 601, // ?? | 74 601, // ?? |
| 127 636, // ldap+ssl | 75 636, // ldap+ssl |
| 128 993, // ldap+ssl | 76 993, // ldap+ssl |
| 129 995, // pop3+ssl | 77 995, // pop3+ssl |
| 130 2049, // nfs | 78 2049, // nfs |
| 131 3659, // apple-sasl / PasswordServer | 79 3659, // apple-sasl / PasswordServer |
| 132 4045, // lockd | 80 4045, // lockd |
| 133 6000, // X11 | 81 6000, // X11 |
| 134 6665, // Alternate IRC [Apple addition] | 82 6665, // Alternate IRC [Apple addition] |
| 135 6666, // Alternate IRC [Apple addition] | 83 6666, // Alternate IRC [Apple addition] |
| 136 6667, // Standard IRC [Apple addition] | 84 6667, // Standard IRC [Apple addition] |
| 137 6668, // Alternate IRC [Apple addition] | 85 6668, // Alternate IRC [Apple addition] |
| 138 6669, // Alternate IRC [Apple addition] | 86 6669, // Alternate IRC [Apple addition] |
| 139 0xFFFF, // Used to block all invalid port numbers (see | 87 0xFFFF, // Used to block all invalid port numbers (see |
| 140 // third_party/WebKit/Source/platform/weborigin/KURL.cpp, | 88 // third_party/WebKit/Source/platform/weborigin/KURL.cpp, |
| 141 // KURL::port()) | 89 // KURL::port()) |
| 142 }; | 90 }; |
| 143 | 91 |
| 144 // FTP overrides the following restricted ports. | 92 // FTP overrides the following restricted ports. |
| 145 static const int kAllowedFtpPorts[] = { | 93 static const int kAllowedFtpPorts[] = { |
| 146 21, // ftp data | 94 21, // ftp data |
| 147 22, // ssh | 95 22, // ssh |
| 148 }; | 96 }; |
| 149 | 97 |
| 150 std::string NormalizeHostname(const std::string& host) { | |
| 151 std::string result = base::StringToLowerASCII(host); | |
| 152 if (!result.empty() && *result.rbegin() == '.') | |
| 153 result.resize(result.size() - 1); | |
| 154 return result; | |
| 155 } | |
| 156 | |
| 157 bool IsNormalizedLocalhostTLD(const std::string& host) { | |
| 158 return base::EndsWith(host, ".localhost", true); | |
| 159 } | |
| 160 | |
| 161 // |host| should be normalized. | |
| 162 bool IsLocalHostname(const std::string& host) { | |
| 163 return host == "localhost" || host == "localhost.localdomain" || | |
| 164 IsNormalizedLocalhostTLD(host); | |
| 165 } | |
| 166 | |
| 167 // |host| should be normalized. | |
| 168 bool IsLocal6Hostname(const std::string& host) { | |
| 169 return host == "localhost6" || host == "localhost6.localdomain6"; | |
| 170 } | |
| 171 | |
| 172 } // namespace | 98 } // namespace |
| 173 | 99 |
| 174 static base::LazyInstance<std::multiset<int> >::Leaky | 100 static base::LazyInstance<std::multiset<int>>::Leaky |
| 175 g_explicitly_allowed_ports = LAZY_INSTANCE_INITIALIZER; | 101 g_explicitly_allowed_ports = LAZY_INSTANCE_INITIALIZER; |
|
mmenke
2015/07/16 15:07:57
Optional: Know it was like this before...maybe mo
eroman
2015/07/21 01:04:04
Done.
| |
| 176 | 102 |
| 177 std::string CanonicalizeHost(const std::string& host, | |
| 178 url::CanonHostInfo* host_info) { | |
| 179 // Try to canonicalize the host. | |
| 180 const url::Component raw_host_component(0, static_cast<int>(host.length())); | |
| 181 std::string canon_host; | |
| 182 url::StdStringCanonOutput canon_host_output(&canon_host); | |
| 183 url::CanonicalizeHostVerbose(host.c_str(), raw_host_component, | |
| 184 &canon_host_output, host_info); | |
| 185 | |
| 186 if (host_info->out_host.is_nonempty() && | |
| 187 host_info->family != url::CanonHostInfo::BROKEN) { | |
| 188 // Success! Assert that there's no extra garbage. | |
| 189 canon_host_output.Complete(); | |
| 190 DCHECK_EQ(host_info->out_host.len, static_cast<int>(canon_host.length())); | |
| 191 } else { | |
| 192 // Empty host, or canonicalization failed. We'll return empty. | |
| 193 canon_host.clear(); | |
| 194 } | |
| 195 | |
| 196 return canon_host; | |
| 197 } | |
| 198 | |
| 199 std::string GetDirectoryListingHeader(const base::string16& title) { | |
| 200 static const base::StringPiece header( | |
| 201 NetModule::GetResource(IDR_DIR_HEADER_HTML)); | |
| 202 // This can be null in unit tests. | |
| 203 DLOG_IF(WARNING, header.empty()) << | |
| 204 "Missing resource: directory listing header"; | |
| 205 | |
| 206 std::string result; | |
| 207 if (!header.empty()) | |
| 208 result.assign(header.data(), header.size()); | |
| 209 | |
| 210 result.append("<script>start("); | |
| 211 base::EscapeJSONString(title, true, &result); | |
| 212 result.append(");</script>\n"); | |
| 213 | |
| 214 return result; | |
| 215 } | |
| 216 | |
| 217 inline bool IsHostCharAlphanumeric(char c) { | |
| 218 // We can just check lowercase because uppercase characters have already been | |
| 219 // normalized. | |
| 220 return ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')); | |
| 221 } | |
| 222 | |
| 223 bool IsCanonicalizedHostCompliant(const std::string& host) { | |
| 224 if (host.empty()) | |
| 225 return false; | |
| 226 | |
| 227 bool in_component = false; | |
| 228 bool most_recent_component_started_alphanumeric = false; | |
| 229 | |
| 230 for (std::string::const_iterator i(host.begin()); i != host.end(); ++i) { | |
| 231 const char c = *i; | |
| 232 if (!in_component) { | |
| 233 most_recent_component_started_alphanumeric = IsHostCharAlphanumeric(c); | |
| 234 if (!most_recent_component_started_alphanumeric && (c != '-') && | |
| 235 (c != '_')) { | |
| 236 return false; | |
| 237 } | |
| 238 in_component = true; | |
| 239 } else if (c == '.') { | |
| 240 in_component = false; | |
| 241 } else if (!IsHostCharAlphanumeric(c) && (c != '-') && (c != '_')) { | |
| 242 return false; | |
| 243 } | |
| 244 } | |
| 245 | |
| 246 return most_recent_component_started_alphanumeric; | |
| 247 } | |
| 248 | |
| 249 base::string16 StripWWW(const base::string16& text) { | |
| 250 const base::string16 www(base::ASCIIToUTF16("www.")); | |
| 251 return base::StartsWith(text, www, base::CompareCase::SENSITIVE) | |
| 252 ? text.substr(www.length()) : text; | |
| 253 } | |
| 254 | |
| 255 base::string16 StripWWWFromHost(const GURL& url) { | |
| 256 DCHECK(url.is_valid()); | |
| 257 return StripWWW(base::ASCIIToUTF16(url.host())); | |
| 258 } | |
| 259 | |
| 260 bool IsPortValid(int port) { | 103 bool IsPortValid(int port) { |
| 261 return port >= 0 && port <= std::numeric_limits<uint16_t>::max(); | 104 return port >= 0 && port <= std::numeric_limits<uint16_t>::max(); |
| 262 } | 105 } |
| 263 | 106 |
| 264 bool IsWellKnownPort(int port) { | 107 bool IsWellKnownPort(int port) { |
| 265 return port >= 0 && port < 1024; | 108 return port >= 0 && port < 1024; |
| 266 } | 109 } |
| 267 | 110 |
| 268 bool IsPortAllowedForScheme(int port, const std::string& url_scheme) { | 111 bool IsPortAllowedForScheme(int port, const std::string& url_scheme) { |
| 269 // Reject invalid ports. | 112 // Reject invalid ports. |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 334 | 177 |
| 335 ScopedPortException::~ScopedPortException() { | 178 ScopedPortException::~ScopedPortException() { |
| 336 std::multiset<int>::iterator it = | 179 std::multiset<int>::iterator it = |
| 337 g_explicitly_allowed_ports.Get().find(port_); | 180 g_explicitly_allowed_ports.Get().find(port_); |
| 338 if (it != g_explicitly_allowed_ports.Get().end()) | 181 if (it != g_explicitly_allowed_ports.Get().end()) |
| 339 g_explicitly_allowed_ports.Get().erase(it); | 182 g_explicitly_allowed_ports.Get().erase(it); |
| 340 else | 183 else |
| 341 NOTREACHED(); | 184 NOTREACHED(); |
| 342 } | 185 } |
| 343 | 186 |
| 344 int SetNonBlocking(int fd) { | |
| 345 #if defined(OS_WIN) | |
| 346 unsigned long no_block = 1; | |
| 347 return ioctlsocket(fd, FIONBIO, &no_block); | |
| 348 #elif defined(OS_POSIX) | |
| 349 int flags = fcntl(fd, F_GETFL, 0); | |
| 350 if (-1 == flags) | |
| 351 return flags; | |
| 352 return fcntl(fd, F_SETFL, flags | O_NONBLOCK); | |
| 353 #endif | |
| 354 } | |
| 355 | |
| 356 bool ParseHostAndPort(std::string::const_iterator host_and_port_begin, | |
| 357 std::string::const_iterator host_and_port_end, | |
| 358 std::string* host, | |
| 359 int* port) { | |
| 360 if (host_and_port_begin >= host_and_port_end) | |
| 361 return false; | |
| 362 | |
| 363 // When using url, we use char*. | |
| 364 const char* auth_begin = &(*host_and_port_begin); | |
| 365 int auth_len = host_and_port_end - host_and_port_begin; | |
| 366 | |
| 367 url::Component auth_component(0, auth_len); | |
| 368 url::Component username_component; | |
| 369 url::Component password_component; | |
| 370 url::Component hostname_component; | |
| 371 url::Component port_component; | |
| 372 | |
| 373 url::ParseAuthority(auth_begin, auth_component, &username_component, | |
| 374 &password_component, &hostname_component, &port_component); | |
| 375 | |
| 376 // There shouldn't be a username/password. | |
| 377 if (username_component.is_valid() || password_component.is_valid()) | |
| 378 return false; | |
| 379 | |
| 380 if (!hostname_component.is_nonempty()) | |
| 381 return false; // Failed parsing. | |
| 382 | |
| 383 int parsed_port_number = -1; | |
| 384 if (port_component.is_nonempty()) { | |
| 385 parsed_port_number = url::ParsePort(auth_begin, port_component); | |
| 386 | |
| 387 // If parsing failed, port_number will be either PORT_INVALID or | |
| 388 // PORT_UNSPECIFIED, both of which are negative. | |
| 389 if (parsed_port_number < 0) | |
| 390 return false; // Failed parsing the port number. | |
| 391 } | |
| 392 | |
| 393 if (port_component.len == 0) | |
| 394 return false; // Reject inputs like "foo:" | |
| 395 | |
| 396 unsigned char tmp_ipv6_addr[16]; | |
| 397 | |
| 398 // If the hostname starts with a bracket, it is either an IPv6 literal or | |
| 399 // invalid. If it is an IPv6 literal then strip the brackets. | |
| 400 if (hostname_component.len > 0 && | |
| 401 auth_begin[hostname_component.begin] == '[') { | |
| 402 if (auth_begin[hostname_component.end() - 1] == ']' && | |
| 403 url::IPv6AddressToNumber( | |
| 404 auth_begin, hostname_component, tmp_ipv6_addr)) { | |
| 405 // Strip the brackets. | |
| 406 hostname_component.begin++; | |
| 407 hostname_component.len -= 2; | |
| 408 } else { | |
| 409 return false; | |
| 410 } | |
| 411 } | |
| 412 | |
| 413 // Pass results back to caller. | |
| 414 host->assign(auth_begin + hostname_component.begin, hostname_component.len); | |
| 415 *port = parsed_port_number; | |
| 416 | |
| 417 return true; // Success. | |
| 418 } | |
| 419 | |
| 420 bool ParseHostAndPort(const std::string& host_and_port, | |
| 421 std::string* host, | |
| 422 int* port) { | |
| 423 return ParseHostAndPort( | |
| 424 host_and_port.begin(), host_and_port.end(), host, port); | |
| 425 } | |
| 426 | |
| 427 std::string GetHostAndPort(const GURL& url) { | |
| 428 // For IPv6 literals, GURL::host() already includes the brackets so it is | |
| 429 // safe to just append a colon. | |
| 430 return base::StringPrintf("%s:%d", url.host().c_str(), | |
| 431 url.EffectiveIntPort()); | |
| 432 } | |
| 433 | |
| 434 std::string GetHostAndOptionalPort(const GURL& url) { | |
| 435 // For IPv6 literals, GURL::host() already includes the brackets | |
| 436 // so it is safe to just append a colon. | |
| 437 if (url.has_port()) | |
| 438 return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str()); | |
| 439 return url.host(); | |
| 440 } | |
| 441 | |
| 442 bool IsHostnameNonUnique(const std::string& hostname) { | |
| 443 // CanonicalizeHost requires surrounding brackets to parse an IPv6 address. | |
| 444 const std::string host_or_ip = hostname.find(':') != std::string::npos ? | |
| 445 "[" + hostname + "]" : hostname; | |
| 446 url::CanonHostInfo host_info; | |
| 447 std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info); | |
| 448 | |
| 449 // If canonicalization fails, then the input is truly malformed. However, | |
| 450 // to avoid mis-reporting bad inputs as "non-unique", treat them as unique. | |
| 451 if (canonical_name.empty()) | |
| 452 return false; | |
| 453 | |
| 454 // If |hostname| is an IP address, check to see if it's in an IANA-reserved | |
| 455 // range. | |
| 456 if (host_info.IsIPAddress()) { | |
| 457 IPAddressNumber host_addr; | |
| 458 if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin, | |
| 459 host_info.out_host.len), | |
| 460 &host_addr)) { | |
| 461 return false; | |
| 462 } | |
| 463 switch (host_info.family) { | |
| 464 case url::CanonHostInfo::IPV4: | |
| 465 case url::CanonHostInfo::IPV6: | |
| 466 return IsIPAddressReserved(host_addr); | |
| 467 case url::CanonHostInfo::NEUTRAL: | |
| 468 case url::CanonHostInfo::BROKEN: | |
| 469 return false; | |
| 470 } | |
| 471 } | |
| 472 | |
| 473 // Check for a registry controlled portion of |hostname|, ignoring private | |
| 474 // registries, as they already chain to ICANN-administered registries, | |
| 475 // and explicitly ignoring unknown registries. | |
| 476 // | |
| 477 // Note: This means that as new gTLDs are introduced on the Internet, they | |
| 478 // will be treated as non-unique until the registry controlled domain list | |
| 479 // is updated. However, because gTLDs are expected to provide significant | |
| 480 // advance notice to deprecate older versions of this code, this an | |
| 481 // acceptable tradeoff. | |
| 482 return 0 == registry_controlled_domains::GetRegistryLength( | |
| 483 canonical_name, | |
| 484 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, | |
| 485 registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); | |
| 486 } | |
| 487 | |
| 488 SockaddrStorage::SockaddrStorage(const SockaddrStorage& other) | |
| 489 : addr_len(other.addr_len), | |
| 490 addr(reinterpret_cast<struct sockaddr*>(&addr_storage)) { | |
| 491 memcpy(addr, other.addr, addr_len); | |
| 492 } | |
| 493 | |
| 494 void SockaddrStorage::operator=(const SockaddrStorage& other) { | |
| 495 addr_len = other.addr_len; | |
| 496 // addr is already set to &this->addr_storage by default ctor. | |
| 497 memcpy(addr, other.addr, addr_len); | |
| 498 } | |
| 499 | |
| 500 // Extracts the address and port portions of a sockaddr. | |
| 501 bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr, | |
| 502 socklen_t sock_addr_len, | |
| 503 const uint8_t** address, | |
| 504 size_t* address_len, | |
| 505 uint16_t* port) { | |
| 506 if (sock_addr->sa_family == AF_INET) { | |
| 507 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in))) | |
| 508 return false; | |
| 509 const struct sockaddr_in* addr = | |
| 510 reinterpret_cast<const struct sockaddr_in*>(sock_addr); | |
| 511 *address = reinterpret_cast<const uint8_t*>(&addr->sin_addr); | |
| 512 *address_len = kIPv4AddressSize; | |
| 513 if (port) | |
| 514 *port = base::NetToHost16(addr->sin_port); | |
| 515 return true; | |
| 516 } | |
| 517 | |
| 518 if (sock_addr->sa_family == AF_INET6) { | |
| 519 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in6))) | |
| 520 return false; | |
| 521 const struct sockaddr_in6* addr = | |
| 522 reinterpret_cast<const struct sockaddr_in6*>(sock_addr); | |
| 523 *address = reinterpret_cast<const uint8_t*>(&addr->sin6_addr); | |
| 524 *address_len = kIPv6AddressSize; | |
| 525 if (port) | |
| 526 *port = base::NetToHost16(addr->sin6_port); | |
| 527 return true; | |
| 528 } | |
| 529 | |
| 530 #if defined(OS_WIN) | |
| 531 if (sock_addr->sa_family == AF_BTH) { | |
| 532 if (sock_addr_len < static_cast<socklen_t>(sizeof(SOCKADDR_BTH))) | |
| 533 return false; | |
| 534 const SOCKADDR_BTH* addr = | |
| 535 reinterpret_cast<const SOCKADDR_BTH*>(sock_addr); | |
| 536 *address = reinterpret_cast<const uint8_t*>(&addr->btAddr); | |
| 537 *address_len = kBluetoothAddressSize; | |
| 538 if (port) | |
| 539 *port = static_cast<uint16_t>(addr->port); | |
| 540 return true; | |
| 541 } | |
| 542 #endif | |
| 543 | |
| 544 return false; // Unrecognized |sa_family|. | |
| 545 } | |
| 546 | |
| 547 std::string NetAddressToString(const struct sockaddr* sa, | |
| 548 socklen_t sock_addr_len) { | |
| 549 const uint8_t* address; | |
| 550 size_t address_len; | |
| 551 if (!GetIPAddressFromSockAddr(sa, sock_addr_len, &address, | |
| 552 &address_len, NULL)) { | |
| 553 NOTREACHED(); | |
| 554 return std::string(); | |
| 555 } | |
| 556 return IPAddressToString(address, address_len); | |
| 557 } | |
| 558 | |
| 559 std::string NetAddressToStringWithPort(const struct sockaddr* sa, | |
| 560 socklen_t sock_addr_len) { | |
| 561 const uint8_t* address; | |
| 562 size_t address_len; | |
| 563 uint16_t port; | |
| 564 if (!GetIPAddressFromSockAddr(sa, sock_addr_len, &address, | |
| 565 &address_len, &port)) { | |
| 566 NOTREACHED(); | |
| 567 return std::string(); | |
| 568 } | |
| 569 return IPAddressToStringWithPort(address, address_len, port); | |
| 570 } | |
| 571 | |
| 572 std::string GetHostName() { | |
| 573 #if defined(OS_NACL) | |
| 574 NOTIMPLEMENTED(); | |
| 575 return std::string(); | |
| 576 #else // defined(OS_NACL) | |
| 577 #if defined(OS_WIN) | |
| 578 EnsureWinsockInit(); | |
| 579 #endif | |
| 580 | |
| 581 // Host names are limited to 255 bytes. | |
| 582 char buffer[256]; | |
| 583 int result = gethostname(buffer, sizeof(buffer)); | |
| 584 if (result != 0) { | |
| 585 DVLOG(1) << "gethostname() failed with " << result; | |
| 586 buffer[0] = '\0'; | |
| 587 } | |
| 588 return std::string(buffer); | |
| 589 #endif // !defined(OS_NACL) | |
| 590 } | |
| 591 | |
| 592 void GetIdentityFromURL(const GURL& url, | |
| 593 base::string16* username, | |
| 594 base::string16* password) { | |
| 595 UnescapeRule::Type flags = | |
| 596 UnescapeRule::SPACES | UnescapeRule::URL_SPECIAL_CHARS; | |
| 597 *username = UnescapeAndDecodeUTF8URLComponent(url.username(), flags); | |
| 598 *password = UnescapeAndDecodeUTF8URLComponent(url.password(), flags); | |
| 599 } | |
| 600 | |
| 601 std::string GetHostOrSpecFromURL(const GURL& url) { | |
| 602 return url.has_host() ? TrimEndingDot(url.host()) : url.spec(); | |
| 603 } | |
| 604 | |
| 605 bool CanStripTrailingSlash(const GURL& url) { | |
| 606 // Omit the path only for standard, non-file URLs with nothing but "/" after | |
| 607 // the hostname. | |
| 608 return url.IsStandard() && !url.SchemeIsFile() && | |
| 609 !url.SchemeIsFileSystem() && !url.has_query() && !url.has_ref() | |
| 610 && url.path() == "/"; | |
| 611 } | |
| 612 | |
| 613 GURL SimplifyUrlForRequest(const GURL& url) { | |
| 614 DCHECK(url.is_valid()); | |
| 615 GURL::Replacements replacements; | |
| 616 replacements.ClearUsername(); | |
| 617 replacements.ClearPassword(); | |
| 618 replacements.ClearRef(); | |
| 619 return url.ReplaceComponents(replacements); | |
| 620 } | |
| 621 | |
| 622 bool HaveOnlyLoopbackAddresses() { | |
| 623 #if defined(OS_ANDROID) | |
| 624 return android::HaveOnlyLoopbackAddresses(); | |
| 625 #elif defined(OS_NACL) | |
| 626 NOTIMPLEMENTED(); | |
| 627 return false; | |
| 628 #elif defined(OS_POSIX) | |
| 629 struct ifaddrs* interface_addr = NULL; | |
| 630 int rv = getifaddrs(&interface_addr); | |
| 631 if (rv != 0) { | |
| 632 DVLOG(1) << "getifaddrs() failed with errno = " << errno; | |
| 633 return false; | |
| 634 } | |
| 635 | |
| 636 bool result = true; | |
| 637 for (struct ifaddrs* interface = interface_addr; | |
| 638 interface != NULL; | |
| 639 interface = interface->ifa_next) { | |
| 640 if (!(IFF_UP & interface->ifa_flags)) | |
| 641 continue; | |
| 642 if (IFF_LOOPBACK & interface->ifa_flags) | |
| 643 continue; | |
| 644 const struct sockaddr* addr = interface->ifa_addr; | |
| 645 if (!addr) | |
| 646 continue; | |
| 647 if (addr->sa_family == AF_INET6) { | |
| 648 // Safe cast since this is AF_INET6. | |
| 649 const struct sockaddr_in6* addr_in6 = | |
| 650 reinterpret_cast<const struct sockaddr_in6*>(addr); | |
| 651 const struct in6_addr* sin6_addr = &addr_in6->sin6_addr; | |
| 652 if (IN6_IS_ADDR_LOOPBACK(sin6_addr) || IN6_IS_ADDR_LINKLOCAL(sin6_addr)) | |
| 653 continue; | |
| 654 } | |
| 655 if (addr->sa_family != AF_INET6 && addr->sa_family != AF_INET) | |
| 656 continue; | |
| 657 | |
| 658 result = false; | |
| 659 break; | |
| 660 } | |
| 661 freeifaddrs(interface_addr); | |
| 662 return result; | |
| 663 #elif defined(OS_WIN) | |
| 664 // TODO(wtc): implement with the GetAdaptersAddresses function. | |
| 665 NOTIMPLEMENTED(); | |
| 666 return false; | |
| 667 #else | |
| 668 NOTIMPLEMENTED(); | |
| 669 return false; | |
| 670 #endif // defined(various platforms) | |
| 671 } | |
| 672 | |
| 673 AddressFamily GetAddressFamily(const IPAddressNumber& address) { | |
| 674 switch (address.size()) { | |
| 675 case kIPv4AddressSize: | |
| 676 return ADDRESS_FAMILY_IPV4; | |
| 677 case kIPv6AddressSize: | |
| 678 return ADDRESS_FAMILY_IPV6; | |
| 679 default: | |
| 680 return ADDRESS_FAMILY_UNSPECIFIED; | |
| 681 } | |
| 682 } | |
| 683 | |
| 684 int ConvertAddressFamily(AddressFamily address_family) { | |
| 685 switch (address_family) { | |
| 686 case ADDRESS_FAMILY_UNSPECIFIED: | |
| 687 return AF_UNSPEC; | |
| 688 case ADDRESS_FAMILY_IPV4: | |
| 689 return AF_INET; | |
| 690 case ADDRESS_FAMILY_IPV6: | |
| 691 return AF_INET6; | |
| 692 } | |
| 693 NOTREACHED(); | |
| 694 return AF_UNSPEC; | |
| 695 } | |
| 696 | |
| 697 const uint16_t* GetPortFieldFromSockaddr(const struct sockaddr* address, | |
| 698 socklen_t address_len) { | |
| 699 if (address->sa_family == AF_INET) { | |
| 700 DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len)); | |
| 701 const struct sockaddr_in* sockaddr = | |
| 702 reinterpret_cast<const struct sockaddr_in*>(address); | |
| 703 return &sockaddr->sin_port; | |
| 704 } else if (address->sa_family == AF_INET6) { | |
| 705 DCHECK_LE(sizeof(sockaddr_in6), static_cast<size_t>(address_len)); | |
| 706 const struct sockaddr_in6* sockaddr = | |
| 707 reinterpret_cast<const struct sockaddr_in6*>(address); | |
| 708 return &sockaddr->sin6_port; | |
| 709 } else { | |
| 710 NOTREACHED(); | |
| 711 return NULL; | |
| 712 } | |
| 713 } | |
| 714 | |
| 715 int GetPortFromSockaddr(const struct sockaddr* address, socklen_t address_len) { | |
| 716 const uint16_t* port_field = GetPortFieldFromSockaddr(address, address_len); | |
| 717 if (!port_field) | |
| 718 return -1; | |
| 719 return base::NetToHost16(*port_field); | |
| 720 } | |
| 721 | |
| 722 bool ResolveLocalHostname(const std::string& host, | |
| 723 uint16_t port, | |
| 724 AddressList* address_list) { | |
| 725 static const unsigned char kLocalhostIPv4[] = {127, 0, 0, 1}; | |
| 726 static const unsigned char kLocalhostIPv6[] = { | |
| 727 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}; | |
| 728 | |
| 729 std::string normalized_host = NormalizeHostname(host); | |
| 730 | |
| 731 address_list->clear(); | |
| 732 | |
| 733 bool is_local6 = IsLocal6Hostname(normalized_host); | |
| 734 if (!is_local6 && !IsLocalHostname(normalized_host)) | |
| 735 return false; | |
| 736 | |
| 737 address_list->push_back( | |
| 738 IPEndPoint(IPAddressNumber(kLocalhostIPv6, | |
| 739 kLocalhostIPv6 + arraysize(kLocalhostIPv6)), | |
| 740 port)); | |
| 741 if (!is_local6) { | |
| 742 address_list->push_back( | |
| 743 IPEndPoint(IPAddressNumber(kLocalhostIPv4, | |
| 744 kLocalhostIPv4 + arraysize(kLocalhostIPv4)), | |
| 745 port)); | |
| 746 } | |
| 747 | |
| 748 return true; | |
| 749 } | |
| 750 | |
| 751 bool IsLocalhost(const std::string& host) { | |
| 752 std::string normalized_host = NormalizeHostname(host); | |
| 753 if (IsLocalHostname(normalized_host) || IsLocal6Hostname(normalized_host)) | |
| 754 return true; | |
| 755 | |
| 756 IPAddressNumber ip_number; | |
| 757 if (ParseIPLiteralToNumber(host, &ip_number)) { | |
| 758 size_t size = ip_number.size(); | |
| 759 switch (size) { | |
| 760 case kIPv4AddressSize: { | |
| 761 IPAddressNumber localhost_prefix; | |
| 762 localhost_prefix.push_back(127); | |
| 763 for (int i = 0; i < 3; ++i) { | |
| 764 localhost_prefix.push_back(0); | |
| 765 } | |
| 766 return IPNumberMatchesPrefix(ip_number, localhost_prefix, 8); | |
| 767 } | |
| 768 | |
| 769 case kIPv6AddressSize: { | |
| 770 struct in6_addr sin6_addr; | |
| 771 memcpy(&sin6_addr, &ip_number[0], kIPv6AddressSize); | |
| 772 return !!IN6_IS_ADDR_LOOPBACK(&sin6_addr); | |
| 773 } | |
| 774 | |
| 775 default: | |
| 776 NOTREACHED(); | |
| 777 } | |
| 778 } | |
| 779 | |
| 780 return false; | |
| 781 } | |
| 782 | |
| 783 bool IsLocalhostTLD(const std::string& host) { | |
| 784 return IsNormalizedLocalhostTLD(NormalizeHostname(host)); | |
| 785 } | |
| 786 | |
| 787 bool HasGoogleHost(const GURL& url) { | |
| 788 static const char* kGoogleHostSuffixes[] = { | |
| 789 ".google.com", | |
| 790 ".youtube.com", | |
| 791 ".gmail.com", | |
| 792 ".doubleclick.net", | |
| 793 ".gstatic.com", | |
| 794 ".googlevideo.com", | |
| 795 ".googleusercontent.com", | |
| 796 ".googlesyndication.com", | |
| 797 ".google-analytics.com", | |
| 798 ".googleadservices.com", | |
| 799 ".googleapis.com", | |
| 800 ".ytimg.com", | |
| 801 }; | |
| 802 const std::string& host = url.host(); | |
| 803 for (const char* suffix : kGoogleHostSuffixes) { | |
| 804 if (base::EndsWith(host, suffix, false)) | |
| 805 return true; | |
| 806 } | |
| 807 return false; | |
| 808 } | |
| 809 | |
| 810 } // namespace net | 187 } // namespace net |
| OLD | NEW |