a6_38.c revision 1.5
1/* $NetBSD: a6_38.c,v 1.5 2020/05/24 19:46:25 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 http://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/* RFC2874 */ 15 16#ifndef RDATA_IN_1_A6_28_C 17#define RDATA_IN_1_A6_28_C 18 19#include <isc/net.h> 20 21#define RRTYPE_A6_ATTRIBUTES (0) 22 23static inline isc_result_t 24fromtext_in_a6(ARGS_FROMTEXT) { 25 isc_token_t token; 26 unsigned char addr[16]; 27 unsigned char prefixlen; 28 unsigned char octets; 29 unsigned char mask; 30 dns_name_t name; 31 isc_buffer_t buffer; 32 bool ok; 33 34 REQUIRE(type == dns_rdatatype_a6); 35 REQUIRE(rdclass == dns_rdataclass_in); 36 37 UNUSED(type); 38 UNUSED(rdclass); 39 UNUSED(callbacks); 40 41 /* 42 * Prefix length. 43 */ 44 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 45 false)); 46 if (token.value.as_ulong > 128U) { 47 RETTOK(ISC_R_RANGE); 48 } 49 50 prefixlen = (unsigned char)token.value.as_ulong; 51 RETERR(mem_tobuffer(target, &prefixlen, 1)); 52 53 /* 54 * Suffix. 55 */ 56 if (prefixlen != 128) { 57 /* 58 * Prefix 0..127. 59 */ 60 octets = prefixlen / 8; 61 /* 62 * Octets 0..15. 63 */ 64 RETERR(isc_lex_getmastertoken(lexer, &token, 65 isc_tokentype_string, false)); 66 if (inet_pton(AF_INET6, DNS_AS_STR(token), addr) != 1) { 67 RETTOK(DNS_R_BADAAAA); 68 } 69 mask = 0xff >> (prefixlen % 8); 70 addr[octets] &= mask; 71 RETERR(mem_tobuffer(target, &addr[octets], 16 - octets)); 72 } 73 74 if (prefixlen == 0) { 75 return (ISC_R_SUCCESS); 76 } 77 78 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 79 false)); 80 dns_name_init(&name, NULL); 81 buffer_fromregion(&buffer, &token.value.as_region); 82 if (origin == NULL) { 83 origin = dns_rootname; 84 } 85 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 86 ok = true; 87 if ((options & DNS_RDATA_CHECKNAMES) != 0) { 88 ok = dns_name_ishostname(&name, false); 89 } 90 if (!ok && (options & DNS_RDATA_CHECKNAMESFAIL) != 0) { 91 RETTOK(DNS_R_BADNAME); 92 } 93 if (!ok && callbacks != NULL) { 94 warn_badname(&name, lexer, callbacks); 95 } 96 return (ISC_R_SUCCESS); 97} 98 99static inline isc_result_t 100totext_in_a6(ARGS_TOTEXT) { 101 isc_region_t sr, ar; 102 unsigned char addr[16]; 103 unsigned char prefixlen; 104 unsigned char octets; 105 unsigned char mask; 106 char buf[sizeof("128")]; 107 dns_name_t name; 108 dns_name_t prefix; 109 bool sub; 110 111 REQUIRE(rdata->type == dns_rdatatype_a6); 112 REQUIRE(rdata->rdclass == dns_rdataclass_in); 113 REQUIRE(rdata->length != 0); 114 115 dns_rdata_toregion(rdata, &sr); 116 prefixlen = sr.base[0]; 117 INSIST(prefixlen <= 128); 118 isc_region_consume(&sr, 1); 119 snprintf(buf, sizeof(buf), "%u", prefixlen); 120 RETERR(str_totext(buf, target)); 121 RETERR(str_totext(" ", target)); 122 123 if (prefixlen != 128) { 124 octets = prefixlen / 8; 125 memset(addr, 0, sizeof(addr)); 126 memmove(&addr[octets], sr.base, 16 - octets); 127 mask = 0xff >> (prefixlen % 8); 128 addr[octets] &= mask; 129 ar.base = addr; 130 ar.length = sizeof(addr); 131 RETERR(inet_totext(AF_INET6, &ar, target)); 132 isc_region_consume(&sr, 16 - octets); 133 } 134 135 if (prefixlen == 0) { 136 return (ISC_R_SUCCESS); 137 } 138 139 RETERR(str_totext(" ", target)); 140 dns_name_init(&name, NULL); 141 dns_name_init(&prefix, NULL); 142 dns_name_fromregion(&name, &sr); 143 sub = name_prefix(&name, tctx->origin, &prefix); 144 return (dns_name_totext(&prefix, sub, target)); 145} 146 147static inline isc_result_t 148fromwire_in_a6(ARGS_FROMWIRE) { 149 isc_region_t sr; 150 unsigned char prefixlen; 151 unsigned char octets; 152 unsigned char mask; 153 dns_name_t name; 154 155 REQUIRE(type == dns_rdatatype_a6); 156 REQUIRE(rdclass == dns_rdataclass_in); 157 158 UNUSED(type); 159 UNUSED(rdclass); 160 161 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 162 163 isc_buffer_activeregion(source, &sr); 164 /* 165 * Prefix length. 166 */ 167 if (sr.length < 1) { 168 return (ISC_R_UNEXPECTEDEND); 169 } 170 prefixlen = sr.base[0]; 171 if (prefixlen > 128) { 172 return (ISC_R_RANGE); 173 } 174 isc_region_consume(&sr, 1); 175 RETERR(mem_tobuffer(target, &prefixlen, 1)); 176 isc_buffer_forward(source, 1); 177 178 /* 179 * Suffix. 180 */ 181 if (prefixlen != 128) { 182 octets = 16 - prefixlen / 8; 183 if (sr.length < octets) { 184 return (ISC_R_UNEXPECTEDEND); 185 } 186 mask = 0xff >> (prefixlen % 8); 187 sr.base[0] &= mask; /* Ensure pad bits are zero. */ 188 RETERR(mem_tobuffer(target, sr.base, octets)); 189 isc_buffer_forward(source, octets); 190 } 191 192 if (prefixlen == 0) { 193 return (ISC_R_SUCCESS); 194 } 195 196 dns_name_init(&name, NULL); 197 return (dns_name_fromwire(&name, source, dctx, options, target)); 198} 199 200static inline isc_result_t 201towire_in_a6(ARGS_TOWIRE) { 202 isc_region_t sr; 203 dns_name_t name; 204 dns_offsets_t offsets; 205 unsigned char prefixlen; 206 unsigned char octets; 207 208 REQUIRE(rdata->type == dns_rdatatype_a6); 209 REQUIRE(rdata->rdclass == dns_rdataclass_in); 210 REQUIRE(rdata->length != 0); 211 212 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 213 dns_rdata_toregion(rdata, &sr); 214 prefixlen = sr.base[0]; 215 INSIST(prefixlen <= 128); 216 217 octets = 1 + 16 - prefixlen / 8; 218 RETERR(mem_tobuffer(target, sr.base, octets)); 219 isc_region_consume(&sr, octets); 220 221 if (prefixlen == 0) { 222 return (ISC_R_SUCCESS); 223 } 224 225 dns_name_init(&name, offsets); 226 dns_name_fromregion(&name, &sr); 227 return (dns_name_towire(&name, cctx, target)); 228} 229 230static inline int 231compare_in_a6(ARGS_COMPARE) { 232 int order; 233 unsigned char prefixlen1, prefixlen2; 234 unsigned char octets; 235 dns_name_t name1; 236 dns_name_t name2; 237 isc_region_t region1; 238 isc_region_t region2; 239 240 REQUIRE(rdata1->type == rdata2->type); 241 REQUIRE(rdata1->rdclass == rdata2->rdclass); 242 REQUIRE(rdata1->type == dns_rdatatype_a6); 243 REQUIRE(rdata1->rdclass == dns_rdataclass_in); 244 REQUIRE(rdata1->length != 0); 245 REQUIRE(rdata2->length != 0); 246 247 dns_rdata_toregion(rdata1, ®ion1); 248 dns_rdata_toregion(rdata2, ®ion2); 249 prefixlen1 = region1.base[0]; 250 prefixlen2 = region2.base[0]; 251 isc_region_consume(®ion1, 1); 252 isc_region_consume(®ion2, 1); 253 if (prefixlen1 < prefixlen2) { 254 return (-1); 255 } else if (prefixlen1 > prefixlen2) { 256 return (1); 257 } 258 /* 259 * Prefix lengths are equal. 260 */ 261 octets = 16 - prefixlen1 / 8; 262 263 if (octets > 0) { 264 order = memcmp(region1.base, region2.base, octets); 265 if (order < 0) { 266 return (-1); 267 } else if (order > 0) { 268 return (1); 269 } 270 /* 271 * Address suffixes are equal. 272 */ 273 if (prefixlen1 == 0) { 274 return (order); 275 } 276 isc_region_consume(®ion1, octets); 277 isc_region_consume(®ion2, octets); 278 } 279 280 dns_name_init(&name1, NULL); 281 dns_name_init(&name2, NULL); 282 dns_name_fromregion(&name1, ®ion1); 283 dns_name_fromregion(&name2, ®ion2); 284 return (dns_name_rdatacompare(&name1, &name2)); 285} 286 287static inline isc_result_t 288fromstruct_in_a6(ARGS_FROMSTRUCT) { 289 dns_rdata_in_a6_t *a6 = source; 290 isc_region_t region; 291 int octets; 292 uint8_t bits; 293 uint8_t first; 294 uint8_t mask; 295 296 REQUIRE(type == dns_rdatatype_a6); 297 REQUIRE(rdclass == dns_rdataclass_in); 298 REQUIRE(a6 != NULL); 299 REQUIRE(a6->common.rdtype == type); 300 REQUIRE(a6->common.rdclass == rdclass); 301 302 UNUSED(type); 303 UNUSED(rdclass); 304 305 if (a6->prefixlen > 128) { 306 return (ISC_R_RANGE); 307 } 308 309 RETERR(uint8_tobuffer(a6->prefixlen, target)); 310 311 /* Suffix */ 312 if (a6->prefixlen != 128) { 313 octets = 16 - a6->prefixlen / 8; 314 bits = a6->prefixlen % 8; 315 if (bits != 0) { 316 mask = 0xffU >> bits; 317 first = a6->in6_addr.s6_addr[16 - octets] & mask; 318 RETERR(uint8_tobuffer(first, target)); 319 octets--; 320 } 321 if (octets > 0) { 322 RETERR(mem_tobuffer(target, 323 a6->in6_addr.s6_addr + 16 - octets, 324 octets)); 325 } 326 } 327 328 if (a6->prefixlen == 0) { 329 return (ISC_R_SUCCESS); 330 } 331 dns_name_toregion(&a6->prefix, ®ion); 332 return (isc_buffer_copyregion(target, ®ion)); 333} 334 335static inline isc_result_t 336tostruct_in_a6(ARGS_TOSTRUCT) { 337 dns_rdata_in_a6_t *a6 = target; 338 unsigned char octets; 339 dns_name_t name; 340 isc_region_t r; 341 342 REQUIRE(rdata->type == dns_rdatatype_a6); 343 REQUIRE(rdata->rdclass == dns_rdataclass_in); 344 REQUIRE(a6 != NULL); 345 REQUIRE(rdata->length != 0); 346 347 a6->common.rdclass = rdata->rdclass; 348 a6->common.rdtype = rdata->type; 349 ISC_LINK_INIT(&a6->common, link); 350 351 dns_rdata_toregion(rdata, &r); 352 353 a6->prefixlen = uint8_fromregion(&r); 354 isc_region_consume(&r, 1); 355 memset(a6->in6_addr.s6_addr, 0, sizeof(a6->in6_addr.s6_addr)); 356 357 /* 358 * Suffix. 359 */ 360 if (a6->prefixlen != 128) { 361 octets = 16 - a6->prefixlen / 8; 362 INSIST(r.length >= octets); 363 memmove(a6->in6_addr.s6_addr + 16 - octets, r.base, octets); 364 isc_region_consume(&r, octets); 365 } 366 367 /* 368 * Prefix. 369 */ 370 dns_name_init(&a6->prefix, NULL); 371 if (a6->prefixlen != 0) { 372 dns_name_init(&name, NULL); 373 dns_name_fromregion(&name, &r); 374 RETERR(name_duporclone(&name, mctx, &a6->prefix)); 375 } 376 a6->mctx = mctx; 377 return (ISC_R_SUCCESS); 378} 379 380static inline void 381freestruct_in_a6(ARGS_FREESTRUCT) { 382 dns_rdata_in_a6_t *a6 = source; 383 384 REQUIRE(a6 != NULL); 385 REQUIRE(a6->common.rdclass == dns_rdataclass_in); 386 REQUIRE(a6->common.rdtype == dns_rdatatype_a6); 387 388 if (a6->mctx == NULL) { 389 return; 390 } 391 392 if (dns_name_dynamic(&a6->prefix)) { 393 dns_name_free(&a6->prefix, a6->mctx); 394 } 395 a6->mctx = NULL; 396} 397 398static inline isc_result_t 399additionaldata_in_a6(ARGS_ADDLDATA) { 400 REQUIRE(rdata->type == dns_rdatatype_a6); 401 REQUIRE(rdata->rdclass == dns_rdataclass_in); 402 403 UNUSED(rdata); 404 UNUSED(add); 405 UNUSED(arg); 406 407 return (ISC_R_SUCCESS); 408} 409 410static inline isc_result_t 411digest_in_a6(ARGS_DIGEST) { 412 isc_region_t r1, r2; 413 unsigned char prefixlen, octets; 414 isc_result_t result; 415 dns_name_t name; 416 417 REQUIRE(rdata->type == dns_rdatatype_a6); 418 REQUIRE(rdata->rdclass == dns_rdataclass_in); 419 420 dns_rdata_toregion(rdata, &r1); 421 r2 = r1; 422 prefixlen = r1.base[0]; 423 octets = 1 + 16 - prefixlen / 8; 424 425 r1.length = octets; 426 result = (digest)(arg, &r1); 427 if (result != ISC_R_SUCCESS) { 428 return (result); 429 } 430 if (prefixlen == 0) { 431 return (ISC_R_SUCCESS); 432 } 433 434 isc_region_consume(&r2, octets); 435 dns_name_init(&name, NULL); 436 dns_name_fromregion(&name, &r2); 437 return (dns_name_digest(&name, digest, arg)); 438} 439 440static inline bool 441checkowner_in_a6(ARGS_CHECKOWNER) { 442 REQUIRE(type == dns_rdatatype_a6); 443 REQUIRE(rdclass == dns_rdataclass_in); 444 445 UNUSED(type); 446 UNUSED(rdclass); 447 448 return (dns_name_ishostname(name, wildcard)); 449} 450 451static inline bool 452checknames_in_a6(ARGS_CHECKNAMES) { 453 isc_region_t region; 454 dns_name_t name; 455 unsigned int prefixlen; 456 457 REQUIRE(rdata->type == dns_rdatatype_a6); 458 REQUIRE(rdata->rdclass == dns_rdataclass_in); 459 460 UNUSED(owner); 461 462 dns_rdata_toregion(rdata, ®ion); 463 prefixlen = uint8_fromregion(®ion); 464 if (prefixlen == 0) { 465 return (true); 466 } 467 isc_region_consume(®ion, 1 + 16 - prefixlen / 8); 468 dns_name_init(&name, NULL); 469 dns_name_fromregion(&name, ®ion); 470 if (!dns_name_ishostname(&name, false)) { 471 if (bad != NULL) { 472 dns_name_clone(&name, bad); 473 } 474 return (false); 475 } 476 return (true); 477} 478 479static inline int 480casecompare_in_a6(ARGS_COMPARE) { 481 return (compare_in_a6(rdata1, rdata2)); 482} 483 484#endif /* RDATA_IN_1_A6_38_C */ 485