Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: net/base/net_util.cc

Issue 22538003: Add IP address handling to net::IsHostnameNonUnique (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Take 3 Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/net_util.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 #include <map> 9 #include <map>
10 10
(...skipping 1373 matching lines...) Expand 10 before | Expand all | Expand 10 after
1384 } 1384 }
1385 1385
1386 std::string GetHostAndOptionalPort(const GURL& url) { 1386 std::string GetHostAndOptionalPort(const GURL& url) {
1387 // For IPv6 literals, GURL::host() already includes the brackets 1387 // For IPv6 literals, GURL::host() already includes the brackets
1388 // so it is safe to just append a colon. 1388 // so it is safe to just append a colon.
1389 if (url.has_port()) 1389 if (url.has_port())
1390 return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str()); 1390 return base::StringPrintf("%s:%s", url.host().c_str(), url.port().c_str());
1391 return url.host(); 1391 return url.host();
1392 } 1392 }
1393 1393
1394 // static
1395 bool IsHostnameNonUnique(const std::string& hostname) { 1394 bool IsHostnameNonUnique(const std::string& hostname) {
1396 // CanonicalizeHost requires surrounding brackets to parse an IPv6 address. 1395 // CanonicalizeHost requires surrounding brackets to parse an IPv6 address.
1397 const std::string host_or_ip = hostname.find(':') != std::string::npos ? 1396 const std::string host_or_ip = hostname.find(':') != std::string::npos ?
1398 "[" + hostname + "]" : hostname; 1397 "[" + hostname + "]" : hostname;
1399 url_canon::CanonHostInfo host_info; 1398 url_canon::CanonHostInfo host_info;
1400 std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info); 1399 std::string canonical_name = CanonicalizeHost(host_or_ip, &host_info);
1401 1400
1402 // If canonicalization fails, then the input is truly malformed. However, 1401 // If canonicalization fails, then the input is truly malformed. However,
1403 // to avoid mis-reporting bad inputs as "non-unique", treat them as unique. 1402 // to avoid mis-reporting bad inputs as "non-unique", treat them as unique.
1404 if (canonical_name.empty()) 1403 if (canonical_name.empty())
1405 return false; 1404 return false;
1406 1405
1407 // If |hostname| is an IP address, presume it's unique. 1406 // If |hostname| is an IP address, check to see if it's in an IANA-reserved
1408 // TODO(rsleevi): In the future, this should also reject IP addresses in 1407 // range.
1409 // IANA-reserved ranges. 1408 if (host_info.IsIPAddress()) {
1410 if (host_info.IsIPAddress()) 1409 IPAddressNumber host_addr;
1411 return false; 1410 if (!ParseIPLiteralToNumber(hostname.substr(host_info.out_host.begin,
1411 host_info.out_host.len),
1412 &host_addr)) {
1413 return false;
1414 }
1415 switch (host_info.family) {
1416 case url_canon::CanonHostInfo::IPV4:
1417 case url_canon::CanonHostInfo::IPV6:
1418 return IsIPAddressReserved(host_addr);
1419 case url_canon::CanonHostInfo::NEUTRAL:
1420 case url_canon::CanonHostInfo::BROKEN:
1421 return false;
1422 }
1423 }
1412 1424
1413 // Check for a registry controlled portion of |hostname|, ignoring private 1425 // Check for a registry controlled portion of |hostname|, ignoring private
1414 // registries, as they already chain to ICANN-administered registries, 1426 // registries, as they already chain to ICANN-administered registries,
1415 // and explicitly ignoring unknown registries. 1427 // and explicitly ignoring unknown registries.
1416 // 1428 //
1417 // Note: This means that as new gTLDs are introduced on the Internet, they 1429 // Note: This means that as new gTLDs are introduced on the Internet, they
1418 // will be treated as non-unique until the registry controlled domain list 1430 // will be treated as non-unique until the registry controlled domain list
1419 // is updated. However, because gTLDs are expected to provide significant 1431 // is updated. However, because gTLDs are expected to provide significant
1420 // advance notice to deprecate older versions of this code, this an 1432 // advance notice to deprecate older versions of this code, this an
1421 // acceptable tradeoff. 1433 // acceptable tradeoff.
1422 return 0 == registry_controlled_domains::GetRegistryLength( 1434 return 0 == registry_controlled_domains::GetRegistryLength(
1423 canonical_name, 1435 canonical_name,
1424 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 1436 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
1425 registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 1437 registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
1426 } 1438 }
1427 1439
1440 bool IPNumberPrefixCheck(const IPAddressNumber& ip_number,
1441 const unsigned char* ip_prefix,
1442 size_t prefix_length_in_bits) {
1443 // Compare all the bytes that fall entirely within the prefix.
1444 int num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
1445 for (int i = 0; i < num_entire_bytes_in_prefix; ++i) {
1446 if (ip_number[i] != ip_prefix[i])
1447 return false;
1448 }
1449
1450 // In case the prefix was not a multiple of 8, there will be 1 byte
1451 // which is only partially masked.
1452 int remaining_bits = prefix_length_in_bits % 8;
1453 if (remaining_bits != 0) {
1454 unsigned char mask = 0xFF << (8 - remaining_bits);
1455 int i = num_entire_bytes_in_prefix;
1456 if ((ip_number[i] & mask) != (ip_prefix[i] & mask))
Ryan Sleevi 2013/08/12 21:11:51 style nit: indentation is off by one here
felt 2013/08/13 04:17:06 Done.
1457 return false;
1458 }
1459 return true;
1460 }
1461
1462 // We shouldn't compare IPv4 to IPv6 (they have different range reservations),
1463 // so we keep separate arrays. Within each array, adjacent reserved ranges are
1464 // consolidated when possible.
Ryan Sleevi 2013/08/12 21:11:51 Can you rewrite this comment without the "We". Enj
felt 2013/08/13 04:17:06 Oh, huh, I hadn't heard that before. Done.
1465 // Sources for info:
1466 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
1467 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
1468 // They're formatted here with the prefix as the last element. For example:
1469 // 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10.
1470 bool IsIPAddressReserved(const IPAddressNumber& host_addr) {
1471 static const unsigned char kReservedIPv4[][5] = {
1472 { 0,0,0,0,8 }, { 10,0,0,0,8 }, { 100,64,0,0,10 }, { 127,0,0,0,8 },
1473 { 169,254,0,0,16 }, { 172,16,0,0,12 }, { 192,0,2,0,24 }, { 192,88,99,0,24 },
1474 { 192,168,0,0,16 }, { 198,18,0,0,15 }, { 198,51,100,0,24 },
1475 { 203,0,113,0,24 }, { 224,0,0,0,3 }
Ryan Sleevi 2013/08/12 21:11:51 style nit: four spaces
felt 2013/08/13 04:17:06 Done.
1476 };
1477 static const unsigned char kReservedIPv6[][17] = {
1478 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8 },
1479 { 0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
1480 { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
1481 { 0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3 },
1482 { 0xe0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 },
1483 { 0xf0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 },
1484 { 0xf8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 },
1485 { 0xfc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7 },
1486 { 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 },
1487 { 0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
1488 { 0xfe,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
Ryan Sleevi 2013/08/12 21:11:51 style nit: four spaces
felt 2013/08/13 04:17:06 Done.
1489 };
1490 size_t array_size = 0;
1491 const unsigned char* array = NULL;
1492 switch (host_addr.size()) {
1493 case kIPv4AddressSize:
1494 array_size = arraysize(kReservedIPv4);
1495 array = kReservedIPv4[0];
1496 break;
1497 case kIPv6AddressSize:
1498 array_size = arraysize(kReservedIPv6);
1499 array = kReservedIPv6[0];
1500 break;
1501 }
1502 if (!array)
1503 return false;
1504 int width = host_addr.size()+1;
Ryan Sleevi 2013/08/12 21:11:51 style nit: "host_addr.size()+1" -> "host_addr.size
felt 2013/08/13 04:17:06 Done.
1505 for (size_t i = 0; i < array_size*width; i = i + width) {
Ryan Sleevi 2013/08/12 21:11:51 style nit: "array_size*width" -> "array_size * wid
felt 2013/08/13 04:17:06 is it generally preferred to avoid indexing, or is
Ryan Sleevi 2013/08/13 20:45:39 Shorter and more readable. Forms like (&foo[bar])[
1506 if (IPNumberPrefixCheck(
1507 host_addr, &array[i], (&array[i])[width-1])) {
1508 return true;
1509 }
1510 }
1511 return false;
1512 }
1513
1428 // Extracts the address and port portions of a sockaddr. 1514 // Extracts the address and port portions of a sockaddr.
1429 bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr, 1515 bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr,
1430 socklen_t sock_addr_len, 1516 socklen_t sock_addr_len,
1431 const uint8** address, 1517 const uint8** address,
1432 size_t* address_len, 1518 size_t* address_len,
1433 uint16* port) { 1519 uint16* port) {
1434 if (sock_addr->sa_family == AF_INET) { 1520 if (sock_addr->sa_family == AF_INET) {
1435 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in))) 1521 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in)))
1436 return false; 1522 return false;
1437 const struct sockaddr_in* addr = 1523 const struct sockaddr_in* addr =
(...skipping 551 matching lines...) Expand 10 before | Expand all | Expand 10 after
1989 if (ip_number.size() != ip_prefix.size()) { 2075 if (ip_number.size() != ip_prefix.size()) {
1990 if (ip_number.size() == 4) { 2076 if (ip_number.size() == 4) {
1991 return IPNumberMatchesPrefix(ConvertIPv4NumberToIPv6Number(ip_number), 2077 return IPNumberMatchesPrefix(ConvertIPv4NumberToIPv6Number(ip_number),
1992 ip_prefix, prefix_length_in_bits); 2078 ip_prefix, prefix_length_in_bits);
1993 } 2079 }
1994 return IPNumberMatchesPrefix(ip_number, 2080 return IPNumberMatchesPrefix(ip_number,
1995 ConvertIPv4NumberToIPv6Number(ip_prefix), 2081 ConvertIPv4NumberToIPv6Number(ip_prefix),
1996 96 + prefix_length_in_bits); 2082 96 + prefix_length_in_bits);
1997 } 2083 }
1998 2084
1999 // Otherwise we are comparing two IPv4 addresses, or two IPv6 addresses. 2085 return IPNumberPrefixCheck(ip_number, &ip_prefix[0], prefix_length_in_bits);
2000 // Compare all the bytes that fall entirely within the prefix.
2001 int num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
2002 for (int i = 0; i < num_entire_bytes_in_prefix; ++i) {
2003 if (ip_number[i] != ip_prefix[i])
2004 return false;
2005 }
2006
2007 // In case the prefix was not a multiple of 8, there will be 1 byte
2008 // which is only partially masked.
2009 int remaining_bits = prefix_length_in_bits % 8;
2010 if (remaining_bits != 0) {
2011 unsigned char mask = 0xFF << (8 - remaining_bits);
2012 int i = num_entire_bytes_in_prefix;
2013 if ((ip_number[i] & mask) != (ip_prefix[i] & mask))
2014 return false;
2015 }
2016
2017 return true;
2018 } 2086 }
2019 2087
2020 const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address, 2088 const uint16* GetPortFieldFromSockaddr(const struct sockaddr* address,
2021 socklen_t address_len) { 2089 socklen_t address_len) {
2022 if (address->sa_family == AF_INET) { 2090 if (address->sa_family == AF_INET) {
2023 DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len)); 2091 DCHECK_LE(sizeof(sockaddr_in), static_cast<size_t>(address_len));
2024 const struct sockaddr_in* sockaddr = 2092 const struct sockaddr_in* sockaddr =
2025 reinterpret_cast<const struct sockaddr_in*>(address); 2093 reinterpret_cast<const struct sockaddr_in*>(address);
2026 return &sockaddr->sin_port; 2094 return &sockaddr->sin_port;
2027 } else if (address->sa_family == AF_INET6) { 2095 } else if (address->sa_family == AF_INET6) {
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 2149
2082 NetworkInterface::NetworkInterface(const std::string& name, 2150 NetworkInterface::NetworkInterface(const std::string& name,
2083 const IPAddressNumber& address) 2151 const IPAddressNumber& address)
2084 : name(name), address(address) { 2152 : name(name), address(address) {
2085 } 2153 }
2086 2154
2087 NetworkInterface::~NetworkInterface() { 2155 NetworkInterface::~NetworkInterface() {
2088 } 2156 }
2089 2157
2090 } // namespace net 2158 } // namespace net
OLDNEW
« net/base/net_util.h ('K') | « net/base/net_util.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698