Coverage Report

Created: 2026-01-24 06:24

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
190
dns_name_hasbuffer(const dns_name_t *name) {
120
  /*
121
   * Does 'name' have a dedicated buffer?
122
   */
123
124
190
  REQUIRE(DNS_NAME_VALID(name));
125
126
190
  if (name->buffer != NULL) {
127
190
    return true;
128
190
  }
129
130
0
  return false;
131
190
}
132
133
bool
134
10.5M
dns_name_isabsolute(const dns_name_t *name) {
135
  /*
136
   * Does 'name' end in the root label?
137
   */
138
139
10.5M
  REQUIRE(DNS_NAME_VALID(name));
140
141
10.5M
  return name->attributes.absolute;
142
10.5M
}
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
21.8M
dns_name_iswildcard(const dns_name_t *name) {
259
21.8M
  unsigned char *ndata;
260
261
  /*
262
   * Is 'name' a wildcard name?
263
   */
264
265
21.8M
  REQUIRE(DNS_NAME_VALID(name));
266
21.8M
  REQUIRE(name->length > 0);
267
268
21.8M
  if (name->length >= 2) {
269
21.6M
    ndata = name->ndata;
270
21.6M
    if (ndata[0] == 1 && ndata[1] == '*') {
271
2.32M
      return true;
272
2.32M
    }
273
21.6M
  }
274
275
19.5M
  return false;
276
21.8M
}
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
249k
dns_name_hash(const dns_name_t *name) {
315
249k
  REQUIRE(DNS_NAME_VALID(name));
316
317
249k
  return isc_hash32(name->ndata, name->length, false);
318
249k
}
319
320
dns_namereln_t
321
dns_name_fullcompare(const dns_name_t *name1, const dns_name_t *name2,
322
10.0M
         int *orderp, unsigned int *nlabelsp) {
323
10.0M
  unsigned int l1, l2, l, count1, count2, count, nlabels;
324
10.0M
  int cdiff, ldiff, diff;
325
10.0M
  unsigned char *label1, *label2;
326
10.0M
  dns_offsets_t offsets1, offsets2;
327
10.0M
  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
10.0M
  REQUIRE(DNS_NAME_VALID(name1));
341
10.0M
  REQUIRE(DNS_NAME_VALID(name2));
342
10.0M
  REQUIRE(orderp != NULL);
343
10.0M
  REQUIRE(nlabelsp != NULL);
344
  /*
345
   * Either name1 is absolute and name2 is absolute, or neither is.
346
   */
347
10.0M
  REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
348
349
10.0M
  if (name1 == name2) {
350
1.31k
    *orderp = 0;
351
1.31k
    *nlabelsp = dns_name_countlabels(name1);
352
353
1.31k
    return dns_namereln_equal;
354
1.31k
  }
355
356
10.0M
  l1 = dns_name_offsets(name1, offsets1);
357
10.0M
  l2 = dns_name_offsets(name2, offsets2);
358
359
10.0M
  nlabels = 0;
360
10.0M
  if (l2 > l1) {
361
19
    l = l1;
362
19
    ldiff = 0 - (l2 - l1);
363
10.0M
  } else {
364
10.0M
    l = l2;
365
10.0M
    ldiff = l1 - l2;
366
10.0M
  }
367
368
20.0M
  while (l-- > 0) {
369
10.0M
    l1--;
370
10.0M
    l2--;
371
10.0M
    label1 = &name1->ndata[offsets1[l1]];
372
10.0M
    label2 = &name2->ndata[offsets2[l2]];
373
10.0M
    count1 = *label1++;
374
10.0M
    count2 = *label2++;
375
376
10.0M
    cdiff = (int)count1 - (int)count2;
377
10.0M
    if (cdiff < 0) {
378
29
      count = count1;
379
10.0M
    } else {
380
10.0M
      count = count2;
381
10.0M
    }
382
383
10.0M
    diff = isc_ascii_lowercmp(label1, label2, count);
384
10.0M
    if (diff != 0) {
385
195
      *orderp = diff;
386
195
      goto done;
387
195
    }
388
389
10.0M
    if (cdiff != 0) {
390
53
      *orderp = cdiff;
391
53
      goto done;
392
53
    }
393
10.0M
    nlabels++;
394
10.0M
  }
395
396
10.0M
  *orderp = ldiff;
397
10.0M
  if (ldiff < 0) {
398
19
    namereln = dns_namereln_contains;
399
10.0M
  } else if (ldiff > 0) {
400
9.85M
    namereln = dns_namereln_subdomain;
401
9.85M
  } else {
402
179k
    namereln = dns_namereln_equal;
403
179k
  }
404
10.0M
  *nlabelsp = nlabels;
405
10.0M
  return namereln;
406
407
248
done:
408
248
  *nlabelsp = nlabels;
409
248
  if (nlabels > 0) {
410
248
    namereln = dns_namereln_commonancestor;
411
248
  }
412
413
248
  return namereln;
414
10.0M
}
415
416
int
417
1.65k
dns_name_compare(const dns_name_t *name1, const dns_name_t *name2) {
418
1.65k
  int order;
419
1.65k
  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.65k
  (void)dns_name_fullcompare(name1, name2, &order, &nlabels);
432
433
1.65k
  return order;
434
1.65k
}
435
436
bool
437
262k
dns_name_equal(const dns_name_t *name1, const dns_name_t *name2) {
438
262k
  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
262k
  REQUIRE(DNS_NAME_VALID(name1));
450
262k
  REQUIRE(DNS_NAME_VALID(name2));
451
  /*
452
   * Either name1 is absolute and name2 is absolute, or neither is.
453
   */
454
262k
  REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
455
456
262k
  if (name1 == name2) {
457
0
    return true;
458
0
  }
459
460
262k
  length = name1->length;
461
262k
  if (length != name2->length) {
462
32.8k
    return false;
463
32.8k
  }
464
465
  /* label lengths are < 64 so tolower() does not affect them */
466
229k
  return isc_ascii_lowerequal(name1->ndata, name2->ndata, length);
467
262k
}
468
469
bool
470
110k
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
110k
  REQUIRE(DNS_NAME_VALID(name1));
481
110k
  REQUIRE(DNS_NAME_VALID(name2));
482
  /*
483
   * Either name1 is absolute and name2 is absolute, or neither is.
484
   */
485
110k
  REQUIRE((name1->attributes.absolute) == (name2->attributes.absolute));
486
487
110k
  if (name1->length != name2->length) {
488
25.4k
    return false;
489
25.4k
  }
490
491
85.4k
  if (memcmp(name1->ndata, name2->ndata, name1->length) != 0) {
492
9.57k
    return false;
493
9.57k
  }
494
495
75.9k
  return true;
496
85.4k
}
497
498
int
499
31.7M
dns_name_rdatacompare(const dns_name_t *name1, const dns_name_t *name2) {
500
  /*
501
   * Compare two absolute names as rdata.
502
   */
503
504
31.7M
  REQUIRE(DNS_NAME_VALID(name1));
505
31.7M
  REQUIRE(name1->length > 0);
506
31.7M
  REQUIRE(name1->attributes.absolute);
507
31.7M
  REQUIRE(DNS_NAME_VALID(name2));
508
31.7M
  REQUIRE(name2->length > 0);
509
31.7M
  REQUIRE(name2->attributes.absolute);
510
511
  /* label lengths are < 64 so tolower() does not affect them */
512
31.7M
  return isc_ascii_lowercmp(name1->ndata, name2->ndata,
513
31.7M
          ISC_MIN(name1->length, name2->length));
514
31.7M
}
515
516
bool
517
10.0M
dns_name_issubdomain(const dns_name_t *name1, const dns_name_t *name2) {
518
10.0M
  int order;
519
10.0M
  unsigned int nlabels;
520
10.0M
  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
10.0M
  namereln = dns_name_fullcompare(name1, name2, &order, &nlabels);
532
10.0M
  if (namereln == dns_namereln_subdomain ||
533
179k
      namereln == dns_namereln_equal)
534
10.0M
  {
535
10.0M
    return true;
536
10.0M
  }
537
538
2
  return false;
539
10.0M
}
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
4.61k
dns_name_getlabel(const dns_name_t *name, unsigned int n, dns_label_t *label) {
566
4.61k
  dns_offsets_t offsets;
567
568
  /*
569
   * Make 'label' refer to the 'n'th least significant label of 'name'.
570
   */
571
572
4.61k
  REQUIRE(DNS_NAME_VALID(name));
573
4.61k
  REQUIRE(label != NULL);
574
575
4.61k
  uint8_t labels = dns_name_offsets(name, offsets);
576
577
4.61k
  REQUIRE(labels > 0);
578
4.61k
  REQUIRE(n < labels);
579
580
4.61k
  label->base = &name->ndata[offsets[n]];
581
4.61k
  if (n == (unsigned int)labels - 1) {
582
2.55k
    label->length = name->length - offsets[n];
583
2.55k
  } else {
584
2.05k
    label->length = offsets[n + 1] - offsets[n];
585
2.05k
  }
586
4.61k
}
587
588
void
589
dns_name_getlabelsequence(const dns_name_t *source, unsigned int first,
590
14.2M
        unsigned int n, dns_name_t *target) {
591
14.2M
  unsigned char *p, l;
592
14.2M
  unsigned int firstoffset, endoffset;
593
14.2M
  unsigned int i;
594
595
  /*
596
   * Make 'target' refer to the 'n' labels including and following
597
   * 'first' in 'source'.
598
   */
599
600
14.2M
  REQUIRE(DNS_NAME_VALID(source));
601
14.2M
  REQUIRE(DNS_NAME_VALID(target));
602
14.2M
  REQUIRE(DNS_NAME_BINDABLE(target));
603
604
14.2M
  uint8_t labels = dns_name_countlabels(source);
605
14.2M
  REQUIRE(first <= labels && n <= labels - first);
606
607
14.2M
  p = source->ndata;
608
14.2M
  if (first == labels) {
609
0
    firstoffset = source->length;
610
14.2M
  } else {
611
183M
    for (i = 0; i < first; i++) {
612
169M
      l = *p;
613
169M
      p += l + 1;
614
169M
    }
615
14.2M
    firstoffset = (unsigned int)(p - source->ndata);
616
14.2M
  }
617
618
14.2M
  if (first + n == labels) {
619
14.2M
    endoffset = source->length;
620
14.2M
  } 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
14.2M
  target->ndata = &source->ndata[firstoffset];
629
14.2M
  target->length = endoffset - firstoffset;
630
631
14.2M
  if (first + n == labels && n > 0 && source->attributes.absolute) {
632
14.2M
    target->attributes.absolute = true;
633
14.2M
  } else {
634
0
    target->attributes.absolute = false;
635
0
  }
636
14.2M
}
637
638
void
639
2.87k
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.87k
  REQUIRE(DNS_NAME_VALID(source));
645
2.87k
  REQUIRE(DNS_NAME_VALID(target));
646
2.87k
  REQUIRE(DNS_NAME_BINDABLE(target));
647
648
2.87k
  target->ndata = source->ndata;
649
2.87k
  target->length = source->length;
650
2.87k
  target->attributes = source->attributes;
651
2.87k
  target->attributes.readonly = false;
652
2.87k
  target->attributes.dynamic = false;
653
2.87k
}
654
655
void
656
64.0M
dns_name_fromregion(dns_name_t *name, const isc_region_t *r) {
657
64.0M
  size_t length;
658
64.0M
  isc_region_t r2 = { .base = NULL, .length = 0 };
659
660
  /*
661
   * Make 'name' refer to region 'r'.
662
   */
663
664
64.0M
  REQUIRE(DNS_NAME_VALID(name));
665
64.0M
  REQUIRE(r != NULL);
666
64.0M
  REQUIRE(DNS_NAME_BINDABLE(name));
667
668
64.0M
  name->ndata = r->base;
669
64.0M
  if (name->buffer != NULL) {
670
35.0k
    isc_buffer_clear(name->buffer);
671
35.0k
    isc_buffer_availableregion(name->buffer, &r2);
672
35.0k
    length = (r->length < r2.length) ? r->length : r2.length;
673
35.0k
    if (length > DNS_NAME_MAXWIRE) {
674
0
      length = DNS_NAME_MAXWIRE;
675
0
    }
676
63.9M
  } else {
677
63.9M
    length = (r->length <= DNS_NAME_MAXWIRE) ? r->length
678
63.9M
               : DNS_NAME_MAXWIRE;
679
63.9M
  }
680
681
64.0M
  name->attributes.absolute = false;
682
683
64.0M
  if (length > 0) {
684
64.0M
    size_t offset = 0;
685
64.0M
    uint8_t nlabels = 0;
686
157M
    while (offset != length) {
687
157M
      uint8_t count;
688
689
157M
      INSIST(nlabels < DNS_NAME_MAXLABELS);
690
157M
      nlabels++;
691
692
157M
      count = name->ndata[offset];
693
157M
      INSIST(count <= DNS_NAME_LABELLEN);
694
695
157M
      offset += count + 1;
696
157M
      INSIST(offset <= length);
697
698
157M
      if (count == 0) {
699
64.0M
        name->attributes.absolute = true;
700
64.0M
        break;
701
64.0M
      }
702
157M
    }
703
64.0M
    name->length = offset;
704
64.0M
  }
705
706
64.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
35.0k
    if (name->length > 0) {
713
35.0k
      memmove(r2.base, r->base, name->length);
714
35.0k
    }
715
35.0k
    name->ndata = r2.base;
716
35.0k
    isc_buffer_add(name->buffer, name->length);
717
35.0k
  }
718
64.0M
}
719
720
static isc_result_t
721
convert_text(isc_buffer_t *source, const dns_name_t *origin,
722
19.7M
       unsigned int options, dns_name_t *name, isc_buffer_t *target) {
723
19.7M
  unsigned char *ndata = NULL, *label = NULL;
724
19.7M
  char *tdata = NULL;
725
19.7M
  char c;
726
19.7M
  ft_state state;
727
19.7M
  unsigned int value = 0, count = 0;
728
19.7M
  unsigned int n1 = 0, n2 = 0;
729
19.7M
  unsigned int tlen, nrem, nused, digits = 0, labels, tused;
730
19.7M
  bool done;
731
19.7M
  bool downcase;
732
733
19.7M
  REQUIRE(DNS_NAME_VALID(name));
734
19.7M
  REQUIRE(ISC_BUFFER_VALID(source));
735
19.7M
  REQUIRE(ISC_BUFFER_VALID(target));
736
737
19.7M
  downcase = ((options & DNS_NAME_DOWNCASE) != 0);
738
739
19.7M
  if (target == NULL && name->buffer != NULL) {
740
0
    target = name->buffer;
741
0
    isc_buffer_clear(target);
742
0
  }
743
744
19.7M
  REQUIRE(DNS_NAME_BINDABLE(name));
745
746
  /*
747
   * Set up the state machine.
748
   */
749
19.7M
  tdata = (char *)source->base + source->current;
750
19.7M
  tlen = isc_buffer_remaininglength(source);
751
19.7M
  tused = 0;
752
19.7M
  ndata = isc_buffer_used(target);
753
19.7M
  nrem = isc_buffer_availablelength(target);
754
19.7M
  if (nrem > DNS_NAME_MAXWIRE) {
755
833k
    nrem = DNS_NAME_MAXWIRE;
756
833k
  }
757
19.7M
  nused = 0;
758
19.7M
  labels = 0;
759
19.7M
  done = false;
760
19.7M
  state = ft_init;
761
762
135M
  while (nrem > 0 && tlen > 0 && !done) {
763
115M
    c = *tdata++;
764
115M
    tlen--;
765
115M
    tused++;
766
767
115M
    switch (state) {
768
19.7M
    case ft_init:
769
      /*
770
       * Is this the root name?
771
       */
772
19.7M
      if (c == '.') {
773
226k
        if (tlen != 0) {
774
70
          return DNS_R_EMPTYLABEL;
775
70
        }
776
226k
        labels++;
777
226k
        *ndata++ = 0;
778
226k
        nrem--;
779
226k
        nused++;
780
226k
        done = true;
781
226k
        break;
782
226k
      }
783
19.5M
      if (c == '@' && tlen == 0) {
784
158k
        state = ft_at;
785
158k
        break;
786
158k
      }
787
788
19.3M
      FALLTHROUGH;
789
31.1M
    case ft_start:
790
31.1M
      label = ndata;
791
31.1M
      ndata++;
792
31.1M
      nrem--;
793
31.1M
      nused++;
794
31.1M
      count = 0;
795
31.1M
      if (c == '\\') {
796
15.9k
        state = ft_initialescape;
797
15.9k
        break;
798
15.9k
      }
799
31.1M
      state = ft_ordinary;
800
31.1M
      if (nrem == 0) {
801
12
        return ISC_R_NOSPACE;
802
12
      }
803
31.1M
      FALLTHROUGH;
804
114M
    case ft_ordinary:
805
114M
      if (c == '.') {
806
11.7M
        if (count == 0) {
807
15
          return DNS_R_EMPTYLABEL;
808
15
        }
809
11.7M
        *label = count;
810
11.7M
        labels++;
811
11.7M
        INSIST(labels < DNS_NAME_MAXLABELS);
812
11.7M
        if (tlen == 0) {
813
34.5k
          labels++;
814
34.5k
          *ndata++ = 0;
815
34.5k
          nrem--;
816
34.5k
          nused++;
817
34.5k
          done = true;
818
34.5k
        }
819
11.7M
        state = ft_start;
820
103M
      } else if (c == '\\') {
821
48.0k
        state = ft_escape;
822
103M
      } else {
823
103M
        if (count >= DNS_NAME_LABELLEN) {
824
65
          return DNS_R_LABELTOOLONG;
825
65
        }
826
103M
        count++;
827
103M
        if (downcase) {
828
0
          c = isc_ascii_tolower(c);
829
0
        }
830
103M
        *ndata++ = c;
831
103M
        nrem--;
832
103M
        nused++;
833
103M
      }
834
114M
      break;
835
114M
    case ft_initialescape:
836
15.9k
      if (c == '[') {
837
        /*
838
         * This looks like a bitstring label, which
839
         * was deprecated.  Intentionally drop it.
840
         */
841
3
        return DNS_R_BADLABELTYPE;
842
3
      }
843
15.9k
      state = ft_escape;
844
15.9k
      POST(state);
845
15.9k
      FALLTHROUGH;
846
64.0k
    case ft_escape:
847
64.0k
      if (!isdigit((unsigned char)c)) {
848
27.1k
        if (count >= DNS_NAME_LABELLEN) {
849
5
          return DNS_R_LABELTOOLONG;
850
5
        }
851
27.1k
        count++;
852
27.1k
        if (downcase) {
853
0
          c = isc_ascii_tolower(c);
854
0
        }
855
27.1k
        *ndata++ = c;
856
27.1k
        nrem--;
857
27.1k
        nused++;
858
27.1k
        state = ft_ordinary;
859
27.1k
        break;
860
27.1k
      }
861
36.9k
      digits = 0;
862
36.9k
      value = 0;
863
36.9k
      state = ft_escdecimal;
864
36.9k
      FALLTHROUGH;
865
110k
    case ft_escdecimal:
866
110k
      if (!isdigit((unsigned char)c)) {
867
19
        return DNS_R_BADESCAPE;
868
19
      }
869
110k
      value = 10 * value + c - '0';
870
110k
      digits++;
871
110k
      if (digits == 3) {
872
36.8k
        if (value > 255) {
873
15
          return DNS_R_BADESCAPE;
874
15
        }
875
36.8k
        if (count >= DNS_NAME_LABELLEN) {
876
3
          return DNS_R_LABELTOOLONG;
877
3
        }
878
36.8k
        count++;
879
36.8k
        if (downcase) {
880
0
          value = isc_ascii_tolower(value);
881
0
        }
882
36.8k
        *ndata++ = value;
883
36.8k
        nrem--;
884
36.8k
        nused++;
885
36.8k
        state = ft_ordinary;
886
36.8k
      }
887
110k
      break;
888
110k
    default:
889
0
      FATAL_ERROR("Unexpected state %d", state);
890
      /* Does not return. */
891
115M
    }
892
115M
  }
893
894
19.7M
  if (!done) {
895
19.5M
    if (nrem == 0) {
896
18
      return ISC_R_NOSPACE;
897
18
    }
898
19.5M
    INSIST(tlen == 0);
899
19.5M
    if (state != ft_ordinary && state != ft_at) {
900
106
      return ISC_R_UNEXPECTEDEND;
901
106
    }
902
19.5M
    if (state == ft_ordinary) {
903
19.3M
      INSIST(count != 0);
904
19.3M
      INSIST(label != NULL);
905
19.3M
      *label = count;
906
19.3M
      labels++;
907
19.3M
      INSIST(labels < DNS_NAME_MAXLABELS);
908
19.3M
    }
909
19.5M
    if (origin != NULL) {
910
19.5M
      if (nrem < origin->length) {
911
6
        return ISC_R_NOSPACE;
912
6
      }
913
19.5M
      label = origin->ndata;
914
19.5M
      n1 = origin->length;
915
19.5M
      nrem -= n1;
916
19.5M
      POST(nrem);
917
39.5M
      while (n1 > 0) {
918
20.0M
        n2 = *label++;
919
20.0M
        INSIST(n2 <= DNS_NAME_LABELLEN);
920
20.0M
        *ndata++ = n2;
921
20.0M
        n1 -= n2 + 1;
922
20.0M
        nused += n2 + 1;
923
23.3M
        while (n2 > 0) {
924
3.30M
          c = *label++;
925
3.30M
          if (downcase) {
926
0
            c = isc_ascii_tolower(c);
927
0
          }
928
3.30M
          *ndata++ = c;
929
3.30M
          n2--;
930
3.30M
        }
931
20.0M
        labels++;
932
20.0M
        if (n1 > 0) {
933
518k
          INSIST(labels < DNS_NAME_MAXLABELS);
934
518k
        }
935
20.0M
      }
936
19.5M
      if (origin->attributes.absolute) {
937
19.5M
        name->attributes.absolute = true;
938
19.5M
      }
939
19.5M
    }
940
19.5M
  } else {
941
261k
    name->attributes.absolute = true;
942
261k
  }
943
944
19.7M
  name->ndata = (unsigned char *)target->base + target->used;
945
19.7M
  name->length = nused;
946
947
19.7M
  isc_buffer_forward(source, tused);
948
19.7M
  isc_buffer_add(target, name->length);
949
950
19.7M
  return ISC_R_SUCCESS;
951
19.7M
}
952
953
isc_result_t
954
dns_name_wirefromtext(isc_buffer_t *source, const dns_name_t *origin,
955
834k
          unsigned int options, isc_buffer_t *target) {
956
834k
  dns_name_t name;
957
958
834k
  REQUIRE(ISC_BUFFER_VALID(target));
959
960
834k
  dns_name_init(&name);
961
834k
  return convert_text(source, origin, options, &name, target);
962
834k
}
963
964
isc_result_t
965
dns_name_fromtext(dns_name_t *name, isc_buffer_t *source,
966
18.9M
      const dns_name_t *origin, unsigned int options) {
967
18.9M
  REQUIRE(DNS_NAME_VALID(name));
968
18.9M
  REQUIRE(ISC_BUFFER_VALID(name->buffer));
969
970
18.9M
  isc_buffer_clear(name->buffer);
971
18.9M
  return convert_text(source, origin, options, name, name->buffer);
972
18.9M
}
973
974
isc_result_t
975
dns_name_totext(const dns_name_t *name, unsigned int options,
976
848k
    isc_buffer_t *target) {
977
848k
  isc_result_t result;
978
848k
  unsigned char *ndata = NULL;
979
848k
  unsigned int nlen;
980
848k
  unsigned int labels;
981
848k
  bool saw_root = false;
982
848k
  unsigned int oused;
983
848k
  bool omit_final_dot = ((options & DNS_NAME_OMITFINALDOT) != 0);
984
848k
  bool first = true;
985
986
  /*
987
   * This function assumes the name is in proper uncompressed
988
   * wire format.
989
   */
990
848k
  REQUIRE(DNS_NAME_VALID(name));
991
848k
  REQUIRE(ISC_BUFFER_VALID(target));
992
993
848k
  oused = target->used;
994
995
848k
  ndata = name->ndata;
996
848k
  nlen = name->length;
997
848k
  labels = dns_name_countlabels(name);
998
999
848k
  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
848k
  } else if (nlen == 1 && labels == 1 && *ndata == '\0') {
1012
    /*
1013
     * Special handling for the root label.
1014
     */
1015
366k
    saw_root = true;
1016
366k
    omit_final_dot = false;
1017
1018
    /*
1019
     * Skip the while() loop.
1020
     */
1021
366k
    nlen = 0;
1022
366k
  }
1023
1024
5.69M
  while (labels > 0 && nlen > 0) {
1025
5.33M
    unsigned int count = *ndata++;
1026
5.33M
    labels--;
1027
5.33M
    nlen--;
1028
5.33M
    if (count == 0) {
1029
481k
      saw_root = true;
1030
481k
      break;
1031
4.84M
    } else if (!first) {
1032
4.36M
      CHECK(isc_buffer_reserve(target, 1));
1033
4.36M
      isc_buffer_putuint8(target, '.');
1034
4.36M
    }
1035
4.84M
    first = false;
1036
1037
4.84M
    if (count <= DNS_NAME_LABELLEN) {
1038
4.84M
      unsigned char c;
1039
1040
4.84M
      INSIST(nlen >= count);
1041
1042
80.6M
      while (count > 0) {
1043
75.7M
        uint32_t value;
1044
1045
75.7M
        c = *ndata;
1046
75.7M
        switch (c) {
1047
        /* Special modifiers in zone files. */
1048
462k
        case 0x40: /* '@' */
1049
976k
        case 0x24: /* '$' */
1050
976k
          if ((options & DNS_NAME_PRINCIPAL) != 0)
1051
0
          {
1052
0
            goto no_escape;
1053
0
          }
1054
976k
          FALLTHROUGH;
1055
1.14M
        case 0x22: /* '"' */
1056
1.34M
        case 0x28: /* '(' */
1057
1.54M
        case 0x29: /* ')' */
1058
1.73M
        case 0x2E: /* '.' */
1059
1.93M
        case 0x3B: /* ';' */
1060
1.95M
        case 0x5C: /* '\\' */
1061
1.95M
          value = '\\' << 8 | c;
1062
1.95M
          CHECK(isc_buffer_reserve(target, 2));
1063
1.95M
          isc_buffer_putuint16(target, value);
1064
1.95M
          ndata++;
1065
1.95M
          nlen--;
1066
1.95M
          break;
1067
0
        no_escape:
1068
73.8M
        default:
1069
73.8M
          if (c > 0x20 && c < 0x7f) {
1070
5.31M
            CHECK(isc_buffer_reserve(target,
1071
5.31M
                   1));
1072
5.31M
            isc_buffer_putuint8(target, c);
1073
5.31M
            ndata++;
1074
5.31M
            nlen--;
1075
68.4M
          } else {
1076
68.4M
            value = 0x5c << 24;
1077
68.4M
            value |= (0x30 +
1078
68.4M
                ((c / 100) % 10))
1079
68.4M
               << 16;
1080
68.4M
            value |=
1081
68.4M
              (0x30 + ((c / 10) % 10))
1082
68.4M
              << 8;
1083
68.4M
            value |= 0x30 + (c % 10);
1084
68.4M
            CHECK(isc_buffer_reserve(target,
1085
68.4M
                   4));
1086
68.4M
            isc_buffer_putuint32(target,
1087
68.4M
                     value);
1088
68.4M
            ndata++;
1089
68.4M
            nlen--;
1090
68.4M
          }
1091
75.7M
        }
1092
75.7M
        count--;
1093
75.7M
      }
1094
4.84M
    } else {
1095
0
      FATAL_ERROR("Unexpected label type %02x", count);
1096
0
      UNREACHABLE();
1097
0
    }
1098
4.84M
  }
1099
1100
848k
  if (saw_root && !omit_final_dot) {
1101
846k
    CHECK(isc_buffer_reserve(target, 1));
1102
846k
    isc_buffer_putuint8(target, '.');
1103
846k
  }
1104
1105
848k
  if (isc_buffer_availablelength(target) > 1) {
1106
848k
    uint8_t *p = isc_buffer_used(target);
1107
848k
    *p = 0;
1108
848k
  }
1109
1110
848k
  if (totext_filter_proc != NULL) {
1111
0
    return (totext_filter_proc)(target, oused);
1112
0
  }
1113
1114
848k
  return ISC_R_SUCCESS;
1115
1116
4
cleanup:
1117
4
  return result;
1118
848k
}
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
292
dns_name_downcase(const dns_name_t *source, dns_name_t *name) {
1237
  /*
1238
   * Downcase 'source'.
1239
   */
1240
1241
292
  REQUIRE(DNS_NAME_VALID(source));
1242
292
  REQUIRE(DNS_NAME_VALID(name));
1243
1244
292
  if (source == name) {
1245
292
    REQUIRE(!name->attributes.readonly);
1246
292
    isc_ascii_lowercopy(name->ndata, source->ndata, source->length);
1247
292
    return ISC_R_SUCCESS;
1248
292
  }
1249
1250
0
  REQUIRE(DNS_NAME_BINDABLE(name));
1251
0
  REQUIRE(ISC_BUFFER_VALID(name->buffer));
1252
1253
0
  isc_buffer_clear(name->buffer);
1254
0
  name->ndata = (uint8_t *)name->buffer->base + name->buffer->used;
1255
1256
  /* label lengths are < 64 so tolower() does not affect them */
1257
0
  isc_ascii_lowercopy(name->ndata, source->ndata, source->length);
1258
1259
0
  name->length = source->length;
1260
0
  name->attributes = (struct dns_name_attrs){
1261
0
    .absolute = source->attributes.absolute
1262
0
  };
1263
0
  isc_buffer_add(name->buffer, name->length);
1264
1265
0
  return ISC_R_SUCCESS;
1266
292
}
1267
1268
isc_result_t
1269
dns_name_fromwire(dns_name_t *const name, isc_buffer_t *const source,
1270
1.68M
      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
   * > occurance 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.68M
  REQUIRE(DNS_NAME_VALID(name));
1323
1.68M
  REQUIRE(DNS_NAME_BINDABLE(name));
1324
1.68M
  REQUIRE((target != NULL && ISC_BUFFER_VALID(target)) ||
1325
1.68M
    (target == NULL && ISC_BUFFER_VALID(name->buffer)));
1326
1327
1.68M
  if (target == NULL && name->buffer != NULL) {
1328
5.26k
    target = name->buffer;
1329
5.26k
    isc_buffer_clear(target);
1330
5.26k
  }
1331
1332
1.68M
  uint8_t *const name_buf = isc_buffer_used(target);
1333
1.68M
  const uint32_t name_max = ISC_MIN(DNS_NAME_MAXWIRE,
1334
1.68M
            isc_buffer_availablelength(target));
1335
1.68M
  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.68M
  const uint8_t *const source_buf = isc_buffer_base(source);
1355
1.68M
  const uint8_t *const source_max = isc_buffer_used(source);
1356
1.68M
  const uint8_t *const start = isc_buffer_current(source);
1357
1.68M
  const uint8_t *marker = start;
1358
1.68M
  const uint8_t *cursor = start;
1359
1.68M
  const uint8_t *consumed = NULL;
1360
1361
  /*
1362
   * One iteration per label.
1363
   */
1364
12.9M
  while (cursor < source_max) {
1365
12.9M
    const uint8_t label_len = *cursor++;
1366
12.9M
    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
11.5M
      cursor += label_len;
1375
11.5M
      name_len += label_len + 1;
1376
11.5M
      if (name_len > name_max) {
1377
56.3k
        return name_max == DNS_NAME_MAXWIRE
1378
56.3k
                 ? DNS_R_NAMETOOLONG
1379
56.3k
                 : ISC_R_NOSPACE;
1380
11.4M
      } else if (label_len == 0) {
1381
1.62M
        goto root_label;
1382
1.62M
      }
1383
11.5M
    } else if (label_len < 192) {
1384
545
      return DNS_R_BADLABELTYPE;
1385
1.38M
    } else if (!dns_decompress_getpermitted(dctx)) {
1386
272
      return DNS_R_DISALLOWED;
1387
1.38M
    } 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.38M
      const uint32_t hi = label_len & 0x3F;
1397
1.38M
      const uint32_t lo = *cursor++;
1398
1.38M
      const uint8_t *pointer = source_buf + (256 * hi + lo);
1399
1.38M
      if (pointer >= marker) {
1400
93
        return DNS_R_BADPOINTER;
1401
93
      }
1402
1.38M
      const uint32_t copy_len = (cursor - 2) - marker;
1403
1.38M
      uint8_t *const dest = name_buf + name_len - copy_len;
1404
1.38M
      memmove(dest, marker, copy_len);
1405
1.38M
      consumed = consumed != NULL ? consumed : cursor;
1406
      /* it's just a jump to the left */
1407
1.38M
      cursor = marker = pointer;
1408
1.38M
    }
1409
12.9M
  }
1410
2.17k
  return ISC_R_UNEXPECTEDEND;
1411
1.62M
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.62M
  const uint32_t copy_len = cursor - marker;
1417
1.62M
  memmove(name_buf + name_len - copy_len, marker, copy_len);
1418
1.62M
  consumed = consumed != NULL ? consumed : cursor;
1419
1.62M
  isc_buffer_forward(source, consumed - start);
1420
1421
1.62M
  name->attributes.absolute = true;
1422
1.62M
  name->ndata = name_buf;
1423
1.62M
  name->length = name_len;
1424
1.62M
  isc_buffer_add(target, name_len);
1425
1426
1.62M
  return ISC_R_SUCCESS;
1427
1.68M
}
1428
1429
isc_result_t
1430
dns_name_towire(const dns_name_t *name, dns_compress_t *cctx,
1431
9.19M
    isc_buffer_t *target) {
1432
9.19M
  bool compress, multi;
1433
9.19M
  unsigned int here;
1434
9.19M
  unsigned int prefix_length;
1435
9.19M
  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
9.19M
  REQUIRE(DNS_NAME_VALID(name));
1444
9.19M
  REQUIRE(ISC_BUFFER_VALID(target));
1445
1446
9.19M
  if (cctx == NULL) {
1447
8.89M
    if (isc_buffer_availablelength(target) < name->length) {
1448
0
      return ISC_R_NOSPACE;
1449
0
    }
1450
8.89M
    memmove(isc_buffer_used(target), name->ndata, name->length);
1451
8.89M
    isc_buffer_add(target, name->length);
1452
8.89M
    return ISC_R_SUCCESS;
1453
8.89M
  }
1454
1455
299k
  compress = !name->attributes.nocompress &&
1456
299k
       dns_compress_getpermitted(cctx);
1457
299k
  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
299k
  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
299k
  prefix_length = name->length;
1476
299k
  suffix_coff = 0;
1477
299k
  dns_compress_name(cctx, target, name, &prefix_length, &suffix_coff);
1478
299k
  if (!compress) {
1479
24.5k
    prefix_length = name->length;
1480
24.5k
    suffix_coff = 0;
1481
24.5k
  }
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
299k
  here = isc_buffer_usedlength(target);
1488
299k
  if (multi && here < 0x4000 && prefix_length > 1) {
1489
0
    cctx->coff = (uint16_t)here;
1490
0
  }
1491
1492
299k
  if (prefix_length > 0) {
1493
273k
    if (isc_buffer_availablelength(target) < prefix_length) {
1494
102k
      return ISC_R_NOSPACE;
1495
102k
    }
1496
171k
    memmove(isc_buffer_used(target), name->ndata, prefix_length);
1497
171k
    isc_buffer_add(target, prefix_length);
1498
171k
  }
1499
1500
196k
  if (suffix_coff > 0) {
1501
34.8k
    if (multi && prefix_length == 0) {
1502
0
      cctx->coff = suffix_coff;
1503
0
    }
1504
34.8k
    if (isc_buffer_availablelength(target) < 2) {
1505
83
      return ISC_R_NOSPACE;
1506
83
    }
1507
34.8k
    isc_buffer_putuint16(target, suffix_coff | 0xc000);
1508
34.8k
  }
1509
1510
196k
  return ISC_R_SUCCESS;
1511
196k
}
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
9.84M
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
9.84M
  REQUIRE(DNS_NAME_VALID(source));
1606
9.84M
  REQUIRE(source->length > 0);
1607
9.84M
  REQUIRE(DNS_NAME_VALID(target));
1608
9.84M
  REQUIRE(DNS_NAME_BINDABLE(target));
1609
1610
9.84M
  target->ndata = isc_mem_get(mctx, source->length);
1611
1612
9.84M
  memmove(target->ndata, source->ndata, source->length);
1613
1614
9.84M
  target->length = source->length;
1615
9.84M
  target->attributes = (struct dns_name_attrs){ .dynamic = true };
1616
9.84M
  target->attributes.absolute = source->attributes.absolute;
1617
9.84M
}
1618
1619
void
1620
9.84M
dns_name_free(dns_name_t *name, isc_mem_t *mctx) {
1621
9.84M
  size_t size;
1622
1623
  /*
1624
   * Free 'name'.
1625
   */
1626
1627
9.84M
  REQUIRE(DNS_NAME_VALID(name));
1628
9.84M
  REQUIRE(name->attributes.dynamic);
1629
1630
9.84M
  size = name->length;
1631
9.84M
  isc_mem_put(mctx, name->ndata, size);
1632
9.84M
  dns_name_invalidate(name);
1633
9.84M
}
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
494k
dns_name_dynamic(const dns_name_t *name) {
1671
494k
  REQUIRE(DNS_NAME_VALID(name));
1672
1673
  /*
1674
   * Returns whether there is dynamic memory associated with this name.
1675
   */
1676
1677
494k
  return name->attributes.dynamic;
1678
494k
}
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
20.7k
dns_name_format(const dns_name_t *name, char *cp, unsigned int size) {
1722
20.7k
  isc_result_t result;
1723
20.7k
  isc_buffer_t buf;
1724
1725
20.7k
  REQUIRE(size > 0);
1726
1727
  /*
1728
   * Leave room for null termination after buffer.
1729
   */
1730
20.7k
  isc_buffer_init(&buf, cp, size - 1);
1731
20.7k
  result = dns_name_totext(name, DNS_NAME_OMITFINALDOT, &buf);
1732
20.7k
  if (result == ISC_R_SUCCESS) {
1733
20.7k
    isc_buffer_putuint8(&buf, (uint8_t)'\0');
1734
20.7k
  } else {
1735
0
    snprintf(cp, size, "<unknown>");
1736
0
  }
1737
20.7k
}
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
314k
dns_name_copy(const dns_name_t *source, dns_name_t *dest) {
1793
314k
  isc_buffer_t *target = NULL;
1794
314k
  unsigned char *ndata = NULL;
1795
1796
314k
  REQUIRE(DNS_NAME_VALID(source));
1797
314k
  REQUIRE(DNS_NAME_VALID(dest));
1798
314k
  REQUIRE(DNS_NAME_BINDABLE(dest));
1799
1800
314k
  target = dest->buffer;
1801
1802
314k
  REQUIRE(target != NULL);
1803
314k
  REQUIRE(target->length >= source->length);
1804
1805
314k
  isc_buffer_clear(target);
1806
1807
314k
  ndata = (unsigned char *)target->base;
1808
314k
  dest->ndata = target->base;
1809
1810
314k
  if (source->length != 0) {
1811
314k
    memmove(ndata, source->ndata, source->length);
1812
314k
  }
1813
1814
314k
  dest->ndata = ndata;
1815
314k
  dest->length = source->length;
1816
314k
  dest->attributes.absolute = source->attributes.absolute;
1817
1818
314k
  isc_buffer_add(target, dest->length);
1819
314k
}
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
94.0M
dns_name_offsets(const dns_name_t *name, dns_offsets_t offsets) {
2092
94.0M
  REQUIRE(DNS_NAME_VALID(name));
2093
94.0M
  unsigned int offset, count, length, nlabels;
2094
94.0M
  unsigned char *ndata;
2095
2096
94.0M
  ndata = name->ndata;
2097
94.0M
  length = name->length;
2098
94.0M
  offset = 0;
2099
94.0M
  nlabels = 0;
2100
797M
  while (offset != length) {
2101
797M
    INSIST(nlabels < DNS_NAME_MAXLABELS);
2102
797M
    if (offsets != NULL) {
2103
273M
      offsets[nlabels] = offset;
2104
273M
    }
2105
797M
    nlabels++;
2106
797M
    count = *ndata;
2107
797M
    INSIST(count <= DNS_NAME_LABELLEN);
2108
797M
    offset += count + 1;
2109
797M
    ndata += count + 1;
2110
797M
    INSIST(offset <= length);
2111
797M
    if (count == 0) {
2112
      /* Final root label */
2113
94.0M
      break;
2114
94.0M
    }
2115
797M
  }
2116
94.0M
  INSIST(offset == name->length);
2117
2118
94.0M
  return nlabels;
2119
94.0M
}