Coverage Report

Created: 2026-10-17 06:53

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.34M
#define NUMBERSIZE sizeof("037777777777") /* 2^32-1 octal + NUL */
43
44
4.60k
#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 dstalgorithms[] = { PRIVATEDNSS PRIVATEOIDS SECALGNAMES };
180
181
static struct keyflag {
182
  const char *name;
183
  unsigned int value;
184
  unsigned int mask;
185
} keyflags[] = { { "NOCONF", 0x4000, 0xC000 },
186
     { "NOAUTH", 0x8000, 0xC000 },
187
     { "NOKEY", 0xC000, 0xC000 },
188
     { "FLAG2", 0x2000, 0x2000 },
189
     { "EXTEND", 0x1000, 0x1000 },
190
     { "FLAG4", 0x0800, 0x0800 },
191
     { "FLAG5", 0x0400, 0x0400 },
192
     { "USER", 0x0000, 0x0300 },
193
     { "ZONE", 0x0100, 0x0300 },
194
     { "HOST", 0x0200, 0x0300 },
195
     { "NTYP3", 0x0300, 0x0300 },
196
     { "FLAG8", 0x0080, 0x0080 },
197
     { "FLAG9", 0x0040, 0x0040 },
198
     { "FLAG10", 0x0020, 0x0020 },
199
     { "FLAG11", 0x0010, 0x0010 },
200
     { "SIG0", 0x0000, 0x000F },
201
     { "SIG1", 0x0001, 0x000F },
202
     { "SIG2", 0x0002, 0x000F },
203
     { "SIG3", 0x0003, 0x000F },
204
     { "SIG4", 0x0004, 0x000F },
205
     { "SIG5", 0x0005, 0x000F },
206
     { "SIG6", 0x0006, 0x000F },
207
     { "SIG7", 0x0007, 0x000F },
208
     { "SIG8", 0x0008, 0x000F },
209
     { "SIG9", 0x0009, 0x000F },
210
     { "SIG10", 0x000A, 0x000F },
211
     { "SIG11", 0x000B, 0x000F },
212
     { "SIG12", 0x000C, 0x000F },
213
     { "SIG13", 0x000D, 0x000F },
214
     { "SIG14", 0x000E, 0x000F },
215
     { "SIG15", 0x000F, 0x000F },
216
     { "KSK", DNS_KEYFLAG_KSK, DNS_KEYFLAG_KSK },
217
     { NULL, 0, 0 } };
218
219
static isc_result_t
220
714k
str_totext(const char *source, isc_buffer_t *target) {
221
714k
  unsigned int l;
222
714k
  isc_region_t region;
223
224
714k
  isc_buffer_availableregion(target, &region);
225
714k
  l = strlen(source);
226
227
714k
  if (l > region.length) {
228
2
    return ISC_R_NOSPACE;
229
2
  }
230
231
714k
  memmove(region.base, source, l);
232
714k
  isc_buffer_add(target, l);
233
714k
  return ISC_R_SUCCESS;
234
714k
}
235
236
static isc_result_t
237
maybe_numeric(unsigned int *valuep, isc_textregion_t *source, unsigned int max,
238
1.48M
        bool hex_allowed) {
239
1.48M
  isc_result_t result;
240
1.48M
  uint32_t n;
241
1.48M
  char buffer[NUMBERSIZE];
242
1.48M
  int v;
243
244
1.48M
  if (!isdigit((unsigned char)source->base[0]) ||
245
1.34M
      source->length > NUMBERSIZE - 1)
246
144k
  {
247
144k
    return ISC_R_BADNUMBER;
248
144k
  }
249
250
  /*
251
   * We have a potential number.  Try to parse it with
252
   * isc_parse_uint32().  isc_parse_uint32() requires
253
   * null termination, so we must make a copy.
254
   */
255
1.34M
  v = snprintf(buffer, sizeof(buffer), "%.*s", (int)source->length,
256
1.34M
         source->base);
257
1.34M
  if (v < 0 || (unsigned int)v != source->length) {
258
5
    return ISC_R_BADNUMBER;
259
5
  }
260
1.34M
  INSIST(buffer[source->length] == '\0');
261
262
1.34M
  result = isc_parse_uint32(&n, buffer, 10);
263
1.34M
  if (result == ISC_R_BADNUMBER && hex_allowed) {
264
417
    result = isc_parse_uint32(&n, buffer, 16);
265
417
  }
266
1.34M
  if (result != ISC_R_SUCCESS) {
267
41
    return result;
268
41
  }
269
1.34M
  if (n > max) {
270
131
    return ISC_R_RANGE;
271
131
  }
272
1.34M
  *valuep = n;
273
1.34M
  return ISC_R_SUCCESS;
274
1.34M
}
275
276
static isc_result_t
277
dns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source,
278
1.34M
          struct tbl *table, unsigned int max) {
279
1.34M
  isc_result_t result;
280
1.34M
  int i;
281
282
1.34M
  result = maybe_numeric(valuep, source, max, false);
283
1.34M
  if (result != ISC_R_BADNUMBER) {
284
1.33M
    return result;
285
1.33M
  }
286
287
27.7k
  for (i = 0; table[i].name != NULL; i++) {
288
26.7k
    unsigned int n;
289
26.7k
    n = strlen(table[i].name);
290
26.7k
    if (n == source->length && (table[i].flags & TOTEXTONLY) == 0 &&
291
4.56k
        strncasecmp(source->base, table[i].name, n) == 0)
292
1.55k
    {
293
1.55k
      *valuep = table[i].value;
294
1.55k
      return ISC_R_SUCCESS;
295
1.55k
    }
296
26.7k
  }
297
1.02k
  return DNS_R_UNKNOWN;
298
2.57k
}
299
300
static isc_result_t
301
dns_mnemonic_totext(unsigned int value, isc_buffer_t *target,
302
35.8k
        struct tbl *table) {
303
35.8k
  int i = 0;
304
35.8k
  char buf[sizeof("4294967296")];
305
335k
  while (table[i].name != NULL) {
306
323k
    if (table[i].value == value) {
307
23.6k
      return str_totext(table[i].name, target);
308
23.6k
    }
309
299k
    i++;
310
299k
  }
311
12.2k
  snprintf(buf, sizeof(buf), "%u", value);
312
12.2k
  return str_totext(buf, target);
313
35.8k
}
314
315
isc_result_t
316
0
dns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
317
0
  unsigned int value;
318
0
  RETERR(dns_mnemonic_fromtext(&value, source, rcodes, 0xffff));
319
0
  *rcodep = value;
320
0
  return ISC_R_SUCCESS;
321
0
}
322
323
isc_result_t
324
17.1k
dns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
325
17.1k
  return dns_mnemonic_totext(rcode, target, rcodes);
326
17.1k
}
327
328
isc_result_t
329
419
dns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) {
330
419
  unsigned int value;
331
419
  RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff));
332
91
  *rcodep = value;
333
91
  return ISC_R_SUCCESS;
334
419
}
335
336
isc_result_t
337
3.99k
dns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) {
338
3.99k
  return dns_mnemonic_totext(rcode, target, tsigrcodes);
339
3.99k
}
340
341
isc_result_t
342
1.08k
dns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source) {
343
1.08k
  unsigned int value;
344
1.08k
  RETERR(dns_mnemonic_fromtext(&value, source, certs, 0xffff));
345
975
  *certp = value;
346
975
  return ISC_R_SUCCESS;
347
1.08k
}
348
349
isc_result_t
350
2.89k
dns_cert_totext(dns_cert_t cert, isc_buffer_t *target) {
351
2.89k
  return dns_mnemonic_totext(cert, target, certs);
352
2.89k
}
353
354
isc_result_t
355
152k
dns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) {
356
152k
  unsigned int value;
357
152k
  RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff));
358
152k
  *secalgp = value;
359
152k
  return ISC_R_SUCCESS;
360
152k
}
361
362
isc_result_t
363
10.0k
dns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) {
364
10.0k
  return dns_mnemonic_totext(secalg, target, secalgs);
365
10.0k
}
366
367
void
368
7.11k
dns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) {
369
7.11k
  isc_buffer_t b;
370
7.11k
  isc_result_t result;
371
372
7.11k
  REQUIRE(cp != NULL && size > 0);
373
7.11k
  isc_buffer_init(&b, cp, size - 1);
374
7.11k
  result = dns_secalg_totext(alg, &b);
375
7.11k
  cp[isc_buffer_usedlength(&b)] = 0;
376
7.11k
  if (result != ISC_R_SUCCESS) {
377
0
    cp[0] = 0;
378
0
  }
379
7.11k
}
380
381
isc_result_t
382
144k
dns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) {
383
144k
  unsigned int value;
384
144k
  RETERR(dns_mnemonic_fromtext(&value, source, secprotos, 0xff));
385
144k
  *secprotop = value;
386
144k
  return ISC_R_SUCCESS;
387
144k
}
388
389
isc_result_t
390
0
dns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target) {
391
0
  return dns_mnemonic_totext(secproto, target, secprotos);
392
0
}
393
394
isc_result_t
395
3.78k
dns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) {
396
3.78k
  unsigned int value;
397
3.78k
  RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff));
398
3.70k
  *hashalg = value;
399
3.70k
  return ISC_R_SUCCESS;
400
3.78k
}
401
402
isc_result_t
403
144k
dns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source) {
404
144k
  isc_result_t result;
405
144k
  char *text, *end;
406
144k
  unsigned int value = 0;
407
#ifdef notyet
408
  unsigned int mask = 0;
409
#endif /* ifdef notyet */
410
411
144k
  result = maybe_numeric(&value, source, 0xffff, true);
412
144k
  if (result == ISC_R_SUCCESS) {
413
2.92k
    *flagsp = value;
414
2.92k
    return ISC_R_SUCCESS;
415
2.92k
  }
416
141k
  if (result != ISC_R_BADNUMBER) {
417
41
    return result;
418
41
  }
419
420
141k
  text = source->base;
421
141k
  end = source->base + source->length;
422
423
283k
  while (text < end) {
424
142k
    struct keyflag *p;
425
142k
    unsigned int len;
426
142k
    char *delim = memchr(text, '|', end - text);
427
142k
    if (delim != NULL) {
428
401
      len = (unsigned int)(delim - text);
429
141k
    } else {
430
141k
      len = (unsigned int)(end - text);
431
141k
    }
432
1.13M
    for (p = keyflags; p->name != NULL; p++) {
433
1.13M
      if (strncasecmp(p->name, text, len) == 0) {
434
142k
        break;
435
142k
      }
436
1.13M
    }
437
142k
    if (p->name == NULL) {
438
70
      return DNS_R_UNKNOWNFLAG;
439
70
    }
440
142k
    value |= p->value;
441
#ifdef notyet
442
    if ((mask & p->mask) != 0) {
443
      warn("overlapping key flags");
444
    }
445
    mask |= p->mask;
446
#endif /* ifdef notyet */
447
142k
    text += len;
448
142k
    if (delim != NULL) {
449
400
      text++; /* Skip "|" */
450
400
    }
451
142k
  }
452
141k
  *flagsp = value;
453
141k
  return ISC_R_SUCCESS;
454
141k
}
455
456
isc_result_t
457
1.85k
dns_dsdigest_fromtext(dns_dsdigest_t *dsdigestp, isc_textregion_t *source) {
458
1.85k
  unsigned int value;
459
1.85k
  RETERR(dns_mnemonic_fromtext(&value, source, dsdigests, 0xff));
460
1.67k
  *dsdigestp = value;
461
1.67k
  return ISC_R_SUCCESS;
462
1.85k
}
463
464
isc_result_t
465
0
dns_dsdigest_totext(dns_dsdigest_t dsdigest, isc_buffer_t *target) {
466
0
  return dns_mnemonic_totext(dsdigest, target, dsdigests);
467
0
}
468
469
void
470
0
dns_dsdigest_format(dns_dsdigest_t typ, char *cp, unsigned int size) {
471
0
  isc_buffer_t b;
472
0
  isc_region_t r;
473
0
  isc_result_t result;
474
475
0
  REQUIRE(cp != NULL && size > 0);
476
0
  isc_buffer_init(&b, cp, size - 1);
477
0
  result = dns_dsdigest_totext(typ, &b);
478
0
  isc_buffer_usedregion(&b, &r);
479
0
  cp[r.length] = 0;
480
0
  if (result != ISC_R_SUCCESS) {
481
0
    r.base[0] = 0;
482
0
  }
483
0
}
484
485
/*
486
 * DSYNC Scheme
487
 */
488
489
isc_result_t
490
1.03M
dns_dsyncscheme_fromtext(dns_dsyncscheme_t *schemep, isc_textregion_t *source) {
491
1.03M
  unsigned int value;
492
493
1.03M
  REQUIRE(schemep != NULL);
494
1.03M
  RETERR(dns_mnemonic_fromtext(&value, source, dsyncschemes, 0xff));
495
1.03M
  *schemep = value;
496
1.03M
  return ISC_R_SUCCESS;
497
1.03M
}
498
499
isc_result_t
500
1.76k
dns_dsyncscheme_totext(dns_dsyncscheme_t scheme, isc_buffer_t *target) {
501
1.76k
  return dns_mnemonic_totext(scheme, target, dsyncschemes);
502
1.76k
}
503
504
void
505
0
dns_dsyncscheme_format(dns_dsyncscheme_t scheme, char *cp, unsigned int size) {
506
0
  isc_buffer_t b;
507
0
  isc_region_t r;
508
0
  isc_result_t result;
509
510
0
  REQUIRE(cp != NULL && size > 0);
511
0
  isc_buffer_init(&b, cp, size - 1);
512
0
  result = dns_dsyncscheme_totext(scheme, &b);
513
0
  isc_buffer_usedregion(&b, &r);
514
0
  cp[r.length] = 0;
515
0
  if (result != ISC_R_SUCCESS) {
516
0
    r.base[0] = 0;
517
0
  }
518
0
}
519
520
/*
521
 * This uses lots of hard coded values, but how often do we actually
522
 * add classes?
523
 */
524
isc_result_t
525
449k
dns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) {
526
449k
#define COMPARE(string, rdclass)                                      \
527
449k
  if (((sizeof(string) - 1) == source->length) &&               \
528
136k
      (strncasecmp(source->base, string, source->length) == 0)) \
529
136k
  {                                                             \
530
1.22k
    *classp = rdclass;                                    \
531
1.22k
    return (ISC_R_SUCCESS);                               \
532
1.22k
  }
533
534
449k
  switch (isc_ascii_tolower(source->base[0])) {
535
79.1k
  case 'a':
536
79.1k
    COMPARE("any", dns_rdataclass_any);
537
79.1k
    break;
538
2.91k
  case 'c':
539
    /*
540
     * RFC1035 says the mnemonic for the CHAOS class is CH,
541
     * but historical BIND practice is to call it CHAOS.
542
     * We will accept both forms, but only generate CH.
543
     */
544
2.91k
    COMPARE("ch", dns_rdataclass_chaos);
545
2.90k
    COMPARE("chaos", dns_rdataclass_chaos);
546
547
2.90k
    if (source->length > 5 &&
548
1.21k
        source->length < (5 + sizeof("65000")) &&
549
1.02k
        strncasecmp("class", source->base, 5) == 0)
550
232
    {
551
232
      char buf[sizeof("65000")];
552
232
      char *endp;
553
232
      unsigned int val;
554
555
      /*
556
       * source->base is not required to be NUL terminated.
557
       * Copy up to remaining bytes and NUL terminate.
558
       */
559
232
      snprintf(buf, sizeof(buf), "%.*s",
560
232
         (int)(source->length - 5), source->base + 5);
561
232
      val = strtoul(buf, &endp, 10);
562
232
      if (*endp == '\0' && val <= 0xffff) {
563
213
        *classp = (dns_rdataclass_t)val;
564
213
        return ISC_R_SUCCESS;
565
213
      }
566
232
    }
567
2.68k
    break;
568
2.68k
  case 'h':
569
1.47k
    COMPARE("hs", dns_rdataclass_hs);
570
1.47k
    COMPARE("hesiod", dns_rdataclass_hs);
571
1.47k
    break;
572
1.97k
  case 'i':
573
1.97k
    COMPARE("in", dns_rdataclass_in);
574
792
    break;
575
44.3k
  case 'n':
576
44.3k
    COMPARE("none", dns_rdataclass_none);
577
44.3k
    break;
578
1.90k
  case 'r':
579
1.90k
    COMPARE("reserved0", dns_rdataclass_reserved0);
580
1.90k
    break;
581
449k
  }
582
583
448k
#undef COMPARE
584
585
448k
  return DNS_R_UNKNOWN;
586
449k
}
587
588
isc_result_t
589
678k
dns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
590
678k
  switch (rdclass) {
591
9.15k
  case dns_rdataclass_any:
592
9.15k
    return str_totext("ANY", target);
593
12.2k
  case dns_rdataclass_chaos:
594
12.2k
    return str_totext("CH", target);
595
4.49k
  case dns_rdataclass_hs:
596
4.49k
    return str_totext("HS", target);
597
54.4k
  case dns_rdataclass_in:
598
54.4k
    return str_totext("IN", target);
599
7.16k
  case dns_rdataclass_none:
600
7.16k
    return str_totext("NONE", target);
601
68.9k
  case dns_rdataclass_reserved0:
602
68.9k
    return str_totext("RESERVED0", target);
603
522k
  default:
604
522k
    return dns_rdataclass_tounknowntext(rdclass, target);
605
678k
  }
606
678k
}
607
608
isc_result_t
609
522k
dns_rdataclass_tounknowntext(dns_rdataclass_t rdclass, isc_buffer_t *target) {
610
522k
  char buf[sizeof("CLASS65535")];
611
612
522k
  snprintf(buf, sizeof(buf), "CLASS%u", rdclass);
613
522k
  return str_totext(buf, target);
614
522k
}
615
616
void
617
dns_rdataclass_format(dns_rdataclass_t rdclass, char *array,
618
50
          unsigned int size) {
619
50
  isc_result_t result;
620
50
  isc_buffer_t buf;
621
622
50
  if (size == 0U) {
623
0
    return;
624
0
  }
625
626
50
  isc_buffer_init(&buf, array, size);
627
50
  result = dns_rdataclass_totext(rdclass, &buf);
628
  /*
629
   * Null terminate.
630
   */
631
50
  if (result == ISC_R_SUCCESS) {
632
50
    if (isc_buffer_availablelength(&buf) >= 1) {
633
50
      isc_buffer_putuint8(&buf, 0);
634
50
    } else {
635
0
      result = ISC_R_NOSPACE;
636
0
    }
637
50
  }
638
50
  if (result != ISC_R_SUCCESS) {
639
0
    strlcpy(array, "<unknown>", size);
640
0
  }
641
50
}
642
643
isc_result_t
644
0
dst_algorithm_fromtext(dst_algorithm_t *dstalgp, isc_textregion_t *source) {
645
0
  unsigned int value;
646
0
  RETERR(dns_mnemonic_fromtext(&value, source, dstalgorithms, 255));
647
0
  *dstalgp = value;
648
0
  return ISC_R_SUCCESS;
649
0
}
650
651
isc_result_t
652
0
dst_algorithm_totext(dst_algorithm_t alg, isc_buffer_t *target) {
653
0
  return dns_mnemonic_totext(alg, target, dstalgorithms);
654
0
}
655
656
void
657
0
dst_algorithm_format(dst_algorithm_t alg, char *cp, unsigned int size) {
658
0
  isc_buffer_t b;
659
0
  isc_region_t r;
660
0
  isc_result_t result;
661
662
0
  REQUIRE(cp != NULL && size > 0);
663
0
  isc_buffer_init(&b, cp, size - 1);
664
0
  result = dst_algorithm_totext(alg, &b);
665
0
  isc_buffer_usedregion(&b, &r);
666
0
  cp[r.length] = 0;
667
0
  if (result != ISC_R_SUCCESS) {
668
0
    r.base[0] = 0;
669
0
  }
670
0
}