1 /* $NetBSD: naptr_35.c,v 1.1.1.6 2014/12/10 03:34:42 christos Exp $ */ 2 3 /* 4 * Copyright (C) 2004, 2005, 2007-2009, 2011-2014 Internet Systems Consortium, Inc. ("ISC") 5 * Copyright (C) 1999-2001, 2003 Internet Software Consortium. 6 * 7 * Permission to use, copy, modify, and/or distribute this software for any 8 * purpose with or without fee is hereby granted, provided that the above 9 * copyright notice and this permission notice appear in all copies. 10 * 11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH 12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT, 14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE 16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /* Id */ 21 22 /* Reviewed: Thu Mar 16 16:52:50 PST 2000 by bwelling */ 23 24 /* RFC2915 */ 25 26 #ifndef RDATA_GENERIC_NAPTR_35_C 27 #define RDATA_GENERIC_NAPTR_35_C 28 29 #define RRTYPE_NAPTR_ATTRIBUTES (0) 30 31 #include <isc/regex.h> 32 33 /* 34 * Check the wire format of the Regexp field. 35 * Don't allow embeded NUL's. 36 */ 37 static inline isc_result_t 38 txt_valid_regex(const unsigned char *txt) { 39 unsigned int nsub = 0; 40 char regex[256]; 41 char *cp; 42 isc_boolean_t flags = ISC_FALSE; 43 isc_boolean_t replace = ISC_FALSE; 44 unsigned char c; 45 unsigned char delim; 46 unsigned int len; 47 int n; 48 49 len = *txt++; 50 if (len == 0U) 51 return (ISC_R_SUCCESS); 52 53 delim = *txt++; 54 len--; 55 56 /* 57 * Digits, backslash and flags can't be delimiters. 58 */ 59 switch (delim) { 60 case '0': case '1': case '2': case '3': case '4': 61 case '5': case '6': case '7': case '8': case '9': 62 case '\\': case 'i': case 0: 63 return (DNS_R_SYNTAX); 64 } 65 66 cp = regex; 67 while (len-- > 0) { 68 c = *txt++; 69 if (c == 0) 70 return (DNS_R_SYNTAX); 71 if (c == delim && !replace) { 72 replace = ISC_TRUE; 73 continue; 74 } else if (c == delim && !flags) { 75 flags = ISC_TRUE; 76 continue; 77 } else if (c == delim) 78 return (DNS_R_SYNTAX); 79 /* 80 * Flags are not escaped. 81 */ 82 if (flags) { 83 switch (c) { 84 case 'i': 85 continue; 86 default: 87 return (DNS_R_SYNTAX); 88 } 89 } 90 if (!replace) 91 *cp++ = c; 92 if (c == '\\') { 93 if (len == 0) 94 return (DNS_R_SYNTAX); 95 c = *txt++; 96 if (c == 0) 97 return (DNS_R_SYNTAX); 98 len--; 99 if (replace) 100 switch (c) { 101 case '0': return (DNS_R_SYNTAX); 102 case '1': if (nsub < 1) nsub = 1; break; 103 case '2': if (nsub < 2) nsub = 2; break; 104 case '3': if (nsub < 3) nsub = 3; break; 105 case '4': if (nsub < 4) nsub = 4; break; 106 case '5': if (nsub < 5) nsub = 5; break; 107 case '6': if (nsub < 6) nsub = 6; break; 108 case '7': if (nsub < 7) nsub = 7; break; 109 case '8': if (nsub < 8) nsub = 8; break; 110 case '9': if (nsub < 9) nsub = 9; break; 111 } 112 if (!replace) 113 *cp++ = c; 114 } 115 } 116 if (!flags) 117 return (DNS_R_SYNTAX); 118 *cp = '\0'; 119 n = isc_regex_validate(regex); 120 if (n < 0 || nsub > (unsigned int)n) 121 return (DNS_R_SYNTAX); 122 return (ISC_R_SUCCESS); 123 } 124 125 static inline isc_result_t 126 fromtext_naptr(ARGS_FROMTEXT) { 127 isc_token_t token; 128 dns_name_t name; 129 isc_buffer_t buffer; 130 unsigned char *regex; 131 132 REQUIRE(type == 35); 133 134 UNUSED(type); 135 UNUSED(rdclass); 136 UNUSED(callbacks); 137 138 /* 139 * Order. 140 */ 141 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 142 ISC_FALSE)); 143 if (token.value.as_ulong > 0xffffU) 144 RETTOK(ISC_R_RANGE); 145 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 146 147 /* 148 * Preference. 149 */ 150 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_number, 151 ISC_FALSE)); 152 if (token.value.as_ulong > 0xffffU) 153 RETTOK(ISC_R_RANGE); 154 RETERR(uint16_tobuffer(token.value.as_ulong, target)); 155 156 /* 157 * Flags. 158 */ 159 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 160 ISC_FALSE)); 161 RETTOK(txt_fromtext(&token.value.as_textregion, target)); 162 163 /* 164 * Service. 165 */ 166 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 167 ISC_FALSE)); 168 RETTOK(txt_fromtext(&token.value.as_textregion, target)); 169 170 /* 171 * Regexp. 172 */ 173 regex = isc_buffer_used(target); 174 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_qstring, 175 ISC_FALSE)); 176 RETTOK(txt_fromtext(&token.value.as_textregion, target)); 177 RETTOK(txt_valid_regex(regex)); 178 179 /* 180 * Replacement. 181 */ 182 RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, 183 ISC_FALSE)); 184 dns_name_init(&name, NULL); 185 buffer_fromregion(&buffer, &token.value.as_region); 186 origin = (origin != NULL) ? origin : dns_rootname; 187 RETTOK(dns_name_fromtext(&name, &buffer, origin, options, target)); 188 return (ISC_R_SUCCESS); 189 } 190 191 static inline isc_result_t 192 totext_naptr(ARGS_TOTEXT) { 193 isc_region_t region; 194 dns_name_t name; 195 dns_name_t prefix; 196 isc_boolean_t sub; 197 char buf[sizeof("64000")]; 198 unsigned short num; 199 200 REQUIRE(rdata->type == 35); 201 REQUIRE(rdata->length != 0); 202 203 dns_name_init(&name, NULL); 204 dns_name_init(&prefix, NULL); 205 206 dns_rdata_toregion(rdata, ®ion); 207 208 /* 209 * Order. 210 */ 211 num = uint16_fromregion(®ion); 212 isc_region_consume(®ion, 2); 213 sprintf(buf, "%u", num); 214 RETERR(str_totext(buf, target)); 215 RETERR(str_totext(" ", target)); 216 217 /* 218 * Preference. 219 */ 220 num = uint16_fromregion(®ion); 221 isc_region_consume(®ion, 2); 222 sprintf(buf, "%u", num); 223 RETERR(str_totext(buf, target)); 224 RETERR(str_totext(" ", target)); 225 226 /* 227 * Flags. 228 */ 229 RETERR(txt_totext(®ion, ISC_TRUE, target)); 230 RETERR(str_totext(" ", target)); 231 232 /* 233 * Service. 234 */ 235 RETERR(txt_totext(®ion, ISC_TRUE, target)); 236 RETERR(str_totext(" ", target)); 237 238 /* 239 * Regexp. 240 */ 241 RETERR(txt_totext(®ion, ISC_TRUE, target)); 242 RETERR(str_totext(" ", target)); 243 244 /* 245 * Replacement. 246 */ 247 dns_name_fromregion(&name, ®ion); 248 sub = name_prefix(&name, tctx->origin, &prefix); 249 return (dns_name_totext(&prefix, sub, target)); 250 } 251 252 static inline isc_result_t 253 fromwire_naptr(ARGS_FROMWIRE) { 254 dns_name_t name; 255 isc_region_t sr; 256 unsigned char *regex; 257 258 REQUIRE(type == 35); 259 260 UNUSED(type); 261 UNUSED(rdclass); 262 263 dns_decompress_setmethods(dctx, DNS_COMPRESS_NONE); 264 265 dns_name_init(&name, NULL); 266 267 /* 268 * Order, preference. 269 */ 270 isc_buffer_activeregion(source, &sr); 271 if (sr.length < 4) 272 return (ISC_R_UNEXPECTEDEND); 273 RETERR(mem_tobuffer(target, sr.base, 4)); 274 isc_buffer_forward(source, 4); 275 276 /* 277 * Flags. 278 */ 279 RETERR(txt_fromwire(source, target)); 280 281 /* 282 * Service. 283 */ 284 RETERR(txt_fromwire(source, target)); 285 286 /* 287 * Regexp. 288 */ 289 regex = isc_buffer_used(target); 290 RETERR(txt_fromwire(source, target)); 291 RETERR(txt_valid_regex(regex)); 292 293 /* 294 * Replacement. 295 */ 296 return (dns_name_fromwire(&name, source, dctx, options, target)); 297 } 298 299 static inline isc_result_t 300 towire_naptr(ARGS_TOWIRE) { 301 dns_name_t name; 302 dns_offsets_t offsets; 303 isc_region_t sr; 304 305 REQUIRE(rdata->type == 35); 306 REQUIRE(rdata->length != 0); 307 308 dns_compress_setmethods(cctx, DNS_COMPRESS_NONE); 309 /* 310 * Order, preference. 311 */ 312 dns_rdata_toregion(rdata, &sr); 313 RETERR(mem_tobuffer(target, sr.base, 4)); 314 isc_region_consume(&sr, 4); 315 316 /* 317 * Flags. 318 */ 319 RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1)); 320 isc_region_consume(&sr, sr.base[0] + 1); 321 322 /* 323 * Service. 324 */ 325 RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1)); 326 isc_region_consume(&sr, sr.base[0] + 1); 327 328 /* 329 * Regexp. 330 */ 331 RETERR(mem_tobuffer(target, sr.base, sr.base[0] + 1)); 332 isc_region_consume(&sr, sr.base[0] + 1); 333 334 /* 335 * Replacement. 336 */ 337 dns_name_init(&name, offsets); 338 dns_name_fromregion(&name, &sr); 339 return (dns_name_towire(&name, cctx, target)); 340 } 341 342 static inline int 343 compare_naptr(ARGS_COMPARE) { 344 dns_name_t name1; 345 dns_name_t name2; 346 isc_region_t region1; 347 isc_region_t region2; 348 int order, len; 349 350 REQUIRE(rdata1->type == rdata2->type); 351 REQUIRE(rdata1->rdclass == rdata2->rdclass); 352 REQUIRE(rdata1->type == 35); 353 REQUIRE(rdata1->length != 0); 354 REQUIRE(rdata2->length != 0); 355 356 dns_rdata_toregion(rdata1, ®ion1); 357 dns_rdata_toregion(rdata2, ®ion2); 358 359 /* 360 * Order, preference. 361 */ 362 order = memcmp(region1.base, region2.base, 4); 363 if (order != 0) 364 return (order < 0 ? -1 : 1); 365 isc_region_consume(®ion1, 4); 366 isc_region_consume(®ion2, 4); 367 368 /* 369 * Flags. 370 */ 371 len = ISC_MIN(region1.base[0], region2.base[0]); 372 order = memcmp(region1.base, region2.base, len + 1); 373 if (order != 0) 374 return (order < 0 ? -1 : 1); 375 isc_region_consume(®ion1, region1.base[0] + 1); 376 isc_region_consume(®ion2, region2.base[0] + 1); 377 378 /* 379 * Service. 380 */ 381 len = ISC_MIN(region1.base[0], region2.base[0]); 382 order = memcmp(region1.base, region2.base, len + 1); 383 if (order != 0) 384 return (order < 0 ? -1 : 1); 385 isc_region_consume(®ion1, region1.base[0] + 1); 386 isc_region_consume(®ion2, region2.base[0] + 1); 387 388 /* 389 * Regexp. 390 */ 391 len = ISC_MIN(region1.base[0], region2.base[0]); 392 order = memcmp(region1.base, region2.base, len + 1); 393 if (order != 0) 394 return (order < 0 ? -1 : 1); 395 isc_region_consume(®ion1, region1.base[0] + 1); 396 isc_region_consume(®ion2, region2.base[0] + 1); 397 398 /* 399 * Replacement. 400 */ 401 dns_name_init(&name1, NULL); 402 dns_name_init(&name2, NULL); 403 404 dns_name_fromregion(&name1, ®ion1); 405 dns_name_fromregion(&name2, ®ion2); 406 407 return (dns_name_rdatacompare(&name1, &name2)); 408 } 409 410 static inline isc_result_t 411 fromstruct_naptr(ARGS_FROMSTRUCT) { 412 dns_rdata_naptr_t *naptr = source; 413 isc_region_t region; 414 415 REQUIRE(type == 35); 416 REQUIRE(source != NULL); 417 REQUIRE(naptr->common.rdtype == type); 418 REQUIRE(naptr->common.rdclass == rdclass); 419 REQUIRE(naptr->flags != NULL || naptr->flags_len == 0); 420 REQUIRE(naptr->service != NULL || naptr->service_len == 0); 421 REQUIRE(naptr->regexp != NULL || naptr->regexp_len == 0); 422 423 UNUSED(type); 424 UNUSED(rdclass); 425 426 RETERR(uint16_tobuffer(naptr->order, target)); 427 RETERR(uint16_tobuffer(naptr->preference, target)); 428 RETERR(uint8_tobuffer(naptr->flags_len, target)); 429 RETERR(mem_tobuffer(target, naptr->flags, naptr->flags_len)); 430 RETERR(uint8_tobuffer(naptr->service_len, target)); 431 RETERR(mem_tobuffer(target, naptr->service, naptr->service_len)); 432 RETERR(uint8_tobuffer(naptr->regexp_len, target)); 433 RETERR(mem_tobuffer(target, naptr->regexp, naptr->regexp_len)); 434 dns_name_toregion(&naptr->replacement, ®ion); 435 return (isc_buffer_copyregion(target, ®ion)); 436 } 437 438 static inline isc_result_t 439 tostruct_naptr(ARGS_TOSTRUCT) { 440 dns_rdata_naptr_t *naptr = target; 441 isc_region_t r; 442 isc_result_t result; 443 dns_name_t name; 444 445 REQUIRE(rdata->type == 35); 446 REQUIRE(target != NULL); 447 REQUIRE(rdata->length != 0); 448 449 naptr->common.rdclass = rdata->rdclass; 450 naptr->common.rdtype = rdata->type; 451 ISC_LINK_INIT(&naptr->common, link); 452 453 naptr->flags = NULL; 454 naptr->service = NULL; 455 naptr->regexp = NULL; 456 457 dns_rdata_toregion(rdata, &r); 458 459 naptr->order = uint16_fromregion(&r); 460 isc_region_consume(&r, 2); 461 462 naptr->preference = uint16_fromregion(&r); 463 isc_region_consume(&r, 2); 464 465 naptr->flags_len = uint8_fromregion(&r); 466 isc_region_consume(&r, 1); 467 INSIST(naptr->flags_len <= r.length); 468 naptr->flags = mem_maybedup(mctx, r.base, naptr->flags_len); 469 if (naptr->flags == NULL) 470 goto cleanup; 471 isc_region_consume(&r, naptr->flags_len); 472 473 naptr->service_len = uint8_fromregion(&r); 474 isc_region_consume(&r, 1); 475 INSIST(naptr->service_len <= r.length); 476 naptr->service = mem_maybedup(mctx, r.base, naptr->service_len); 477 if (naptr->service == NULL) 478 goto cleanup; 479 isc_region_consume(&r, naptr->service_len); 480 481 naptr->regexp_len = uint8_fromregion(&r); 482 isc_region_consume(&r, 1); 483 INSIST(naptr->regexp_len <= r.length); 484 naptr->regexp = mem_maybedup(mctx, r.base, naptr->regexp_len); 485 if (naptr->regexp == NULL) 486 goto cleanup; 487 isc_region_consume(&r, naptr->regexp_len); 488 489 dns_name_init(&name, NULL); 490 dns_name_fromregion(&name, &r); 491 dns_name_init(&naptr->replacement, NULL); 492 result = name_duporclone(&name, mctx, &naptr->replacement); 493 if (result != ISC_R_SUCCESS) 494 goto cleanup; 495 naptr->mctx = mctx; 496 return (ISC_R_SUCCESS); 497 498 cleanup: 499 if (mctx != NULL && naptr->flags != NULL) 500 isc_mem_free(mctx, naptr->flags); 501 if (mctx != NULL && naptr->service != NULL) 502 isc_mem_free(mctx, naptr->service); 503 if (mctx != NULL && naptr->regexp != NULL) 504 isc_mem_free(mctx, naptr->regexp); 505 return (ISC_R_NOMEMORY); 506 } 507 508 static inline void 509 freestruct_naptr(ARGS_FREESTRUCT) { 510 dns_rdata_naptr_t *naptr = source; 511 512 REQUIRE(source != NULL); 513 REQUIRE(naptr->common.rdtype == 35); 514 515 if (naptr->mctx == NULL) 516 return; 517 518 if (naptr->flags != NULL) 519 isc_mem_free(naptr->mctx, naptr->flags); 520 if (naptr->service != NULL) 521 isc_mem_free(naptr->mctx, naptr->service); 522 if (naptr->regexp != NULL) 523 isc_mem_free(naptr->mctx, naptr->regexp); 524 dns_name_free(&naptr->replacement, naptr->mctx); 525 naptr->mctx = NULL; 526 } 527 528 static inline isc_result_t 529 additionaldata_naptr(ARGS_ADDLDATA) { 530 dns_name_t name; 531 dns_offsets_t offsets; 532 isc_region_t sr; 533 dns_rdatatype_t atype; 534 unsigned int i, flagslen; 535 char *cp; 536 537 REQUIRE(rdata->type == 35); 538 539 /* 540 * Order, preference. 541 */ 542 dns_rdata_toregion(rdata, &sr); 543 isc_region_consume(&sr, 4); 544 545 /* 546 * Flags. 547 */ 548 atype = 0; 549 flagslen = sr.base[0]; 550 cp = (char *)&sr.base[1]; 551 for (i = 0; i < flagslen; i++, cp++) { 552 if (*cp == 'S' || *cp == 's') { 553 atype = dns_rdatatype_srv; 554 break; 555 } 556 if (*cp == 'A' || *cp == 'a') { 557 atype = dns_rdatatype_a; 558 break; 559 } 560 } 561 isc_region_consume(&sr, flagslen + 1); 562 563 /* 564 * Service. 565 */ 566 isc_region_consume(&sr, sr.base[0] + 1); 567 568 /* 569 * Regexp. 570 */ 571 isc_region_consume(&sr, sr.base[0] + 1); 572 573 /* 574 * Replacement. 575 */ 576 dns_name_init(&name, offsets); 577 dns_name_fromregion(&name, &sr); 578 579 if (atype != 0) 580 return ((add)(arg, &name, atype)); 581 582 return (ISC_R_SUCCESS); 583 } 584 585 static inline isc_result_t 586 digest_naptr(ARGS_DIGEST) { 587 isc_region_t r1, r2; 588 unsigned int length, n; 589 isc_result_t result; 590 dns_name_t name; 591 592 REQUIRE(rdata->type == 35); 593 594 dns_rdata_toregion(rdata, &r1); 595 r2 = r1; 596 length = 0; 597 598 /* 599 * Order, preference. 600 */ 601 length += 4; 602 isc_region_consume(&r2, 4); 603 604 /* 605 * Flags. 606 */ 607 n = r2.base[0] + 1; 608 length += n; 609 isc_region_consume(&r2, n); 610 611 /* 612 * Service. 613 */ 614 n = r2.base[0] + 1; 615 length += n; 616 isc_region_consume(&r2, n); 617 618 /* 619 * Regexp. 620 */ 621 n = r2.base[0] + 1; 622 length += n; 623 isc_region_consume(&r2, n); 624 625 /* 626 * Digest the RR up to the replacement name. 627 */ 628 r1.length = length; 629 result = (digest)(arg, &r1); 630 if (result != ISC_R_SUCCESS) 631 return (result); 632 633 /* 634 * Replacement. 635 */ 636 637 dns_name_init(&name, NULL); 638 dns_name_fromregion(&name, &r2); 639 640 return (dns_name_digest(&name, digest, arg)); 641 } 642 643 static inline isc_boolean_t 644 checkowner_naptr(ARGS_CHECKOWNER) { 645 646 REQUIRE(type == 35); 647 648 UNUSED(name); 649 UNUSED(type); 650 UNUSED(rdclass); 651 UNUSED(wildcard); 652 653 return (ISC_TRUE); 654 } 655 656 static inline isc_boolean_t 657 checknames_naptr(ARGS_CHECKNAMES) { 658 659 REQUIRE(rdata->type == 35); 660 661 UNUSED(rdata); 662 UNUSED(owner); 663 UNUSED(bad); 664 665 return (ISC_TRUE); 666 } 667 668 static inline int 669 casecompare_naptr(ARGS_COMPARE) { 670 return (compare_naptr(rdata1, rdata2)); 671 } 672 673 #endif /* RDATA_GENERIC_NAPTR_35_C */ 674