1135446Strhodes/* 2224092Sdougb * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3135446Strhodes * Copyright (C) 1999-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: nxt_30.c,v 1.65 2009/12/04 22:06:37 tbox Exp $ */ 19135446Strhodes 20135446Strhodes/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */ 21135446Strhodes 22170222Sdougb/* RFC2535 */ 23135446Strhodes 24135446Strhodes#ifndef RDATA_GENERIC_NXT_30_C 25135446Strhodes#define RDATA_GENERIC_NXT_30_C 26135446Strhodes 27135446Strhodes/* 28135446Strhodes * The attributes do not include DNS_RDATATYPEATTR_SINGLETON 29135446Strhodes * because we must be able to handle a parent/child NXT pair. 30135446Strhodes */ 31135446Strhodes#define RRTYPE_NXT_ATTRIBUTES (0) 32135446Strhodes 33135446Strhodesstatic inline isc_result_t 34135446Strhodesfromtext_nxt(ARGS_FROMTEXT) { 35135446Strhodes isc_token_t token; 36135446Strhodes dns_name_t name; 37135446Strhodes isc_buffer_t buffer; 38135446Strhodes char *e; 39135446Strhodes unsigned char bm[8*1024]; /* 64k bits */ 40135446Strhodes dns_rdatatype_t covered; 41135446Strhodes dns_rdatatype_t maxcovered = 0; 42135446Strhodes isc_boolean_t first = ISC_TRUE; 43135446Strhodes long n; 44135446Strhodes 45135446Strhodes REQUIRE(type == 30); 46135446Strhodes 47135446Strhodes UNUSED(type); 48135446Strhodes UNUSED(rdclass); 49135446Strhodes UNUSED(callbacks); 50135446Strhodes 51135446Strhodes /* 52135446Strhodes * Next domain. 53135446Strhodes */ 54135446Strhodes RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 55135446Strhodes ISC_FALSE)); 56135446Strhodes dns_name_init(&name, NULL); 57135446Strhodes buffer_fromregion(&buffer, &token.value.as_region); 58135446Strhodes origin = (origin != NULL) ? origin : dns_rootname; 59135446Strhodes RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 60135446Strhodes 61135446Strhodes memset(bm, 0, sizeof(bm)); 62135446Strhodes do { 63135446Strhodes RETERR(isc_lex_getmastertoken(lexer, &token, 64135446Strhodes isc_tokentype_string, ISC_TRUE)); 65135446Strhodes if (token.type != isc_tokentype_string) 66135446Strhodes break; 67135446Strhodes n = strtol(DNS_AS_STR(token), &e, 10); 68135446Strhodes if (e != DNS_AS_STR(token) && *e == '\0') { 69135446Strhodes covered = (dns_rdatatype_t)n; 70135446Strhodes } else if (dns_rdatatype_fromtext(&covered, 71135446Strhodes &token.value.as_textregion) == DNS_R_UNKNOWN) 72135446Strhodes RETTOK(DNS_R_UNKNOWN); 73135446Strhodes /* 74135446Strhodes * NXT is only specified for types 1..127. 75135446Strhodes */ 76135446Strhodes if (covered < 1 || covered > 127) 77135446Strhodes return (ISC_R_RANGE); 78135446Strhodes if (first || covered > maxcovered) 79135446Strhodes maxcovered = covered; 80135446Strhodes first = ISC_FALSE; 81135446Strhodes bm[covered/8] |= (0x80>>(covered%8)); 82135446Strhodes } while (1); 83135446Strhodes isc_lex_ungettoken(lexer, &token); 84135446Strhodes if (first) 85135446Strhodes return (ISC_R_SUCCESS); 86135446Strhodes n = (maxcovered + 8) / 8; 87135446Strhodes return (mem_tobuffer(target, bm, n)); 88135446Strhodes} 89135446Strhodes 90135446Strhodesstatic inline isc_result_t 91135446Strhodestotext_nxt(ARGS_TOTEXT) { 92135446Strhodes isc_region_t sr; 93135446Strhodes unsigned int i, j; 94135446Strhodes dns_name_t name; 95135446Strhodes dns_name_t prefix; 96135446Strhodes isc_boolean_t sub; 97135446Strhodes 98135446Strhodes REQUIRE(rdata->type == 30); 99135446Strhodes REQUIRE(rdata->length != 0); 100135446Strhodes 101135446Strhodes dns_name_init(&name, NULL); 102135446Strhodes dns_name_init(&prefix, NULL); 103135446Strhodes dns_rdata_toregion(rdata, &sr); 104135446Strhodes dns_name_fromregion(&name, &sr); 105135446Strhodes isc_region_consume(&sr, name_length(&name)); 106135446Strhodes sub = name_prefix(&name, tctx->origin, &prefix); 107135446Strhodes RETERR(dns_name_totext(&prefix, sub, target)); 108135446Strhodes 109135446Strhodes for (i = 0; i < sr.length; i++) { 110135446Strhodes if (sr.base[i] != 0) 111135446Strhodes for (j = 0; j < 8; j++) 112135446Strhodes if ((sr.base[i] & (0x80 >> j)) != 0) { 113135446Strhodes dns_rdatatype_t t = i * 8 + j; 114135446Strhodes RETERR(str_totext(" ", target)); 115135446Strhodes if (dns_rdatatype_isknown(t)) { 116135446Strhodes RETERR(dns_rdatatype_totext(t, 117135446Strhodes target)); 118135446Strhodes } else { 119135446Strhodes char buf[sizeof("65535")]; 120135446Strhodes sprintf(buf, "%u", t); 121135446Strhodes RETERR(str_totext(buf, 122135446Strhodes target)); 123135446Strhodes } 124135446Strhodes } 125135446Strhodes } 126135446Strhodes return (ISC_R_SUCCESS); 127135446Strhodes} 128135446Strhodes 129135446Strhodesstatic inline isc_result_t 130135446Strhodesfromwire_nxt(ARGS_FROMWIRE) { 131135446Strhodes isc_region_t sr; 132135446Strhodes dns_name_t name; 133135446Strhodes 134135446Strhodes REQUIRE(type == 30); 135135446Strhodes 136135446Strhodes UNUSED(type); 137135446Strhodes UNUSED(rdclass); 138135446Strhodes 139135446Strhodes dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 140135446Strhodes 141135446Strhodes dns_name_init(&name, NULL); 142135446Strhodes RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 143135446Strhodes 144135446Strhodes isc_buffer_activeregion(source, &sr); 145135446Strhodes if (sr.length > 0 && (sr.base[0] & 0x80) == 0 && 146135446Strhodes ((sr.length > 16) || sr.base[sr.length - 1] == 0)) 147135446Strhodes return (DNS_R_BADBITMAP); 148135446Strhodes RETERR(mem_tobuffer(target, sr.base, sr.length)); 149135446Strhodes isc_buffer_forward(source, sr.length); 150135446Strhodes return (ISC_R_SUCCESS); 151135446Strhodes} 152135446Strhodes 153135446Strhodesstatic inline isc_result_t 154135446Strhodestowire_nxt(ARGS_TOWIRE) { 155135446Strhodes isc_region_t sr; 156135446Strhodes dns_name_t name; 157135446Strhodes dns_offsets_t offsets; 158135446Strhodes 159135446Strhodes REQUIRE(rdata->type == 30); 160135446Strhodes REQUIRE(rdata->length != 0); 161135446Strhodes 162135446Strhodes dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 163135446Strhodes dns_name_init(&name, offsets); 164135446Strhodes dns_rdata_toregion(rdata, &sr); 165135446Strhodes dns_name_fromregion(&name, &sr); 166135446Strhodes isc_region_consume(&sr, name_length(&name)); 167135446Strhodes RETERR(dns_name_towire(&name, cctx, target)); 168135446Strhodes 169135446Strhodes return (mem_tobuffer(target, sr.base, sr.length)); 170135446Strhodes} 171135446Strhodes 172135446Strhodesstatic inline int 173135446Strhodescompare_nxt(ARGS_COMPARE) { 174135446Strhodes isc_region_t r1; 175135446Strhodes isc_region_t r2; 176135446Strhodes dns_name_t name1; 177135446Strhodes dns_name_t name2; 178135446Strhodes int order; 179135446Strhodes 180135446Strhodes REQUIRE(rdata1->type == rdata2->type); 181135446Strhodes REQUIRE(rdata1->rdclass == rdata2->rdclass); 182135446Strhodes REQUIRE(rdata1->type == 30); 183135446Strhodes REQUIRE(rdata1->length != 0); 184135446Strhodes REQUIRE(rdata2->length != 0); 185135446Strhodes 186135446Strhodes dns_name_init(&name1, NULL); 187135446Strhodes dns_name_init(&name2, NULL); 188135446Strhodes dns_rdata_toregion(rdata1, &r1); 189135446Strhodes dns_rdata_toregion(rdata2, &r2); 190135446Strhodes dns_name_fromregion(&name1, &r1); 191135446Strhodes dns_name_fromregion(&name2, &r2); 192135446Strhodes order = dns_name_rdatacompare(&name1, &name2); 193135446Strhodes if (order != 0) 194135446Strhodes return (order); 195135446Strhodes 196135446Strhodes return (isc_region_compare(&r1, &r2)); 197135446Strhodes} 198135446Strhodes 199135446Strhodesstatic inline isc_result_t 200135446Strhodesfromstruct_nxt(ARGS_FROMSTRUCT) { 201135446Strhodes dns_rdata_nxt_t *nxt = source; 202135446Strhodes isc_region_t region; 203135446Strhodes 204135446Strhodes REQUIRE(type == 30); 205135446Strhodes REQUIRE(source != NULL); 206135446Strhodes REQUIRE(nxt->common.rdtype == type); 207135446Strhodes REQUIRE(nxt->common.rdclass == rdclass); 208135446Strhodes REQUIRE(nxt->typebits != NULL || nxt->len == 0); 209135446Strhodes if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) { 210135446Strhodes REQUIRE(nxt->len <= 16); 211135446Strhodes REQUIRE(nxt->typebits[nxt->len - 1] != 0); 212135446Strhodes } 213135446Strhodes 214135446Strhodes UNUSED(type); 215135446Strhodes UNUSED(rdclass); 216135446Strhodes 217135446Strhodes dns_name_toregion(&nxt->next, ®ion); 218135446Strhodes RETERR(isc_buffer_copyregion(target, ®ion)); 219135446Strhodes 220135446Strhodes return (mem_tobuffer(target, nxt->typebits, nxt->len)); 221135446Strhodes} 222135446Strhodes 223135446Strhodesstatic inline isc_result_t 224135446Strhodestostruct_nxt(ARGS_TOSTRUCT) { 225135446Strhodes isc_region_t region; 226135446Strhodes dns_rdata_nxt_t *nxt = target; 227135446Strhodes dns_name_t name; 228135446Strhodes 229135446Strhodes REQUIRE(rdata->type == 30); 230135446Strhodes REQUIRE(target != NULL); 231135446Strhodes REQUIRE(rdata->length != 0); 232135446Strhodes 233135446Strhodes nxt->common.rdclass = rdata->rdclass; 234135446Strhodes nxt->common.rdtype = rdata->type; 235135446Strhodes ISC_LINK_INIT(&nxt->common, link); 236135446Strhodes 237135446Strhodes dns_name_init(&name, NULL); 238135446Strhodes dns_rdata_toregion(rdata, ®ion); 239135446Strhodes dns_name_fromregion(&name, ®ion); 240135446Strhodes isc_region_consume(®ion, name_length(&name)); 241135446Strhodes dns_name_init(&nxt->next, NULL); 242135446Strhodes RETERR(name_duporclone(&name, mctx, &nxt->next)); 243135446Strhodes 244135446Strhodes nxt->len = region.length; 245135446Strhodes nxt->typebits = mem_maybedup(mctx, region.base, region.length); 246135446Strhodes if (nxt->typebits == NULL) 247135446Strhodes goto cleanup; 248135446Strhodes 249135446Strhodes nxt->mctx = mctx; 250135446Strhodes return (ISC_R_SUCCESS); 251135446Strhodes 252135446Strhodes cleanup: 253135446Strhodes if (mctx != NULL) 254135446Strhodes dns_name_free(&nxt->next, mctx); 255135446Strhodes return (ISC_R_NOMEMORY); 256135446Strhodes} 257135446Strhodes 258135446Strhodesstatic inline void 259135446Strhodesfreestruct_nxt(ARGS_FREESTRUCT) { 260135446Strhodes dns_rdata_nxt_t *nxt = source; 261135446Strhodes 262135446Strhodes REQUIRE(source != NULL); 263135446Strhodes REQUIRE(nxt->common.rdtype == 30); 264135446Strhodes 265135446Strhodes if (nxt->mctx == NULL) 266135446Strhodes return; 267135446Strhodes 268135446Strhodes dns_name_free(&nxt->next, nxt->mctx); 269135446Strhodes if (nxt->typebits != NULL) 270135446Strhodes isc_mem_free(nxt->mctx, nxt->typebits); 271135446Strhodes nxt->mctx = NULL; 272135446Strhodes} 273135446Strhodes 274135446Strhodesstatic inline isc_result_t 275135446Strhodesadditionaldata_nxt(ARGS_ADDLDATA) { 276135446Strhodes REQUIRE(rdata->type == 30); 277135446Strhodes 278135446Strhodes UNUSED(rdata); 279135446Strhodes UNUSED(add); 280135446Strhodes UNUSED(arg); 281135446Strhodes 282135446Strhodes return (ISC_R_SUCCESS); 283135446Strhodes} 284135446Strhodes 285135446Strhodesstatic inline isc_result_t 286135446Strhodesdigest_nxt(ARGS_DIGEST) { 287135446Strhodes isc_region_t r; 288135446Strhodes dns_name_t name; 289135446Strhodes isc_result_t result; 290135446Strhodes 291135446Strhodes REQUIRE(rdata->type == 30); 292135446Strhodes 293135446Strhodes dns_rdata_toregion(rdata, &r); 294135446Strhodes dns_name_init(&name, NULL); 295135446Strhodes dns_name_fromregion(&name, &r); 296135446Strhodes result = dns_name_digest(&name, digest, arg); 297135446Strhodes if (result != ISC_R_SUCCESS) 298135446Strhodes return (result); 299135446Strhodes isc_region_consume(&r, name_length(&name)); 300135446Strhodes 301135446Strhodes return ((digest)(arg, &r)); 302135446Strhodes} 303135446Strhodes 304135446Strhodesstatic inline isc_boolean_t 305135446Strhodescheckowner_nxt(ARGS_CHECKOWNER) { 306135446Strhodes 307135446Strhodes REQUIRE(type == 30); 308135446Strhodes 309135446Strhodes UNUSED(name); 310135446Strhodes UNUSED(type); 311135446Strhodes UNUSED(rdclass); 312135446Strhodes UNUSED(wildcard); 313135446Strhodes 314135446Strhodes return (ISC_TRUE); 315135446Strhodes} 316135446Strhodes 317135446Strhodesstatic inline isc_boolean_t 318135446Strhodeschecknames_nxt(ARGS_CHECKNAMES) { 319135446Strhodes 320135446Strhodes REQUIRE(rdata->type == 30); 321135446Strhodes 322135446Strhodes UNUSED(rdata); 323135446Strhodes UNUSED(owner); 324135446Strhodes UNUSED(bad); 325135446Strhodes 326135446Strhodes return (ISC_TRUE); 327135446Strhodes} 328135446Strhodes 329224092Sdougbstatic inline int 330224092Sdougbcasecompare_nxt(ARGS_COMPARE) { 331224092Sdougb return (compare_nxt(rdata1, rdata2)); 332224092Sdougb} 333135446Strhodes#endif /* RDATA_GENERIC_NXT_30_C */ 334