1 /* 2 * rdata.c -- RDATA conversion functions. 3 * 4 * Copyright (c) 2001-2011, 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 { 252, "INDIRECT" }, 62 { 253, "PRIVATEDNS" }, 63 { 254, "PRIVATEOID" }, 64 { 0, NULL } 65 }; 66 67 typedef int (*rdata_to_string_type)(buffer_type *output, 68 rdata_atom_type rdata, 69 rr_type *rr); 70 71 static int 72 rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata, 73 rr_type* ATTR_UNUSED(rr)) 74 { 75 buffer_printf(output, 76 "%s", 77 dname_to_string(domain_dname(rdata_atom_domain(rdata)), 78 NULL)); 79 return 1; 80 } 81 82 static int 83 rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata, 84 rr_type* ATTR_UNUSED(rr)) 85 { 86 const uint8_t *data = rdata_atom_data(rdata); 87 size_t offset = 0; 88 uint8_t length = data[offset]; 89 size_t i; 90 91 while (length > 0) 92 { 93 if (offset) /* concat label */ 94 buffer_printf(output, "."); 95 96 for (i = 1; i <= length; ++i) { 97 uint8_t ch = data[i+offset]; 98 99 if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') { 100 buffer_printf(output, "\\%c", (char) ch); 101 } else if (!isgraph((int) ch)) { 102 buffer_printf(output, "\\%03u", (unsigned int) ch); 103 } else if (isprint((int) ch)) { 104 buffer_printf(output, "%c", (char) ch); 105 } else { 106 buffer_printf(output, "\\%03u", (unsigned int) ch); 107 } 108 } 109 /* next label */ 110 offset = offset+length+1; 111 length = data[offset]; 112 } 113 114 /* root label */ 115 buffer_printf(output, "."); 116 return 1; 117 } 118 119 static int 120 rdata_text_to_string(buffer_type *output, rdata_atom_type rdata, 121 rr_type* ATTR_UNUSED(rr)) 122 { 123 const uint8_t *data = rdata_atom_data(rdata); 124 uint8_t length = data[0]; 125 size_t i; 126 127 buffer_printf(output, "\""); 128 for (i = 1; i <= length; ++i) { 129 char ch = (char) data[i]; 130 if (isprint((int)ch)) { 131 if (ch == '"' || ch == '\\') { 132 buffer_printf(output, "\\"); 133 } 134 buffer_printf(output, "%c", ch); 135 } else { 136 buffer_printf(output, "\\%03u", (unsigned) data[i]); 137 } 138 } 139 buffer_printf(output, "\""); 140 return 1; 141 } 142 143 static int 144 rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata, 145 rr_type* ATTR_UNUSED(rr)) 146 { 147 uint16_t pos = 0; 148 const uint8_t *data = rdata_atom_data(rdata); 149 uint16_t length = rdata_atom_size(rdata); 150 size_t i; 151 152 while (pos < length && pos + data[pos] < length) { 153 buffer_printf(output, "\""); 154 for (i = 1; i <= data[pos]; ++i) { 155 char ch = (char) data[pos + i]; 156 if (isprint((int)ch)) { 157 if (ch == '"' || ch == '\\') { 158 buffer_printf(output, "\\"); 159 } 160 buffer_printf(output, "%c", ch); 161 } else { 162 buffer_printf(output, "\\%03u", (unsigned) data[pos+i]); 163 } 164 } 165 pos += data[pos]+1; 166 buffer_printf(output, pos < length?"\" ":"\""); 167 } 168 return 1; 169 } 170 171 static int 172 rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata, 173 rr_type* ATTR_UNUSED(rr)) 174 { 175 uint8_t data = *rdata_atom_data(rdata); 176 buffer_printf(output, "%lu", (unsigned long) data); 177 return 1; 178 } 179 180 static int 181 rdata_short_to_string(buffer_type *output, rdata_atom_type rdata, 182 rr_type* ATTR_UNUSED(rr)) 183 { 184 uint16_t data = read_uint16(rdata_atom_data(rdata)); 185 buffer_printf(output, "%lu", (unsigned long) data); 186 return 1; 187 } 188 189 static int 190 rdata_long_to_string(buffer_type *output, rdata_atom_type rdata, 191 rr_type* ATTR_UNUSED(rr)) 192 { 193 uint32_t data = read_uint32(rdata_atom_data(rdata)); 194 buffer_printf(output, "%lu", (unsigned long) data); 195 return 1; 196 } 197 198 static int 199 rdata_a_to_string(buffer_type *output, rdata_atom_type rdata, 200 rr_type* ATTR_UNUSED(rr)) 201 { 202 int result = 0; 203 char str[200]; 204 if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) { 205 buffer_printf(output, "%s", str); 206 result = 1; 207 } 208 return result; 209 } 210 211 static int 212 rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata, 213 rr_type* ATTR_UNUSED(rr)) 214 { 215 int result = 0; 216 char str[200]; 217 if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) { 218 buffer_printf(output, "%s", str); 219 result = 1; 220 } 221 return result; 222 } 223 224 static int 225 rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata, 226 rr_type* ATTR_UNUSED(rr)) 227 { 228 uint16_t type = read_uint16(rdata_atom_data(rdata)); 229 buffer_printf(output, "%s", rrtype_to_string(type)); 230 return 1; 231 } 232 233 static int 234 rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata, 235 rr_type* ATTR_UNUSED(rr)) 236 { 237 uint8_t id = *rdata_atom_data(rdata); 238 buffer_printf(output, "%u", (unsigned) id); 239 return 1; 240 } 241 242 static int 243 rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata, 244 rr_type* ATTR_UNUSED(rr)) 245 { 246 uint16_t id = read_uint16(rdata_atom_data(rdata)); 247 lookup_table_type *type 248 = lookup_by_id(dns_certificate_types, id); 249 if (type) { 250 buffer_printf(output, "%s", type->name); 251 } else { 252 buffer_printf(output, "%u", (unsigned) id); 253 } 254 return 1; 255 } 256 257 static int 258 rdata_period_to_string(buffer_type *output, rdata_atom_type rdata, 259 rr_type* ATTR_UNUSED(rr)) 260 { 261 uint32_t period = read_uint32(rdata_atom_data(rdata)); 262 buffer_printf(output, "%lu", (unsigned long) period); 263 return 1; 264 } 265 266 static int 267 rdata_time_to_string(buffer_type *output, rdata_atom_type rdata, 268 rr_type* ATTR_UNUSED(rr)) 269 { 270 int result = 0; 271 time_t time = (time_t) read_uint32(rdata_atom_data(rdata)); 272 struct tm *tm = gmtime(&time); 273 char buf[15]; 274 if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) { 275 buffer_printf(output, "%s", buf); 276 result = 1; 277 } 278 return result; 279 } 280 281 static int 282 rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata, 283 rr_type* ATTR_UNUSED(rr)) 284 { 285 int length; 286 size_t size = rdata_atom_size(rdata); 287 if(size == 0) { 288 buffer_write(output, "-", 1); 289 return 1; 290 } 291 size -= 1; /* remove length byte from count */ 292 buffer_reserve(output, size * 2 + 1); 293 length = b32_ntop(rdata_atom_data(rdata)+1, size, 294 (char *) buffer_current(output), size * 2); 295 if (length > 0) { 296 buffer_skip(output, length); 297 } 298 return length != -1; 299 } 300 301 static int 302 rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata, 303 rr_type* ATTR_UNUSED(rr)) 304 { 305 int length; 306 size_t size = rdata_atom_size(rdata); 307 if(size == 0) 308 return 1; 309 buffer_reserve(output, size * 2 + 1); 310 length = b64_ntop(rdata_atom_data(rdata), size, 311 (char *) buffer_current(output), size * 2); 312 if (length > 0) { 313 buffer_skip(output, length); 314 } 315 return length != -1; 316 } 317 318 static void 319 hex_to_string(buffer_type *output, const uint8_t *data, size_t size) 320 { 321 static const char hexdigits[] = { 322 '0', '1', '2', '3', '4', '5', '6', '7', 323 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 324 }; 325 size_t i; 326 327 buffer_reserve(output, size * 2); 328 for (i = 0; i < size; ++i) { 329 uint8_t octet = *data++; 330 buffer_write_u8(output, hexdigits[octet >> 4]); 331 buffer_write_u8(output, hexdigits[octet & 0x0f]); 332 } 333 } 334 335 static int 336 rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata, 337 rr_type* ATTR_UNUSED(rr)) 338 { 339 hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata)); 340 return 1; 341 } 342 343 static int 344 rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata, 345 rr_type* ATTR_UNUSED(rr)) 346 { 347 if(rdata_atom_size(rdata) <= 1) { 348 /* NSEC3 salt hex can be empty */ 349 buffer_printf(output, "-"); 350 return 1; 351 } 352 hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1); 353 return 1; 354 } 355 356 static int 357 rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata, 358 rr_type* ATTR_UNUSED(rr)) 359 { 360 buffer_printf(output, "0x"); 361 hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata)); 362 return 1; 363 } 364 365 static int 366 rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata, 367 rr_type* ATTR_UNUSED(rr)) 368 { 369 int result = 0; 370 buffer_type packet; 371 372 buffer_create_from( 373 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 374 375 if (buffer_available(&packet, 4)) { 376 uint16_t address_family = buffer_read_u16(&packet); 377 uint8_t prefix = buffer_read_u8(&packet); 378 uint8_t length = buffer_read_u8(&packet); 379 int negated = length & APL_NEGATION_MASK; 380 int af = -1; 381 382 length &= APL_LENGTH_MASK; 383 switch (address_family) { 384 case 1: af = AF_INET; break; 385 case 2: af = AF_INET6; break; 386 } 387 if (af != -1 && buffer_available(&packet, length)) { 388 char text_address[1000]; 389 uint8_t address[128]; 390 memset(address, 0, sizeof(address)); 391 buffer_read(&packet, address, length); 392 if (inet_ntop(af, address, text_address, sizeof(text_address))) { 393 buffer_printf(output, "%s%d:%s/%d", 394 negated ? "!" : "", 395 (int) address_family, 396 text_address, 397 (int) prefix); 398 result = 1; 399 } 400 } 401 } 402 return result; 403 } 404 405 static int 406 rdata_services_to_string(buffer_type *output, rdata_atom_type rdata, 407 rr_type* ATTR_UNUSED(rr)) 408 { 409 int result = 0; 410 buffer_type packet; 411 412 buffer_create_from( 413 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 414 415 if (buffer_available(&packet, 1)) { 416 uint8_t protocol_number = buffer_read_u8(&packet); 417 ssize_t bitmap_size = buffer_remaining(&packet); 418 uint8_t *bitmap = buffer_current(&packet); 419 struct protoent *proto = getprotobynumber(protocol_number); 420 421 if (proto) { 422 int i; 423 424 buffer_printf(output, "%s", proto->p_name); 425 426 for (i = 0; i < bitmap_size * 8; ++i) { 427 if (get_bit(bitmap, i)) { 428 struct servent *service = getservbyport((int)htons(i), proto->p_name); 429 if (service) { 430 buffer_printf(output, " %s", service->s_name); 431 } else { 432 buffer_printf(output, " %d", i); 433 } 434 } 435 } 436 buffer_skip(&packet, bitmap_size); 437 result = 1; 438 } 439 } 440 return result; 441 } 442 443 static int 444 rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr) 445 { 446 int gateway_type = rdata_atom_data(rr->rdatas[1])[0]; 447 switch(gateway_type) { 448 case IPSECKEY_NOGATEWAY: 449 buffer_printf(output, "."); 450 break; 451 case IPSECKEY_IP4: 452 rdata_a_to_string(output, rdata, rr); 453 break; 454 case IPSECKEY_IP6: 455 rdata_aaaa_to_string(output, rdata, rr); 456 break; 457 case IPSECKEY_DNAME: 458 { 459 region_type* temp = region_create(xalloc, free); 460 const dname_type* d = dname_make(temp, 461 rdata_atom_data(rdata), 0); 462 if(!d) { 463 region_destroy(temp); 464 return 0; 465 } 466 buffer_printf(output, "%s", dname_to_string(d, NULL)); 467 region_destroy(temp); 468 } 469 break; 470 default: 471 return 0; 472 } 473 return 1; 474 } 475 476 static int 477 rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata, 478 rr_type* ATTR_UNUSED(rr)) 479 { 480 size_t i; 481 uint8_t *bitmap = rdata_atom_data(rdata); 482 size_t bitmap_size = rdata_atom_size(rdata); 483 484 for (i = 0; i < bitmap_size * 8; ++i) { 485 if (get_bit(bitmap, i)) { 486 buffer_printf(output, "%s ", rrtype_to_string(i)); 487 } 488 } 489 490 buffer_skip(output, -1); 491 492 return 1; 493 } 494 495 static int 496 rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata, 497 rr_type* ATTR_UNUSED(rr)) 498 { 499 size_t saved_position = buffer_position(output); 500 buffer_type packet; 501 int insert_space = 0; 502 503 buffer_create_from( 504 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 505 506 while (buffer_available(&packet, 2)) { 507 uint8_t window = buffer_read_u8(&packet); 508 uint8_t bitmap_size = buffer_read_u8(&packet); 509 uint8_t *bitmap = buffer_current(&packet); 510 int i; 511 512 if (!buffer_available(&packet, bitmap_size)) { 513 buffer_set_position(output, saved_position); 514 return 0; 515 } 516 517 for (i = 0; i < bitmap_size * 8; ++i) { 518 if (get_bit(bitmap, i)) { 519 buffer_printf(output, 520 "%s%s", 521 insert_space ? " " : "", 522 rrtype_to_string( 523 window * 256 + i)); 524 insert_space = 1; 525 } 526 } 527 buffer_skip(&packet, bitmap_size); 528 } 529 530 return 1; 531 } 532 533 static int 534 rdata_loc_to_string(buffer_type *ATTR_UNUSED(output), 535 rdata_atom_type ATTR_UNUSED(rdata), 536 rr_type* ATTR_UNUSED(rr)) 537 { 538 /* 539 * Returning 0 forces the record to be printed in unknown 540 * format. 541 */ 542 return 0; 543 } 544 545 static int 546 rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata, 547 rr_type* ATTR_UNUSED(rr)) 548 { 549 uint16_t size = rdata_atom_size(rdata); 550 buffer_printf(output, "\\# %lu ", (unsigned long) size); 551 hex_to_string(output, rdata_atom_data(rdata), size); 552 return 1; 553 } 554 555 static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = { 556 rdata_dname_to_string, 557 rdata_dns_name_to_string, 558 rdata_text_to_string, 559 rdata_texts_to_string, 560 rdata_byte_to_string, 561 rdata_short_to_string, 562 rdata_long_to_string, 563 rdata_a_to_string, 564 rdata_aaaa_to_string, 565 rdata_rrtype_to_string, 566 rdata_algorithm_to_string, 567 rdata_certificate_type_to_string, 568 rdata_period_to_string, 569 rdata_time_to_string, 570 rdata_base64_to_string, 571 rdata_base32_to_string, 572 rdata_hex_to_string, 573 rdata_hexlen_to_string, 574 rdata_nsap_to_string, 575 rdata_apl_to_string, 576 rdata_ipsecgateway_to_string, 577 rdata_services_to_string, 578 rdata_nxt_to_string, 579 rdata_nsec_to_string, 580 rdata_loc_to_string, 581 rdata_unknown_to_string 582 }; 583 584 int 585 rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type, 586 rdata_atom_type rdata, rr_type* record) 587 { 588 return rdata_to_string_table[type](output, rdata, record); 589 } 590 591 ssize_t 592 rdata_wireformat_to_rdata_atoms(region_type *region, 593 domain_table_type *owners, 594 uint16_t rrtype, 595 uint16_t data_size, 596 buffer_type *packet, 597 rdata_atom_type **rdatas) 598 { 599 size_t end = buffer_position(packet) + data_size; 600 size_t i; 601 rdata_atom_type temp_rdatas[MAXRDATALEN]; 602 rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype); 603 region_type *temp_region; 604 605 assert(descriptor->maximum <= MAXRDATALEN); 606 607 if (!buffer_available(packet, data_size)) { 608 return -1; 609 } 610 611 temp_region = region_create(xalloc, free); 612 613 for (i = 0; i < descriptor->maximum; ++i) { 614 int is_domain = 0; 615 int is_normalized = 0; 616 int is_wirestore = 0; 617 size_t length = 0; 618 int required = i < descriptor->minimum; 619 620 switch (rdata_atom_wireformat_type(rrtype, i)) { 621 case RDATA_WF_COMPRESSED_DNAME: 622 case RDATA_WF_UNCOMPRESSED_DNAME: 623 is_domain = 1; 624 is_normalized = 1; 625 break; 626 case RDATA_WF_LITERAL_DNAME: 627 is_domain = 1; 628 is_wirestore = 1; 629 break; 630 case RDATA_WF_BYTE: 631 length = sizeof(uint8_t); 632 break; 633 case RDATA_WF_SHORT: 634 length = sizeof(uint16_t); 635 break; 636 case RDATA_WF_LONG: 637 length = sizeof(uint32_t); 638 break; 639 case RDATA_WF_TEXTS: 640 length = data_size; 641 break; 642 case RDATA_WF_TEXT: 643 case RDATA_WF_BINARYWITHLENGTH: 644 /* Length is stored in the first byte. */ 645 length = 1; 646 if (buffer_position(packet) + length <= end) { 647 length += buffer_current(packet)[length - 1]; 648 } 649 break; 650 case RDATA_WF_A: 651 length = sizeof(in_addr_t); 652 break; 653 case RDATA_WF_AAAA: 654 length = IP6ADDRLEN; 655 break; 656 case RDATA_WF_BINARY: 657 /* Remaining RDATA is binary. */ 658 length = end - buffer_position(packet); 659 break; 660 case RDATA_WF_APL: 661 length = (sizeof(uint16_t) /* address family */ 662 + sizeof(uint8_t) /* prefix */ 663 + sizeof(uint8_t)); /* length */ 664 if (buffer_position(packet) + length <= end) { 665 /* Mask out negation bit. */ 666 length += (buffer_current(packet)[length - 1] 667 & APL_LENGTH_MASK); 668 } 669 break; 670 case RDATA_WF_IPSECGATEWAY: 671 switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ { 672 default: 673 case IPSECKEY_NOGATEWAY: 674 length = 0; 675 break; 676 case IPSECKEY_IP4: 677 length = IP4ADDRLEN; 678 break; 679 case IPSECKEY_IP6: 680 length = IP6ADDRLEN; 681 break; 682 case IPSECKEY_DNAME: 683 is_domain = 1; 684 is_normalized = 1; 685 is_wirestore = 1; 686 break; 687 } 688 break; 689 } 690 691 if (is_domain) { 692 const dname_type *dname; 693 694 if (!required && buffer_position(packet) == end) { 695 break; 696 } 697 698 dname = dname_make_from_packet( 699 temp_region, packet, 1, is_normalized); 700 if (!dname || buffer_position(packet) > end) { 701 /* Error in domain name. */ 702 region_destroy(temp_region); 703 return -1; 704 } 705 if(is_wirestore) { 706 temp_rdatas[i].data = (uint16_t *) region_alloc( 707 region, sizeof(uint16_t) + dname->name_size); 708 temp_rdatas[i].data[0] = dname->name_size; 709 memcpy(temp_rdatas[i].data+1, dname_name(dname), 710 dname->name_size); 711 } else 712 temp_rdatas[i].domain 713 = domain_table_insert(owners, dname); 714 } else { 715 if (buffer_position(packet) + length > end) { 716 if (required) { 717 /* Truncated RDATA. */ 718 region_destroy(temp_region); 719 return -1; 720 } else { 721 break; 722 } 723 } 724 if (!required && buffer_position(packet) == end) { 725 break; 726 } 727 728 temp_rdatas[i].data = (uint16_t *) region_alloc( 729 region, sizeof(uint16_t) + length); 730 temp_rdatas[i].data[0] = length; 731 buffer_read(packet, temp_rdatas[i].data + 1, length); 732 } 733 } 734 735 if (buffer_position(packet) < end) { 736 /* Trailing garbage. */ 737 region_destroy(temp_region); 738 return -1; 739 } 740 741 *rdatas = (rdata_atom_type *) region_alloc_init( 742 region, temp_rdatas, i * sizeof(rdata_atom_type)); 743 region_destroy(temp_region); 744 return (ssize_t)i; 745 } 746 747 size_t 748 rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor, 749 size_t rdata_count, 750 rdata_atom_type *rdatas) 751 { 752 size_t result = 0; 753 size_t i; 754 for (i = 0; i < rdata_count; ++i) { 755 if (rdata_atom_is_domain(descriptor->type, i)) { 756 result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size; 757 } else { 758 result += rdata_atom_size(rdatas[i]); 759 } 760 } 761 return result; 762 } 763 764 int 765 rdata_atoms_to_unknown_string(buffer_type *output, 766 rrtype_descriptor_type *descriptor, 767 size_t rdata_count, 768 rdata_atom_type *rdatas) 769 { 770 size_t i; 771 size_t size = 772 rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas); 773 buffer_printf(output, " \\# %lu ", (unsigned long) size); 774 for (i = 0; i < rdata_count; ++i) { 775 if (rdata_atom_is_domain(descriptor->type, i)) { 776 const dname_type *dname = 777 domain_dname(rdata_atom_domain(rdatas[i])); 778 hex_to_string( 779 output, dname_name(dname), dname->name_size); 780 } else { 781 hex_to_string(output, rdata_atom_data(rdatas[i]), 782 rdata_atom_size(rdatas[i])); 783 } 784 } 785 return 1; 786 } 787 788 int 789 print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor, 790 rr_type *record) 791 { 792 size_t i; 793 size_t saved_position = buffer_position(output); 794 795 for (i = 0; i < record->rdata_count; ++i) { 796 if (i == 0) { 797 buffer_printf(output, "\t"); 798 } else if (descriptor->type == TYPE_SOA && i == 2) { 799 buffer_printf(output, " (\n\t\t"); 800 } else { 801 buffer_printf(output, " "); 802 } 803 if (!rdata_atom_to_string( 804 output, 805 (rdata_zoneformat_type) descriptor->zoneformat[i], 806 record->rdatas[i], record)) 807 { 808 buffer_set_position(output, saved_position); 809 return 0; 810 } 811 } 812 if (descriptor->type == TYPE_SOA) { 813 buffer_printf(output, " )"); 814 } 815 816 return 1; 817 } 818 819 820