1 /* 2 * rdata.c -- RDATA conversion functions. 3 * 4 * Copyright (c) 2001-2006, NLnet Labs. All rights reserved. 5 * 6 * See LICENSE for the license. 7 * 8 */ 9 10 #include "config.h" 11 12 #include <sys/types.h> 13 #include <sys/socket.h> 14 #include <netinet/in.h> 15 #include <arpa/inet.h> 16 #include <ctype.h> 17 #include <netdb.h> 18 #include <stdlib.h> 19 #include <string.h> 20 #ifdef HAVE_STRINGS_H 21 #include <strings.h> 22 #endif 23 24 #include "rdata.h" 25 #include "zonec.h" 26 27 /* Taken from RFC 4398, section 2.1. */ 28 lookup_table_type dns_certificate_types[] = { 29 /* 0 Reserved */ 30 { 1, "PKIX" }, /* X.509 as per PKIX */ 31 { 2, "SPKI" }, /* SPKI cert */ 32 { 3, "PGP" }, /* OpenPGP packet */ 33 { 4, "IPKIX" }, /* The URL of an X.509 data object */ 34 { 5, "ISPKI" }, /* The URL of an SPKI certificate */ 35 { 6, "IPGP" }, /* The fingerprint and URL of an OpenPGP packet */ 36 { 7, "ACPKIX" }, /* Attribute Certificate */ 37 { 8, "IACPKIX" }, /* The URL of an Attribute Certificate */ 38 { 253, "URI" }, /* URI private */ 39 { 254, "OID" }, /* OID private */ 40 /* 255 Reserved */ 41 /* 256-65279 Available for IANA assignment */ 42 /* 65280-65534 Experimental */ 43 /* 65535 Reserved */ 44 { 0, NULL } 45 }; 46 47 /* Taken from RFC 2535, section 7. */ 48 lookup_table_type dns_algorithms[] = { 49 { 1, "RSAMD5" }, /* RFC 2537 */ 50 { 2, "DH" }, /* RFC 2539 */ 51 { 3, "DSA" }, /* RFC 2536 */ 52 { 4, "ECC" }, 53 { 5, "RSASHA1" }, /* RFC 3110 */ 54 { 6, "DSA-NSEC3-SHA1" }, /* RFC 5155 */ 55 { 7, "RSASHA1-NSEC3-SHA1" }, /* RFC 5155 */ 56 { 8, "RSASHA256" }, /* RFC 5702 */ 57 { 10, "RSASHA512" }, /* RFC 5702 */ 58 { 12, "ECC-GOST" }, /* RFC 5933 */ 59 { 13, "ECDSAP256SHA256" }, /* RFC 6605 */ 60 { 14, "ECDSAP384SHA384" }, /* RFC 6605 */ 61 { 15, "ED25519" }, /* RFC 8080 */ 62 { 16, "ED448" }, /* RFC 8080 */ 63 { 252, "INDIRECT" }, 64 { 253, "PRIVATEDNS" }, 65 { 254, "PRIVATEOID" }, 66 { 0, NULL } 67 }; 68 69 typedef int (*rdata_to_string_type)(buffer_type *output, 70 rdata_atom_type rdata, 71 rr_type *rr); 72 73 static int 74 rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata, 75 rr_type* ATTR_UNUSED(rr)) 76 { 77 buffer_printf(output, 78 "%s", 79 dname_to_string(domain_dname(rdata_atom_domain(rdata)), 80 NULL)); 81 return 1; 82 } 83 84 static int 85 rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata, 86 rr_type* ATTR_UNUSED(rr)) 87 { 88 const uint8_t *data = rdata_atom_data(rdata); 89 size_t offset = 0; 90 uint8_t length = data[offset]; 91 size_t i; 92 93 while (length > 0) 94 { 95 if (offset) /* concat label */ 96 buffer_printf(output, "."); 97 98 for (i = 1; i <= length; ++i) { 99 uint8_t ch = data[i+offset]; 100 101 if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') { 102 buffer_printf(output, "\\%c", (char) ch); 103 } else if (!isgraph((unsigned char) ch)) { 104 buffer_printf(output, "\\%03u", (unsigned int) ch); 105 } else if (isprint((unsigned char) ch)) { 106 buffer_printf(output, "%c", (char) ch); 107 } else { 108 buffer_printf(output, "\\%03u", (unsigned int) ch); 109 } 110 } 111 /* next label */ 112 offset = offset+length+1; 113 length = data[offset]; 114 } 115 116 /* root label */ 117 buffer_printf(output, "."); 118 return 1; 119 } 120 121 static int 122 rdata_text_to_string(buffer_type *output, rdata_atom_type rdata, 123 rr_type* ATTR_UNUSED(rr)) 124 { 125 const uint8_t *data = rdata_atom_data(rdata); 126 uint8_t length = data[0]; 127 size_t i; 128 129 buffer_printf(output, "\""); 130 for (i = 1; i <= length; ++i) { 131 char ch = (char) data[i]; 132 if (isprint((unsigned char)ch)) { 133 if (ch == '"' || ch == '\\') { 134 buffer_printf(output, "\\"); 135 } 136 buffer_printf(output, "%c", ch); 137 } else { 138 buffer_printf(output, "\\%03u", (unsigned) data[i]); 139 } 140 } 141 buffer_printf(output, "\""); 142 return 1; 143 } 144 145 static int 146 rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata, 147 rr_type* ATTR_UNUSED(rr)) 148 { 149 uint16_t pos = 0; 150 const uint8_t *data = rdata_atom_data(rdata); 151 uint16_t length = rdata_atom_size(rdata); 152 size_t i; 153 154 while (pos < length && pos + data[pos] < length) { 155 buffer_printf(output, "\""); 156 for (i = 1; i <= data[pos]; ++i) { 157 char ch = (char) data[pos + i]; 158 if (isprint((unsigned char)ch)) { 159 if (ch == '"' || ch == '\\') { 160 buffer_printf(output, "\\"); 161 } 162 buffer_printf(output, "%c", ch); 163 } else { 164 buffer_printf(output, "\\%03u", (unsigned) data[pos+i]); 165 } 166 } 167 pos += data[pos]+1; 168 buffer_printf(output, pos < length?"\" ":"\""); 169 } 170 return 1; 171 } 172 173 static int 174 rdata_long_text_to_string(buffer_type *output, rdata_atom_type rdata, 175 rr_type* ATTR_UNUSED(rr)) 176 { 177 const uint8_t *data = rdata_atom_data(rdata); 178 uint16_t length = rdata_atom_size(rdata); 179 size_t i; 180 181 buffer_printf(output, "\""); 182 for (i = 0; i < length; ++i) { 183 char ch = (char) data[i]; 184 if (isprint((unsigned char)ch)) { 185 if (ch == '"' || ch == '\\') { 186 buffer_printf(output, "\\"); 187 } 188 buffer_printf(output, "%c", ch); 189 } else { 190 buffer_printf(output, "\\%03u", (unsigned) data[i]); 191 } 192 } 193 buffer_printf(output, "\""); 194 return 1; 195 } 196 197 static int 198 rdata_tag_to_string(buffer_type *output, rdata_atom_type rdata, 199 rr_type* ATTR_UNUSED(rr)) 200 { 201 const uint8_t *data = rdata_atom_data(rdata); 202 uint8_t length = data[0]; 203 size_t i; 204 for (i = 1; i <= length; ++i) { 205 char ch = (char) data[i]; 206 if (isdigit((unsigned char)ch) || islower((unsigned char)ch)) 207 buffer_printf(output, "%c", ch); 208 else return 0; 209 } 210 return 1; 211 } 212 213 static int 214 rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata, 215 rr_type* ATTR_UNUSED(rr)) 216 { 217 uint8_t data = *rdata_atom_data(rdata); 218 buffer_printf(output, "%lu", (unsigned long) data); 219 return 1; 220 } 221 222 static int 223 rdata_short_to_string(buffer_type *output, rdata_atom_type rdata, 224 rr_type* ATTR_UNUSED(rr)) 225 { 226 uint16_t data = read_uint16(rdata_atom_data(rdata)); 227 buffer_printf(output, "%lu", (unsigned long) data); 228 return 1; 229 } 230 231 static int 232 rdata_long_to_string(buffer_type *output, rdata_atom_type rdata, 233 rr_type* ATTR_UNUSED(rr)) 234 { 235 uint32_t data = read_uint32(rdata_atom_data(rdata)); 236 buffer_printf(output, "%lu", (unsigned long) data); 237 return 1; 238 } 239 240 static int 241 rdata_a_to_string(buffer_type *output, rdata_atom_type rdata, 242 rr_type* ATTR_UNUSED(rr)) 243 { 244 int result = 0; 245 char str[200]; 246 if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) { 247 buffer_printf(output, "%s", str); 248 result = 1; 249 } 250 return result; 251 } 252 253 static int 254 rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata, 255 rr_type* ATTR_UNUSED(rr)) 256 { 257 int result = 0; 258 char str[200]; 259 if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) { 260 buffer_printf(output, "%s", str); 261 result = 1; 262 } 263 return result; 264 } 265 266 static int 267 rdata_ilnp64_to_string(buffer_type *output, rdata_atom_type rdata, 268 rr_type* ATTR_UNUSED(rr)) 269 { 270 uint8_t* data = rdata_atom_data(rdata); 271 uint16_t a1 = read_uint16(data); 272 uint16_t a2 = read_uint16(data+2); 273 uint16_t a3 = read_uint16(data+4); 274 uint16_t a4 = read_uint16(data+6); 275 276 buffer_printf(output, "%.4x:%.4x:%.4x:%.4x", a1, a2, a3, a4); 277 return 1; 278 } 279 280 static int 281 rdata_eui48_to_string(buffer_type *output, rdata_atom_type rdata, 282 rr_type* ATTR_UNUSED(rr)) 283 { 284 uint8_t* data = rdata_atom_data(rdata); 285 uint8_t a1 = data[0]; 286 uint8_t a2 = data[1]; 287 uint8_t a3 = data[2]; 288 uint8_t a4 = data[3]; 289 uint8_t a5 = data[4]; 290 uint8_t a6 = data[5]; 291 292 buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 293 a1, a2, a3, a4, a5, a6); 294 return 1; 295 } 296 297 static int 298 rdata_eui64_to_string(buffer_type *output, rdata_atom_type rdata, 299 rr_type* ATTR_UNUSED(rr)) 300 { 301 uint8_t* data = rdata_atom_data(rdata); 302 uint8_t a1 = data[0]; 303 uint8_t a2 = data[1]; 304 uint8_t a3 = data[2]; 305 uint8_t a4 = data[3]; 306 uint8_t a5 = data[4]; 307 uint8_t a6 = data[5]; 308 uint8_t a7 = data[6]; 309 uint8_t a8 = data[7]; 310 311 buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 312 a1, a2, a3, a4, a5, a6, a7, a8); 313 return 1; 314 } 315 316 static int 317 rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata, 318 rr_type* ATTR_UNUSED(rr)) 319 { 320 uint16_t type = read_uint16(rdata_atom_data(rdata)); 321 buffer_printf(output, "%s", rrtype_to_string(type)); 322 return 1; 323 } 324 325 static int 326 rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata, 327 rr_type* ATTR_UNUSED(rr)) 328 { 329 uint8_t id = *rdata_atom_data(rdata); 330 buffer_printf(output, "%u", (unsigned) id); 331 return 1; 332 } 333 334 static int 335 rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata, 336 rr_type* ATTR_UNUSED(rr)) 337 { 338 uint16_t id = read_uint16(rdata_atom_data(rdata)); 339 lookup_table_type *type 340 = lookup_by_id(dns_certificate_types, id); 341 if (type) { 342 buffer_printf(output, "%s", type->name); 343 } else { 344 buffer_printf(output, "%u", (unsigned) id); 345 } 346 return 1; 347 } 348 349 static int 350 rdata_period_to_string(buffer_type *output, rdata_atom_type rdata, 351 rr_type* ATTR_UNUSED(rr)) 352 { 353 uint32_t period = read_uint32(rdata_atom_data(rdata)); 354 buffer_printf(output, "%lu", (unsigned long) period); 355 return 1; 356 } 357 358 static int 359 rdata_time_to_string(buffer_type *output, rdata_atom_type rdata, 360 rr_type* ATTR_UNUSED(rr)) 361 { 362 int result = 0; 363 time_t time = (time_t) read_uint32(rdata_atom_data(rdata)); 364 struct tm *tm = gmtime(&time); 365 char buf[15]; 366 if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) { 367 buffer_printf(output, "%s", buf); 368 result = 1; 369 } 370 return result; 371 } 372 373 static int 374 rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata, 375 rr_type* ATTR_UNUSED(rr)) 376 { 377 int length; 378 size_t size = rdata_atom_size(rdata); 379 if(size == 0) { 380 buffer_write(output, "-", 1); 381 return 1; 382 } 383 size -= 1; /* remove length byte from count */ 384 buffer_reserve(output, size * 2 + 1); 385 length = b32_ntop(rdata_atom_data(rdata)+1, size, 386 (char *) buffer_current(output), size * 2); 387 if (length > 0) { 388 buffer_skip(output, length); 389 } 390 return length != -1; 391 } 392 393 static int 394 rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata, 395 rr_type* ATTR_UNUSED(rr)) 396 { 397 int length; 398 size_t size = rdata_atom_size(rdata); 399 if(size == 0) { 400 /* single zero represents empty buffer */ 401 buffer_write(output, "0", 1); 402 return 1; 403 } 404 buffer_reserve(output, size * 2 + 1); 405 length = __b64_ntop(rdata_atom_data(rdata), size, 406 (char *) buffer_current(output), size * 2); 407 if (length > 0) { 408 buffer_skip(output, length); 409 } 410 return length != -1; 411 } 412 413 static void 414 hex_to_string(buffer_type *output, const uint8_t *data, size_t size) 415 { 416 static const char hexdigits[] = { 417 '0', '1', '2', '3', '4', '5', '6', '7', 418 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 419 }; 420 size_t i; 421 422 buffer_reserve(output, size * 2); 423 for (i = 0; i < size; ++i) { 424 uint8_t octet = *data++; 425 buffer_write_u8(output, hexdigits[octet >> 4]); 426 buffer_write_u8(output, hexdigits[octet & 0x0f]); 427 } 428 } 429 430 static int 431 rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata, 432 rr_type* ATTR_UNUSED(rr)) 433 { 434 if(rdata_atom_size(rdata) == 0) { 435 /* single zero represents empty buffer, such as CDS deletes */ 436 buffer_printf(output, "0"); 437 } else { 438 hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata)); 439 } 440 return 1; 441 } 442 443 static int 444 rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata, 445 rr_type* ATTR_UNUSED(rr)) 446 { 447 if(rdata_atom_size(rdata) <= 1) { 448 /* NSEC3 salt hex can be empty */ 449 buffer_printf(output, "-"); 450 return 1; 451 } 452 hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1); 453 return 1; 454 } 455 456 static int 457 rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata, 458 rr_type* ATTR_UNUSED(rr)) 459 { 460 buffer_printf(output, "0x"); 461 hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata)); 462 return 1; 463 } 464 465 static int 466 rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata, 467 rr_type* ATTR_UNUSED(rr)) 468 { 469 int result = 0; 470 buffer_type packet; 471 472 buffer_create_from( 473 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 474 475 if (buffer_available(&packet, 4)) { 476 uint16_t address_family = buffer_read_u16(&packet); 477 uint8_t prefix = buffer_read_u8(&packet); 478 uint8_t length = buffer_read_u8(&packet); 479 int negated = length & APL_NEGATION_MASK; 480 int af = -1; 481 482 length &= APL_LENGTH_MASK; 483 switch (address_family) { 484 case 1: af = AF_INET; break; 485 case 2: af = AF_INET6; break; 486 } 487 if (af != -1 && buffer_available(&packet, length)) { 488 char text_address[1000]; 489 uint8_t address[128]; 490 memset(address, 0, sizeof(address)); 491 buffer_read(&packet, address, length); 492 if (inet_ntop(af, address, text_address, sizeof(text_address))) { 493 buffer_printf(output, "%s%d:%s/%d", 494 negated ? "!" : "", 495 (int) address_family, 496 text_address, 497 (int) prefix); 498 result = 1; 499 } 500 } 501 } 502 return result; 503 } 504 505 static int 506 rdata_services_to_string(buffer_type *output, rdata_atom_type rdata, 507 rr_type* ATTR_UNUSED(rr)) 508 { 509 int result = 0; 510 buffer_type packet; 511 512 buffer_create_from( 513 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 514 515 if (buffer_available(&packet, 1)) { 516 uint8_t protocol_number = buffer_read_u8(&packet); 517 ssize_t bitmap_size = buffer_remaining(&packet); 518 uint8_t *bitmap = buffer_current(&packet); 519 struct protoent *proto = getprotobynumber(protocol_number); 520 521 if (proto) { 522 int i; 523 524 buffer_printf(output, "%s", proto->p_name); 525 526 for (i = 0; i < bitmap_size * 8; ++i) { 527 if (get_bit(bitmap, i)) { 528 struct servent *service = getservbyport((int)htons(i), proto->p_name); 529 if (service) { 530 buffer_printf(output, " %s", service->s_name); 531 } else { 532 buffer_printf(output, " %d", i); 533 } 534 } 535 } 536 buffer_skip(&packet, bitmap_size); 537 result = 1; 538 } 539 } 540 return result; 541 } 542 543 static int 544 rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr) 545 { 546 int gateway_type = rdata_atom_data(rr->rdatas[1])[0]; 547 switch(gateway_type) { 548 case IPSECKEY_NOGATEWAY: 549 buffer_printf(output, "."); 550 break; 551 case IPSECKEY_IP4: 552 rdata_a_to_string(output, rdata, rr); 553 break; 554 case IPSECKEY_IP6: 555 rdata_aaaa_to_string(output, rdata, rr); 556 break; 557 case IPSECKEY_DNAME: 558 { 559 region_type* temp = region_create(xalloc, free); 560 const dname_type* d = dname_make(temp, 561 rdata_atom_data(rdata), 0); 562 if(!d) { 563 region_destroy(temp); 564 return 0; 565 } 566 buffer_printf(output, "%s", dname_to_string(d, NULL)); 567 region_destroy(temp); 568 } 569 break; 570 default: 571 return 0; 572 } 573 return 1; 574 } 575 576 static int 577 rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata, 578 rr_type* ATTR_UNUSED(rr)) 579 { 580 size_t i; 581 uint8_t *bitmap = rdata_atom_data(rdata); 582 size_t bitmap_size = rdata_atom_size(rdata); 583 584 for (i = 0; i < bitmap_size * 8; ++i) { 585 if (get_bit(bitmap, i)) { 586 buffer_printf(output, "%s ", rrtype_to_string(i)); 587 } 588 } 589 590 buffer_skip(output, -1); 591 592 return 1; 593 } 594 595 static int 596 rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata, 597 rr_type* ATTR_UNUSED(rr)) 598 { 599 size_t saved_position = buffer_position(output); 600 buffer_type packet; 601 int insert_space = 0; 602 603 buffer_create_from( 604 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 605 606 while (buffer_available(&packet, 2)) { 607 uint8_t window = buffer_read_u8(&packet); 608 uint8_t bitmap_size = buffer_read_u8(&packet); 609 uint8_t *bitmap = buffer_current(&packet); 610 int i; 611 612 if (!buffer_available(&packet, bitmap_size)) { 613 buffer_set_position(output, saved_position); 614 return 0; 615 } 616 617 for (i = 0; i < bitmap_size * 8; ++i) { 618 if (get_bit(bitmap, i)) { 619 buffer_printf(output, 620 "%s%s", 621 insert_space ? " " : "", 622 rrtype_to_string( 623 window * 256 + i)); 624 insert_space = 1; 625 } 626 } 627 buffer_skip(&packet, bitmap_size); 628 } 629 630 return 1; 631 } 632 633 static int 634 rdata_loc_to_string(buffer_type *ATTR_UNUSED(output), 635 rdata_atom_type ATTR_UNUSED(rdata), 636 rr_type* ATTR_UNUSED(rr)) 637 { 638 /* 639 * Returning 0 forces the record to be printed in unknown 640 * format. 641 */ 642 return 0; 643 } 644 645 static int 646 rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata, 647 rr_type* ATTR_UNUSED(rr)) 648 { 649 uint16_t size = rdata_atom_size(rdata); 650 buffer_printf(output, "\\# %lu ", (unsigned long) size); 651 hex_to_string(output, rdata_atom_data(rdata), size); 652 return 1; 653 } 654 655 static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = { 656 rdata_dname_to_string, 657 rdata_dns_name_to_string, 658 rdata_text_to_string, 659 rdata_texts_to_string, 660 rdata_byte_to_string, 661 rdata_short_to_string, 662 rdata_long_to_string, 663 rdata_a_to_string, 664 rdata_aaaa_to_string, 665 rdata_rrtype_to_string, 666 rdata_algorithm_to_string, 667 rdata_certificate_type_to_string, 668 rdata_period_to_string, 669 rdata_time_to_string, 670 rdata_base64_to_string, 671 rdata_base32_to_string, 672 rdata_hex_to_string, 673 rdata_hexlen_to_string, 674 rdata_nsap_to_string, 675 rdata_apl_to_string, 676 rdata_ipsecgateway_to_string, 677 rdata_services_to_string, 678 rdata_nxt_to_string, 679 rdata_nsec_to_string, 680 rdata_loc_to_string, 681 rdata_ilnp64_to_string, 682 rdata_eui48_to_string, 683 rdata_eui64_to_string, 684 rdata_long_text_to_string, 685 rdata_tag_to_string, 686 rdata_unknown_to_string 687 }; 688 689 int 690 rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type, 691 rdata_atom_type rdata, rr_type* record) 692 { 693 return rdata_to_string_table[type](output, rdata, record); 694 } 695 696 ssize_t 697 rdata_wireformat_to_rdata_atoms(region_type *region, 698 domain_table_type *owners, 699 uint16_t rrtype, 700 uint16_t data_size, 701 buffer_type *packet, 702 rdata_atom_type **rdatas) 703 { 704 size_t end = buffer_position(packet) + data_size; 705 size_t i; 706 rdata_atom_type temp_rdatas[MAXRDATALEN]; 707 rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype); 708 region_type *temp_region; 709 710 assert(descriptor->maximum <= MAXRDATALEN); 711 712 if (!buffer_available(packet, data_size)) { 713 return -1; 714 } 715 716 temp_region = region_create(xalloc, free); 717 718 for (i = 0; i < descriptor->maximum; ++i) { 719 int is_domain = 0; 720 int is_normalized = 0; 721 int is_wirestore = 0; 722 size_t length = 0; 723 int required = i < descriptor->minimum; 724 725 switch (rdata_atom_wireformat_type(rrtype, i)) { 726 case RDATA_WF_COMPRESSED_DNAME: 727 case RDATA_WF_UNCOMPRESSED_DNAME: 728 is_domain = 1; 729 is_normalized = 1; 730 break; 731 case RDATA_WF_LITERAL_DNAME: 732 is_domain = 1; 733 is_wirestore = 1; 734 break; 735 case RDATA_WF_BYTE: 736 length = sizeof(uint8_t); 737 break; 738 case RDATA_WF_SHORT: 739 length = sizeof(uint16_t); 740 break; 741 case RDATA_WF_LONG: 742 length = sizeof(uint32_t); 743 break; 744 case RDATA_WF_TEXTS: 745 case RDATA_WF_LONG_TEXT: 746 length = end - buffer_position(packet); 747 break; 748 case RDATA_WF_TEXT: 749 case RDATA_WF_BINARYWITHLENGTH: 750 /* Length is stored in the first byte. */ 751 length = 1; 752 if (buffer_position(packet) + length <= end) { 753 length += buffer_current(packet)[length - 1]; 754 } 755 break; 756 case RDATA_WF_A: 757 length = sizeof(in_addr_t); 758 break; 759 case RDATA_WF_AAAA: 760 length = IP6ADDRLEN; 761 break; 762 case RDATA_WF_ILNP64: 763 length = IP6ADDRLEN/2; 764 break; 765 case RDATA_WF_EUI48: 766 length = EUI48ADDRLEN; 767 break; 768 case RDATA_WF_EUI64: 769 length = EUI64ADDRLEN; 770 break; 771 case RDATA_WF_BINARY: 772 /* Remaining RDATA is binary. */ 773 length = end - buffer_position(packet); 774 break; 775 case RDATA_WF_APL: 776 length = (sizeof(uint16_t) /* address family */ 777 + sizeof(uint8_t) /* prefix */ 778 + sizeof(uint8_t)); /* length */ 779 if (buffer_position(packet) + length <= end) { 780 /* Mask out negation bit. */ 781 length += (buffer_current(packet)[length - 1] 782 & APL_LENGTH_MASK); 783 } 784 break; 785 case RDATA_WF_IPSECGATEWAY: 786 switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ { 787 default: 788 case IPSECKEY_NOGATEWAY: 789 length = 0; 790 break; 791 case IPSECKEY_IP4: 792 length = IP4ADDRLEN; 793 break; 794 case IPSECKEY_IP6: 795 length = IP6ADDRLEN; 796 break; 797 case IPSECKEY_DNAME: 798 is_domain = 1; 799 is_normalized = 1; 800 is_wirestore = 1; 801 break; 802 } 803 break; 804 } 805 806 if (is_domain) { 807 const dname_type *dname; 808 809 if (!required && buffer_position(packet) == end) { 810 break; 811 } 812 813 dname = dname_make_from_packet( 814 temp_region, packet, 1, is_normalized); 815 if (!dname || buffer_position(packet) > end) { 816 /* Error in domain name. */ 817 region_destroy(temp_region); 818 return -1; 819 } 820 if(is_wirestore) { 821 temp_rdatas[i].data = (uint16_t *) region_alloc( 822 region, sizeof(uint16_t) + ((size_t)dname->name_size)); 823 temp_rdatas[i].data[0] = dname->name_size; 824 memcpy(temp_rdatas[i].data+1, dname_name(dname), 825 dname->name_size); 826 } else { 827 temp_rdatas[i].domain 828 = domain_table_insert(owners, dname); 829 temp_rdatas[i].domain->usage ++; 830 } 831 } else { 832 if (buffer_position(packet) + length > end) { 833 if (required) { 834 /* Truncated RDATA. */ 835 region_destroy(temp_region); 836 return -1; 837 } else { 838 break; 839 } 840 } 841 if (!required && buffer_position(packet) == end) { 842 break; 843 } 844 845 temp_rdatas[i].data = (uint16_t *) region_alloc( 846 region, sizeof(uint16_t) + length); 847 temp_rdatas[i].data[0] = length; 848 buffer_read(packet, temp_rdatas[i].data + 1, length); 849 } 850 } 851 852 if (buffer_position(packet) < end) { 853 /* Trailing garbage. */ 854 region_destroy(temp_region); 855 return -1; 856 } 857 858 *rdatas = (rdata_atom_type *) region_alloc_array_init( 859 region, temp_rdatas, i, sizeof(rdata_atom_type)); 860 region_destroy(temp_region); 861 return (ssize_t)i; 862 } 863 864 size_t 865 rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor, 866 size_t rdata_count, 867 rdata_atom_type *rdatas) 868 { 869 size_t result = 0; 870 size_t i; 871 for (i = 0; i < rdata_count; ++i) { 872 if (rdata_atom_is_domain(descriptor->type, i)) { 873 result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size; 874 } else { 875 result += rdata_atom_size(rdatas[i]); 876 } 877 } 878 return result; 879 } 880 881 int 882 rdata_atoms_to_unknown_string(buffer_type *output, 883 rrtype_descriptor_type *descriptor, 884 size_t rdata_count, 885 rdata_atom_type *rdatas) 886 { 887 size_t i; 888 size_t size = 889 rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas); 890 buffer_printf(output, " \\# %lu ", (unsigned long) size); 891 for (i = 0; i < rdata_count; ++i) { 892 if (rdata_atom_is_domain(descriptor->type, i)) { 893 const dname_type *dname = 894 domain_dname(rdata_atom_domain(rdatas[i])); 895 hex_to_string( 896 output, dname_name(dname), dname->name_size); 897 } else { 898 hex_to_string(output, rdata_atom_data(rdatas[i]), 899 rdata_atom_size(rdatas[i])); 900 } 901 } 902 return 1; 903 } 904 905 int 906 print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor, 907 rr_type *record) 908 { 909 size_t i; 910 size_t saved_position = buffer_position(output); 911 912 for (i = 0; i < record->rdata_count; ++i) { 913 if (i == 0) { 914 buffer_printf(output, "\t"); 915 } else if (descriptor->type == TYPE_SOA && i == 2) { 916 buffer_printf(output, " (\n\t\t"); 917 } else { 918 buffer_printf(output, " "); 919 } 920 if (!rdata_atom_to_string( 921 output, 922 (rdata_zoneformat_type) descriptor->zoneformat[i], 923 record->rdatas[i], record)) 924 { 925 buffer_set_position(output, saved_position); 926 return 0; 927 } 928 } 929 if (descriptor->type == TYPE_SOA) { 930 buffer_printf(output, " )"); 931 } 932 933 return 1; 934 } 935 936 937