1 /* 2 * Copyright (c) 2000-2004, 2010, 2015, 2020 Proofpoint, Inc. and its suppliers. 3 * All rights reserved. 4 * 5 * By using this file, you agree to the terms and conditions set 6 * forth in the LICENSE file which can be found at the top level of 7 * the sendmail distribution. 8 * 9 */ 10 11 /* 12 * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H�gskolan 13 * (Royal Institute of Technology, Stockholm, Sweden). 14 * All rights reserved. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 20 * 1. Redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer. 22 * 23 * 2. Redistributions in binary form must reproduce the above copyright 24 * notice, this list of conditions and the following disclaimer in the 25 * documentation and/or other materials provided with the distribution. 26 * 27 * 3. Neither the name of the Institute nor the names of its contributors 28 * may be used to endorse or promote products derived from this software 29 * without specific prior written permission. 30 * 31 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 32 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 33 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 34 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 35 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 39 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 40 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 41 * SUCH DAMAGE. 42 */ 43 44 #include <sendmail.h> 45 #if DNSMAP || DANE 46 # if NAMED_BIND 47 # if NETINET 48 # include <netinet/in_systm.h> 49 # include <netinet/ip.h> 50 # endif 51 # define _DEFINE_SMR_GLOBALS 1 52 # include "sm_resolve.h" 53 54 #include <arpa/inet.h> 55 56 SM_RCSID("$Id: sm_resolve.c,v 8.40 2013-11-22 20:51:56 ca Exp $") 57 58 static struct stot 59 { 60 const char *st_name; 61 int st_type; 62 } stot[] = 63 { 64 # if NETINET 65 { "A", T_A }, 66 # endif 67 # if NETINET6 68 { "AAAA", T_AAAA }, 69 # endif 70 { "NS", T_NS }, 71 { "CNAME", T_CNAME }, 72 { "PTR", T_PTR }, 73 { "MX", T_MX }, 74 { "TXT", T_TXT }, 75 { "AFSDB", T_AFSDB }, 76 { "SRV", T_SRV }, 77 # ifdef T_DS 78 { "DS", T_DS }, 79 # endif 80 { "RRSIG", T_RRSIG }, 81 # ifdef T_NSEC 82 { "NSEC", T_NSEC }, 83 # endif 84 # ifdef T_DNSKEY 85 { "DNSKEY", T_DNSKEY }, 86 # endif 87 { "TLSA", T_TLSA }, 88 { NULL, 0 } 89 }; 90 91 static DNS_REPLY_T *parse_dns_reply __P((unsigned char *, int, unsigned int)); 92 # if DNSSEC_TEST && defined(T_TLSA) 93 static char *hex2bin __P((const char *, int)); 94 # endif 95 96 /* 97 ** DNS_STRING_TO_TYPE -- convert resource record name into type 98 ** 99 ** Parameters: 100 ** name -- name of resource record type 101 ** 102 ** Returns: 103 ** type if succeeded. 104 ** -1 otherwise. 105 */ 106 107 int 108 dns_string_to_type(name) 109 const char *name; 110 { 111 struct stot *p = stot; 112 113 for (p = stot; p->st_name != NULL; p++) 114 if (sm_strcasecmp(name, p->st_name) == 0) 115 return p->st_type; 116 return -1; 117 } 118 119 /* 120 ** DNS_TYPE_TO_STRING -- convert resource record type into name 121 ** 122 ** Parameters: 123 ** type -- resource record type 124 ** 125 ** Returns: 126 ** name if succeeded. 127 ** NULL otherwise. 128 */ 129 130 const char * 131 dns_type_to_string(type) 132 int type; 133 { 134 struct stot *p = stot; 135 136 for (p = stot; p->st_name != NULL; p++) 137 if (type == p->st_type) 138 return p->st_name; 139 return NULL; 140 } 141 142 /* 143 ** DNS_FREE_DATA -- free all components of a DNS_REPLY_T 144 ** 145 ** Parameters: 146 ** dr -- pointer to DNS_REPLY_T 147 ** 148 ** Returns: 149 ** none. 150 */ 151 152 void 153 dns_free_data(dr) 154 DNS_REPLY_T *dr; 155 { 156 RESOURCE_RECORD_T *rr; 157 158 if (dr == NULL) 159 return; 160 if (dr->dns_r_q.dns_q_domain != NULL) 161 sm_free(dr->dns_r_q.dns_q_domain); 162 for (rr = dr->dns_r_head; rr != NULL; ) 163 { 164 RESOURCE_RECORD_T *tmp = rr; 165 166 if (rr->rr_domain != NULL) 167 sm_free(rr->rr_domain); 168 if (rr->rr_u.rr_data != NULL) 169 sm_free(rr->rr_u.rr_data); 170 rr = rr->rr_next; 171 sm_free(tmp); 172 } 173 sm_free(dr); 174 } 175 176 /* 177 ** BIN2HEX -- convert binary TLSA RR to hex string 178 ** 179 ** Parameters: 180 ** tlsa -- pointer to result (allocated here) 181 ** p -- binary data (TLSA RR) 182 ** size -- length of p 183 ** min_size -- minimum expected size 184 ** 185 ** Returns: 186 ** >0: length of string (*tlsa) 187 ** -1: error 188 */ 189 190 static int bin2hex __P((char **, unsigned char *, int, int)); 191 192 static int 193 bin2hex(tlsa, p, size, min_size) 194 char **tlsa; 195 unsigned char *p; 196 int size; 197 int min_size; 198 { 199 int i, pos, txtlen; 200 201 txtlen = size * 3; 202 if (txtlen <= size || size < min_size) 203 { 204 if (LogLevel > 5) 205 sm_syslog(LOG_WARNING, NOQID, 206 "ERROR: bin2hex: size %d wrong", size); 207 return -1; 208 } 209 *tlsa = (char *) sm_malloc(txtlen); 210 if (*tlsa == NULL) 211 { 212 if (tTd(8, 17)) 213 sm_dprintf("len=%d, rr_data=NULL\n", txtlen); 214 return -1; 215 } 216 snprintf(*tlsa, txtlen, 217 "%02X %02X %02X", p[0], p[1], p[2]); 218 pos = strlen(*tlsa); 219 220 /* why isn't there a print function like strlcat? */ 221 for (i = 3; i < size && pos < txtlen; i++, pos += 3) 222 snprintf(*tlsa + pos, txtlen - pos, "%c%02X", 223 (i == 3) ? ' ' : ':', p[i]); 224 225 return i; 226 } 227 228 /* 229 ** PARSE_DNS_REPLY -- parse DNS reply data. 230 ** 231 ** Parameters: 232 ** data -- pointer to dns data 233 ** len -- len of data 234 ** flags -- flags (RR_*) 235 ** 236 ** Returns: 237 ** pointer to DNS_REPLY_T if succeeded. 238 ** NULL otherwise. 239 ** 240 ** Note: 241 ** use dns_free_data() to free() the result when no longer needed. 242 */ 243 244 static DNS_REPLY_T * 245 parse_dns_reply(data, len, flags) 246 unsigned char *data; 247 int len; 248 unsigned int flags; 249 { 250 unsigned char *p; 251 unsigned short ans_cnt, ui; 252 int status; 253 size_t l; 254 char host[MAXHOSTNAMELEN]; 255 DNS_REPLY_T *dr; 256 RESOURCE_RECORD_T **rr; 257 258 if (tTd(8, 90)) 259 { 260 FILE *fp; 261 262 fp = fopen("dns.buffer", "w"); 263 if (fp != NULL) 264 { 265 fwrite(data, 1, len, fp); 266 fclose(fp); 267 fp = NULL; 268 } 269 else 270 sm_dprintf("parse_dns_reply: fp=%p, e=%d\n", 271 (void *)fp, errno); 272 } 273 274 dr = (DNS_REPLY_T *) sm_malloc(sizeof(*dr)); 275 if (dr == NULL) 276 return NULL; 277 memset(dr, 0, sizeof(*dr)); 278 279 p = data; 280 281 /* doesn't work on Crays? */ 282 memcpy(&dr->dns_r_h, p, sizeof(dr->dns_r_h)); 283 p += sizeof(dr->dns_r_h); 284 status = dn_expand(data, data + len, p, host, sizeof(host)); 285 if (status < 0) 286 goto error; 287 dr->dns_r_q.dns_q_domain = sm_strdup(host); 288 if (dr->dns_r_q.dns_q_domain == NULL) 289 goto error; 290 291 ans_cnt = ntohs((unsigned short) dr->dns_r_h.ancount); 292 if (tTd(8, 17)) 293 sm_dprintf("parse_dns_reply: ac=%d, ad=%d\n", ans_cnt, 294 dr->dns_r_h.ad); 295 296 p += status; 297 GETSHORT(dr->dns_r_q.dns_q_type, p); 298 GETSHORT(dr->dns_r_q.dns_q_class, p); 299 rr = &dr->dns_r_head; 300 ui = 0; 301 while (p < data + len && ui < ans_cnt) 302 { 303 int type, class, ttl, size, txtlen; 304 305 status = dn_expand(data, data + len, p, host, sizeof(host)); 306 if (status < 0) 307 goto error; 308 ++ui; 309 p += status; 310 GETSHORT(type, p); 311 GETSHORT(class, p); 312 GETLONG(ttl, p); 313 GETSHORT(size, p); 314 if (p + size > data + len) 315 { 316 /* 317 ** announced size of data exceeds length of 318 ** data paket: someone is cheating. 319 */ 320 321 if (LogLevel > 5) 322 sm_syslog(LOG_WARNING, NOQID, 323 "ERROR: DNS RDLENGTH=%d > data len=%d", 324 size, len - (int)(p - data)); 325 goto error; 326 } 327 *rr = (RESOURCE_RECORD_T *) sm_malloc(sizeof(**rr)); 328 if (*rr == NULL) 329 goto error; 330 memset(*rr, 0, sizeof(**rr)); 331 (*rr)->rr_domain = sm_strdup(host); 332 if ((*rr)->rr_domain == NULL) 333 goto error; 334 (*rr)->rr_type = type; 335 (*rr)->rr_class = class; 336 (*rr)->rr_ttl = ttl; 337 (*rr)->rr_size = size; 338 switch (type) 339 { 340 case T_NS: 341 case T_CNAME: 342 case T_PTR: 343 status = dn_expand(data, data + len, p, host, 344 sizeof(host)); 345 if (status < 0) 346 goto error; 347 if (tTd(8, 50)) 348 sm_dprintf("parse_dns_reply: type=%s, host=%s\n", 349 dns_type_to_string(type), host); 350 (*rr)->rr_u.rr_txt = sm_strdup(host); 351 if ((*rr)->rr_u.rr_txt == NULL) 352 goto error; 353 break; 354 355 case T_MX: 356 case T_AFSDB: 357 status = dn_expand(data, data + len, p + 2, host, 358 sizeof(host)); 359 if (status < 0) 360 goto error; 361 l = strlen(host) + 1; 362 (*rr)->rr_u.rr_mx = (MX_RECORD_T *) 363 sm_malloc(sizeof(*((*rr)->rr_u.rr_mx)) + l); 364 if ((*rr)->rr_u.rr_mx == NULL) 365 goto error; 366 (*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1]; 367 (void) sm_strlcpy((*rr)->rr_u.rr_mx->mx_r_domain, 368 host, l); 369 if (tTd(8, 50)) 370 sm_dprintf("mx=%s, pref=%d\n", host, 371 (*rr)->rr_u.rr_mx->mx_r_preference); 372 break; 373 374 case T_SRV: 375 status = dn_expand(data, data + len, p + 6, host, 376 sizeof(host)); 377 if (status < 0) 378 goto error; 379 l = strlen(host) + 1; 380 (*rr)->rr_u.rr_srv = (SRV_RECORDT_T*) 381 sm_malloc(sizeof(*((*rr)->rr_u.rr_srv)) + l); 382 if ((*rr)->rr_u.rr_srv == NULL) 383 goto error; 384 (*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1]; 385 (*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3]; 386 (*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5]; 387 (void) sm_strlcpy((*rr)->rr_u.rr_srv->srv_r_target, 388 host, l); 389 break; 390 391 case T_TXT: 392 393 /* 394 ** The TXT record contains the length as 395 ** leading byte, hence the value is restricted 396 ** to 255, which is less than the maximum value 397 ** of RDLENGTH (size). Nevertheless, txtlen 398 ** must be less than size because the latter 399 ** specifies the length of the entire TXT 400 ** record. 401 */ 402 403 txtlen = *p; 404 if (txtlen >= size) 405 { 406 if (LogLevel > 5) 407 sm_syslog(LOG_WARNING, NOQID, 408 "ERROR: DNS TXT record size=%d <= text len=%d", 409 size, txtlen); 410 goto error; 411 } 412 (*rr)->rr_u.rr_txt = (char *) sm_malloc(txtlen + 1); 413 if ((*rr)->rr_u.rr_txt == NULL) 414 goto error; 415 (void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1, 416 txtlen + 1); 417 break; 418 419 # ifdef T_TLSA 420 case T_TLSA: 421 if (tTd(8, 61)) 422 sm_dprintf("parse_dns_reply: TLSA, size=%d, flags=%X\n", 423 size, flags); 424 if ((flags & RR_AS_TEXT) != 0) 425 { 426 txtlen = bin2hex((char **)&((*rr)->rr_u.rr_data), 427 p, size, 4); 428 if (txtlen <= 0) 429 goto error; 430 break; 431 } 432 /* FALLTHROUGH */ 433 /* return "raw" data for caller to use as it pleases */ 434 # endif /* T_TLSA */ 435 436 default: 437 (*rr)->rr_u.rr_data = (unsigned char*) sm_malloc(size); 438 if ((*rr)->rr_u.rr_data == NULL) 439 goto error; 440 (void) memcpy((*rr)->rr_u.rr_data, p, size); 441 if (tTd(8, 61) && type == T_A) 442 { 443 SOCKADDR addr; 444 445 (void) memcpy((void *)&addr.sin.sin_addr.s_addr, p, size); 446 sm_dprintf("parse_dns_reply: IPv4=%s\n", 447 inet_ntoa(addr.sin.sin_addr)); 448 } 449 break; 450 } 451 p += size; 452 rr = &(*rr)->rr_next; 453 } 454 *rr = NULL; 455 return dr; 456 457 error: 458 dns_free_data(dr); 459 return NULL; 460 } 461 462 # if DNSSEC_TEST 463 464 #include <arpa/nameser.h> 465 466 static int gen_dns_reply __P((unsigned char *, int, unsigned char *, 467 const char *, int, const char *, int, int, int, int, 468 const char *, int, int, int)); 469 static int dnscrtrr __P((const char *, const char *, int, char *, int, 470 unsigned int, int *, int *, unsigned char *, int, unsigned char *)); 471 472 /* 473 ** HERRNO2TXT -- return error text for h_errno 474 ** 475 ** Parameters: 476 ** e -- h_errno 477 ** 478 ** Returns: 479 ** DNS error text if available 480 */ 481 482 const char * 483 herrno2txt(e) 484 int e; 485 { 486 switch (e) 487 { 488 case NETDB_INTERNAL: 489 return "see errno"; 490 case NETDB_SUCCESS: 491 return "OK"; 492 case HOST_NOT_FOUND: 493 return "HOST_NOT_FOUND"; 494 case TRY_AGAIN: 495 return "TRY_AGAIN"; 496 case NO_RECOVERY: 497 return "NO_RECOVERY"; 498 case NO_DATA: 499 return "NO_DATA"; 500 } 501 return "bogus h_errno"; 502 } 503 504 /* 505 ** GEN_DNS_REPLY -- generate DNS reply data. 506 ** 507 ** Parameters: 508 ** buf -- buffer to which DNS data is written 509 ** buflen -- length of buffer 510 ** bufpos -- position in buffer where DNS RRs are appended 511 ** query -- name of query 512 ** qtype -- resource record type of query 513 ** domain -- name of domain which has been "found" 514 ** class -- resource record class 515 ** type -- resource record type 516 ** ttl -- TTL 517 ** size -- size of data 518 ** data -- data 519 ** txtlen -- length of text 520 ** pref -- MX preference 521 ** ad -- ad flag 522 ** 523 ** Returns: 524 ** >0 length of buffer that has been used. 525 ** <0 error 526 */ 527 528 static int 529 gen_dns_reply(buf, buflen, bufpos, query, qtype, domain, class, type, ttl, size, data, txtlen, pref, ad) 530 unsigned char *buf; 531 int buflen; 532 unsigned char *bufpos; 533 const char *query; 534 int qtype; 535 const char *domain; 536 int class; 537 int type; 538 int ttl; 539 int size; 540 const char *data; 541 int txtlen; 542 int pref; 543 int ad; 544 { 545 unsigned short ans_cnt; 546 HEADER *hp; 547 unsigned char *cp, *ep; 548 int n; 549 static unsigned char *dnptrs[20], **dpp, **lastdnptr; 550 551 SM_REQUIRE(NULL != buf); 552 SM_REQUIRE(buflen >= HFIXEDSZ); 553 SM_REQUIRE(query != NULL); 554 hp = (HEADER *) buf; 555 ep = buf + buflen; 556 cp = buf + HFIXEDSZ; 557 558 if (bufpos != NULL) 559 cp = bufpos; 560 else 561 { 562 sm_dprintf("gen_dns_reply: query=%s, domain=%s, type=%s, size=%d, ad=%d\n", 563 query, domain, dns_type_to_string(type), size, ad); 564 dpp = dnptrs; 565 *dpp++ = buf; 566 *dpp++ = NULL; 567 lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0]; 568 569 memset(buf, 0, HFIXEDSZ); 570 hp->id = 0xdead; /* HACK */ 571 hp->qr = 1; 572 hp->opcode = QUERY; 573 hp->rd = 0; /* recursion desired? */ 574 hp->rcode = 0; /* !!! */ 575 /* hp->aa = ?; * !!! */ 576 /* hp->tc = ?; * !!! */ 577 /* hp->ra = ?; * !!! */ 578 hp->qdcount = htons(1); 579 hp->ancount = 0; 580 581 n = dn_comp(query, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr); 582 if (n < 0) 583 return n; 584 cp += n; 585 PUTSHORT(qtype, cp); 586 PUTSHORT(class, cp); 587 } 588 hp->ad = ad; 589 590 if (ep - cp < QFIXEDSZ) 591 return (-1); 592 n = dn_comp(domain, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr); 593 if (n < 0) 594 return n; 595 cp += n; 596 PUTSHORT(type, cp); 597 PUTSHORT(class, cp); 598 PUTLONG(ttl, cp); 599 600 ans_cnt = ntohs((unsigned short) hp->ancount); 601 ++ans_cnt; 602 hp->ancount = htons((unsigned short) ans_cnt); 603 604 switch (type) 605 { 606 case T_MX: 607 n = dn_comp(data, cp + 4, ep - cp - QFIXEDSZ, dnptrs, lastdnptr); 608 if (n < 0) 609 return n; 610 PUTSHORT(n + 2, cp); 611 PUTSHORT(pref, cp); 612 cp += n; 613 break; 614 615 case T_TXT: 616 if (txtlen >= size) 617 return -1; 618 PUTSHORT(txtlen, cp); 619 (void) sm_strlcpy((char *)cp, data, txtlen + 1); 620 cp += txtlen; 621 break; 622 623 case T_CNAME: 624 n = dn_comp(data, cp + 2, ep - cp - QFIXEDSZ, dnptrs, lastdnptr); 625 if (n < 0) 626 return n; 627 PUTSHORT(n, cp); 628 cp += n; 629 break; 630 631 # if defined(T_TLSA) 632 case T_TLSA: 633 { 634 char *tlsa; 635 636 tlsa = hex2bin(data, size); 637 if (tlsa == NULL) 638 return (-1); 639 n = size / 2; 640 PUTSHORT(n, cp); 641 (void) memcpy(cp, tlsa, n); 642 cp += n; 643 } 644 break; 645 # endif /* T_TLSA */ 646 647 default: 648 PUTSHORT(size, cp); 649 (void) memcpy(cp, data, size); 650 cp += size; 651 break; 652 } 653 654 return (cp - buf); 655 } 656 657 /* 658 ** SETHERRNOFROMSTRING -- set h_errno based on text 659 ** 660 ** Parameters: 661 ** str -- string which might contain h_errno text 662 ** prc -- pointer to rcode (EX_*) 663 ** 664 ** Returns: 665 ** h_errno if found 666 ** 0 otherwise 667 */ 668 669 int 670 setherrnofromstring(str, prc) 671 const char *str; 672 int *prc; 673 { 674 SM_SET_H_ERRNO(0); 675 if (str == NULL || *str == '\0') 676 return 0; 677 if (strstr(str, "herrno:") == NULL) 678 return 0; 679 if (prc != NULL) 680 *prc = EX_NOHOST; 681 if (strstr(str, "host_not_found")) 682 SM_SET_H_ERRNO(HOST_NOT_FOUND); 683 else if (strstr(str, "try_again")) 684 { 685 SM_SET_H_ERRNO(TRY_AGAIN); 686 if (prc != NULL) 687 *prc = EX_TEMPFAIL; 688 } 689 else if (strstr(str, "no_recovery")) 690 SM_SET_H_ERRNO(NO_RECOVERY); 691 else if (strstr(str, "no_data")) 692 SM_SET_H_ERRNO(NO_DATA); 693 else 694 SM_SET_H_ERRNO(NETDB_INTERNAL); 695 return h_errno; 696 } 697 698 /* 699 ** GETTTLFROMSTRING -- extract ttl from a string 700 ** 701 ** Parameters: 702 ** str -- string which might contain ttl 703 ** 704 ** Returns: 705 ** ttl if found 706 ** 0 otherwise 707 */ 708 709 int 710 getttlfromstring(str) 711 const char *str; 712 { 713 if (str == NULL || *str == '\0') 714 return 0; 715 #define TTL_PRE "ttl=" 716 if (strstr(str, TTL_PRE) == NULL) 717 return 0; 718 return strtoul(str + strlen(TTL_PRE), NULL, 10); 719 } 720 721 /* 722 ** NSPORTIP -- parse port@IPv4 and set NS accordingly 723 ** 724 ** Parameters: 725 ** p -- port@Ipv4 726 ** 727 ** Returns: 728 ** <0: error 729 ** >0: ok 730 ** 731 ** Side Effects: 732 ** sets NS for DNS lookups 733 */ 734 735 /* 736 ** There should be a generic function for this... 737 ** milter_open(), socket_map_open(), others? 738 */ 739 740 int 741 nsportip(p) 742 char *p; 743 { 744 char *h; 745 int r; 746 unsigned short port; 747 struct in_addr nsip; 748 749 if (p == NULL || *p == '\0') 750 return -1; 751 752 port = 0; 753 while (SM_ISSPACE(*p)) 754 p++; 755 if (*p == '\0') 756 return -1; 757 h = strchr(p, '@'); 758 if (h != NULL) 759 { 760 *h = '\0'; 761 if (isascii(*p) && isdigit(*p)) 762 port = atoi(p); 763 *h = '@'; 764 p = h + 1; 765 } 766 h = strchr(p, ' '); 767 if (h != NULL) 768 *h = '\0'; 769 r = inet_pton(AF_INET, p, &nsip); 770 if (r > 0) 771 { 772 if ((_res.options & RES_INIT) == 0) 773 (void) res_init(); 774 dns_setns(&nsip, port); 775 } 776 if (h != NULL) 777 *h = ' '; 778 return r > 0 ? 0 : -1; 779 } 780 781 /* 782 ** DNS_SETNS -- set one NS in resolver context 783 ** 784 ** Parameters: 785 ** ns -- (IPv4 address of) nameserver 786 ** port -- nameserver port 787 ** 788 ** Returns: 789 ** None. 790 */ 791 792 void 793 dns_setns(ns, port) 794 struct in_addr *ns; 795 unsigned int port; 796 { 797 _res.nsaddr_list[0].sin_family = AF_INET; 798 _res.nsaddr_list[0].sin_addr = *ns; 799 if (port != 0) 800 _res.nsaddr_list[0].sin_port = htons(port); 801 _res.nscount = 1; 802 if (tTd(8, 61)) 803 sm_dprintf("dns_setns(%s,%u)\n", inet_ntoa(*ns), port); 804 } 805 806 # if defined(T_TLSA) 807 /* 808 ** HEX2BIN -- convert hex string to binary TLSA RR 809 ** 810 ** Parameters: 811 ** p -- hex representation of TLSA RR 812 ** size -- length of p 813 ** 814 ** Returns: 815 ** pointer to binary TLSA RR 816 ** NULL: error 817 */ 818 819 static char * 820 hex2bin(p, size) 821 const char *p; 822 int size; 823 { 824 int i, pos, txtlen; 825 char *tlsa; 826 827 txtlen = size / 2; 828 if (txtlen * 2 == size) 829 { 830 if (LogLevel > 5) 831 sm_syslog(LOG_WARNING, NOQID, 832 "ERROR: hex2bin: size %d wrong", size); 833 return NULL; 834 } 835 tlsa = sm_malloc(txtlen + 1); 836 if (tlsa == NULL) 837 { 838 if (tTd(8, 17)) 839 sm_dprintf("len=%d, tlsa=NULL\n", txtlen); 840 return NULL; 841 } 842 843 #define CHAR2INT(c) (((c) <= '9') ? ((c) - '0') : (toupper(c) - 'A' + 10)) 844 for (i = 0, pos = 0; i + 1 < size && pos < txtlen; i += 2, pos++) 845 tlsa[pos] = CHAR2INT(p[i]) * 16 + CHAR2INT(p[i+1]); 846 847 return tlsa; 848 } 849 # endif /* T_TLSA */ 850 851 const char * 852 rr_type2tag(rr_type) 853 int rr_type; 854 { 855 switch (rr_type) 856 { 857 case T_A: 858 return "ipv4"; 859 # if NETINET6 860 case T_AAAA: 861 return "ipv6"; 862 # endif 863 case T_CNAME: 864 return "cname"; 865 case T_MX: 866 return "mx"; 867 # ifdef T_TLSA 868 case T_TLSA: 869 return "tlsa"; 870 # endif 871 } 872 return NULL; 873 } 874 875 /* 876 ** DNSCRTRR -- create DNS RR 877 ** 878 ** Parameters: 879 ** domain -- original query domain 880 ** query -- name of query 881 ** qtype -- resource record type of query 882 ** value -- (list of) data to set 883 ** rr_type -- resource record type 884 ** flags -- flags how to handle various lookups 885 ** herr -- (pointer to) h_errno (output if non-NULL) 886 ** adp -- (pointer to) ad flag 887 ** answer -- buffer for RRs 888 ** anslen -- size of answer 889 ** anspos -- current position in answer 890 ** 891 ** Returns: 892 ** >0: length of data in answer 893 ** <0: error, check *herr 894 */ 895 896 static int 897 dnscrtrr(domain, query, qtype, value, rr_type, flags, herr, adp, answer, anslen, anspos) 898 const char *domain; 899 const char *query; 900 int qtype; 901 char *value; 902 int rr_type; 903 unsigned int flags; 904 int *herr; 905 int *adp; 906 unsigned char *answer; 907 int anslen; 908 unsigned char *anspos; 909 { 910 SOCKADDR addr; 911 int ttl, ad, rlen; 912 char *p, *token; 913 char data[IN6ADDRSZ]; 914 char rhs[MAXLINE]; 915 916 rlen = -1; 917 if (NULL == value || '\0' == *value) 918 return rlen; 919 SM_REQUIRE(adp != NULL); 920 (void) sm_strlcpy(rhs, value, sizeof(rhs)); 921 p = rhs; 922 if (setherrnofromstring(p, NULL) != 0) 923 { 924 if (herr != NULL) 925 *herr = h_errno; 926 if (tTd(8, 16)) 927 sm_dprintf("dnscrtrr rhs=%s h_errno=%d (%s)\n", 928 p, h_errno, herrno2txt(h_errno)); 929 return rlen; 930 } 931 932 ttl = 0; 933 ad = 0; 934 for (token = p; token != NULL && *token != '\0'; token = p) 935 { 936 rlen = 0; 937 while (p != NULL && *p != '\0' && !SM_ISSPACE(*p)) 938 ++p; 939 if (SM_ISSPACE(*p)) 940 *p++ = '\0'; 941 sm_dprintf("dnscrtrr: token=%s\n", token); 942 if (strcmp(token, "ad") == 0) 943 { 944 bool adflag; 945 946 adflag = (_res.options & RES_USE_DNSSEC) != 0; 947 948 /* maybe print this only for the final RR? */ 949 if (tTd(8, 61)) 950 sm_dprintf("dnscrtrr: ad=1, adp=%d, adflag=%d\n", 951 *adp, adflag); 952 if (*adp != 0 && adflag) 953 { 954 *adp = 1; 955 ad = 1; 956 } 957 continue; 958 } 959 if (ttl == 0 && (ttl = getttlfromstring(token)) > 0) 960 { 961 if (tTd(8, 61)) 962 sm_dprintf("dnscrtrr: ttl=%d\n", ttl); 963 continue; 964 } 965 966 if (rr_type == T_A) 967 { 968 addr.sin.sin_addr.s_addr = inet_addr(token); 969 (void) memmove(data, (void *)&addr.sin.sin_addr.s_addr, 970 INADDRSZ); 971 rlen = gen_dns_reply(answer, anslen, anspos, 972 query, qtype, domain, C_IN, rr_type, ttl, 973 INADDRSZ, data, 0, 0, ad); 974 } 975 976 # if NETINET6 977 if (rr_type == T_AAAA) 978 { 979 anynet_pton(AF_INET6, token, &addr.sin6.sin6_addr); 980 memmove(data, (void *)&addr.sin6.sin6_addr, IN6ADDRSZ); 981 rlen = gen_dns_reply(answer, anslen, anspos, 982 query, qtype, domain, C_IN, rr_type, ttl, 983 IN6ADDRSZ, data, 0, 0, ad); 984 } 985 # endif /* NETINET6 */ 986 987 if (rr_type == T_MX) 988 { 989 char *endptr; 990 int pref; 991 992 pref = (int) strtoul(token, &endptr, 10); 993 if (endptr == NULL || *endptr != ':') 994 goto error; 995 token = endptr + 1; 996 rlen = gen_dns_reply(answer, anslen, anspos, 997 query, qtype, domain, C_IN, rr_type, ttl, 998 strlen(token) + 1, token, 0, pref, ad); 999 if (tTd(8, 50)) 1000 sm_dprintf("dnscrtrr: mx=%s, pref=%d\n", 1001 token, pref); 1002 } 1003 1004 # ifdef T_TLSA 1005 if (rr_type == T_TLSA) 1006 rlen = gen_dns_reply(answer, anslen, anspos, 1007 query, qtype, domain, C_IN, rr_type, ttl, 1008 strlen(token) + 1, token, 0, 0, ad); 1009 # endif 1010 1011 if (rr_type == T_CNAME) 1012 rlen = gen_dns_reply(answer, anslen, anspos, 1013 query, qtype, domain, C_IN, rr_type, ttl, 1014 strlen(token), token, 0, 0, ad); 1015 if (rlen < 0) 1016 goto error; 1017 if (rlen > 0) 1018 anspos = answer + rlen; 1019 } 1020 1021 if (ad != 1) 1022 *adp = 0; 1023 1024 return rlen; 1025 1026 error: 1027 if (herr != NULL && 0 == *herr) 1028 *herr = NO_RECOVERY; 1029 return -1; 1030 } 1031 1032 /* 1033 ** TSTDNS_SEARCH -- replacement for res_search() for testing 1034 ** 1035 ** Parameters: 1036 ** domain -- query domain 1037 ** class -- class 1038 ** type -- resource record type 1039 ** answer -- buffer for RRs 1040 ** anslen -- size of answer 1041 ** 1042 ** Returns: 1043 ** >0: length of data in answer 1044 ** <0: error, check h_errno 1045 */ 1046 1047 int 1048 tstdns_search(domain, class, type, answer, anslen) 1049 const char *domain; 1050 int class; 1051 int type; 1052 unsigned char *answer; 1053 int anslen; 1054 { 1055 int rlen, ad, maprcode, cnt, flags, herr; 1056 bool found_cname; 1057 const char *query; 1058 char *p; 1059 const char *tag; 1060 char *av[2]; 1061 STAB *map; 1062 char key[MAXNAME + 16]; 1063 char rhs[MAXLINE]; 1064 unsigned char *anspos; 1065 1066 rlen = -1; 1067 herr = 0; 1068 if (class != C_IN) 1069 goto error; 1070 if (NULL == domain || '\0' == *domain) 1071 goto error; 1072 tag = rr_type2tag(type); 1073 if (tag == NULL) 1074 goto error; 1075 maprcode = EX_OK; 1076 ad = -1; 1077 flags = 0; 1078 query = domain; 1079 anspos = NULL; 1080 1081 map = stab("access", ST_MAP, ST_FIND); 1082 if (NULL == map) 1083 { 1084 sm_dprintf("access map not found\n"); 1085 goto error; 1086 } 1087 if (!bitset(MF_OPEN, map->s_map.map_mflags) && 1088 !openmap(&(map->s_map))) 1089 { 1090 sm_dprintf("access map open failed\n"); 1091 goto error; 1092 } 1093 1094 /* 1095 ** Look up tag:domain, if not found and domain does not end with a dot 1096 ** (and the proper debug level is selected), also try with trailing dot. 1097 */ 1098 1099 #define SM_LOOKUP2(tag) \ 1100 do { \ 1101 int len; \ 1102 \ 1103 len = strlen(domain); \ 1104 av[0] = key; \ 1105 av[1] = NULL; \ 1106 snprintf(key, sizeof(key), "%s:%s", tag, domain); \ 1107 p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \ 1108 &maprcode); \ 1109 if (p != NULL) \ 1110 break; \ 1111 if (!tTd(8, 112) || (len > 0 && '.' == domain[len - 1])) \ 1112 break; \ 1113 snprintf(key, sizeof(key), "%s:%s.", tag, domain); \ 1114 p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \ 1115 &maprcode); \ 1116 } while (0) 1117 1118 cnt = 0; 1119 found_cname = false; 1120 while (cnt < 6) 1121 { 1122 char *last; 1123 1124 /* Should this try with/without trailing dot? */ 1125 SM_LOOKUP2(tag); 1126 if (p != NULL) 1127 { 1128 sm_dprintf("access map lookup key=%s, value=%s\n", key, 1129 p); 1130 break; 1131 } 1132 if (NULL == p && (flags & RR_NO_CNAME) == 0) 1133 { 1134 sm_dprintf("access map lookup failed key=%s, try cname\n", 1135 key); 1136 SM_LOOKUP2("cname"); 1137 if (p != NULL) 1138 { 1139 sm_dprintf("cname lookup key=%s, value=%s, ad=%d\n", 1140 key, p, ad); 1141 rlen = dnscrtrr(domain, query, type, p, T_CNAME, 1142 flags, &herr, &ad, answer, 1143 anslen, anspos); 1144 if (rlen < 0) 1145 goto error; 1146 if (rlen > 0) 1147 anspos = answer + rlen; 1148 found_cname = true; 1149 } 1150 } 1151 if (NULL == p) 1152 break; 1153 1154 (void) sm_strlcpy(rhs, p, sizeof(rhs)); 1155 p = rhs; 1156 1157 /* skip (leading) ad/ttl: look for last ' ' */ 1158 if ((last = strrchr(p, ' ')) != NULL && last[1] != '\0') 1159 domain = last + 1; 1160 else 1161 domain = p; 1162 ++cnt; 1163 } 1164 if (NULL == p) 1165 { 1166 int t; 1167 char *tags[] = { "ipv4", "mx", "tlsa", 1168 # if NETINET6 1169 "ipv6", 1170 # endif 1171 NULL 1172 }; 1173 1174 for (t = 0; tags[t] != NULL; t++) 1175 { 1176 if (strcmp(tag, tags[t]) == 0) 1177 continue; 1178 SM_LOOKUP2(tags[t]); 1179 if (p != NULL) 1180 { 1181 sm_dprintf("access map lookup failed key=%s:%s, but found key=%s\n", 1182 tag, domain, key); 1183 herr = NO_DATA; 1184 goto error; 1185 } 1186 } 1187 sm_dprintf("access map lookup failed key=%s\n", key); 1188 herr = HOST_NOT_FOUND; 1189 goto error; 1190 } 1191 if (found_cname && (flags & RR_ONLY_CNAME) != 0) 1192 return rlen; 1193 rlen = dnscrtrr(domain, query, type, p, type, flags, &herr, &ad, 1194 answer, anslen, anspos); 1195 if (rlen < 0) 1196 goto error; 1197 return rlen; 1198 1199 error: 1200 if (0 == herr) 1201 herr = NO_RECOVERY; 1202 SM_SET_H_ERRNO(herr); 1203 sm_dprintf("rlen=%d, herr=%d\n", rlen, herr); 1204 return -1; 1205 } 1206 1207 /* 1208 ** TSTDNS_QUERYDOMAIN -- replacement for res_querydomain() for testing 1209 ** 1210 ** Parameters: 1211 ** name -- query name 1212 ** domain -- query domain 1213 ** class -- class 1214 ** type -- resource record type 1215 ** answer -- buffer for RRs 1216 ** anslen -- size of answer 1217 ** 1218 ** Returns: 1219 ** >0: length of data in answer 1220 ** <0: error, check h_errno 1221 */ 1222 1223 int 1224 tstdns_querydomain(name, domain, class, type, answer, anslen) 1225 const char *name; 1226 const char *domain; 1227 int class; 1228 int type; 1229 unsigned char *answer; 1230 int anslen; 1231 { 1232 char query[MAXNAME]; 1233 int len; 1234 1235 if (NULL == name) 1236 goto error; 1237 if (NULL == domain || '\0' == *domain) 1238 return tstdns_search(name, class, type, answer, anslen); 1239 1240 len = snprintf(query, sizeof(query), "%s.%s", name, domain); 1241 if (len >= (int)sizeof(query)) 1242 goto error; 1243 return tstdns_search(query, class, type, answer, anslen); 1244 1245 error: 1246 SM_SET_H_ERRNO(NO_RECOVERY); 1247 return -1; 1248 } 1249 1250 # endif /* DNSSEC_TEST */ 1251 1252 /* 1253 ** DNS_LOOKUP_INT -- perform DNS lookup 1254 ** 1255 ** Parameters: 1256 ** domain -- name to lookup 1257 ** rr_class -- resource record class 1258 ** rr_type -- resource record type 1259 ** retrans -- retransmission timeout 1260 ** retry -- number of retries 1261 ** options -- DNS resolver options 1262 ** flags -- currently only passed to parse_dns_reply() 1263 ** err -- (pointer to) errno (output if non-NULL) 1264 ** herr -- (pointer to) h_errno (output if non-NULL) 1265 ** 1266 ** Returns: 1267 ** result of lookup if succeeded. 1268 ** NULL otherwise. 1269 */ 1270 1271 DNS_REPLY_T * 1272 dns_lookup_int(domain, rr_class, rr_type, retrans, retry, options, flags, err, herr) 1273 const char *domain; 1274 int rr_class; 1275 int rr_type; 1276 time_t retrans; 1277 int retry; 1278 unsigned int options; 1279 unsigned int flags; 1280 int *err; 1281 int *herr; 1282 { 1283 int len; 1284 unsigned long old_options = 0; 1285 time_t save_retrans = 0; 1286 int save_retry = 0; 1287 DNS_REPLY_T *dr = NULL; 1288 querybuf reply_buf; 1289 unsigned char *reply; 1290 int (*resfunc) __P((const char *, int, int, u_char *, int)); 1291 1292 # define SMRBSIZE ((int) sizeof(reply_buf)) 1293 # ifndef IP_MAXPACKET 1294 # define IP_MAXPACKET 65535 1295 # endif 1296 1297 resfunc = res_search; 1298 # if DNSSEC_TEST 1299 if (tTd(8, 110)) 1300 resfunc = tstdns_search; 1301 # endif 1302 1303 old_options = _res.options; 1304 _res.options |= options; 1305 if (err != NULL) 1306 *err = 0; 1307 if (herr != NULL) 1308 *herr = 0; 1309 if (tTd(8, 16)) 1310 { 1311 _res.options |= RES_DEBUG; 1312 sm_dprintf("dns_lookup_int(%s, %d, %s, %x)\n", domain, 1313 rr_class, dns_type_to_string(rr_type), options); 1314 } 1315 # if DNSSEC_TEST 1316 if (tTd(8, 15)) 1317 sm_dprintf("NS=%s, port=%d\n", 1318 inet_ntoa(_res.nsaddr_list[0].sin_addr), 1319 ntohs(_res.nsaddr_list[0].sin_port)); 1320 # endif 1321 if (retrans > 0) 1322 { 1323 save_retrans = _res.retrans; 1324 _res.retrans = retrans; 1325 } 1326 if (retry > 0) 1327 { 1328 save_retry = _res.retry; 1329 _res.retry = retry; 1330 } 1331 errno = 0; 1332 SM_SET_H_ERRNO(0); 1333 reply = (unsigned char *)&reply_buf; 1334 len = (*resfunc)(domain, rr_class, rr_type, reply, SMRBSIZE); 1335 if (len >= SMRBSIZE) 1336 { 1337 if (len >= IP_MAXPACKET) 1338 { 1339 if (tTd(8, 4)) 1340 sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response too long\n", 1341 domain, len, SMRBSIZE, IP_MAXPACKET); 1342 } 1343 else 1344 { 1345 if (tTd(8, 6)) 1346 sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response longer than default size, resizing\n", 1347 domain, len, SMRBSIZE, IP_MAXPACKET); 1348 reply = (unsigned char *)sm_malloc(IP_MAXPACKET); 1349 if (reply == NULL) 1350 SM_SET_H_ERRNO(TRY_AGAIN); 1351 else 1352 { 1353 SM_SET_H_ERRNO(0); 1354 len = (*resfunc)(domain, rr_class, rr_type, 1355 reply, IP_MAXPACKET); 1356 } 1357 } 1358 } 1359 _res.options = old_options; 1360 if (len < 0) 1361 { 1362 if (err != NULL) 1363 *err = errno; 1364 if (herr != NULL) 1365 *herr = h_errno; 1366 if (tTd(8, 16)) 1367 { 1368 sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d, errno=%d, h_errno=%d" 1369 # if DNSSEC_TEST 1370 " (%s)" 1371 # endif 1372 "\n", 1373 domain, rr_class, dns_type_to_string(rr_type), 1374 options, len, errno, h_errno 1375 # if DNSSEC_TEST 1376 , herrno2txt(h_errno) 1377 # endif 1378 ); 1379 } 1380 } 1381 else if (tTd(8, 16)) 1382 { 1383 sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d\n", 1384 domain, rr_class, dns_type_to_string(rr_type), 1385 options, len); 1386 } 1387 if (len >= 0 && len < IP_MAXPACKET && reply != NULL) 1388 dr = parse_dns_reply(reply, len, flags); 1389 if (reply != (unsigned char *)&reply_buf && reply != NULL) 1390 { 1391 sm_free(reply); 1392 reply = NULL; 1393 } 1394 if (retrans > 0) 1395 _res.retrans = save_retrans; 1396 if (retry > 0) 1397 _res.retry = save_retry; 1398 return dr; 1399 } 1400 1401 /* 1402 ** DNS_LOOKUP_MAP -- perform DNS map lookup 1403 ** 1404 ** Parameters: 1405 ** domain -- name to lookup 1406 ** rr_class -- resource record class 1407 ** rr_type -- resource record type 1408 ** retrans -- retransmission timeout 1409 ** retry -- number of retries 1410 ** options -- DNS resolver options 1411 ** 1412 ** Returns: 1413 ** result of lookup if succeeded. 1414 ** NULL otherwise. 1415 */ 1416 1417 DNS_REPLY_T * 1418 dns_lookup_map(domain, rr_class, rr_type, retrans, retry, options) 1419 const char *domain; 1420 int rr_class; 1421 int rr_type; 1422 time_t retrans; 1423 int retry; 1424 unsigned int options; 1425 { 1426 return dns_lookup_int(domain, rr_class, rr_type, retrans, retry, 1427 options, RR_AS_TEXT, NULL, NULL); 1428 } 1429 1430 # if DANE 1431 /* 1432 ** DNS2HE -- convert DNS_REPLY_T list to hostent struct 1433 ** 1434 ** Parameters: 1435 ** dr -- DNS lookup result 1436 ** family -- address family 1437 ** 1438 ** Returns: 1439 ** hostent struct if succeeded. 1440 ** NULL otherwise. 1441 ** 1442 ** Note: 1443 ** this returns a pointer to a static struct! 1444 */ 1445 1446 struct hostent * 1447 dns2he(dr, family) 1448 DNS_REPLY_T *dr; 1449 int family; 1450 { 1451 # define SM_MAX_ADDRS 256 1452 static struct hostent he; 1453 static char *he_aliases[1]; 1454 static char *he_addr_list[SM_MAX_ADDRS]; 1455 # ifdef IN6ADDRSZ 1456 # define IN_ADDRSZ IN6ADDRSZ 1457 # else 1458 # define IN_ADDRSZ INADDRSZ 1459 # endif 1460 static char he_addrs[SM_MAX_ADDRS * IN_ADDRSZ]; 1461 static char he_name[MAXNAME]; 1462 static bool he_init = false; 1463 struct hostent *h; 1464 struct in_addr ia; 1465 int i; 1466 size_t sz; 1467 # if NETINET6 && DNSSEC_TEST 1468 struct in6_addr ia6; 1469 char buf6[INET6_ADDRSTRLEN]; 1470 # endif 1471 RESOURCE_RECORD_T *rr; 1472 1473 if (dr == NULL) 1474 return NULL; 1475 1476 h = &he; 1477 if (!he_init) 1478 { 1479 he_aliases[0] = NULL; 1480 he.h_aliases = he_aliases; 1481 he.h_addr_list = he_addr_list; 1482 he.h_name = he_name; 1483 he_init = true; 1484 } 1485 h->h_addrtype = family; 1486 1487 if (tTd(8, 17)) 1488 sm_dprintf("dns2he: ad=%d\n", dr->dns_r_h.ad); 1489 1490 /* do we want/need to copy the name? */ 1491 rr = dr->dns_r_head; 1492 if (rr != NULL && rr->rr_domain != NULL) 1493 sm_strlcpy(h->h_name, rr->rr_domain, sizeof(he_name)); 1494 else 1495 h->h_name[0] = '\0'; 1496 1497 sz = 0; 1498 # if NETINET 1499 if (family == AF_INET) 1500 sz = INADDRSZ; 1501 # endif 1502 # if NETINET6 1503 if (family == AF_INET6) 1504 sz = IN6ADDRSZ; 1505 # endif 1506 if (sz == 0) 1507 return NULL; 1508 h->h_length = sz; 1509 1510 for (rr = dr->dns_r_head, i = 0; rr != NULL && i < SM_MAX_ADDRS - 1; 1511 rr = rr->rr_next) 1512 { 1513 h->h_addr_list[i] = he_addrs + i * h->h_length; 1514 switch (rr->rr_type) 1515 { 1516 # if NETINET 1517 case T_A: 1518 if (family != AF_INET) 1519 continue; 1520 memmove(h->h_addr_list[i], rr->rr_u.rr_a, INADDRSZ); 1521 ++i; 1522 break; 1523 # endif /* NETINET */ 1524 # if NETINET6 1525 case T_AAAA: 1526 if (family != AF_INET6) 1527 continue; 1528 memmove(h->h_addr_list[i], rr->rr_u.rr_aaaa, IN6ADDRSZ); 1529 ++i; 1530 break; 1531 # endif /* NETINET6 */ 1532 case T_CNAME: 1533 # if DNSSEC_TEST 1534 if (tTd(8, 16)) 1535 sm_dprintf("dns2he: cname: %s ttl=%d\n", 1536 rr->rr_u.rr_txt, rr->rr_ttl); 1537 # endif 1538 break; 1539 case T_MX: 1540 # if DNSSEC_TEST 1541 if (tTd(8, 16)) 1542 sm_dprintf("dns2he: mx: %d %s ttl=%d\n", 1543 rr->rr_u.rr_mx->mx_r_preference, 1544 rr->rr_u.rr_mx->mx_r_domain, 1545 rr->rr_ttl); 1546 # endif 1547 break; 1548 1549 # if defined(T_TLSA) 1550 case T_TLSA: 1551 # if DNSSEC_TEST 1552 if (tTd(8, 16)) 1553 { 1554 char *tlsa; 1555 int len; 1556 1557 len = bin2hex(&tlsa, rr->rr_u.rr_data, 1558 rr->rr_size, 4); 1559 if (len > 0) 1560 sm_dprintf("dns2he: tlsa: %s ttl=%d\n", 1561 tlsa, rr->rr_ttl); 1562 } 1563 # endif 1564 break; 1565 # endif /* T_TLSA */ 1566 } 1567 } 1568 1569 /* complain if list is too long! */ 1570 SM_ASSERT(i < SM_MAX_ADDRS); 1571 h->h_addr_list[i] = NULL; 1572 1573 # if DNSSEC_TEST 1574 if (tTd(8, 16)) 1575 { 1576 for (i = 0; h->h_addr_list[i] != NULL && i < SM_MAX_ADDRS; i++) 1577 { 1578 char *addr; 1579 1580 addr = NULL; 1581 # if NETINET6 1582 if (h->h_addrtype == AF_INET6) 1583 { 1584 memmove(&ia6, h->h_addr_list[i], IN6ADDRSZ); 1585 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 1586 } 1587 else 1588 # endif /* NETINET6 */ 1589 /* "else" in #if code above */ 1590 { 1591 memmove(&ia, h->h_addr_list[i], INADDRSZ); 1592 addr = (char *) inet_ntoa(ia); 1593 } 1594 if (addr != NULL) 1595 sm_dprintf("dns2he: addr[%d]: %s\n", i, addr); 1596 } 1597 } 1598 # endif /* DNSSEC_TEST */ 1599 return h; 1600 } 1601 # endif /* DANE */ 1602 # endif /* NAMED_BIND */ 1603 #endif /* DNSMAP || DANE */ 1604