1 /* $NetBSD: caa_257.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 #ifndef GENERIC_CAA_257_C 15 #define GENERIC_CAA_257_C 1 16 17 #define RRTYPE_CAA_ATTRIBUTES (0) 18 19 static unsigned char const alphanumeric[256] = { 20 /* 0x00-0x0f */ 0, 21 0, 22 0, 23 0, 24 0, 25 0, 26 0, 27 0, 28 0, 29 0, 30 0, 31 0, 32 0, 33 0, 34 0, 35 0, 36 /* 0x10-0x1f */ 0, 37 0, 38 0, 39 0, 40 0, 41 0, 42 0, 43 0, 44 0, 45 0, 46 0, 47 0, 48 0, 49 0, 50 0, 51 0, 52 /* 0x20-0x2f */ 0, 53 0, 54 0, 55 0, 56 0, 57 0, 58 0, 59 0, 60 0, 61 0, 62 0, 63 0, 64 0, 65 0, 66 0, 67 0, 68 /* 0x30-0x3f */ 1, 69 1, 70 1, 71 1, 72 1, 73 1, 74 1, 75 1, 76 1, 77 1, 78 0, 79 0, 80 0, 81 0, 82 0, 83 0, 84 /* 0x40-0x4f */ 0, 85 1, 86 1, 87 1, 88 1, 89 1, 90 1, 91 1, 92 1, 93 1, 94 1, 95 1, 96 1, 97 1, 98 1, 99 1, 100 /* 0x50-0x5f */ 1, 101 1, 102 1, 103 1, 104 1, 105 1, 106 1, 107 1, 108 1, 109 1, 110 1, 111 0, 112 0, 113 0, 114 0, 115 0, 116 /* 0x60-0x6f */ 0, 117 1, 118 1, 119 1, 120 1, 121 1, 122 1, 123 1, 124 1, 125 1, 126 1, 127 1, 128 1, 129 1, 130 1, 131 1, 132 /* 0x70-0x7f */ 1, 133 1, 134 1, 135 1, 136 1, 137 1, 138 1, 139 1, 140 1, 141 1, 142 1, 143 0, 144 0, 145 0, 146 0, 147 0, 148 /* 0x80-0x8f */ 0, 149 0, 150 0, 151 0, 152 0, 153 0, 154 0, 155 0, 156 0, 157 0, 158 0, 159 0, 160 0, 161 0, 162 0, 163 0, 164 /* 0x90-0x9f */ 0, 165 0, 166 0, 167 0, 168 0, 169 0, 170 0, 171 0, 172 0, 173 0, 174 0, 175 0, 176 0, 177 0, 178 0, 179 0, 180 /* 0xa0-0xaf */ 0, 181 0, 182 0, 183 0, 184 0, 185 0, 186 0, 187 0, 188 0, 189 0, 190 0, 191 0, 192 0, 193 0, 194 0, 195 0, 196 /* 0xb0-0xbf */ 0, 197 0, 198 0, 199 0, 200 0, 201 0, 202 0, 203 0, 204 0, 205 0, 206 0, 207 0, 208 0, 209 0, 210 0, 211 0, 212 /* 0xc0-0xcf */ 0, 213 0, 214 0, 215 0, 216 0, 217 0, 218 0, 219 0, 220 0, 221 0, 222 0, 223 0, 224 0, 225 0, 226 0, 227 0, 228 /* 0xd0-0xdf */ 0, 229 0, 230 0, 231 0, 232 0, 233 0, 234 0, 235 0, 236 0, 237 0, 238 0, 239 0, 240 0, 241 0, 242 0, 243 0, 244 /* 0xe0-0xef */ 0, 245 0, 246 0, 247 0, 248 0, 249 0, 250 0, 251 0, 252 0, 253 0, 254 0, 255 0, 256 0, 257 0, 258 0, 259 0, 260 /* 0xf0-0xff */ 0, 261 0, 262 0, 263 0, 264 0, 265 0, 266 0, 267 0, 268 0, 269 0, 270 0, 271 0, 272 0, 273 0, 274 0, 275 0, 276 }; 277 278 static inline isc_result_t 279 fromtext_caa(ARGS_FROMTEXT) { 280 isc_token_t token; 281 isc_textregion_t tr; 282 uint8_t flags; 283 unsigned int i; 284 285 REQUIRE(type == dns_rdatatype_caa); 286 287 UNUSED(type); 288 UNUSED(rdclass); 289 UNUSED(origin); 290 UNUSED(options); 291 UNUSED(callbacks); 292 293 /* Flags. */ 294 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 295 false)); 296 if (token.value.as_ulong > 255U) { 297 RETTOK(ISC_R_RANGE); 298 } 299 flags = (uint8_t)(token.value.as_ulong & 255U); 300 RETERR(uint8_tobuffer(flags, target)); 301 302 /* 303 * Tag 304 */ 305 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 306 false)); 307 tr = token.value.as_textregion; 308 for (i = 0; i < tr.length; i++) { 309 if (!alphanumeric[(unsigned char)tr.base[i]]) { 310 RETTOK(DNS_R_SYNTAX); 311 } 312 } 313 RETERR(uint8_tobuffer(tr.length, target)); 314 RETERR(mem_tobuffer(target, tr.base, tr.length)); 315 316 /* 317 * Value 318 */ 319 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 320 false)); 321 if (token.type != isc_tokentype_qstring && 322 token.type != isc_tokentype_string) { 323 RETERR(DNS_R_SYNTAX); 324 } 325 RETERR(multitxt_fromtext(&token.value.as_textregion, target)); 326 return (ISC_R_SUCCESS); 327 } 328 329 static inline isc_result_t 330 totext_caa(ARGS_TOTEXT) { 331 isc_region_t region; 332 uint8_t flags; 333 char buf[256]; 334 335 UNUSED(tctx); 336 337 REQUIRE(rdata->type == dns_rdatatype_caa); 338 REQUIRE(rdata->length >= 3U); 339 REQUIRE(rdata->data != NULL); 340 341 dns_rdata_toregion(rdata, ®ion); 342 343 /* 344 * Flags 345 */ 346 flags = uint8_consume_fromregion(®ion); 347 snprintf(buf, sizeof(buf), "%u ", flags); 348 RETERR(str_totext(buf, target)); 349 350 /* 351 * Tag 352 */ 353 RETERR(txt_totext(®ion, false, target)); 354 RETERR(str_totext(" ", target)); 355 356 /* 357 * Value 358 */ 359 RETERR(multitxt_totext(®ion, target)); 360 return (ISC_R_SUCCESS); 361 } 362 363 static inline isc_result_t 364 fromwire_caa(ARGS_FROMWIRE) { 365 isc_region_t sr; 366 unsigned int len, i; 367 368 REQUIRE(type == dns_rdatatype_caa); 369 370 UNUSED(type); 371 UNUSED(rdclass); 372 UNUSED(dctx); 373 UNUSED(options); 374 375 /* 376 * Flags 377 */ 378 isc_buffer_activeregion(source, &sr); 379 if (sr.length < 2) { 380 return (ISC_R_UNEXPECTEDEND); 381 } 382 383 /* 384 * Flags, tag length 385 */ 386 RETERR(mem_tobuffer(target, sr.base, 2)); 387 len = sr.base[1]; 388 isc_region_consume(&sr, 2); 389 isc_buffer_forward(source, 2); 390 391 /* 392 * Zero length tag fields are illegal. 393 */ 394 if (sr.length < len || len == 0) { 395 RETERR(DNS_R_FORMERR); 396 } 397 398 /* Check the Tag's value */ 399 for (i = 0; i < len; i++) { 400 if (!alphanumeric[sr.base[i]]) { 401 RETERR(DNS_R_FORMERR); 402 /* 403 * Tag + Value 404 */ 405 } 406 } 407 /* 408 * Tag + Value 409 */ 410 isc_buffer_forward(source, sr.length); 411 return (mem_tobuffer(target, sr.base, sr.length)); 412 } 413 414 static inline isc_result_t 415 towire_caa(ARGS_TOWIRE) { 416 isc_region_t region; 417 418 REQUIRE(rdata->type == dns_rdatatype_caa); 419 REQUIRE(rdata->length >= 3U); 420 REQUIRE(rdata->data != NULL); 421 422 UNUSED(cctx); 423 424 dns_rdata_toregion(rdata, ®ion); 425 return (mem_tobuffer(target, region.base, region.length)); 426 } 427 428 static inline int 429 compare_caa(ARGS_COMPARE) { 430 isc_region_t r1, r2; 431 432 REQUIRE(rdata1->type == rdata2->type); 433 REQUIRE(rdata1->rdclass == rdata2->rdclass); 434 REQUIRE(rdata1->type == dns_rdatatype_caa); 435 REQUIRE(rdata1->length >= 3U); 436 REQUIRE(rdata2->length >= 3U); 437 REQUIRE(rdata1->data != NULL); 438 REQUIRE(rdata2->data != NULL); 439 440 dns_rdata_toregion(rdata1, &r1); 441 dns_rdata_toregion(rdata2, &r2); 442 return (isc_region_compare(&r1, &r2)); 443 } 444 445 static inline isc_result_t 446 fromstruct_caa(ARGS_FROMSTRUCT) { 447 dns_rdata_caa_t *caa = source; 448 isc_region_t region; 449 unsigned int i; 450 451 REQUIRE(type == dns_rdatatype_caa); 452 REQUIRE(caa != NULL); 453 REQUIRE(caa->common.rdtype == type); 454 REQUIRE(caa->common.rdclass == rdclass); 455 REQUIRE(caa->tag != NULL && caa->tag_len != 0); 456 REQUIRE(caa->value != NULL); 457 458 UNUSED(type); 459 UNUSED(rdclass); 460 461 /* 462 * Flags 463 */ 464 RETERR(uint8_tobuffer(caa->flags, target)); 465 466 /* 467 * Tag length 468 */ 469 RETERR(uint8_tobuffer(caa->tag_len, target)); 470 471 /* 472 * Tag 473 */ 474 region.base = caa->tag; 475 region.length = caa->tag_len; 476 for (i = 0; i < region.length; i++) { 477 if (!alphanumeric[region.base[i]]) { 478 RETERR(DNS_R_SYNTAX); 479 } 480 } 481 RETERR(isc_buffer_copyregion(target, ®ion)); 482 483 /* 484 * Value 485 */ 486 region.base = caa->value; 487 region.length = caa->value_len; 488 return (isc_buffer_copyregion(target, ®ion)); 489 } 490 491 static inline isc_result_t 492 tostruct_caa(ARGS_TOSTRUCT) { 493 dns_rdata_caa_t *caa = target; 494 isc_region_t sr; 495 496 REQUIRE(rdata->type == dns_rdatatype_caa); 497 REQUIRE(caa != NULL); 498 REQUIRE(rdata->length >= 3U); 499 REQUIRE(rdata->data != NULL); 500 501 caa->common.rdclass = rdata->rdclass; 502 caa->common.rdtype = rdata->type; 503 ISC_LINK_INIT(&caa->common, link); 504 505 dns_rdata_toregion(rdata, &sr); 506 507 /* 508 * Flags 509 */ 510 if (sr.length < 1) { 511 return (ISC_R_UNEXPECTEDEND); 512 } 513 caa->flags = uint8_fromregion(&sr); 514 isc_region_consume(&sr, 1); 515 516 /* 517 * Tag length 518 */ 519 if (sr.length < 1) { 520 return (ISC_R_UNEXPECTEDEND); 521 } 522 caa->tag_len = uint8_fromregion(&sr); 523 isc_region_consume(&sr, 1); 524 525 /* 526 * Tag 527 */ 528 if (sr.length < caa->tag_len) { 529 return (ISC_R_UNEXPECTEDEND); 530 } 531 caa->tag = mem_maybedup(mctx, sr.base, caa->tag_len); 532 if (caa->tag == NULL) { 533 return (ISC_R_NOMEMORY); 534 } 535 isc_region_consume(&sr, caa->tag_len); 536 537 /* 538 * Value 539 */ 540 caa->value_len = sr.length; 541 caa->value = mem_maybedup(mctx, sr.base, sr.length); 542 if (caa->value == NULL) { 543 return (ISC_R_NOMEMORY); 544 } 545 546 caa->mctx = mctx; 547 return (ISC_R_SUCCESS); 548 } 549 550 static inline void 551 freestruct_caa(ARGS_FREESTRUCT) { 552 dns_rdata_caa_t *caa = (dns_rdata_caa_t *)source; 553 554 REQUIRE(caa != NULL); 555 REQUIRE(caa->common.rdtype == dns_rdatatype_caa); 556 557 if (caa->mctx == NULL) { 558 return; 559 } 560 561 if (caa->tag != NULL) { 562 isc_mem_free(caa->mctx, caa->tag); 563 } 564 if (caa->value != NULL) { 565 isc_mem_free(caa->mctx, caa->value); 566 } 567 caa->mctx = NULL; 568 } 569 570 static inline isc_result_t 571 additionaldata_caa(ARGS_ADDLDATA) { 572 REQUIRE(rdata->type == dns_rdatatype_caa); 573 REQUIRE(rdata->data != NULL); 574 REQUIRE(rdata->length >= 3U); 575 576 UNUSED(rdata); 577 UNUSED(add); 578 UNUSED(arg); 579 580 return (ISC_R_SUCCESS); 581 } 582 583 static inline isc_result_t 584 digest_caa(ARGS_DIGEST) { 585 isc_region_t r; 586 587 REQUIRE(rdata->type == dns_rdatatype_caa); 588 REQUIRE(rdata->data != NULL); 589 REQUIRE(rdata->length >= 3U); 590 591 dns_rdata_toregion(rdata, &r); 592 593 return ((digest)(arg, &r)); 594 } 595 596 static inline bool 597 checkowner_caa(ARGS_CHECKOWNER) { 598 REQUIRE(type == dns_rdatatype_caa); 599 600 UNUSED(name); 601 UNUSED(type); 602 UNUSED(rdclass); 603 UNUSED(wildcard); 604 605 return (true); 606 } 607 608 static inline bool 609 checknames_caa(ARGS_CHECKNAMES) { 610 REQUIRE(rdata->type == dns_rdatatype_caa); 611 REQUIRE(rdata->data != NULL); 612 REQUIRE(rdata->length >= 3U); 613 614 UNUSED(rdata); 615 UNUSED(owner); 616 UNUSED(bad); 617 618 return (true); 619 } 620 621 static inline int 622 casecompare_caa(ARGS_COMPARE) { 623 return (compare_caa(rdata1, rdata2)); 624 } 625 626 #endif /* GENERIC_CAA_257_C */ 627