OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/base/ip_address.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 #include "base/strings/string_number_conversions.h" |
| 9 #include "base/strings/string_split.h" |
| 10 #include "base/strings/stringprintf.h" |
| 11 #include "base/sys_byteorder.h" |
| 12 #include "url/gurl.h" |
| 13 #include "url/url_canon_ip.h" |
| 14 |
| 15 namespace net { |
| 16 |
| 17 const unsigned char IPAddress::kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, |
| 18 0, 0, 0, 0, 0xFF, 0xFF}; |
| 19 |
| 20 IPAddress::IPAddress() {} |
| 21 |
| 22 IPAddress::~IPAddress() {} |
| 23 |
| 24 IPAddress::IPAddress(std::vector<unsigned char>& ip_address) |
| 25 : ip_address_(ip_address) {} |
| 26 |
| 27 // Don't compare IPv4 and IPv6 addresses (they have different range |
| 28 // reservations). Keep separate reservation arrays for each IP type, and |
| 29 // consolidate adjacent reserved ranges within a reservation array when |
| 30 // possible. |
| 31 // Sources for info: |
| 32 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml |
| 33 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml |
| 34 // They're formatted here with the prefix as the last element. For example: |
| 35 // 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10. |
| 36 bool IPAddress::IsIPAddressReserved() const { |
| 37 static const unsigned char kReservedIPv4[][5] = { |
| 38 {0, 0, 0, 0, 8}, {10, 0, 0, 0, 8}, {100, 64, 0, 0, 10}, |
| 39 {127, 0, 0, 0, 8}, {169, 254, 0, 0, 16}, {172, 16, 0, 0, 12}, |
| 40 {192, 0, 2, 0, 24}, {192, 88, 99, 0, 24}, {192, 168, 0, 0, 16}, |
| 41 {198, 18, 0, 0, 15}, {198, 51, 100, 0, 24}, {203, 0, 113, 0, 24}, |
| 42 {224, 0, 0, 0, 3}}; |
| 43 static const unsigned char kReservedIPv6[][17] = { |
| 44 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8}, |
| 45 {0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, |
| 46 {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2}, |
| 47 {0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3}, |
| 48 {0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4}, |
| 49 {0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5}, |
| 50 {0xf8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6}, |
| 51 {0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7}, |
| 52 {0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9}, |
| 53 {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, |
| 54 {0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10}, |
| 55 }; |
| 56 size_t array_size = 0; |
| 57 const unsigned char* array = NULL; |
| 58 switch (ip_address_.size()) { |
| 59 case kIPv4AddressSize: |
| 60 array_size = arraysize(kReservedIPv4); |
| 61 array = kReservedIPv4[0]; |
| 62 break; |
| 63 case kIPv6AddressSize: |
| 64 array_size = arraysize(kReservedIPv6); |
| 65 array = kReservedIPv6[0]; |
| 66 break; |
| 67 } |
| 68 if (!array) |
| 69 return false; |
| 70 size_t width = ip_address_.size() + 1; |
| 71 for (size_t i = 0; i < array_size; ++i, array += width) { |
| 72 if (IPAddressPrefixCheck(array, array[width - 1])) |
| 73 return true; |
| 74 } |
| 75 return false; |
| 76 } |
| 77 |
| 78 std::string IPAddress::ToString() const { |
| 79 std::string str; |
| 80 url::StdStringCanonOutput output(&str); |
| 81 |
| 82 if (IsIPv4()) { |
| 83 url::AppendIPv4Address(&ip_address_.front(), &output); |
| 84 } else if (IsIPv6()) { |
| 85 url::AppendIPv6Address(&ip_address_.front(), &output); |
| 86 } else { |
| 87 size_t address_len = ip_address_.size(); |
| 88 CHECK(false) << "Invalid IP address with length: " << address_len; |
| 89 } |
| 90 |
| 91 output.Complete(); |
| 92 return str; |
| 93 } |
| 94 |
| 95 std::string IPAddress::ToStringWithPort(uint16_t port) const { |
| 96 std::string address_str = ToString(); |
| 97 |
| 98 if (IsIPv6()) { |
| 99 // Need to bracket IPv6 addresses since they contain colons. |
| 100 return base::StringPrintf("[%s]:%d", address_str.c_str(), port); |
| 101 } |
| 102 return base::StringPrintf("%s:%d", address_str.c_str(), port); |
| 103 } |
| 104 |
| 105 std::string IPAddress::ToPackedString() const { |
| 106 return std::string(reinterpret_cast<const char*>(&ip_address_.front()), |
| 107 ip_address_.size()); |
| 108 } |
| 109 |
| 110 // Returns number of matching initial bits between the addresses and |other|. |
| 111 unsigned IPAddress::CommonPrefixLength(const IPAddress& other) const { |
| 112 DCHECK_EQ(ip_address_.size(), other.ip_address_.size()); |
| 113 for (size_t i = 0; i < ip_address_.size(); ++i) { |
| 114 unsigned diff = ip_address_[i] ^ other.ip_address_[i]; |
| 115 if (!diff) |
| 116 continue; |
| 117 for (unsigned j = 0; j < CHAR_BIT; ++j) { |
| 118 if (diff & (1 << (CHAR_BIT - 1))) |
| 119 return i * CHAR_BIT + j; |
| 120 diff <<= 1; |
| 121 } |
| 122 NOTREACHED(); |
| 123 } |
| 124 return ip_address_.size() * CHAR_BIT; |
| 125 } |
| 126 |
| 127 // Computes the number of leading 1-bits in |ip_address_|. |
| 128 unsigned IPAddress::MaskPrefixLength() const { |
| 129 std::vector<unsigned char> all_ones_mask(ip_address_.size(), 0xFF); |
| 130 IPAddress all_ones(all_ones_mask); |
| 131 return all_ones.CommonPrefixLength(all_ones); |
| 132 } |
| 133 |
| 134 bool IPAddress::IsIPv4Mapped() const { |
| 135 if (!IsIPv6()) |
| 136 return false; |
| 137 return std::equal(ip_address_.begin(), |
| 138 ip_address_.begin() + arraysize(kIPv4MappedPrefix), |
| 139 kIPv4MappedPrefix); |
| 140 } |
| 141 |
| 142 AddressFamily IPAddress::GetAddressFamily() const { |
| 143 switch (ip_address_.size()) { |
| 144 case kIPv4AddressSize: |
| 145 return ADDRESS_FAMILY_IPV4; |
| 146 case kIPv6AddressSize: |
| 147 return ADDRESS_FAMILY_IPV6; |
| 148 default: |
| 149 return ADDRESS_FAMILY_UNSPECIFIED; |
| 150 } |
| 151 } |
| 152 |
| 153 bool IPAddress::MatchesPrefix(const IPAddress& ip_prefix, |
| 154 size_t prefix_length_in_bits) { |
| 155 // Both the input IP address and the prefix IP address should be |
| 156 // either IPv4 or IPv6. |
| 157 DCHECK(IsIPv4() || IsIPv6()); |
| 158 DCHECK(ip_prefix.IsIPv4() || ip_prefix.IsIPv6()); |
| 159 |
| 160 DCHECK_LE(prefix_length_in_bits, ip_prefix.ip_address_.size() * 8); |
| 161 |
| 162 // In case we have an IPv6 / IPv4 mismatch, convert the IPv4 addresses to |
| 163 // IPv6 addresses in order to do the comparison. |
| 164 if (ip_address_.size() != ip_prefix.ip_address_.size()) { |
| 165 if (IsIPv4()) { |
| 166 IPAddress temp = IPAddress::ConvertIPv4ToIPv6(*this); |
| 167 return temp.MatchesPrefix(ip_prefix, prefix_length_in_bits); |
| 168 } |
| 169 IPAddress temp = IPAddress::ConvertIPv4ToIPv6(ip_prefix); |
| 170 return MatchesPrefix(temp, 96 + prefix_length_in_bits); |
| 171 } |
| 172 |
| 173 return IPAddressPrefixCheck(&ip_prefix, prefix_length_in_bits); |
| 174 } |
| 175 |
| 176 bool IPAddress::ToSockAddrWithPort(struct sockaddr* address, |
| 177 socklen_t* address_length, |
| 178 int port) const { |
| 179 DCHECK(address); |
| 180 DCHECK(address_length); |
| 181 switch (ip_address_.size()) { |
| 182 case kIPv4AddressSize: { |
| 183 socklen_t kSockaddrInSize = sizeof(struct sockaddr_in); |
| 184 if (*address_length < kSockaddrInSize) |
| 185 return false; |
| 186 *address_length = kSockaddrInSize; |
| 187 struct sockaddr_in* addr = reinterpret_cast<struct sockaddr_in*>(address); |
| 188 memset(addr, 0, sizeof(struct sockaddr_in)); |
| 189 addr->sin_family = AF_INET; |
| 190 addr->sin_port = base::HostToNet16(port); |
| 191 memcpy(&addr->sin_addr, &ip_address_[0], kIPv4AddressSize); |
| 192 break; |
| 193 } |
| 194 case kIPv6AddressSize: { |
| 195 socklen_t kSockaddrInSize = sizeof(struct sockaddr_in6); |
| 196 if (*address_length < kSockaddrInSize) |
| 197 return false; |
| 198 *address_length = kSockaddrInSize; |
| 199 struct sockaddr_in6* addr6 = |
| 200 reinterpret_cast<struct sockaddr_in6*>(address); |
| 201 memset(addr6, 0, sizeof(struct sockaddr_in6)); |
| 202 addr6->sin6_family = AF_INET6; |
| 203 addr6->sin6_port = base::HostToNet16(port); |
| 204 memcpy(&addr6->sin6_addr, &ip_address_[0], kIPv6AddressSize); |
| 205 break; |
| 206 } |
| 207 default: |
| 208 return false; |
| 209 } |
| 210 return true; |
| 211 } |
| 212 |
| 213 // static |
| 214 bool IPAddress::FromURLHostname(const std::string& hostname, |
| 215 IPAddress* ip_address) { |
| 216 // |hostname| is an already canoncalized hostname, conforming to RFC 3986. |
| 217 // For an IP address, this is defined in Section 3.2.2 of RFC 3986, with |
| 218 // the canonical form for IPv6 addresses defined in Section 4 of RFC 5952. |
| 219 url::Component host_comp(0, hostname.size()); |
| 220 |
| 221 std::vector<unsigned char> ip; |
| 222 |
| 223 // If it has a bracket, try parsing it as an IPv6 address. |
| 224 if (hostname[0] == '[') { |
| 225 ip.resize(16); // 128 bits. |
| 226 bool result = |
| 227 url::IPv6AddressToNumber(hostname.data(), host_comp, &(ip)[0]); |
| 228 ip_address->ip_address_ = ip; |
| 229 return result; |
| 230 } |
| 231 |
| 232 // Otherwise, try IPv4. |
| 233 ip.resize(4); // 32 bits. |
| 234 int num_components; |
| 235 url::CanonHostInfo::Family family = url::IPv4AddressToNumber( |
| 236 hostname.data(), host_comp, &(ip)[0], &num_components); |
| 237 ip_address->ip_address_ = ip; |
| 238 return family == url::CanonHostInfo::IPV4; |
| 239 } |
| 240 |
| 241 // static |
| 242 bool IPAddress::FromIPLiteral(const base::StringPiece& ip_literal, |
| 243 IPAddress* ip_address) { |
| 244 std::vector<unsigned char> ip; |
| 245 |
| 246 // |ip_literal| could be either a IPv4 or an IPv6 literal. If it contains |
| 247 // a colon however, it must be an IPv6 address. |
| 248 if (ip_literal.find(':') != base::StringPiece::npos) { |
| 249 // GURL expects IPv6 hostnames to be surrounded with brackets. |
| 250 std::string host_brackets = "["; |
| 251 ip_literal.AppendToString(&host_brackets); |
| 252 host_brackets.push_back(']'); |
| 253 url::Component host_comp(0, host_brackets.size()); |
| 254 |
| 255 // Try parsing the hostname as an IPv6 literal. |
| 256 ip.resize(16); // 128 bits. |
| 257 bool result = |
| 258 url::IPv6AddressToNumber(host_brackets.data(), host_comp, &(ip)[0]); |
| 259 ip_address->ip_address_ = ip; |
| 260 return result; |
| 261 } |
| 262 |
| 263 // Otherwise the string is an IPv4 address. |
| 264 ip.resize(4); // 32 bits. |
| 265 url::Component host_comp(0, ip_literal.size()); |
| 266 int num_components; |
| 267 url::CanonHostInfo::Family family = url::IPv4AddressToNumber( |
| 268 ip_literal.data(), host_comp, &(ip)[0], &num_components); |
| 269 |
| 270 ip_address->ip_address_ = ip; |
| 271 return family == url::CanonHostInfo::IPV4; |
| 272 } |
| 273 |
| 274 // static |
| 275 bool IPAddress::FromCIDRBlock(const std::string& cidr_literal, |
| 276 IPAddress* ip_address, |
| 277 size_t* prefix_length_in_bits) { |
| 278 // We expect CIDR notation to match one of these two templates: |
| 279 // <IPv4-literal> "/" <number of bits> |
| 280 // <IPv6-literal> "/" <number of bits> |
| 281 |
| 282 std::vector<base::StringPiece> parts = base::SplitStringPiece( |
| 283 cidr_literal, "/", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL); |
| 284 if (parts.size() != 2) |
| 285 return false; |
| 286 |
| 287 // Parse the IP address. |
| 288 if (!IPAddress::FromIPLiteral(parts[0], ip_address)) |
| 289 return false; |
| 290 |
| 291 // Parse the prefix length. |
| 292 int number_of_bits = -1; |
| 293 if (!base::StringToInt(parts[1], &number_of_bits)) |
| 294 return false; |
| 295 |
| 296 // Make sure the prefix length is in a valid range. |
| 297 if (number_of_bits < 0 || |
| 298 number_of_bits > static_cast<int>(ip_address->ip_address_.size() * 8)) |
| 299 return false; |
| 300 |
| 301 *prefix_length_in_bits = static_cast<size_t>(number_of_bits); |
| 302 return true; |
| 303 } |
| 304 |
| 305 // static |
| 306 IPAddress IPAddress::FromLegacy(const IPAddressNumber& ip_address) { |
| 307 std::vector<unsigned char> address_copy(ip_address); |
| 308 IPAddress new_address(address_copy); |
| 309 return new_address; |
| 310 } |
| 311 |
| 312 // static |
| 313 IPAddress IPAddress::ConvertIPv4ToIPv6(const IPAddress& ipv4_address) { |
| 314 DCHECK(ipv4_address.IsIPv4()); |
| 315 |
| 316 // IPv4-mapped addresses are formed by: |
| 317 // <80 bits of zeros> + <16 bits of ones> + <32-bit IPv4 address>. |
| 318 std::vector<unsigned char> ipv6_address; |
| 319 ipv6_address.reserve(16); |
| 320 ipv6_address.insert(ipv6_address.end(), kIPv4MappedPrefix, |
| 321 kIPv4MappedPrefix + arraysize(kIPv4MappedPrefix)); |
| 322 ipv6_address.insert(ipv6_address.end(), ipv4_address.ip_address_.begin(), |
| 323 ipv4_address.ip_address_.end()); |
| 324 return IPAddress(ipv6_address); |
| 325 } |
| 326 |
| 327 // static |
| 328 IPAddress IPAddress::ConvertIPv4MappedToIPv4(const IPAddress& address) { |
| 329 DCHECK(address.IsIPv4Mapped()); |
| 330 std::vector<unsigned char> without_prefix( |
| 331 address.ip_address_.begin() + arraysize(kIPv4MappedPrefix), |
| 332 address.ip_address_.end()); |
| 333 IPAddress ip_address(without_prefix); |
| 334 return ip_address; |
| 335 } |
| 336 |
| 337 bool IPAddress::operator==(const IPAddress& that) const { |
| 338 return ip_address_ == that.ip_address_; |
| 339 } |
| 340 |
| 341 bool IPAddress::operator!=(const IPAddress& that) const { |
| 342 return ip_address_ != that.ip_address_; |
| 343 } |
| 344 |
| 345 bool IPAddress::operator<(const IPAddress& that) const { |
| 346 // Sort IPv4 before IPv6. |
| 347 if (ip_address_.size() != that.ip_address_.size()) { |
| 348 return ip_address_.size() < that.ip_address_.size(); |
| 349 } |
| 350 |
| 351 return ip_address_ < that.ip_address_; |
| 352 } |
| 353 |
| 354 bool IPAddress::operator>(const IPAddress& that) const { |
| 355 // Sort IPv4 after IPv6. |
| 356 if (ip_address_.size() != that.ip_address_.size()) { |
| 357 return ip_address_.size() > that.ip_address_.size(); |
| 358 } |
| 359 |
| 360 return ip_address_ > that.ip_address_; |
| 361 } |
| 362 |
| 363 bool IPAddress::IPAddressPrefixCheck(const IPAddress* ip_prefix, |
| 364 size_t prefix_length_in_bits) const { |
| 365 return IPAddressPrefixCheck(&(ip_prefix->ip_address_)[0], |
| 366 prefix_length_in_bits); |
| 367 } |
| 368 |
| 369 bool IPAddress::IPAddressPrefixCheck(const unsigned char* ip_prefix, |
| 370 size_t prefix_length_in_bits) const { |
| 371 // Compare all the bytes that fall entirely within the prefix. |
| 372 int num_entire_bytes_in_prefix = prefix_length_in_bits / 8; |
| 373 for (int i = 0; i < num_entire_bytes_in_prefix; ++i) { |
| 374 if (ip_address_[i] != ip_prefix[i]) |
| 375 return false; |
| 376 } |
| 377 |
| 378 // In case the prefix was not a multiple of 8, there will be 1 byte |
| 379 // which is only partially masked. |
| 380 int remaining_bits = prefix_length_in_bits % 8; |
| 381 if (remaining_bits != 0) { |
| 382 unsigned char mask = 0xFF << (8 - remaining_bits); |
| 383 int i = num_entire_bytes_in_prefix; |
| 384 if ((ip_address_[i] & mask) != (ip_prefix[i] & mask)) |
| 385 return false; |
| 386 } |
| 387 return true; |
| 388 } |
| 389 |
| 390 } // namespace net |
OLD | NEW |