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

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

Issue 156963003: Support replacement of IP address resolutions via command line flag (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: remove use of back() and front() string methods Created 6 years, 10 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
(Empty)
1 // Copyright (c) 2014 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_pattern.h"
6
7 #include "base/logging.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/stl_util.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/string_split.h"
12 #include "base/strings/string_tokenizer.h"
13
14 namespace net {
15
16 class IPPattern::ComponentPattern {
17 public:
18 ComponentPattern();
19 void AppendRange(uint32 min, uint32 max);
20 bool Match(uint32 value) const;
21
22 private:
23 struct Range {
24 public:
25 Range(uint32 min, uint32 max) : minimum(min), maximum(max) {}
26 uint32 minimum;
27 uint32 maximum;
28 };
29 typedef std::vector<Range> RangeVector;
30
31 RangeVector ranges_;
32
33 DISALLOW_COPY_AND_ASSIGN(ComponentPattern);
34 };
35
36 IPPattern::ComponentPattern::ComponentPattern() {}
37
38 void IPPattern::ComponentPattern::AppendRange(uint32 min, uint32 max) {
39 ranges_.push_back(Range(min, max));
40 }
41
42 bool IPPattern::ComponentPattern::Match(uint32 value) const {
43 // Simple linear search should be fine, as we usually only have very few
44 // distinct ranges to test.
45 for (RangeVector::const_iterator range_it = ranges_.begin();
46 range_it != ranges_.end(); ++range_it) {
47 if (range_it->maximum >= value && range_it->minimum <= value)
48 return true;
49 }
50 return false;
51 }
52
53 IPPattern::IPPattern() : is_ipv4_(true) {}
54
55 IPPattern::~IPPattern() {
56 ::STLDeleteElements(&component_patterns_);
wtc 2014/02/19 00:24:11 Nit: omit :: in this case.
jar (doing other things) 2014/02/19 02:47:04 Done.
57 }
58
59 bool IPPattern::Match(const IPAddressNumber& address) const {
60 if (ip_mask_.empty())
61 return false;
62 bool address_is_ipv4 = address.size() == kIPv4AddressSize;
63 if (address_is_ipv4 != is_ipv4_)
64 return false;
65
66 ComponentPatternList::const_iterator pattern_it(component_patterns_.begin());
67 int fixed_value_index = 0;
68 // IPv6 |address| vectors have 16 pieces, while our |ip_mask_| has only
69 // 8, so it is easier to count separately.
70 int address_index = 0;
71 for (size_t i = 0; i < ip_mask_.size(); ++i) {
72 uint32 value_to_test = address[address_index++];
73 if (!is_ipv4_) {
74 value_to_test = (value_to_test << 8) + address[address_index++];
75 }
76 if (ip_mask_[i]) {
77 if (component_values_[fixed_value_index++] != value_to_test)
78 return false;
79 continue;
80 }
81 if (!(*pattern_it)->Match(value_to_test))
82 return false;
83 ++pattern_it;
84 }
85 return true;
86 }
87
88 bool IPPattern::ParsePattern(const std::string& ip_pattern) {
89 DCHECK(ip_mask_.empty());
90 if (ip_pattern.find(':') != std::string::npos) {
91 is_ipv4_ = false;
92 }
93 Strings components;
94 base::SplitString(ip_pattern, is_ipv4_ ? '.' : ':', &components);
95 if (components.size() != (is_ipv4_ ? 4u : 8u)) {
96 DVLOG(1) << "Invalid component count: " << ip_pattern;
97 return false;
98 }
99 for (Strings::iterator component_it = components.begin();
100 component_it != components.end(); ++component_it) {
101 if (component_it->empty()) {
102 DVLOG(1) << "Empty component: " << ip_pattern;
103 return false;
104 }
105 if (*component_it == "*") {
106 // Let standard code handle this below.
107 *component_it = is_ipv4_ ? "[0-255]" : "[0-FFFF]";
108 } else if ((*component_it)[0] != '[') {
109 // This value will just have a specific integer to match.
110 uint32 value;
111 if (!ValueTextToInt(*component_it, &value))
112 return false;
113 ip_mask_.push_back(true);
114 component_values_.push_back(value);
115 continue;
116 }
117 if ((*component_it)[component_it->size() - 1] != ']') {
118 DVLOG(1) << "Missing close bracket: " << ip_pattern;
119 return false;
120 }
121 // Now we know the size() is at least 2.
122 if (component_it->size() == 2) {
123 DVLOG(1) << "Empty bracket: " << ip_pattern;
124 return false;
125 }
126 // We'll need a pattern to match this bracketed component.
127 scoped_ptr<ComponentPattern> component_pattern(new ComponentPattern);
128 // Trim leading and trailing bracket before calling for parsing.
129 if (!ParseComponentPattern(base::StringPiece(component_it->data() + 1,
130 component_it->size() - 2), component_pattern.get())) {
131 return false;
132 }
133 ip_mask_.push_back(false);
134 component_patterns_.push_back(component_pattern.release());
135 }
136 return true;
137 }
138
139 bool IPPattern::ParseComponentPattern(const base::StringPiece& text,
140 ComponentPattern* pattern) const {
141 // We're given a comma separated set of ranges, some of which may be simple
142 // constants.
143 Strings ranges;
144 base::SplitString(text.as_string(), ',', &ranges);
145 for (Strings::iterator range_it = ranges.begin();
146 range_it != ranges.end(); ++range_it) {
147 base::StringTokenizer range_pair(*range_it, "-");
148 uint32 min = 0;
149 range_pair.GetNext();
150 if (!ValueTextToInt(range_pair.token(), &min))
151 return false;
152 uint32 max = min; // Sometimes we have no distinct max.
153 if (range_pair.GetNext()) {
154 if (!ValueTextToInt(range_pair.token(), &max))
155 return false;
156 }
157 if (range_pair.GetNext()) {
158 // Too many "-" in this range specifier.
159 DVLOG(1) << "Too many hyphens in range: ";
160 return false;
161 }
162 pattern->AppendRange(min, max);
163 }
164 return true;
165 }
166
167 bool IPPattern::ValueTextToInt(const base::StringPiece& input,
168 uint32* output) const {
169 bool ok = is_ipv4_ ? base::StringToUint(input, output) :
170 base::HexStringToUInt(input, output);
171 if (!ok) {
172 DVLOG(1) << "Could not convert value to number: " << input;
wtc 2014/02/19 00:24:11 This is missing a "return false" statement.
jar (doing other things) 2014/02/19 02:47:04 Done.
173 }
174 if (is_ipv4_ && *output > 255u) {
175 DVLOG(1) << "IPv4 component greater than 255";
176 return false;
177 }
178 if (!is_ipv4_ && *output > 0xFFFFu) {
179 DVLOG(1) << "IPv6 component greater than 0xFFFF";
180 return false;
181 }
182 return ok;
183 }
184
185 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698