1135446Strhodes/* 2262706Serwin * Copyright (C) 2004-2014 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1998-2003 Internet Software Consortium. 4135446Strhodes * 5193149Sdougb * Permission to use, copy, modify, and/or distribute this software for any 6135446Strhodes * purpose with or without fee is hereby granted, provided that the above 7135446Strhodes * copyright notice and this permission notice appear in all copies. 8135446Strhodes * 9135446Strhodes * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10135446Strhodes * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11135446Strhodes * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12135446Strhodes * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13135446Strhodes * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14135446Strhodes * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15135446Strhodes * PERFORMANCE OF THIS SOFTWARE. 16135446Strhodes */ 17135446Strhodes 18234010Sdougb/* $Id$ */ 19135446Strhodes 20135446Strhodes#include <config.h> 21135446Strhodes#include <ctype.h> 22135446Strhodes 23135446Strhodes#include <isc/buffer.h> 24135446Strhodes#include <isc/parseint.h> 25135446Strhodes#include <isc/print.h> 26135446Strhodes#include <isc/region.h> 27135446Strhodes#include <isc/result.h> 28135446Strhodes#include <isc/stdio.h> 29135446Strhodes#include <isc/stdlib.h> 30135446Strhodes#include <isc/string.h> 31135446Strhodes#include <isc/types.h> 32135446Strhodes#include <isc/util.h> 33135446Strhodes 34135446Strhodes#include <dns/cert.h> 35135446Strhodes#include <dns/keyflags.h> 36135446Strhodes#include <dns/keyvalues.h> 37135446Strhodes#include <dns/rcode.h> 38135446Strhodes#include <dns/rdataclass.h> 39135446Strhodes#include <dns/result.h> 40135446Strhodes#include <dns/secalg.h> 41135446Strhodes#include <dns/secproto.h> 42135446Strhodes 43135446Strhodes#define RETERR(x) \ 44135446Strhodes do { \ 45135446Strhodes isc_result_t _r = (x); \ 46135446Strhodes if (_r != ISC_R_SUCCESS) \ 47135446Strhodes return (_r); \ 48135446Strhodes } while (0) 49135446Strhodes 50135446Strhodes#define NUMBERSIZE sizeof("037777777777") /* 2^32-1 octal + NUL */ 51135446Strhodes 52135446Strhodes#define RCODENAMES \ 53135446Strhodes /* standard rcodes */ \ 54135446Strhodes { dns_rcode_noerror, "NOERROR", 0}, \ 55135446Strhodes { dns_rcode_formerr, "FORMERR", 0}, \ 56135446Strhodes { dns_rcode_servfail, "SERVFAIL", 0}, \ 57135446Strhodes { dns_rcode_nxdomain, "NXDOMAIN", 0}, \ 58135446Strhodes { dns_rcode_notimp, "NOTIMP", 0}, \ 59135446Strhodes { dns_rcode_refused, "REFUSED", 0}, \ 60135446Strhodes { dns_rcode_yxdomain, "YXDOMAIN", 0}, \ 61135446Strhodes { dns_rcode_yxrrset, "YXRRSET", 0}, \ 62135446Strhodes { dns_rcode_nxrrset, "NXRRSET", 0}, \ 63135446Strhodes { dns_rcode_notauth, "NOTAUTH", 0}, \ 64135446Strhodes { dns_rcode_notzone, "NOTZONE", 0}, 65135446Strhodes 66135446Strhodes#define ERCODENAMES \ 67135446Strhodes /* extended rcodes */ \ 68135446Strhodes { dns_rcode_badvers, "BADVERS", 0}, \ 69193149Sdougb { 0, NULL, 0 } 70135446Strhodes 71135446Strhodes#define TSIGRCODENAMES \ 72135446Strhodes /* extended rcodes */ \ 73135446Strhodes { dns_tsigerror_badsig, "BADSIG", 0}, \ 74135446Strhodes { dns_tsigerror_badkey, "BADKEY", 0}, \ 75135446Strhodes { dns_tsigerror_badtime, "BADTIME", 0}, \ 76135446Strhodes { dns_tsigerror_badmode, "BADMODE", 0}, \ 77135446Strhodes { dns_tsigerror_badname, "BADNAME", 0}, \ 78135446Strhodes { dns_tsigerror_badalg, "BADALG", 0}, \ 79170222Sdougb { dns_tsigerror_badtrunc, "BADTRUNC", 0}, \ 80135446Strhodes { 0, NULL, 0 } 81135446Strhodes 82224092Sdougb/* RFC4398 section 2.1 */ 83135446Strhodes 84135446Strhodes#define CERTNAMES \ 85135446Strhodes { 1, "PKIX", 0}, \ 86135446Strhodes { 2, "SPKI", 0}, \ 87135446Strhodes { 3, "PGP", 0}, \ 88224092Sdougb { 4, "IPKIX", 0}, \ 89224092Sdougb { 5, "ISPKI", 0}, \ 90224092Sdougb { 6, "IPGP", 0}, \ 91224092Sdougb { 7, "ACPKIX", 0}, \ 92224092Sdougb { 8, "IACPKIX", 0}, \ 93135446Strhodes { 253, "URI", 0}, \ 94135446Strhodes { 254, "OID", 0}, \ 95135446Strhodes { 0, NULL, 0} 96135446Strhodes 97135446Strhodes/* RFC2535 section 7, RFC3110 */ 98135446Strhodes 99135446Strhodes#define SECALGNAMES \ 100135446Strhodes { DNS_KEYALG_RSAMD5, "RSAMD5", 0 }, \ 101135446Strhodes { DNS_KEYALG_RSAMD5, "RSA", 0 }, \ 102135446Strhodes { DNS_KEYALG_DH, "DH", 0 }, \ 103135446Strhodes { DNS_KEYALG_DSA, "DSA", 0 }, \ 104193149Sdougb { DNS_KEYALG_NSEC3DSA, "NSEC3DSA", 0 }, \ 105135446Strhodes { DNS_KEYALG_ECC, "ECC", 0 }, \ 106135446Strhodes { DNS_KEYALG_RSASHA1, "RSASHA1", 0 }, \ 107193149Sdougb { DNS_KEYALG_NSEC3RSASHA1, "NSEC3RSASHA1", 0 }, \ 108204619Sdougb { DNS_KEYALG_RSASHA256, "RSASHA256", 0 }, \ 109204619Sdougb { DNS_KEYALG_RSASHA512, "RSASHA512", 0 }, \ 110224092Sdougb { DNS_KEYALG_ECCGOST, "ECCGOST", 0 }, \ 111245163Serwin { DNS_KEYALG_ECDSA256, "ECDSAP256SHA256", 0 }, \ 112245163Serwin { DNS_KEYALG_ECDSA384, "ECDSAP384SHA384", 0 }, \ 113135446Strhodes { DNS_KEYALG_INDIRECT, "INDIRECT", 0 }, \ 114135446Strhodes { DNS_KEYALG_PRIVATEDNS, "PRIVATEDNS", 0 }, \ 115135446Strhodes { DNS_KEYALG_PRIVATEOID, "PRIVATEOID", 0 }, \ 116135446Strhodes { 0, NULL, 0} 117135446Strhodes 118135446Strhodes/* RFC2535 section 7.1 */ 119135446Strhodes 120135446Strhodes#define SECPROTONAMES \ 121135446Strhodes { 0, "NONE", 0 }, \ 122135446Strhodes { 1, "TLS", 0 }, \ 123135446Strhodes { 2, "EMAIL", 0 }, \ 124135446Strhodes { 3, "DNSSEC", 0 }, \ 125135446Strhodes { 4, "IPSEC", 0 }, \ 126135446Strhodes { 255, "ALL", 0 }, \ 127135446Strhodes { 0, NULL, 0} 128135446Strhodes 129193149Sdougb#define HASHALGNAMES \ 130193149Sdougb { 1, "SHA-1", 0 }, \ 131193149Sdougb { 0, NULL, 0 } 132193149Sdougb 133135446Strhodesstruct tbl { 134135446Strhodes unsigned int value; 135135446Strhodes const char *name; 136135446Strhodes int flags; 137135446Strhodes}; 138135446Strhodes 139135446Strhodesstatic struct tbl rcodes[] = { RCODENAMES ERCODENAMES }; 140135446Strhodesstatic struct tbl tsigrcodes[] = { RCODENAMES TSIGRCODENAMES }; 141135446Strhodesstatic struct tbl certs[] = { CERTNAMES }; 142135446Strhodesstatic struct tbl secalgs[] = { SECALGNAMES }; 143135446Strhodesstatic struct tbl secprotos[] = { SECPROTONAMES }; 144193149Sdougbstatic struct tbl hashalgs[] = { HASHALGNAMES }; 145135446Strhodes 146135446Strhodesstatic struct keyflag { 147135446Strhodes const char *name; 148135446Strhodes unsigned int value; 149135446Strhodes unsigned int mask; 150135446Strhodes} keyflags[] = { 151135446Strhodes { "NOCONF", 0x4000, 0xC000 }, 152135446Strhodes { "NOAUTH", 0x8000, 0xC000 }, 153135446Strhodes { "NOKEY", 0xC000, 0xC000 }, 154135446Strhodes { "FLAG2", 0x2000, 0x2000 }, 155135446Strhodes { "EXTEND", 0x1000, 0x1000 }, 156135446Strhodes { "FLAG4", 0x0800, 0x0800 }, 157135446Strhodes { "FLAG5", 0x0400, 0x0400 }, 158135446Strhodes { "USER", 0x0000, 0x0300 }, 159135446Strhodes { "ZONE", 0x0100, 0x0300 }, 160135446Strhodes { "HOST", 0x0200, 0x0300 }, 161135446Strhodes { "NTYP3", 0x0300, 0x0300 }, 162135446Strhodes { "FLAG8", 0x0080, 0x0080 }, 163135446Strhodes { "FLAG9", 0x0040, 0x0040 }, 164135446Strhodes { "FLAG10", 0x0020, 0x0020 }, 165135446Strhodes { "FLAG11", 0x0010, 0x0010 }, 166135446Strhodes { "SIG0", 0x0000, 0x000F }, 167135446Strhodes { "SIG1", 0x0001, 0x000F }, 168135446Strhodes { "SIG2", 0x0002, 0x000F }, 169135446Strhodes { "SIG3", 0x0003, 0x000F }, 170135446Strhodes { "SIG4", 0x0004, 0x000F }, 171135446Strhodes { "SIG5", 0x0005, 0x000F }, 172135446Strhodes { "SIG6", 0x0006, 0x000F }, 173135446Strhodes { "SIG7", 0x0007, 0x000F }, 174135446Strhodes { "SIG8", 0x0008, 0x000F }, 175135446Strhodes { "SIG9", 0x0009, 0x000F }, 176135446Strhodes { "SIG10", 0x000A, 0x000F }, 177135446Strhodes { "SIG11", 0x000B, 0x000F }, 178135446Strhodes { "SIG12", 0x000C, 0x000F }, 179135446Strhodes { "SIG13", 0x000D, 0x000F }, 180135446Strhodes { "SIG14", 0x000E, 0x000F }, 181135446Strhodes { "SIG15", 0x000F, 0x000F }, 182135446Strhodes { "KSK", DNS_KEYFLAG_KSK, DNS_KEYFLAG_KSK }, 183135446Strhodes { NULL, 0, 0 } 184135446Strhodes}; 185135446Strhodes 186135446Strhodesstatic isc_result_t 187135446Strhodesstr_totext(const char *source, isc_buffer_t *target) { 188135446Strhodes unsigned int l; 189135446Strhodes isc_region_t region; 190135446Strhodes 191135446Strhodes isc_buffer_availableregion(target, ®ion); 192135446Strhodes l = strlen(source); 193135446Strhodes 194135446Strhodes if (l > region.length) 195135446Strhodes return (ISC_R_NOSPACE); 196135446Strhodes 197262706Serwin memmove(region.base, source, l); 198135446Strhodes isc_buffer_add(target, l); 199135446Strhodes return (ISC_R_SUCCESS); 200135446Strhodes} 201135446Strhodes 202135446Strhodesstatic isc_result_t 203135446Strhodesmaybe_numeric(unsigned int *valuep, isc_textregion_t *source, 204135446Strhodes unsigned int max, isc_boolean_t hex_allowed) 205135446Strhodes{ 206135446Strhodes isc_result_t result; 207135446Strhodes isc_uint32_t n; 208135446Strhodes char buffer[NUMBERSIZE]; 209135446Strhodes 210135446Strhodes if (! isdigit(source->base[0] & 0xff) || 211135446Strhodes source->length > NUMBERSIZE - 1) 212135446Strhodes return (ISC_R_BADNUMBER); 213135446Strhodes 214135446Strhodes /* 215135446Strhodes * We have a potential number. Try to parse it with 216135446Strhodes * isc_parse_uint32(). isc_parse_uint32() requires 217135446Strhodes * null termination, so we must make a copy. 218135446Strhodes */ 219135446Strhodes strncpy(buffer, source->base, NUMBERSIZE); 220135446Strhodes INSIST(buffer[source->length] == '\0'); 221135446Strhodes 222135446Strhodes result = isc_parse_uint32(&n, buffer, 10); 223135446Strhodes if (result == ISC_R_BADNUMBER && hex_allowed) 224135446Strhodes result = isc_parse_uint32(&n, buffer, 16); 225135446Strhodes if (result != ISC_R_SUCCESS) 226135446Strhodes return (result); 227135446Strhodes if (n > max) 228135446Strhodes return (ISC_R_RANGE); 229135446Strhodes *valuep = n; 230135446Strhodes return (ISC_R_SUCCESS); 231135446Strhodes} 232135446Strhodes 233135446Strhodesstatic isc_result_t 234135446Strhodesdns_mnemonic_fromtext(unsigned int *valuep, isc_textregion_t *source, 235135446Strhodes struct tbl *table, unsigned int max) 236135446Strhodes{ 237135446Strhodes isc_result_t result; 238135446Strhodes int i; 239135446Strhodes 240135446Strhodes result = maybe_numeric(valuep, source, max, ISC_FALSE); 241135446Strhodes if (result != ISC_R_BADNUMBER) 242135446Strhodes return (result); 243135446Strhodes 244135446Strhodes for (i = 0; table[i].name != NULL; i++) { 245135446Strhodes unsigned int n; 246135446Strhodes n = strlen(table[i].name); 247135446Strhodes if (n == source->length && 248135446Strhodes strncasecmp(source->base, table[i].name, n) == 0) { 249135446Strhodes *valuep = table[i].value; 250135446Strhodes return (ISC_R_SUCCESS); 251135446Strhodes } 252135446Strhodes } 253135446Strhodes return (DNS_R_UNKNOWN); 254135446Strhodes} 255135446Strhodes 256135446Strhodesstatic isc_result_t 257135446Strhodesdns_mnemonic_totext(unsigned int value, isc_buffer_t *target, 258193149Sdougb struct tbl *table) 259135446Strhodes{ 260135446Strhodes int i = 0; 261135446Strhodes char buf[sizeof("4294967296")]; 262135446Strhodes while (table[i].name != NULL) { 263135446Strhodes if (table[i].value == value) { 264135446Strhodes return (str_totext(table[i].name, target)); 265135446Strhodes } 266135446Strhodes i++; 267135446Strhodes } 268135446Strhodes snprintf(buf, sizeof(buf), "%u", value); 269135446Strhodes return (str_totext(buf, target)); 270135446Strhodes} 271135446Strhodes 272135446Strhodesisc_result_t 273135446Strhodesdns_rcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) { 274135446Strhodes unsigned int value; 275135446Strhodes RETERR(dns_mnemonic_fromtext(&value, source, rcodes, 0xffff)); 276135446Strhodes *rcodep = value; 277135446Strhodes return (ISC_R_SUCCESS); 278135446Strhodes} 279135446Strhodes 280135446Strhodesisc_result_t 281135446Strhodesdns_rcode_totext(dns_rcode_t rcode, isc_buffer_t *target) { 282135446Strhodes return (dns_mnemonic_totext(rcode, target, rcodes)); 283135446Strhodes} 284135446Strhodes 285135446Strhodesisc_result_t 286135446Strhodesdns_tsigrcode_fromtext(dns_rcode_t *rcodep, isc_textregion_t *source) { 287135446Strhodes unsigned int value; 288135446Strhodes RETERR(dns_mnemonic_fromtext(&value, source, tsigrcodes, 0xffff)); 289135446Strhodes *rcodep = value; 290135446Strhodes return (ISC_R_SUCCESS); 291193149Sdougb} 292135446Strhodes 293135446Strhodesisc_result_t 294135446Strhodesdns_tsigrcode_totext(dns_rcode_t rcode, isc_buffer_t *target) { 295135446Strhodes return (dns_mnemonic_totext(rcode, target, tsigrcodes)); 296135446Strhodes} 297135446Strhodes 298135446Strhodesisc_result_t 299135446Strhodesdns_cert_fromtext(dns_cert_t *certp, isc_textregion_t *source) { 300135446Strhodes unsigned int value; 301135446Strhodes RETERR(dns_mnemonic_fromtext(&value, source, certs, 0xffff)); 302135446Strhodes *certp = value; 303135446Strhodes return (ISC_R_SUCCESS); 304135446Strhodes} 305135446Strhodes 306135446Strhodesisc_result_t 307135446Strhodesdns_cert_totext(dns_cert_t cert, isc_buffer_t *target) { 308135446Strhodes return (dns_mnemonic_totext(cert, target, certs)); 309135446Strhodes} 310135446Strhodes 311135446Strhodesisc_result_t 312135446Strhodesdns_secalg_fromtext(dns_secalg_t *secalgp, isc_textregion_t *source) { 313135446Strhodes unsigned int value; 314135446Strhodes RETERR(dns_mnemonic_fromtext(&value, source, secalgs, 0xff)); 315135446Strhodes *secalgp = value; 316135446Strhodes return (ISC_R_SUCCESS); 317135446Strhodes} 318135446Strhodes 319135446Strhodesisc_result_t 320135446Strhodesdns_secalg_totext(dns_secalg_t secalg, isc_buffer_t *target) { 321135446Strhodes return (dns_mnemonic_totext(secalg, target, secalgs)); 322135446Strhodes} 323135446Strhodes 324224092Sdougbvoid 325224092Sdougbdns_secalg_format(dns_secalg_t alg, char *cp, unsigned int size) { 326224092Sdougb isc_buffer_t b; 327224092Sdougb isc_region_t r; 328224092Sdougb isc_result_t result; 329224092Sdougb 330224092Sdougb REQUIRE(cp != NULL && size > 0); 331224092Sdougb isc_buffer_init(&b, cp, size - 1); 332224092Sdougb result = dns_secalg_totext(alg, &b); 333224092Sdougb isc_buffer_usedregion(&b, &r); 334224092Sdougb r.base[r.length] = 0; 335224092Sdougb if (result != ISC_R_SUCCESS) 336224092Sdougb r.base[0] = 0; 337224092Sdougb} 338224092Sdougb 339135446Strhodesisc_result_t 340135446Strhodesdns_secproto_fromtext(dns_secproto_t *secprotop, isc_textregion_t *source) { 341135446Strhodes unsigned int value; 342135446Strhodes RETERR(dns_mnemonic_fromtext(&value, source, secprotos, 0xff)); 343135446Strhodes *secprotop = value; 344135446Strhodes return (ISC_R_SUCCESS); 345135446Strhodes} 346135446Strhodes 347135446Strhodesisc_result_t 348135446Strhodesdns_secproto_totext(dns_secproto_t secproto, isc_buffer_t *target) { 349135446Strhodes return (dns_mnemonic_totext(secproto, target, secprotos)); 350135446Strhodes} 351135446Strhodes 352135446Strhodesisc_result_t 353193149Sdougbdns_hashalg_fromtext(unsigned char *hashalg, isc_textregion_t *source) { 354193149Sdougb unsigned int value; 355193149Sdougb RETERR(dns_mnemonic_fromtext(&value, source, hashalgs, 0xff)); 356193149Sdougb *hashalg = value; 357193149Sdougb return (ISC_R_SUCCESS); 358193149Sdougb} 359193149Sdougb 360193149Sdougbisc_result_t 361135446Strhodesdns_keyflags_fromtext(dns_keyflags_t *flagsp, isc_textregion_t *source) 362135446Strhodes{ 363135446Strhodes isc_result_t result; 364135446Strhodes char *text, *end; 365135446Strhodes unsigned int value, mask; 366135446Strhodes 367135446Strhodes result = maybe_numeric(&value, source, 0xffff, ISC_TRUE); 368135446Strhodes if (result == ISC_R_SUCCESS) { 369135446Strhodes *flagsp = value; 370135446Strhodes return (ISC_R_SUCCESS); 371135446Strhodes } 372135446Strhodes if (result != ISC_R_BADNUMBER) 373135446Strhodes return (result); 374135446Strhodes 375135446Strhodes text = source->base; 376135446Strhodes end = source->base + source->length; 377135446Strhodes value = mask = 0; 378135446Strhodes 379135446Strhodes while (text < end) { 380135446Strhodes struct keyflag *p; 381135446Strhodes unsigned int len; 382135446Strhodes char *delim = memchr(text, '|', end - text); 383135446Strhodes if (delim != NULL) 384262706Serwin len = (unsigned int)(delim - text); 385135446Strhodes else 386262706Serwin len = (unsigned int)(end - text); 387135446Strhodes for (p = keyflags; p->name != NULL; p++) { 388135446Strhodes if (strncasecmp(p->name, text, len) == 0) 389135446Strhodes break; 390135446Strhodes } 391135446Strhodes if (p->name == NULL) 392135446Strhodes return (DNS_R_UNKNOWNFLAG); 393135446Strhodes value |= p->value; 394135446Strhodes#ifdef notyet 395135446Strhodes if ((mask & p->mask) != 0) 396135446Strhodes warn("overlapping key flags"); 397135446Strhodes#endif 398135446Strhodes mask |= p->mask; 399135446Strhodes text += len; 400135446Strhodes if (delim != NULL) 401135446Strhodes text++; /* Skip "|" */ 402135446Strhodes } 403135446Strhodes *flagsp = value; 404135446Strhodes return (ISC_R_SUCCESS); 405135446Strhodes} 406135446Strhodes 407135446Strhodes/* 408135446Strhodes * This uses lots of hard coded values, but how often do we actually 409135446Strhodes * add classes? 410135446Strhodes */ 411135446Strhodesisc_result_t 412135446Strhodesdns_rdataclass_fromtext(dns_rdataclass_t *classp, isc_textregion_t *source) { 413135446Strhodes#define COMPARE(string, rdclass) \ 414135446Strhodes if (((sizeof(string) - 1) == source->length) \ 415135446Strhodes && (strncasecmp(source->base, string, source->length) == 0)) { \ 416135446Strhodes *classp = rdclass; \ 417135446Strhodes return (ISC_R_SUCCESS); \ 418135446Strhodes } 419135446Strhodes 420135446Strhodes switch (tolower((unsigned char)source->base[0])) { 421135446Strhodes case 'a': 422135446Strhodes COMPARE("any", dns_rdataclass_any); 423135446Strhodes break; 424135446Strhodes case 'c': 425135446Strhodes /* 426135446Strhodes * RFC1035 says the mnemonic for the CHAOS class is CH, 427135446Strhodes * but historical BIND practice is to call it CHAOS. 428135446Strhodes * We will accept both forms, but only generate CH. 429135446Strhodes */ 430135446Strhodes COMPARE("ch", dns_rdataclass_chaos); 431135446Strhodes COMPARE("chaos", dns_rdataclass_chaos); 432135446Strhodes 433135446Strhodes if (source->length > 5 && 434135446Strhodes source->length < (5 + sizeof("65000")) && 435135446Strhodes strncasecmp("class", source->base, 5) == 0) { 436135446Strhodes char buf[sizeof("65000")]; 437135446Strhodes char *endp; 438135446Strhodes unsigned int val; 439135446Strhodes 440135446Strhodes strncpy(buf, source->base + 5, source->length - 5); 441135446Strhodes buf[source->length - 5] = '\0'; 442135446Strhodes val = strtoul(buf, &endp, 10); 443135446Strhodes if (*endp == '\0' && val <= 0xffff) { 444135446Strhodes *classp = (dns_rdataclass_t)val; 445135446Strhodes return (ISC_R_SUCCESS); 446135446Strhodes } 447135446Strhodes } 448135446Strhodes break; 449135446Strhodes case 'h': 450135446Strhodes COMPARE("hs", dns_rdataclass_hs); 451135446Strhodes COMPARE("hesiod", dns_rdataclass_hs); 452135446Strhodes break; 453135446Strhodes case 'i': 454135446Strhodes COMPARE("in", dns_rdataclass_in); 455135446Strhodes break; 456135446Strhodes case 'n': 457135446Strhodes COMPARE("none", dns_rdataclass_none); 458135446Strhodes break; 459135446Strhodes case 'r': 460135446Strhodes COMPARE("reserved0", dns_rdataclass_reserved0); 461135446Strhodes break; 462135446Strhodes } 463135446Strhodes 464135446Strhodes#undef COMPARE 465135446Strhodes 466135446Strhodes return (DNS_R_UNKNOWN); 467135446Strhodes} 468135446Strhodes 469135446Strhodesisc_result_t 470135446Strhodesdns_rdataclass_totext(dns_rdataclass_t rdclass, isc_buffer_t *target) { 471135446Strhodes char buf[sizeof("CLASS65535")]; 472135446Strhodes 473135446Strhodes switch (rdclass) { 474135446Strhodes case dns_rdataclass_any: 475135446Strhodes return (str_totext("ANY", target)); 476135446Strhodes case dns_rdataclass_chaos: 477135446Strhodes return (str_totext("CH", target)); 478135446Strhodes case dns_rdataclass_hs: 479135446Strhodes return (str_totext("HS", target)); 480135446Strhodes case dns_rdataclass_in: 481135446Strhodes return (str_totext("IN", target)); 482135446Strhodes case dns_rdataclass_none: 483135446Strhodes return (str_totext("NONE", target)); 484135446Strhodes case dns_rdataclass_reserved0: 485135446Strhodes return (str_totext("RESERVED0", target)); 486135446Strhodes default: 487135446Strhodes snprintf(buf, sizeof(buf), "CLASS%u", rdclass); 488135446Strhodes return (str_totext(buf, target)); 489135446Strhodes } 490135446Strhodes} 491135446Strhodes 492135446Strhodesvoid 493135446Strhodesdns_rdataclass_format(dns_rdataclass_t rdclass, 494135446Strhodes char *array, unsigned int size) 495135446Strhodes{ 496135446Strhodes isc_result_t result; 497135446Strhodes isc_buffer_t buf; 498135446Strhodes 499225361Sdougb if (size == 0U) 500225361Sdougb return; 501225361Sdougb 502135446Strhodes isc_buffer_init(&buf, array, size); 503135446Strhodes result = dns_rdataclass_totext(rdclass, &buf); 504135446Strhodes /* 505135446Strhodes * Null terminate. 506135446Strhodes */ 507135446Strhodes if (result == ISC_R_SUCCESS) { 508135446Strhodes if (isc_buffer_availablelength(&buf) >= 1) 509135446Strhodes isc_buffer_putuint8(&buf, 0); 510135446Strhodes else 511135446Strhodes result = ISC_R_NOSPACE; 512135446Strhodes } 513225361Sdougb if (result != ISC_R_SUCCESS) 514225361Sdougb strlcpy(array, "<unknown>", size); 515135446Strhodes} 516