Coverage Report

Created: 2026-01-10 06:27

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
0
#define NUMBERSIZE sizeof("037777777777") /* 2^32-1 octal + NUL */
43
44
0
#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
0
str_totext(const char *source, isc_buffer_t *target) {
223
0
  unsigned int l;
224
0
  isc_region_t region;
225
226
0
  isc_buffer_availableregion(target, &region);
227
0
  l = strlen(source);
228
229
0
  if (l > region.length) {
230
0
    return ISC_R_NOSPACE;
231
0
  }
232
233
0
  memmove(region.base, source, l);
234
0
  isc_buffer_add(target, l);
235
0
  return ISC_R_SUCCESS;
236
0
}
237
238
static isc_result_t
239
maybe_numeric(unsigned int *valuep, isc_textregion_t *source, unsigned int max,
240
0
        bool hex_allowed) {
241
0
  isc_result_t result;
242
0
  uint32_t n;
243
0
  char buffer[NUMBERSIZE];
244
0
  int v;
245
246
0
  if (!isdigit((unsigned char)source->base[0]) ||
247
0
      source->length > NUMBERSIZE - 1)
248
0
  {
249
0
    return ISC_R_BADNUMBER;
250
0
  }
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
0
  v = snprintf(buffer, sizeof(buffer), "%.*s", (int)source->length,
258
0
         source->base);
259
0
  if (v < 0 || (unsigned int)v != source->length) {
260
0
    return ISC_R_BADNUMBER;
261
0
  }
262
0
  INSIST(buffer[source->length] == '\0');
263
264
0
  result = isc_parse_uint32(&n, buffer, 10);
265
0
  if (result == ISC_R_BADNUMBER && hex_allowed) {
266
0
    result = isc_parse_uint32(&n, buffer, 16);
267
0
  }
268
0
  if (result != ISC_R_SUCCESS) {
269
0
    return result;
270
0
  }
271
0
  if (n > max) {
272
0
    return ISC_R_RANGE;
273
0
  }
274
0
  *valuep = n;
275
0
  return ISC_R_SUCCESS;
276
0
}
277
278
static isc_result_t
279
dns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source,
280
0
          struct tbl *table, unsigned int max) {
281
0
  isc_result_t result;
282
0
  int i;
283
284
0
  result = maybe_numeric(valuep, source, max, false);
285
0
  if (result != ISC_R_BADNUMBER) {
286
0
    return result;
287
0
  }
288
289
0
  for (i = 0; table[i].name != NULL; i++) {
290
0
    unsigned int n;
291
0
    n = strlen(table[i].name);
292
0
    if (n == source->length && (table[i].flags & TOTEXTONLY) == 0 &&
293
0
        strncasecmp(source->base, table[i].name, n) == 0)
294
0
    {
295
0
      *valuep = table[i].value;
296
0
      return ISC_R_SUCCESS;
297
0
    }
298
0
  }
299
0
  return DNS_R_UNKNOWN;
300
0
}
301
302
static isc_result_t
303
dns_mnemonic_totext(unsigned int value, isc_buffer_t *target,
304
0
        struct tbl *table) {
305
0
  int i = 0;
306
0
  char buf[sizeof("4294967296")];
307
0
  while (table[i].name != NULL) {
308
0
    if (table[i].value == value) {
309
0
      return str_totext(table[i].name, target);
310
0
    }
311
0
    i++;
312
0
  }
313
0
  snprintf(buf, sizeof(buf), "%u", value);
314
0
  return str_totext(buf, target);
315
0
}
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
0
dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
327
0
  return dns_mnemonic_totext(rcode, target, rcodes);
328
0
}
329
330
isc_result_t
331
0
dns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
332
0
  unsigned int value;
333
0
  RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff));
334
0
  *rcodep = value;
335
0
  return ISC_R_SUCCESS;
336
0
}
337
338
isc_result_t
339
0
dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
340
0
  return dns_mnemonic_totext(rcode, target, tsigrcodes);
341
0
}
342
343
isc_result_t
344
0
dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source) {
345
0
  unsigned int value;
346
0
  RETERR(dns_mnemonic_fromtext(&value, source, certs, 0xffff));
347
0
  *certp = value;
348
0
  return ISC_R_SUCCESS;
349
0
}
350
351
isc_result_t
352
0
dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) {
353
0
  return dns_mnemonic_totext(cert, target, certs);
354
0
}
355
356
isc_result_t
357
0
dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) {
358
0
  unsigned int value;
359
0
  RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff));
360
0
  *secalgp = value;
361
0
  return ISC_R_SUCCESS;
362
0
}
363
364
isc_result_t
365
0
dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) {
366
0
  return dns_mnemonic_totext(secalg, target, secalgs);
367
0
}
368
369
void
370
0
dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
371
0
  isc_buffer_t b;
372
0
  isc_region_t r;
373
0
  isc_result_t result;
374
375
0
  REQUIRE(cp != NULL && size > 0);
376
0
  isc_buffer_init(&b, cp, size - 1);
377
0
  result = dns_secalg_totext(alg, &b);
378
0
  isc_buffer_usedregion(&b, &r);
379
0
  r.base[r.length] = 0;
380
0
  if (result != ISC_R_SUCCESS) {
381
0
    r.base[0] = 0;
382
0
  }
383
0
}
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
0
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
445
0
  unsigned int value;
446
0
  RETERR(dns_mnemonic_fromtext(&value, source, secprotos, 0xff));
447
0
  *secprotop = value;
448
0
  return ISC_R_SUCCESS;
449
0
}
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
0
dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) {
458
0
  unsigned int value;
459
0
  RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff));
460
0
  *hashalg = value;
461
0
  return ISC_R_SUCCESS;
462
0
}
463
464
isc_result_t
465
0
dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source) {
466
0
  isc_result_t result;
467
0
  char *text, *end;
468
0
  unsigned int value = 0;
469
#ifdef notyet
470
  unsigned int mask = 0;
471
#endif /* ifdef notyet */
472
473
0
  result = maybe_numeric(&value, source, 0xffff, true);
474
0
  if (result == ISC_R_SUCCESS) {
475
0
    *flagsp = value;
476
0
    return ISC_R_SUCCESS;
477
0
  }
478
0
  if (result != ISC_R_BADNUMBER) {
479
0
    return result;
480
0
  }
481
482
0
  text = source->base;
483
0
  end = source->base + source->length;
484
485
0
  while (text < end) {
486
0
    struct keyflag *p;
487
0
    unsigned int len;
488
0
    char *delim = memchr(text, '|', end - text);
489
0
    if (delim != NULL) {
490
0
      len = (unsigned int)(delim - text);
491
0
    } else {
492
0
      len = (unsigned int)(end - text);
493
0
    }
494
0
    for (p = keyflags; p->name != NULL; p++) {
495
0
      if (strncasecmp(p->name, text, len) == 0) {
496
0
        break;
497
0
      }
498
0
    }
499
0
    if (p->name == NULL) {
500
0
      return DNS_R_UNKNOWNFLAG;
501
0
    }
502
0
    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
0
    text += len;
510
0
    if (delim != NULL) {
511
0
      text++; /* Skip "|" */
512
0
    }
513
0
  }
514
0
  *flagsp = value;
515
0
  return ISC_R_SUCCESS;
516
0
}
517
518
isc_result_t
519
0
dns_dsdigest_fromtext(dns_dsdigest_t *dsdigestp, isc_textregion_t *source) {
520
0
  unsigned int value;
521
0
  RETERR(dns_mnemonic_fromtext(&value, source, dsdigests, 0xff));
522
0
  *dsdigestp = value;
523
0
  return ISC_R_SUCCESS;
524
0
}
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
0
dns_dsyncscheme_fromtext(dns_dsyncscheme_t *schemep, isc_textregion_t *source) {
553
0
  unsigned int value;
554
555
0
  REQUIRE(schemep != NULL);
556
0
  RETERR(dns_mnemonic_fromtext(&value, source, dsyncschemes, 0xff));
557
0
  *schemep = value;
558
0
  return ISC_R_SUCCESS;
559
0
}
560
561
isc_result_t
562
0
dns_dsyncscheme_totext(dns_dsyncscheme_t scheme, isc_buffer_t *target) {
563
0
  return dns_mnemonic_totext(scheme, target, dsyncschemes);
564
0
}
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
0
dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) {
588
0
#define COMPARE(string, rdclass)                                      \
589
0
  if (((sizeof(string) - 1) == source->length) &&               \
590
0
      (strncasecmp(source->base, string, source->length) == 0)) \
591
0
  {                                                             \
592
0
    *classp = rdclass;                                    \
593
0
    return (ISC_R_SUCCESS);                               \
594
0
  }
595
596
0
  switch (isc_ascii_tolower(source->base[0])) {
597
0
  case 'a':
598
0
    COMPARE("any", dns_rdataclass_any);
599
0
    break;
600
0
  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
0
    COMPARE("ch", dns_rdataclass_chaos);
607
0
    COMPARE("chaos", dns_rdataclass_chaos);
608
609
0
    if (source->length > 5 &&
610
0
        source->length < (5 + sizeof("65000")) &&
611
0
        strncasecmp("class", source->base, 5) == 0)
612
0
    {
613
0
      char buf[sizeof("65000")];
614
0
      char *endp;
615
0
      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
0
      snprintf(buf, sizeof(buf), "%.*s",
622
0
         (int)(source->length - 5), source->base + 5);
623
0
      val = strtoul(buf, &endp, 10);
624
0
      if (*endp == '\0' && val <= 0xffff) {
625
0
        *classp = (dns_rdataclass_t)val;
626
0
        return ISC_R_SUCCESS;
627
0
      }
628
0
    }
629
0
    break;
630
0
  case 'h':
631
0
    COMPARE("hs", dns_rdataclass_hs);
632
0
    COMPARE("hesiod", dns_rdataclass_hs);
633
0
    break;
634
0
  case 'i':
635
0
    COMPARE("in", dns_rdataclass_in);
636
0
    break;
637
0
  case 'n':
638
0
    COMPARE("none", dns_rdataclass_none);
639
0
    break;
640
0
  case 'r':
641
0
    COMPARE("reserved0", dns_rdataclass_reserved0);
642
0
    break;
643
0
  }
644
645
0
#undef COMPARE
646
647
0
  return DNS_R_UNKNOWN;
648
0
}
649
650
isc_result_t
651
0
dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
652
0
  switch (rdclass) {
653
0
  case dns_rdataclass_any:
654
0
    return str_totext("ANY", target);
655
0
  case dns_rdataclass_chaos:
656
0
    return str_totext("CH", target);
657
0
  case dns_rdataclass_hs:
658
0
    return str_totext("HS", target);
659
0
  case dns_rdataclass_in:
660
0
    return str_totext("IN", target);
661
0
  case dns_rdataclass_none:
662
0
    return str_totext("NONE", target);
663
0
  case dns_rdataclass_reserved0:
664
0
    return str_totext("RESERVED0", target);
665
0
  default:
666
0
    return dns_rdataclass_tounknowntext(rdclass, target);
667
0
  }
668
0
}
669
670
isc_result_t
671
0
dns_rdataclass_tounknowntext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
672
0
  char buf[sizeof("CLASS65535")];
673
674
0
  snprintf(buf, sizeof(buf), "CLASS%u", rdclass);
675
0
  return str_totext(buf, target);
676
0
}
677
678
void
679
dns_rdataclass_format(dns_rdataclass_t rdclass, char *array,
680
0
          unsigned int size) {
681
0
  isc_result_t result;
682
0
  isc_buffer_t buf;
683
684
0
  if (size == 0U) {
685
0
    return;
686
0
  }
687
688
0
  isc_buffer_init(&buf, array, size);
689
0
  result = dns_rdataclass_totext(rdclass, &buf);
690
  /*
691
   * Null terminate.
692
   */
693
0
  if (result == ISC_R_SUCCESS) {
694
0
    if (isc_buffer_availablelength(&buf) >= 1) {
695
0
      isc_buffer_putuint8(&buf, 0);
696
0
    } else {
697
0
      result = ISC_R_NOSPACE;
698
0
    }
699
0
  }
700
0
  if (result != ISC_R_SUCCESS) {
701
0
    strlcpy(array, "<unknown>", size);
702
0
  }
703
0
}
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
}