Coverage Report

Created: 2026-06-07 06:21

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/name.c
Line
Count
Source
1
/*
2
 * Copyright (C) Internet Systems Consortium, Inc. ("ISC")
3
 *
4
 * SPDX-License-Identifier: MPL-2.0
5
 *
6
 * This Source Code Form is subject to the terms of the Mozilla Public
7
 * License, v. 2.0. If a copy of the MPL was not distributed with this
8
 * file, you can obtain one at https://mozilla.org/MPL/2.0/.
9
 *
10
 * See the COPYRIGHT file distributed with this work for additional
11
 * information regarding copyright ownership.
12
 */
13
14
/*! \file */
15
16
#include <ctype.h>
17
#include <inttypes.h>
18
#include <stdbool.h>
19
#include <stdlib.h>
20
#include <unistd.h>
21
22
#include <isc/ascii.h>
23
#include <isc/attributes.h>
24
#include <isc/buffer.h>
25
#include <isc/hash.h>
26
#include <isc/hex.h>
27
#include <isc/mem.h>
28
#include <isc/once.h>
29
#include <isc/random.h>
30
#include <isc/result.h>
31
#include <isc/string.h>
32
#include <isc/thread.h>
33
#include <isc/util.h>
34
35
#include <dns/compress.h>
36
#include <dns/fixedname.h>
37
#include <dns/name.h>
38
39
typedef enum {
40
  ft_init = 0,
41
  ft_start,
42
  ft_ordinary,
43
  ft_initialescape,
44
  ft_escape,
45
  ft_escdecimal,
46
  ft_at
47
} ft_state;
48
49
/*%
50
 * Note that the name data must be a char array, not a string
51
 * literal, to avoid compiler warnings about discarding
52
 * the const attribute of a string.
53
 */
54
static unsigned char root_ndata[] = { "" };
55
static dns_name_t const root = DNS_NAME_INITABSOLUTE(root_ndata);
56
const dns_name_t *dns_rootname = &root;
57
58
static unsigned char wild_ndata[] = { "\001*" };
59
static dns_name_t const wild = DNS_NAME_INITNONABSOLUTE(wild_ndata);
60
const dns_name_t *dns_wildcardname = &wild;
61
62
static unsigned char ip6arpa_data[] = "\003IP6\004ARPA";
63
static dns_name_t const ip6arpa = DNS_NAME_INITABSOLUTE(ip6arpa_data);
64
const dns_name_t *dns_ip6arpa = &ip6arpa;
65
66
static unsigned char ip6int_data[] = "\003IP6\003INT";
67
static dns_name_t const ip6int = DNS_NAME_INITABSOLUTE(ip6int_data);
68
const dns_name_t *dns_ip6int = &ip6int;
69
70
static unsigned char inaddrarpa_data[] = "\007IN-ADDR\004ARPA";
71
static dns_name_t const inaddrarpa = DNS_NAME_INITABSOLUTE(inaddrarpa_data);
72
const dns_name_t *dns_inaddrarpa = &inaddrarpa;
73
74
/*
75
 * dns_name_t to text post-conversion procedure.
76
 */
77
static thread_local dns_name_totextfilter_t *totext_filter_proc = NULL;
78
79
bool
80
0
dns_name_isvalid(const dns_name_t *name) {
81
0
  unsigned char *ndata;
82
0
  unsigned int offset, count, length, nlabels;
83
84
0
  if (!DNS_NAME_VALID(name)) {
85
0
    return false;
86
0
  }
87
88
0
  ndata = name->ndata;
89
0
  length = name->length;
90
0
  offset = 0;
91
0
  nlabels = 0;
92
93
0
  while (offset != length) {
94
0
    count = *ndata;
95
0
    if (count > DNS_NAME_LABELLEN) {
96
0
      return false;
97
0
    }
98
99
0
    nlabels++;
100
0
    offset += count + 1;
101
0
    ndata += count + 1;
102
0
    if (offset > length) {
103
0
      return false;
104
0
    }
105
106
0
    if (count == 0) {
107
0
      break;
108
0
    }
109
0
  }
110
111
0
  if (nlabels > DNS_NAME_MAXLABELS || offset != name->length) {
112
0
    return false;
113
0
  }
114
115
0
  return true;
116
0
}
117
118
bool
119
209
dns_name_hasbuffer(const dns_name_t *name) {
120
  /*
121
   * Does 'name' have a dedicated buffer?
122
   */
123
124
209
  REQUIRE(DNS_NAME_VALID(name));
125
126
209
  if (name->buffer != NULL) {
127
209
    return true;
128
209
  }
129
130
0
  return false;
131
209
}
132
133
bool
134
12.8M
dns_name_isabsolute(const dns_name_t *name) {
135
  /*
136
   * Does 'name' end in the root label?
137
   */
138
139
12.8M
  REQUIRE(DNS_NAME_VALID(name));
140
141
12.8M
  return name->attributes.absolute;
142
12.8M
}
143
144
0
#define hyphenchar(c) ((c) == 0x2d)
145
#define asterchar(c)  ((c) == 0x2a)
146
#define alphachar(c) \
147
0
  (((c) >= 0x41 && (c) <= 0x5a) || ((c) >= 0x61 && (c) <= 0x7a))
148
0
#define digitchar(c)  ((c) >= 0x30 && (c) <= 0x39)
149
0
#define borderchar(c) (alphachar(c) || digitchar(c))
150
0
#define middlechar(c) (borderchar(c) || hyphenchar(c))
151
0
#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
152
153
bool
154
0
dns_name_ismailbox(const dns_name_t *name) {
155
0
  unsigned char *ndata, ch;
156
0
  unsigned int n;
157
0
  bool first;
158
159
0
  REQUIRE(DNS_NAME_VALID(name));
160
0
  REQUIRE(name->length > 0);
161
0
  REQUIRE(name->attributes.absolute);
162
163
  /*
164
   * Root label.
165
   */
166
0
  if (name->length == 1) {
167
0
    return true;
168
0
  }
169
170
0
  ndata = name->ndata;
171
0
  n = *ndata++;
172
0
  INSIST(n <= DNS_NAME_LABELLEN);
173
0
  while (n--) {
174
0
    ch = *ndata++;
175
0
    if (!domainchar(ch)) {
176
0
      return false;
177
0
    }
178
0
  }
179
180
0
  if (ndata == name->ndata + name->length) {
181
0
    return false;
182
0
  }
183
184
  /*
185
   * RFC952/RFC1123 hostname.
186
   */
187
0
  while (ndata < (name->ndata + name->length)) {
188
0
    n = *ndata++;
189
0
    INSIST(n <= DNS_NAME_LABELLEN);
190
0
    first = true;
191
0
    while (n--) {
192
0
      ch = *ndata++;
193
0
      if (first || n == 0) {
194
0
        if (!borderchar(ch)) {
195
0
          return false;
196
0
        }
197
0
      } else {
198
0
        if (!middlechar(ch)) {
199
0
          return false;
200
0
        }
201
0
      }
202
0
      first = false;
203
0
    }
204
0
  }
205
0
  return true;
206
0
}
207
208
bool
209
0
dns_name_ishostname(const dns_name_t *name, bool wildcard) {
210
0
  unsigned char *ndata, ch;
211
0
  unsigned int n;
212
0
  bool first;
213
214
0
  REQUIRE(DNS_NAME_VALID(name));
215
0
  REQUIRE(name->length > 0);
216
0
  REQUIRE(name->attributes.absolute);
217
218
  /*
219
   * Root label.
220
   */
221
0
  if (name->length == 1) {
222
0
    return true;
223
0
  }
224
225
  /*
226
   * Skip wildcard if this is a ownername.
227
   */
228
0
  ndata = name->ndata;
229
0
  if (wildcard && ndata[0] == 1 && ndata[1] == '*') {
230
0
    ndata += 2;
231
0
  }
232
233
  /*
234
   * RFC952/RFC1123 hostname.
235
   */
236
0
  while (ndata < (name->ndata + name->length)) {
237
0
    n = *ndata++;
238
0
    INSIST(n <= DNS_NAME_LABELLEN);
239
0
    first = true;
240
0
    while (n--) {
241
0
      ch = *ndata++;
242
0
      if (first || n == 0) {
243
0
        if (!borderchar(ch)) {
244
0
          return false;
245
0
        }
246
0
      } else {
247
0
        if (!middlechar(ch)) {
248
0
          return false;
249
0
        }
250
0
      }
251
0
      first = false;
252
0
    }
253
0
  }
254
0
  return true;
255
0
}
256
257
bool
258
26.7M
dns_name_iswildcard(const dns_name_t *name) {
259
26.7M
  unsigned char *ndata;
260
261
  /*
262
   * Is 'name' a wildcard name?
263
   */
264
265
26.7M
  REQUIRE(DNS_NAME_VALID(name));
266
26.7M
  REQUIRE(name->length > 0);
267
268
26.7M
  if (name->length >= 2) {
269
26.5M
    ndata = name->ndata;
270
26.5M
    if (ndata[0] == 1 && ndata[1] == '*') {
271
2.94M
      return true;
272
2.94M
    }
273
26.5M
  }
274
275
23.7M
  return false;
276
26.7M
}
277
278
bool
279
0
dns_name_internalwildcard(const dns_name_t *name) {
280
0
  unsigned char *ndata;
281
0
  unsigned int count;
282
0
  unsigned int label;
283
284
  /*
285
   * Does 'name' contain a internal wildcard?
286
   */
287
288
0
  REQUIRE(DNS_NAME_VALID(name));
289
290
  /*
291
   * Skip first label.
292
   */
293
0
  ndata = name->ndata;
294
0
  count = *ndata++;
295
0
  INSIST(count <= DNS_NAME_LABELLEN);
296
0
  ndata += count;
297
0
  label = 1;
298
299
0
  uint8_t labels = dns_name_countlabels(name);
300
0
  while (label + 1 < labels) {
301
0
    count = *ndata++;
302
0
    INSIST(count <= DNS_NAME_LABELLEN);
303
304
0
    if (count == 1 && *ndata == '*') {
305
0
      return true;
306
0
    }
307
0
    ndata += count;
308
0
    label++;
309
0
  }
310
0
  return false;
311
0
}
312
313
uint32_t
314
243k
dns_name_hash(const dns_name_t *name) {
315
243k
  REQUIRE(DNS_NAME_VALID(name));
316
317
243k
  return isc_hash32(name->ndata, name->length, false);
318
243k
}
319
320
dns_namereln_t
321
dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
322
12.2M
         int *orderp, unsigned int *nlabelsp) {
323
12.2M
  unsigned int l1, l2, l, count1, count2, count, nlabels;
324
12.2M
  int cdiff, ldiff, diff;
325
12.2M
  unsigned char *label1, *label2;
326
12.2M
  dns_offsets_t offsets1, offsets2;
327
12.2M
  dns_namereln_t namereln = dns_namereln_none;
328
329
  /*
330
   * Determine the relative ordering under the DNSSEC order relation of
331
   * 'name1' and 'name2', and also determine the hierarchical
332
   * relationship of the names.
333
   *
334
   * Note: It makes no sense for one of the names to be relative and the
335
   * other absolute.  If both names are relative, then to be meaningfully
336
   * compared the caller must ensure that they are both relative to the
337
   * same domain.
338
   */
339
340
12.2M
  REQUIRE(DNS_NAME_VALID(name1));
341
12.2M
  REQUIRE(DNS_NAME_VALID(name2));
342
12.2M
  REQUIRE(orderp != NULL);
343
12.2M
  REQUIRE(nlabelsp != NULL);
344
  /*
345
   * Either name1 is absolute and name2 is absolute, or neither is.
346
   */
347
12.2M
  REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
348
349
12.2M
  if (name1 == name2) {
350
1.42k
    *orderp = 0;
351
1.42k
    *nlabelsp = dns_name_countlabels(name1);
352
353
1.42k
    return dns_namereln_equal;
354
1.42k
  }
355
356
12.2M
  l1 = dns_name_offsets(name1, offsets1);
357
12.2M
  l2 = dns_name_offsets(name2, offsets2);
358
359
12.2M
  nlabels = 0;
360
12.2M
  if (l2 > l1) {
361
26
    l = l1;
362
26
    ldiff = 0 - (l2 - l1);
363
12.2M
  } else {
364
12.2M
    l = l2;
365
12.2M
    ldiff = l1 - l2;
366
12.2M
  }
367
368
24.5M
  while (l-- > 0) {
369
12.2M
    l1--;
370
12.2M
    l2--;
371
12.2M
    label1 = &name1->ndata[offsets1[l1]];
372
12.2M
    label2 = &name2->ndata[offsets2[l2]];
373
12.2M
    count1 = *label1++;
374
12.2M
    count2 = *label2++;
375
376
12.2M
    cdiff = (int)count1 - (int)count2;
377
12.2M
    if (cdiff < 0) {
378
33
      count = count1;
379
12.2M
    } else {
380
12.2M
      count = count2;
381
12.2M
    }
382
383
12.2M
    diff = isc_ascii_lowercmp(label1, label2, count);
384
12.2M
    if (diff != 0) {
385
207
      *orderp = diff;
386
207
      goto done;
387
207
    }
388
389
12.2M
    if (cdiff != 0) {
390
52
      *orderp = cdiff;
391
52
      goto done;
392
52
    }
393
12.2M
    nlabels++;
394
12.2M
  }
395
396
12.2M
  *orderp = ldiff;
397
12.2M
  if (ldiff < 0) {
398
20
    namereln = dns_namereln_contains;
399
12.2M
  } else if (ldiff > 0) {
400
12.1M
    namereln = dns_namereln_subdomain;
401
12.1M
  } else {
402
149k
    namereln = dns_namereln_equal;
403
149k
  }
404
12.2M
  *nlabelsp = nlabels;
405
12.2M
  return namereln;
406
407
259
done:
408
259
  *nlabelsp = nlabels;
409
259
  if (nlabels > 0) {
410
259
    namereln = dns_namereln_commonancestor;
411
259
  }
412
413
259
  return namereln;
414
12.2M
}
415
416
int
417
1.77k
dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
418
1.77k
  int order;
419
1.77k
  unsigned int nlabels;
420
421
  /*
422
   * Determine the relative ordering under the DNSSEC order relation of
423
   * 'name1' and 'name2'.
424
   *
425
   * Note: It makes no sense for one of the names to be relative and the
426
   * other absolute.  If both names are relative, then to be meaningfully
427
   * compared the caller must ensure that they are both relative to the
428
   * same domain.
429
   */
430
431
1.77k
  (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
432
433
1.77k
  return order;
434
1.77k
}
435
436
bool
437
242k
dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
438
242k
  unsigned int length;
439
440
  /*
441
   * Are 'name1' and 'name2' equal?
442
   *
443
   * Note: It makes no sense for one of the names to be relative and the
444
   * other absolute.  If both names are relative, then to be meaningfully
445
   * compared the caller must ensure that they are both relative to the
446
   * same domain.
447
   */
448
449
242k
  REQUIRE(DNS_NAME_VALID(name1));
450
242k
  REQUIRE(DNS_NAME_VALID(name2));
451
  /*
452
   * Either name1 is absolute and name2 is absolute, or neither is.
453
   */
454
242k
  REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
455
456
242k
  if (name1 == name2) {
457
0
    return true;
458
0
  }
459
460
242k
  length = name1->length;
461
242k
  if (length != name2->length) {
462
17.7k
    return false;
463
17.7k
  }
464
465
  /* label lengths are < 64 so tolower() does not affect them */
466
224k
  return isc_ascii_lowerequal(name1->ndata, name2->ndata, length);
467
242k
}
468
469
bool
470
68.7k
dns_name_caseequal(const dns_name_t *name1, const dns_name_t *name2) {
471
  /*
472
   * Are 'name1' and 'name2' equal?
473
   *
474
   * Note: It makes no sense for one of the names to be relative and the
475
   * other absolute.  If both names are relative, then to be meaningfully
476
   * compared the caller must ensure that they are both relative to the
477
   * same domain.
478
   */
479
480
68.7k
  REQUIRE(DNS_NAME_VALID(name1));
481
68.7k
  REQUIRE(DNS_NAME_VALID(name2));
482
  /*
483
   * Either name1 is absolute and name2 is absolute, or neither is.
484
   */
485
68.7k
  REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
486
487
68.7k
  if (name1->length != name2->length) {
488
21.5k
    return false;
489
21.5k
  }
490
491
47.1k
  if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) {
492
7.98k
    return false;
493
7.98k
  }
494
495
39.1k
  return true;
496
47.1k
}
497
498
int
499
24.2M
dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
500
  /*
501
   * Compare two absolute names as rdata.
502
   */
503
504
24.2M
  REQUIRE(DNS_NAME_VALID(name1));
505
24.2M
  REQUIRE(name1->length > 0);
506
24.2M
  REQUIRE(name1->attributes.absolute);
507
24.2M
  REQUIRE(DNS_NAME_VALID(name2));
508
24.2M
  REQUIRE(name2->length > 0);
509
24.2M
  REQUIRE(name2->attributes.absolute);
510
511
  /* label lengths are < 64 so tolower() does not affect them */
512
24.2M
  return isc_ascii_lowercmp(name1->ndata, name2->ndata,
513
24.2M
          ISC_MIN(name1->length, name2->length));
514
24.2M
}
515
516
bool
517
12.2M
dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
518
12.2M
  int order;
519
12.2M
  unsigned int nlabels;
520
12.2M
  dns_namereln_t namereln;
521
522
  /*
523
   * Is 'name1' a subdomain of 'name2'?
524
   *
525
   * Note: It makes no sense for one of the names to be relative and the
526
   * other absolute.  If both names are relative, then to be meaningfully
527
   * compared the caller must ensure that they are both relative to the
528
   * same domain.
529
   */
530
531
12.2M
  namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
532
12.2M
  if (namereln == dns_namereln_subdomain ||
533
149k
      namereln == dns_namereln_equal)
534
12.2M
  {
535
12.2M
    return true;
536
12.2M
  }
537
538
2
  return false;
539
12.2M
}
540
541
bool
542
0
dns_name_matcheswildcard(const dns_name_t *name, const dns_name_t *wname) {
543
0
  int order;
544
0
  unsigned int nlabels, labels;
545
0
  dns_name_t tname;
546
547
0
  REQUIRE(DNS_NAME_VALID(name));
548
0
  REQUIRE(name->length > 0);
549
0
  REQUIRE(DNS_NAME_VALID(wname));
550
0
  labels = dns_name_countlabels(wname);
551
0
  REQUIRE(labels > 0);
552
0
  REQUIRE(dns_name_iswildcard(wname));
553
554
0
  dns_name_init(&tname);
555
0
  dns_name_getlabelsequence(wname, 1, labels - 1, &tname);
556
0
  if (dns_name_fullcompare(name, &tname, &order, &nlabels) ==
557
0
      dns_namereln_subdomain)
558
0
  {
559
0
    return true;
560
0
  }
561
0
  return false;
562
0
}
563
564
void
565
5.01k
dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
566
5.01k
  dns_offsets_t offsets;
567
568
  /*
569
   * Make 'label' refer to the 'n'th least significant label of 'name'.
570
   */
571
572
5.01k
  REQUIRE(DNS_NAME_VALID(name));
573
5.01k
  REQUIRE(label != NULL);
574
575
5.01k
  uint8_t labels = dns_name_offsets(name, offsets);
576
577
5.01k
  REQUIRE(labels > 0);
578
5.01k
  REQUIRE(n < labels);
579
580
5.01k
  label->base = &name->ndata[offsets[n]];
581
5.01k
  if (n == (unsigned int)labels - 1) {
582
2.87k
    label->length = name->length - offsets[n];
583
2.87k
  } else {
584
2.13k
    label->length = offsets[n + 1] - offsets[n];
585
2.13k
  }
586
5.01k
}
587
588
void
589
dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
590
17.4M
        unsigned int n, dns_name_t *target) {
591
17.4M
  unsigned char *p, l;
592
17.4M
  unsigned int firstoffset, endoffset;
593
17.4M
  unsigned int i;
594
595
  /*
596
   * Make 'target' refer to the 'n' labels including and following
597
   * 'first' in 'source'.
598
   */
599
600
17.4M
  REQUIRE(DNS_NAME_VALID(source));
601
17.4M
  REQUIRE(DNS_NAME_VALID(target));
602
17.4M
  REQUIRE(DNS_NAME_BINDABLE(target));
603
604
17.4M
  uint8_t labels = dns_name_countlabels(source);
605
17.4M
  REQUIRE(first <= labels && n <= labels - first);
606
607
17.4M
  p = source->ndata;
608
17.4M
  if (first == labels) {
609
0
    firstoffset = source->length;
610
17.4M
  } else {
611
162M
    for (i = 0; i < first; i++) {
612
145M
      l = *p;
613
145M
      p += l + 1;
614
145M
    }
615
17.4M
    firstoffset = (unsigned int)(p - source->ndata);
616
17.4M
  }
617
618
17.4M
  if (first + n == labels) {
619
17.4M
    endoffset = source->length;
620
17.4M
  } else {
621
0
    for (i = 0; i < n; i++) {
622
0
      l = *p;
623
0
      p += l + 1;
624
0
    }
625
0
    endoffset = (unsigned int)(p - source->ndata);
626
0
  }
627
628
17.4M
  target->ndata = &source->ndata[firstoffset];
629
17.4M
  target->length = endoffset - firstoffset;
630
631
17.4M
  if (first + n == labels && n > 0 && source->attributes.absolute) {
632
17.4M
    target->attributes.absolute = true;
633
17.4M
  } else {
634
0
    target->attributes.absolute = false;
635
0
  }
636
17.4M
}
637
638
void
639
2.71k
dns_name_clone(const dns_name_t *source, dns_name_t *target) {
640
  /*
641
   * Make 'target' refer to the same name as 'source'.
642
   */
643
644
2.71k
  REQUIRE(DNS_NAME_VALID(source));
645
2.71k
  REQUIRE(DNS_NAME_VALID(target));
646
2.71k
  REQUIRE(DNS_NAME_BINDABLE(target));
647
648
2.71k
  target->ndata = source->ndata;
649
2.71k
  target->length = source->length;
650
2.71k
  target->attributes = source->attributes;
651
2.71k
  target->attributes.readonly = false;
652
2.71k
  target->attributes.dynamic = false;
653
2.71k
}
654
655
void
656
49.0M
dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
657
49.0M
  size_t length;
658
49.0M
  isc_region_t r2 = { .base = NULL, .length = 0 };
659
660
  /*
661
   * Make 'name' refer to region 'r'.
662
   */
663
664
49.0M
  REQUIRE(DNS_NAME_VALID(name));
665
49.0M
  REQUIRE(r != NULL);
666
49.0M
  REQUIRE(DNS_NAME_BINDABLE(name));
667
668
49.0M
  name->ndata = r->base;
669
49.0M
  if (name->buffer != NULL) {
670
37.6k
    isc_buffer_clear(name->buffer);
671
37.6k
    isc_buffer_availableregion(name->buffer, &r2);
672
37.6k
    length = (r->length < r2.length) ? r->length : r2.length;
673
37.6k
    if (length > DNS_NAME_MAXWIRE) {
674
0
      length = DNS_NAME_MAXWIRE;
675
0
    }
676
49.0M
  } else {
677
49.0M
    length = (r->length <= DNS_NAME_MAXWIRE) ? r->length
678
49.0M
               : DNS_NAME_MAXWIRE;
679
49.0M
  }
680
681
49.0M
  name->attributes.absolute = false;
682
683
49.0M
  if (length > 0) {
684
49.0M
    size_t offset = 0;
685
49.0M
    uint8_t nlabels = 0;
686
109M
    while (offset != length) {
687
109M
      uint8_t count;
688
689
109M
      INSIST(nlabels < DNS_NAME_MAXLABELS);
690
109M
      nlabels++;
691
692
109M
      count = name->ndata[offset];
693
109M
      INSIST(count <= DNS_NAME_LABELLEN);
694
695
109M
      offset += count + 1;
696
109M
      INSIST(offset <= length);
697
698
109M
      if (count == 0) {
699
49.0M
        name->attributes.absolute = true;
700
49.0M
        break;
701
49.0M
      }
702
109M
    }
703
49.0M
    name->length = offset;
704
49.0M
  }
705
706
49.0M
  if (name->buffer != NULL) {
707
    /*
708
     * name->length has been updated by set_offsets to the actual
709
     * length of the name data so we can now copy the actual name
710
     * data and not anything after it.
711
     */
712
37.6k
    if (name->length > 0) {
713
37.6k
      memmove(r2.base, r->base, name->length);
714
37.6k
    }
715
37.6k
    name->ndata = r2.base;
716
37.6k
    isc_buffer_add(name->buffer, name->length);
717
37.6k
  }
718
49.0M
}
719
720
static isc_result_t
721
convert_text(isc_buffer_t *source, const dns_name_t *origin,
722
23.9M
       unsigned int options, dns_name_t *name, isc_buffer_t *target) {
723
23.9M
  unsigned char *ndata = NULL, *label = NULL;
724
23.9M
  char *tdata = NULL;
725
23.9M
  char c;
726
23.9M
  ft_state state;
727
23.9M
  unsigned int value = 0, count = 0;
728
23.9M
  unsigned int n1 = 0, n2 = 0;
729
23.9M
  unsigned int tlen, nrem, nused, digits = 0, labels, tused;
730
23.9M
  bool done;
731
23.9M
  bool downcase;
732
733
23.9M
  REQUIRE(DNS_NAME_VALID(name));
734
23.9M
  REQUIRE(ISC_BUFFER_VALID(source));
735
23.9M
  REQUIRE(ISC_BUFFER_VALID(target));
736
737
23.9M
  downcase = ((options & DNS_NAME_DOWNCASE) != 0);
738
739
23.9M
  if (target == NULL && name->buffer != NULL) {
740
0
    target = name->buffer;
741
0
    isc_buffer_clear(target);
742
0
  }
743
744
23.9M
  REQUIRE(DNS_NAME_BINDABLE(name));
745
746
  /*
747
   * Set up the state machine.
748
   */
749
23.9M
  tdata = (char *)source->base + source->current;
750
23.9M
  tlen = isc_buffer_remaininglength(source);
751
23.9M
  tused = 0;
752
23.9M
  ndata = isc_buffer_used(target);
753
23.9M
  nrem = isc_buffer_availablelength(target);
754
23.9M
  if (nrem > DNS_NAME_MAXWIRE) {
755
1.08M
    nrem = DNS_NAME_MAXWIRE;
756
1.08M
  }
757
23.9M
  nused = 0;
758
23.9M
  labels = 0;
759
23.9M
  done = false;
760
23.9M
  state = ft_init;
761
762
154M
  while (nrem > 0 && tlen > 0 && !done) {
763
130M
    c = *tdata++;
764
130M
    tlen--;
765
130M
    tused++;
766
767
130M
    switch (state) {
768
23.9M
    case ft_init:
769
      /*
770
       * Is this the root name?
771
       */
772
23.9M
      if (c == '.') {
773
321k
        if (tlen != 0) {
774
77
          return DNS_R_EMPTYLABEL;
775
77
        }
776
321k
        labels++;
777
321k
        *ndata++ = 0;
778
321k
        nrem--;
779
321k
        nused++;
780
321k
        done = true;
781
321k
        break;
782
321k
      }
783
23.6M
      if (c == '@' && tlen == 0) {
784
401k
        state = ft_at;
785
401k
        break;
786
401k
      }
787
788
23.2M
      FALLTHROUGH;
789
37.6M
    case ft_start:
790
37.6M
      label = ndata;
791
37.6M
      ndata++;
792
37.6M
      nrem--;
793
37.6M
      nused++;
794
37.6M
      count = 0;
795
37.6M
      if (c == '\\') {
796
150k
        state = ft_initialescape;
797
150k
        break;
798
150k
      }
799
37.5M
      state = ft_ordinary;
800
37.5M
      if (nrem == 0) {
801
11
        return ISC_R_NOSPACE;
802
11
      }
803
37.5M
      FALLTHROUGH;
804
128M
    case ft_ordinary:
805
128M
      if (c == '.') {
806
14.5M
        if (count == 0) {
807
25
          return DNS_R_EMPTYLABEL;
808
25
        }
809
14.5M
        *label = count;
810
14.5M
        labels++;
811
14.5M
        INSIST(labels < DNS_NAME_MAXLABELS);
812
14.5M
        if (tlen == 0) {
813
149k
          labels++;
814
149k
          *ndata++ = 0;
815
149k
          nrem--;
816
149k
          nused++;
817
149k
          done = true;
818
149k
        }
819
14.5M
        state = ft_start;
820
114M
      } else if (c == '\\') {
821
822k
        state = ft_escape;
822
113M
      } else {
823
113M
        if (count >= DNS_NAME_LABELLEN) {
824
57
          return DNS_R_LABELTOOLONG;
825
57
        }
826
113M
        count++;
827
113M
        if (downcase) {
828
0
          c = isc_ascii_tolower(c);
829
0
        }
830
113M
        *ndata++ = c;
831
113M
        nrem--;
832
113M
        nused++;
833
113M
      }
834
128M
      break;
835
128M
    case ft_initialescape:
836
150k
      if (c == '[') {
837
        /*
838
         * This looks like a bitstring label, which
839
         * was deprecated.  Intentionally drop it.
840
         */
841
5
        return DNS_R_BADLABELTYPE;
842
5
      }
843
150k
      state = ft_escape;
844
150k
      POST(state);
845
150k
      FALLTHROUGH;
846
973k
    case ft_escape:
847
973k
      if (!isdigit((unsigned char)c)) {
848
926k
        if (count >= DNS_NAME_LABELLEN) {
849
3
          return DNS_R_LABELTOOLONG;
850
3
        }
851
926k
        count++;
852
926k
        if (downcase) {
853
0
          c = isc_ascii_tolower(c);
854
0
        }
855
926k
        *ndata++ = c;
856
926k
        nrem--;
857
926k
        nused++;
858
926k
        state = ft_ordinary;
859
926k
        break;
860
926k
      }
861
46.9k
      digits = 0;
862
46.9k
      value = 0;
863
46.9k
      state = ft_escdecimal;
864
46.9k
      FALLTHROUGH;
865
140k
    case ft_escdecimal:
866
140k
      if (!isdigit((unsigned char)c)) {
867
12
        return DNS_R_BADESCAPE;
868
12
      }
869
140k
      value = 10 * value + c - '0';
870
140k
      digits++;
871
140k
      if (digits == 3) {
872
46.8k
        if (value > 255) {
873
18
          return DNS_R_BADESCAPE;
874
18
        }
875
46.8k
        if (count >= DNS_NAME_LABELLEN) {
876
4
          return DNS_R_LABELTOOLONG;
877
4
        }
878
46.8k
        count++;
879
46.8k
        if (downcase) {
880
0
          value = isc_ascii_tolower(value);
881
0
        }
882
46.8k
        *ndata++ = value;
883
46.8k
        nrem--;
884
46.8k
        nused++;
885
46.8k
        state = ft_ordinary;
886
46.8k
      }
887
140k
      break;
888
140k
    default:
889
0
      FATAL_ERROR("Unexpected state %d", state);
890
      /* Does not return. */
891
130M
    }
892
130M
  }
893
894
23.9M
  if (!done) {
895
23.4M
    if (nrem == 0) {
896
13
      return ISC_R_NOSPACE;
897
13
    }
898
23.4M
    INSIST(tlen == 0);
899
23.4M
    if (state != ft_ordinary && state != ft_at) {
900
93
      return ISC_R_UNEXPECTEDEND;
901
93
    }
902
23.4M
    if (state == ft_ordinary) {
903
23.0M
      INSIST(count != 0);
904
23.0M
      INSIST(label != NULL);
905
23.0M
      *label = count;
906
23.0M
      labels++;
907
23.0M
      INSIST(labels < DNS_NAME_MAXLABELS);
908
23.0M
    }
909
23.4M
    if (origin != NULL) {
910
23.4M
      if (nrem < origin->length) {
911
7
        return ISC_R_NOSPACE;
912
7
      }
913
23.4M
      label = origin->ndata;
914
23.4M
      n1 = origin->length;
915
23.4M
      nrem -= n1;
916
23.4M
      POST(nrem);
917
47.4M
      while (n1 > 0) {
918
23.9M
        n2 = *label++;
919
23.9M
        INSIST(n2 <= DNS_NAME_LABELLEN);
920
23.9M
        *ndata++ = n2;
921
23.9M
        n1 -= n2 + 1;
922
23.9M
        nused += n2 + 1;
923
26.6M
        while (n2 > 0) {
924
2.62M
          c = *label++;
925
2.62M
          if (downcase) {
926
0
            c = isc_ascii_tolower(c);
927
0
          }
928
2.62M
          *ndata++ = c;
929
2.62M
          n2--;
930
2.62M
        }
931
23.9M
        labels++;
932
23.9M
        if (n1 > 0) {
933
489k
          INSIST(labels < DNS_NAME_MAXLABELS);
934
489k
        }
935
23.9M
      }
936
23.4M
      if (origin->attributes.absolute) {
937
23.4M
        name->attributes.absolute = true;
938
23.4M
      }
939
23.4M
    }
940
23.4M
  } else {
941
471k
    name->attributes.absolute = true;
942
471k
  }
943
944
23.9M
  name->ndata = (unsigned char *)target->base + target->used;
945
23.9M
  name->length = nused;
946
947
23.9M
  isc_buffer_forward(source, tused);
948
23.9M
  isc_buffer_add(target, name->length);
949
950
23.9M
  return ISC_R_SUCCESS;
951
23.9M
}
952
953
isc_result_t
954
dns_name_wirefromtext(isc_buffer_t *source, const dns_name_t *origin,
955
1.09M
          unsigned int options, isc_buffer_t *target) {
956
1.09M
  dns_name_t name;
957
958
1.09M
  REQUIRE(ISC_BUFFER_VALID(target));
959
960
1.09M
  dns_name_init(&name);
961
1.09M
  return convert_text(source, origin, options, &name, target);
962
1.09M
}
963
964
isc_result_t
965
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
966
22.8M
      const dns_name_t *origin, unsigned int options) {
967
22.8M
  REQUIRE(DNS_NAME_VALID(name));
968
22.8M
  REQUIRE(ISC_BUFFER_VALID(name->buffer));
969
970
22.8M
  isc_buffer_clear(name->buffer);
971
22.8M
  return convert_text(source, origin, options, name, name->buffer);
972
22.8M
}
973
974
isc_result_t
975
dns_name_totext(const dns_name_t *name, unsigned int options,
976
894k
    isc_buffer_t *target) {
977
894k
  isc_result_t result;
978
894k
  unsigned char *ndata = NULL;
979
894k
  unsigned int nlen;
980
894k
  unsigned int labels;
981
894k
  bool saw_root = false;
982
894k
  unsigned int oused;
983
894k
  bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
984
894k
  bool first = true;
985
986
  /*
987
   * This function assumes the name is in proper uncompressed
988
   * wire format.
989
   */
990
894k
  REQUIRE(DNS_NAME_VALID(name));
991
894k
  REQUIRE(ISC_BUFFER_VALID(target));
992
993
894k
  oused = target->used;
994
995
894k
  ndata = name->ndata;
996
894k
  nlen = name->length;
997
894k
  labels = dns_name_countlabels(name);
998
999
894k
  if (labels == 0 && nlen == 0) {
1000
    /*
1001
     * Special handling for an empty name.
1002
     */
1003
0
    omit_final_dot = true;
1004
0
    CHECK(isc_buffer_reserve(target, 1));
1005
0
    isc_buffer_putuint8(target, '@');
1006
1007
    /*
1008
     * Skip the while() loop.
1009
     */
1010
0
    nlen = 0;
1011
894k
  } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1012
    /*
1013
     * Special handling for the root label.
1014
     */
1015
387k
    saw_root = true;
1016
387k
    omit_final_dot = false;
1017
1018
    /*
1019
     * Skip the while() loop.
1020
     */
1021
387k
    nlen = 0;
1022
387k
  }
1023
1024
6.07M
  while (labels > 0 && nlen > 0) {
1025
5.68M
    unsigned int count = *ndata++;
1026
5.68M
    labels--;
1027
5.68M
    nlen--;
1028
5.68M
    if (count == 0) {
1029
506k
      saw_root = true;
1030
506k
      break;
1031
5.17M
    } else if (!first) {
1032
4.67M
      CHECK(isc_buffer_reserve(target, 1));
1033
4.67M
      isc_buffer_putuint8(target, '.');
1034
4.67M
    }
1035
5.17M
    first = false;
1036
1037
5.17M
    if (count <= DNS_NAME_LABELLEN) {
1038
5.17M
      unsigned char c;
1039
1040
5.17M
      INSIST(nlen >= count);
1041
1042
90.6M
      while (count > 0) {
1043
85.4M
        uint32_t value;
1044
1045
85.4M
        c = *ndata;
1046
85.4M
        switch (c) {
1047
        /* Special modifiers in zone files. */
1048
482k
        case 0x40: /* '@' */
1049
1.02M
        case 0x24: /* '$' */
1050
1.02M
          if ((options & DNS_NAME_PRINCIPAL) != 0)
1051
0
          {
1052
0
            goto no_escape;
1053
0
          }
1054
1.02M
          FALLTHROUGH;
1055
1.21M
        case 0x22: /* '"' */
1056
1.51M
        case 0x28: /* '(' */
1057
1.80M
        case 0x29: /* ')' */
1058
2.08M
        case 0x2E: /* '.' */
1059
2.29M
        case 0x3B: /* ';' */
1060
2.31M
        case 0x5C: /* '\\' */
1061
2.31M
          value = '\\' << 8 | c;
1062
2.31M
          CHECK(isc_buffer_reserve(target, 2));
1063
2.31M
          isc_buffer_putuint16(target, value);
1064
2.31M
          ndata++;
1065
2.31M
          nlen--;
1066
2.31M
          break;
1067
0
        no_escape:
1068
83.1M
        default:
1069
83.1M
          if (c > 0x20 && c < 0x7f) {
1070
5.38M
            CHECK(isc_buffer_reserve(target,
1071
5.38M
                   1));
1072
5.38M
            isc_buffer_putuint8(target, c);
1073
5.38M
            ndata++;
1074
5.38M
            nlen--;
1075
77.7M
          } else {
1076
77.7M
            value = 0x5c << 24;
1077
77.7M
            value |= (0x30 +
1078
77.7M
                ((c / 100) % 10))
1079
77.7M
               << 16;
1080
77.7M
            value |=
1081
77.7M
              (0x30 + ((c / 10) % 10))
1082
77.7M
              << 8;
1083
77.7M
            value |= 0x30 + (c % 10);
1084
77.7M
            CHECK(isc_buffer_reserve(target,
1085
77.7M
                   4));
1086
77.7M
            isc_buffer_putuint32(target,
1087
77.7M
                     value);
1088
77.7M
            ndata++;
1089
77.7M
            nlen--;
1090
77.7M
          }
1091
85.4M
        }
1092
85.4M
        count--;
1093
85.4M
      }
1094
5.17M
    } else {
1095
0
      FATAL_ERROR("Unexpected label type %02x", count);
1096
0
      UNREACHABLE();
1097
0
    }
1098
5.17M
  }
1099
1100
894k
  if (saw_root && !omit_final_dot) {
1101
891k
    CHECK(isc_buffer_reserve(target, 1));
1102
891k
    isc_buffer_putuint8(target, '.');
1103
891k
  }
1104
1105
894k
  if (isc_buffer_availablelength(target) > 1) {
1106
894k
    uint8_t *p = isc_buffer_used(target);
1107
894k
    *p = 0;
1108
894k
  }
1109
1110
894k
  if (totext_filter_proc != NULL) {
1111
0
    return (totext_filter_proc)(target, oused);
1112
0
  }
1113
1114
894k
  return ISC_R_SUCCESS;
1115
1116
7
cleanup:
1117
7
  return result;
1118
894k
}
1119
1120
isc_result_t
1121
dns_name_tofilenametext(const dns_name_t *name, bool omit_final_dot,
1122
0
      isc_buffer_t *target) {
1123
0
  unsigned char *ndata;
1124
0
  char *tdata;
1125
0
  unsigned int nlen, tlen;
1126
0
  unsigned char c;
1127
0
  unsigned int trem, count;
1128
0
  unsigned int labels;
1129
1130
  /*
1131
   * This function assumes the name is in proper uncompressed
1132
   * wire format.
1133
   */
1134
0
  REQUIRE(DNS_NAME_VALID(name));
1135
0
  REQUIRE(name->attributes.absolute);
1136
0
  REQUIRE(ISC_BUFFER_VALID(target));
1137
1138
0
  ndata = name->ndata;
1139
0
  nlen = name->length;
1140
0
  labels = dns_name_countlabels(name);
1141
0
  tdata = isc_buffer_used(target);
1142
0
  tlen = isc_buffer_availablelength(target);
1143
1144
0
  trem = tlen;
1145
1146
0
  if (nlen == 1 && labels == 1 && *ndata == '\0') {
1147
    /*
1148
     * Special handling for the root label.
1149
     */
1150
0
    if (trem == 0) {
1151
0
      return ISC_R_NOSPACE;
1152
0
    }
1153
1154
0
    omit_final_dot = false;
1155
0
    *tdata++ = '.';
1156
0
    trem--;
1157
1158
    /*
1159
     * Skip the while() loop.
1160
     */
1161
0
    nlen = 0;
1162
0
  }
1163
1164
0
  while (labels > 0 && nlen > 0 && trem > 0) {
1165
0
    labels--;
1166
0
    count = *ndata++;
1167
0
    nlen--;
1168
0
    if (count == 0) {
1169
0
      break;
1170
0
    }
1171
0
    if (count <= DNS_NAME_LABELLEN) {
1172
0
      INSIST(nlen >= count);
1173
0
      while (count > 0) {
1174
0
        c = *ndata;
1175
0
        if ((c >= 0x30 && c <= 0x39) || /* digit */
1176
0
            (c >= 0x41 && c <= 0x5A) || /* uppercase */
1177
0
            (c >= 0x61 && c <= 0x7A) || /* lowercase */
1178
0
            c == 0x2D ||   /* hyphen */
1179
0
            c == 0x5F)     /* underscore */
1180
0
        {
1181
0
          if (trem == 0) {
1182
0
            return ISC_R_NOSPACE;
1183
0
          }
1184
          /* downcase */
1185
0
          if (c >= 0x41 && c <= 0x5A) {
1186
0
            c += 0x20;
1187
0
          }
1188
0
          *tdata++ = c;
1189
0
          ndata++;
1190
0
          trem--;
1191
0
          nlen--;
1192
0
        } else {
1193
0
          if (trem < 4) {
1194
0
            return ISC_R_NOSPACE;
1195
0
          }
1196
0
          snprintf(tdata, trem, "%%%02X", c);
1197
0
          tdata += 3;
1198
0
          trem -= 3;
1199
0
          ndata++;
1200
0
          nlen--;
1201
0
        }
1202
0
        count--;
1203
0
      }
1204
0
    } else {
1205
0
      FATAL_ERROR("Unexpected label type %02x", count);
1206
0
      UNREACHABLE();
1207
0
    }
1208
1209
    /*
1210
     * The following assumes names are absolute.  If not, we
1211
     * fix things up later.  Note that this means that in some
1212
     * cases one more byte of text buffer is required than is
1213
     * needed in the final output.
1214
     */
1215
0
    if (trem == 0) {
1216
0
      return ISC_R_NOSPACE;
1217
0
    }
1218
0
    *tdata++ = '.';
1219
0
    trem--;
1220
0
  }
1221
1222
0
  if (nlen != 0 && trem == 0) {
1223
0
    return ISC_R_NOSPACE;
1224
0
  }
1225
1226
0
  if (omit_final_dot) {
1227
0
    trem++;
1228
0
  }
1229
1230
0
  isc_buffer_add(target, tlen - trem);
1231
1232
0
  return ISC_R_SUCCESS;
1233
0
}
1234
1235
isc_result_t
1236
327
dns_name_downcase(const dns_name_t *source, dns_name_t *name) {
1237
  /*
1238
   * Downcase 'source'.
1239
   */
1240
1241
327
  REQUIRE(DNS_NAME_VALID(source));
1242
327
  REQUIRE(DNS_NAME_VALID(name));
1243
1244
327
  if (source == name) {
1245
325
    REQUIRE(!name->attributes.readonly);
1246
325
    isc_ascii_lowercopy(name->ndata, source->ndata, source->length);
1247
325
    return ISC_R_SUCCESS;
1248
325
  }
1249
1250
2
  REQUIRE(DNS_NAME_BINDABLE(name));
1251
2
  REQUIRE(ISC_BUFFER_VALID(name->buffer));
1252
1253
2
  isc_buffer_clear(name->buffer);
1254
2
  name->ndata = (uint8_t *)name->buffer->base + name->buffer->used;
1255
1256
  /* label lengths are < 64 so tolower() does not affect them */
1257
2
  isc_ascii_lowercopy(name->ndata, source->ndata, source->length);
1258
1259
2
  name->length = source->length;
1260
2
  name->attributes = (struct dns_name_attrs){
1261
2
    .absolute = source->attributes.absolute
1262
2
  };
1263
2
  isc_buffer_add(name->buffer, name->length);
1264
1265
2
  return ISC_R_SUCCESS;
1266
327
}
1267
1268
isc_result_t
1269
dns_name_fromwire(dns_name_t *const name, isc_buffer_t *const source,
1270
1.89M
      const dns_decompress_t dctx, isc_buffer_t *target) {
1271
  /*
1272
   * Copy the name at source into target, decompressing it.
1273
   *
1274
   *  *** WARNING ***
1275
   *
1276
   * dns_name_fromwire() deals with raw network data. An error in this
1277
   * routine could result in the failure or hijacking of the server.
1278
   *
1279
   * The description of name compression in RFC 1035 section 4.1.4 is
1280
   * subtle wrt certain edge cases. The first important sentence is:
1281
   *
1282
   * > In this scheme, an entire domain name or a list of labels at the
1283
   * > end of a domain name is replaced with a pointer to a prior
1284
   * > occurrence of the same name.
1285
   *
1286
   * The key word is "prior". This says that compression pointers must
1287
   * point strictly earlier in the message (before our "marker" variable),
1288
   * which is enough to prevent DoS attacks due to compression loops.
1289
   *
1290
   * The next important sentence is:
1291
   *
1292
   * > If a domain name is contained in a part of the message subject to a
1293
   * > length field (such as the RDATA section of an RR), and compression
1294
   * > is used, the length of the compressed name is used in the length
1295
   * > calculation, rather than the length of the expanded name.
1296
   *
1297
   * When decompressing, this means that the amount of the source buffer
1298
   * that we consumed (which is checked wrt the container's length field)
1299
   * is the length of the compressed name. A compressed name is defined as
1300
   * a sequence of labels ending with the root label or a compression
1301
   * pointer, that is, the segment of the name that dns_name_fromwire()
1302
   * examines first.
1303
   *
1304
   * This matters when handling names that play dirty tricks, like:
1305
   *
1306
   *  +---+---+---+---+---+---+
1307
   *  | 4 | 1 |'a'|192| 0 | 0 |
1308
   *  +---+---+---+---+---+---+
1309
   *
1310
   * We start at octet 1. There is an ordinary single character label "a",
1311
   * followed by a compression pointer that refers back to octet zero.
1312
   * Here there is a label of length 4, which weirdly re-uses the octets
1313
   * we already examined as the data for the label. It is followed by the
1314
   * root label,
1315
   *
1316
   * The specification says that the compressed name ends after the first
1317
   * zero octet (after the compression pointer) not the second zero octet,
1318
   * even though the second octet is later in the message. This shows the
1319
   * correct way to set our "consumed" variable.
1320
   */
1321
1322
1.89M
  REQUIRE(DNS_NAME_VALID(name));
1323
1.89M
  REQUIRE(DNS_NAME_BINDABLE(name));
1324
1.89M
  REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1325
1.89M
    (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1326
1327
1.89M
  if (target == NULL && name->buffer != NULL) {
1328
7.61k
    target = name->buffer;
1329
7.61k
    isc_buffer_clear(target);
1330
7.61k
  }
1331
1332
1.89M
  uint8_t *const name_buf = isc_buffer_used(target);
1333
1.89M
  const uint32_t name_max = ISC_MIN(DNS_NAME_MAXWIRE,
1334
1.89M
            isc_buffer_availablelength(target));
1335
1.89M
  uint32_t name_len = 0;
1336
1337
  /*
1338
   * After chasing a compression pointer, these variables refer to the
1339
   * source buffer as follows:
1340
   *
1341
   * sb --- mr --- cr --- st --- cd --- sm
1342
   *
1343
   * sb = source_buf (const)
1344
   * mr = marker
1345
   * cr = cursor
1346
   * st = start (const)
1347
   * cd = consumed
1348
   * sm = source_max (const)
1349
   *
1350
   * The marker hops backwards for each pointer.
1351
   * The cursor steps forwards for each label.
1352
   * The amount of the source we consumed is set once.
1353
   */
1354
1.89M
  const uint8_t *const source_buf = isc_buffer_base(source);
1355
1.89M
  const uint8_t *const source_max = isc_buffer_used(source);
1356
1.89M
  const uint8_t *const start = isc_buffer_current(source);
1357
1.89M
  const uint8_t *marker = start;
1358
1.89M
  const uint8_t *cursor = start;
1359
1.89M
  const uint8_t *consumed = NULL;
1360
1361
  /*
1362
   * One iteration per label.
1363
   */
1364
14.7M
  while (cursor < source_max) {
1365
14.7M
    const uint8_t label_len = *cursor++;
1366
14.7M
    if (label_len <= DNS_NAME_LABELLEN) {
1367
      /*
1368
       * Normal label: record its offset, and check bounds on
1369
       * the name length, which also ensures we don't overrun
1370
       * the offsets array. Don't touch any source bytes yet!
1371
       * The source bounds check will happen when we loop.
1372
       */
1373
      /* and then a step to the ri-i-i-i-i-ight */
1374
13.1M
      cursor += label_len;
1375
13.1M
      name_len += label_len + 1;
1376
13.1M
      if (name_len > name_max) {
1377
58.8k
        return name_max == DNS_NAME_MAXWIRE
1378
58.8k
                 ? DNS_R_NAMETOOLONG
1379
58.8k
                 : ISC_R_NOSPACE;
1380
13.0M
      } else if (label_len == 0) {
1381
1.82M
        goto root_label;
1382
1.82M
      }
1383
13.1M
    } else if (label_len < 192) {
1384
677
      return DNS_R_BADLABELTYPE;
1385
1.65M
    } else if (!dns_decompress_getpermitted(dctx)) {
1386
257
      return DNS_R_DISALLOWED;
1387
1.65M
    } else if (cursor < source_max) {
1388
      /*
1389
       * Compression pointer. Ensure it does not loop.
1390
       *
1391
       * Copy multiple labels in one go, to make the most of
1392
       * memmove() performance. Start at the marker and finish
1393
       * just before the pointer's hi+lo bytes, before the
1394
       * cursor. Bounds were already checked.
1395
       */
1396
1.65M
      const uint32_t hi = label_len & 0x3F;
1397
1.65M
      const uint32_t lo = *cursor++;
1398
1.65M
      const uint8_t *pointer = source_buf + (256 * hi + lo);
1399
1.65M
      if (pointer >= marker) {
1400
89
        return DNS_R_BADPOINTER;
1401
89
      }
1402
1.65M
      const uint32_t copy_len = (cursor - 2) - marker;
1403
1.65M
      uint8_t *const dest = name_buf + name_len - copy_len;
1404
1.65M
      memmove(dest, marker, copy_len);
1405
1.65M
      consumed = consumed != NULL ? consumed : cursor;
1406
      /* it's just a jump to the left */
1407
1.65M
      cursor = marker = pointer;
1408
1.65M
    }
1409
14.7M
  }
1410
2.65k
  return ISC_R_UNEXPECTEDEND;
1411
1.82M
root_label:;
1412
  /*
1413
   * Copy labels almost like we do for compression pointers,
1414
   * from the marker up to and including the root label.
1415
   */
1416
1.82M
  const uint32_t copy_len = cursor - marker;
1417
1.82M
  memmove(name_buf + name_len - copy_len, marker, copy_len);
1418
1.82M
  consumed = consumed != NULL ? consumed : cursor;
1419
1.82M
  isc_buffer_forward(source, consumed - start);
1420
1421
1.82M
  name->attributes.absolute = true;
1422
1.82M
  name->ndata = name_buf;
1423
1.82M
  name->length = name_len;
1424
1.82M
  isc_buffer_add(target, name_len);
1425
1426
1.82M
  return ISC_R_SUCCESS;
1427
1.89M
}
1428
1429
isc_result_t
1430
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1431
10.8M
    isc_buffer_t *target) {
1432
10.8M
  bool compress, multi;
1433
10.8M
  unsigned int here;
1434
10.8M
  unsigned int prefix_length;
1435
10.8M
  unsigned int suffix_coff;
1436
1437
  /*
1438
   * Convert 'name' into wire format, compressing it as specified by the
1439
   * compression context 'cctx' (or without compressing if 'cctx'
1440
   * is NULL), and storing the result in 'target'.
1441
   */
1442
1443
10.8M
  REQUIRE(DNS_NAME_VALID(name));
1444
10.8M
  REQUIRE(ISC_BUFFER_VALID(target));
1445
1446
10.8M
  if (cctx == NULL) {
1447
10.5M
    if (isc_buffer_availablelength(target) < name->length) {
1448
0
      return ISC_R_NOSPACE;
1449
0
    }
1450
10.5M
    memmove(isc_buffer_used(target), name->ndata, name->length);
1451
10.5M
    isc_buffer_add(target, name->length);
1452
10.5M
    return ISC_R_SUCCESS;
1453
10.5M
  }
1454
1455
286k
  compress = !name->attributes.nocompress &&
1456
286k
       dns_compress_getpermitted(cctx);
1457
286k
  multi = compress && dns_compress_getmultiuse(cctx);
1458
1459
  /*
1460
   * Write a compression pointer directly if the caller passed us
1461
   * a pointer to this name's offset that we saved previously.
1462
   */
1463
286k
  if (multi && cctx->coff < 0x4000) {
1464
0
    if (isc_buffer_availablelength(target) < 2) {
1465
0
      return ISC_R_NOSPACE;
1466
0
    }
1467
0
    isc_buffer_putuint16(target, cctx->coff | 0xc000);
1468
0
    return ISC_R_SUCCESS;
1469
0
  }
1470
1471
  /*
1472
   * Always add the name to the compression context; if compression
1473
   * is off, reset the return values before writing the name.
1474
   */
1475
286k
  prefix_length = name->length;
1476
286k
  suffix_coff = 0;
1477
286k
  dns_compress_name(cctx, target, name, &prefix_length, &suffix_coff);
1478
286k
  if (!compress) {
1479
24.2k
    prefix_length = name->length;
1480
24.2k
    suffix_coff = 0;
1481
24.2k
  }
1482
1483
  /*
1484
   * Return this name's compression offset for use next time, provided
1485
   * it isn't too short for compression to help (i.e. it's the root)
1486
   */
1487
286k
  here = isc_buffer_usedlength(target);
1488
286k
  if (multi && here < 0x4000 && prefix_length > 1) {
1489
0
    cctx->coff = (uint16_t)here;
1490
0
  }
1491
1492
286k
  if (prefix_length > 0) {
1493
263k
    if (isc_buffer_availablelength(target) < prefix_length) {
1494
92.1k
      return ISC_R_NOSPACE;
1495
92.1k
    }
1496
171k
    memmove(isc_buffer_used(target), name->ndata, prefix_length);
1497
171k
    isc_buffer_add(target, prefix_length);
1498
171k
  }
1499
1500
194k
  if (suffix_coff > 0) {
1501
33.8k
    if (multi && prefix_length == 0) {
1502
0
      cctx->coff = suffix_coff;
1503
0
    }
1504
33.8k
    if (isc_buffer_availablelength(target) < 2) {
1505
92
      return ISC_R_NOSPACE;
1506
92
    }
1507
33.7k
    isc_buffer_putuint16(target, suffix_coff | 0xc000);
1508
33.7k
  }
1509
1510
194k
  return ISC_R_SUCCESS;
1511
194k
}
1512
1513
isc_result_t
1514
dns_name_concatenate(const dns_name_t *prefix, const dns_name_t *suffix,
1515
0
         dns_name_t *name) {
1516
0
  unsigned char *ndata = NULL;
1517
0
  unsigned int nrem, prefix_length, length;
1518
0
  bool copy_prefix = true;
1519
0
  bool copy_suffix = true;
1520
0
  bool absolute = false;
1521
0
  dns_name_t tmp_name;
1522
0
  isc_buffer_t *target = NULL;
1523
1524
  /*
1525
   * Concatenate 'prefix' and 'suffix'.
1526
   */
1527
1528
0
  REQUIRE(prefix == NULL || DNS_NAME_VALID(prefix));
1529
0
  REQUIRE(suffix == NULL || DNS_NAME_VALID(suffix));
1530
0
  REQUIRE(DNS_NAME_VALID(name) && ISC_BUFFER_VALID(name->buffer));
1531
0
  REQUIRE(DNS_NAME_BINDABLE(name));
1532
1533
0
  if (prefix == NULL || prefix->length == 0) {
1534
0
    copy_prefix = false;
1535
0
  }
1536
0
  if (suffix == NULL || suffix->length == 0) {
1537
0
    copy_suffix = false;
1538
0
  }
1539
0
  if (copy_prefix && prefix->attributes.absolute) {
1540
0
    absolute = true;
1541
0
    REQUIRE(!copy_suffix);
1542
0
  }
1543
0
  if (name == NULL) {
1544
0
    dns_name_init(&tmp_name);
1545
0
    name = &tmp_name;
1546
0
  }
1547
1548
0
  target = name->buffer;
1549
0
  isc_buffer_clear(target);
1550
1551
  /*
1552
   * Set up.
1553
   */
1554
0
  nrem = target->length - target->used;
1555
0
  ndata = (unsigned char *)target->base + target->used;
1556
0
  if (nrem > DNS_NAME_MAXWIRE) {
1557
0
    nrem = DNS_NAME_MAXWIRE;
1558
0
  }
1559
0
  length = 0;
1560
0
  prefix_length = 0;
1561
0
  if (copy_prefix) {
1562
0
    prefix_length = prefix->length;
1563
0
    length += prefix_length;
1564
0
  }
1565
0
  if (copy_suffix) {
1566
0
    length += suffix->length;
1567
0
  }
1568
0
  if (length > DNS_NAME_MAXWIRE) {
1569
0
    return DNS_R_NAMETOOLONG;
1570
0
  }
1571
0
  if (length > nrem) {
1572
0
    return ISC_R_NOSPACE;
1573
0
  }
1574
1575
0
  if (copy_suffix) {
1576
0
    if (suffix->attributes.absolute) {
1577
0
      absolute = true;
1578
0
    }
1579
0
    memmove(ndata + prefix_length, suffix->ndata, suffix->length);
1580
0
  }
1581
1582
  /*
1583
   * If 'prefix' and 'name' are the same object, we don't have to
1584
   * copy anything.
1585
   */
1586
0
  if (copy_prefix && (prefix != name || prefix->buffer != target)) {
1587
0
    memmove(ndata, prefix->ndata, prefix_length);
1588
0
  }
1589
1590
0
  name->ndata = ndata;
1591
0
  name->length = length;
1592
0
  name->attributes.absolute = absolute;
1593
1594
0
  isc_buffer_add(target, name->length);
1595
1596
0
  return ISC_R_SUCCESS;
1597
0
}
1598
1599
void
1600
12.6M
dns_name_dup(const dns_name_t *source, isc_mem_t *mctx, dns_name_t *target) {
1601
  /*
1602
   * Make 'target' a dynamically allocated copy of 'source'.
1603
   */
1604
1605
12.6M
  REQUIRE(DNS_NAME_VALID(source));
1606
12.6M
  REQUIRE(source->length > 0);
1607
12.6M
  REQUIRE(DNS_NAME_VALID(target));
1608
12.6M
  REQUIRE(DNS_NAME_BINDABLE(target));
1609
1610
12.6M
  target->ndata = isc_mem_get(mctx, source->length);
1611
1612
12.6M
  memmove(target->ndata, source->ndata, source->length);
1613
1614
12.6M
  target->length = source->length;
1615
12.6M
  target->attributes = (struct dns_name_attrs){ .dynamic = true };
1616
12.6M
  target->attributes.absolute = source->attributes.absolute;
1617
12.6M
}
1618
1619
void
1620
12.6M
dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
1621
12.6M
  size_t size;
1622
1623
  /*
1624
   * Free 'name'.
1625
   */
1626
1627
12.6M
  REQUIRE(DNS_NAME_VALID(name));
1628
12.6M
  REQUIRE(name->attributes.dynamic);
1629
1630
12.6M
  size = name->length;
1631
12.6M
  isc_mem_put(mctx, name->ndata, size);
1632
12.6M
  dns_name_invalidate(name);
1633
12.6M
}
1634
1635
size_t
1636
0
dns_name_size(const dns_name_t *name) {
1637
0
  size_t size;
1638
1639
0
  REQUIRE(DNS_NAME_VALID(name));
1640
1641
0
  if (!name->attributes.dynamic) {
1642
0
    return 0;
1643
0
  }
1644
1645
0
  size = name->length;
1646
1647
0
  return size;
1648
0
}
1649
1650
isc_result_t
1651
0
dns_name_digest(const dns_name_t *name, dns_digestfunc_t digest, void *arg) {
1652
  /*
1653
   * Send 'name' in DNSSEC canonical form to 'digest'.
1654
   */
1655
1656
0
  REQUIRE(DNS_NAME_VALID(name));
1657
0
  REQUIRE(digest != NULL);
1658
1659
0
  unsigned char ndata[DNS_NAME_MAXWIRE];
1660
0
  isc_ascii_lowercopy(ndata, name->ndata, name->length);
1661
1662
0
  isc_region_t r = {
1663
0
    .base = ndata,
1664
0
    .length = name->length,
1665
0
  };
1666
0
  return (digest)(arg, &r);
1667
0
}
1668
1669
bool
1670
484k
dns_name_dynamic(const dns_name_t *name) {
1671
484k
  REQUIRE(DNS_NAME_VALID(name));
1672
1673
  /*
1674
   * Returns whether there is dynamic memory associated with this name.
1675
   */
1676
1677
484k
  return name->attributes.dynamic;
1678
484k
}
1679
1680
isc_result_t
1681
0
dns_name_print(const dns_name_t *name, FILE *stream) {
1682
0
  isc_buffer_t b;
1683
0
  isc_region_t r;
1684
0
  char t[1024];
1685
1686
  /*
1687
   * Print 'name' on 'stream'.
1688
   */
1689
1690
0
  REQUIRE(DNS_NAME_VALID(name));
1691
1692
0
  isc_buffer_init(&b, t, sizeof(t));
1693
0
  RETERR(dns_name_totext(name, 0, &b));
1694
0
  isc_buffer_usedregion(&b, &r);
1695
0
  fprintf(stream, "%.*s", (int)r.length, (char *)r.base);
1696
1697
0
  return ISC_R_SUCCESS;
1698
0
}
1699
1700
isc_result_t
1701
0
dns_name_settotextfilter(dns_name_totextfilter_t *proc) {
1702
  /*
1703
   * If we already have been here set / clear as appropriate.
1704
   */
1705
0
  if (totext_filter_proc != NULL && proc != NULL) {
1706
0
    if (totext_filter_proc == proc) {
1707
0
      return ISC_R_SUCCESS;
1708
0
    }
1709
0
  }
1710
0
  if (proc == NULL && totext_filter_proc != NULL) {
1711
0
    totext_filter_proc = NULL;
1712
0
    return ISC_R_SUCCESS;
1713
0
  }
1714
1715
0
  totext_filter_proc = proc;
1716
1717
0
  return ISC_R_SUCCESS;
1718
0
}
1719
1720
void
1721
23.1k
dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
1722
23.1k
  isc_result_t result;
1723
23.1k
  isc_buffer_t buf;
1724
1725
23.1k
  REQUIRE(size > 0);
1726
1727
  /*
1728
   * Leave room for null termination after buffer.
1729
   */
1730
23.1k
  isc_buffer_init(&buf, cp, size - 1);
1731
23.1k
  result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buf);
1732
23.1k
  if (result == ISC_R_SUCCESS) {
1733
23.1k
    isc_buffer_putuint8(&buf, (uint8_t)'\0');
1734
23.1k
  } else {
1735
0
    snprintf(cp, size, "<unknown>");
1736
0
  }
1737
23.1k
}
1738
1739
/*
1740
 * dns_name_tostring() -- similar to dns_name_format() but allocates its own
1741
 * memory.
1742
 */
1743
isc_result_t
1744
0
dns_name_tostring(const dns_name_t *name, char **target, isc_mem_t *mctx) {
1745
0
  isc_buffer_t buf;
1746
0
  isc_region_t reg;
1747
0
  char *p, txt[DNS_NAME_FORMATSIZE];
1748
1749
0
  REQUIRE(DNS_NAME_VALID(name));
1750
0
  REQUIRE(target != NULL && *target == NULL);
1751
1752
0
  isc_buffer_init(&buf, txt, sizeof(txt));
1753
0
  RETERR(dns_name_totext(name, 0, &buf));
1754
1755
0
  isc_buffer_usedregion(&buf, &reg);
1756
0
  p = isc_mem_allocate(mctx, reg.length + 1);
1757
0
  memmove(p, (char *)reg.base, (int)reg.length);
1758
0
  p[reg.length] = '\0';
1759
1760
0
  *target = p;
1761
0
  return ISC_R_SUCCESS;
1762
0
}
1763
1764
isc_result_t
1765
dns_name_fromstring(dns_name_t *target, const char *src,
1766
        const dns_name_t *origin, unsigned int options,
1767
4
        isc_mem_t *mctx) {
1768
4
  isc_buffer_t buf;
1769
4
  dns_fixedname_t fn;
1770
4
  dns_name_t *name;
1771
1772
4
  REQUIRE(src != NULL);
1773
1774
4
  isc_buffer_constinit(&buf, src, strlen(src));
1775
4
  isc_buffer_add(&buf, strlen(src));
1776
4
  if (DNS_NAME_BINDABLE(target) && target->buffer != NULL) {
1777
4
    name = target;
1778
4
  } else {
1779
0
    name = dns_fixedname_initname(&fn);
1780
0
  }
1781
1782
4
  RETERR(dns_name_fromtext(name, &buf, origin, options));
1783
1784
4
  if (name != target) {
1785
0
    dns_name_dup(name, mctx, target);
1786
0
  }
1787
1788
4
  return ISC_R_SUCCESS;
1789
4
}
1790
1791
void
1792
303k
dns_name_copy(const dns_name_t *source, dns_name_t *dest) {
1793
303k
  isc_buffer_t *target = NULL;
1794
303k
  unsigned char *ndata = NULL;
1795
1796
303k
  REQUIRE(DNS_NAME_VALID(source));
1797
303k
  REQUIRE(DNS_NAME_VALID(dest));
1798
303k
  REQUIRE(DNS_NAME_BINDABLE(dest));
1799
1800
303k
  target = dest->buffer;
1801
1802
303k
  REQUIRE(target != NULL);
1803
303k
  REQUIRE(target->length >= source->length);
1804
1805
303k
  isc_buffer_clear(target);
1806
1807
303k
  ndata = (unsigned char *)target->base;
1808
303k
  dest->ndata = target->base;
1809
1810
303k
  if (source->length != 0) {
1811
303k
    memmove(ndata, source->ndata, source->length);
1812
303k
  }
1813
1814
303k
  dest->ndata = ndata;
1815
303k
  dest->length = source->length;
1816
303k
  dest->attributes.absolute = source->attributes.absolute;
1817
1818
303k
  isc_buffer_add(target, dest->length);
1819
303k
}
1820
1821
/*
1822
 * Service Discovery Prefixes RFC 6763.
1823
 */
1824
static unsigned char b_dns_sd_udp_data[] = "\001b\007_dns-sd\004_udp";
1825
static unsigned char db_dns_sd_udp_data[] = "\002db\007_dns-sd\004_udp";
1826
static unsigned char r_dns_sd_udp_data[] = "\001r\007_dns-sd\004_udp";
1827
static unsigned char dr_dns_sd_udp_data[] = "\002dr\007_dns-sd\004_udp";
1828
static unsigned char lb_dns_sd_udp_data[] = "\002lb\007_dns-sd\004_udp";
1829
1830
static dns_name_t const dns_sd[] = {
1831
  DNS_NAME_INITNONABSOLUTE(b_dns_sd_udp_data),
1832
  DNS_NAME_INITNONABSOLUTE(db_dns_sd_udp_data),
1833
  DNS_NAME_INITNONABSOLUTE(r_dns_sd_udp_data),
1834
  DNS_NAME_INITNONABSOLUTE(dr_dns_sd_udp_data),
1835
  DNS_NAME_INITNONABSOLUTE(lb_dns_sd_udp_data)
1836
};
1837
1838
bool
1839
0
dns_name_isdnssd(const dns_name_t *name) {
1840
0
  size_t i;
1841
0
  dns_name_t prefix;
1842
1843
0
  if (dns_name_countlabels(name) > 3U) {
1844
0
    dns_name_init(&prefix);
1845
0
    dns_name_getlabelsequence(name, 0, 3, &prefix);
1846
0
    for (i = 0; i < (sizeof(dns_sd) / sizeof(dns_sd[0])); i++) {
1847
0
      if (dns_name_equal(&prefix, &dns_sd[i])) {
1848
0
        return true;
1849
0
      }
1850
0
    }
1851
0
  }
1852
1853
0
  return false;
1854
0
}
1855
1856
static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
1857
1858
static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
1859
static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
1860
static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
1861
static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
1862
static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
1863
static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
1864
static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
1865
static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
1866
static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
1867
static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
1868
static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
1869
static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
1870
static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
1871
static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
1872
static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
1873
static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
1874
1875
static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
1876
1877
static dns_name_t const rfc1918names[] = {
1878
  DNS_NAME_INITABSOLUTE(inaddr10),    DNS_NAME_INITABSOLUTE(inaddr16172),
1879
  DNS_NAME_INITABSOLUTE(inaddr17172), DNS_NAME_INITABSOLUTE(inaddr18172),
1880
  DNS_NAME_INITABSOLUTE(inaddr19172), DNS_NAME_INITABSOLUTE(inaddr20172),
1881
  DNS_NAME_INITABSOLUTE(inaddr21172), DNS_NAME_INITABSOLUTE(inaddr22172),
1882
  DNS_NAME_INITABSOLUTE(inaddr23172), DNS_NAME_INITABSOLUTE(inaddr24172),
1883
  DNS_NAME_INITABSOLUTE(inaddr25172), DNS_NAME_INITABSOLUTE(inaddr26172),
1884
  DNS_NAME_INITABSOLUTE(inaddr27172), DNS_NAME_INITABSOLUTE(inaddr28172),
1885
  DNS_NAME_INITABSOLUTE(inaddr29172), DNS_NAME_INITABSOLUTE(inaddr30172),
1886
  DNS_NAME_INITABSOLUTE(inaddr31172), DNS_NAME_INITABSOLUTE(inaddr168192)
1887
};
1888
1889
bool
1890
0
dns_name_isrfc1918(const dns_name_t *name) {
1891
0
  size_t i;
1892
1893
0
  for (i = 0; i < (sizeof(rfc1918names) / sizeof(*rfc1918names)); i++) {
1894
0
    if (dns_name_issubdomain(name, &rfc1918names[i])) {
1895
0
      return true;
1896
0
    }
1897
0
  }
1898
0
  return false;
1899
0
}
1900
1901
static unsigned char ip6fc[] = "\001c\001f\003ip6\004ARPA";
1902
static unsigned char ip6fd[] = "\001d\001f\003ip6\004ARPA";
1903
1904
static dns_name_t const ulanames[] = { DNS_NAME_INITABSOLUTE(ip6fc),
1905
               DNS_NAME_INITABSOLUTE(ip6fd) };
1906
1907
bool
1908
0
dns_name_isula(const dns_name_t *name) {
1909
0
  size_t i;
1910
1911
0
  for (i = 0; i < (sizeof(ulanames) / sizeof(*ulanames)); i++) {
1912
0
    if (dns_name_issubdomain(name, &ulanames[i])) {
1913
0
      return true;
1914
0
    }
1915
0
  }
1916
0
  return false;
1917
0
}
1918
1919
bool
1920
0
dns_name_istat(const dns_name_t *name) {
1921
0
  unsigned char len;
1922
0
  const unsigned char *ndata;
1923
1924
0
  REQUIRE(DNS_NAME_VALID(name));
1925
1926
0
  if (name->length == 0) {
1927
0
    return false;
1928
0
  }
1929
1930
0
  ndata = name->ndata;
1931
0
  len = ndata[0];
1932
0
  INSIST(len <= name->length);
1933
0
  ndata++;
1934
1935
  /*
1936
   * Is there at least one trust anchor reported and is the
1937
   * label length consistent with a trust-anchor-telemetry label.
1938
   */
1939
0
  if ((len < 8) || (len - 3) % 5 != 0) {
1940
0
    return false;
1941
0
  }
1942
1943
0
  if (ndata[0] != '_' || isc_ascii_tolower(ndata[1]) != 't' ||
1944
0
      isc_ascii_tolower(ndata[2]) != 'a')
1945
0
  {
1946
0
    return false;
1947
0
  }
1948
0
  ndata += 3;
1949
0
  len -= 3;
1950
1951
0
  while (len > 0) {
1952
0
    INSIST(len >= 5);
1953
0
    if (ndata[0] != '-' || !isc_hex_char(ndata[1]) ||
1954
0
        !isc_hex_char(ndata[2]) || !isc_hex_char(ndata[3]) ||
1955
0
        !isc_hex_char(ndata[4]))
1956
0
    {
1957
0
      return false;
1958
0
    }
1959
0
    ndata += 5;
1960
0
    len -= 5;
1961
0
  }
1962
0
  return true;
1963
0
}
1964
1965
bool
1966
0
dns_name_isdnssvcb(const dns_name_t *name) {
1967
0
  unsigned char len, len1;
1968
0
  const unsigned char *ndata;
1969
1970
0
  REQUIRE(DNS_NAME_VALID(name));
1971
1972
0
  if (name->length < 5) {
1973
0
    return false;
1974
0
  }
1975
1976
0
  ndata = name->ndata;
1977
0
  len = len1 = ndata[0];
1978
0
  INSIST(len <= name->length);
1979
0
  ndata++;
1980
1981
0
  if (len < 2 || ndata[0] != '_') {
1982
0
    return false;
1983
0
  }
1984
0
  if (isdigit(ndata[1]) && name->length > len + 1) {
1985
0
    char buf[sizeof("65000")];
1986
0
    long port;
1987
0
    char *endp;
1988
1989
    /*
1990
     * Do we have a valid _port label?
1991
     */
1992
0
    if (len > 6U || (ndata[1] == '0' && len != 2)) {
1993
0
      return false;
1994
0
    }
1995
0
    memcpy(buf, ndata + 1, len - 1);
1996
0
    buf[len - 1] = 0;
1997
0
    port = strtol(buf, &endp, 10);
1998
0
    if (*endp != 0 || port < 0 || port > 0xffff) {
1999
0
      return false;
2000
0
    }
2001
2002
    /*
2003
     * Move to next label.
2004
     */
2005
0
    ndata += len;
2006
0
    INSIST(len1 + 1U < name->length);
2007
0
    len = *ndata;
2008
0
    INSIST(len + len1 + 1U <= name->length);
2009
0
    ndata++;
2010
0
  }
2011
2012
0
  if (len == 4U && strncasecmp((const char *)ndata, "_dns", 4) == 0) {
2013
0
    return true;
2014
0
  }
2015
2016
0
  return false;
2017
0
}
2018
2019
bool
2020
0
dns_name_israd(const dns_name_t *name, const dns_name_t *rad) {
2021
0
  dns_name_t suffix;
2022
0
  char labelbuf[64];
2023
0
  unsigned long v, last = ULONG_MAX;
2024
0
  char *end, *l;
2025
2026
0
  REQUIRE(DNS_NAME_VALID(name));
2027
0
  REQUIRE(DNS_NAME_VALID(rad));
2028
2029
0
  uint8_t name_labels = dns_name_countlabels(name);
2030
0
  uint8_t rad_labels = dns_name_countlabels(rad);
2031
2032
0
  if (name_labels < rad_labels + 4U || name->length < 4U) {
2033
0
    return false;
2034
0
  }
2035
2036
0
  if (name->ndata[0] != 3 || name->ndata[1] != '_' ||
2037
0
      tolower(name->ndata[2]) != 'e' || tolower(name->ndata[3]) != 'r')
2038
0
  {
2039
0
    return false;
2040
0
  }
2041
2042
0
  dns_name_init(&suffix);
2043
0
  dns_name_split(name, rad_labels + 1, NULL, &suffix);
2044
2045
0
  if (suffix.ndata[0] != 3 || suffix.ndata[1] != '_' ||
2046
0
      tolower(suffix.ndata[2]) != 'e' || tolower(suffix.ndata[3]) != 'r')
2047
0
  {
2048
0
    return false;
2049
0
  }
2050
2051
  /* type list */
2052
0
  dns_name_split(name, name_labels - 1, NULL, &suffix);
2053
0
  INSIST(*suffix.ndata < sizeof(labelbuf));
2054
0
  memmove(labelbuf, suffix.ndata + 1, *suffix.ndata);
2055
0
  labelbuf[*suffix.ndata] = 0;
2056
0
  if (strlen(labelbuf) != *suffix.ndata) {
2057
0
    return false;
2058
0
  }
2059
0
  l = labelbuf;
2060
0
  do {
2061
0
    v = strtoul(l, &end, 10);
2062
0
    if (v > 0xffff || (*end != 0 && *end != '-') || end == l) {
2063
0
      return false;
2064
0
    }
2065
0
    if (last != ULONG_MAX && v <= last) {
2066
0
      return false;
2067
0
    }
2068
0
    last = v;
2069
0
    if (*end == '-') {
2070
0
      l = end + 1;
2071
0
    }
2072
0
  } while (*end != 0);
2073
2074
  /* extended error code */
2075
0
  dns_name_split(name, rad_labels + 2, NULL, &suffix);
2076
0
  INSIST(*suffix.ndata < sizeof(labelbuf));
2077
0
  memmove(labelbuf, suffix.ndata + 1, *suffix.ndata);
2078
0
  labelbuf[*suffix.ndata] = 0;
2079
0
  if (strlen(labelbuf) != *suffix.ndata) {
2080
0
    return false;
2081
0
  }
2082
0
  v = strtoul(labelbuf, &end, 10);
2083
0
  if (v > 0xfff || *end != 0) {
2084
0
    return false;
2085
0
  }
2086
2087
0
  return dns_name_issubdomain(name, rad);
2088
0
}
2089
2090
uint8_t
2091
116M
dns_name_offsets(const dns_name_t *name, dns_offsets_t offsets) {
2092
116M
  REQUIRE(DNS_NAME_VALID(name));
2093
116M
  unsigned int offset, count, length, nlabels;
2094
116M
  unsigned char *ndata;
2095
2096
116M
  ndata = name->ndata;
2097
116M
  length = name->length;
2098
116M
  offset = 0;
2099
116M
  nlabels = 0;
2100
799M
  while (offset != length) {
2101
799M
    INSIST(nlabels < DNS_NAME_MAXLABELS);
2102
799M
    if (offsets != NULL) {
2103
310M
      offsets[nlabels] = offset;
2104
310M
    }
2105
799M
    nlabels++;
2106
799M
    count = *ndata;
2107
799M
    INSIST(count <= DNS_NAME_LABELLEN);
2108
799M
    offset += count + 1;
2109
799M
    ndata += count + 1;
2110
799M
    INSIST(offset <= length);
2111
799M
    if (count == 0) {
2112
      /* Final root label */
2113
116M
      break;
2114
116M
    }
2115
799M
  }
2116
116M
  INSIST(offset == name->length);
2117
2118
116M
  return nlabels;
2119
116M
}