xref: /aosp_15_r20/external/cronet/url/url_canon_ip.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker // Copyright 2013 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker 
5*6777b538SAndroid Build Coastguard Worker #include "url/url_canon_ip.h"
6*6777b538SAndroid Build Coastguard Worker 
7*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdlib.h>
9*6777b538SAndroid Build Coastguard Worker 
10*6777b538SAndroid Build Coastguard Worker #include <limits>
11*6777b538SAndroid Build Coastguard Worker 
12*6777b538SAndroid Build Coastguard Worker #include "base/check.h"
13*6777b538SAndroid Build Coastguard Worker #include "url/url_canon_internal.h"
14*6777b538SAndroid Build Coastguard Worker #include "url/url_features.h"
15*6777b538SAndroid Build Coastguard Worker 
16*6777b538SAndroid Build Coastguard Worker namespace url {
17*6777b538SAndroid Build Coastguard Worker 
18*6777b538SAndroid Build Coastguard Worker namespace {
19*6777b538SAndroid Build Coastguard Worker 
20*6777b538SAndroid Build Coastguard Worker // Converts one of the character types that represent a numerical base to the
21*6777b538SAndroid Build Coastguard Worker // corresponding base.
BaseForType(SharedCharTypes type)22*6777b538SAndroid Build Coastguard Worker int BaseForType(SharedCharTypes type) {
23*6777b538SAndroid Build Coastguard Worker   switch (type) {
24*6777b538SAndroid Build Coastguard Worker     case CHAR_HEX:
25*6777b538SAndroid Build Coastguard Worker       return 16;
26*6777b538SAndroid Build Coastguard Worker     case CHAR_DEC:
27*6777b538SAndroid Build Coastguard Worker       return 10;
28*6777b538SAndroid Build Coastguard Worker     case CHAR_OCT:
29*6777b538SAndroid Build Coastguard Worker       return 8;
30*6777b538SAndroid Build Coastguard Worker     default:
31*6777b538SAndroid Build Coastguard Worker       return 0;
32*6777b538SAndroid Build Coastguard Worker   }
33*6777b538SAndroid Build Coastguard Worker }
34*6777b538SAndroid Build Coastguard Worker 
35*6777b538SAndroid Build Coastguard Worker // Converts an IPv4 component to a 32-bit number, while checking for overflow.
36*6777b538SAndroid Build Coastguard Worker //
37*6777b538SAndroid Build Coastguard Worker // Possible return values:
38*6777b538SAndroid Build Coastguard Worker // - IPV4    - The number was valid, and did not overflow.
39*6777b538SAndroid Build Coastguard Worker // - BROKEN  - The input was numeric, but too large for a 32-bit field.
40*6777b538SAndroid Build Coastguard Worker // - NEUTRAL - Input was not numeric.
41*6777b538SAndroid Build Coastguard Worker //
42*6777b538SAndroid Build Coastguard Worker // The input is assumed to be ASCII. The components are assumed to be non-empty.
43*6777b538SAndroid Build Coastguard Worker template<typename CHAR>
IPv4ComponentToNumber(const CHAR * spec,const Component & component,uint32_t * number)44*6777b538SAndroid Build Coastguard Worker CanonHostInfo::Family IPv4ComponentToNumber(const CHAR* spec,
45*6777b538SAndroid Build Coastguard Worker                                             const Component& component,
46*6777b538SAndroid Build Coastguard Worker                                             uint32_t* number) {
47*6777b538SAndroid Build Coastguard Worker   // Empty components are considered non-numeric.
48*6777b538SAndroid Build Coastguard Worker   if (component.is_empty())
49*6777b538SAndroid Build Coastguard Worker     return CanonHostInfo::NEUTRAL;
50*6777b538SAndroid Build Coastguard Worker 
51*6777b538SAndroid Build Coastguard Worker   // Figure out the base
52*6777b538SAndroid Build Coastguard Worker   SharedCharTypes base;
53*6777b538SAndroid Build Coastguard Worker   int base_prefix_len = 0;  // Size of the prefix for this base.
54*6777b538SAndroid Build Coastguard Worker   if (spec[component.begin] == '0') {
55*6777b538SAndroid Build Coastguard Worker     // Either hex or dec, or a standalone zero.
56*6777b538SAndroid Build Coastguard Worker     if (component.len == 1) {
57*6777b538SAndroid Build Coastguard Worker       base = CHAR_DEC;
58*6777b538SAndroid Build Coastguard Worker     } else if (spec[component.begin + 1] == 'X' ||
59*6777b538SAndroid Build Coastguard Worker                spec[component.begin + 1] == 'x') {
60*6777b538SAndroid Build Coastguard Worker       base = CHAR_HEX;
61*6777b538SAndroid Build Coastguard Worker       base_prefix_len = 2;
62*6777b538SAndroid Build Coastguard Worker     } else {
63*6777b538SAndroid Build Coastguard Worker       base = CHAR_OCT;
64*6777b538SAndroid Build Coastguard Worker       base_prefix_len = 1;
65*6777b538SAndroid Build Coastguard Worker     }
66*6777b538SAndroid Build Coastguard Worker   } else {
67*6777b538SAndroid Build Coastguard Worker     base = CHAR_DEC;
68*6777b538SAndroid Build Coastguard Worker   }
69*6777b538SAndroid Build Coastguard Worker 
70*6777b538SAndroid Build Coastguard Worker   // Extend the prefix to consume all leading zeros.
71*6777b538SAndroid Build Coastguard Worker   while (base_prefix_len < component.len &&
72*6777b538SAndroid Build Coastguard Worker          spec[component.begin + base_prefix_len] == '0')
73*6777b538SAndroid Build Coastguard Worker     base_prefix_len++;
74*6777b538SAndroid Build Coastguard Worker 
75*6777b538SAndroid Build Coastguard Worker   // Put the component, minus any base prefix, into a NULL-terminated buffer so
76*6777b538SAndroid Build Coastguard Worker   // we can call the standard library. Because leading zeros have already been
77*6777b538SAndroid Build Coastguard Worker   // discarded, filling the entire buffer is guaranteed to trigger the 32-bit
78*6777b538SAndroid Build Coastguard Worker   // overflow check.
79*6777b538SAndroid Build Coastguard Worker   const int kMaxComponentLen = 16;
80*6777b538SAndroid Build Coastguard Worker   char buf[kMaxComponentLen + 1];  // digits + '\0'
81*6777b538SAndroid Build Coastguard Worker   int dest_i = 0;
82*6777b538SAndroid Build Coastguard Worker   bool may_be_broken_octal = false;
83*6777b538SAndroid Build Coastguard Worker   for (int i = component.begin + base_prefix_len; i < component.end(); i++) {
84*6777b538SAndroid Build Coastguard Worker     if (spec[i] >= 0x80)
85*6777b538SAndroid Build Coastguard Worker       return CanonHostInfo::NEUTRAL;
86*6777b538SAndroid Build Coastguard Worker 
87*6777b538SAndroid Build Coastguard Worker     // We know the input is 7-bit, so convert to narrow (if this is the wide
88*6777b538SAndroid Build Coastguard Worker     // version of the template) by casting.
89*6777b538SAndroid Build Coastguard Worker     char input = static_cast<char>(spec[i]);
90*6777b538SAndroid Build Coastguard Worker 
91*6777b538SAndroid Build Coastguard Worker     // Validate that this character is OK for the given base.
92*6777b538SAndroid Build Coastguard Worker     if (!IsCharOfType(input, base)) {
93*6777b538SAndroid Build Coastguard Worker       if (IsCharOfType(input, CHAR_DEC)) {
94*6777b538SAndroid Build Coastguard Worker         // Entirely numeric components with leading 0s that aren't octal are
95*6777b538SAndroid Build Coastguard Worker         // considered broken.
96*6777b538SAndroid Build Coastguard Worker         may_be_broken_octal = true;
97*6777b538SAndroid Build Coastguard Worker       } else {
98*6777b538SAndroid Build Coastguard Worker         return CanonHostInfo::NEUTRAL;
99*6777b538SAndroid Build Coastguard Worker       }
100*6777b538SAndroid Build Coastguard Worker     }
101*6777b538SAndroid Build Coastguard Worker 
102*6777b538SAndroid Build Coastguard Worker     // Fill the buffer, if there's space remaining. This check allows us to
103*6777b538SAndroid Build Coastguard Worker     // verify that all characters are numeric, even those that don't fit.
104*6777b538SAndroid Build Coastguard Worker     if (dest_i < kMaxComponentLen)
105*6777b538SAndroid Build Coastguard Worker       buf[dest_i++] = input;
106*6777b538SAndroid Build Coastguard Worker   }
107*6777b538SAndroid Build Coastguard Worker 
108*6777b538SAndroid Build Coastguard Worker   if (may_be_broken_octal)
109*6777b538SAndroid Build Coastguard Worker     return CanonHostInfo::BROKEN;
110*6777b538SAndroid Build Coastguard Worker 
111*6777b538SAndroid Build Coastguard Worker   buf[dest_i] = '\0';
112*6777b538SAndroid Build Coastguard Worker 
113*6777b538SAndroid Build Coastguard Worker   // Use the 64-bit strtoi so we get a big number (no hex, decimal, or octal
114*6777b538SAndroid Build Coastguard Worker   // number can overflow a 64-bit number in <= 16 characters).
115*6777b538SAndroid Build Coastguard Worker   uint64_t num = _strtoui64(buf, NULL, BaseForType(base));
116*6777b538SAndroid Build Coastguard Worker 
117*6777b538SAndroid Build Coastguard Worker   // Check for 32-bit overflow.
118*6777b538SAndroid Build Coastguard Worker   if (num > std::numeric_limits<uint32_t>::max())
119*6777b538SAndroid Build Coastguard Worker     return CanonHostInfo::BROKEN;
120*6777b538SAndroid Build Coastguard Worker 
121*6777b538SAndroid Build Coastguard Worker   // No overflow. Success!
122*6777b538SAndroid Build Coastguard Worker   *number = static_cast<uint32_t>(num);
123*6777b538SAndroid Build Coastguard Worker   return CanonHostInfo::IPV4;
124*6777b538SAndroid Build Coastguard Worker }
125*6777b538SAndroid Build Coastguard Worker 
126*6777b538SAndroid Build Coastguard Worker // See declaration of IPv4AddressToNumber for documentation.
127*6777b538SAndroid Build Coastguard Worker template <typename CHAR, typename UCHAR>
DoIPv4AddressToNumber(const CHAR * spec,Component host,unsigned char address[4],int * num_ipv4_components)128*6777b538SAndroid Build Coastguard Worker CanonHostInfo::Family DoIPv4AddressToNumber(const CHAR* spec,
129*6777b538SAndroid Build Coastguard Worker                                             Component host,
130*6777b538SAndroid Build Coastguard Worker                                             unsigned char address[4],
131*6777b538SAndroid Build Coastguard Worker                                             int* num_ipv4_components) {
132*6777b538SAndroid Build Coastguard Worker   // Ignore terminal dot, if present.
133*6777b538SAndroid Build Coastguard Worker   if (host.is_nonempty() && spec[host.end() - 1] == '.')
134*6777b538SAndroid Build Coastguard Worker     --host.len;
135*6777b538SAndroid Build Coastguard Worker 
136*6777b538SAndroid Build Coastguard Worker   // Do nothing if empty.
137*6777b538SAndroid Build Coastguard Worker   if (host.is_empty())
138*6777b538SAndroid Build Coastguard Worker     return CanonHostInfo::NEUTRAL;
139*6777b538SAndroid Build Coastguard Worker 
140*6777b538SAndroid Build Coastguard Worker   // Read component values.  The first `existing_components` of them are
141*6777b538SAndroid Build Coastguard Worker   // populated front to back, with the first one corresponding to the last
142*6777b538SAndroid Build Coastguard Worker   // component, which allows for early exit if the last component isn't a
143*6777b538SAndroid Build Coastguard Worker   // number.
144*6777b538SAndroid Build Coastguard Worker   uint32_t component_values[4];
145*6777b538SAndroid Build Coastguard Worker   int existing_components = 0;
146*6777b538SAndroid Build Coastguard Worker 
147*6777b538SAndroid Build Coastguard Worker   int current_component_end = host.end();
148*6777b538SAndroid Build Coastguard Worker   int current_position = current_component_end;
149*6777b538SAndroid Build Coastguard Worker   while (true) {
150*6777b538SAndroid Build Coastguard Worker     // If this is not the first character of a component, go to the next
151*6777b538SAndroid Build Coastguard Worker     // component.
152*6777b538SAndroid Build Coastguard Worker     if (current_position != host.begin && spec[current_position - 1] != '.') {
153*6777b538SAndroid Build Coastguard Worker       --current_position;
154*6777b538SAndroid Build Coastguard Worker       continue;
155*6777b538SAndroid Build Coastguard Worker     }
156*6777b538SAndroid Build Coastguard Worker 
157*6777b538SAndroid Build Coastguard Worker     CanonHostInfo::Family family = IPv4ComponentToNumber(
158*6777b538SAndroid Build Coastguard Worker         spec,
159*6777b538SAndroid Build Coastguard Worker         Component(current_position, current_component_end - current_position),
160*6777b538SAndroid Build Coastguard Worker         &component_values[existing_components]);
161*6777b538SAndroid Build Coastguard Worker 
162*6777b538SAndroid Build Coastguard Worker     // If `family` is NEUTRAL and this is the last component, return NEUTRAL. If
163*6777b538SAndroid Build Coastguard Worker     // `family` is NEUTRAL but not the last component, this is considered a
164*6777b538SAndroid Build Coastguard Worker     // BROKEN IPv4 address, as opposed to a non-IPv4 hostname.
165*6777b538SAndroid Build Coastguard Worker     if (family == CanonHostInfo::NEUTRAL && existing_components == 0)
166*6777b538SAndroid Build Coastguard Worker       return CanonHostInfo::NEUTRAL;
167*6777b538SAndroid Build Coastguard Worker 
168*6777b538SAndroid Build Coastguard Worker     if (family != CanonHostInfo::IPV4)
169*6777b538SAndroid Build Coastguard Worker       return CanonHostInfo::BROKEN;
170*6777b538SAndroid Build Coastguard Worker 
171*6777b538SAndroid Build Coastguard Worker     ++existing_components;
172*6777b538SAndroid Build Coastguard Worker 
173*6777b538SAndroid Build Coastguard Worker     // If this is the final component, nothing else to do.
174*6777b538SAndroid Build Coastguard Worker     if (current_position == host.begin)
175*6777b538SAndroid Build Coastguard Worker       break;
176*6777b538SAndroid Build Coastguard Worker 
177*6777b538SAndroid Build Coastguard Worker     // If there are more than 4 components, fail.
178*6777b538SAndroid Build Coastguard Worker     if (existing_components == 4)
179*6777b538SAndroid Build Coastguard Worker       return CanonHostInfo::BROKEN;
180*6777b538SAndroid Build Coastguard Worker 
181*6777b538SAndroid Build Coastguard Worker     current_component_end = current_position - 1;
182*6777b538SAndroid Build Coastguard Worker     --current_position;
183*6777b538SAndroid Build Coastguard Worker   }
184*6777b538SAndroid Build Coastguard Worker 
185*6777b538SAndroid Build Coastguard Worker   // Use `component_values` to fill out the 4-component IP address.
186*6777b538SAndroid Build Coastguard Worker 
187*6777b538SAndroid Build Coastguard Worker   // First, process all components but the last, while making sure each fits
188*6777b538SAndroid Build Coastguard Worker   // within an 8-bit field.
189*6777b538SAndroid Build Coastguard Worker   for (int i = existing_components - 1; i > 0; i--) {
190*6777b538SAndroid Build Coastguard Worker     if (component_values[i] > std::numeric_limits<uint8_t>::max())
191*6777b538SAndroid Build Coastguard Worker       return CanonHostInfo::BROKEN;
192*6777b538SAndroid Build Coastguard Worker     address[existing_components - i - 1] =
193*6777b538SAndroid Build Coastguard Worker         static_cast<unsigned char>(component_values[i]);
194*6777b538SAndroid Build Coastguard Worker   }
195*6777b538SAndroid Build Coastguard Worker 
196*6777b538SAndroid Build Coastguard Worker   uint32_t last_value = component_values[0];
197*6777b538SAndroid Build Coastguard Worker   for (int i = 3; i >= existing_components - 1; i--) {
198*6777b538SAndroid Build Coastguard Worker     address[i] = static_cast<unsigned char>(last_value);
199*6777b538SAndroid Build Coastguard Worker     last_value >>= 8;
200*6777b538SAndroid Build Coastguard Worker   }
201*6777b538SAndroid Build Coastguard Worker 
202*6777b538SAndroid Build Coastguard Worker   // If the last component has residual bits, report overflow.
203*6777b538SAndroid Build Coastguard Worker   if (last_value != 0)
204*6777b538SAndroid Build Coastguard Worker     return CanonHostInfo::BROKEN;
205*6777b538SAndroid Build Coastguard Worker 
206*6777b538SAndroid Build Coastguard Worker   // Tell the caller how many components we saw.
207*6777b538SAndroid Build Coastguard Worker   *num_ipv4_components = existing_components;
208*6777b538SAndroid Build Coastguard Worker 
209*6777b538SAndroid Build Coastguard Worker   // Success!
210*6777b538SAndroid Build Coastguard Worker   return CanonHostInfo::IPV4;
211*6777b538SAndroid Build Coastguard Worker }
212*6777b538SAndroid Build Coastguard Worker 
213*6777b538SAndroid Build Coastguard Worker // Return true if we've made a final IPV4/BROKEN decision, false if the result
214*6777b538SAndroid Build Coastguard Worker // is NEUTRAL, and we could use a second opinion.
215*6777b538SAndroid Build Coastguard Worker template<typename CHAR, typename UCHAR>
DoCanonicalizeIPv4Address(const CHAR * spec,const Component & host,CanonOutput * output,CanonHostInfo * host_info)216*6777b538SAndroid Build Coastguard Worker bool DoCanonicalizeIPv4Address(const CHAR* spec,
217*6777b538SAndroid Build Coastguard Worker                                const Component& host,
218*6777b538SAndroid Build Coastguard Worker                                CanonOutput* output,
219*6777b538SAndroid Build Coastguard Worker                                CanonHostInfo* host_info) {
220*6777b538SAndroid Build Coastguard Worker   host_info->family = IPv4AddressToNumber(
221*6777b538SAndroid Build Coastguard Worker       spec, host, host_info->address, &host_info->num_ipv4_components);
222*6777b538SAndroid Build Coastguard Worker 
223*6777b538SAndroid Build Coastguard Worker   switch (host_info->family) {
224*6777b538SAndroid Build Coastguard Worker     case CanonHostInfo::IPV4:
225*6777b538SAndroid Build Coastguard Worker       // Definitely an IPv4 address.
226*6777b538SAndroid Build Coastguard Worker       host_info->out_host.begin = output->length();
227*6777b538SAndroid Build Coastguard Worker       AppendIPv4Address(host_info->address, output);
228*6777b538SAndroid Build Coastguard Worker       host_info->out_host.len = output->length() - host_info->out_host.begin;
229*6777b538SAndroid Build Coastguard Worker       return true;
230*6777b538SAndroid Build Coastguard Worker     case CanonHostInfo::BROKEN:
231*6777b538SAndroid Build Coastguard Worker       // Definitely broken.
232*6777b538SAndroid Build Coastguard Worker       return true;
233*6777b538SAndroid Build Coastguard Worker     default:
234*6777b538SAndroid Build Coastguard Worker       // Could be IPv6 or a hostname.
235*6777b538SAndroid Build Coastguard Worker       return false;
236*6777b538SAndroid Build Coastguard Worker   }
237*6777b538SAndroid Build Coastguard Worker }
238*6777b538SAndroid Build Coastguard Worker 
239*6777b538SAndroid Build Coastguard Worker // Helper class that describes the main components of an IPv6 input string.
240*6777b538SAndroid Build Coastguard Worker // See the following examples to understand how it breaks up an input string:
241*6777b538SAndroid Build Coastguard Worker //
242*6777b538SAndroid Build Coastguard Worker // [Example 1]: input = "[::aa:bb]"
243*6777b538SAndroid Build Coastguard Worker //  ==> num_hex_components = 2
244*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[0] = Component(3,2) "aa"
245*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[1] = Component(6,2) "bb"
246*6777b538SAndroid Build Coastguard Worker //  ==> index_of_contraction = 0
247*6777b538SAndroid Build Coastguard Worker //  ==> ipv4_component = Component(0, -1)
248*6777b538SAndroid Build Coastguard Worker //
249*6777b538SAndroid Build Coastguard Worker // [Example 2]: input = "[1:2::3:4:5]"
250*6777b538SAndroid Build Coastguard Worker //  ==> num_hex_components = 5
251*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[0] = Component(1,1) "1"
252*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[1] = Component(3,1) "2"
253*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[2] = Component(6,1) "3"
254*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[3] = Component(8,1) "4"
255*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[4] = Component(10,1) "5"
256*6777b538SAndroid Build Coastguard Worker //  ==> index_of_contraction = 2
257*6777b538SAndroid Build Coastguard Worker //  ==> ipv4_component = Component(0, -1)
258*6777b538SAndroid Build Coastguard Worker //
259*6777b538SAndroid Build Coastguard Worker // [Example 3]: input = "[::ffff:192.168.0.1]"
260*6777b538SAndroid Build Coastguard Worker //  ==> num_hex_components = 1
261*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[0] = Component(3,4) "ffff"
262*6777b538SAndroid Build Coastguard Worker //  ==> index_of_contraction = 0
263*6777b538SAndroid Build Coastguard Worker //  ==> ipv4_component = Component(8, 11) "192.168.0.1"
264*6777b538SAndroid Build Coastguard Worker //
265*6777b538SAndroid Build Coastguard Worker // [Example 4]: input = "[1::]"
266*6777b538SAndroid Build Coastguard Worker //  ==> num_hex_components = 1
267*6777b538SAndroid Build Coastguard Worker //  ==> hex_components[0] = Component(1,1) "1"
268*6777b538SAndroid Build Coastguard Worker //  ==> index_of_contraction = 1
269*6777b538SAndroid Build Coastguard Worker //  ==> ipv4_component = Component(0, -1)
270*6777b538SAndroid Build Coastguard Worker //
271*6777b538SAndroid Build Coastguard Worker // [Example 5]: input = "[::192.168.0.1]"
272*6777b538SAndroid Build Coastguard Worker //  ==> num_hex_components = 0
273*6777b538SAndroid Build Coastguard Worker //  ==> index_of_contraction = 0
274*6777b538SAndroid Build Coastguard Worker //  ==> ipv4_component = Component(8, 11) "192.168.0.1"
275*6777b538SAndroid Build Coastguard Worker //
276*6777b538SAndroid Build Coastguard Worker struct IPv6Parsed {
277*6777b538SAndroid Build Coastguard Worker   // Zero-out the parse information.
reseturl::__anona6a949f00111::IPv6Parsed278*6777b538SAndroid Build Coastguard Worker   void reset() {
279*6777b538SAndroid Build Coastguard Worker     num_hex_components = 0;
280*6777b538SAndroid Build Coastguard Worker     index_of_contraction = -1;
281*6777b538SAndroid Build Coastguard Worker     ipv4_component.reset();
282*6777b538SAndroid Build Coastguard Worker   }
283*6777b538SAndroid Build Coastguard Worker 
284*6777b538SAndroid Build Coastguard Worker   // There can be up to 8 hex components (colon separated) in the literal.
285*6777b538SAndroid Build Coastguard Worker   Component hex_components[8];
286*6777b538SAndroid Build Coastguard Worker 
287*6777b538SAndroid Build Coastguard Worker   // The count of hex components present. Ranges from [0,8].
288*6777b538SAndroid Build Coastguard Worker   int num_hex_components;
289*6777b538SAndroid Build Coastguard Worker 
290*6777b538SAndroid Build Coastguard Worker   // The index of the hex component that the "::" contraction precedes, or
291*6777b538SAndroid Build Coastguard Worker   // -1 if there is no contraction.
292*6777b538SAndroid Build Coastguard Worker   int index_of_contraction;
293*6777b538SAndroid Build Coastguard Worker 
294*6777b538SAndroid Build Coastguard Worker   // The range of characters which are an IPv4 literal.
295*6777b538SAndroid Build Coastguard Worker   Component ipv4_component;
296*6777b538SAndroid Build Coastguard Worker };
297*6777b538SAndroid Build Coastguard Worker 
298*6777b538SAndroid Build Coastguard Worker // Parse the IPv6 input string. If parsing succeeded returns true and fills
299*6777b538SAndroid Build Coastguard Worker // |parsed| with the information. If parsing failed (because the input is
300*6777b538SAndroid Build Coastguard Worker // invalid) returns false.
301*6777b538SAndroid Build Coastguard Worker template<typename CHAR, typename UCHAR>
DoParseIPv6(const CHAR * spec,const Component & host,IPv6Parsed * parsed)302*6777b538SAndroid Build Coastguard Worker bool DoParseIPv6(const CHAR* spec, const Component& host, IPv6Parsed* parsed) {
303*6777b538SAndroid Build Coastguard Worker   // Zero-out the info.
304*6777b538SAndroid Build Coastguard Worker   parsed->reset();
305*6777b538SAndroid Build Coastguard Worker 
306*6777b538SAndroid Build Coastguard Worker   if (host.is_empty())
307*6777b538SAndroid Build Coastguard Worker     return false;
308*6777b538SAndroid Build Coastguard Worker 
309*6777b538SAndroid Build Coastguard Worker   // The index for start and end of address range (no brackets).
310*6777b538SAndroid Build Coastguard Worker   int begin = host.begin;
311*6777b538SAndroid Build Coastguard Worker   int end = host.end();
312*6777b538SAndroid Build Coastguard Worker 
313*6777b538SAndroid Build Coastguard Worker   int cur_component_begin = begin;  // Start of the current component.
314*6777b538SAndroid Build Coastguard Worker 
315*6777b538SAndroid Build Coastguard Worker   // Scan through the input, searching for hex components, "::" contractions,
316*6777b538SAndroid Build Coastguard Worker   // and IPv4 components.
317*6777b538SAndroid Build Coastguard Worker   for (int i = begin; /* i <= end */; i++) {
318*6777b538SAndroid Build Coastguard Worker     bool is_colon = spec[i] == ':';
319*6777b538SAndroid Build Coastguard Worker     bool is_contraction = is_colon && i < end - 1 && spec[i + 1] == ':';
320*6777b538SAndroid Build Coastguard Worker 
321*6777b538SAndroid Build Coastguard Worker     // We reached the end of the current component if we encounter a colon
322*6777b538SAndroid Build Coastguard Worker     // (separator between hex components, or start of a contraction), or end of
323*6777b538SAndroid Build Coastguard Worker     // input.
324*6777b538SAndroid Build Coastguard Worker     if (is_colon || i == end) {
325*6777b538SAndroid Build Coastguard Worker       int component_len = i - cur_component_begin;
326*6777b538SAndroid Build Coastguard Worker 
327*6777b538SAndroid Build Coastguard Worker       // A component should not have more than 4 hex digits.
328*6777b538SAndroid Build Coastguard Worker       if (component_len > 4)
329*6777b538SAndroid Build Coastguard Worker         return false;
330*6777b538SAndroid Build Coastguard Worker 
331*6777b538SAndroid Build Coastguard Worker       // Don't allow empty components.
332*6777b538SAndroid Build Coastguard Worker       if (component_len == 0) {
333*6777b538SAndroid Build Coastguard Worker         // The exception is when contractions appear at beginning of the
334*6777b538SAndroid Build Coastguard Worker         // input or at the end of the input.
335*6777b538SAndroid Build Coastguard Worker         if (!((is_contraction && i == begin) || (i == end &&
336*6777b538SAndroid Build Coastguard Worker             parsed->index_of_contraction == parsed->num_hex_components)))
337*6777b538SAndroid Build Coastguard Worker           return false;
338*6777b538SAndroid Build Coastguard Worker       }
339*6777b538SAndroid Build Coastguard Worker 
340*6777b538SAndroid Build Coastguard Worker       // Add the hex component we just found to running list.
341*6777b538SAndroid Build Coastguard Worker       if (component_len > 0) {
342*6777b538SAndroid Build Coastguard Worker         // Can't have more than 8 components!
343*6777b538SAndroid Build Coastguard Worker         if (parsed->num_hex_components >= 8)
344*6777b538SAndroid Build Coastguard Worker           return false;
345*6777b538SAndroid Build Coastguard Worker 
346*6777b538SAndroid Build Coastguard Worker         parsed->hex_components[parsed->num_hex_components++] =
347*6777b538SAndroid Build Coastguard Worker             Component(cur_component_begin, component_len);
348*6777b538SAndroid Build Coastguard Worker       }
349*6777b538SAndroid Build Coastguard Worker     }
350*6777b538SAndroid Build Coastguard Worker 
351*6777b538SAndroid Build Coastguard Worker     if (i == end)
352*6777b538SAndroid Build Coastguard Worker       break;  // Reached the end of the input, DONE.
353*6777b538SAndroid Build Coastguard Worker 
354*6777b538SAndroid Build Coastguard Worker     // We found a "::" contraction.
355*6777b538SAndroid Build Coastguard Worker     if (is_contraction) {
356*6777b538SAndroid Build Coastguard Worker       // There can be at most one contraction in the literal.
357*6777b538SAndroid Build Coastguard Worker       if (parsed->index_of_contraction != -1)
358*6777b538SAndroid Build Coastguard Worker         return false;
359*6777b538SAndroid Build Coastguard Worker       parsed->index_of_contraction = parsed->num_hex_components;
360*6777b538SAndroid Build Coastguard Worker       ++i;  // Consume the colon we peeked.
361*6777b538SAndroid Build Coastguard Worker     }
362*6777b538SAndroid Build Coastguard Worker 
363*6777b538SAndroid Build Coastguard Worker     if (is_colon) {
364*6777b538SAndroid Build Coastguard Worker       // Colons are separators between components, keep track of where the
365*6777b538SAndroid Build Coastguard Worker       // current component started (after this colon).
366*6777b538SAndroid Build Coastguard Worker       cur_component_begin = i + 1;
367*6777b538SAndroid Build Coastguard Worker     } else {
368*6777b538SAndroid Build Coastguard Worker       if (static_cast<UCHAR>(spec[i]) >= 0x80)
369*6777b538SAndroid Build Coastguard Worker         return false;  // Not ASCII.
370*6777b538SAndroid Build Coastguard Worker 
371*6777b538SAndroid Build Coastguard Worker       if (!IsHexChar(static_cast<unsigned char>(spec[i]))) {
372*6777b538SAndroid Build Coastguard Worker         // Regular components are hex numbers. It is also possible for
373*6777b538SAndroid Build Coastguard Worker         // a component to be an IPv4 address in dotted form.
374*6777b538SAndroid Build Coastguard Worker         if (IsIPv4Char(static_cast<unsigned char>(spec[i]))) {
375*6777b538SAndroid Build Coastguard Worker           // Since IPv4 address can only appear at the end, assume the rest
376*6777b538SAndroid Build Coastguard Worker           // of the string is an IPv4 address. (We will parse this separately
377*6777b538SAndroid Build Coastguard Worker           // later).
378*6777b538SAndroid Build Coastguard Worker           parsed->ipv4_component =
379*6777b538SAndroid Build Coastguard Worker               Component(cur_component_begin, end - cur_component_begin);
380*6777b538SAndroid Build Coastguard Worker           break;
381*6777b538SAndroid Build Coastguard Worker         } else {
382*6777b538SAndroid Build Coastguard Worker           // The character was neither a hex digit, nor an IPv4 character.
383*6777b538SAndroid Build Coastguard Worker           return false;
384*6777b538SAndroid Build Coastguard Worker         }
385*6777b538SAndroid Build Coastguard Worker       }
386*6777b538SAndroid Build Coastguard Worker     }
387*6777b538SAndroid Build Coastguard Worker   }
388*6777b538SAndroid Build Coastguard Worker 
389*6777b538SAndroid Build Coastguard Worker   return true;
390*6777b538SAndroid Build Coastguard Worker }
391*6777b538SAndroid Build Coastguard Worker 
392*6777b538SAndroid Build Coastguard Worker // Verifies the parsed IPv6 information, checking that the various components
393*6777b538SAndroid Build Coastguard Worker // add up to the right number of bits (hex components are 16 bits, while
394*6777b538SAndroid Build Coastguard Worker // embedded IPv4 formats are 32 bits, and contractions are placeholdes for
395*6777b538SAndroid Build Coastguard Worker // 16 or more bits). Returns true if sizes match up, false otherwise. On
396*6777b538SAndroid Build Coastguard Worker // success writes the length of the contraction (if any) to
397*6777b538SAndroid Build Coastguard Worker // |out_num_bytes_of_contraction|.
CheckIPv6ComponentsSize(const IPv6Parsed & parsed,int * out_num_bytes_of_contraction)398*6777b538SAndroid Build Coastguard Worker bool CheckIPv6ComponentsSize(const IPv6Parsed& parsed,
399*6777b538SAndroid Build Coastguard Worker                              int* out_num_bytes_of_contraction) {
400*6777b538SAndroid Build Coastguard Worker   // Each group of four hex digits contributes 16 bits.
401*6777b538SAndroid Build Coastguard Worker   int num_bytes_without_contraction = parsed.num_hex_components * 2;
402*6777b538SAndroid Build Coastguard Worker 
403*6777b538SAndroid Build Coastguard Worker   // If an IPv4 address was embedded at the end, it contributes 32 bits.
404*6777b538SAndroid Build Coastguard Worker   if (parsed.ipv4_component.is_valid())
405*6777b538SAndroid Build Coastguard Worker     num_bytes_without_contraction += 4;
406*6777b538SAndroid Build Coastguard Worker 
407*6777b538SAndroid Build Coastguard Worker   // If there was a "::" contraction, its size is going to be:
408*6777b538SAndroid Build Coastguard Worker   // MAX([16bits], [128bits] - num_bytes_without_contraction).
409*6777b538SAndroid Build Coastguard Worker   int num_bytes_of_contraction = 0;
410*6777b538SAndroid Build Coastguard Worker   if (parsed.index_of_contraction != -1) {
411*6777b538SAndroid Build Coastguard Worker     num_bytes_of_contraction = 16 - num_bytes_without_contraction;
412*6777b538SAndroid Build Coastguard Worker     if (num_bytes_of_contraction < 2)
413*6777b538SAndroid Build Coastguard Worker       num_bytes_of_contraction = 2;
414*6777b538SAndroid Build Coastguard Worker   }
415*6777b538SAndroid Build Coastguard Worker 
416*6777b538SAndroid Build Coastguard Worker   // Check that the numbers add up.
417*6777b538SAndroid Build Coastguard Worker   if (num_bytes_without_contraction + num_bytes_of_contraction != 16)
418*6777b538SAndroid Build Coastguard Worker     return false;
419*6777b538SAndroid Build Coastguard Worker 
420*6777b538SAndroid Build Coastguard Worker   *out_num_bytes_of_contraction = num_bytes_of_contraction;
421*6777b538SAndroid Build Coastguard Worker   return true;
422*6777b538SAndroid Build Coastguard Worker }
423*6777b538SAndroid Build Coastguard Worker 
424*6777b538SAndroid Build Coastguard Worker // Converts a hex component into a number. This cannot fail since the caller has
425*6777b538SAndroid Build Coastguard Worker // already verified that each character in the string was a hex digit, and
426*6777b538SAndroid Build Coastguard Worker // that there were no more than 4 characters.
427*6777b538SAndroid Build Coastguard Worker template <typename CHAR>
IPv6HexComponentToNumber(const CHAR * spec,const Component & component)428*6777b538SAndroid Build Coastguard Worker uint16_t IPv6HexComponentToNumber(const CHAR* spec,
429*6777b538SAndroid Build Coastguard Worker                                   const Component& component) {
430*6777b538SAndroid Build Coastguard Worker   DCHECK(component.len <= 4);
431*6777b538SAndroid Build Coastguard Worker 
432*6777b538SAndroid Build Coastguard Worker   // Copy the hex string into a C-string.
433*6777b538SAndroid Build Coastguard Worker   char buf[5];
434*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < component.len; ++i)
435*6777b538SAndroid Build Coastguard Worker     buf[i] = static_cast<char>(spec[component.begin + i]);
436*6777b538SAndroid Build Coastguard Worker   buf[component.len] = '\0';
437*6777b538SAndroid Build Coastguard Worker 
438*6777b538SAndroid Build Coastguard Worker   // Convert it to a number (overflow is not possible, since with 4 hex
439*6777b538SAndroid Build Coastguard Worker   // characters we can at most have a 16 bit number).
440*6777b538SAndroid Build Coastguard Worker   return static_cast<uint16_t>(_strtoui64(buf, NULL, 16));
441*6777b538SAndroid Build Coastguard Worker }
442*6777b538SAndroid Build Coastguard Worker 
443*6777b538SAndroid Build Coastguard Worker // Converts an IPv6 address to a 128-bit number (network byte order), returning
444*6777b538SAndroid Build Coastguard Worker // true on success. False means that the input was not a valid IPv6 address.
445*6777b538SAndroid Build Coastguard Worker template<typename CHAR, typename UCHAR>
DoIPv6AddressToNumber(const CHAR * spec,const Component & host,unsigned char address[16])446*6777b538SAndroid Build Coastguard Worker bool DoIPv6AddressToNumber(const CHAR* spec,
447*6777b538SAndroid Build Coastguard Worker                            const Component& host,
448*6777b538SAndroid Build Coastguard Worker                            unsigned char address[16]) {
449*6777b538SAndroid Build Coastguard Worker   // Make sure the component is bounded by '[' and ']'.
450*6777b538SAndroid Build Coastguard Worker   int end = host.end();
451*6777b538SAndroid Build Coastguard Worker   if (host.is_empty() || spec[host.begin] != '[' || spec[end - 1] != ']')
452*6777b538SAndroid Build Coastguard Worker     return false;
453*6777b538SAndroid Build Coastguard Worker 
454*6777b538SAndroid Build Coastguard Worker   // Exclude the square brackets.
455*6777b538SAndroid Build Coastguard Worker   Component ipv6_comp(host.begin + 1, host.len - 2);
456*6777b538SAndroid Build Coastguard Worker 
457*6777b538SAndroid Build Coastguard Worker   // Parse the IPv6 address -- identify where all the colon separated hex
458*6777b538SAndroid Build Coastguard Worker   // components are, the "::" contraction, and the embedded IPv4 address.
459*6777b538SAndroid Build Coastguard Worker   IPv6Parsed ipv6_parsed;
460*6777b538SAndroid Build Coastguard Worker   if (!DoParseIPv6<CHAR, UCHAR>(spec, ipv6_comp, &ipv6_parsed))
461*6777b538SAndroid Build Coastguard Worker     return false;
462*6777b538SAndroid Build Coastguard Worker 
463*6777b538SAndroid Build Coastguard Worker   // Do some basic size checks to make sure that the address doesn't
464*6777b538SAndroid Build Coastguard Worker   // specify more than 128 bits or fewer than 128 bits. This also resolves
465*6777b538SAndroid Build Coastguard Worker   // how may zero bytes the "::" contraction represents.
466*6777b538SAndroid Build Coastguard Worker   int num_bytes_of_contraction;
467*6777b538SAndroid Build Coastguard Worker   if (!CheckIPv6ComponentsSize(ipv6_parsed, &num_bytes_of_contraction))
468*6777b538SAndroid Build Coastguard Worker     return false;
469*6777b538SAndroid Build Coastguard Worker 
470*6777b538SAndroid Build Coastguard Worker   int cur_index_in_address = 0;
471*6777b538SAndroid Build Coastguard Worker 
472*6777b538SAndroid Build Coastguard Worker   // Loop through each hex components, and contraction in order.
473*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i <= ipv6_parsed.num_hex_components; ++i) {
474*6777b538SAndroid Build Coastguard Worker     // Append the contraction if it appears before this component.
475*6777b538SAndroid Build Coastguard Worker     if (i == ipv6_parsed.index_of_contraction) {
476*6777b538SAndroid Build Coastguard Worker       for (int j = 0; j < num_bytes_of_contraction; ++j)
477*6777b538SAndroid Build Coastguard Worker         address[cur_index_in_address++] = 0;
478*6777b538SAndroid Build Coastguard Worker     }
479*6777b538SAndroid Build Coastguard Worker     // Append the hex component's value.
480*6777b538SAndroid Build Coastguard Worker     if (i != ipv6_parsed.num_hex_components) {
481*6777b538SAndroid Build Coastguard Worker       // Get the 16-bit value for this hex component.
482*6777b538SAndroid Build Coastguard Worker       uint16_t number = IPv6HexComponentToNumber<CHAR>(
483*6777b538SAndroid Build Coastguard Worker           spec, ipv6_parsed.hex_components[i]);
484*6777b538SAndroid Build Coastguard Worker       // Append to |address|, in network byte order.
485*6777b538SAndroid Build Coastguard Worker       address[cur_index_in_address++] = (number & 0xFF00) >> 8;
486*6777b538SAndroid Build Coastguard Worker       address[cur_index_in_address++] = (number & 0x00FF);
487*6777b538SAndroid Build Coastguard Worker     }
488*6777b538SAndroid Build Coastguard Worker   }
489*6777b538SAndroid Build Coastguard Worker 
490*6777b538SAndroid Build Coastguard Worker   // If there was an IPv4 section, convert it into a 32-bit number and append
491*6777b538SAndroid Build Coastguard Worker   // it to |address|.
492*6777b538SAndroid Build Coastguard Worker   if (ipv6_parsed.ipv4_component.is_valid()) {
493*6777b538SAndroid Build Coastguard Worker     // Append the 32-bit number to |address|.
494*6777b538SAndroid Build Coastguard Worker     int num_ipv4_components = 0;
495*6777b538SAndroid Build Coastguard Worker     // IPv4AddressToNumber will remove the trailing dot from the component.
496*6777b538SAndroid Build Coastguard Worker     bool trailing_dot = ipv6_parsed.ipv4_component.is_nonempty() &&
497*6777b538SAndroid Build Coastguard Worker                         spec[ipv6_parsed.ipv4_component.end() - 1] == '.';
498*6777b538SAndroid Build Coastguard Worker     // The URL standard requires the embedded IPv4 address to be concisely
499*6777b538SAndroid Build Coastguard Worker     // composed of 4 parts and disallows terminal dots.
500*6777b538SAndroid Build Coastguard Worker     // See https://url.spec.whatwg.org/#concept-ipv6-parser
501*6777b538SAndroid Build Coastguard Worker     if (CanonHostInfo::IPV4 !=
502*6777b538SAndroid Build Coastguard Worker             IPv4AddressToNumber(spec, ipv6_parsed.ipv4_component,
503*6777b538SAndroid Build Coastguard Worker                                 &address[cur_index_in_address],
504*6777b538SAndroid Build Coastguard Worker                                 &num_ipv4_components)) {
505*6777b538SAndroid Build Coastguard Worker       return false;
506*6777b538SAndroid Build Coastguard Worker     }
507*6777b538SAndroid Build Coastguard Worker     if ((num_ipv4_components != 4 || trailing_dot)) {
508*6777b538SAndroid Build Coastguard Worker       return false;
509*6777b538SAndroid Build Coastguard Worker     }
510*6777b538SAndroid Build Coastguard Worker   }
511*6777b538SAndroid Build Coastguard Worker 
512*6777b538SAndroid Build Coastguard Worker   return true;
513*6777b538SAndroid Build Coastguard Worker }
514*6777b538SAndroid Build Coastguard Worker 
515*6777b538SAndroid Build Coastguard Worker // Searches for the longest sequence of zeros in |address|, and writes the
516*6777b538SAndroid Build Coastguard Worker // range into |contraction_range|. The run of zeros must be at least 16 bits,
517*6777b538SAndroid Build Coastguard Worker // and if there is a tie the first is chosen.
ChooseIPv6ContractionRange(const unsigned char address[16],Component * contraction_range)518*6777b538SAndroid Build Coastguard Worker void ChooseIPv6ContractionRange(const unsigned char address[16],
519*6777b538SAndroid Build Coastguard Worker                                 Component* contraction_range) {
520*6777b538SAndroid Build Coastguard Worker   // The longest run of zeros in |address| seen so far.
521*6777b538SAndroid Build Coastguard Worker   Component max_range;
522*6777b538SAndroid Build Coastguard Worker 
523*6777b538SAndroid Build Coastguard Worker   // The current run of zeros in |address| being iterated over.
524*6777b538SAndroid Build Coastguard Worker   Component cur_range;
525*6777b538SAndroid Build Coastguard Worker 
526*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 16; i += 2) {
527*6777b538SAndroid Build Coastguard Worker     // Test for 16 bits worth of zero.
528*6777b538SAndroid Build Coastguard Worker     bool is_zero = (address[i] == 0 && address[i + 1] == 0);
529*6777b538SAndroid Build Coastguard Worker 
530*6777b538SAndroid Build Coastguard Worker     if (is_zero) {
531*6777b538SAndroid Build Coastguard Worker       // Add the zero to the current range (or start a new one).
532*6777b538SAndroid Build Coastguard Worker       if (!cur_range.is_valid())
533*6777b538SAndroid Build Coastguard Worker         cur_range = Component(i, 0);
534*6777b538SAndroid Build Coastguard Worker       cur_range.len += 2;
535*6777b538SAndroid Build Coastguard Worker     }
536*6777b538SAndroid Build Coastguard Worker 
537*6777b538SAndroid Build Coastguard Worker     if (!is_zero || i == 14) {
538*6777b538SAndroid Build Coastguard Worker       // Just completed a run of zeros. If the run is greater than 16 bits,
539*6777b538SAndroid Build Coastguard Worker       // it is a candidate for the contraction.
540*6777b538SAndroid Build Coastguard Worker       if (cur_range.len > 2 && cur_range.len > max_range.len) {
541*6777b538SAndroid Build Coastguard Worker         max_range = cur_range;
542*6777b538SAndroid Build Coastguard Worker       }
543*6777b538SAndroid Build Coastguard Worker       cur_range.reset();
544*6777b538SAndroid Build Coastguard Worker     }
545*6777b538SAndroid Build Coastguard Worker   }
546*6777b538SAndroid Build Coastguard Worker   *contraction_range = max_range;
547*6777b538SAndroid Build Coastguard Worker }
548*6777b538SAndroid Build Coastguard Worker 
549*6777b538SAndroid Build Coastguard Worker // Return true if we've made a final IPV6/BROKEN decision, false if the result
550*6777b538SAndroid Build Coastguard Worker // is NEUTRAL, and we could use a second opinion.
551*6777b538SAndroid Build Coastguard Worker template<typename CHAR, typename UCHAR>
DoCanonicalizeIPv6Address(const CHAR * spec,const Component & host,CanonOutput * output,CanonHostInfo * host_info)552*6777b538SAndroid Build Coastguard Worker bool DoCanonicalizeIPv6Address(const CHAR* spec,
553*6777b538SAndroid Build Coastguard Worker                                const Component& host,
554*6777b538SAndroid Build Coastguard Worker                                CanonOutput* output,
555*6777b538SAndroid Build Coastguard Worker                                CanonHostInfo* host_info) {
556*6777b538SAndroid Build Coastguard Worker   // Turn the IP address into a 128 bit number.
557*6777b538SAndroid Build Coastguard Worker   if (!IPv6AddressToNumber(spec, host, host_info->address)) {
558*6777b538SAndroid Build Coastguard Worker     // If it's not an IPv6 address, scan for characters that should *only*
559*6777b538SAndroid Build Coastguard Worker     // exist in an IPv6 address.
560*6777b538SAndroid Build Coastguard Worker     for (int i = host.begin; i < host.end(); i++) {
561*6777b538SAndroid Build Coastguard Worker       switch (spec[i]) {
562*6777b538SAndroid Build Coastguard Worker         case '[':
563*6777b538SAndroid Build Coastguard Worker         case ']':
564*6777b538SAndroid Build Coastguard Worker         case ':':
565*6777b538SAndroid Build Coastguard Worker           host_info->family = CanonHostInfo::BROKEN;
566*6777b538SAndroid Build Coastguard Worker           return true;
567*6777b538SAndroid Build Coastguard Worker       }
568*6777b538SAndroid Build Coastguard Worker     }
569*6777b538SAndroid Build Coastguard Worker 
570*6777b538SAndroid Build Coastguard Worker     // No invalid characters. Could still be IPv4 or a hostname.
571*6777b538SAndroid Build Coastguard Worker     host_info->family = CanonHostInfo::NEUTRAL;
572*6777b538SAndroid Build Coastguard Worker     return false;
573*6777b538SAndroid Build Coastguard Worker   }
574*6777b538SAndroid Build Coastguard Worker 
575*6777b538SAndroid Build Coastguard Worker   host_info->out_host.begin = output->length();
576*6777b538SAndroid Build Coastguard Worker   output->push_back('[');
577*6777b538SAndroid Build Coastguard Worker   AppendIPv6Address(host_info->address, output);
578*6777b538SAndroid Build Coastguard Worker   output->push_back(']');
579*6777b538SAndroid Build Coastguard Worker   host_info->out_host.len = output->length() - host_info->out_host.begin;
580*6777b538SAndroid Build Coastguard Worker 
581*6777b538SAndroid Build Coastguard Worker   host_info->family = CanonHostInfo::IPV6;
582*6777b538SAndroid Build Coastguard Worker   return true;
583*6777b538SAndroid Build Coastguard Worker }
584*6777b538SAndroid Build Coastguard Worker 
585*6777b538SAndroid Build Coastguard Worker }  // namespace
586*6777b538SAndroid Build Coastguard Worker 
AppendIPv4Address(const unsigned char address[4],CanonOutput * output)587*6777b538SAndroid Build Coastguard Worker void AppendIPv4Address(const unsigned char address[4], CanonOutput* output) {
588*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i < 4; i++) {
589*6777b538SAndroid Build Coastguard Worker     char str[16];
590*6777b538SAndroid Build Coastguard Worker     _itoa_s(address[i], str, 10);
591*6777b538SAndroid Build Coastguard Worker 
592*6777b538SAndroid Build Coastguard Worker     for (int ch = 0; str[ch] != 0; ch++)
593*6777b538SAndroid Build Coastguard Worker       output->push_back(str[ch]);
594*6777b538SAndroid Build Coastguard Worker 
595*6777b538SAndroid Build Coastguard Worker     if (i != 3)
596*6777b538SAndroid Build Coastguard Worker       output->push_back('.');
597*6777b538SAndroid Build Coastguard Worker   }
598*6777b538SAndroid Build Coastguard Worker }
599*6777b538SAndroid Build Coastguard Worker 
AppendIPv6Address(const unsigned char address[16],CanonOutput * output)600*6777b538SAndroid Build Coastguard Worker void AppendIPv6Address(const unsigned char address[16], CanonOutput* output) {
601*6777b538SAndroid Build Coastguard Worker   // We will output the address according to the rules in:
602*6777b538SAndroid Build Coastguard Worker   // http://tools.ietf.org/html/draft-kawamura-ipv6-text-representation-01#section-4
603*6777b538SAndroid Build Coastguard Worker 
604*6777b538SAndroid Build Coastguard Worker   // Start by finding where to place the "::" contraction (if any).
605*6777b538SAndroid Build Coastguard Worker   Component contraction_range;
606*6777b538SAndroid Build Coastguard Worker   ChooseIPv6ContractionRange(address, &contraction_range);
607*6777b538SAndroid Build Coastguard Worker 
608*6777b538SAndroid Build Coastguard Worker   for (int i = 0; i <= 14;) {
609*6777b538SAndroid Build Coastguard Worker     // We check 2 bytes at a time, from bytes (0, 1) to (14, 15), inclusive.
610*6777b538SAndroid Build Coastguard Worker     DCHECK(i % 2 == 0);
611*6777b538SAndroid Build Coastguard Worker     if (i == contraction_range.begin && contraction_range.len > 0) {
612*6777b538SAndroid Build Coastguard Worker       // Jump over the contraction.
613*6777b538SAndroid Build Coastguard Worker       if (i == 0)
614*6777b538SAndroid Build Coastguard Worker         output->push_back(':');
615*6777b538SAndroid Build Coastguard Worker       output->push_back(':');
616*6777b538SAndroid Build Coastguard Worker       i = contraction_range.end();
617*6777b538SAndroid Build Coastguard Worker     } else {
618*6777b538SAndroid Build Coastguard Worker       // Consume the next 16 bits from |address|.
619*6777b538SAndroid Build Coastguard Worker       int x = address[i] << 8 | address[i + 1];
620*6777b538SAndroid Build Coastguard Worker 
621*6777b538SAndroid Build Coastguard Worker       i += 2;
622*6777b538SAndroid Build Coastguard Worker 
623*6777b538SAndroid Build Coastguard Worker       // Stringify the 16 bit number (at most requires 4 hex digits).
624*6777b538SAndroid Build Coastguard Worker       char str[5];
625*6777b538SAndroid Build Coastguard Worker       _itoa_s(x, str, 16);
626*6777b538SAndroid Build Coastguard Worker       for (int ch = 0; str[ch] != 0; ++ch)
627*6777b538SAndroid Build Coastguard Worker         output->push_back(str[ch]);
628*6777b538SAndroid Build Coastguard Worker 
629*6777b538SAndroid Build Coastguard Worker       // Put a colon after each number, except the last.
630*6777b538SAndroid Build Coastguard Worker       if (i < 16)
631*6777b538SAndroid Build Coastguard Worker         output->push_back(':');
632*6777b538SAndroid Build Coastguard Worker     }
633*6777b538SAndroid Build Coastguard Worker   }
634*6777b538SAndroid Build Coastguard Worker }
635*6777b538SAndroid Build Coastguard Worker 
CanonicalizeIPAddress(const char * spec,const Component & host,CanonOutput * output,CanonHostInfo * host_info)636*6777b538SAndroid Build Coastguard Worker void CanonicalizeIPAddress(const char* spec,
637*6777b538SAndroid Build Coastguard Worker                            const Component& host,
638*6777b538SAndroid Build Coastguard Worker                            CanonOutput* output,
639*6777b538SAndroid Build Coastguard Worker                            CanonHostInfo* host_info) {
640*6777b538SAndroid Build Coastguard Worker   if (DoCanonicalizeIPv4Address<char, unsigned char>(
641*6777b538SAndroid Build Coastguard Worker           spec, host, output, host_info))
642*6777b538SAndroid Build Coastguard Worker     return;
643*6777b538SAndroid Build Coastguard Worker   if (DoCanonicalizeIPv6Address<char, unsigned char>(
644*6777b538SAndroid Build Coastguard Worker           spec, host, output, host_info))
645*6777b538SAndroid Build Coastguard Worker     return;
646*6777b538SAndroid Build Coastguard Worker }
647*6777b538SAndroid Build Coastguard Worker 
CanonicalizeIPAddress(const char16_t * spec,const Component & host,CanonOutput * output,CanonHostInfo * host_info)648*6777b538SAndroid Build Coastguard Worker void CanonicalizeIPAddress(const char16_t* spec,
649*6777b538SAndroid Build Coastguard Worker                            const Component& host,
650*6777b538SAndroid Build Coastguard Worker                            CanonOutput* output,
651*6777b538SAndroid Build Coastguard Worker                            CanonHostInfo* host_info) {
652*6777b538SAndroid Build Coastguard Worker   if (DoCanonicalizeIPv4Address<char16_t, char16_t>(spec, host, output,
653*6777b538SAndroid Build Coastguard Worker                                                     host_info))
654*6777b538SAndroid Build Coastguard Worker     return;
655*6777b538SAndroid Build Coastguard Worker   if (DoCanonicalizeIPv6Address<char16_t, char16_t>(spec, host, output,
656*6777b538SAndroid Build Coastguard Worker                                                     host_info))
657*6777b538SAndroid Build Coastguard Worker     return;
658*6777b538SAndroid Build Coastguard Worker }
659*6777b538SAndroid Build Coastguard Worker 
CanonicalizeIPv6Address(const char * spec,const Component & host,CanonOutput & output,CanonHostInfo & host_info)660*6777b538SAndroid Build Coastguard Worker void CanonicalizeIPv6Address(const char* spec,
661*6777b538SAndroid Build Coastguard Worker                              const Component& host,
662*6777b538SAndroid Build Coastguard Worker                              CanonOutput& output,
663*6777b538SAndroid Build Coastguard Worker                              CanonHostInfo& host_info) {
664*6777b538SAndroid Build Coastguard Worker   DoCanonicalizeIPv6Address<char, unsigned char>(spec, host, &output,
665*6777b538SAndroid Build Coastguard Worker                                                  &host_info);
666*6777b538SAndroid Build Coastguard Worker }
667*6777b538SAndroid Build Coastguard Worker 
CanonicalizeIPv6Address(const char16_t * spec,const Component & host,CanonOutput & output,CanonHostInfo & host_info)668*6777b538SAndroid Build Coastguard Worker void CanonicalizeIPv6Address(const char16_t* spec,
669*6777b538SAndroid Build Coastguard Worker                              const Component& host,
670*6777b538SAndroid Build Coastguard Worker                              CanonOutput& output,
671*6777b538SAndroid Build Coastguard Worker                              CanonHostInfo& host_info) {
672*6777b538SAndroid Build Coastguard Worker   DoCanonicalizeIPv6Address<char16_t, char16_t>(spec, host, &output,
673*6777b538SAndroid Build Coastguard Worker                                                 &host_info);
674*6777b538SAndroid Build Coastguard Worker }
675*6777b538SAndroid Build Coastguard Worker 
IPv4AddressToNumber(const char * spec,const Component & host,unsigned char address[4],int * num_ipv4_components)676*6777b538SAndroid Build Coastguard Worker CanonHostInfo::Family IPv4AddressToNumber(const char* spec,
677*6777b538SAndroid Build Coastguard Worker                                           const Component& host,
678*6777b538SAndroid Build Coastguard Worker                                           unsigned char address[4],
679*6777b538SAndroid Build Coastguard Worker                                           int* num_ipv4_components) {
680*6777b538SAndroid Build Coastguard Worker   return DoIPv4AddressToNumber<char, unsigned char>(spec, host, address,
681*6777b538SAndroid Build Coastguard Worker                                                     num_ipv4_components);
682*6777b538SAndroid Build Coastguard Worker }
683*6777b538SAndroid Build Coastguard Worker 
IPv4AddressToNumber(const char16_t * spec,const Component & host,unsigned char address[4],int * num_ipv4_components)684*6777b538SAndroid Build Coastguard Worker CanonHostInfo::Family IPv4AddressToNumber(const char16_t* spec,
685*6777b538SAndroid Build Coastguard Worker                                           const Component& host,
686*6777b538SAndroid Build Coastguard Worker                                           unsigned char address[4],
687*6777b538SAndroid Build Coastguard Worker                                           int* num_ipv4_components) {
688*6777b538SAndroid Build Coastguard Worker   return DoIPv4AddressToNumber<char16_t, char16_t>(spec, host, address,
689*6777b538SAndroid Build Coastguard Worker                                                    num_ipv4_components);
690*6777b538SAndroid Build Coastguard Worker }
691*6777b538SAndroid Build Coastguard Worker 
IPv6AddressToNumber(const char * spec,const Component & host,unsigned char address[16])692*6777b538SAndroid Build Coastguard Worker bool IPv6AddressToNumber(const char* spec,
693*6777b538SAndroid Build Coastguard Worker                          const Component& host,
694*6777b538SAndroid Build Coastguard Worker                          unsigned char address[16]) {
695*6777b538SAndroid Build Coastguard Worker   return DoIPv6AddressToNumber<char, unsigned char>(spec, host, address);
696*6777b538SAndroid Build Coastguard Worker }
697*6777b538SAndroid Build Coastguard Worker 
IPv6AddressToNumber(const char16_t * spec,const Component & host,unsigned char address[16])698*6777b538SAndroid Build Coastguard Worker bool IPv6AddressToNumber(const char16_t* spec,
699*6777b538SAndroid Build Coastguard Worker                          const Component& host,
700*6777b538SAndroid Build Coastguard Worker                          unsigned char address[16]) {
701*6777b538SAndroid Build Coastguard Worker   return DoIPv6AddressToNumber<char16_t, char16_t>(spec, host, address);
702*6777b538SAndroid Build Coastguard Worker }
703*6777b538SAndroid Build Coastguard Worker 
704*6777b538SAndroid Build Coastguard Worker }  // namespace url
705