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