nxt_30.c revision 1.6
1/* $NetBSD: nxt_30.c,v 1.6 2021/02/19 16:42:17 christos Exp $ */ 2 3/* 4 * Copyright (C) Internet Systems Consortium, Inc. ("ISC") 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/* RFC2535 */ 15 16#ifndef RDATA_GENERIC_NXT_30_C 17#define RDATA_GENERIC_NXT_30_C 18 19/* 20 * The attributes do not include DNS_RDATATYPEATTR_SINGLETON 21 * because we must be able to handle a parent/child NXT pair. 22 */ 23#define RRTYPE_NXT_ATTRIBUTES (0) 24 25static inline isc_result_t 26fromtext_nxt(ARGS_FROMTEXT) { 27 isc_token_t token; 28 dns_name_t name; 29 isc_buffer_t buffer; 30 char *e; 31 unsigned char bm[8 * 1024]; /* 64k bits */ 32 dns_rdatatype_t covered; 33 dns_rdatatype_t maxcovered = 0; 34 bool first = true; 35 long n; 36 37 REQUIRE(type == dns_rdatatype_nxt); 38 39 UNUSED(type); 40 UNUSED(rdclass); 41 UNUSED(callbacks); 42 43 /* 44 * Next domain. 45 */ 46 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 47 false)); 48 dns_name_init(&name, NULL); 49 buffer_fromregion(&buffer, &token.value.as_region); 50 if (origin == NULL) { 51 origin = dns_rootname; 52 } 53 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 54 55 memset(bm, 0, sizeof(bm)); 56 do { 57 RETERR(isc_lex_getmastertoken(lexer, &token, 58 isc_tokentype_string, true)); 59 if (token.type != isc_tokentype_string) { 60 break; 61 } 62 n = strtol(DNS_AS_STR(token), &e, 10); 63 if (e != DNS_AS_STR(token) && *e == '\0') { 64 covered = (dns_rdatatype_t)n; 65 } else if (dns_rdatatype_fromtext(&covered, 66 &token.value.as_textregion) == 67 DNS_R_UNKNOWN) 68 { 69 RETTOK(DNS_R_UNKNOWN); 70 } 71 /* 72 * NXT is only specified for types 1..127. 73 */ 74 if (covered < 1 || covered > 127) { 75 return (ISC_R_RANGE); 76 } 77 if (first || covered > maxcovered) { 78 maxcovered = covered; 79 } 80 first = 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 } 87 n = (maxcovered + 8) / 8; 88 return (mem_tobuffer(target, bm, n)); 89} 90 91static inline isc_result_t 92totext_nxt(ARGS_TOTEXT) { 93 isc_region_t sr; 94 unsigned int i, j; 95 dns_name_t name; 96 dns_name_t prefix; 97 bool sub; 98 99 REQUIRE(rdata->type == dns_rdatatype_nxt); 100 REQUIRE(rdata->length != 0); 101 102 dns_name_init(&name, NULL); 103 dns_name_init(&prefix, NULL); 104 dns_rdata_toregion(rdata, &sr); 105 dns_name_fromregion(&name, &sr); 106 isc_region_consume(&sr, name_length(&name)); 107 sub = name_prefix(&name, tctx->origin, &prefix); 108 RETERR(dns_name_totext(&prefix, sub, target)); 109 110 for (i = 0; i < sr.length; i++) { 111 if (sr.base[i] != 0) { 112 for (j = 0; j < 8; j++) { 113 if ((sr.base[i] & (0x80 >> j)) != 0) { 114 { 115 dns_rdatatype_t t = i * 8 + j; 116 RETERR(str_totext(" ", target)); 117 if (dns_rdatatype_isknown(t)) { 118 RETERR(dns_rdatatype_totext( 119 t, target)); 120 } else { 121 char buf[sizeof("6553" 122 "5")]; 123 snprintf(buf, 124 sizeof(buf), 125 "%u", t); 126 RETERR(str_totext( 127 buf, target)); 128 } 129 } 130 } 131 } 132 } 133 } 134 return (ISC_R_SUCCESS); 135} 136 137static inline isc_result_t 138fromwire_nxt(ARGS_FROMWIRE) { 139 isc_region_t sr; 140 dns_name_t name; 141 142 REQUIRE(type == dns_rdatatype_nxt); 143 144 UNUSED(type); 145 UNUSED(rdclass); 146 147 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 148 149 dns_name_init(&name, NULL); 150 RETERR(dns_name_fromwire(&name, source, dctx, options, target)); 151 152 isc_buffer_activeregion(source, &sr); 153 if (sr.length > 0 && ((sr.base[0] & 0x80) != 0 || sr.length > 16 || 154 sr.base[sr.length - 1] == 0)) 155 { 156 return (DNS_R_BADBITMAP); 157 } 158 RETERR(mem_tobuffer(target, sr.base, sr.length)); 159 isc_buffer_forward(source, sr.length); 160 return (ISC_R_SUCCESS); 161} 162 163static inline isc_result_t 164towire_nxt(ARGS_TOWIRE) { 165 isc_region_t sr; 166 dns_name_t name; 167 dns_offsets_t offsets; 168 169 REQUIRE(rdata->type == dns_rdatatype_nxt); 170 REQUIRE(rdata->length != 0); 171 172 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 173 dns_name_init(&name, offsets); 174 dns_rdata_toregion(rdata, &sr); 175 dns_name_fromregion(&name, &sr); 176 isc_region_consume(&sr, name_length(&name)); 177 RETERR(dns_name_towire(&name, cctx, target)); 178 179 return (mem_tobuffer(target, sr.base, sr.length)); 180} 181 182static inline int 183compare_nxt(ARGS_COMPARE) { 184 isc_region_t r1; 185 isc_region_t r2; 186 dns_name_t name1; 187 dns_name_t name2; 188 int order; 189 190 REQUIRE(rdata1->type == rdata2->type); 191 REQUIRE(rdata1->rdclass == rdata2->rdclass); 192 REQUIRE(rdata1->type == dns_rdatatype_nxt); 193 REQUIRE(rdata1->length != 0); 194 REQUIRE(rdata2->length != 0); 195 196 dns_name_init(&name1, NULL); 197 dns_name_init(&name2, NULL); 198 dns_rdata_toregion(rdata1, &r1); 199 dns_rdata_toregion(rdata2, &r2); 200 dns_name_fromregion(&name1, &r1); 201 dns_name_fromregion(&name2, &r2); 202 order = dns_name_rdatacompare(&name1, &name2); 203 if (order != 0) { 204 return (order); 205 } 206 207 isc_region_consume(&r1, name_length(&name1)); 208 isc_region_consume(&r2, name_length(&name2)); 209 210 return (isc_region_compare(&r1, &r2)); 211} 212 213static inline isc_result_t 214fromstruct_nxt(ARGS_FROMSTRUCT) { 215 dns_rdata_nxt_t *nxt = source; 216 isc_region_t region; 217 218 REQUIRE(type == dns_rdatatype_nxt); 219 REQUIRE(nxt != NULL); 220 REQUIRE(nxt->common.rdtype == type); 221 REQUIRE(nxt->common.rdclass == rdclass); 222 REQUIRE(nxt->typebits != NULL || nxt->len == 0); 223 if (nxt->typebits != NULL && (nxt->typebits[0] & 0x80) == 0) { 224 REQUIRE(nxt->len <= 16); 225 REQUIRE(nxt->typebits[nxt->len - 1] != 0); 226 } 227 228 UNUSED(type); 229 UNUSED(rdclass); 230 231 dns_name_toregion(&nxt->next, ®ion); 232 RETERR(isc_buffer_copyregion(target, ®ion)); 233 234 return (mem_tobuffer(target, nxt->typebits, nxt->len)); 235} 236 237static inline isc_result_t 238tostruct_nxt(ARGS_TOSTRUCT) { 239 isc_region_t region; 240 dns_rdata_nxt_t *nxt = target; 241 dns_name_t name; 242 243 REQUIRE(rdata->type == dns_rdatatype_nxt); 244 REQUIRE(nxt != NULL); 245 REQUIRE(rdata->length != 0); 246 247 nxt->common.rdclass = rdata->rdclass; 248 nxt->common.rdtype = rdata->type; 249 ISC_LINK_INIT(&nxt->common, link); 250 251 dns_name_init(&name, NULL); 252 dns_rdata_toregion(rdata, ®ion); 253 dns_name_fromregion(&name, ®ion); 254 isc_region_consume(®ion, name_length(&name)); 255 dns_name_init(&nxt->next, NULL); 256 RETERR(name_duporclone(&name, mctx, &nxt->next)); 257 258 nxt->len = region.length; 259 nxt->typebits = mem_maybedup(mctx, region.base, region.length); 260 if (nxt->typebits == NULL) { 261 goto cleanup; 262 } 263 264 nxt->mctx = mctx; 265 return (ISC_R_SUCCESS); 266 267cleanup: 268 if (mctx != NULL) { 269 dns_name_free(&nxt->next, mctx); 270 } 271 return (ISC_R_NOMEMORY); 272} 273 274static inline void 275freestruct_nxt(ARGS_FREESTRUCT) { 276 dns_rdata_nxt_t *nxt = source; 277 278 REQUIRE(nxt != NULL); 279 REQUIRE(nxt->common.rdtype == dns_rdatatype_nxt); 280 281 if (nxt->mctx == NULL) { 282 return; 283 } 284 285 dns_name_free(&nxt->next, nxt->mctx); 286 if (nxt->typebits != NULL) { 287 isc_mem_free(nxt->mctx, nxt->typebits); 288 } 289 nxt->mctx = NULL; 290} 291 292static inline isc_result_t 293additionaldata_nxt(ARGS_ADDLDATA) { 294 REQUIRE(rdata->type == dns_rdatatype_nxt); 295 296 UNUSED(rdata); 297 UNUSED(add); 298 UNUSED(arg); 299 300 return (ISC_R_SUCCESS); 301} 302 303static inline isc_result_t 304digest_nxt(ARGS_DIGEST) { 305 isc_region_t r; 306 dns_name_t name; 307 isc_result_t result; 308 309 REQUIRE(rdata->type == dns_rdatatype_nxt); 310 311 dns_rdata_toregion(rdata, &r); 312 dns_name_init(&name, NULL); 313 dns_name_fromregion(&name, &r); 314 result = dns_name_digest(&name, digest, arg); 315 if (result != ISC_R_SUCCESS) { 316 return (result); 317 } 318 isc_region_consume(&r, name_length(&name)); 319 320 return ((digest)(arg, &r)); 321} 322 323static inline bool 324checkowner_nxt(ARGS_CHECKOWNER) { 325 REQUIRE(type == dns_rdatatype_nxt); 326 327 UNUSED(name); 328 UNUSED(type); 329 UNUSED(rdclass); 330 UNUSED(wildcard); 331 332 return (true); 333} 334 335static inline bool 336checknames_nxt(ARGS_CHECKNAMES) { 337 REQUIRE(rdata->type == dns_rdatatype_nxt); 338 339 UNUSED(rdata); 340 UNUSED(owner); 341 UNUSED(bad); 342 343 return (true); 344} 345 346static inline int 347casecompare_nxt(ARGS_COMPARE) { 348 return (compare_nxt(rdata1, rdata2)); 349} 350#endif /* RDATA_GENERIC_NXT_30_C */ 351