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

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

Issue 1886043002: Update IPAddress::IsReserved() ranges. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: comments eroman Created 4 years, 8 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
« no previous file with comments | « no previous file | net/base/ip_address_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) 2015 The Chromium Authors. All rights reserved. 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 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.h" 5 #include "net/base/ip_address.h"
6 6
7 #include "base/strings/string_piece.h" 7 #include "base/strings/string_piece.h"
8 #include "base/strings/string_split.h" 8 #include "base/strings/string_split.h"
9 #include "net/base/ip_address_number.h" 9 #include "net/base/ip_address_number.h"
10 #include "net/base/parse_number.h" 10 #include "net/base/parse_number.h"
11 #include "url/gurl.h" 11 #include "url/gurl.h"
12 #include "url/url_canon_ip.h" 12 #include "url/url_canon_ip.h"
13 13
14 namespace { 14 namespace {
15 15
16 // The prefix for IPv6 mapped IPv4 addresses. 16 // The prefix for IPv6 mapped IPv4 addresses.
17 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2 17 // https://tools.ietf.org/html/rfc4291#section-2.5.5.2
18 const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF}; 18 const uint8_t kIPv4MappedPrefix[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF};
19 19
20 // Note that this function assumes:
21 // * |ip_address| is at least |prefix_length_in_bits| (bits) long;
22 // * |ip_prefix| is at least |prefix_length_in_bits| (bits) long.
20 bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address, 23 bool IPAddressPrefixCheck(const std::vector<uint8_t>& ip_address,
21 const unsigned char* ip_prefix, 24 const uint8_t* ip_prefix,
22 size_t prefix_length_in_bits) { 25 size_t prefix_length_in_bits) {
23 // Compare all the bytes that fall entirely within the prefix. 26 // Compare all the bytes that fall entirely within the prefix.
24 int num_entire_bytes_in_prefix = prefix_length_in_bits / 8; 27 size_t num_entire_bytes_in_prefix = prefix_length_in_bits / 8;
25 for (int i = 0; i < num_entire_bytes_in_prefix; ++i) { 28 for (size_t i = 0; i < num_entire_bytes_in_prefix; ++i) {
26 if (ip_address[i] != ip_prefix[i]) 29 if (ip_address[i] != ip_prefix[i])
27 return false; 30 return false;
28 } 31 }
29 32
30 // In case the prefix was not a multiple of 8, there will be 1 byte 33 // In case the prefix was not a multiple of 8, there will be 1 byte
31 // which is only partially masked. 34 // which is only partially masked.
32 int remaining_bits = prefix_length_in_bits % 8; 35 size_t remaining_bits = prefix_length_in_bits % 8;
33 if (remaining_bits != 0) { 36 if (remaining_bits != 0) {
34 unsigned char mask = 0xFF << (8 - remaining_bits); 37 uint8_t mask = 0xFF << (8 - remaining_bits);
35 int i = num_entire_bytes_in_prefix; 38 size_t i = num_entire_bytes_in_prefix;
36 if ((ip_address[i] & mask) != (ip_prefix[i] & mask)) 39 if ((ip_address[i] & mask) != (ip_prefix[i] & mask))
37 return false; 40 return false;
38 } 41 }
39 return true; 42 return true;
40 } 43 }
41 44
45 // Returns true if |ip_address| matches any of the reserved IPv4 ranges. This
46 // method operates on a blacklist of reserved IPv4 ranges. Some ranges are
47 // consolidated.
48 // Sources for info:
49 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
50 // www.iana.org/assignments/iana-ipv4-special-registry/
51 // iana-ipv4-special-registry.xhtml
52 bool IsReservedIPv4(const std::vector<uint8_t>& ip_address) {
53 // Different IP versions have different range reservations.
54 DCHECK_EQ(net::IPAddress::kIPv4AddressSize, ip_address.size());
55 struct {
56 const uint8_t address[4];
57 size_t prefix_length_in_bits;
58 } static const kReservedIPv4Ranges[] = {
59 {{0, 0, 0, 0}, 8}, {{10, 0, 0, 0}, 8}, {{100, 64, 0, 0}, 10},
60 {{127, 0, 0, 0}, 8}, {{169, 254, 0, 0}, 16}, {{172, 16, 0, 0}, 12},
61 {{192, 0, 2, 0}, 24}, {{192, 88, 99, 0}, 24}, {{192, 168, 0, 0}, 16},
62 {{198, 18, 0, 0}, 15}, {{198, 51, 100, 0}, 24}, {{203, 0, 113, 0}, 24},
63 {{224, 0, 0, 0}, 3}};
64
65 for (const auto& range : kReservedIPv4Ranges) {
66 if (IPAddressPrefixCheck(ip_address, range.address,
67 range.prefix_length_in_bits)) {
68 return true;
69 }
70 }
71
72 return false;
73 }
74
75 // Returns true if |ip_address| matches any of the reserved IPv6 ranges. This
76 // method operates on a whitelist of non-reserved IPv6 ranges. All IPv6
77 // addresses outside these ranges are reserved.
78 // Sources for info:
79 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
80 bool IsReservedIPv6(const std::vector<uint8_t>& ip_address) {
81 // Different IP versions have different range reservations.
82 DCHECK_EQ(net::IPAddress::kIPv6AddressSize, ip_address.size());
83 struct {
84 const uint8_t address_prefix[2];
85 size_t prefix_length_in_bits;
86 } static const kPublicIPv6Ranges[] = {
87 // 2000::/3 -- Global Unicast
88 {{0x20, 0}, 3},
89 // ff00::/8 -- Multicast
90 {{0xff, 0}, 8},
91 };
92
93 for (const auto& range : kPublicIPv6Ranges) {
94 if (IPAddressPrefixCheck(ip_address, range.address_prefix,
95 range.prefix_length_in_bits)) {
96 return false;
97 }
98 }
99
100 return true;
101 }
102
42 } // namespace 103 } // namespace
43 104
44 namespace net { 105 namespace net {
45 106
46 IPAddress::IPAddress() {} 107 IPAddress::IPAddress() {}
47 108
48 IPAddress::IPAddress(const IPAddressNumber& address) : ip_address_(address) {} 109 IPAddress::IPAddress(const IPAddressNumber& address) : ip_address_(address) {}
49 110
50 IPAddress::IPAddress(const IPAddress& other) = default; 111 IPAddress::IPAddress(const IPAddress& other) = default;
51 112
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 } 149 }
89 150
90 bool IPAddress::IsIPv6() const { 151 bool IPAddress::IsIPv6() const {
91 return ip_address_.size() == kIPv6AddressSize; 152 return ip_address_.size() == kIPv6AddressSize;
92 } 153 }
93 154
94 bool IPAddress::IsValid() const { 155 bool IPAddress::IsValid() const {
95 return IsIPv4() || IsIPv6(); 156 return IsIPv4() || IsIPv6();
96 } 157 }
97 158
98 // Don't compare IPv4 and IPv6 addresses (they have different range
99 // reservations). Keep separate reservation arrays for each IP type, and
100 // consolidate adjacent reserved ranges within a reservation array when
101 // possible.
102 // Sources for info:
103 // www.iana.org/assignments/ipv4-address-space/ipv4-address-space.xhtml
104 // www.iana.org/assignments/ipv6-address-space/ipv6-address-space.xhtml
105 // They're formatted here with the prefix as the last element. For example:
106 // 10.0.0.0/8 becomes 10,0,0,0,8 and fec0::/10 becomes 0xfe,0xc0,0,0,0...,10.
107 bool IPAddress::IsReserved() const { 159 bool IPAddress::IsReserved() const {
108 static const unsigned char kReservedIPv4[][5] = { 160 if (IsIPv4()) {
109 {0, 0, 0, 0, 8}, {10, 0, 0, 0, 8}, {100, 64, 0, 0, 10}, 161 return IsReservedIPv4(ip_address_);
110 {127, 0, 0, 0, 8}, {169, 254, 0, 0, 16}, {172, 16, 0, 0, 12}, 162 } else if (IsIPv6()) {
111 {192, 0, 2, 0, 24}, {192, 88, 99, 0, 24}, {192, 168, 0, 0, 16}, 163 return IsReservedIPv6(ip_address_);
112 {198, 18, 0, 0, 15}, {198, 51, 100, 0, 24}, {203, 0, 113, 0, 24},
113 {224, 0, 0, 0, 3}};
114 static const unsigned char kReservedIPv6[][17] = {
115 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8},
116 {0x40, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
117 {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2},
118 {0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3},
119 {0xe0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4},
120 {0xf0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5},
121 {0xf8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6},
122 {0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7},
123 {0xfe, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9},
124 {0xfe, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10},
125 {0xfe, 0xc0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 10},
126 };
127 size_t array_size = 0;
128 const unsigned char* array = nullptr;
129 switch (ip_address_.size()) {
130 case kIPv4AddressSize:
131 array_size = arraysize(kReservedIPv4);
132 array = kReservedIPv4[0];
133 break;
134 case kIPv6AddressSize:
135 array_size = arraysize(kReservedIPv6);
136 array = kReservedIPv6[0];
137 break;
138 }
139 if (!array)
140 return false;
141 size_t width = ip_address_.size() + 1;
142 for (size_t i = 0; i < array_size; ++i, array += width) {
143 if (IPAddressPrefixCheck(ip_address_, array, array[width - 1]))
144 return true;
145 } 164 }
146 return false; 165 return false;
147 } 166 }
148 167
149 bool IPAddress::IsZero() const { 168 bool IPAddress::IsZero() const {
150 for (auto x : ip_address_) { 169 for (auto x : ip_address_) {
151 if (x != 0) 170 if (x != 0)
152 return false; 171 return false;
153 } 172 }
154 173
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 334
316 unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) { 335 unsigned CommonPrefixLength(const IPAddress& a1, const IPAddress& a2) {
317 return CommonPrefixLength(a1.bytes(), a2.bytes()); 336 return CommonPrefixLength(a1.bytes(), a2.bytes());
318 } 337 }
319 338
320 unsigned MaskPrefixLength(const IPAddress& mask) { 339 unsigned MaskPrefixLength(const IPAddress& mask) {
321 return MaskPrefixLength(mask.bytes()); 340 return MaskPrefixLength(mask.bytes());
322 } 341 }
323 342
324 } // namespace net 343 } // namespace net
OLDNEW
« no previous file with comments | « no previous file | net/base/ip_address_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698