1/* 2 * Copyright (C) 2004, 2005, 2007, 2009 Internet Systems Consortium, Inc. ("ISC") 3 * Copyright (C) 1999-2003 Internet Software Consortium. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 15 * PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18/* $Id: nxt_30.c,v 1.65 2009/12/04 22:06:37 tbox Exp $ */ 19 20/* reviewed: Wed Mar 15 18:21:15 PST 2000 by brister */ 21 22/* RFC2535 */ 23 24#ifndef RDATA_GENERIC_NXT_30_C 25#define RDATA_GENERIC_NXT_30_C 26 27/* 28 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON 29 * because we must be able to handle a parent/child NXT pair. 30 */ 31#define RRTYPE_NXT_ATTRIBUTES (0) 32 33static inline isc_result_t 34fromtext_nxt(ARGS_FROMTEXT) { 35 isc_token_t token; 36 dns_name_t name; 37 isc_buffer_t buffer; 38 char *e; 39 unsigned char bm[8*1024]; /* 64k bits */ 40 dns_rdatatype_t covered; 41 dns_rdatatype_t maxcovered = 0; 42 isc_boolean_t first = ISC_TRUE; 43 long n; 44 45 REQUIRE(type == 30); 46 47 UNUSED(type); 48 UNUSED(rdclass); 49 UNUSED(callbacks); 50 51 /* 52 * Next domain. 53 */ 54 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 55 ISC_FALSE)); 56 dns_name_init(&name, NULL); 57 buffer_fromregion(&buffer, &token.value.as_region); 58 origin = (origin != NULL) ? origin : dns_rootname; 59 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 60 61 memset(bm, 0, sizeof(bm)); 62 do { 63 RETERR(isc_lex_getmastertoken(lexer, &token, 64 isc_tokentype_string, ISC_TRUE)); 65 if (token.type != isc_tokentype_string) 66 break; 67 n = strtol(DNS_AS_STR(token), &e, 10); 68 if (e != DNS_AS_STR(token) && *e == '\0') { 69 covered = (dns_rdatatype_t)n; 70 } else if (dns_rdatatype_fromtext(&covered, 71 &token.value.as_textregion) == DNS_R_UNKNOWN) 72 RETTOK(DNS_R_UNKNOWN); 73 /* 74 * NXT is only specified for types 1..127. 75 */ 76 if (covered < 1 || covered > 127) 77 return (ISC_R_RANGE); 78 if (first || covered > maxcovered) 79 maxcovered = covered; 80 first = ISC_FALSE; 81 bm[covered/8] |= (0x80>>(covered%8)); 82 } while (1); 83 isc_lex_ungettoken(lexer, &token); 84 if (first) 85 return (ISC_R_SUCCESS); 86 n = (maxcovered + 8) / 8; 87 return (mem_tobuffer(target, bm, n)); 88} 89 90static inline isc_result_t 91totext_nxt(ARGS_TOTEXT) { 92 isc_region_t sr; 93 unsigned int i, j; 94 dns_name_t name; 95 dns_name_t prefix; 96 isc_boolean_t sub; 97 98 REQUIRE(rdata->type == 30); 99 REQUIRE(rdata->length != 0); 100 101 dns_name_init(&name, NULL); 102 dns_name_init(&prefix, NULL); 103 dns_rdata_toregion(rdata, &sr); 104 dns_name_fromregion(&name, &sr); 105 isc_region_consume(&sr, name_length(&name)); 106 sub = name_prefix(&name, tctx->origin, &prefix); 107 RETERR(dns_name_totext(&prefix, sub, target)); 108 109 for (i = 0; i < sr.length; i++) { 110 if (sr.base[i] != 0) 111 for (j = 0; j < 8; j++) 112 if ((sr.base[i] & (0x80 >> j)) != 0) { 113 dns_rdatatype_t t = i * 8 + j; 114 RETERR(str_totext(" ", target)); 115 if (dns_rdatatype_isknown(t)) { 116 RETERR(dns_rdatatype_totext(t, 117 target)); 118 } else { 119 char buf[sizeof("65535")]; 120 sprintf(buf, "%u", t); 121 RETERR(str_totext(buf, 122 target)); 123 } 124 } 125 } 126 return (ISC_R_SUCCESS); 127} 128 129static inline isc_result_t 130fromwire_nxt(ARGS_FROMWIRE) { 131 isc_region_t sr; 132 dns_name_t name; 133 134 REQUIRE(type == 30); 135 136 UNUSED(type); 137 UNUSED(rdclass); 138 139 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 140 141 dns_name_init(&name, NULL); 142 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 143 144 isc_buffer_activeregion(source, &sr); 145 if (sr.length > 0 && (sr.base[0] & 0x80) == 0 && 146 ((sr.length > 16) || sr.base[sr.length - 1] == 0)) 147 return (DNS_R_BADBITMAP); 148 RETERR(mem_tobuffer(target, sr.base, sr.length)); 149 isc_buffer_forward(source, sr.length); 150 return (ISC_R_SUCCESS); 151} 152 153static inline isc_result_t 154towire_nxt(ARGS_TOWIRE) { 155 isc_region_t sr; 156 dns_name_t name; 157 dns_offsets_t offsets; 158 159 REQUIRE(rdata->type == 30); 160 REQUIRE(rdata->length != 0); 161 162 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 163 dns_name_init(&name, offsets); 164 dns_rdata_toregion(rdata, &sr); 165 dns_name_fromregion(&name, &sr); 166 isc_region_consume(&sr, name_length(&name)); 167 RETERR(dns_name_towire(&name, cctx, target)); 168 169 return (mem_tobuffer(target, sr.base, sr.length)); 170} 171 172static inline int 173compare_nxt(ARGS_COMPARE) { 174 isc_region_t r1; 175 isc_region_t r2; 176 dns_name_t name1; 177 dns_name_t name2; 178 int order; 179 180 REQUIRE(rdata1->type == rdata2->type); 181 REQUIRE(rdata1->rdclass == rdata2->rdclass); 182 REQUIRE(rdata1->type == 30); 183 REQUIRE(rdata1->length != 0); 184 REQUIRE(rdata2->length != 0); 185 186 dns_name_init(&name1, NULL); 187 dns_name_init(&name2, NULL); 188 dns_rdata_toregion(rdata1, &r1); 189 dns_rdata_toregion(rdata2, &r2); 190 dns_name_fromregion(&name1, &r1); 191 dns_name_fromregion(&name2, &r2); 192 order = dns_name_rdatacompare(&name1, &name2); 193 if (order != 0) 194 return (order); 195 196 return (isc_region_compare(&r1, &r2)); 197} 198 199static inline isc_result_t 200fromstruct_nxt(ARGS_FROMSTRUCT) { 201 dns_rdata_nxt_t *nxt = source; 202 isc_region_t region; 203 204 REQUIRE(type == 30); 205 REQUIRE(source != NULL); 206 REQUIRE(nxt->common.rdtype == type); 207 REQUIRE(nxt->common.rdclass == rdclass); 208 REQUIRE(nxt->typebits != NULL || nxt->len == 0); 209 if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) { 210 REQUIRE(nxt->len <= 16); 211 REQUIRE(nxt->typebits[nxt->len - 1] != 0); 212 } 213 214 UNUSED(type); 215 UNUSED(rdclass); 216 217 dns_name_toregion(&nxt->next, ®ion); 218 RETERR(isc_buffer_copyregion(target, ®ion)); 219 220 return (mem_tobuffer(target, nxt->typebits, nxt->len)); 221} 222 223static inline isc_result_t 224tostruct_nxt(ARGS_TOSTRUCT) { 225 isc_region_t region; 226 dns_rdata_nxt_t *nxt = target; 227 dns_name_t name; 228 229 REQUIRE(rdata->type == 30); 230 REQUIRE(target != NULL); 231 REQUIRE(rdata->length != 0); 232 233 nxt->common.rdclass = rdata->rdclass; 234 nxt->common.rdtype = rdata->type; 235 ISC_LINK_INIT(&nxt->common, link); 236 237 dns_name_init(&name, NULL); 238 dns_rdata_toregion(rdata, ®ion); 239 dns_name_fromregion(&name, ®ion); 240 isc_region_consume(®ion, name_length(&name)); 241 dns_name_init(&nxt->next, NULL); 242 RETERR(name_duporclone(&name, mctx, &nxt->next)); 243 244 nxt->len = region.length; 245 nxt->typebits = mem_maybedup(mctx, region.base, region.length); 246 if (nxt->typebits == NULL) 247 goto cleanup; 248 249 nxt->mctx = mctx; 250 return (ISC_R_SUCCESS); 251 252 cleanup: 253 if (mctx != NULL) 254 dns_name_free(&nxt->next, mctx); 255 return (ISC_R_NOMEMORY); 256} 257 258static inline void 259freestruct_nxt(ARGS_FREESTRUCT) { 260 dns_rdata_nxt_t *nxt = source; 261 262 REQUIRE(source != NULL); 263 REQUIRE(nxt->common.rdtype == 30); 264 265 if (nxt->mctx == NULL) 266 return; 267 268 dns_name_free(&nxt->next, nxt->mctx); 269 if (nxt->typebits != NULL) 270 isc_mem_free(nxt->mctx, nxt->typebits); 271 nxt->mctx = NULL; 272} 273 274static inline isc_result_t 275additionaldata_nxt(ARGS_ADDLDATA) { 276 REQUIRE(rdata->type == 30); 277 278 UNUSED(rdata); 279 UNUSED(add); 280 UNUSED(arg); 281 282 return (ISC_R_SUCCESS); 283} 284 285static inline isc_result_t 286digest_nxt(ARGS_DIGEST) { 287 isc_region_t r; 288 dns_name_t name; 289 isc_result_t result; 290 291 REQUIRE(rdata->type == 30); 292 293 dns_rdata_toregion(rdata, &r); 294 dns_name_init(&name, NULL); 295 dns_name_fromregion(&name, &r); 296 result = dns_name_digest(&name, digest, arg); 297 if (result != ISC_R_SUCCESS) 298 return (result); 299 isc_region_consume(&r, name_length(&name)); 300 301 return ((digest)(arg, &r)); 302} 303 304static inline isc_boolean_t 305checkowner_nxt(ARGS_CHECKOWNER) { 306 307 REQUIRE(type == 30); 308 309 UNUSED(name); 310 UNUSED(type); 311 UNUSED(rdclass); 312 UNUSED(wildcard); 313 314 return (ISC_TRUE); 315} 316 317static inline isc_boolean_t 318checknames_nxt(ARGS_CHECKNAMES) { 319 320 REQUIRE(rdata->type == 30); 321 322 UNUSED(rdata); 323 UNUSED(owner); 324 UNUSED(bad); 325 326 return (ISC_TRUE); 327} 328 329static inline int 330casecompare_nxt(ARGS_COMPARE) { 331 return (compare_nxt(rdata1, rdata2)); 332} 333#endif /* RDATA_GENERIC_NXT_30_C */ 334