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