15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NB: Modelled after Mozilla's code (originally written by Pamela Greene,
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// later modified by others), but almost entirely rewritten for Chrome.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//   (netwerk/dns/src/nsEffectiveTLDService.cpp)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/* ***** BEGIN LICENSE BLOCK *****
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Version: MPL 1.1/GPL 2.0/LGPL 2.1
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The contents of this file are subject to the Mozilla Public License Version
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * 1.1 (the "License"); you may not use this file except in compliance with
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the License. You may obtain a copy of the License at
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * http://www.mozilla.org/MPL/
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Software distributed under the License is distributed on an "AS IS" basis,
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * for the specific language governing rights and limitations under the
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * License.
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Original Code is Mozilla Effective-TLD Service
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * The Initial Developer of the Original Code is
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Google Inc.
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Portions created by the Initial Developer are Copyright (C) 2006
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the Initial Developer. All Rights Reserved.
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Contributor(s):
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Pamela Greene <pamg.bugs@gmail.com> (original author)
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *   Daniel Witte <dwitte@stanford.edu>
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Alternatively, the contents of this file may be used under the terms of
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * either the GNU General Public License Version 2 or later (the "GPL"), or
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * in which case the provisions of the GPL or the LGPL are applicable instead
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * of those above. If you wish to allow use of your version of this file only
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * under the terms of either the GPL or the LGPL, and not to allow others to
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * use your version of this file under the terms of the MPL, indicate your
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * decision by deleting the provisions above and replace them with the notice
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * and other provisions required by the GPL or the LGPL. If you do not delete
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the provisions above, a recipient may use your version of this file under
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * the terms of any one of the MPL, the GPL or the LGPL.
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * ***** END LICENSE BLOCK ***** */
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
495e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/string_util.h"
50868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_module.h"
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
537dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_parse.h"
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
57a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)namespace registry_controlled_domains {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/registry_controlled_domains/effective_tld_names-inc.cc"
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// See make_dafsa.py for documentation of the generated dafsa byte array.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const unsigned char* g_graph = kDafsa;
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)size_t g_graph_length = sizeof(kDafsa);
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)const int kNotFound = -1;
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kExceptionRule = 1;
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const int kWildcardRule = 2;
707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const int kPrivateRule = 4;
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Read next offset from pos.
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true if an offset could be read, false otherwise.
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool GetNextOffset(const unsigned char** pos, const unsigned char* end,
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                   const unsigned char** offset) {
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (*pos == end)
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return false;
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // When reading an offset the byte array must always contain at least
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // three more bytes to consume. First the offset to read, then a node
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // to skip over and finally a destination node. No object can be smaller
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // than one byte.
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_LT(*pos + 2, end);
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  size_t bytes_consumed;
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  switch (**pos & 0x60) {
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 0x60:  // Read three byte offset
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *offset += (((*pos)[0] & 0x1F) << 16) | ((*pos)[1] << 8) | (*pos)[2];
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_consumed = 3;
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    case 0x40:  // Read two byte offset
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *offset += (((*pos)[0] & 0x1F) << 8) | (*pos)[1];
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_consumed = 2;
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    default:
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      *offset += (*pos)[0] & 0x3F;
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      bytes_consumed = 1;
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if ((**pos & 0x80) != 0) {
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *pos = end;
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *pos += bytes_consumed;
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return true;
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Check if byte at offset is last in label.
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsEOL(const unsigned char* offset, const unsigned char* end) {
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_LT(offset, end);
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return (*offset & 0x80) != 0;
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Check if byte at offset matches first character in key.
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This version matches characters not last in label.
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsMatch(const unsigned char* offset, const unsigned char* end,
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)             const char* key) {
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_LT(offset, end);
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return *offset == *key;
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Check if byte at offset matches first character in key.
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// This version matches characters last in label.
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool IsEndCharMatch(const unsigned char* offset, const unsigned char* end,
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    const char* key) {
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_LT(offset, end);
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return *offset == (*key | 0x80);
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1277dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Read return value at offset.
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Returns true if a return value could be read, false otherwise.
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool GetReturnValue(const unsigned char* offset, const unsigned char* end,
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                    int* return_value) {
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_LT(offset, end);
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if ((*offset & 0xE0) == 0x80) {
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    *return_value = *offset & 0x0F;
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return true;
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return false;
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
1397dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Lookup a domain key in a byte array generated by make_dafsa.py.
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// The rule type is returned if key is found, otherwise kNotFound is returned.
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)int LookupString(const unsigned char* graph, size_t length, const char* key,
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                 size_t key_length) {
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const unsigned char* pos = graph;
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const unsigned char* end = graph + length;
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const unsigned char* offset = pos;
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  const char* key_end = key + key_length;
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  while (GetNextOffset(&pos, end, &offset)) {
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //   char <char>+ end_char offsets
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //   char <char>+ return value
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //   char end_char offsets
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //   char return value
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //   end_char offsets
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    //   return_value
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool did_consume = false;
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (key != key_end && !IsEOL(offset, end)) {
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Leading <char> is not a match. Don't dive into this child
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (!IsMatch(offset, end, key))
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        continue;
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      did_consume = true;
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ++offset;
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      ++key;
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Possible matches at this point:
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // <char>+ end_char offsets
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // <char>+ return value
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // end_char offsets
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // return value
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Remove all remaining <char> nodes possible
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      while (!IsEOL(offset, end) && key != key_end) {
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (!IsMatch(offset, end, key))
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return kNotFound;
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ++key;
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        ++offset;
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Possible matches at this point:
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // end_char offsets
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // return_value
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If one or more <char> elements were consumed, a failure
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // to match is terminal. Otherwise, try the next node.
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (key == key_end) {
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      int return_value;
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (GetReturnValue(offset, end, &return_value))
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return return_value;
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // The DAFSA guarantees that if the first char is a match, all
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // remaining char elements MUST match if the key is truly present.
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (did_consume)
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return kNotFound;
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!IsEndCharMatch(offset, end, key)) {
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (did_consume)
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return kNotFound;  // Unexpected
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ++key;
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pos = ++offset;  // Dive into child
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return kNotFound;  // No match
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
202a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)size_t GetRegistryLengthImpl(
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const std::string& host,
204a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    UnknownRegistryFilter unknown_filter,
205a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    PrivateRegistryFilter private_filter) {
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!host.empty());
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Skip leading dots.
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const size_t host_check_begin = host.find_first_not_of('.');
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host_check_begin == std::string::npos)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;  // Host is only dots.
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A single trailing dot isn't relevant in this determination, but does need
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to be included in the final returned length.
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t host_check_len = host.length();
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (host[host_check_len - 1] == '.') {
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    --host_check_len;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(host_check_len > 0);  // If this weren't true, the host would be ".",
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                 // and we'd have already returned above.
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (host[host_check_len - 1] == '.')
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return 0;  // Multiple trailing dots.
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Walk up the domain tree, most specific to least specific,
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // looking for matches at each level.
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t prev_start = std::string::npos;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t curr_start = host_check_begin;
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t next_dot = host.find('.', curr_start);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (next_dot >= host_check_len)  // Catches std::string::npos as well.
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return 0;  // This can't have a registry + domain.
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (1) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const char* domain_str = host.data() + curr_start;
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    size_t domain_length = host_check_len - curr_start;
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int type = LookupString(g_graph, g_graph_length, domain_str, domain_length);
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    bool do_check =
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        type != kNotFound && (!(type & kPrivateRule) ||
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                              private_filter == INCLUDE_PRIVATE_REGISTRIES);
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // If the apparent match is a private registry and we're not including
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // those, it can't be an actual match.
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (do_check) {
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Exception rules override wildcard rules when the domain is an exact
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // match, but wildcards take precedence when there's a subdomain.
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (type & kWildcardRule && (prev_start != std::string::npos)) {
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // If prev_start == host_check_begin, then the host is the registry
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        // itself, so return 0.
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return (prev_start == host_check_begin) ? 0
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                                : (host.length() - prev_start);
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (type & kExceptionRule) {
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        if (next_dot == std::string::npos) {
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // If we get here, we had an exception rule with no dots (e.g.
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // "!foo").  This would only be valid if we had a corresponding
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // wildcard rule, which would have to be "*".  But we explicitly
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          // disallow that case, so this kind of rule is invalid.
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          NOTREACHED() << "Invalid exception rule";
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          return 0;
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        }
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        return host.length() - next_dot - 1;
2617dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch      }
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // If curr_start == host_check_begin, then the host is the registry
264cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // itself, so return 0.
265cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      return (curr_start == host_check_begin) ? 0
266cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                              : (host.length() - curr_start);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (next_dot >= host_check_len)  // Catches std::string::npos as well.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    prev_start = curr_start;
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    curr_start = next_dot + 1;
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    next_dot = host.find('.', curr_start);
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // No rule found in the registry.  curr_start now points to the first
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // character of the last subcomponent of the host, so if we allow unknown
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // registries, return the length of this subcomponent.
280a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return unknown_filter == INCLUDE_UNKNOWN_REGISTRIES ?
281a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      (host.length() - curr_start) : 0;
282a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
283a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
284a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::string GetDomainAndRegistryImpl(
285a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const std::string& host, PrivateRegistryFilter private_filter) {
286a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(!host.empty());
287a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
288a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Find the length of the registry for this host.
289a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const size_t registry_length =
290a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      GetRegistryLengthImpl(host, INCLUDE_UNKNOWN_REGISTRIES, private_filter);
291a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if ((registry_length == std::string::npos) || (registry_length == 0))
292a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string();  // No registry.
293a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // The "2" in this next line is 1 for the dot, plus a 1-char minimum preceding
294a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // subcomponent length.
295a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  DCHECK(host.length() >= 2);
296a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (registry_length > (host.length() - 2)) {
297a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    NOTREACHED() <<
298a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)        "Host does not have at least one subcomponent before registry!";
299a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string();
300a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  }
301a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
302a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // Move past the dot preceding the registry, and search for the next previous
303a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // dot.  Return the host from after that dot, or the whole host when there is
304a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // no dot.
305a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const size_t dot = host.rfind('.', host.length() - registry_length - 2);
306a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (dot == std::string::npos)
307a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return host;
308a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return host.substr(dot + 1);
309a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
310a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
311a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}  // namespace
312a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
313a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::string GetDomainAndRegistry(
314a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GURL& gurl,
315a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    PrivateRegistryFilter filter) {
3165c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const url::Component host = gurl.parsed_for_possibly_invalid_spec().host;
317a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if ((host.len <= 0) || gurl.HostIsIPAddress())
318a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string();
319a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return GetDomainAndRegistryImpl(std::string(
320a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      gurl.possibly_invalid_spec().data() + host.begin, host.len), filter);
321a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
322a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
323a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)std::string GetDomainAndRegistry(
324a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const std::string& host,
325a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    PrivateRegistryFilter filter) {
3265c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::CanonHostInfo host_info;
327a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string canon_host(CanonicalizeHost(host, &host_info));
328a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (canon_host.empty() || host_info.IsIPAddress())
329a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string();
330a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return GetDomainAndRegistryImpl(canon_host, filter);
331a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
332a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
333a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)bool SameDomainOrHost(
334a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GURL& gurl1,
335a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GURL& gurl2,
336a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    PrivateRegistryFilter filter) {
337a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // See if both URLs have a known domain + registry, and those values are the
338a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // same.
339a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string domain1(GetDomainAndRegistry(gurl1, filter));
340a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string domain2(GetDomainAndRegistry(gurl2, filter));
341a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (!domain1.empty() || !domain2.empty())
342a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return domain1 == domain2;
343a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
344a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  // No domains.  See if the hosts are identical.
3455c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const url::Component host1 = gurl1.parsed_for_possibly_invalid_spec().host;
3465c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const url::Component host2 = gurl2.parsed_for_possibly_invalid_spec().host;
347a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if ((host1.len <= 0) || (host1.len != host2.len))
348a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return false;
349a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return !strncmp(gurl1.possibly_invalid_spec().data() + host1.begin,
350a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                  gurl2.possibly_invalid_spec().data() + host2.begin,
351a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)                  host1.len);
352a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
353a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
354a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)size_t GetRegistryLength(
355a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const GURL& gurl,
356a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    UnknownRegistryFilter unknown_filter,
357a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    PrivateRegistryFilter private_filter) {
3585c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  const url::Component host = gurl.parsed_for_possibly_invalid_spec().host;
359a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (host.len <= 0)
360a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string::npos;
361a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (gurl.HostIsIPAddress())
362a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return 0;
363a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return GetRegistryLengthImpl(
364a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      std::string(gurl.possibly_invalid_spec().data() + host.begin, host.len),
365a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      unknown_filter,
366a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)      private_filter);
367a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
368a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
369a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)size_t GetRegistryLength(
370a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    const std::string& host,
371a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    UnknownRegistryFilter unknown_filter,
372a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    PrivateRegistryFilter private_filter) {
3735c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::CanonHostInfo host_info;
374a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  const std::string canon_host(CanonicalizeHost(host, &host_info));
375a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (canon_host.empty())
376a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return std::string::npos;
377a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  if (host_info.IsIPAddress())
378a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    return 0;
379a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)  return GetRegistryLengthImpl(canon_host, unknown_filter, private_filter);
380a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}
381a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)
382cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SetFindDomainGraph() {
383cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  g_graph = kDafsa;
384cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  g_graph_length = sizeof(kDafsa);
385cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
386cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
387cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void SetFindDomainGraph(const unsigned char* domains, size_t length) {
388cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK(domains);
389cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  CHECK_NE(length, 0u);
390cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  g_graph = domains;
391cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  g_graph_length = length;
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
394a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)}  // namespace registry_controlled_domains
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
396