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