1/* 2 * Copyright (c) 1999-2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23 24#include <stdio.h> 25#include <stdlib.h> 26#include <ctype.h> 27#include <string.h> 28#include <unistd.h> 29#include <netdb.h> 30#include <stdarg.h> 31#include <sys/stat.h> 32#include <sys/dir.h> 33#include <errno.h> 34#include <sys/types.h> 35#include <sys/socket.h> 36#include <ifaddrs.h> 37#include <net/if.h> 38#include <pthread.h> 39#include <netinet/in.h> 40#include <arpa/nameser.h> 41#include <resolv.h> 42#include "dns.h" 43#include "dns_util.h" 44#include "dns_private.h" 45#include "res_private.h" 46 47#define DNS_RESOLVER_DIR "/etc/resolver" 48 49#define DNS_PRIVATE_HANDLE_TYPE_SUPER 0 50#define DNS_PRIVATE_HANDLE_TYPE_PLAIN 1 51#define DNS_DEFAULT_RECEIVE_SIZE 8192 52#define DNS_MAX_RECEIVE_SIZE 65536 53 54#define SDNS_DEFAULT_STAT_LATENCY 10 55 56#define DNS_FLAGS_QR_MASK 0x8000 57#define DNS_FLAGS_QR_QUERY 0x0000 58 59#define DNS_FLAGS_OPCODE_MASK 0x7800 60 61#define DNS_FLAGS_RCODE_MASK 0x000f 62 63#define DNS_FLAGS_AA 0x0400 64#define DNS_FLAGS_TC 0x0200 65#define DNS_FLAGS_RD 0x0100 66#define DNS_FLAGS_RA 0x0080 67 68#define DNS_SOCK_UDP 0 69#define DNS_SOCK_TCP_UNCONNECTED 1 70#define DNS_SOCK_TCP_CONNECTED 2 71 72#define INET_NTOP_AF_INET_OFFSET 4 73#define INET_NTOP_AF_INET6_OFFSET 8 74 75#define MAXPACKET 1024 76 77extern void res_client_close(res_state res); 78extern int __res_nquery(res_state statp, const char *name, int class, int type, u_char *answer, int anslen); 79extern int dns_res_send(res_state statp, const u_char *buf, int buflen, u_char *ans, int *anssiz, struct sockaddr *from, int *fromlen); 80extern void _check_cache(sdns_handle_t *sdns); 81extern int _sdns_search(sdns_handle_t *sdns, const char *name, uint32_t class, uint32_t type, uint32_t fqdn, uint32_t recurse, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen, int *min); 82extern int _pdns_search(sdns_handle_t *sdns, pdns_handle_t *pdns, const char *name, uint32_t class, uint32_t type, char *buf, uint32_t len, struct sockaddr *from, uint32_t *fromlen); 83static pthread_mutex_t _dnsPrintLock = PTHREAD_MUTEX_INITIALIZER; 84 85static void 86_dns_print_lock(void) 87{ 88 pthread_mutex_lock(&_dnsPrintLock); 89} 90 91static void 92_dns_print_unlock(void) 93{ 94 pthread_mutex_unlock(&_dnsPrintLock); 95} 96 97 98static uint8_t 99_dns_parse_uint8(char **p) 100{ 101 uint8_t v; 102 103 v = (uint8_t)**p; 104 *p += 1; 105 return v; 106} 107 108static uint16_t 109_dns_parse_uint16(char **p) 110{ 111 uint16_t *x, v; 112 113 x = (uint16_t *)*p; 114 v = ntohs(*x); 115 *p += 2; 116 return v; 117} 118 119static uint32_t 120_dns_parse_uint32(char **p) 121{ 122 uint32_t *x, v; 123 124 x = (uint32_t *)*p; 125 v = ntohl(*x); 126 *p += 4; 127 return v; 128} 129 130static uint8_t 131_dns_cname_length(char *s) 132{ 133 uint8_t l; 134 135 if (s == NULL) return 1; 136 l = strlen(s); 137 while ((s[l - 1] == '.') && (l > 1)) l--; 138 return l; 139} 140 141static void 142_dns_insert_cname(char *s, char *p) 143{ 144 int i; 145 uint8_t len, dlen; 146 147 if (s == NULL) 148 { 149 *p = 0; 150 return; 151 } 152 153 if (!strcmp(s, ".")) 154 { 155 p[0] = 1; 156 p[1] = '.'; 157 p[2] = 0; 158 return; 159 } 160 161 len = _dns_cname_length(s); 162 163 p[0] = '.'; 164 memmove(p + 1, s, len); 165 p[len + 1] = '.'; 166 167 dlen = 0; 168 169 for (i = len + 1; i >= 0; i--) 170 { 171 if (p[i] == '.') 172 { 173 p[i] = dlen; 174 dlen = 0; 175 } 176 else dlen++; 177 } 178} 179 180static char * 181_dns_parse_string(const char *p, char **x, int32_t *remaining) 182{ 183 char *str; 184 uint8_t len; 185 186 if (*remaining < 1) return NULL; 187 *remaining -= 1; 188 189 len = (uint8_t)**x; 190 *x += 1; 191 192 if (*remaining < len) return NULL; 193 *remaining -= len; 194 195 str = malloc(len + 1); 196 memmove(str, *x, len); 197 str[len] = '\0'; 198 *x += len; 199 200 return str; 201} 202 203static char * 204_dns_parse_domain_name(const char *p, char **x, int32_t *remaining) 205{ 206 uint8_t *v8; 207 uint16_t *v16, skip; 208 uint16_t i, j, dlen, len; 209 int more, compressed; 210 char *name, *start, *y, *z; 211 212 if (*remaining < 1) return NULL; 213 214 z = *x + *remaining; 215 start = *x; 216 compressed = 0; 217 more = 1; 218 name = malloc(1); 219 name[0] = '\0'; 220 len = 1; 221 j = 0; 222 skip = 0; 223 224 while (more == 1) 225 { 226 if ((*x + 1) > z) 227 { 228 free(name); 229 return NULL; 230 } 231 232 v8 = (uint8_t *)*x; 233 dlen = *v8; 234 235 if ((dlen & 0xc0) == 0xc0) 236 { 237 if ((*x + 2) > z) 238 { 239 free(name); 240 return NULL; 241 } 242 243 v16 = (uint16_t *)*x; 244 245 y = (char *)p + (ntohs(*v16) & 0x3fff); 246 if ((*x == y) || (y > z)) 247 { 248 free(name); 249 return NULL; 250 } 251 252 *x = y; 253 if (compressed == 0) skip += 2; 254 compressed = 1; 255 continue; 256 } 257 258 if ((*x + 1) > z) 259 { 260 free(name); 261 return NULL; 262 } 263 264 *x += 1; 265 266 if (dlen > 0) 267 { 268 len += dlen; 269 name = realloc(name, len); 270 } 271 272 if ((*x + dlen) > z) 273 { 274 free(name); 275 return NULL; 276 } 277 278 for (i = 0; i < dlen; i++) 279 { 280 name[j++] = **x; 281 *x += 1; 282 } 283 284 name[j] = '\0'; 285 if (compressed == 0) skip += (dlen + 1); 286 287 if (dlen == 0) more = 0; 288 else 289 { 290 if ((*x + 1) > z) 291 { 292 free(name); 293 return NULL; 294 } 295 296 v8 = (uint8_t *)*x; 297 if (*v8 != 0) 298 { 299 len += 1; 300 name = realloc(name, len); 301 name[j++] = '.'; 302 name[j] = '\0'; 303 } 304 } 305 } 306 307 if ((start + skip) > z) 308 { 309 free(name); 310 return NULL; 311 } 312 313 *x = start + skip; 314 *remaining -= skip; 315 316 return name; 317} 318 319dns_resource_record_t * 320_dns_parse_resource_record_internal(const char *p, char **x, int32_t *remaining) 321{ 322 uint32_t size, bx, mi; 323 uint16_t rdlen; 324 uint8_t byte, i; 325 dns_resource_record_t *r; 326 char *eor; 327 328 if (*remaining < 1) return NULL; 329 330 r = (dns_resource_record_t *)calloc(1, sizeof(dns_resource_record_t)); 331 332 r->name = _dns_parse_domain_name(p, x, remaining); 333 if (r->name == NULL) 334 { 335 dns_free_resource_record(r); 336 return NULL; 337 } 338 339 if (*remaining < 10) 340 { 341 dns_free_resource_record(r); 342 return NULL; 343 } 344 345 r->dnstype = _dns_parse_uint16(x); 346 r->dnsclass = _dns_parse_uint16(x); 347 r->ttl = _dns_parse_uint32(x); 348 rdlen = _dns_parse_uint16(x); 349 350 *remaining -= 10; 351 352 if (*remaining < rdlen) 353 { 354 dns_free_resource_record(r); 355 return NULL; 356 } 357 358 eor = *x; 359 r->data.A = NULL; 360 361 switch (r->dnstype) 362 { 363 case ns_t_a: 364 if (*remaining < 4) 365 { 366 dns_free_resource_record(r); 367 return NULL; 368 } 369 370 *remaining -= 4; 371 372 size = sizeof(dns_address_record_t); 373 r->data.A = (dns_address_record_t *)calloc(1, size); 374 r->data.A->addr.s_addr = htonl(_dns_parse_uint32(x)); 375 break; 376 377 case ns_t_aaaa: 378 if (*remaining < 16) 379 { 380 dns_free_resource_record(r); 381 return NULL; 382 } 383 384 *remaining -= 16; 385 386 size = sizeof(dns_in6_address_record_t); 387 r->data.AAAA = (dns_in6_address_record_t *)calloc(1, size); 388 r->data.AAAA->addr.__u6_addr.__u6_addr32[0] = htonl(_dns_parse_uint32(x)); 389 r->data.AAAA->addr.__u6_addr.__u6_addr32[1] = htonl(_dns_parse_uint32(x)); 390 r->data.AAAA->addr.__u6_addr.__u6_addr32[2] = htonl(_dns_parse_uint32(x)); 391 r->data.AAAA->addr.__u6_addr.__u6_addr32[3] = htonl(_dns_parse_uint32(x)); 392 break; 393 394 case ns_t_ns: 395 case ns_t_md: 396 case ns_t_mf: 397 case ns_t_cname: 398 case ns_t_mb: 399 case ns_t_mg: 400 case ns_t_mr: 401 case ns_t_ptr: 402 size = sizeof(dns_domain_name_record_t); 403 r->data.CNAME = (dns_domain_name_record_t *)calloc(1,size); 404 r->data.CNAME->name = _dns_parse_domain_name(p, x, remaining); 405 if (r->data.CNAME->name == NULL) 406 { 407 dns_free_resource_record(r); 408 return NULL; 409 } 410 break; 411 412 case ns_t_soa: 413 size = sizeof(dns_SOA_record_t); 414 r->data.SOA = (dns_SOA_record_t *)calloc(1, size); 415 416 r->data.SOA->mname = _dns_parse_domain_name(p, x, remaining); 417 if (r->data.SOA->mname == NULL) 418 { 419 dns_free_resource_record(r); 420 return NULL; 421 } 422 423 r->data.SOA->rname = _dns_parse_domain_name(p, x, remaining); 424 if (r->data.SOA->rname == NULL) 425 { 426 dns_free_resource_record(r); 427 return NULL; 428 } 429 430 if (*remaining < 20) 431 { 432 dns_free_resource_record(r); 433 return NULL; 434 } 435 436 *remaining -= 20; 437 438 r->data.SOA->serial = _dns_parse_uint32(x); 439 r->data.SOA->refresh = _dns_parse_uint32(x); 440 r->data.SOA->retry = _dns_parse_uint32(x); 441 r->data.SOA->expire = _dns_parse_uint32(x); 442 r->data.SOA->minimum = _dns_parse_uint32(x); 443 break; 444 445 case ns_t_wks: 446 if (*remaining < 5) 447 { 448 dns_free_resource_record(r); 449 return NULL; 450 } 451 452 *remaining -= rdlen; 453 454 size = sizeof(dns_WKS_record_t); 455 r->data.WKS = (dns_WKS_record_t *)calloc(1, size); 456 457 r->data.WKS->addr.s_addr = htonl(_dns_parse_uint32(x)); 458 r->data.WKS->protocol = _dns_parse_uint8(x); 459 size = rdlen - 5; 460 r->data.WKS->maplength = size * 8; 461 r->data.WKS->map = NULL; 462 if (size == 0) break; 463 464 r->data.WKS->map = (uint8_t *)calloc(1, r->data.WKS->maplength); 465 mi = 0; 466 for (bx = 0; bx < size; bx++) 467 { 468 byte = _dns_parse_uint8(x); 469 for (i = 128; i >= 1; i = i/2) 470 { 471 if (byte & i) r->data.WKS->map[mi] = 0xff; 472 else r->data.WKS->map[mi] = 0; 473 mi++; 474 } 475 } 476 break; 477 478 case ns_t_hinfo: 479 size = sizeof(dns_HINFO_record_t); 480 r->data.HINFO = (dns_HINFO_record_t *)calloc(1, size); 481 482 r->data.HINFO->cpu = _dns_parse_string(p, x, remaining); 483 if (r->data.HINFO->cpu == NULL) 484 { 485 dns_free_resource_record(r); 486 return NULL; 487 } 488 489 r->data.HINFO->os = _dns_parse_string(p, x, remaining); 490 if (r->data.HINFO->os == NULL) 491 { 492 dns_free_resource_record(r); 493 return NULL; 494 } 495 496 break; 497 498 case ns_t_minfo: 499 size = sizeof(dns_MINFO_record_t); 500 r->data.MINFO = (dns_MINFO_record_t *)calloc(1, size); 501 502 r->data.MINFO->rmailbx = _dns_parse_domain_name(p, x, remaining); 503 if (r->data.MINFO->rmailbx == NULL) 504 { 505 dns_free_resource_record(r); 506 return NULL; 507 } 508 509 r->data.MINFO->emailbx = _dns_parse_domain_name(p, x, remaining); 510 if (r->data.MINFO->emailbx == NULL) 511 { 512 dns_free_resource_record(r); 513 return NULL; 514 } 515 516 break; 517 518 case ns_t_mx: 519 if (*remaining < 2) 520 { 521 dns_free_resource_record(r); 522 return NULL; 523 } 524 525 *remaining -= 2; 526 527 size = sizeof(dns_MX_record_t); 528 r->data.MX = (dns_MX_record_t *)calloc(1, size); 529 530 r->data.MX->preference = _dns_parse_uint16(x); 531 r->data.MX->name = _dns_parse_domain_name(p, x, remaining); 532 if (r->data.MX->name == NULL) 533 { 534 dns_free_resource_record(r); 535 return NULL; 536 } 537 538 break; 539 540 case ns_t_txt: 541 size = sizeof(dns_TXT_record_t); 542 r->data.TXT = (dns_TXT_record_t *)malloc(size); 543 r->data.TXT->string_count = 0; 544 r->data.TXT->strings = NULL; 545 546 while (*x < (eor + rdlen)) 547 { 548 if (r->data.TXT->string_count == 0) 549 { 550 r->data.TXT->strings = (char **)calloc(1, sizeof(char *)); 551 } 552 else 553 { 554 r->data.TXT->strings = (char **)realloc(r->data.TXT->strings, (r->data.TXT->string_count + 1) * sizeof(char *)); 555 } 556 557 r->data.TXT->strings[r->data.TXT->string_count] = _dns_parse_string(p, x, remaining); 558 if (r->data.TXT->strings[r->data.TXT->string_count] == NULL) 559 { 560 dns_free_resource_record(r); 561 return NULL; 562 } 563 r->data.TXT->string_count++; 564 } 565 566 break; 567 568 case ns_t_rp: 569 size = sizeof(dns_RP_record_t); 570 r->data.RP = (dns_RP_record_t *)calloc(1, size); 571 572 r->data.RP->mailbox = _dns_parse_domain_name(p, x, remaining); 573 if (r->data.RP->mailbox == NULL) 574 { 575 dns_free_resource_record(r); 576 return NULL; 577 } 578 579 r->data.RP->txtdname = _dns_parse_domain_name(p, x, remaining); 580 if (r->data.RP->txtdname == NULL) 581 { 582 dns_free_resource_record(r); 583 return NULL; 584 } 585 586 break; 587 588 case ns_t_afsdb: 589 if (*remaining < 4) 590 { 591 dns_free_resource_record(r); 592 return NULL; 593 } 594 595 *remaining -= 4; 596 size = sizeof(dns_AFSDB_record_t); 597 r->data.AFSDB = (dns_AFSDB_record_t *)calloc(1, size); 598 599 r->data.AFSDB->subtype = _dns_parse_uint32(x); 600 r->data.AFSDB->hostname = _dns_parse_domain_name(p, x, remaining); 601 if (r->data.AFSDB->hostname == NULL) 602 { 603 dns_free_resource_record(r); 604 return NULL; 605 } 606 607 break; 608 609 case ns_t_x25: 610 size = sizeof(dns_X25_record_t); 611 r->data.X25 = (dns_X25_record_t *)calloc(1, size); 612 613 r->data.X25->psdn_address = _dns_parse_string(p, x, remaining); 614 if (r->data.X25->psdn_address == NULL) 615 { 616 dns_free_resource_record(r); 617 return NULL; 618 } 619 620 break; 621 622 case ns_t_isdn: 623 size = sizeof(dns_ISDN_record_t); 624 r->data.ISDN = (dns_ISDN_record_t *)calloc(1, size); 625 626 r->data.ISDN->isdn_address = _dns_parse_string(p, x, remaining); 627 if (r->data.ISDN->isdn_address == NULL) 628 { 629 dns_free_resource_record(r); 630 return NULL; 631 } 632 633 if (*x < (eor + rdlen)) 634 { 635 r->data.ISDN->subaddress = _dns_parse_string(p, x, remaining); 636 if (r->data.ISDN->subaddress == NULL) 637 { 638 dns_free_resource_record(r); 639 return NULL; 640 } 641 } 642 else 643 { 644 r->data.ISDN->subaddress = NULL; 645 } 646 647 break; 648 649 case ns_t_rt: 650 if (*remaining < 2) 651 { 652 dns_free_resource_record(r); 653 return NULL; 654 } 655 656 *remaining -= 2; 657 658 size = sizeof(dns_RT_record_t); 659 r->data.RT = (dns_RT_record_t *)calloc(1, size); 660 661 r->data.RT->preference = _dns_parse_uint16(x); 662 r->data.RT->intermediate = _dns_parse_domain_name(p, x, remaining); 663 if (r->data.RT->intermediate == NULL) 664 { 665 dns_free_resource_record(r); 666 return NULL; 667 } 668 669 break; 670 671 case ns_t_loc: 672 if (*remaining < 16) 673 { 674 dns_free_resource_record(r); 675 return NULL; 676 } 677 678 *remaining -= 16; 679 680 size = sizeof(dns_LOC_record_t); 681 r->data.LOC = (dns_LOC_record_t *)calloc(1, size); 682 683 r->data.LOC->version = _dns_parse_uint8(x); 684 r->data.LOC->size = _dns_parse_uint8(x); 685 r->data.LOC->horizontal_precision = _dns_parse_uint8(x); 686 r->data.LOC->vertical_precision = _dns_parse_uint8(x); 687 r->data.LOC->latitude = _dns_parse_uint32(x); 688 r->data.LOC->longitude = _dns_parse_uint32(x); 689 r->data.LOC->altitude = _dns_parse_uint32(x); 690 break; 691 692 case ns_t_srv: 693 if (*remaining < 6) 694 { 695 dns_free_resource_record(r); 696 return NULL; 697 } 698 699 *remaining -= 6; 700 701 size = sizeof(dns_SRV_record_t); 702 r->data.SRV = (dns_SRV_record_t *)calloc(1, size); 703 704 r->data.SRV->priority = _dns_parse_uint16(x); 705 r->data.SRV->weight = _dns_parse_uint16(x); 706 r->data.SRV->port = _dns_parse_uint16(x); 707 r->data.SRV->target = _dns_parse_domain_name(p, x, remaining); 708 if (r->data.SRV->target == NULL) 709 { 710 dns_free_resource_record(r); 711 return NULL; 712 } 713 714 break; 715 716 case ns_t_null: 717 default: 718 *remaining -= rdlen; 719 720 size = sizeof(dns_raw_resource_record_t); 721 r->data.DNSNULL = (dns_raw_resource_record_t *)calloc(1, size); 722 723 r->data.DNSNULL->length = rdlen; 724 r->data.DNSNULL->data = calloc(1, rdlen); 725 memmove(r->data.DNSNULL->data, *x, rdlen); 726 *x += rdlen; 727 break; 728 } 729 730 *x = eor + rdlen; 731 return r; 732} 733 734dns_resource_record_t * 735dns_parse_resource_record(const char *buf, uint32_t len) 736{ 737 char *x; 738 int32_t remaining; 739 740 remaining = len; 741 x = (char *)buf; 742 return _dns_parse_resource_record_internal(buf, &x, &remaining); 743} 744 745dns_question_t * 746_dns_parse_question_internal(const char *p, char **x, int32_t *remaining) 747{ 748 dns_question_t *q; 749 750 if (x == NULL) return NULL; 751 if (*x == NULL) return NULL; 752 if (*remaining < 1) return NULL; 753 754 q = (dns_question_t *)calloc(1, sizeof(dns_question_t)); 755 756 q->name = _dns_parse_domain_name(p, x, remaining); 757 if (q->name == NULL) 758 { 759 free(q); 760 return NULL; 761 } 762 763 if (*remaining < 4) 764 { 765 free(q->name); 766 free(q); 767 return NULL; 768 } 769 770 *remaining = *remaining - 4; 771 772 q->dnstype = _dns_parse_uint16(x); 773 q->dnsclass = _dns_parse_uint16(x); 774 775 return q; 776} 777 778dns_question_t * 779dns_parse_question(const char *buf, uint32_t len) 780{ 781 char *x; 782 int32_t remaining; 783 784 remaining = len; 785 x = (char *)buf; 786 return _dns_parse_question_internal(buf, &x, &remaining); 787} 788 789 790dns_reply_t * 791dns_parse_packet(const char *p, uint32_t len) 792{ 793 dns_reply_t *r; 794 dns_header_t *h; 795 char *x; 796 uint32_t i, size; 797 int32_t remaining; 798 799 if (p == NULL) return NULL; 800 if (len < NS_HFIXEDSZ) return NULL; 801 802 x = (char *)p; 803 804 r = (dns_reply_t *)calloc(1, sizeof(dns_reply_t)); 805 806 r->header = (dns_header_t *)calloc(1, sizeof(dns_header_t)); 807 h = r->header; 808 809 h->xid = _dns_parse_uint16(&x); 810 h->flags = _dns_parse_uint16(&x); 811 h->qdcount = _dns_parse_uint16(&x); 812 h->ancount = _dns_parse_uint16(&x); 813 h->nscount = _dns_parse_uint16(&x); 814 h->arcount = _dns_parse_uint16(&x); 815 816 remaining = len - NS_HFIXEDSZ; 817 818 size = sizeof(dns_question_t *); 819 r->question = (dns_question_t **)calloc(h->qdcount, size); 820 for (i = 0; i < h->qdcount; i++) 821 { 822 r->question[i] = _dns_parse_question_internal(p, &x, &remaining); 823 if (r->question[i] ==NULL) 824 { 825 h->qdcount = 0; 826 if (i > 0) h->qdcount = i - 1; 827 h->ancount = 0; 828 h->nscount = 0; 829 h->arcount = 0; 830 dns_free_reply(r); 831 return NULL; 832 } 833 } 834 835 size = sizeof(dns_resource_record_t *); 836 837 r->answer = (dns_resource_record_t **)calloc(h->ancount, size); 838 for (i = 0; i < h->ancount; i++) 839 { 840 r->answer[i] = _dns_parse_resource_record_internal(p, &x, &remaining); 841 if (r->answer[i] == NULL) 842 { 843 h->ancount = 0; 844 if (i > 0) h->ancount = i - 1; 845 h->nscount = 0; 846 h->arcount = 0; 847 dns_free_reply(r); 848 return NULL; 849 } 850 } 851 852 r->authority = (dns_resource_record_t **)calloc(h->nscount, size); 853 for (i = 0; i < h->nscount; i++) 854 { 855 r->authority[i] = _dns_parse_resource_record_internal(p, &x, &remaining); 856 if (r->authority[i] == NULL) 857 { 858 h->nscount = 0; 859 if (i > 0) h->nscount = i - 1; 860 h->arcount = 0; 861 dns_free_reply(r); 862 return NULL; 863 } 864 } 865 866 r->additional = (dns_resource_record_t **)calloc(h->arcount, size); 867 for (i = 0; i < h->arcount; i++) 868 { 869 r->additional[i] = _dns_parse_resource_record_internal(p, &x, &remaining); 870 if (r->additional[i] == NULL) 871 { 872 h->arcount = 0; 873 if (i > 0) h->arcount = i - 1; 874 dns_free_reply(r); 875 return NULL; 876 } 877 } 878 879 return r; 880} 881 882void 883dns_free_resource_record(dns_resource_record_t *r) 884{ 885 int i; 886 887 free(r->name); 888 889 switch (r->dnstype) 890 { 891 case ns_t_a: 892 if (r->data.A != NULL) free(r->data.A); 893 break; 894 895 case ns_t_aaaa: 896 if (r->data.AAAA != NULL) free(r->data.AAAA); 897 break; 898 899 case ns_t_ns: 900 case ns_t_md: 901 case ns_t_mf: 902 case ns_t_cname: 903 case ns_t_mb: 904 case ns_t_mg: 905 case ns_t_mr: 906 case ns_t_ptr: 907 if (r->data.CNAME != NULL) 908 { 909 if (r->data.CNAME->name != NULL) free(r->data.CNAME->name); 910 free(r->data.CNAME); 911 } 912 break; 913 914 case ns_t_soa: 915 if (r->data.SOA != NULL) 916 { 917 if (r->data.SOA->mname != NULL) free(r->data.SOA->mname); 918 if (r->data.SOA->rname != NULL) free(r->data.SOA->rname); 919 free(r->data.SOA); 920 } 921 break; 922 923 case ns_t_wks: 924 if (r->data.WKS != NULL) 925 { 926 if (r->data.WKS->map != NULL) free(r->data.WKS->map); 927 free(r->data.WKS); 928 } 929 break; 930 931 case ns_t_hinfo: 932 if (r->data.HINFO != NULL) 933 { 934 if (r->data.HINFO->cpu != NULL) free(r->data.HINFO->cpu); 935 if (r->data.HINFO->os != NULL) free(r->data.HINFO->os); 936 free(r->data.HINFO); 937 } 938 break; 939 940 case ns_t_minfo: 941 if (r->data.MINFO != NULL) 942 { 943 if (r->data.MINFO->rmailbx != NULL) free(r->data.MINFO->rmailbx); 944 if (r->data.MINFO->emailbx != NULL) free(r->data.MINFO->emailbx); 945 free(r->data.MINFO); 946 } 947 break; 948 949 case ns_t_mx: 950 if (r->data.MX != NULL) 951 { 952 if (r->data.MX->name != NULL) free(r->data.MX->name); 953 free(r->data.MX); 954 } 955 break; 956 957 958 case ns_t_txt: 959 if (r->data.TXT != NULL) 960 { 961 for (i = 0; i < r->data.TXT->string_count; i++) free(r->data.TXT->strings[i]); 962 if (r->data.TXT->strings != NULL) free(r->data.TXT->strings); 963 free(r->data.TXT); 964 } 965 break; 966 967 case ns_t_rp: 968 if (r->data.RP != NULL) 969 { 970 if (r->data.RP->mailbox != NULL) free(r->data.RP->mailbox); 971 if (r->data.RP->txtdname != NULL) free(r->data.RP->txtdname); 972 free(r->data.RP); 973 } 974 break; 975 976 case ns_t_afsdb: 977 if (r->data.AFSDB != NULL) 978 { 979 if (r->data.AFSDB->hostname != NULL) free(r->data.AFSDB->hostname); 980 free(r->data.AFSDB); 981 } 982 break; 983 984 case ns_t_x25: 985 if (r->data.X25 != NULL) 986 { 987 if (r->data.X25->psdn_address != NULL) free(r->data.X25->psdn_address); 988 free(r->data.X25); 989 } 990 break; 991 992 case ns_t_isdn: 993 if (r->data.ISDN != NULL) 994 { 995 if (r->data.ISDN->isdn_address != NULL) free(r->data.ISDN->isdn_address); 996 if (r->data.ISDN->subaddress != NULL) free(r->data.ISDN->subaddress); 997 free(r->data.ISDN); 998 } 999 break; 1000 1001 case ns_t_rt: 1002 if (r->data.RT != NULL) 1003 { 1004 if (r->data.RT->intermediate != NULL) free(r->data.RT->intermediate); 1005 free(r->data.RT); 1006 } 1007 break; 1008 1009 case ns_t_loc: 1010 if (r->data.LOC != NULL) free(r->data.LOC); 1011 break; 1012 1013 case ns_t_srv: 1014 if (r->data.SRV != NULL) 1015 { 1016 if (r->data.SRV->target != NULL) free(r->data.SRV->target); 1017 free(r->data.SRV); 1018 } 1019 break; 1020 1021 case ns_t_invalid: 1022 break; 1023 1024 case ns_t_null: 1025 default: 1026 if (r->data.DNSNULL != NULL) 1027 { 1028 if (r->data.DNSNULL->data != NULL) free(r->data.DNSNULL->data); 1029 free(r->data.DNSNULL); 1030 } 1031 break; 1032 } 1033 1034 free(r); 1035} 1036 1037void 1038dns_free_reply(dns_reply_t *r) 1039{ 1040 uint32_t i; 1041 1042 if (r == NULL) return; 1043 if (r->header != NULL) 1044 { 1045 for (i = 0; i < r->header->qdcount; i++) 1046 { 1047 free(r->question[i]->name); 1048 free(r->question[i]); 1049 } 1050 1051 for (i = 0; i < r->header->ancount; i++) dns_free_resource_record(r->answer[i]); 1052 for (i = 0; i < r->header->nscount; i++) dns_free_resource_record(r->authority[i]); 1053 for (i = 0; i < r->header->arcount; i++) dns_free_resource_record(r->additional[i]); 1054 1055 free(r->header); 1056 } 1057 1058 if (r->question != NULL) free(r->question); 1059 if (r->answer != NULL) free(r->answer); 1060 if (r->authority != NULL) free(r->authority); 1061 if (r->additional != NULL) free(r->additional); 1062 1063 if (r->server != NULL) free(r->server); 1064 1065 free(r); 1066} 1067 1068static void 1069_dns_append_question(dns_question_t *q, char **s, uint16_t *l) 1070{ 1071 uint16_t len, *p; 1072 char *x; 1073 1074 if (q == NULL) return; 1075 1076 len = *l + _dns_cname_length(q->name) + 2 + 4; 1077 *s = realloc(*s, len); 1078 1079 _dns_insert_cname(q->name, (char *)*s + *l); 1080 *l = len; 1081 1082 x = *s + (len - 4); 1083 1084 p = (uint16_t *)x; 1085 *p = htons(q->dnstype); 1086 x += 2; 1087 1088 p = (uint16_t *)x; 1089 *p = htons(q->dnsclass); 1090 1091} 1092 1093static void 1094_dns_append_resource_record(dns_resource_record_t *r, char **s, uint16_t *l) 1095{ 1096 uint16_t clen, len, *p, extra, rdlen; 1097 uint32_t *p2; 1098 char *x; 1099 1100 if (r == NULL) return; 1101 1102 extra = 10; 1103 switch (r->dnstype) 1104 { 1105 case ns_t_a: 1106 extra += 4; 1107 break; 1108 case ns_t_ptr: 1109 extra += 2; 1110 clen = _dns_cname_length(r->data.PTR->name); 1111 extra += clen; 1112 break; 1113 default: break; 1114 } 1115 1116 len = *l + _dns_cname_length(r->name) + 2 + extra; 1117 *s = realloc(*s, len); 1118 1119 _dns_insert_cname(r->name, (char *)*s + *l); 1120 *l = len; 1121 1122 x = *s + (len - extra); 1123 1124 p = (uint16_t *)x; 1125 *p = htons(r->dnstype); 1126 x += 2; 1127 1128 p = (uint16_t *)x; 1129 *p = htons(r->dnsclass); 1130 x += 2; 1131 1132 p2 = (uint32_t *)x; 1133 *p2 = htonl(r->ttl); 1134 x += 4; 1135 1136 switch (r->dnstype) 1137 { 1138 case ns_t_a: 1139 rdlen = 4; 1140 p = (uint16_t *)x; 1141 *p = htons(rdlen); 1142 x += 2; 1143 1144 p2 = (uint32_t *)x; 1145 *p2 = htons(r->data.A->addr.s_addr); 1146 x += 4; 1147 return; 1148 1149 case ns_t_ptr: 1150 clen = _dns_cname_length(r->data.PTR->name) + 2; 1151 p = (uint16_t *)x; 1152 *p = htons(clen); 1153 x += 2; 1154 _dns_insert_cname(r->data.PTR->name, x); 1155 x += clen; 1156 return; 1157 1158 default: return; 1159 } 1160} 1161 1162char * 1163dns_build_reply(dns_reply_t *dnsr, uint16_t *rl) 1164{ 1165 uint16_t i, len; 1166 dns_header_t *h; 1167 char *s, *x; 1168 1169 if (dnsr == NULL) return NULL; 1170 1171 len = NS_HFIXEDSZ; 1172 1173 s = malloc(len); 1174 x = s + len; 1175 1176 memset(s, 0, len); 1177 *rl = len; 1178 1179 h = (dns_header_t *)s; 1180 1181 h->xid = htons(dnsr->header->xid); 1182 h->flags = htons(dnsr->header->flags); 1183 h->qdcount = htons(dnsr->header->qdcount); 1184 h->ancount = htons(dnsr->header->ancount); 1185 h->nscount = htons(dnsr->header->nscount); 1186 h->arcount = htons(dnsr->header->arcount); 1187 1188 for (i = 0; i < dnsr->header->qdcount; i++) 1189 { 1190 _dns_append_question(dnsr->question[i], &s, rl); 1191 } 1192 1193 for (i = 0; i < dnsr->header->ancount; i++) 1194 { 1195 _dns_append_resource_record(dnsr->answer[i], &s, rl); 1196 } 1197 1198 for (i = 0; i < dnsr->header->nscount; i++) 1199 { 1200 _dns_append_resource_record(dnsr->authority[i], &s, rl); 1201 } 1202 1203 for (i = 0; i < dnsr->header->arcount; i++) 1204 { 1205 _dns_append_resource_record(dnsr->additional[i], &s, rl); 1206 } 1207 1208 return s; 1209} 1210 1211void 1212dns_free_question(dns_question_t *q) 1213{ 1214 if (q == NULL) return; 1215 if (q->name != NULL) free(q->name); 1216 free(q); 1217} 1218 1219void 1220dns_set_buffer_size(dns_handle_t d, uint32_t len) 1221{ 1222 dns_private_handle_t *dns; 1223 if (d == NULL) return; 1224 1225 dns = (dns_private_handle_t *)d; 1226 if (dns->recvsize == len) return; 1227 1228 if (dns->recvbuf != NULL) 1229 { 1230 free(dns->recvbuf); 1231 dns->recvbuf = NULL; 1232 } 1233 1234 dns->recvsize = len; 1235 if (dns->recvsize > DNS_MAX_RECEIVE_SIZE) dns->recvsize = DNS_MAX_RECEIVE_SIZE; 1236 1237 if (dns->recvsize > 0) dns->recvbuf = malloc(dns->recvsize); 1238} 1239 1240uint32_t 1241dns_get_buffer_size(dns_handle_t d) 1242{ 1243 dns_private_handle_t *dns; 1244 if (d == NULL) return 0; 1245 1246 dns = (dns_private_handle_t *)d; 1247 return dns->recvsize; 1248} 1249 1250dns_reply_t * 1251dns_lookup_soa_min(dns_handle_t d, const char *name, uint32_t class, uint32_t type, int *min) 1252{ 1253 dns_private_handle_t *dns; 1254 dns_reply_t *r; 1255 int len; 1256 struct sockaddr_storage *from; 1257 uint32_t fromlen; 1258 1259 if (d == NULL) return NULL; 1260 if (name == NULL) return NULL; 1261 1262 dns = (dns_private_handle_t *)d; 1263 if (min != NULL) *min = -1; 1264 1265 if (dns->recvbuf == NULL) 1266 { 1267 if (dns->recvsize == 0) dns->recvsize = DNS_DEFAULT_RECEIVE_SIZE; 1268 1269 dns->recvbuf = malloc(dns->recvsize); 1270 if (dns->recvbuf == NULL) return NULL; 1271 } 1272 1273 fromlen = sizeof(struct sockaddr_storage); 1274 from = (struct sockaddr_storage *)calloc(1, sizeof(struct sockaddr_storage)); 1275 len = -1; 1276 1277 if (dns->handle_type == DNS_PRIVATE_HANDLE_TYPE_SUPER) 1278 { 1279 _check_cache(dns->sdns); 1280 len = _sdns_search(dns->sdns, name, class, type, 0, 1, dns->recvbuf, dns->recvsize, (struct sockaddr *)from, &fromlen, min); 1281 } 1282 else 1283 { 1284 /* NB. Minumium SOA TTL values are NOT provided when the caller passes a DNS_PRIVATE_HANDLE_TYPE_PLAIN handle */ 1285 len = _pdns_search(dns->sdns, dns->pdns, name, class, type, dns->recvbuf, dns->recvsize, (struct sockaddr *)from, &fromlen); 1286 } 1287 1288 if (len <= 0) 1289 { 1290 free(from); 1291 return NULL; 1292 } 1293 1294 r = dns_parse_packet(dns->recvbuf, len); 1295 1296 if (r == NULL) free(from); 1297 else r->server = (struct sockaddr *)from; 1298 1299 return r; 1300} 1301 1302dns_reply_t * 1303dns_lookup(dns_handle_t d, const char *name, uint32_t class, uint32_t type) 1304{ 1305 int unused = 0; 1306 1307 return dns_lookup_soa_min(d, name, class, type, &unused); 1308} 1309 1310/* 1311 * DNS printing utilities 1312 */ 1313 1314static char * 1315coord_ntoa(int32_t coord, uint32_t islat) 1316{ 1317 int32_t deg, min, sec, secfrac; 1318 static char buf[64]; 1319 char dir; 1320 1321 coord = coord - 0x80000000; 1322 dir = 'N'; 1323 1324 if ((islat == 1) && (coord < 0)) 1325 { 1326 dir = 'S'; 1327 coord = -coord; 1328 } 1329 1330 if (islat == 0) 1331 { 1332 dir = 'E'; 1333 if (coord < 0) 1334 { 1335 dir = 'W'; 1336 coord = -coord; 1337 } 1338 } 1339 1340 secfrac = coord % 1000; 1341 coord = coord / 1000; 1342 sec = coord % 60; 1343 coord = coord / 60; 1344 min = coord % 60; 1345 coord = coord / 60; 1346 deg = coord; 1347 1348 sprintf(buf, "%d %.2d %.2d.%.3d %c", deg, min, sec, secfrac, dir); 1349 return buf; 1350} 1351 1352static char * 1353alt_ntoa(int32_t alt) 1354{ 1355 int32_t ref, m, frac, sign; 1356 static char buf[128]; 1357 1358 ref = 100000 * 100; 1359 sign = 1; 1360 1361 if (alt < ref) 1362 { 1363 alt = ref - alt; 1364 sign = -1; 1365 } 1366 else 1367 { 1368 alt = alt - ref; 1369 } 1370 1371 frac = alt % 100; 1372 m = (alt / 100) * sign; 1373 1374 sprintf(buf, "%d.%.2d", m, frac); 1375 return buf; 1376} 1377 1378static unsigned int 1379poweroften[10] = 1380{ 1, 1381 10, 1382 100, 1383 1000, 1384 10000, 1385 100000, 1386 1000000, 1387 10000000, 1388 100000000, 1389 1000000000 1390}; 1391 1392static char * 1393precsize_ntoa(uint8_t prec) 1394{ 1395 static char buf[19]; 1396 unsigned long val; 1397 int mantissa, exponent; 1398 1399 mantissa = (int)((prec >> 4) & 0x0f) % 10; 1400 exponent = (int)((prec >> 0) & 0x0f) % 10; 1401 1402 val = mantissa * poweroften[exponent]; 1403 1404 sprintf(buf, "%ld.%.2ld", val/100, val%100); 1405 return buf; 1406} 1407 1408const char * 1409dns_type_string(uint16_t t) 1410{ 1411 switch (t) 1412 { 1413 case ns_t_a: return "A "; 1414 case ns_t_ns: return "NS "; 1415 case ns_t_md: return "MD "; 1416 case ns_t_mf: return "MF "; 1417 case ns_t_cname: return "CNAME"; 1418 case ns_t_soa: return "SOA "; 1419 case ns_t_mb: return "MB "; 1420 case ns_t_mg: return "MG "; 1421 case ns_t_mr: return "MR "; 1422 case ns_t_null: return "NULL "; 1423 case ns_t_wks: return "WKS "; 1424 case ns_t_ptr: return "PTR "; 1425 case ns_t_hinfo: return "HINFO"; 1426 case ns_t_minfo: return "MINFO"; 1427 case ns_t_mx: return "MX "; 1428 case ns_t_txt: return "TXT "; 1429 case ns_t_rp: return "PR "; 1430 case ns_t_afsdb: return "AFSDB"; 1431 case ns_t_x25: return "X25 "; 1432 case ns_t_isdn: return "ISDN "; 1433 case ns_t_rt: return "RT "; 1434 case ns_t_nsap: return "NSAP "; 1435 case ns_t_nsap_ptr: return "NSPTR"; 1436 case ns_t_sig: return "SIG "; 1437 case ns_t_key: return "KEY "; 1438 case ns_t_px: return "PX "; 1439 case ns_t_gpos: return "GPOS "; 1440 case ns_t_aaaa: return "AAAA "; 1441 case ns_t_loc: return "LOC "; 1442 case ns_t_nxt: return "NXT "; 1443 case ns_t_eid: return "EID "; 1444 case ns_t_nimloc: return "NIMLC"; 1445 case ns_t_srv: return "SRV "; 1446 case ns_t_atma: return "ATMA "; 1447 case ns_t_naptr: return "NAPTR"; 1448 case ns_t_kx: return "KX "; 1449 case ns_t_cert: return "CERT "; 1450 case ns_t_a6: return "A6 "; 1451 case ns_t_dname: return "DNAME"; 1452 case ns_t_sink: return "SINK "; 1453 case ns_t_opt: return "OPT "; 1454 case ns_t_tkey: return "TKEY "; 1455 case ns_t_tsig: return "TSIG "; 1456 case ns_t_ixfr: return "IXFR "; 1457 case ns_t_axfr: return "AXFR "; 1458 case ns_t_mailb: return "MAILB"; 1459 case ns_t_maila: return "MAILA"; 1460 case ns_t_any: return "ANY "; 1461 case ns_t_zxfr: return "ZXFR "; 1462 default: return "?????"; 1463 } 1464 1465 return "?????"; 1466} 1467 1468int32_t 1469dns_type_number(const char *t, uint16_t *n) 1470{ 1471 if (t == NULL) return -1; 1472 1473 if (!strcasecmp(t, "A")) { *n = ns_t_a; return 0; } 1474 if (!strcasecmp(t, "NS")) { *n = ns_t_ns; return 0; } 1475 if (!strcasecmp(t, "MD")) { *n = ns_t_md; return 0; } 1476 if (!strcasecmp(t, "MF")) { *n = ns_t_mf; return 0; } 1477 if (!strcasecmp(t, "CNAME")) { *n = ns_t_cname; return 0; } 1478 if (!strcasecmp(t, "SOA")) { *n = ns_t_soa; return 0; } 1479 if (!strcasecmp(t, "MB")) { *n = ns_t_mb; return 0; } 1480 if (!strcasecmp(t, "MG")) { *n = ns_t_mg; return 0; } 1481 if (!strcasecmp(t, "MR")) { *n = ns_t_mr; return 0; } 1482 if (!strcasecmp(t, "NULL")) { *n = ns_t_null; return 0; } 1483 if (!strcasecmp(t, "WKS")) { *n = ns_t_wks; return 0; } 1484 if (!strcasecmp(t, "PTR")) { *n = ns_t_ptr; return 0; } 1485 if (!strcasecmp(t, "HINFO")) { *n = ns_t_hinfo; return 0; } 1486 if (!strcasecmp(t, "MINFO")) { *n = ns_t_minfo; return 0; } 1487 if (!strcasecmp(t, "MX")) { *n = ns_t_mx; return 0; } 1488 if (!strcasecmp(t, "TXT")) { *n = ns_t_txt; return 0; } 1489 if (!strcasecmp(t, "RP")) { *n = ns_t_rp; return 0; } 1490 if (!strcasecmp(t, "AFSDB")) { *n = ns_t_afsdb; return 0; } 1491 if (!strcasecmp(t, "X25")) { *n = ns_t_x25; return 0; } 1492 if (!strcasecmp(t, "ISDN")) { *n = ns_t_isdn; return 0; } 1493 if (!strcasecmp(t, "RT")) { *n = ns_t_rt; return 0; } 1494 if (!strcasecmp(t, "NSAP")) { *n = ns_t_nsap; return 0; } 1495 if (!strcasecmp(t, "NSPTR")) { *n = ns_t_nsap_ptr; return 0; } 1496 if (!strcasecmp(t, "NSAP_PTR")){ *n = ns_t_nsap_ptr; return 0; } 1497 if (!strcasecmp(t, "SIG")) { *n = ns_t_sig; return 0; } 1498 if (!strcasecmp(t, "KEY")) { *n = ns_t_key; return 0; } 1499 if (!strcasecmp(t, "PX")) { *n = ns_t_px; return 0; } 1500 if (!strcasecmp(t, "GPOS")) { *n = ns_t_gpos; return 0; } 1501 if (!strcasecmp(t, "AAAA")) { *n = ns_t_aaaa; return 0; } 1502 if (!strcasecmp(t, "LOC")) { *n = ns_t_loc; return 0; } 1503 if (!strcasecmp(t, "NXT")) { *n = ns_t_nxt; return 0; } 1504 if (!strcasecmp(t, "EID")) { *n = ns_t_eid; return 0; } 1505 if (!strcasecmp(t, "NIMLOC")) { *n = ns_t_nimloc; return 0; } 1506 if (!strcasecmp(t, "SRV")) { *n = ns_t_srv; return 0; } 1507 if (!strcasecmp(t, "ATMA")) { *n = ns_t_atma; return 0; } 1508 if (!strcasecmp(t, "NAPTR")) { *n = ns_t_naptr; return 0; } 1509 if (!strcasecmp(t, "KX")) { *n = ns_t_kx; return 0; } 1510 if (!strcasecmp(t, "CERT")) { *n = ns_t_cert; return 0; } 1511 if (!strcasecmp(t, "A6")) { *n = ns_t_a6; return 0; } 1512 if (!strcasecmp(t, "DNAME")) { *n = ns_t_dname; return 0; } 1513 if (!strcasecmp(t, "SINK")) { *n = ns_t_sink; return 0; } 1514 if (!strcasecmp(t, "OPT")) { *n = ns_t_opt; return 0; } 1515 if (!strcasecmp(t, "TKEY")) { *n = ns_t_tkey; return 0; } 1516 if (!strcasecmp(t, "TSIG")) { *n = ns_t_tsig; return 0; } 1517 if (!strcasecmp(t, "IXFR")) { *n = ns_t_ixfr; return 0; } 1518 if (!strcasecmp(t, "AXFR")) { *n = ns_t_axfr; return 0; } 1519 if (!strcasecmp(t, "MAILB")) { *n = ns_t_mailb; return 0; } 1520 if (!strcasecmp(t, "MAILA")) { *n = ns_t_maila; return 0; } 1521 if (!strcasecmp(t, "ANY")) { *n = ns_t_any; return 0; } 1522 if (!strcasecmp(t, "ZXFR")) { *n = ns_t_zxfr; return 0; } 1523 1524 return -1; 1525} 1526 1527const char * 1528dns_class_string(uint16_t c) 1529{ 1530 switch (c) 1531 { 1532 case ns_c_in: return "IN"; 1533 case ns_c_2: return "CS"; 1534 case ns_c_chaos: return "CH"; 1535 case ns_c_hs: return "HS"; 1536 case ns_c_none: return "NONE"; 1537 case ns_c_any: return "ANY"; 1538 default: return "??"; 1539 } 1540 1541 return "??"; 1542} 1543 1544int32_t 1545dns_class_number(const char *c, uint16_t *n) 1546{ 1547 if (c == NULL) return -1; 1548 1549 if (!strcasecmp(c, "IN")) { *n = ns_c_in; return 0; } 1550 if (!strcasecmp(c, "CS")) { *n = ns_c_2; return 0; } 1551 if (!strcasecmp(c, "CH")) { *n = ns_c_chaos; return 0; } 1552 if (!strcasecmp(c, "HS")) { *n = ns_c_hs; return 0; } 1553 if (!strcasecmp(c, "NONE")) { *n = ns_c_none; return 0; } 1554 if (!strcasecmp(c, "ANY")) { *n = ns_c_any; return 0; } 1555 1556 return -1; 1557} 1558 1559static void 1560_dns_print_question_lock(const dns_question_t *q, FILE *f, int lockit) 1561{ 1562 if (lockit != 0) _dns_print_lock(); 1563 fprintf(f, "%s %s %s\n", q->name, dns_class_string(q->dnsclass), dns_type_string(q->dnstype)); 1564 if (lockit != 0) _dns_print_unlock(); 1565} 1566 1567void 1568dns_print_question(const dns_question_t *q, FILE *f) 1569{ 1570 _dns_print_question_lock(q, f, 1); 1571} 1572 1573static void 1574_dns_print_resource_record_lock(const dns_resource_record_t *r, FILE *f, int lockit) 1575{ 1576 struct protoent *p; 1577 struct servent *s; 1578 uint32_t i, len; 1579 uint8_t x; 1580 struct sockaddr_in6 s6; 1581 char pbuf[64]; 1582 1583 if (lockit != 0) _dns_print_lock(); 1584 1585 fprintf(f, "%s %s %s ", r->name, dns_class_string(r->dnsclass), dns_type_string(r->dnstype)); 1586 fprintf(f, "%u", r->ttl); 1587 1588 switch (r->dnstype) 1589 { 1590 case ns_t_a: 1591 fprintf(f, " %s", inet_ntoa(r->data.A->addr)); 1592 break; 1593 1594 case ns_t_aaaa: 1595 memset(&s6, 0, sizeof(struct sockaddr_in6)); 1596 s6.sin6_len = sizeof(struct sockaddr_in6); 1597 s6.sin6_family = AF_INET6; 1598 s6.sin6_addr = r->data.AAAA->addr; 1599 fprintf(f, " %s", inet_ntop(AF_INET6, (char *)(&s6) + INET_NTOP_AF_INET6_OFFSET, pbuf, 64)); 1600 break; 1601 1602 case ns_t_md: 1603 case ns_t_mf: 1604 case ns_t_cname: 1605 case ns_t_mb: 1606 case ns_t_mg: 1607 case ns_t_mr: 1608 case ns_t_ptr: 1609 case ns_t_ns: 1610 fprintf(f, " %s", r->data.CNAME->name); 1611 break; 1612 1613 case ns_t_soa: 1614 fprintf(f, " %s %s %u %u %u %u %u", 1615 r->data.SOA->mname, r->data.SOA->rname, 1616 r->data.SOA->serial, r->data.SOA->refresh, r->data.SOA->retry, 1617 r->data.SOA->expire, r->data.SOA->minimum); 1618 break; 1619 1620 case ns_t_wks: 1621 fprintf(f, " %s", inet_ntoa(r->data.WKS->addr)); 1622 p = getprotobynumber(r->data.WKS->protocol); 1623 if (p != NULL) 1624 { 1625 fprintf(f, " %s", p->p_name); 1626 1627 for (i = 0; i < r->data.WKS->maplength; i++) 1628 { 1629 if (r->data.WKS->map[i]) 1630 { 1631 s = getservbyport(i, p->p_name); 1632 if (s == NULL) fprintf(f, " %u", i); 1633 else fprintf(f, " %s", s->s_name); 1634 } 1635 } 1636 } 1637 else fprintf(f, " UNKNOWN PROTOCOL %u", r->data.WKS->protocol); 1638 break; 1639 1640 case ns_t_hinfo: 1641 fprintf(f, " %s %s", r->data.HINFO->cpu, r->data.HINFO->os); 1642 break; 1643 1644 case ns_t_minfo: 1645 fprintf(f, " %s %s", r->data.MINFO->rmailbx, r->data.MINFO->emailbx); 1646 break; 1647 1648 case ns_t_mx: 1649 fprintf(f, " %u %s", r->data.MX->preference, r->data.MX->name); 1650 break; 1651 1652 case ns_t_txt: 1653 for (i = 0; i < r->data.TXT->string_count; i++) 1654 { 1655 fprintf(f, " \"%s\"", r->data.TXT->strings[i]); 1656 } 1657 break; 1658 1659 case ns_t_rp: 1660 fprintf(f, " %s %s", r->data.RP->mailbox, r->data.RP->txtdname); 1661 break; 1662 1663 case ns_t_afsdb: 1664 fprintf(f, " %u %s", r->data.AFSDB->subtype, 1665 r->data.AFSDB->hostname); 1666 break; 1667 1668 case ns_t_x25: 1669 fprintf(f, " %s", r->data.X25->psdn_address); 1670 break; 1671 1672 case ns_t_isdn: 1673 fprintf(f, " %s", r->data.ISDN->isdn_address); 1674 if (r->data.ISDN->subaddress != NULL) 1675 fprintf(f, " %s", r->data.ISDN->subaddress); 1676 break; 1677 1678 case ns_t_rt: 1679 fprintf(f, " %hu %s", r->data.RT->preference, 1680 r->data.RT->intermediate); 1681 break; 1682 1683 case ns_t_loc: 1684 fprintf(f, " %s", coord_ntoa(r->data.LOC->latitude, 1)); 1685 fprintf(f, " %s", coord_ntoa(r->data.LOC->longitude, 0)); 1686 fprintf(f, " %sm", alt_ntoa(r->data.LOC->altitude)); 1687 fprintf(f, " %sm", precsize_ntoa(r->data.LOC->size)); 1688 fprintf(f, " %sm", precsize_ntoa(r->data.LOC->horizontal_precision)); 1689 fprintf(f, " %sm", precsize_ntoa(r->data.LOC->vertical_precision)); 1690 break; 1691 1692 case ns_t_srv: 1693 fprintf(f, " %hu %hu %hu %s", 1694 r->data.SRV->priority, r->data.SRV->weight, 1695 r->data.SRV->port, r->data.SRV->target); 1696 break; 1697 1698 case ns_t_null: 1699 default: 1700 len = r->data.DNSNULL->length; 1701 fprintf(f, " %u ", len); 1702 for (i = 0; i < len; i++) 1703 { 1704 x = r->data.DNSNULL->data[i]; 1705 fprintf(f, "%x", x); 1706 } 1707 1708 fprintf(f, " ("); 1709 1710 len = r->data.DNSNULL->length; 1711 for (i = 0; i < len; i++) 1712 { 1713 x = r->data.DNSNULL->data[i]; 1714 if (isascii(x)) fprintf(f, "%c", x); 1715 else fprintf(f, " "); 1716 } 1717 fprintf(f, ")\n"); 1718 1719 } 1720 1721 fprintf(f, "\n"); 1722 1723 if (lockit != 0) _dns_print_unlock(); 1724} 1725 1726void 1727dns_print_resource_record(const dns_resource_record_t *r, FILE *f) 1728{ 1729 _dns_print_resource_record_lock(r, f, 1); 1730} 1731 1732void 1733dns_print_reply(const dns_reply_t *r, FILE *f, uint16_t mask) 1734{ 1735 uint16_t i; 1736 dns_header_t *h; 1737 char scratch[1024]; 1738 uint32_t offset, iface; 1739 1740 _dns_print_lock(); 1741 1742 if (r == NULL) 1743 { 1744 fprintf(f, "-nil-\n"); 1745 _dns_print_unlock(); 1746 return; 1747 } 1748 1749 if (r->status != DNS_STATUS_OK) 1750 { 1751 if (r->status == DNS_STATUS_TIMEOUT) 1752 fprintf(f, "Timeout\n"); 1753 else if (r->status == DNS_STATUS_SEND_FAILED) 1754 fprintf(f, "Send failed\n"); 1755 else if (r->status == DNS_STATUS_RECEIVE_FAILED) 1756 fprintf(f, "Receive failed\n"); 1757 else fprintf(f, "status %u\n", r->status); 1758 1759 _dns_print_unlock(); 1760 return; 1761 } 1762 1763 h = r->header; 1764 1765 if (mask & DNS_PRINT_XID) 1766 { 1767 fprintf(f, "Xid: %u\n", h->xid); 1768 } 1769 1770 if (mask & DNS_PRINT_QR) 1771 { 1772 if ((h->flags & DNS_FLAGS_QR_MASK) == DNS_FLAGS_QR_QUERY) 1773 fprintf(f, "QR: Query\n"); 1774 else 1775 fprintf(f, "QR: Reply\n"); 1776 } 1777 1778 if (mask & DNS_PRINT_SERVER) 1779 { 1780 if (r->server == NULL) 1781 { 1782 fprintf(f, "Server: -nil-\n"); 1783 } 1784 else 1785 { 1786 offset = INET_NTOP_AF_INET_OFFSET; 1787 if (r->server->sa_family == AF_INET6) offset = INET_NTOP_AF_INET6_OFFSET; 1788 1789 fprintf(f, "Server: %s", inet_ntop(r->server->sa_family, (char *)(r->server) + offset, scratch, 1024)); 1790 if (r->server->sa_family == AF_INET) 1791 { 1792 memcpy(&iface, (((struct sockaddr_in *)(r->server))->sin_zero), 4); 1793 if (iface > 0) fprintf(f, "%%%s", if_indextoname(iface, scratch)); 1794 } 1795 else if (r->server->sa_family == AF_INET6) 1796 { 1797 iface = ((struct sockaddr_in6 *)(r->server))->sin6_scope_id; 1798 if (iface > 0) fprintf(f, "%%%s", if_indextoname(iface, scratch)); 1799 } 1800 fprintf(f, "\n"); 1801 } 1802 } 1803 1804 if (mask & DNS_PRINT_OPCODE) 1805 { 1806 fprintf(f, "Opcode: "); 1807 switch (h->flags & DNS_FLAGS_OPCODE_MASK) 1808 { 1809 case ns_o_query: fprintf(f, "Standard\n"); break; 1810 case ns_o_iquery: fprintf(f, "Inverse\n"); break; 1811 case ns_o_status: fprintf(f, "Status\n"); break; 1812 case ns_o_notify: fprintf(f, "Notify\n"); break; 1813 case ns_o_update: fprintf(f, "Update\n"); break; 1814 default: 1815 fprintf(f, "Reserved (%hu)\n", 1816 (uint16_t)((h->flags & DNS_FLAGS_OPCODE_MASK) >> 11)); 1817 } 1818 } 1819 1820 if (mask & DNS_PRINT_AA) 1821 { 1822 if (h->flags & DNS_FLAGS_AA) fprintf(f, "AA: Authoritative\n"); 1823 else fprintf(f, "AA: Non-Authoritative\n"); 1824 } 1825 1826 if (mask & DNS_PRINT_TC) 1827 { 1828 if (h->flags & DNS_FLAGS_TC) fprintf(f, "TC: Truncated\n"); 1829 else fprintf(f, "TC: Non-Truncated\n"); 1830 } 1831 1832 if (mask & DNS_PRINT_RD) 1833 { 1834 if (h->flags & DNS_FLAGS_RD) fprintf(f, "RD: Recursion desired\n"); 1835 else fprintf(f, "RD: No recursion desired\n"); 1836 } 1837 1838 if (mask & DNS_PRINT_RA) 1839 { 1840 if (h->flags & DNS_FLAGS_RA) fprintf(f, "RA: Recursion available\n"); 1841 else fprintf(f, "RA: No recursion available \n"); 1842 } 1843 1844 if (mask & DNS_PRINT_RCODE) 1845 { 1846 fprintf(f, "Rcode: "); 1847 switch (h->flags & DNS_FLAGS_RCODE_MASK) 1848 { 1849 case ns_r_noerror: 1850 fprintf(f, "No error\n"); 1851 break; 1852 case ns_r_formerr: 1853 fprintf(f, "Format error \n"); 1854 break; 1855 case ns_r_servfail: 1856 fprintf(f, "Server failure\n"); 1857 break; 1858 case ns_r_nxdomain: 1859 fprintf(f, "Name error \n"); 1860 break; 1861 case ns_r_notimpl: 1862 fprintf(f, "Not implemented\n"); 1863 break; 1864 case ns_r_refused: 1865 fprintf(f, "Refused\n"); 1866 break; 1867 case ns_r_yxdomain: 1868 fprintf(f, "Name exists\n"); 1869 break; 1870 case ns_r_yxrrset: 1871 fprintf(f, "RR Set exists\n"); 1872 break; 1873 case ns_r_nxrrset: 1874 fprintf(f, "RR Set does not exist\n"); 1875 break; 1876 case ns_r_notauth: 1877 fprintf(f, "Not authoritative\n"); 1878 break; 1879 case ns_r_notzone: 1880 fprintf(f, "Record zone does not match section zone\n"); 1881 break; 1882 case ns_r_badvers: 1883 fprintf(f, "Invalid EDNS version or TSIG signature\n"); 1884 break; 1885 case ns_r_badkey: 1886 fprintf(f, "Invalid key\n"); 1887 break; 1888 case ns_r_badtime: 1889 fprintf(f, "Invalid time\n"); 1890 break; 1891 default: 1892 fprintf(f, "Reserved (%hu)\n",(uint16_t)(h->flags & DNS_FLAGS_RCODE_MASK)); 1893 } 1894 } 1895 1896 if (mask & DNS_PRINT_QUESTION) 1897 { 1898 fprintf(f, "Question (%hu):\n", h->qdcount); 1899 for (i = 0; i < h->qdcount; i++) 1900 _dns_print_question_lock(r->question[i], f, 0); 1901 } 1902 1903 if (mask & DNS_PRINT_ANSWER) 1904 { 1905 fprintf(f, "Answer (%hu):\n", h->ancount); 1906 for (i = 0; i < h->ancount; i++) 1907 _dns_print_resource_record_lock(r->answer[i], f, 0); 1908 } 1909 1910 if (mask & DNS_PRINT_AUTHORITY) 1911 { 1912 fprintf(f, "Authority (%hu):\n", h->nscount); 1913 for (i = 0; i < h->nscount; i++) 1914 _dns_print_resource_record_lock(r->authority[i], f, 0); 1915 } 1916 1917 if (mask & DNS_PRINT_ADDITIONAL) 1918 { 1919 fprintf(f, "Additional records (%hu):\n", h->arcount); 1920 for (i = 0; i < h->arcount; i++) 1921 _dns_print_resource_record_lock(r->additional[i], f, 0); 1922 } 1923 1924 _dns_print_unlock(); 1925} 1926 1927static void 1928_pdns_print_handle(pdns_handle_t *pdns, FILE *f) 1929{ 1930 uint32_t i, offset; 1931 struct in_addr a; 1932 char scratch[1024]; 1933 struct sockaddr *sa; 1934 res_state r; 1935 1936 if (pdns == NULL) 1937 { 1938 fprintf(f, "-nil-\n"); 1939 return; 1940 } 1941 1942 if (pdns->name == NULL) fprintf(f, "Name: -nil-\n"); 1943 else fprintf(f, "Name: %s\n", pdns->name); 1944 1945 fprintf(f, "Flags:"); 1946 if (pdns->flags == 0) fprintf(f, " None\n"); 1947 else 1948 { 1949 if (pdns->flags & DNS_FLAG_DEBUG) fprintf(f, " Debug"); 1950 if (pdns->flags & DNS_FLAG_CHECK_RESOLVER_DIR) fprintf(f, " DirCheck"); 1951 if (pdns->flags & DNS_FLAG_HAVE_IPV6_SERVER) fprintf(f, " IPv6"); 1952 if (pdns->flags & DNS_FLAG_OK_TO_SKIP_AAAA) fprintf(f, " SkipAAAA"); 1953 if (pdns->flags & DNS_FLAG_DEFAULT_RESOLVER) fprintf(f, " Default"); 1954 fprintf(f, "\n"); 1955 } 1956 1957 r = pdns->res; 1958 if (r == NULL) return; 1959 1960 if (r->defdname[0] != '\0') fprintf(f, "Domain: %s\n", r->defdname); 1961 fprintf(f, "Search Order: %d\n", pdns->search_order); 1962 fprintf(f, "Total Timeout: %d\n", pdns->total_timeout); 1963 fprintf(f, "Retry Timeout: %d\n", pdns->res->retrans); 1964 fprintf(f, "Retry Attempts: %d\n", pdns->res->retry); 1965 1966 fprintf(f, "Server%s:\n", (r->nscount == 1) ? "" : "s"); 1967 for (i = 0; i < r->nscount; i++) 1968 { 1969 sa = get_nsaddr(r, i); 1970 offset = INET_NTOP_AF_INET_OFFSET; 1971 if (sa->sa_family == AF_INET6) offset = INET_NTOP_AF_INET6_OFFSET; 1972 fprintf(f, " %u: %s", i, inet_ntop(sa->sa_family, (char *)sa + offset, scratch, 1024)); 1973 fprintf(f, "\n"); 1974 } 1975 1976 if (pdns->search_count > 0) 1977 { 1978 fprintf(f, "Search List:\n"); 1979 for (i = 0; i < pdns->search_count; i++) 1980 fprintf(f, " %u: %s\n", i, pdns->search_list[i]); 1981 } 1982 1983 if (r->sort_list[0].addr.s_addr != 0) 1984 { 1985 fprintf(f, "Sortlist:\n"); 1986 for (i = 0; (r->sort_list[i].addr.s_addr != 0); i++) 1987 { 1988 fprintf(f, " %u: ", i); 1989 a.s_addr = r->sort_list[i].addr.s_addr; 1990 fprintf(f, "%s/", inet_ntoa(a)); 1991 a.s_addr = r->sort_list[i].mask; 1992 fprintf(f, "%s\n", inet_ntoa(a)); 1993 } 1994 } 1995} 1996 1997static void 1998_sdns_print_handle(sdns_handle_t *sdns, FILE *f) 1999{ 2000 int i; 2001 2002 if (sdns == NULL) 2003 { 2004 fprintf(f, "-nil-\n"); 2005 return; 2006 } 2007 2008 for (i = 0; i < sdns->client_count; i++) 2009 { 2010 fprintf(f, "DNS client %d\n", i); 2011 _pdns_print_handle(sdns->client[i], f); 2012 fprintf(f, "\n"); 2013 } 2014 2015 fprintf(f, "resolver dir mod time = %u\n", sdns->modtime); 2016 fprintf(f, "resolver dir stat time = %u\n", sdns->stattime); 2017 fprintf(f, "resolver dir stat latency = %u\n", sdns->stat_latency); 2018} 2019 2020void 2021dns_print_handle(dns_handle_t d, FILE *f) 2022{ 2023 dns_private_handle_t *dns; 2024 2025 _dns_print_lock(); 2026 2027 if (d == NULL) 2028 { 2029 fprintf(f, "-nil-\n"); 2030 _dns_print_unlock(); 2031 return; 2032 } 2033 2034 dns = (dns_private_handle_t *)d; 2035 2036 if (dns->handle_type == DNS_PRIVATE_HANDLE_TYPE_SUPER) 2037 { 2038 _sdns_print_handle(dns->sdns, f); 2039 } 2040 else 2041 { 2042 _pdns_print_handle(dns->pdns, f); 2043 } 2044 2045 _dns_print_unlock(); 2046} 2047 2048void 2049dns_all_server_addrs(dns_handle_t d, struct sockaddr ***addrs, uint32_t *count) 2050{ 2051 int i, j, k, n, found; 2052 dns_private_handle_t *dns; 2053 pdns_handle_t *pdns; 2054 struct sockaddr *sa; 2055 struct sockaddr_storage **l; 2056 res_state r; 2057 2058 *addrs = NULL; 2059 *count = 0; 2060 l = NULL; 2061 n = 0; 2062 2063 if (d == NULL) return; 2064 2065 dns = (dns_private_handle_t *)d; 2066 2067 if (dns->handle_type != DNS_PRIVATE_HANDLE_TYPE_SUPER) return; 2068 2069 if (dns->sdns == NULL) return; 2070 2071 /* Just to initialize / validate clients */ 2072 i = dns_search_list_count(d); 2073 2074 for (i = 0; i < dns->sdns->client_count; i++) 2075 { 2076 pdns = dns->sdns->client[i]; 2077 if (pdns == NULL) continue; 2078 2079 r = pdns->res; 2080 if (r == NULL) continue; 2081 2082 for (j = 0; j < r->nscount; j++) 2083 { 2084 sa = get_nsaddr(r, j); 2085 found = 0; 2086 for (k = 0; (found == 0) && (k < n); k++) 2087 { 2088 if (memcmp(l[k], sa, sa->sa_len) == 0) found = 1; 2089 } 2090 if (found == 1) continue; 2091 2092 if (n == 0) 2093 { 2094 l = (struct sockaddr_storage **)calloc(1, sizeof(struct sockaddr_storage *)); 2095 } 2096 else 2097 { 2098 l = (struct sockaddr_storage **)reallocf(l, (n + 1) * sizeof(struct sockaddr_storage *)); 2099 } 2100 2101 if (l == NULL) return; 2102 2103 l[n] = (struct sockaddr_storage *)calloc(1, sizeof(struct sockaddr_storage)); 2104 if (l[n] == NULL) return; 2105 2106 memset(l[n], 0, sizeof(struct sockaddr_storage)); 2107 memcpy(l[n], sa, sa->sa_len); 2108 n++; 2109 } 2110 } 2111 2112 *addrs = (struct sockaddr **)l; 2113 *count = n; 2114} 2115 2116int 2117dns_res_once(struct sockaddr *server, struct timeval *timeout, int options, const char *name, int class, int type, u_char *res, int *reslen) 2118{ 2119 res_state statp; 2120 int n, fromlen, status; 2121 struct sockaddr_storage from; 2122 u_char buf[MAXPACKET]; 2123 2124 if (server == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT; 2125 if (name == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT; 2126 if (res == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT; 2127 if (reslen == NULL) return DNS_RES_STATUS_INVALID_ARGUMENT; 2128 2129 fromlen = sizeof(struct sockaddr_storage); 2130 2131 statp = res_state_new(); 2132 statp->retry = 1; 2133 statp->options = options; 2134 statp->id = res_randomid(); 2135 if (timeout == NULL) statp->retrans = 5; 2136 else statp->retrans = timeout->tv_sec; 2137 2138 statp->ndots = 1; 2139 statp->_vcsock = -1; 2140 statp->nscount = 1; 2141 2142 strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa"); 2143 strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int"); 2144 strcpy(statp->_u._ext.ext->bsuffix, "ip6.arpa"); 2145 2146 if (server->sa_family == AF_INET6) 2147 { 2148 memcpy(&(statp->_u._ext.ext->nsaddrs[0]), server, sizeof(struct sockaddr_in6)); 2149 statp->nsaddr_list[0].sin_family = 0; 2150 } 2151 else 2152 { 2153 memcpy(&(statp->_u._ext.ext->nsaddrs[0]), server, sizeof(struct sockaddr_in)); 2154 memcpy(&(statp->nsaddr_list[0]), server, sizeof(struct sockaddr_in)); 2155 } 2156 2157 n = res_nmkquery(statp, ns_o_query, name, class, type, NULL, 0, NULL, buf, sizeof(buf)); 2158 2159 status = dns_res_send(statp, buf, n, res, reslen, (struct sockaddr *)&from, &fromlen); 2160 2161 res_client_close(statp); 2162 2163 return status; 2164} 2165