Coverage Report

Created: 2026-06-15 06:56

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/bind9/lib/dns/rcode.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
#include <ctype.h>
15
#include <inttypes.h>
16
#include <stdbool.h>
17
#include <stdlib.h>
18
19
#include <isc/ascii.h>
20
#include <isc/buffer.h>
21
#include <isc/parseint.h>
22
#include <isc/region.h>
23
#include <isc/result.h>
24
#include <isc/stdio.h>
25
#include <isc/string.h>
26
#include <isc/types.h>
27
#include <isc/util.h>
28
29
#include <dns/cert.h>
30
#include <dns/ds.h>
31
#include <dns/dsdigest.h>
32
#include <dns/dsync.h>
33
#include <dns/keyflags.h>
34
#include <dns/keyvalues.h>
35
#include <dns/rcode.h>
36
#include <dns/rdataclass.h>
37
#include <dns/secalg.h>
38
#include <dns/secproto.h>
39
40
#include <dst/dst.h>
41
42
1.31M
#define NUMBERSIZE sizeof("037777777777") /* 2^32-1 octal + NUL */
43
44
6.75k
#define TOTEXTONLY 0x01
45
46
/* clang-format off */
47
#define SENTINEL { 0, NULL, 0 }
48
/* clang-format on */
49
50
#define RCODENAMES                                     \
51
  /* standard rcodes */                          \
52
  { dns_rcode_noerror, "NOERROR", 0 },           \
53
    { dns_rcode_formerr, "FORMERR", 0 },   \
54
    { dns_rcode_servfail, "SERVFAIL", 0 }, \
55
    { dns_rcode_nxdomain, "NXDOMAIN", 0 }, \
56
    { dns_rcode_notimp, "NOTIMP", 0 },     \
57
    { dns_rcode_refused, "REFUSED", 0 },   \
58
    { dns_rcode_yxdomain, "YXDOMAIN", 0 }, \
59
    { dns_rcode_yxrrset, "YXRRSET", 0 },   \
60
    { dns_rcode_nxrrset, "NXRRSET", 0 },   \
61
    { dns_rcode_notauth, "NOTAUTH", 0 },   \
62
    { dns_rcode_notzone, "NOTZONE", 0 },   \
63
    { 11, "RESERVED11", TOTEXTONLY },      \
64
    { 12, "RESERVED12", TOTEXTONLY },      \
65
    { 13, "RESERVED13", TOTEXTONLY },      \
66
    { 14, "RESERVED14", TOTEXTONLY },      \
67
    { 15, "RESERVED15", TOTEXTONLY },
68
69
#define ERCODENAMES                          \
70
  /* extended rcodes */                \
71
  { dns_rcode_badvers, "BADVERS", 0 }, \
72
    { dns_rcode_badcookie, "BADCOOKIE", 0 }, SENTINEL
73
74
#define TSIGRCODENAMES                                   \
75
  /* extended rcodes */                            \
76
  { dns_tsigerror_badsig, "BADSIG", 0 },           \
77
    { dns_tsigerror_badkey, "BADKEY", 0 },   \
78
    { dns_tsigerror_badtime, "BADTIME", 0 }, \
79
    { dns_tsigerror_badmode, "BADMODE", 0 }, \
80
    { dns_tsigerror_badname, "BADNAME", 0 }, \
81
    { dns_tsigerror_badalg, "BADALG", 0 },   \
82
    { dns_tsigerror_badtrunc, "BADTRUNC", 0 }, SENTINEL
83
84
/* RFC4398 section 2.1 */
85
86
#define CERTNAMES                                                           \
87
  { 1, "PKIX", 0 }, { 2, "SPKI", 0 }, { 3, "PGP", 0 },                \
88
    { 4, "IPKIX", 0 }, { 5, "ISPKI", 0 }, { 6, "IPGP", 0 },     \
89
    { 7, "ACPKIX", 0 }, { 8, "IACPKIX", 0 }, { 253, "URI", 0 }, \
90
    { 254, "OID", 0 }, SENTINEL
91
92
/* RFC2535 section 7, RFC3110 */
93
94
#define SECALGNAMES                                             \
95
  { DNS_KEYALG_RSAMD5, "RSAMD5", 0 },                     \
96
    { DNS_KEYALG_DH_DEPRECATED, "DH", 0 },          \
97
    { DNS_KEYALG_DSA, "DSA", 0 },                   \
98
    { DNS_KEYALG_RSASHA1, "RSASHA1", 0 },           \
99
    { DNS_KEYALG_NSEC3DSA, "NSEC3DSA", 0 },         \
100
    { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \
101
    { DNS_KEYALG_RSASHA256, "RSASHA256", 0 },       \
102
    { DNS_KEYALG_RSASHA512, "RSASHA512", 0 },       \
103
    { DNS_KEYALG_ECCGOST, "ECCGOST", 0 },           \
104
    { DNS_KEYALG_ECDSA256, "ECDSAP256SHA256", 0 },  \
105
    { DNS_KEYALG_ECDSA256, "ECDSA256", 0 },         \
106
    { DNS_KEYALG_ECDSA384, "ECDSAP384SHA384", 0 },  \
107
    { DNS_KEYALG_ECDSA384, "ECDSA384", 0 },         \
108
    { DNS_KEYALG_ED25519, "ED25519", 0 },           \
109
    { DNS_KEYALG_ED448, "ED448", 0 },               \
110
    { DNS_KEYALG_INDIRECT, "INDIRECT", 0 },         \
111
    { DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 },     \
112
    { DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, SENTINEL
113
114
/*
115
 * PRIVATEDNS subtypes we support.
116
 */
117
#define PRIVATEDNSS /* currently empty */
118
119
/*
120
 * PRIVATEOID subtypes we support.
121
 */
122
#define PRIVATEOIDS                                         \
123
  { DST_ALG_RSASHA256PRIVATEOID, "RSASHA256OID", 0 }, \
124
    { DST_ALG_RSASHA512PRIVATEOID, "RSASHA512OID", 0 },
125
126
/* RFC2535 section 7.1 */
127
128
#define SECPROTONAMES                                                     \
129
  { 0, "NONE", 0 }, { 1, "TLS", 0 }, { 2, "EMAIL", 0 },             \
130
    { 3, "DNSSEC", 0 }, { 4, "IPSEC", 0 }, { 255, "ALL", 0 }, \
131
    SENTINEL
132
133
#define HASHALGNAMES { 1, "SHA-1", 0 }, SENTINEL
134
135
/* RFC3658, RFC4509, RFC5933, RFC6605, RFC9558, RFC9563 */
136
137
#if defined(DNS_DSDIGEST_SHA256PRIVATE) &&     \
138
  defined(DNS_DSDIGEST_SHA384PRIVATE) && \
139
  defined(DNS_DSDIGEST_SM3PRIVATE)
140
#define DSDIGESTPRIVATENAMES                                          \
141
  { DNS_DSDIGEST_SHA256PRIVATE, "SHA-256-PRIVATE", 0 },         \
142
    { DNS_DSDIGEST_SHA256PRIVATE, "SHA256PRIVATE", 0 },   \
143
    { DNS_DSDIGEST_SHA384PRIVATE, "SHA-384-PRIVATE", 0 }, \
144
    { DNS_DSDIGEST_SHA384PRIVATE, "SHA384PRIVATE", 0 },   \
145
    { DNS_DSDIGEST_SM3PRIVATE, "SM3-PRIVATE", 0 },        \
146
    { DNS_DSDIGEST_SM3PRIVATE, "SM3PRIVATE", 0 },
147
#else
148
#define DSDIGESTPRIVATENAMES
149
#endif
150
151
#define DSDIGESTNAMES                                                        \
152
  { DNS_DSDIGEST_SHA1, "SHA-1", 0 }, { DNS_DSDIGEST_SHA1, "SHA1", 0 }, \
153
    { DNS_DSDIGEST_SHA256, "SHA-256", 0 },                       \
154
    { DNS_DSDIGEST_SHA256, "SHA256", 0 },                        \
155
    { DNS_DSDIGEST_GOST, "GOST", 0 },                            \
156
    { DNS_DSDIGEST_SM3, "SM3", 0 },                              \
157
    { DNS_DSDIGEST_SHA384, "SHA-384", 0 },                       \
158
    { DNS_DSDIGEST_SHA384, "SHA384", 0 },                        \
159
    { DNS_DSDIGEST_GOST2012, "GOST-2012", 0 },                   \
160
    { DNS_DSDIGEST_GOST2012, "GOST2012", 0 },                    \
161
    DSDIGESTPRIVATENAMES SENTINEL
162
163
#define DSYNCSCHEMES { DNS_DSYNCSCHEME_NOTIFY, "NOTIFY", 0 }, SENTINEL
164
165
struct tbl {
166
  unsigned int value;
167
  const char *name;
168
  int flags;
169
};
170
171
static struct tbl rcodes[] = { RCODENAMES ERCODENAMES };
172
static struct tbl tsigrcodes[] = { RCODENAMES TSIGRCODENAMES };
173
static struct tbl certs[] = { CERTNAMES };
174
static struct tbl secalgs[] = { SECALGNAMES };
175
static struct tbl secprotos[] = { SECPROTONAMES };
176
static struct tbl hashalgs[] = { HASHALGNAMES };
177
static struct tbl dsdigests[] = { DSDIGESTNAMES };
178
static struct tbl dsyncschemes[] = { DSYNCSCHEMES };
179
static struct tbl privatednss[] = { PRIVATEDNSS SENTINEL };
180
static struct tbl privateoids[] = { PRIVATEOIDS SENTINEL };
181
static struct tbl dstalgorithms[] = { PRIVATEDNSS PRIVATEOIDS SECALGNAMES };
182
183
static struct keyflag {
184
  const char *name;
185
  unsigned int value;
186
  unsigned int mask;
187
} keyflags[] = { { "NOCONF", 0x4000, 0xC000 },
188
     { "NOAUTH", 0x8000, 0xC000 },
189
     { "NOKEY", 0xC000, 0xC000 },
190
     { "FLAG2", 0x2000, 0x2000 },
191
     { "EXTEND", 0x1000, 0x1000 },
192
     { "FLAG4", 0x0800, 0x0800 },
193
     { "FLAG5", 0x0400, 0x0400 },
194
     { "USER", 0x0000, 0x0300 },
195
     { "ZONE", 0x0100, 0x0300 },
196
     { "HOST", 0x0200, 0x0300 },
197
     { "NTYP3", 0x0300, 0x0300 },
198
     { "FLAG8", 0x0080, 0x0080 },
199
     { "FLAG9", 0x0040, 0x0040 },
200
     { "FLAG10", 0x0020, 0x0020 },
201
     { "FLAG11", 0x0010, 0x0010 },
202
     { "SIG0", 0x0000, 0x000F },
203
     { "SIG1", 0x0001, 0x000F },
204
     { "SIG2", 0x0002, 0x000F },
205
     { "SIG3", 0x0003, 0x000F },
206
     { "SIG4", 0x0004, 0x000F },
207
     { "SIG5", 0x0005, 0x000F },
208
     { "SIG6", 0x0006, 0x000F },
209
     { "SIG7", 0x0007, 0x000F },
210
     { "SIG8", 0x0008, 0x000F },
211
     { "SIG9", 0x0009, 0x000F },
212
     { "SIG10", 0x000A, 0x000F },
213
     { "SIG11", 0x000B, 0x000F },
214
     { "SIG12", 0x000C, 0x000F },
215
     { "SIG13", 0x000D, 0x000F },
216
     { "SIG14", 0x000E, 0x000F },
217
     { "SIG15", 0x000F, 0x000F },
218
     { "KSK", DNS_KEYFLAG_KSK, DNS_KEYFLAG_KSK },
219
     { NULL, 0, 0 } };
220
221
static isc_result_t
222
428k
str_totext(const char *source, isc_buffer_t *target) {
223
428k
  unsigned int l;
224
428k
  isc_region_t region;
225
226
428k
  isc_buffer_availableregion(target, &region);
227
428k
  l = strlen(source);
228
229
428k
  if (l > region.length) {
230
0
    return ISC_R_NOSPACE;
231
0
  }
232
233
428k
  memmove(region.base, source, l);
234
428k
  isc_buffer_add(target, l);
235
428k
  return ISC_R_SUCCESS;
236
428k
}
237
238
static isc_result_t
239
maybe_numeric(unsigned int *valuep, isc_textregion_t *source, unsigned int max,
240
1.32M
        bool hex_allowed) {
241
1.32M
  isc_result_t result;
242
1.32M
  uint32_t n;
243
1.32M
  char buffer[NUMBERSIZE];
244
1.32M
  int v;
245
246
1.32M
  if (!isdigit((unsigned char)source->base[0]) ||
247
1.31M
      source->length > NUMBERSIZE - 1)
248
5.17k
  {
249
5.17k
    return ISC_R_BADNUMBER;
250
5.17k
  }
251
252
  /*
253
   * We have a potential number.  Try to parse it with
254
   * isc_parse_uint32().  isc_parse_uint32() requires
255
   * null termination, so we must make a copy.
256
   */
257
1.31M
  v = snprintf(buffer, sizeof(buffer), "%.*s", (int)source->length,
258
1.31M
         source->base);
259
1.31M
  if (v < 0 || (unsigned int)v != source->length) {
260
41
    return ISC_R_BADNUMBER;
261
41
  }
262
1.31M
  INSIST(buffer[source->length] == '\0');
263
264
1.31M
  result = isc_parse_uint32(&n, buffer, 10);
265
1.31M
  if (result == ISC_R_BADNUMBER && hex_allowed) {
266
173
    result = isc_parse_uint32(&n, buffer, 16);
267
173
  }
268
1.31M
  if (result != ISC_R_SUCCESS) {
269
59
    return result;
270
59
  }
271
1.31M
  if (n > max) {
272
134
    return ISC_R_RANGE;
273
134
  }
274
1.31M
  *valuep = n;
275
1.31M
  return ISC_R_SUCCESS;
276
1.31M
}
277
278
static isc_result_t
279
dns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source,
280
1.32M
          struct tbl *table, unsigned int max) {
281
1.32M
  isc_result_t result;
282
1.32M
  int i;
283
284
1.32M
  result = maybe_numeric(valuep, source, max, false);
285
1.32M
  if (result != ISC_R_BADNUMBER) {
286
1.31M
    return result;
287
1.31M
  }
288
289
30.4k
  for (i = 0; table[i].name != NULL; i++) {
290
29.3k
    unsigned int n;
291
29.3k
    n = strlen(table[i].name);
292
29.3k
    if (n == source->length && (table[i].flags & TOTEXTONLY) == 0 &&
293
6.70k
        strncasecmp(source->base, table[i].name, n) == 0)
294
3.62k
    {
295
3.62k
      *valuep = table[i].value;
296
3.62k
      return ISC_R_SUCCESS;
297
3.62k
    }
298
29.3k
  }
299
1.14k
  return DNS_R_UNKNOWN;
300
4.76k
}
301
302
static isc_result_t
303
dns_mnemonic_totext(unsigned int value, isc_buffer_t *target,
304
34.5k
        struct tbl *table) {
305
34.5k
  int i = 0;
306
34.5k
  char buf[sizeof("4294967296")];
307
331k
  while (table[i].name != NULL) {
308
320k
    if (table[i].value == value) {
309
23.5k
      return str_totext(table[i].name, target);
310
23.5k
    }
311
297k
    i++;
312
297k
  }
313
10.9k
  snprintf(buf, sizeof(buf), "%u", value);
314
10.9k
  return str_totext(buf, target);
315
34.5k
}
316
317
isc_result_t
318
0
dns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
319
0
  unsigned int value;
320
0
  RETERR(dns_mnemonic_fromtext(&value, source, rcodes, 0xffff));
321
0
  *rcodep = value;
322
0
  return ISC_R_SUCCESS;
323
0
}
324
325
isc_result_t
326
18.4k
dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
327
18.4k
  return dns_mnemonic_totext(rcode, target, rcodes);
328
18.4k
}
329
330
isc_result_t
331
433
dns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
332
433
  unsigned int value;
333
433
  RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff));
334
101
  *rcodep = value;
335
101
  return ISC_R_SUCCESS;
336
433
}
337
338
isc_result_t
339
3.26k
dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
340
3.26k
  return dns_mnemonic_totext(rcode, target, tsigrcodes);
341
3.26k
}
342
343
isc_result_t
344
974
dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source) {
345
974
  unsigned int value;
346
974
  RETERR(dns_mnemonic_fromtext(&value, source, certs, 0xffff));
347
850
  *certp = value;
348
850
  return ISC_R_SUCCESS;
349
974
}
350
351
isc_result_t
352
2.72k
dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) {
353
2.72k
  return dns_mnemonic_totext(cert, target, certs);
354
2.72k
}
355
356
isc_result_t
357
14.0k
dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) {
358
14.0k
  unsigned int value;
359
14.0k
  RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff));
360
13.7k
  *secalgp = value;
361
13.7k
  return ISC_R_SUCCESS;
362
14.0k
}
363
364
isc_result_t
365
8.93k
dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) {
366
8.93k
  return dns_mnemonic_totext(secalg, target, secalgs);
367
8.93k
}
368
369
void
370
6.20k
dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
371
6.20k
  isc_buffer_t b;
372
6.20k
  isc_region_t r;
373
6.20k
  isc_result_t result;
374
375
6.20k
  REQUIRE(cp != NULL && size > 0);
376
6.20k
  isc_buffer_init(&b, cp, size - 1);
377
6.20k
  result = dns_secalg_totext(alg, &b);
378
6.20k
  isc_buffer_usedregion(&b, &r);
379
6.20k
  r.base[r.length] = 0;
380
6.20k
  if (result != ISC_R_SUCCESS) {
381
0
    r.base[0] = 0;
382
0
  }
383
6.20k
}
384
385
isc_result_t
386
0
dst_privatedns_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
387
0
  unsigned int value;
388
0
  RETERR(dns_mnemonic_fromtext(&value, source, privatednss, 0));
389
0
  *dstalgp = value;
390
0
  return ISC_R_SUCCESS;
391
0
}
392
393
isc_result_t
394
0
dns_privatedns_totext(dst_algorithm_t alg, isc_buffer_t *target) {
395
0
  return dns_mnemonic_totext(alg, target, privatednss);
396
0
}
397
398
void
399
0
dns_privatedns_format(dst_algorithm_t alg, char *cp, unsigned int size) {
400
0
  isc_buffer_t b;
401
0
  isc_region_t r;
402
0
  isc_result_t result;
403
404
0
  REQUIRE(cp != NULL && size > 0);
405
0
  isc_buffer_init(&b, cp, size - 1);
406
0
  result = dns_privatedns_totext(alg, &b);
407
0
  isc_buffer_usedregion(&b, &r);
408
0
  r.base[r.length] = 0;
409
0
  if (result != ISC_R_SUCCESS) {
410
0
    r.base[0] = 0;
411
0
  }
412
0
}
413
414
isc_result_t
415
0
dst_privateoid_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
416
0
  unsigned int value;
417
0
  RETERR(dns_mnemonic_fromtext(&value, source, privateoids, 0));
418
0
  *dstalgp = value;
419
0
  return ISC_R_SUCCESS;
420
0
}
421
422
isc_result_t
423
0
dns_privateoid_totext(dst_algorithm_t alg, isc_buffer_t *target) {
424
0
  return dns_mnemonic_totext(alg, target, privateoids);
425
0
}
426
427
void
428
0
dns_privateoid_format(dst_algorithm_t alg, char *cp, unsigned int size) {
429
0
  isc_buffer_t b;
430
0
  isc_region_t r;
431
0
  isc_result_t result;
432
433
0
  REQUIRE(cp != NULL && size > 0);
434
0
  isc_buffer_init(&b, cp, size - 1);
435
0
  result = dns_privateoid_totext(alg, &b);
436
0
  isc_buffer_usedregion(&b, &r);
437
0
  r.base[r.length] = 0;
438
0
  if (result != ISC_R_SUCCESS) {
439
0
    r.base[0] = 0;
440
0
  }
441
0
}
442
443
isc_result_t
444
2.95k
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
445
2.95k
  unsigned int value;
446
2.95k
  RETERR(dns_mnemonic_fromtext(&value, source, secprotos, 0xff));
447
2.82k
  *secprotop = value;
448
2.82k
  return ISC_R_SUCCESS;
449
2.95k
}
450
451
isc_result_t
452
0
dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target) {
453
0
  return dns_mnemonic_totext(secproto, target, secprotos);
454
0
}
455
456
isc_result_t
457
4.52k
dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) {
458
4.52k
  unsigned int value;
459
4.52k
  RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff));
460
4.41k
  *hashalg = value;
461
4.41k
  return ISC_R_SUCCESS;
462
4.52k
}
463
464
isc_result_t
465
3.17k
dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source) {
466
3.17k
  isc_result_t result;
467
3.17k
  char *text, *end;
468
3.17k
  unsigned int value = 0;
469
#ifdef notyet
470
  unsigned int mask = 0;
471
#endif /* ifdef notyet */
472
473
3.17k
  result = maybe_numeric(&value, source, 0xffff, true);
474
3.17k
  if (result == ISC_R_SUCCESS) {
475
2.61k
    *flagsp = value;
476
2.61k
    return ISC_R_SUCCESS;
477
2.61k
  }
478
556
  if (result != ISC_R_BADNUMBER) {
479
52
    return result;
480
52
  }
481
482
504
  text = source->base;
483
504
  end = source->base + source->length;
484
485
1.30k
  while (text < end) {
486
891
    struct keyflag *p;
487
891
    unsigned int len;
488
891
    char *delim = memchr(text, '|', end - text);
489
891
    if (delim != NULL) {
490
403
      len = (unsigned int)(delim - text);
491
488
    } else {
492
488
      len = (unsigned int)(end - text);
493
488
    }
494
9.14k
    for (p = keyflags; p->name != NULL; p++) {
495
9.05k
      if (strncasecmp(p->name, text, len) == 0) {
496
804
        break;
497
804
      }
498
9.05k
    }
499
891
    if (p->name == NULL) {
500
87
      return DNS_R_UNKNOWNFLAG;
501
87
    }
502
804
    value |= p->value;
503
#ifdef notyet
504
    if ((mask & p->mask) != 0) {
505
      warn("overlapping key flags");
506
    }
507
    mask |= p->mask;
508
#endif /* ifdef notyet */
509
804
    text += len;
510
804
    if (delim != NULL) {
511
403
      text++; /* Skip "|" */
512
403
    }
513
804
  }
514
417
  *flagsp = value;
515
417
  return ISC_R_SUCCESS;
516
504
}
517
518
isc_result_t
519
1.63k
dns_dsdigest_fromtext(dns_dsdigest_t *dsdigestp, isc_textregion_t *source) {
520
1.63k
  unsigned int value;
521
1.63k
  RETERR(dns_mnemonic_fromtext(&value, source, dsdigests, 0xff));
522
1.44k
  *dsdigestp = value;
523
1.44k
  return ISC_R_SUCCESS;
524
1.63k
}
525
526
isc_result_t
527
0
dns_dsdigest_totext(dns_dsdigest_t dsdigest, isc_buffer_t *target) {
528
0
  return dns_mnemonic_totext(dsdigest, target, dsdigests);
529
0
}
530
531
void
532
0
dns_dsdigest_format(dns_dsdigest_t typ, char *cp, unsigned int size) {
533
0
  isc_buffer_t b;
534
0
  isc_region_t r;
535
0
  isc_result_t result;
536
537
0
  REQUIRE(cp != NULL && size > 0);
538
0
  isc_buffer_init(&b, cp, size - 1);
539
0
  result = dns_dsdigest_totext(typ, &b);
540
0
  isc_buffer_usedregion(&b, &r);
541
0
  r.base[r.length] = 0;
542
0
  if (result != ISC_R_SUCCESS) {
543
0
    r.base[0] = 0;
544
0
  }
545
0
}
546
547
/*
548
 * DSYNC Scheme
549
 */
550
551
isc_result_t
552
1.29M
dns_dsyncscheme_fromtext(dns_dsyncscheme_t *schemep, isc_textregion_t *source) {
553
1.29M
  unsigned int value;
554
555
1.29M
  REQUIRE(schemep != NULL);
556
1.29M
  RETERR(dns_mnemonic_fromtext(&value, source, dsyncschemes, 0xff));
557
1.29M
  *schemep = value;
558
1.29M
  return ISC_R_SUCCESS;
559
1.29M
}
560
561
isc_result_t
562
1.12k
dns_dsyncscheme_totext(dns_dsyncscheme_t scheme, isc_buffer_t *target) {
563
1.12k
  return dns_mnemonic_totext(scheme, target, dsyncschemes);
564
1.12k
}
565
566
void
567
0
dns_dsyncscheme_format(dns_dsyncscheme_t scheme, char *cp, unsigned int size) {
568
0
  isc_buffer_t b;
569
0
  isc_region_t r;
570
0
  isc_result_t result;
571
572
0
  REQUIRE(cp != NULL && size > 0);
573
0
  isc_buffer_init(&b, cp, size - 1);
574
0
  result = dns_dsyncscheme_totext(scheme, &b);
575
0
  isc_buffer_usedregion(&b, &r);
576
0
  r.base[r.length] = 0;
577
0
  if (result != ISC_R_SUCCESS) {
578
0
    r.base[0] = 0;
579
0
  }
580
0
}
581
582
/*
583
 * This uses lots of hard coded values, but how often do we actually
584
 * add classes?
585
 */
586
isc_result_t
587
566k
dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) {
588
566k
#define COMPARE(string, rdclass)                                      \
589
566k
  if (((sizeof(string) - 1) == source->length) &&               \
590
137k
      (strncasecmp(source->base, string, source->length) == 0)) \
591
137k
  {                                                             \
592
1.58k
    *classp = rdclass;                                    \
593
1.58k
    return (ISC_R_SUCCESS);                               \
594
1.58k
  }
595
596
566k
  switch (isc_ascii_tolower(source->base[0])) {
597
55.9k
  case 'a':
598
55.9k
    COMPARE("any", dns_rdataclass_any);
599
55.9k
    break;
600
2.58k
  case 'c':
601
    /*
602
     * RFC1035 says the mnemonic for the CHAOS class is CH,
603
     * but historical BIND practice is to call it CHAOS.
604
     * We will accept both forms, but only generate CH.
605
     */
606
2.58k
    COMPARE("ch", dns_rdataclass_chaos);
607
2.57k
    COMPARE("chaos", dns_rdataclass_chaos);
608
609
2.57k
    if (source->length > 5 &&
610
1.08k
        source->length < (5 + sizeof("65000")) &&
611
960
        strncasecmp("class", source->base, 5) == 0)
612
238
    {
613
238
      char buf[sizeof("65000")];
614
238
      char *endp;
615
238
      unsigned int val;
616
617
      /*
618
       * source->base is not required to be NUL terminated.
619
       * Copy up to remaining bytes and NUL terminate.
620
       */
621
238
      snprintf(buf, sizeof(buf), "%.*s",
622
238
         (int)(source->length - 5), source->base + 5);
623
238
      val = strtoul(buf, &endp, 10);
624
238
      if (*endp == '\0' && val <= 0xffff) {
625
215
        *classp = (dns_rdataclass_t)val;
626
215
        return ISC_R_SUCCESS;
627
215
      }
628
238
    }
629
2.36k
    break;
630
2.36k
  case 'h':
631
1.91k
    COMPARE("hs", dns_rdataclass_hs);
632
1.91k
    COMPARE("hesiod", dns_rdataclass_hs);
633
1.91k
    break;
634
2.40k
  case 'i':
635
2.40k
    COMPARE("in", dns_rdataclass_in);
636
858
    break;
637
68.3k
  case 'n':
638
68.3k
    COMPARE("none", dns_rdataclass_none);
639
68.3k
    break;
640
2.10k
  case 'r':
641
2.10k
    COMPARE("reserved0", dns_rdataclass_reserved0);
642
2.10k
    break;
643
566k
  }
644
645
564k
#undef COMPARE
646
647
564k
  return DNS_R_UNKNOWN;
648
566k
}
649
650
isc_result_t
651
394k
dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
652
394k
  switch (rdclass) {
653
6.22k
  case dns_rdataclass_any:
654
6.22k
    return str_totext("ANY", target);
655
4.56k
  case dns_rdataclass_chaos:
656
4.56k
    return str_totext("CH", target);
657
2.44k
  case dns_rdataclass_hs:
658
2.44k
    return str_totext("HS", target);
659
44.3k
  case dns_rdataclass_in:
660
44.3k
    return str_totext("IN", target);
661
5.74k
  case dns_rdataclass_none:
662
5.74k
    return str_totext("NONE", target);
663
47.4k
  case dns_rdataclass_reserved0:
664
47.4k
    return str_totext("RESERVED0", target);
665
283k
  default:
666
283k
    return dns_rdataclass_tounknowntext(rdclass, target);
667
394k
  }
668
394k
}
669
670
isc_result_t
671
283k
dns_rdataclass_tounknowntext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
672
283k
  char buf[sizeof("CLASS65535")];
673
674
283k
  snprintf(buf, sizeof(buf), "CLASS%u", rdclass);
675
283k
  return str_totext(buf, target);
676
283k
}
677
678
void
679
dns_rdataclass_format(dns_rdataclass_t rdclass, char *array,
680
52
          unsigned int size) {
681
52
  isc_result_t result;
682
52
  isc_buffer_t buf;
683
684
52
  if (size == 0U) {
685
0
    return;
686
0
  }
687
688
52
  isc_buffer_init(&buf, array, size);
689
52
  result = dns_rdataclass_totext(rdclass, &buf);
690
  /*
691
   * Null terminate.
692
   */
693
52
  if (result == ISC_R_SUCCESS) {
694
52
    if (isc_buffer_availablelength(&buf) >= 1) {
695
52
      isc_buffer_putuint8(&buf, 0);
696
52
    } else {
697
0
      result = ISC_R_NOSPACE;
698
0
    }
699
52
  }
700
52
  if (result != ISC_R_SUCCESS) {
701
0
    strlcpy(array, "<unknown>", size);
702
0
  }
703
52
}
704
705
isc_result_t
706
0
dst_algorithm_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
707
0
  unsigned int value;
708
0
  RETERR(dns_mnemonic_fromtext(&value, source, dstalgorithms, 255));
709
0
  *dstalgp = value;
710
0
  return ISC_R_SUCCESS;
711
0
}
712
713
isc_result_t
714
0
dst_algorithm_totext(dst_algorithm_t alg, isc_buffer_t *target) {
715
0
  return dns_mnemonic_totext(alg, target, dstalgorithms);
716
0
}
717
718
void
719
0
dst_algorithm_format(dst_algorithm_t alg, char *cp, unsigned int size) {
720
0
  isc_buffer_t b;
721
0
  isc_region_t r;
722
0
  isc_result_t result;
723
724
0
  REQUIRE(cp != NULL && size > 0);
725
0
  isc_buffer_init(&b, cp, size - 1);
726
0
  result = dst_algorithm_totext(alg, &b);
727
0
  isc_buffer_usedregion(&b, &r);
728
0
  r.base[r.length] = 0;
729
0
  if (result != ISC_R_SUCCESS) {
730
0
    r.base[0] = 0;
731
0
  }
732
0
}