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

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: Rewrote IsIPAddressReserved to avoid conversions 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
« no previous file with comments | « net/base/net_util.h ('k') | net/base/net_util_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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, &host_addr))
1411 return false;
1412 switch (host_info.family) {
1413 case url_canon::CanonHostInfo::IPV4:
1414 return IsIPAddressReserved(host_addr, true);
1415 case url_canon::CanonHostInfo::IPV6:
1416 return IsIPAddressReserved(host_addr, false);
1417 case url_canon::CanonHostInfo::NEUTRAL:
1418 case url_canon::CanonHostInfo::BROKEN:
1419 return false;
1420 }
1421 }
1412 1422
1413 // Check for a registry controlled portion of |hostname|, ignoring private 1423 // Check for a registry controlled portion of |hostname|, ignoring private
1414 // registries, as they already chain to ICANN-administered registries, 1424 // registries, as they already chain to ICANN-administered registries,
1415 // and explicitly ignoring unknown registries. 1425 // and explicitly ignoring unknown registries.
1416 // 1426 //
1417 // Note: This means that as new gTLDs are introduced on the Internet, they 1427 // 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 1428 // will be treated as non-unique until the registry controlled domain list
1419 // is updated. However, because gTLDs are expected to provide significant 1429 // is updated. However, because gTLDs are expected to provide significant
1420 // advance notice to deprecate older versions of this code, this an 1430 // advance notice to deprecate older versions of this code, this an
1421 // acceptable tradeoff. 1431 // acceptable tradeoff.
1422 return 0 == registry_controlled_domains::GetRegistryLength( 1432 return 0 == registry_controlled_domains::GetRegistryLength(
1423 canonical_name, 1433 canonical_name,
1424 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES, 1434 registry_controlled_domains::EXCLUDE_UNKNOWN_REGISTRIES,
1425 registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 1435 registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
1426 } 1436 }
1427 1437
1438 bool IsIPAddressReserved(const IPAddressNumber& host_addr, bool ipv4) {
1439 // We shouldn't compare IPv4 to IPv6 (they have different range
1440 // reservations), so we keep separate arrays.
1441 // Within each array, adjacent ranges are consolidated when possible.
1442 // Sources for info:
1443 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
1444 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
1445 // They're formatted here with the prefix as the last element. For example:
1446 // 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10.
1447 unsigned char reserved_ipv4[][5] = {
1448 { 0,0,0,0,8 }, { 10,0,0,0,8 }, { 100,64,0,0,10 }, { 127,0,0,0,8 },
1449 { 169,254,0,0,16 }, { 172,16,0,0,12 }, { 192,0,2,0,24 }, { 192,88,99,0,24 },
1450 { 192,168,0,0,16 }, { 198,18,0,0,15 }, { 198,51,100,0,24 },
1451 { 203,0,113,0,24 }, { 224,0,0,0,3 }
1452 };
1453 unsigned char reserved_ipv6[][17] = {
1454 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8 },
1455 { 0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
1456 { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 },
1457 { 0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3 },
1458 { 0xe0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 },
1459 { 0xf0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 },
1460 { 0xf8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 },
1461 { 0xfc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7 },
1462 { 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 },
1463 { 0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
1464 { 0xfe,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 },
1465 };
1466
1467 // Code altered from IPNumberMatchesPrefix; we don't call it directly to avoid
1468 // unnecessary parsing and conversions.
1469 size_t arr_size = (ipv4) ?
1470 arraysize(reserved_ipv4) : arraysize(reserved_ipv6);
1471 for (size_t i = 0; i < arr_size; ++i) {
1472 bool match = true;
1473 int prefix;
1474 if (ipv4)
1475 prefix = reserved_ipv4[i][4];
1476 else
1477 prefix = reserved_ipv6[i][16];
1478 // Compare all the bytes that fall entirely within the prefix.
1479 int num_entire_bytes_in_prefix = prefix / 8;
1480 for (int j = 0; j < num_entire_bytes_in_prefix; ++j) {
1481 if (ipv4 && (host_addr[j] != reserved_ipv4[i][j])) {
1482 match = false;
1483 } else if (!ipv4 && (host_addr[j] != reserved_ipv6[i][j])) {
1484 match = false;
1485 }
1486 }
1487 // In case the prefix was not a multiple of 8, there will be 1 byte
1488 // which is only partially masked.
1489 int remaining_bits = prefix % 8;
1490 if (remaining_bits != 0) {
1491 unsigned char mask = 0xFF << (8 - remaining_bits);
1492 int j = num_entire_bytes_in_prefix;
1493 if (ipv4 && ((host_addr[j] & mask) != (reserved_ipv4[i][j] & mask))) {
1494 match = false;
1495 } else if (!ipv4 &&
1496 ((host_addr[j] & mask) != (reserved_ipv6[i][j] & mask))) {
1497 match = false;
1498 }
1499 }
1500 if (match)
1501 return true;
1502 }
1503 return false;
1504 }
1505
1428 // Extracts the address and port portions of a sockaddr. 1506 // Extracts the address and port portions of a sockaddr.
1429 bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr, 1507 bool GetIPAddressFromSockAddr(const struct sockaddr* sock_addr,
1430 socklen_t sock_addr_len, 1508 socklen_t sock_addr_len,
1431 const uint8** address, 1509 const uint8** address,
1432 size_t* address_len, 1510 size_t* address_len,
1433 uint16* port) { 1511 uint16* port) {
1434 if (sock_addr->sa_family == AF_INET) { 1512 if (sock_addr->sa_family == AF_INET) {
1435 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in))) 1513 if (sock_addr_len < static_cast<socklen_t>(sizeof(struct sockaddr_in)))
1436 return false; 1514 return false;
1437 const struct sockaddr_in* addr = 1515 const struct sockaddr_in* addr =
(...skipping 643 matching lines...) Expand 10 before | Expand all | Expand 10 after
2081 2159
2082 NetworkInterface::NetworkInterface(const std::string& name, 2160 NetworkInterface::NetworkInterface(const std::string& name,
2083 const IPAddressNumber& address) 2161 const IPAddressNumber& address)
2084 : name(name), address(address) { 2162 : name(name), address(address) {
2085 } 2163 }
2086 2164
2087 NetworkInterface::~NetworkInterface() { 2165 NetworkInterface::~NetworkInterface() {
2088 } 2166 }
2089 2167
2090 } // namespace net 2168 } // namespace net
OLDNEW
« no previous file with comments | « 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