| 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/ip_address_number.h" | 5 #include "net/base/ip_address_number.h" |
| 6 | 6 |
| 7 #include <limits.h> | 7 #include <limits.h> |
| 8 | 8 |
| 9 #include "base/logging.h" | 9 #include "base/logging.h" |
| 10 #include "base/strings/string_number_conversions.h" | 10 #include "base/strings/string_number_conversions.h" |
| 11 #include "base/strings/string_piece.h" | 11 #include "base/strings/string_piece.h" |
| 12 #include "base/strings/string_split.h" | 12 #include "base/strings/string_split.h" |
| 13 #include "base/strings/string_util.h" | 13 #include "base/strings/string_util.h" |
| 14 #include "base/strings/stringprintf.h" | 14 #include "base/strings/stringprintf.h" |
| 15 #include "url/gurl.h" | 15 #include "url/gurl.h" |
| 16 #include "url/url_canon_ip.h" | 16 #include "url/url_canon_ip.h" |
| 17 | 17 |
| 18 namespace net { | 18 namespace net { |
| 19 | 19 |
| 20 namespace { | |
| 21 | |
| 22 bool IPNumberPrefixCheck(const IPAddressNumber& ip_number, | |
| 23 const unsigned char* ip_prefix, | |
| 24 size_t prefix_length_in_bits) { | |
| 25 // Compare all the bytes that fall entirely within the prefix. | |
| 26 int num_entire_bytes_in_prefix = prefix_length_in_bits / 8; | |
| 27 for (int i = 0; i < num_entire_bytes_in_prefix; ++i) { | |
| 28 if (ip_number[i] != ip_prefix[i]) | |
| 29 return false; | |
| 30 } | |
| 31 | |
| 32 // In case the prefix was not a multiple of 8, there will be 1 byte | |
| 33 // which is only partially masked. | |
| 34 int remaining_bits = prefix_length_in_bits % 8; | |
| 35 if (remaining_bits != 0) { | |
| 36 unsigned char mask = 0xFF << (8 - remaining_bits); | |
| 37 int i = num_entire_bytes_in_prefix; | |
| 38 if ((ip_number[i] & mask) != (ip_prefix[i] & mask)) | |
| 39 return false; | |
| 40 } | |
| 41 return true; | |
| 42 } | |
| 43 | |
| 44 } // namespace | |
| 45 | |
| 46 // Don't compare IPv4 and IPv6 addresses (they have different range | |
| 47 // reservations). Keep separate reservation arrays for each IP type, and | |
| 48 // consolidate adjacent reserved ranges within a reservation array when | |
| 49 // possible. | |
| 50 // Sources for info: | |
| 51 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml | |
| 52 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml | |
| 53 // They're formatted here with the prefix as the last element. For example: | |
| 54 // 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10. | |
| 55 bool IsIPAddressReserved(const IPAddressNumber& host_addr) { | |
| 56 static const unsigned char kReservedIPv4[][5] = { | |
| 57 { 0,0,0,0,8 }, { 10,0,0,0,8 }, { 100,64,0,0,10 }, { 127,0,0,0,8 }, | |
| 58 { 169,254,0,0,16 }, { 172,16,0,0,12 }, { 192,0,2,0,24 }, | |
| 59 { 192,88,99,0,24 }, { 192,168,0,0,16 }, { 198,18,0,0,15 }, | |
| 60 { 198,51,100,0,24 }, { 203,0,113,0,24 }, { 224,0,0,0,3 } | |
| 61 }; | |
| 62 static const unsigned char kReservedIPv6[][17] = { | |
| 63 { 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,8 }, | |
| 64 { 0x40,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 }, | |
| 65 { 0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,2 }, | |
| 66 { 0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,3 }, | |
| 67 { 0xe0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,4 }, | |
| 68 { 0xf0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5 }, | |
| 69 { 0xf8,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,6 }, | |
| 70 { 0xfc,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,7 }, | |
| 71 { 0xfe,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,9 }, | |
| 72 { 0xfe,0x80,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 }, | |
| 73 { 0xfe,0xc0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,10 }, | |
| 74 }; | |
| 75 size_t array_size = 0; | |
| 76 const unsigned char* array = NULL; | |
| 77 switch (host_addr.size()) { | |
| 78 case kIPv4AddressSize: | |
| 79 array_size = arraysize(kReservedIPv4); | |
| 80 array = kReservedIPv4[0]; | |
| 81 break; | |
| 82 case kIPv6AddressSize: | |
| 83 array_size = arraysize(kReservedIPv6); | |
| 84 array = kReservedIPv6[0]; | |
| 85 break; | |
| 86 } | |
| 87 if (!array) | |
| 88 return false; | |
| 89 size_t width = host_addr.size() + 1; | |
| 90 for (size_t i = 0; i < array_size; ++i, array += width) { | |
| 91 if (IPNumberPrefixCheck(host_addr, array, array[width-1])) | |
| 92 return true; | |
| 93 } | |
| 94 return false; | |
| 95 } | |
| 96 | |
| 97 std::string IPAddressToString(const uint8_t* address, size_t address_len) { | 20 std::string IPAddressToString(const uint8_t* address, size_t address_len) { |
| 98 std::string str; | 21 std::string str; |
| 99 url::StdStringCanonOutput output(&str); | 22 url::StdStringCanonOutput output(&str); |
| 100 | 23 |
| 101 if (address_len == kIPv4AddressSize) { | 24 if (address_len == kIPv4AddressSize) { |
| 102 url::AppendIPv4Address(address, &output); | 25 url::AppendIPv4Address(address, &output); |
| 103 } else if (address_len == kIPv6AddressSize) { | 26 } else if (address_len == kIPv6AddressSize) { |
| 104 url::AppendIPv6Address(address, &output); | 27 url::AppendIPv6Address(address, &output); |
| 105 } | 28 } |
| 106 | 29 |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 address.begin() + arraysize(kIPv4MappedPrefix), | 112 address.begin() + arraysize(kIPv4MappedPrefix), |
| 190 kIPv4MappedPrefix); | 113 kIPv4MappedPrefix); |
| 191 } | 114 } |
| 192 | 115 |
| 193 IPAddressNumber ConvertIPv4MappedToIPv4(const IPAddressNumber& address) { | 116 IPAddressNumber ConvertIPv4MappedToIPv4(const IPAddressNumber& address) { |
| 194 DCHECK(IsIPv4Mapped(address)); | 117 DCHECK(IsIPv4Mapped(address)); |
| 195 return IPAddressNumber(address.begin() + arraysize(kIPv4MappedPrefix), | 118 return IPAddressNumber(address.begin() + arraysize(kIPv4MappedPrefix), |
| 196 address.end()); | 119 address.end()); |
| 197 } | 120 } |
| 198 | 121 |
| 199 bool IPNumberMatchesPrefix(const IPAddressNumber& ip_number, | |
| 200 const IPAddressNumber& ip_prefix, | |
| 201 size_t prefix_length_in_bits) { | |
| 202 // Both the input IP address and the prefix IP address should be | |
| 203 // either IPv4 or IPv6. | |
| 204 DCHECK(ip_number.size() == 4 || ip_number.size() == 16); | |
| 205 DCHECK(ip_prefix.size() == 4 || ip_prefix.size() == 16); | |
| 206 | |
| 207 DCHECK_LE(prefix_length_in_bits, ip_prefix.size() * 8); | |
| 208 | |
| 209 // In case we have an IPv6 / IPv4 mismatch, convert the IPv4 addresses to | |
| 210 // IPv6 addresses in order to do the comparison. | |
| 211 if (ip_number.size() != ip_prefix.size()) { | |
| 212 if (ip_number.size() == 4) { | |
| 213 return IPNumberMatchesPrefix(ConvertIPv4NumberToIPv6Number(ip_number), | |
| 214 ip_prefix, prefix_length_in_bits); | |
| 215 } | |
| 216 return IPNumberMatchesPrefix(ip_number, | |
| 217 ConvertIPv4NumberToIPv6Number(ip_prefix), | |
| 218 96 + prefix_length_in_bits); | |
| 219 } | |
| 220 | |
| 221 return IPNumberPrefixCheck(ip_number, &ip_prefix[0], prefix_length_in_bits); | |
| 222 } | |
| 223 | |
| 224 unsigned CommonPrefixLength(const IPAddressNumber& a1, | 122 unsigned CommonPrefixLength(const IPAddressNumber& a1, |
| 225 const IPAddressNumber& a2) { | 123 const IPAddressNumber& a2) { |
| 226 DCHECK_EQ(a1.size(), a2.size()); | 124 DCHECK_EQ(a1.size(), a2.size()); |
| 227 for (size_t i = 0; i < a1.size(); ++i) { | 125 for (size_t i = 0; i < a1.size(); ++i) { |
| 228 unsigned diff = a1[i] ^ a2[i]; | 126 unsigned diff = a1[i] ^ a2[i]; |
| 229 if (!diff) | 127 if (!diff) |
| 230 continue; | 128 continue; |
| 231 for (unsigned j = 0; j < CHAR_BIT; ++j) { | 129 for (unsigned j = 0; j < CHAR_BIT; ++j) { |
| 232 if (diff & (1 << (CHAR_BIT - 1))) | 130 if (diff & (1 << (CHAR_BIT - 1))) |
| 233 return i * CHAR_BIT + j; | 131 return i * CHAR_BIT + j; |
| 234 diff <<= 1; | 132 diff <<= 1; |
| 235 } | 133 } |
| 236 NOTREACHED(); | 134 NOTREACHED(); |
| 237 } | 135 } |
| 238 return a1.size() * CHAR_BIT; | 136 return a1.size() * CHAR_BIT; |
| 239 } | 137 } |
| 240 | 138 |
| 241 unsigned MaskPrefixLength(const IPAddressNumber& mask) { | 139 unsigned MaskPrefixLength(const IPAddressNumber& mask) { |
| 242 IPAddressNumber all_ones(mask.size(), 0xFF); | 140 IPAddressNumber all_ones(mask.size(), 0xFF); |
| 243 return CommonPrefixLength(mask, all_ones); | 141 return CommonPrefixLength(mask, all_ones); |
| 244 } | 142 } |
| 245 | 143 |
| 246 } // namespace net | 144 } // namespace net |
| OLD | NEW |