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