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. */ 28lookup_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. */ 48lookup_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 69const char *svcparamkey_strs[] = { 70 "mandatory", "alpn", "no-default-alpn", "port", 71 "ipv4hint", "ech", "ipv6hint", "dohpath" 72 }; 73 74typedef int (*rdata_to_string_type)(buffer_type *output, 75 rdata_atom_type rdata, 76 rr_type *rr); 77 78static int 79rdata_dname_to_string(buffer_type *output, rdata_atom_type rdata, 80 rr_type* ATTR_UNUSED(rr)) 81{ 82 buffer_printf(output, 83 "%s", 84 dname_to_string(domain_dname(rdata_atom_domain(rdata)), 85 NULL)); 86 return 1; 87} 88 89static int 90rdata_dns_name_to_string(buffer_type *output, rdata_atom_type rdata, 91 rr_type* ATTR_UNUSED(rr)) 92{ 93 const uint8_t *data = rdata_atom_data(rdata); 94 size_t offset = 0; 95 uint8_t length = data[offset]; 96 size_t i; 97 98 while (length > 0) 99 { 100 if (offset) /* concat label */ 101 buffer_printf(output, "."); 102 103 for (i = 1; i <= length; ++i) { 104 uint8_t ch = data[i+offset]; 105 106 if (ch=='.' || ch==';' || ch=='(' || ch==')' || ch=='\\') { 107 buffer_printf(output, "\\%c", (char) ch); 108 } else if (!isgraph((unsigned char) ch)) { 109 buffer_printf(output, "\\%03u", (unsigned int) ch); 110 } else if (isprint((unsigned char) ch)) { 111 buffer_printf(output, "%c", (char) ch); 112 } else { 113 buffer_printf(output, "\\%03u", (unsigned int) ch); 114 } 115 } 116 /* next label */ 117 offset = offset+length+1; 118 length = data[offset]; 119 } 120 121 /* root label */ 122 buffer_printf(output, "."); 123 return 1; 124} 125 126static int 127rdata_text_to_string(buffer_type *output, rdata_atom_type rdata, 128 rr_type* ATTR_UNUSED(rr)) 129{ 130 const uint8_t *data = rdata_atom_data(rdata); 131 uint8_t length = data[0]; 132 size_t i; 133 134 buffer_printf(output, "\""); 135 for (i = 1; i <= length; ++i) { 136 char ch = (char) data[i]; 137 if (isprint((unsigned char)ch)) { 138 if (ch == '"' || ch == '\\') { 139 buffer_printf(output, "\\"); 140 } 141 buffer_printf(output, "%c", ch); 142 } else { 143 buffer_printf(output, "\\%03u", (unsigned) data[i]); 144 } 145 } 146 buffer_printf(output, "\""); 147 return 1; 148} 149 150static int 151rdata_texts_to_string(buffer_type *output, rdata_atom_type rdata, 152 rr_type* ATTR_UNUSED(rr)) 153{ 154 uint16_t pos = 0; 155 const uint8_t *data = rdata_atom_data(rdata); 156 uint16_t length = rdata_atom_size(rdata); 157 size_t i; 158 159 while (pos < length && pos + data[pos] < length) { 160 buffer_printf(output, "\""); 161 for (i = 1; i <= data[pos]; ++i) { 162 char ch = (char) data[pos + i]; 163 if (isprint((unsigned char)ch)) { 164 if (ch == '"' || ch == '\\') { 165 buffer_printf(output, "\\"); 166 } 167 buffer_printf(output, "%c", ch); 168 } else { 169 buffer_printf(output, "\\%03u", (unsigned) data[pos+i]); 170 } 171 } 172 pos += data[pos]+1; 173 buffer_printf(output, pos < length?"\" ":"\""); 174 } 175 return 1; 176} 177 178static int 179rdata_long_text_to_string(buffer_type *output, rdata_atom_type rdata, 180 rr_type* ATTR_UNUSED(rr)) 181{ 182 const uint8_t *data = rdata_atom_data(rdata); 183 uint16_t length = rdata_atom_size(rdata); 184 size_t i; 185 186 buffer_printf(output, "\""); 187 for (i = 0; i < length; ++i) { 188 char ch = (char) data[i]; 189 if (isprint((unsigned char)ch)) { 190 if (ch == '"' || ch == '\\') { 191 buffer_printf(output, "\\"); 192 } 193 buffer_printf(output, "%c", ch); 194 } else { 195 buffer_printf(output, "\\%03u", (unsigned) data[i]); 196 } 197 } 198 buffer_printf(output, "\""); 199 return 1; 200} 201 202static int 203rdata_tag_to_string(buffer_type *output, rdata_atom_type rdata, 204 rr_type* ATTR_UNUSED(rr)) 205{ 206 const uint8_t *data = rdata_atom_data(rdata); 207 uint8_t length = data[0]; 208 size_t i; 209 for (i = 1; i <= length; ++i) { 210 char ch = (char) data[i]; 211 if (isdigit((unsigned char)ch) || islower((unsigned char)ch)) 212 buffer_printf(output, "%c", ch); 213 else return 0; 214 } 215 return 1; 216} 217 218static int 219rdata_byte_to_string(buffer_type *output, rdata_atom_type rdata, 220 rr_type* ATTR_UNUSED(rr)) 221{ 222 uint8_t data = *rdata_atom_data(rdata); 223 buffer_printf(output, "%lu", (unsigned long) data); 224 return 1; 225} 226 227static int 228rdata_short_to_string(buffer_type *output, rdata_atom_type rdata, 229 rr_type* ATTR_UNUSED(rr)) 230{ 231 uint16_t data = read_uint16(rdata_atom_data(rdata)); 232 buffer_printf(output, "%lu", (unsigned long) data); 233 return 1; 234} 235 236static int 237rdata_long_to_string(buffer_type *output, rdata_atom_type rdata, 238 rr_type* ATTR_UNUSED(rr)) 239{ 240 uint32_t data = read_uint32(rdata_atom_data(rdata)); 241 buffer_printf(output, "%lu", (unsigned long) data); 242 return 1; 243} 244 245static int 246rdata_a_to_string(buffer_type *output, rdata_atom_type rdata, 247 rr_type* ATTR_UNUSED(rr)) 248{ 249 int result = 0; 250 char str[200]; 251 if (inet_ntop(AF_INET, rdata_atom_data(rdata), str, sizeof(str))) { 252 buffer_printf(output, "%s", str); 253 result = 1; 254 } 255 return result; 256} 257 258static int 259rdata_aaaa_to_string(buffer_type *output, rdata_atom_type rdata, 260 rr_type* ATTR_UNUSED(rr)) 261{ 262 int result = 0; 263 char str[200]; 264 if (inet_ntop(AF_INET6, rdata_atom_data(rdata), str, sizeof(str))) { 265 buffer_printf(output, "%s", str); 266 result = 1; 267 } 268 return result; 269} 270 271static int 272rdata_ilnp64_to_string(buffer_type *output, rdata_atom_type rdata, 273 rr_type* ATTR_UNUSED(rr)) 274{ 275 uint8_t* data = rdata_atom_data(rdata); 276 uint16_t a1 = read_uint16(data); 277 uint16_t a2 = read_uint16(data+2); 278 uint16_t a3 = read_uint16(data+4); 279 uint16_t a4 = read_uint16(data+6); 280 281 buffer_printf(output, "%.4x:%.4x:%.4x:%.4x", a1, a2, a3, a4); 282 return 1; 283} 284 285static int 286rdata_eui48_to_string(buffer_type *output, rdata_atom_type rdata, 287 rr_type* ATTR_UNUSED(rr)) 288{ 289 uint8_t* data = rdata_atom_data(rdata); 290 uint8_t a1 = data[0]; 291 uint8_t a2 = data[1]; 292 uint8_t a3 = data[2]; 293 uint8_t a4 = data[3]; 294 uint8_t a5 = data[4]; 295 uint8_t a6 = data[5]; 296 297 buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 298 a1, a2, a3, a4, a5, a6); 299 return 1; 300} 301 302static int 303rdata_eui64_to_string(buffer_type *output, rdata_atom_type rdata, 304 rr_type* ATTR_UNUSED(rr)) 305{ 306 uint8_t* data = rdata_atom_data(rdata); 307 uint8_t a1 = data[0]; 308 uint8_t a2 = data[1]; 309 uint8_t a3 = data[2]; 310 uint8_t a4 = data[3]; 311 uint8_t a5 = data[4]; 312 uint8_t a6 = data[5]; 313 uint8_t a7 = data[6]; 314 uint8_t a8 = data[7]; 315 316 buffer_printf(output, "%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x-%.2x", 317 a1, a2, a3, a4, a5, a6, a7, a8); 318 return 1; 319} 320 321static int 322rdata_rrtype_to_string(buffer_type *output, rdata_atom_type rdata, 323 rr_type* ATTR_UNUSED(rr)) 324{ 325 uint16_t type = read_uint16(rdata_atom_data(rdata)); 326 buffer_printf(output, "%s", rrtype_to_string(type)); 327 return 1; 328} 329 330static int 331rdata_algorithm_to_string(buffer_type *output, rdata_atom_type rdata, 332 rr_type* ATTR_UNUSED(rr)) 333{ 334 uint8_t id = *rdata_atom_data(rdata); 335 buffer_printf(output, "%u", (unsigned) id); 336 return 1; 337} 338 339static int 340rdata_certificate_type_to_string(buffer_type *output, rdata_atom_type rdata, 341 rr_type* ATTR_UNUSED(rr)) 342{ 343 uint16_t id = read_uint16(rdata_atom_data(rdata)); 344 lookup_table_type *type 345 = lookup_by_id(dns_certificate_types, id); 346 if (type) { 347 buffer_printf(output, "%s", type->name); 348 } else { 349 buffer_printf(output, "%u", (unsigned) id); 350 } 351 return 1; 352} 353 354static int 355rdata_period_to_string(buffer_type *output, rdata_atom_type rdata, 356 rr_type* ATTR_UNUSED(rr)) 357{ 358 uint32_t period = read_uint32(rdata_atom_data(rdata)); 359 buffer_printf(output, "%lu", (unsigned long) period); 360 return 1; 361} 362 363static int 364rdata_time_to_string(buffer_type *output, rdata_atom_type rdata, 365 rr_type* ATTR_UNUSED(rr)) 366{ 367 int result = 0; 368 time_t time = (time_t) read_uint32(rdata_atom_data(rdata)); 369 struct tm *tm = gmtime(&time); 370 char buf[15]; 371 if (strftime(buf, sizeof(buf), "%Y%m%d%H%M%S", tm)) { 372 buffer_printf(output, "%s", buf); 373 result = 1; 374 } 375 return result; 376} 377 378static int 379rdata_base32_to_string(buffer_type *output, rdata_atom_type rdata, 380 rr_type* ATTR_UNUSED(rr)) 381{ 382 int length; 383 size_t size = rdata_atom_size(rdata); 384 if(size == 0) { 385 buffer_write(output, "-", 1); 386 return 1; 387 } 388 size -= 1; /* remove length byte from count */ 389 buffer_reserve(output, size * 2 + 1); 390 length = b32_ntop(rdata_atom_data(rdata)+1, size, 391 (char *) buffer_current(output), size * 2); 392 if (length > 0) { 393 buffer_skip(output, length); 394 } 395 return length != -1; 396} 397 398static int 399rdata_base64_to_string(buffer_type *output, rdata_atom_type rdata, 400 rr_type* ATTR_UNUSED(rr)) 401{ 402 int length; 403 size_t size = rdata_atom_size(rdata); 404 if(size == 0) { 405 /* single zero represents empty buffer */ 406 buffer_write(output, "0", 1); 407 return 1; 408 } 409 buffer_reserve(output, size * 2 + 1); 410 length = b64_ntop(rdata_atom_data(rdata), size, 411 (char *) buffer_current(output), size * 2); 412 if (length > 0) { 413 buffer_skip(output, length); 414 } 415 return length != -1; 416} 417 418static void 419hex_to_string(buffer_type *output, const uint8_t *data, size_t size) 420{ 421 static const char hexdigits[] = { 422 '0', '1', '2', '3', '4', '5', '6', '7', 423 '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' 424 }; 425 size_t i; 426 427 buffer_reserve(output, size * 2); 428 for (i = 0; i < size; ++i) { 429 uint8_t octet = *data++; 430 buffer_write_u8(output, hexdigits[octet >> 4]); 431 buffer_write_u8(output, hexdigits[octet & 0x0f]); 432 } 433} 434 435static int 436rdata_hex_to_string(buffer_type *output, rdata_atom_type rdata, 437 rr_type* ATTR_UNUSED(rr)) 438{ 439 if(rdata_atom_size(rdata) == 0) { 440 /* single zero represents empty buffer, such as CDS deletes */ 441 buffer_printf(output, "0"); 442 } else { 443 hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata)); 444 } 445 return 1; 446} 447 448static int 449rdata_hexlen_to_string(buffer_type *output, rdata_atom_type rdata, 450 rr_type* ATTR_UNUSED(rr)) 451{ 452 if(rdata_atom_size(rdata) <= 1) { 453 /* NSEC3 salt hex can be empty */ 454 buffer_printf(output, "-"); 455 return 1; 456 } 457 hex_to_string(output, rdata_atom_data(rdata)+1, rdata_atom_size(rdata)-1); 458 return 1; 459} 460 461static int 462rdata_nsap_to_string(buffer_type *output, rdata_atom_type rdata, 463 rr_type* ATTR_UNUSED(rr)) 464{ 465 buffer_printf(output, "0x"); 466 hex_to_string(output, rdata_atom_data(rdata), rdata_atom_size(rdata)); 467 return 1; 468} 469 470static int 471rdata_apl_to_string(buffer_type *output, rdata_atom_type rdata, 472 rr_type* ATTR_UNUSED(rr)) 473{ 474 int result = 0; 475 buffer_type packet; 476 477 buffer_create_from( 478 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 479 480 if (buffer_available(&packet, 4)) { 481 uint16_t address_family = buffer_read_u16(&packet); 482 uint8_t prefix = buffer_read_u8(&packet); 483 uint8_t length = buffer_read_u8(&packet); 484 int negated = length & APL_NEGATION_MASK; 485 int af = -1; 486 487 length &= APL_LENGTH_MASK; 488 switch (address_family) { 489 case 1: af = AF_INET; break; 490 case 2: af = AF_INET6; break; 491 } 492 if (af != -1 && buffer_available(&packet, length)) { 493 char text_address[1000]; 494 uint8_t address[128]; 495 memset(address, 0, sizeof(address)); 496 buffer_read(&packet, address, length); 497 if (inet_ntop(af, address, text_address, sizeof(text_address))) { 498 buffer_printf(output, "%s%d:%s/%d", 499 negated ? "!" : "", 500 (int) address_family, 501 text_address, 502 (int) prefix); 503 result = 1; 504 } 505 } 506 } 507 return result; 508} 509 510static int 511rdata_services_to_string(buffer_type *output, rdata_atom_type rdata, 512 rr_type* ATTR_UNUSED(rr)) 513{ 514 int result = 0; 515 buffer_type packet; 516 517 buffer_create_from( 518 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 519 520 if (buffer_available(&packet, 1)) { 521 uint8_t protocol_number = buffer_read_u8(&packet); 522 ssize_t bitmap_size = buffer_remaining(&packet); 523 uint8_t *bitmap = buffer_current(&packet); 524 struct protoent *proto = getprotobynumber(protocol_number); 525 526 if (proto) { 527 int i; 528 529 buffer_printf(output, "%s", proto->p_name); 530 531 for (i = 0; i < bitmap_size * 8; ++i) { 532 if (get_bit(bitmap, i)) { 533 struct servent *service = getservbyport((int)htons(i), proto->p_name); 534 if (service) { 535 buffer_printf(output, " %s", service->s_name); 536 } else { 537 buffer_printf(output, " %d", i); 538 } 539 } 540 } 541 buffer_skip(&packet, bitmap_size); 542 result = 1; 543 } 544 } 545 return result; 546} 547 548static int 549rdata_ipsecgateway_to_string(buffer_type *output, rdata_atom_type rdata, rr_type* rr) 550{ 551 int gateway_type = rdata_atom_data(rr->rdatas[1])[0]; 552 switch(gateway_type) { 553 case IPSECKEY_NOGATEWAY: 554 buffer_printf(output, "."); 555 break; 556 case IPSECKEY_IP4: 557 rdata_a_to_string(output, rdata, rr); 558 break; 559 case IPSECKEY_IP6: 560 rdata_aaaa_to_string(output, rdata, rr); 561 break; 562 case IPSECKEY_DNAME: 563 { 564 region_type* temp = region_create(xalloc, free); 565 const dname_type* d = dname_make(temp, 566 rdata_atom_data(rdata), 0); 567 if(!d) { 568 region_destroy(temp); 569 return 0; 570 } 571 buffer_printf(output, "%s", dname_to_string(d, NULL)); 572 region_destroy(temp); 573 } 574 break; 575 default: 576 return 0; 577 } 578 return 1; 579} 580 581static int 582rdata_nxt_to_string(buffer_type *output, rdata_atom_type rdata, 583 rr_type* ATTR_UNUSED(rr)) 584{ 585 size_t i; 586 uint8_t *bitmap = rdata_atom_data(rdata); 587 size_t bitmap_size = rdata_atom_size(rdata); 588 589 for (i = 0; i < bitmap_size * 8; ++i) { 590 if (get_bit(bitmap, i)) { 591 buffer_printf(output, "%s ", rrtype_to_string(i)); 592 } 593 } 594 595 buffer_skip(output, -1); 596 597 return 1; 598} 599 600static int 601rdata_nsec_to_string(buffer_type *output, rdata_atom_type rdata, 602 rr_type* ATTR_UNUSED(rr)) 603{ 604 size_t saved_position = buffer_position(output); 605 buffer_type packet; 606 int insert_space = 0; 607 608 buffer_create_from( 609 &packet, rdata_atom_data(rdata), rdata_atom_size(rdata)); 610 611 while (buffer_available(&packet, 2)) { 612 uint8_t window = buffer_read_u8(&packet); 613 uint8_t bitmap_size = buffer_read_u8(&packet); 614 uint8_t *bitmap = buffer_current(&packet); 615 int i; 616 617 if (!buffer_available(&packet, bitmap_size)) { 618 buffer_set_position(output, saved_position); 619 return 0; 620 } 621 622 for (i = 0; i < bitmap_size * 8; ++i) { 623 if (get_bit(bitmap, i)) { 624 buffer_printf(output, 625 "%s%s", 626 insert_space ? " " : "", 627 rrtype_to_string( 628 window * 256 + i)); 629 insert_space = 1; 630 } 631 } 632 buffer_skip(&packet, bitmap_size); 633 } 634 635 return 1; 636} 637 638static int 639rdata_loc_to_string(buffer_type *ATTR_UNUSED(output), 640 rdata_atom_type ATTR_UNUSED(rdata), 641 rr_type* ATTR_UNUSED(rr)) 642{ 643 /* 644 * Returning 0 forces the record to be printed in unknown 645 * format. 646 */ 647 return 0; 648} 649 650static void 651buffer_print_svcparamkey(buffer_type *output, uint16_t svcparamkey) 652{ 653 if (svcparamkey < SVCPARAMKEY_COUNT) 654 buffer_printf(output, "%s", svcparamkey_strs[svcparamkey]); 655 else 656 buffer_printf(output, "key%d", (int)svcparamkey); 657} 658 659static int 660rdata_svcparam_port_to_string(buffer_type *output, uint16_t val_len, 661 uint16_t *data) 662{ 663 if (val_len != 2) 664 return 0; /* wireformat error, a short is 2 bytes */ 665 buffer_printf(output, "=%d", (int)ntohs(data[0])); 666 return 1; 667} 668 669static int 670rdata_svcparam_ipv4hint_to_string(buffer_type *output, uint16_t val_len, 671 uint16_t *data) 672{ 673 char ip_str[INET_ADDRSTRLEN + 1]; 674 675 assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */ 676 677 if ((val_len % IP4ADDRLEN) == 0) { 678 if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) 679 return 0; /* wireformat error, incorrect size or inet family */ 680 681 buffer_printf(output, "=%s", ip_str); 682 data += IP4ADDRLEN / sizeof(uint16_t); 683 684 while ((val_len -= IP4ADDRLEN) > 0) { 685 if (inet_ntop(AF_INET, data, ip_str, sizeof(ip_str)) == NULL) 686 return 0; /* wireformat error, incorrect size or inet family */ 687 688 buffer_printf(output, ",%s", ip_str); 689 data += IP4ADDRLEN / sizeof(uint16_t); 690 } 691 return 1; 692 } else 693 return 0; 694} 695 696static int 697rdata_svcparam_ipv6hint_to_string(buffer_type *output, uint16_t val_len, 698 uint16_t *data) 699{ 700 char ip_str[INET6_ADDRSTRLEN + 1]; 701 702 assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */ 703 704 if ((val_len % IP6ADDRLEN) == 0) { 705 if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) 706 return 0; /* wireformat error, incorrect size or inet family */ 707 708 buffer_printf(output, "=%s", ip_str); 709 data += IP6ADDRLEN / sizeof(uint16_t); 710 711 while ((val_len -= IP6ADDRLEN) > 0) { 712 if (inet_ntop(AF_INET6, data, ip_str, sizeof(ip_str)) == NULL) 713 return 0; /* wireformat error, incorrect size or inet family */ 714 715 buffer_printf(output, ",%s", ip_str); 716 data += IP6ADDRLEN / sizeof(uint16_t); 717 } 718 return 1; 719 } else 720 return 0; 721} 722 723static int 724rdata_svcparam_mandatory_to_string(buffer_type *output, uint16_t val_len, 725 uint16_t *data) 726{ 727 assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */ 728 729 if (val_len % sizeof(uint16_t)) 730 return 0; /* wireformat error, val_len must be multiple of shorts */ 731 buffer_write_u8(output, '='); 732 buffer_print_svcparamkey(output, ntohs(*data)); 733 data += 1; 734 735 while ((val_len -= sizeof(uint16_t))) { 736 buffer_write_u8(output, ','); 737 buffer_print_svcparamkey(output, ntohs(*data)); 738 data += 1; 739 } 740 741 return 1; 742} 743 744static int 745rdata_svcparam_ech_to_string(buffer_type *output, uint16_t val_len, 746 uint16_t *data) 747{ 748 int length; 749 750 assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */ 751 752 buffer_write_u8(output, '='); 753 754 buffer_reserve(output, val_len * 2 + 1); 755 length = b64_ntop((uint8_t*) data, val_len, 756 (char *) buffer_current(output), val_len * 2); 757 if (length > 0) { 758 buffer_skip(output, length); 759 } 760 761 return length != -1; 762} 763 764static int 765rdata_svcparam_alpn_to_string(buffer_type *output, uint16_t val_len, 766 uint16_t *data) 767{ 768 uint8_t *dp = (void *)data; 769 770 assert(val_len > 0); /* Guaranteed by rdata_svcparam_to_string */ 771 772 buffer_write_u8(output, '='); 773 buffer_write_u8(output, '"'); 774 while (val_len) { 775 uint8_t i, str_len = *dp++; 776 777 if (str_len > --val_len) 778 return 0; 779 780 for (i = 0; i < str_len; i++) { 781 if (dp[i] == '"' || dp[i] == '\\') 782 buffer_printf(output, "\\\\\\%c", dp[i]); 783 784 else if (dp[i] == ',') 785 buffer_printf(output, "\\\\%c", dp[i]); 786 787 else if (!isprint(dp[i])) 788 buffer_printf(output, "\\%03u", (unsigned) dp[i]); 789 790 else 791 buffer_write_u8(output, dp[i]); 792 } 793 dp += str_len; 794 if ((val_len -= str_len)) 795 buffer_write_u8(output, ','); 796 } 797 buffer_write_u8(output, '"'); 798 return 1; 799} 800 801static int 802rdata_svcparam_to_string(buffer_type *output, rdata_atom_type rdata, 803 rr_type* ATTR_UNUSED(rr)) 804{ 805 uint16_t size = rdata_atom_size(rdata); 806 uint16_t* data = (uint16_t *)rdata_atom_data(rdata); 807 uint16_t svcparamkey, val_len; 808 uint8_t* dp; 809 size_t i; 810 811 if (size < 4) 812 return 0; 813 svcparamkey = ntohs(data[0]); 814 815 buffer_print_svcparamkey(output, svcparamkey); 816 val_len = ntohs(data[1]); 817 if (size != val_len + 4) 818 return 0; /* wireformat error */ 819 if (!val_len) { 820 /* Some SvcParams MUST have values */ 821 switch (svcparamkey) { 822 case SVCB_KEY_ALPN: 823 case SVCB_KEY_PORT: 824 case SVCB_KEY_IPV4HINT: 825 case SVCB_KEY_IPV6HINT: 826 case SVCB_KEY_MANDATORY: 827 case SVCB_KEY_DOHPATH: 828 return 0; 829 default: 830 return 1; 831 } 832 } 833 switch (svcparamkey) { 834 case SVCB_KEY_PORT: 835 return rdata_svcparam_port_to_string(output, val_len, data+2); 836 case SVCB_KEY_IPV4HINT: 837 return rdata_svcparam_ipv4hint_to_string(output, val_len, data+2); 838 case SVCB_KEY_IPV6HINT: 839 return rdata_svcparam_ipv6hint_to_string(output, val_len, data+2); 840 case SVCB_KEY_MANDATORY: 841 return rdata_svcparam_mandatory_to_string(output, val_len, data+2); 842 case SVCB_KEY_NO_DEFAULT_ALPN: 843 return 0; /* wireformat error, should not have a value */ 844 case SVCB_KEY_ALPN: 845 return rdata_svcparam_alpn_to_string(output, val_len, data+2); 846 case SVCB_KEY_ECH: 847 return rdata_svcparam_ech_to_string(output, val_len, data+2); 848 case SVCB_KEY_DOHPATH: 849 /* fallthrough */ 850 default: 851 buffer_write(output, "=\"", 2); 852 dp = (void*) (data + 2); 853 854 for (i = 0; i < val_len; i++) { 855 if (dp[i] == '"' || dp[i] == '\\') 856 buffer_printf(output, "\\%c", dp[i]); 857 858 else if (!isprint(dp[i])) 859 buffer_printf(output, "\\%03u", (unsigned) dp[i]); 860 861 else 862 buffer_write_u8(output, dp[i]); 863 } 864 buffer_write_u8(output, '"'); 865 break; 866 } 867 return 1; 868} 869 870static int 871rdata_unknown_to_string(buffer_type *output, rdata_atom_type rdata, 872 rr_type* ATTR_UNUSED(rr)) 873{ 874 uint16_t size = rdata_atom_size(rdata); 875 buffer_printf(output, "\\# %lu ", (unsigned long) size); 876 hex_to_string(output, rdata_atom_data(rdata), size); 877 return 1; 878} 879 880static rdata_to_string_type rdata_to_string_table[RDATA_ZF_UNKNOWN + 1] = { 881 rdata_dname_to_string, 882 rdata_dns_name_to_string, 883 rdata_text_to_string, 884 rdata_texts_to_string, 885 rdata_byte_to_string, 886 rdata_short_to_string, 887 rdata_long_to_string, 888 rdata_a_to_string, 889 rdata_aaaa_to_string, 890 rdata_rrtype_to_string, 891 rdata_algorithm_to_string, 892 rdata_certificate_type_to_string, 893 rdata_period_to_string, 894 rdata_time_to_string, 895 rdata_base64_to_string, 896 rdata_base32_to_string, 897 rdata_hex_to_string, 898 rdata_hexlen_to_string, 899 rdata_nsap_to_string, 900 rdata_apl_to_string, 901 rdata_ipsecgateway_to_string, 902 rdata_services_to_string, 903 rdata_nxt_to_string, 904 rdata_nsec_to_string, 905 rdata_loc_to_string, 906 rdata_ilnp64_to_string, 907 rdata_eui48_to_string, 908 rdata_eui64_to_string, 909 rdata_long_text_to_string, 910 rdata_tag_to_string, 911 rdata_svcparam_to_string, 912 rdata_unknown_to_string 913}; 914 915int 916rdata_atom_to_string(buffer_type *output, rdata_zoneformat_type type, 917 rdata_atom_type rdata, rr_type* record) 918{ 919 return rdata_to_string_table[type](output, rdata, record); 920} 921 922ssize_t 923rdata_wireformat_to_rdata_atoms(region_type *region, 924 domain_table_type *owners, 925 uint16_t rrtype, 926 uint16_t data_size, 927 buffer_type *packet, 928 rdata_atom_type **rdatas) 929{ 930 size_t end = buffer_position(packet) + data_size; 931 size_t i; 932 rdata_atom_type temp_rdatas[MAXRDATALEN]; 933 rrtype_descriptor_type *descriptor = rrtype_descriptor_by_type(rrtype); 934 region_type *temp_region; 935 936 assert(descriptor->maximum <= MAXRDATALEN); 937 938 if (!buffer_available(packet, data_size)) { 939 return -1; 940 } 941 942 temp_region = region_create(xalloc, free); 943 944 for (i = 0; i < descriptor->maximum; ++i) { 945 int is_domain = 0; 946 int is_normalized = 0; 947 int is_wirestore = 0; 948 size_t length = 0; 949 int required = i < descriptor->minimum; 950 951 switch (rdata_atom_wireformat_type(rrtype, i)) { 952 case RDATA_WF_COMPRESSED_DNAME: 953 case RDATA_WF_UNCOMPRESSED_DNAME: 954 is_domain = 1; 955 is_normalized = 1; 956 break; 957 case RDATA_WF_LITERAL_DNAME: 958 is_domain = 1; 959 is_wirestore = 1; 960 break; 961 case RDATA_WF_BYTE: 962 length = sizeof(uint8_t); 963 break; 964 case RDATA_WF_SHORT: 965 length = sizeof(uint16_t); 966 break; 967 case RDATA_WF_LONG: 968 length = sizeof(uint32_t); 969 break; 970 case RDATA_WF_TEXTS: 971 case RDATA_WF_LONG_TEXT: 972 length = end - buffer_position(packet); 973 break; 974 case RDATA_WF_TEXT: 975 case RDATA_WF_BINARYWITHLENGTH: 976 /* Length is stored in the first byte. */ 977 length = 1; 978 if (buffer_position(packet) + length <= end) { 979 length += buffer_current(packet)[length - 1]; 980 } 981 break; 982 case RDATA_WF_A: 983 length = sizeof(in_addr_t); 984 break; 985 case RDATA_WF_AAAA: 986 length = IP6ADDRLEN; 987 break; 988 case RDATA_WF_ILNP64: 989 length = IP6ADDRLEN/2; 990 break; 991 case RDATA_WF_EUI48: 992 length = EUI48ADDRLEN; 993 break; 994 case RDATA_WF_EUI64: 995 length = EUI64ADDRLEN; 996 break; 997 case RDATA_WF_BINARY: 998 /* Remaining RDATA is binary. */ 999 length = end - buffer_position(packet); 1000 break; 1001 case RDATA_WF_APL: 1002 length = (sizeof(uint16_t) /* address family */ 1003 + sizeof(uint8_t) /* prefix */ 1004 + sizeof(uint8_t)); /* length */ 1005 if (buffer_position(packet) + length <= end) { 1006 /* Mask out negation bit. */ 1007 length += (buffer_current(packet)[length - 1] 1008 & APL_LENGTH_MASK); 1009 } 1010 break; 1011 case RDATA_WF_IPSECGATEWAY: 1012 assert(i>1); /* we are past the gateway type */ 1013 switch(rdata_atom_data(temp_rdatas[1])[0]) /* gateway type */ { 1014 default: 1015 case IPSECKEY_NOGATEWAY: 1016 length = 0; 1017 break; 1018 case IPSECKEY_IP4: 1019 length = IP4ADDRLEN; 1020 break; 1021 case IPSECKEY_IP6: 1022 length = IP6ADDRLEN; 1023 break; 1024 case IPSECKEY_DNAME: 1025 is_domain = 1; 1026 is_normalized = 1; 1027 is_wirestore = 1; 1028 break; 1029 } 1030 break; 1031 case RDATA_WF_SVCPARAM: 1032 length = 4; 1033 if (buffer_position(packet) + 4 <= end) { 1034 length += 1035 read_uint16(buffer_current(packet) + 2); 1036 } 1037 break; 1038 } 1039 1040 if (is_domain) { 1041 const dname_type *dname; 1042 1043 if (!required && buffer_position(packet) == end) { 1044 break; 1045 } 1046 1047 dname = dname_make_from_packet( 1048 temp_region, packet, 1, is_normalized); 1049 if (!dname || buffer_position(packet) > end) { 1050 /* Error in domain name. */ 1051 region_destroy(temp_region); 1052 return -1; 1053 } 1054 if(is_wirestore) { 1055 temp_rdatas[i].data = (uint16_t *) region_alloc( 1056 region, sizeof(uint16_t) + ((size_t)dname->name_size)); 1057 temp_rdatas[i].data[0] = dname->name_size; 1058 memcpy(temp_rdatas[i].data+1, dname_name(dname), 1059 dname->name_size); 1060 } else { 1061 temp_rdatas[i].domain 1062 = domain_table_insert(owners, dname); 1063 temp_rdatas[i].domain->usage ++; 1064 } 1065 } else { 1066 if (buffer_position(packet) + length > end) { 1067 if (required) { 1068 /* Truncated RDATA. */ 1069 region_destroy(temp_region); 1070 return -1; 1071 } else { 1072 break; 1073 } 1074 } 1075 if (!required && buffer_position(packet) == end) { 1076 break; 1077 } 1078 1079 temp_rdatas[i].data = (uint16_t *) region_alloc( 1080 region, sizeof(uint16_t) + length); 1081 temp_rdatas[i].data[0] = length; 1082 buffer_read(packet, temp_rdatas[i].data + 1, length); 1083 } 1084 } 1085 1086 if (buffer_position(packet) < end) { 1087 /* Trailing garbage. */ 1088 region_destroy(temp_region); 1089 return -1; 1090 } 1091 1092 *rdatas = (rdata_atom_type *) region_alloc_array_init( 1093 region, temp_rdatas, i, sizeof(rdata_atom_type)); 1094 region_destroy(temp_region); 1095 return (ssize_t)i; 1096} 1097 1098size_t 1099rdata_maximum_wireformat_size(rrtype_descriptor_type *descriptor, 1100 size_t rdata_count, 1101 rdata_atom_type *rdatas) 1102{ 1103 size_t result = 0; 1104 size_t i; 1105 for (i = 0; i < rdata_count; ++i) { 1106 if (rdata_atom_is_domain(descriptor->type, i)) { 1107 result += domain_dname(rdata_atom_domain(rdatas[i]))->name_size; 1108 } else { 1109 result += rdata_atom_size(rdatas[i]); 1110 } 1111 } 1112 return result; 1113} 1114 1115int 1116rdata_atoms_to_unknown_string(buffer_type *output, 1117 rrtype_descriptor_type *descriptor, 1118 size_t rdata_count, 1119 rdata_atom_type *rdatas) 1120{ 1121 size_t i; 1122 size_t size = 1123 rdata_maximum_wireformat_size(descriptor, rdata_count, rdatas); 1124 buffer_printf(output, " \\# %lu ", (unsigned long) size); 1125 for (i = 0; i < rdata_count; ++i) { 1126 if (rdata_atom_is_domain(descriptor->type, i)) { 1127 const dname_type *dname = 1128 domain_dname(rdata_atom_domain(rdatas[i])); 1129 hex_to_string( 1130 output, dname_name(dname), dname->name_size); 1131 } else { 1132 hex_to_string(output, rdata_atom_data(rdatas[i]), 1133 rdata_atom_size(rdatas[i])); 1134 } 1135 } 1136 return 1; 1137} 1138 1139int 1140print_rdata(buffer_type *output, rrtype_descriptor_type *descriptor, 1141 rr_type *record) 1142{ 1143 size_t i; 1144 size_t saved_position = buffer_position(output); 1145 1146 for (i = 0; i < record->rdata_count; ++i) { 1147 if (i == 0) { 1148 buffer_printf(output, "\t"); 1149 } else if (descriptor->type == TYPE_SOA && i == 2) { 1150 buffer_printf(output, " (\n\t\t"); 1151 } else { 1152 buffer_printf(output, " "); 1153 } 1154 if (!rdata_atom_to_string( 1155 output, 1156 (rdata_zoneformat_type) descriptor->zoneformat[i], 1157 record->rdatas[i], record)) 1158 { 1159 buffer_set_position(output, saved_position); 1160 return 0; 1161 } 1162 } 1163 if (descriptor->type == TYPE_SOA) { 1164 buffer_printf(output, " )"); 1165 } 1166 1167 return 1; 1168} 1169 1170