140266059SGregory Neil Shapiro /*
25b0945b5SGregory Neil Shapiro * Copyright (c) 2000-2004, 2010, 2015, 2020 Proofpoint, Inc. and its suppliers.
340266059SGregory Neil Shapiro * All rights reserved.
440266059SGregory Neil Shapiro *
540266059SGregory Neil Shapiro * By using this file, you agree to the terms and conditions set
640266059SGregory Neil Shapiro * forth in the LICENSE file which can be found at the top level of
740266059SGregory Neil Shapiro * the sendmail distribution.
840266059SGregory Neil Shapiro *
940266059SGregory Neil Shapiro */
1040266059SGregory Neil Shapiro
1140266059SGregory Neil Shapiro /*
1240266059SGregory Neil Shapiro * Copyright (c) 1995, 1996, 1997, 1998, 1999 Kungliga Tekniska H�gskolan
1340266059SGregory Neil Shapiro * (Royal Institute of Technology, Stockholm, Sweden).
1440266059SGregory Neil Shapiro * All rights reserved.
1540266059SGregory Neil Shapiro *
1640266059SGregory Neil Shapiro * Redistribution and use in source and binary forms, with or without
1740266059SGregory Neil Shapiro * modification, are permitted provided that the following conditions
1840266059SGregory Neil Shapiro * are met:
1940266059SGregory Neil Shapiro *
2040266059SGregory Neil Shapiro * 1. Redistributions of source code must retain the above copyright
2140266059SGregory Neil Shapiro * notice, this list of conditions and the following disclaimer.
2240266059SGregory Neil Shapiro *
2340266059SGregory Neil Shapiro * 2. Redistributions in binary form must reproduce the above copyright
2440266059SGregory Neil Shapiro * notice, this list of conditions and the following disclaimer in the
2540266059SGregory Neil Shapiro * documentation and/or other materials provided with the distribution.
2640266059SGregory Neil Shapiro *
2740266059SGregory Neil Shapiro * 3. Neither the name of the Institute nor the names of its contributors
2840266059SGregory Neil Shapiro * may be used to endorse or promote products derived from this software
2940266059SGregory Neil Shapiro * without specific prior written permission.
3040266059SGregory Neil Shapiro *
3140266059SGregory Neil Shapiro * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
3240266059SGregory Neil Shapiro * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
3340266059SGregory Neil Shapiro * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3440266059SGregory Neil Shapiro * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
3540266059SGregory Neil Shapiro * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3640266059SGregory Neil Shapiro * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3740266059SGregory Neil Shapiro * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3840266059SGregory Neil Shapiro * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3940266059SGregory Neil Shapiro * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
4040266059SGregory Neil Shapiro * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
4140266059SGregory Neil Shapiro * SUCH DAMAGE.
4240266059SGregory Neil Shapiro */
4340266059SGregory Neil Shapiro
4440266059SGregory Neil Shapiro #include <sendmail.h>
452fb4f839SGregory Neil Shapiro #include <sm/sendmail.h>
46*d39bd2c1SGregory Neil Shapiro
4740266059SGregory Neil Shapiro #if NAMED_BIND
486f9c8e5bSGregory Neil Shapiro # if NETINET
496f9c8e5bSGregory Neil Shapiro # include <netinet/in_systm.h>
506f9c8e5bSGregory Neil Shapiro # include <netinet/ip.h>
515b0945b5SGregory Neil Shapiro # endif
52*d39bd2c1SGregory Neil Shapiro # if DNSSEC_TEST || _FFR_NAMESERVER
535b0945b5SGregory Neil Shapiro # define _DEFINE_SMR_GLOBALS 1
54*d39bd2c1SGregory Neil Shapiro # endif
5540266059SGregory Neil Shapiro # include "sm_resolve.h"
56*d39bd2c1SGregory Neil Shapiro # if DNSMAP || DANE
5740266059SGregory Neil Shapiro
585b0945b5SGregory Neil Shapiro #include <arpa/inet.h>
595b0945b5SGregory Neil Shapiro
604313cc83SGregory Neil Shapiro SM_RCSID("$Id: sm_resolve.c,v 8.40 2013-11-22 20:51:56 ca Exp $")
6140266059SGregory Neil Shapiro
6240266059SGregory Neil Shapiro static struct stot
6340266059SGregory Neil Shapiro {
6440266059SGregory Neil Shapiro const char *st_name;
6540266059SGregory Neil Shapiro int st_type;
6640266059SGregory Neil Shapiro } stot[] =
6740266059SGregory Neil Shapiro {
6840266059SGregory Neil Shapiro # if NETINET
6940266059SGregory Neil Shapiro { "A", T_A },
705b0945b5SGregory Neil Shapiro # endif
7140266059SGregory Neil Shapiro # if NETINET6
7240266059SGregory Neil Shapiro { "AAAA", T_AAAA },
735b0945b5SGregory Neil Shapiro # endif
7440266059SGregory Neil Shapiro { "NS", T_NS },
7540266059SGregory Neil Shapiro { "CNAME", T_CNAME },
7640266059SGregory Neil Shapiro { "PTR", T_PTR },
7740266059SGregory Neil Shapiro { "MX", T_MX },
7840266059SGregory Neil Shapiro { "TXT", T_TXT },
7940266059SGregory Neil Shapiro { "AFSDB", T_AFSDB },
8040266059SGregory Neil Shapiro { "SRV", T_SRV },
815b0945b5SGregory Neil Shapiro # ifdef T_DS
825b0945b5SGregory Neil Shapiro { "DS", T_DS },
835b0945b5SGregory Neil Shapiro # endif
845b0945b5SGregory Neil Shapiro { "RRSIG", T_RRSIG },
855b0945b5SGregory Neil Shapiro # ifdef T_NSEC
865b0945b5SGregory Neil Shapiro { "NSEC", T_NSEC },
875b0945b5SGregory Neil Shapiro # endif
885b0945b5SGregory Neil Shapiro # ifdef T_DNSKEY
895b0945b5SGregory Neil Shapiro { "DNSKEY", T_DNSKEY },
905b0945b5SGregory Neil Shapiro # endif
915b0945b5SGregory Neil Shapiro { "TLSA", T_TLSA },
9240266059SGregory Neil Shapiro { NULL, 0 }
9340266059SGregory Neil Shapiro };
9440266059SGregory Neil Shapiro
955b0945b5SGregory Neil Shapiro static DNS_REPLY_T *parse_dns_reply __P((unsigned char *, int, unsigned int));
965b0945b5SGregory Neil Shapiro # if DNSSEC_TEST && defined(T_TLSA)
975b0945b5SGregory Neil Shapiro static char *hex2bin __P((const char *, int));
985b0945b5SGregory Neil Shapiro # endif
99b6bacd31SGregory Neil Shapiro
10040266059SGregory Neil Shapiro /*
10140266059SGregory Neil Shapiro ** DNS_STRING_TO_TYPE -- convert resource record name into type
10240266059SGregory Neil Shapiro **
10340266059SGregory Neil Shapiro ** Parameters:
10440266059SGregory Neil Shapiro ** name -- name of resource record type
10540266059SGregory Neil Shapiro **
10640266059SGregory Neil Shapiro ** Returns:
10740266059SGregory Neil Shapiro ** type if succeeded.
10840266059SGregory Neil Shapiro ** -1 otherwise.
10940266059SGregory Neil Shapiro */
11040266059SGregory Neil Shapiro
11140266059SGregory Neil Shapiro int
dns_string_to_type(name)11240266059SGregory Neil Shapiro dns_string_to_type(name)
11340266059SGregory Neil Shapiro const char *name;
11440266059SGregory Neil Shapiro {
11540266059SGregory Neil Shapiro struct stot *p = stot;
11640266059SGregory Neil Shapiro
11740266059SGregory Neil Shapiro for (p = stot; p->st_name != NULL; p++)
1182fb4f839SGregory Neil Shapiro if (SM_STRCASEEQ(name, p->st_name))
11940266059SGregory Neil Shapiro return p->st_type;
12040266059SGregory Neil Shapiro return -1;
12140266059SGregory Neil Shapiro }
12240266059SGregory Neil Shapiro
12340266059SGregory Neil Shapiro /*
12440266059SGregory Neil Shapiro ** DNS_TYPE_TO_STRING -- convert resource record type into name
12540266059SGregory Neil Shapiro **
12640266059SGregory Neil Shapiro ** Parameters:
12740266059SGregory Neil Shapiro ** type -- resource record type
12840266059SGregory Neil Shapiro **
12940266059SGregory Neil Shapiro ** Returns:
13040266059SGregory Neil Shapiro ** name if succeeded.
13140266059SGregory Neil Shapiro ** NULL otherwise.
13240266059SGregory Neil Shapiro */
13340266059SGregory Neil Shapiro
13440266059SGregory Neil Shapiro const char *
dns_type_to_string(type)13540266059SGregory Neil Shapiro dns_type_to_string(type)
13640266059SGregory Neil Shapiro int type;
13740266059SGregory Neil Shapiro {
13840266059SGregory Neil Shapiro struct stot *p = stot;
13940266059SGregory Neil Shapiro
14040266059SGregory Neil Shapiro for (p = stot; p->st_name != NULL; p++)
14140266059SGregory Neil Shapiro if (type == p->st_type)
14240266059SGregory Neil Shapiro return p->st_name;
14340266059SGregory Neil Shapiro return NULL;
14440266059SGregory Neil Shapiro }
14540266059SGregory Neil Shapiro
14640266059SGregory Neil Shapiro /*
14740266059SGregory Neil Shapiro ** DNS_FREE_DATA -- free all components of a DNS_REPLY_T
14840266059SGregory Neil Shapiro **
14940266059SGregory Neil Shapiro ** Parameters:
1505b0945b5SGregory Neil Shapiro ** dr -- pointer to DNS_REPLY_T
15140266059SGregory Neil Shapiro **
15240266059SGregory Neil Shapiro ** Returns:
15340266059SGregory Neil Shapiro ** none.
15440266059SGregory Neil Shapiro */
15540266059SGregory Neil Shapiro
15640266059SGregory Neil Shapiro void
dns_free_data(dr)1575b0945b5SGregory Neil Shapiro dns_free_data(dr)
1585b0945b5SGregory Neil Shapiro DNS_REPLY_T *dr;
15940266059SGregory Neil Shapiro {
16040266059SGregory Neil Shapiro RESOURCE_RECORD_T *rr;
16140266059SGregory Neil Shapiro
1625b0945b5SGregory Neil Shapiro if (dr == NULL)
1635b0945b5SGregory Neil Shapiro return;
1645b0945b5SGregory Neil Shapiro if (dr->dns_r_q.dns_q_domain != NULL)
1655b0945b5SGregory Neil Shapiro sm_free(dr->dns_r_q.dns_q_domain);
1665b0945b5SGregory Neil Shapiro for (rr = dr->dns_r_head; rr != NULL; )
16740266059SGregory Neil Shapiro {
16840266059SGregory Neil Shapiro RESOURCE_RECORD_T *tmp = rr;
16940266059SGregory Neil Shapiro
17040266059SGregory Neil Shapiro if (rr->rr_domain != NULL)
17140266059SGregory Neil Shapiro sm_free(rr->rr_domain);
17240266059SGregory Neil Shapiro if (rr->rr_u.rr_data != NULL)
17340266059SGregory Neil Shapiro sm_free(rr->rr_u.rr_data);
17440266059SGregory Neil Shapiro rr = rr->rr_next;
17540266059SGregory Neil Shapiro sm_free(tmp);
17640266059SGregory Neil Shapiro }
1775b0945b5SGregory Neil Shapiro sm_free(dr);
1785b0945b5SGregory Neil Shapiro }
1795b0945b5SGregory Neil Shapiro
1805b0945b5SGregory Neil Shapiro /*
1815b0945b5SGregory Neil Shapiro ** BIN2HEX -- convert binary TLSA RR to hex string
1825b0945b5SGregory Neil Shapiro **
1835b0945b5SGregory Neil Shapiro ** Parameters:
1845b0945b5SGregory Neil Shapiro ** tlsa -- pointer to result (allocated here)
1855b0945b5SGregory Neil Shapiro ** p -- binary data (TLSA RR)
1865b0945b5SGregory Neil Shapiro ** size -- length of p
1875b0945b5SGregory Neil Shapiro ** min_size -- minimum expected size
1885b0945b5SGregory Neil Shapiro **
1895b0945b5SGregory Neil Shapiro ** Returns:
1905b0945b5SGregory Neil Shapiro ** >0: length of string (*tlsa)
1915b0945b5SGregory Neil Shapiro ** -1: error
1925b0945b5SGregory Neil Shapiro */
1935b0945b5SGregory Neil Shapiro
1945b0945b5SGregory Neil Shapiro static int bin2hex __P((char **, unsigned char *, int, int));
1955b0945b5SGregory Neil Shapiro
1965b0945b5SGregory Neil Shapiro static int
bin2hex(tlsa,p,size,min_size)1975b0945b5SGregory Neil Shapiro bin2hex(tlsa, p, size, min_size)
1985b0945b5SGregory Neil Shapiro char **tlsa;
1995b0945b5SGregory Neil Shapiro unsigned char *p;
2005b0945b5SGregory Neil Shapiro int size;
2015b0945b5SGregory Neil Shapiro int min_size;
2025b0945b5SGregory Neil Shapiro {
2035b0945b5SGregory Neil Shapiro int i, pos, txtlen;
2045b0945b5SGregory Neil Shapiro
2055b0945b5SGregory Neil Shapiro txtlen = size * 3;
2065b0945b5SGregory Neil Shapiro if (txtlen <= size || size < min_size)
2075b0945b5SGregory Neil Shapiro {
2085b0945b5SGregory Neil Shapiro if (LogLevel > 5)
2095b0945b5SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID,
2105b0945b5SGregory Neil Shapiro "ERROR: bin2hex: size %d wrong", size);
2115b0945b5SGregory Neil Shapiro return -1;
2125b0945b5SGregory Neil Shapiro }
2135b0945b5SGregory Neil Shapiro *tlsa = (char *) sm_malloc(txtlen);
2145b0945b5SGregory Neil Shapiro if (*tlsa == NULL)
2155b0945b5SGregory Neil Shapiro {
2165b0945b5SGregory Neil Shapiro if (tTd(8, 17))
2175b0945b5SGregory Neil Shapiro sm_dprintf("len=%d, rr_data=NULL\n", txtlen);
2185b0945b5SGregory Neil Shapiro return -1;
2195b0945b5SGregory Neil Shapiro }
2205b0945b5SGregory Neil Shapiro snprintf(*tlsa, txtlen,
2215b0945b5SGregory Neil Shapiro "%02X %02X %02X", p[0], p[1], p[2]);
2225b0945b5SGregory Neil Shapiro pos = strlen(*tlsa);
2235b0945b5SGregory Neil Shapiro
2245b0945b5SGregory Neil Shapiro /* why isn't there a print function like strlcat? */
2255b0945b5SGregory Neil Shapiro for (i = 3; i < size && pos < txtlen; i++, pos += 3)
2265b0945b5SGregory Neil Shapiro snprintf(*tlsa + pos, txtlen - pos, "%c%02X",
2275b0945b5SGregory Neil Shapiro (i == 3) ? ' ' : ':', p[i]);
2285b0945b5SGregory Neil Shapiro
2295b0945b5SGregory Neil Shapiro return i;
23040266059SGregory Neil Shapiro }
23140266059SGregory Neil Shapiro
23240266059SGregory Neil Shapiro /*
23340266059SGregory Neil Shapiro ** PARSE_DNS_REPLY -- parse DNS reply data.
23440266059SGregory Neil Shapiro **
23540266059SGregory Neil Shapiro ** Parameters:
23640266059SGregory Neil Shapiro ** data -- pointer to dns data
23740266059SGregory Neil Shapiro ** len -- len of data
2385b0945b5SGregory Neil Shapiro ** flags -- flags (RR_*)
23940266059SGregory Neil Shapiro **
24040266059SGregory Neil Shapiro ** Returns:
24140266059SGregory Neil Shapiro ** pointer to DNS_REPLY_T if succeeded.
24240266059SGregory Neil Shapiro ** NULL otherwise.
2435b0945b5SGregory Neil Shapiro **
2445b0945b5SGregory Neil Shapiro ** Note:
2455b0945b5SGregory Neil Shapiro ** use dns_free_data() to free() the result when no longer needed.
24640266059SGregory Neil Shapiro */
24740266059SGregory Neil Shapiro
24840266059SGregory Neil Shapiro static DNS_REPLY_T *
parse_dns_reply(data,len,flags)2495b0945b5SGregory Neil Shapiro parse_dns_reply(data, len, flags)
25040266059SGregory Neil Shapiro unsigned char *data;
25140266059SGregory Neil Shapiro int len;
2525b0945b5SGregory Neil Shapiro unsigned int flags;
25340266059SGregory Neil Shapiro {
25440266059SGregory Neil Shapiro unsigned char *p;
255e3793f76SGregory Neil Shapiro unsigned short ans_cnt, ui;
25640266059SGregory Neil Shapiro int status;
25740266059SGregory Neil Shapiro size_t l;
25840266059SGregory Neil Shapiro char host[MAXHOSTNAMELEN];
2595b0945b5SGregory Neil Shapiro DNS_REPLY_T *dr;
26040266059SGregory Neil Shapiro RESOURCE_RECORD_T **rr;
26140266059SGregory Neil Shapiro
2625b0945b5SGregory Neil Shapiro if (tTd(8, 90))
2635b0945b5SGregory Neil Shapiro {
2645b0945b5SGregory Neil Shapiro FILE *fp;
2655b0945b5SGregory Neil Shapiro
2665b0945b5SGregory Neil Shapiro fp = fopen("dns.buffer", "w");
2675b0945b5SGregory Neil Shapiro if (fp != NULL)
2685b0945b5SGregory Neil Shapiro {
2695b0945b5SGregory Neil Shapiro fwrite(data, 1, len, fp);
2705b0945b5SGregory Neil Shapiro fclose(fp);
2715b0945b5SGregory Neil Shapiro fp = NULL;
2725b0945b5SGregory Neil Shapiro }
2735b0945b5SGregory Neil Shapiro else
2745b0945b5SGregory Neil Shapiro sm_dprintf("parse_dns_reply: fp=%p, e=%d\n",
2755b0945b5SGregory Neil Shapiro (void *)fp, errno);
2765b0945b5SGregory Neil Shapiro }
2775b0945b5SGregory Neil Shapiro
2785b0945b5SGregory Neil Shapiro dr = (DNS_REPLY_T *) sm_malloc(sizeof(*dr));
2795b0945b5SGregory Neil Shapiro if (dr == NULL)
28040266059SGregory Neil Shapiro return NULL;
2815b0945b5SGregory Neil Shapiro memset(dr, 0, sizeof(*dr));
28240266059SGregory Neil Shapiro
28340266059SGregory Neil Shapiro p = data;
28440266059SGregory Neil Shapiro
28540266059SGregory Neil Shapiro /* doesn't work on Crays? */
2865b0945b5SGregory Neil Shapiro memcpy(&dr->dns_r_h, p, sizeof(dr->dns_r_h));
2875b0945b5SGregory Neil Shapiro p += sizeof(dr->dns_r_h);
288d0cef73dSGregory Neil Shapiro status = dn_expand(data, data + len, p, host, sizeof(host));
28940266059SGregory Neil Shapiro if (status < 0)
2905b0945b5SGregory Neil Shapiro goto error;
2915b0945b5SGregory Neil Shapiro dr->dns_r_q.dns_q_domain = sm_strdup(host);
2925b0945b5SGregory Neil Shapiro if (dr->dns_r_q.dns_q_domain == NULL)
2935b0945b5SGregory Neil Shapiro goto error;
294ffb83623SGregory Neil Shapiro
2955b0945b5SGregory Neil Shapiro ans_cnt = ntohs((unsigned short) dr->dns_r_h.ancount);
2965b0945b5SGregory Neil Shapiro if (tTd(8, 17))
2975b0945b5SGregory Neil Shapiro sm_dprintf("parse_dns_reply: ac=%d, ad=%d\n", ans_cnt,
2985b0945b5SGregory Neil Shapiro dr->dns_r_h.ad);
299ffb83623SGregory Neil Shapiro
30040266059SGregory Neil Shapiro p += status;
3015b0945b5SGregory Neil Shapiro GETSHORT(dr->dns_r_q.dns_q_type, p);
3025b0945b5SGregory Neil Shapiro GETSHORT(dr->dns_r_q.dns_q_class, p);
3035b0945b5SGregory Neil Shapiro rr = &dr->dns_r_head;
304ffb83623SGregory Neil Shapiro ui = 0;
305ffb83623SGregory Neil Shapiro while (p < data + len && ui < ans_cnt)
30640266059SGregory Neil Shapiro {
307739ac4d4SGregory Neil Shapiro int type, class, ttl, size, txtlen;
30840266059SGregory Neil Shapiro
309d0cef73dSGregory Neil Shapiro status = dn_expand(data, data + len, p, host, sizeof(host));
31040266059SGregory Neil Shapiro if (status < 0)
3115b0945b5SGregory Neil Shapiro goto error;
312ffb83623SGregory Neil Shapiro ++ui;
31340266059SGregory Neil Shapiro p += status;
31440266059SGregory Neil Shapiro GETSHORT(type, p);
31540266059SGregory Neil Shapiro GETSHORT(class, p);
31640266059SGregory Neil Shapiro GETLONG(ttl, p);
31740266059SGregory Neil Shapiro GETSHORT(size, p);
318739ac4d4SGregory Neil Shapiro if (p + size > data + len)
319739ac4d4SGregory Neil Shapiro {
320739ac4d4SGregory Neil Shapiro /*
321739ac4d4SGregory Neil Shapiro ** announced size of data exceeds length of
322739ac4d4SGregory Neil Shapiro ** data paket: someone is cheating.
323739ac4d4SGregory Neil Shapiro */
324739ac4d4SGregory Neil Shapiro
325739ac4d4SGregory Neil Shapiro if (LogLevel > 5)
326739ac4d4SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID,
327739ac4d4SGregory Neil Shapiro "ERROR: DNS RDLENGTH=%d > data len=%d",
328da7d7b9cSGregory Neil Shapiro size, len - (int)(p - data));
3295b0945b5SGregory Neil Shapiro goto error;
330739ac4d4SGregory Neil Shapiro }
3315ef517c0SGregory Neil Shapiro *rr = (RESOURCE_RECORD_T *) sm_malloc(sizeof(**rr));
33240266059SGregory Neil Shapiro if (*rr == NULL)
3335b0945b5SGregory Neil Shapiro goto error;
3345ef517c0SGregory Neil Shapiro memset(*rr, 0, sizeof(**rr));
33540266059SGregory Neil Shapiro (*rr)->rr_domain = sm_strdup(host);
33640266059SGregory Neil Shapiro if ((*rr)->rr_domain == NULL)
3375b0945b5SGregory Neil Shapiro goto error;
33840266059SGregory Neil Shapiro (*rr)->rr_type = type;
33940266059SGregory Neil Shapiro (*rr)->rr_class = class;
34040266059SGregory Neil Shapiro (*rr)->rr_ttl = ttl;
34140266059SGregory Neil Shapiro (*rr)->rr_size = size;
34240266059SGregory Neil Shapiro switch (type)
34340266059SGregory Neil Shapiro {
34440266059SGregory Neil Shapiro case T_NS:
34540266059SGregory Neil Shapiro case T_CNAME:
34640266059SGregory Neil Shapiro case T_PTR:
34740266059SGregory Neil Shapiro status = dn_expand(data, data + len, p, host,
348d0cef73dSGregory Neil Shapiro sizeof(host));
34940266059SGregory Neil Shapiro if (status < 0)
3505b0945b5SGregory Neil Shapiro goto error;
3515b0945b5SGregory Neil Shapiro if (tTd(8, 50))
3525b0945b5SGregory Neil Shapiro sm_dprintf("parse_dns_reply: type=%s, host=%s\n",
3535b0945b5SGregory Neil Shapiro dns_type_to_string(type), host);
35440266059SGregory Neil Shapiro (*rr)->rr_u.rr_txt = sm_strdup(host);
35540266059SGregory Neil Shapiro if ((*rr)->rr_u.rr_txt == NULL)
3565b0945b5SGregory Neil Shapiro goto error;
35740266059SGregory Neil Shapiro break;
35840266059SGregory Neil Shapiro
35940266059SGregory Neil Shapiro case T_MX:
36040266059SGregory Neil Shapiro case T_AFSDB:
36140266059SGregory Neil Shapiro status = dn_expand(data, data + len, p + 2, host,
362d0cef73dSGregory Neil Shapiro sizeof(host));
36340266059SGregory Neil Shapiro if (status < 0)
3645b0945b5SGregory Neil Shapiro goto error;
36540266059SGregory Neil Shapiro l = strlen(host) + 1;
36640266059SGregory Neil Shapiro (*rr)->rr_u.rr_mx = (MX_RECORD_T *)
3675ef517c0SGregory Neil Shapiro sm_malloc(sizeof(*((*rr)->rr_u.rr_mx)) + l);
36840266059SGregory Neil Shapiro if ((*rr)->rr_u.rr_mx == NULL)
3695b0945b5SGregory Neil Shapiro goto error;
37040266059SGregory Neil Shapiro (*rr)->rr_u.rr_mx->mx_r_preference = (p[0] << 8) | p[1];
37140266059SGregory Neil Shapiro (void) sm_strlcpy((*rr)->rr_u.rr_mx->mx_r_domain,
37240266059SGregory Neil Shapiro host, l);
3735b0945b5SGregory Neil Shapiro if (tTd(8, 50))
3745b0945b5SGregory Neil Shapiro sm_dprintf("mx=%s, pref=%d\n", host,
3755b0945b5SGregory Neil Shapiro (*rr)->rr_u.rr_mx->mx_r_preference);
37640266059SGregory Neil Shapiro break;
37740266059SGregory Neil Shapiro
37840266059SGregory Neil Shapiro case T_SRV:
37940266059SGregory Neil Shapiro status = dn_expand(data, data + len, p + 6, host,
380d0cef73dSGregory Neil Shapiro sizeof(host));
38140266059SGregory Neil Shapiro if (status < 0)
3825b0945b5SGregory Neil Shapiro goto error;
38340266059SGregory Neil Shapiro l = strlen(host) + 1;
38440266059SGregory Neil Shapiro (*rr)->rr_u.rr_srv = (SRV_RECORDT_T*)
3855ef517c0SGregory Neil Shapiro sm_malloc(sizeof(*((*rr)->rr_u.rr_srv)) + l);
38640266059SGregory Neil Shapiro if ((*rr)->rr_u.rr_srv == NULL)
3875b0945b5SGregory Neil Shapiro goto error;
38840266059SGregory Neil Shapiro (*rr)->rr_u.rr_srv->srv_r_priority = (p[0] << 8) | p[1];
38940266059SGregory Neil Shapiro (*rr)->rr_u.rr_srv->srv_r_weight = (p[2] << 8) | p[3];
39040266059SGregory Neil Shapiro (*rr)->rr_u.rr_srv->srv_r_port = (p[4] << 8) | p[5];
39140266059SGregory Neil Shapiro (void) sm_strlcpy((*rr)->rr_u.rr_srv->srv_r_target,
39240266059SGregory Neil Shapiro host, l);
39340266059SGregory Neil Shapiro break;
39440266059SGregory Neil Shapiro
39540266059SGregory Neil Shapiro case T_TXT:
396739ac4d4SGregory Neil Shapiro
397739ac4d4SGregory Neil Shapiro /*
398739ac4d4SGregory Neil Shapiro ** The TXT record contains the length as
399739ac4d4SGregory Neil Shapiro ** leading byte, hence the value is restricted
400739ac4d4SGregory Neil Shapiro ** to 255, which is less than the maximum value
401739ac4d4SGregory Neil Shapiro ** of RDLENGTH (size). Nevertheless, txtlen
402739ac4d4SGregory Neil Shapiro ** must be less than size because the latter
403739ac4d4SGregory Neil Shapiro ** specifies the length of the entire TXT
404739ac4d4SGregory Neil Shapiro ** record.
405739ac4d4SGregory Neil Shapiro */
406739ac4d4SGregory Neil Shapiro
407739ac4d4SGregory Neil Shapiro txtlen = *p;
408739ac4d4SGregory Neil Shapiro if (txtlen >= size)
409739ac4d4SGregory Neil Shapiro {
410739ac4d4SGregory Neil Shapiro if (LogLevel > 5)
411739ac4d4SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID,
412739ac4d4SGregory Neil Shapiro "ERROR: DNS TXT record size=%d <= text len=%d",
413739ac4d4SGregory Neil Shapiro size, txtlen);
4145b0945b5SGregory Neil Shapiro goto error;
415739ac4d4SGregory Neil Shapiro }
4165ef517c0SGregory Neil Shapiro (*rr)->rr_u.rr_txt = (char *) sm_malloc(txtlen + 1);
41740266059SGregory Neil Shapiro if ((*rr)->rr_u.rr_txt == NULL)
4185b0945b5SGregory Neil Shapiro goto error;
419739ac4d4SGregory Neil Shapiro (void) sm_strlcpy((*rr)->rr_u.rr_txt, (char*) p + 1,
420739ac4d4SGregory Neil Shapiro txtlen + 1);
42140266059SGregory Neil Shapiro break;
42240266059SGregory Neil Shapiro
4235b0945b5SGregory Neil Shapiro # ifdef T_TLSA
4245b0945b5SGregory Neil Shapiro case T_TLSA:
4255b0945b5SGregory Neil Shapiro if (tTd(8, 61))
4265b0945b5SGregory Neil Shapiro sm_dprintf("parse_dns_reply: TLSA, size=%d, flags=%X\n",
4275b0945b5SGregory Neil Shapiro size, flags);
4285b0945b5SGregory Neil Shapiro if ((flags & RR_AS_TEXT) != 0)
4295b0945b5SGregory Neil Shapiro {
4305b0945b5SGregory Neil Shapiro txtlen = bin2hex((char **)&((*rr)->rr_u.rr_data),
4315b0945b5SGregory Neil Shapiro p, size, 4);
4325b0945b5SGregory Neil Shapiro if (txtlen <= 0)
4335b0945b5SGregory Neil Shapiro goto error;
4345b0945b5SGregory Neil Shapiro break;
4355b0945b5SGregory Neil Shapiro }
4365b0945b5SGregory Neil Shapiro /* FALLTHROUGH */
4375b0945b5SGregory Neil Shapiro /* return "raw" data for caller to use as it pleases */
4385b0945b5SGregory Neil Shapiro # endif /* T_TLSA */
4395b0945b5SGregory Neil Shapiro
44040266059SGregory Neil Shapiro default:
4415ef517c0SGregory Neil Shapiro (*rr)->rr_u.rr_data = (unsigned char*) sm_malloc(size);
4425ef517c0SGregory Neil Shapiro if ((*rr)->rr_u.rr_data == NULL)
4435b0945b5SGregory Neil Shapiro goto error;
44440266059SGregory Neil Shapiro (void) memcpy((*rr)->rr_u.rr_data, p, size);
4455b0945b5SGregory Neil Shapiro if (tTd(8, 61) && type == T_A)
4465b0945b5SGregory Neil Shapiro {
4475b0945b5SGregory Neil Shapiro SOCKADDR addr;
4485b0945b5SGregory Neil Shapiro
4495b0945b5SGregory Neil Shapiro (void) memcpy((void *)&addr.sin.sin_addr.s_addr, p, size);
4505b0945b5SGregory Neil Shapiro sm_dprintf("parse_dns_reply: IPv4=%s\n",
4515b0945b5SGregory Neil Shapiro inet_ntoa(addr.sin.sin_addr));
4525b0945b5SGregory Neil Shapiro }
453739ac4d4SGregory Neil Shapiro break;
45440266059SGregory Neil Shapiro }
45540266059SGregory Neil Shapiro p += size;
45640266059SGregory Neil Shapiro rr = &(*rr)->rr_next;
45740266059SGregory Neil Shapiro }
45840266059SGregory Neil Shapiro *rr = NULL;
4595b0945b5SGregory Neil Shapiro return dr;
4605b0945b5SGregory Neil Shapiro
4615b0945b5SGregory Neil Shapiro error:
4625b0945b5SGregory Neil Shapiro dns_free_data(dr);
4635b0945b5SGregory Neil Shapiro return NULL;
4645b0945b5SGregory Neil Shapiro }
4655b0945b5SGregory Neil Shapiro
4665b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
4675b0945b5SGregory Neil Shapiro
4685b0945b5SGregory Neil Shapiro # include <arpa/nameser.h>
4692fb4f839SGregory Neil Shapiro # if _FFR_8BITENVADDR
4702fb4f839SGregory Neil Shapiro # include <sm/sendmail.h>
4712fb4f839SGregory Neil Shapiro # endif
4725b0945b5SGregory Neil Shapiro
4735b0945b5SGregory Neil Shapiro static int gen_dns_reply __P((unsigned char *, int, unsigned char *,
4745b0945b5SGregory Neil Shapiro const char *, int, const char *, int, int, int, int,
4755b0945b5SGregory Neil Shapiro const char *, int, int, int));
4765b0945b5SGregory Neil Shapiro static int dnscrtrr __P((const char *, const char *, int, char *, int,
4775b0945b5SGregory Neil Shapiro unsigned int, int *, int *, unsigned char *, int, unsigned char *));
4785b0945b5SGregory Neil Shapiro
4795b0945b5SGregory Neil Shapiro /*
4805b0945b5SGregory Neil Shapiro ** HERRNO2TXT -- return error text for h_errno
4815b0945b5SGregory Neil Shapiro **
4825b0945b5SGregory Neil Shapiro ** Parameters:
4835b0945b5SGregory Neil Shapiro ** e -- h_errno
4845b0945b5SGregory Neil Shapiro **
4855b0945b5SGregory Neil Shapiro ** Returns:
4865b0945b5SGregory Neil Shapiro ** DNS error text if available
4875b0945b5SGregory Neil Shapiro */
4885b0945b5SGregory Neil Shapiro
4895b0945b5SGregory Neil Shapiro const char *
herrno2txt(e)4905b0945b5SGregory Neil Shapiro herrno2txt(e)
4915b0945b5SGregory Neil Shapiro int e;
4925b0945b5SGregory Neil Shapiro {
4935b0945b5SGregory Neil Shapiro switch (e)
4945b0945b5SGregory Neil Shapiro {
4955b0945b5SGregory Neil Shapiro case NETDB_INTERNAL:
4965b0945b5SGregory Neil Shapiro return "see errno";
4975b0945b5SGregory Neil Shapiro case NETDB_SUCCESS:
4985b0945b5SGregory Neil Shapiro return "OK";
4995b0945b5SGregory Neil Shapiro case HOST_NOT_FOUND:
5005b0945b5SGregory Neil Shapiro return "HOST_NOT_FOUND";
5015b0945b5SGregory Neil Shapiro case TRY_AGAIN:
5025b0945b5SGregory Neil Shapiro return "TRY_AGAIN";
5035b0945b5SGregory Neil Shapiro case NO_RECOVERY:
5045b0945b5SGregory Neil Shapiro return "NO_RECOVERY";
5055b0945b5SGregory Neil Shapiro case NO_DATA:
5065b0945b5SGregory Neil Shapiro return "NO_DATA";
5075b0945b5SGregory Neil Shapiro }
5085b0945b5SGregory Neil Shapiro return "bogus h_errno";
50940266059SGregory Neil Shapiro }
51040266059SGregory Neil Shapiro
51140266059SGregory Neil Shapiro /*
5125b0945b5SGregory Neil Shapiro ** GEN_DNS_REPLY -- generate DNS reply data.
5135b0945b5SGregory Neil Shapiro **
5145b0945b5SGregory Neil Shapiro ** Parameters:
5155b0945b5SGregory Neil Shapiro ** buf -- buffer to which DNS data is written
5165b0945b5SGregory Neil Shapiro ** buflen -- length of buffer
5175b0945b5SGregory Neil Shapiro ** bufpos -- position in buffer where DNS RRs are appended
5185b0945b5SGregory Neil Shapiro ** query -- name of query
5195b0945b5SGregory Neil Shapiro ** qtype -- resource record type of query
5205b0945b5SGregory Neil Shapiro ** domain -- name of domain which has been "found"
5215b0945b5SGregory Neil Shapiro ** class -- resource record class
5225b0945b5SGregory Neil Shapiro ** type -- resource record type
5235b0945b5SGregory Neil Shapiro ** ttl -- TTL
5245b0945b5SGregory Neil Shapiro ** size -- size of data
5255b0945b5SGregory Neil Shapiro ** data -- data
5265b0945b5SGregory Neil Shapiro ** txtlen -- length of text
5275b0945b5SGregory Neil Shapiro ** pref -- MX preference
5285b0945b5SGregory Neil Shapiro ** ad -- ad flag
5295b0945b5SGregory Neil Shapiro **
5305b0945b5SGregory Neil Shapiro ** Returns:
5315b0945b5SGregory Neil Shapiro ** >0 length of buffer that has been used.
5325b0945b5SGregory Neil Shapiro ** <0 error
5335b0945b5SGregory Neil Shapiro */
5345b0945b5SGregory Neil Shapiro
5355b0945b5SGregory Neil Shapiro static int
gen_dns_reply(buf,buflen,bufpos,query,qtype,domain,class,type,ttl,size,data,txtlen,pref,ad)5365b0945b5SGregory Neil Shapiro gen_dns_reply(buf, buflen, bufpos, query, qtype, domain, class, type, ttl, size, data, txtlen, pref, ad)
5375b0945b5SGregory Neil Shapiro unsigned char *buf;
5385b0945b5SGregory Neil Shapiro int buflen;
5395b0945b5SGregory Neil Shapiro unsigned char *bufpos;
5405b0945b5SGregory Neil Shapiro const char *query;
5415b0945b5SGregory Neil Shapiro int qtype;
5425b0945b5SGregory Neil Shapiro const char *domain;
5435b0945b5SGregory Neil Shapiro int class;
5445b0945b5SGregory Neil Shapiro int type;
5455b0945b5SGregory Neil Shapiro int ttl;
5465b0945b5SGregory Neil Shapiro int size;
5475b0945b5SGregory Neil Shapiro const char *data;
5485b0945b5SGregory Neil Shapiro int txtlen;
5495b0945b5SGregory Neil Shapiro int pref;
5505b0945b5SGregory Neil Shapiro int ad;
5515b0945b5SGregory Neil Shapiro {
5525b0945b5SGregory Neil Shapiro unsigned short ans_cnt;
5535b0945b5SGregory Neil Shapiro HEADER *hp;
5545b0945b5SGregory Neil Shapiro unsigned char *cp, *ep;
5555b0945b5SGregory Neil Shapiro int n;
5565b0945b5SGregory Neil Shapiro static unsigned char *dnptrs[20], **dpp, **lastdnptr;
5575b0945b5SGregory Neil Shapiro
5582fb4f839SGregory Neil Shapiro #define DN_COMP_CHK do \
5592fb4f839SGregory Neil Shapiro { \
5602fb4f839SGregory Neil Shapiro if (n < 0) \
5612fb4f839SGregory Neil Shapiro { \
5622fb4f839SGregory Neil Shapiro if (tTd(8, 91)) \
5632fb4f839SGregory Neil Shapiro sm_dprintf("gen_dns_reply: dn_comp=%d\n", n); \
5642fb4f839SGregory Neil Shapiro return n; \
5652fb4f839SGregory Neil Shapiro } \
5662fb4f839SGregory Neil Shapiro } while (0)
5672fb4f839SGregory Neil Shapiro
5685b0945b5SGregory Neil Shapiro SM_REQUIRE(NULL != buf);
5695b0945b5SGregory Neil Shapiro SM_REQUIRE(buflen >= HFIXEDSZ);
5705b0945b5SGregory Neil Shapiro SM_REQUIRE(query != NULL);
5715b0945b5SGregory Neil Shapiro hp = (HEADER *) buf;
5725b0945b5SGregory Neil Shapiro ep = buf + buflen;
5735b0945b5SGregory Neil Shapiro cp = buf + HFIXEDSZ;
5745b0945b5SGregory Neil Shapiro
5755b0945b5SGregory Neil Shapiro if (bufpos != NULL)
5765b0945b5SGregory Neil Shapiro cp = bufpos;
5775b0945b5SGregory Neil Shapiro else
5785b0945b5SGregory Neil Shapiro {
5795b0945b5SGregory Neil Shapiro sm_dprintf("gen_dns_reply: query=%s, domain=%s, type=%s, size=%d, ad=%d\n",
5805b0945b5SGregory Neil Shapiro query, domain, dns_type_to_string(type), size, ad);
5815b0945b5SGregory Neil Shapiro dpp = dnptrs;
5825b0945b5SGregory Neil Shapiro *dpp++ = buf;
5835b0945b5SGregory Neil Shapiro *dpp++ = NULL;
5845b0945b5SGregory Neil Shapiro lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
5855b0945b5SGregory Neil Shapiro
5865b0945b5SGregory Neil Shapiro memset(buf, 0, HFIXEDSZ);
5875b0945b5SGregory Neil Shapiro hp->id = 0xdead; /* HACK */
5885b0945b5SGregory Neil Shapiro hp->qr = 1;
5895b0945b5SGregory Neil Shapiro hp->opcode = QUERY;
5905b0945b5SGregory Neil Shapiro hp->rd = 0; /* recursion desired? */
5915b0945b5SGregory Neil Shapiro hp->rcode = 0; /* !!! */
5925b0945b5SGregory Neil Shapiro /* hp->aa = ?; * !!! */
5935b0945b5SGregory Neil Shapiro /* hp->tc = ?; * !!! */
5945b0945b5SGregory Neil Shapiro /* hp->ra = ?; * !!! */
5955b0945b5SGregory Neil Shapiro hp->qdcount = htons(1);
5965b0945b5SGregory Neil Shapiro hp->ancount = 0;
5975b0945b5SGregory Neil Shapiro
5985b0945b5SGregory Neil Shapiro n = dn_comp(query, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
5992fb4f839SGregory Neil Shapiro DN_COMP_CHK;
6005b0945b5SGregory Neil Shapiro cp += n;
6015b0945b5SGregory Neil Shapiro PUTSHORT(qtype, cp);
6025b0945b5SGregory Neil Shapiro PUTSHORT(class, cp);
6035b0945b5SGregory Neil Shapiro }
6045b0945b5SGregory Neil Shapiro hp->ad = ad;
6055b0945b5SGregory Neil Shapiro
6065b0945b5SGregory Neil Shapiro if (ep - cp < QFIXEDSZ)
6072fb4f839SGregory Neil Shapiro {
6082fb4f839SGregory Neil Shapiro if (tTd(8, 91))
6092fb4f839SGregory Neil Shapiro sm_dprintf("gen_dns_reply: ep-cp=%ld\n",
6102fb4f839SGregory Neil Shapiro (long) (ep - cp));
6115b0945b5SGregory Neil Shapiro return (-1);
6122fb4f839SGregory Neil Shapiro }
6135b0945b5SGregory Neil Shapiro n = dn_comp(domain, cp, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
6142fb4f839SGregory Neil Shapiro DN_COMP_CHK;
6155b0945b5SGregory Neil Shapiro cp += n;
6165b0945b5SGregory Neil Shapiro PUTSHORT(type, cp);
6175b0945b5SGregory Neil Shapiro PUTSHORT(class, cp);
6185b0945b5SGregory Neil Shapiro PUTLONG(ttl, cp);
6195b0945b5SGregory Neil Shapiro
6205b0945b5SGregory Neil Shapiro ans_cnt = ntohs((unsigned short) hp->ancount);
6215b0945b5SGregory Neil Shapiro ++ans_cnt;
6225b0945b5SGregory Neil Shapiro hp->ancount = htons((unsigned short) ans_cnt);
6235b0945b5SGregory Neil Shapiro
6245b0945b5SGregory Neil Shapiro switch (type)
6255b0945b5SGregory Neil Shapiro {
6265b0945b5SGregory Neil Shapiro case T_MX:
6275b0945b5SGregory Neil Shapiro n = dn_comp(data, cp + 4, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
6282fb4f839SGregory Neil Shapiro DN_COMP_CHK;
6295b0945b5SGregory Neil Shapiro PUTSHORT(n + 2, cp);
6305b0945b5SGregory Neil Shapiro PUTSHORT(pref, cp);
6315b0945b5SGregory Neil Shapiro cp += n;
6325b0945b5SGregory Neil Shapiro break;
6335b0945b5SGregory Neil Shapiro
6345b0945b5SGregory Neil Shapiro case T_TXT:
6355b0945b5SGregory Neil Shapiro if (txtlen >= size)
6365b0945b5SGregory Neil Shapiro return -1;
6375b0945b5SGregory Neil Shapiro PUTSHORT(txtlen, cp);
6385b0945b5SGregory Neil Shapiro (void) sm_strlcpy((char *)cp, data, txtlen + 1);
6395b0945b5SGregory Neil Shapiro cp += txtlen;
6405b0945b5SGregory Neil Shapiro break;
6415b0945b5SGregory Neil Shapiro
6425b0945b5SGregory Neil Shapiro case T_CNAME:
6435b0945b5SGregory Neil Shapiro n = dn_comp(data, cp + 2, ep - cp - QFIXEDSZ, dnptrs, lastdnptr);
6442fb4f839SGregory Neil Shapiro DN_COMP_CHK;
6455b0945b5SGregory Neil Shapiro PUTSHORT(n, cp);
6465b0945b5SGregory Neil Shapiro cp += n;
6475b0945b5SGregory Neil Shapiro break;
6485b0945b5SGregory Neil Shapiro
6495b0945b5SGregory Neil Shapiro # if defined(T_TLSA)
6505b0945b5SGregory Neil Shapiro case T_TLSA:
6515b0945b5SGregory Neil Shapiro {
6525b0945b5SGregory Neil Shapiro char *tlsa;
6535b0945b5SGregory Neil Shapiro
6545b0945b5SGregory Neil Shapiro tlsa = hex2bin(data, size);
6555b0945b5SGregory Neil Shapiro if (tlsa == NULL)
6565b0945b5SGregory Neil Shapiro return (-1);
6575b0945b5SGregory Neil Shapiro n = size / 2;
6585b0945b5SGregory Neil Shapiro PUTSHORT(n, cp);
6595b0945b5SGregory Neil Shapiro (void) memcpy(cp, tlsa, n);
6605b0945b5SGregory Neil Shapiro cp += n;
6615b0945b5SGregory Neil Shapiro }
6625b0945b5SGregory Neil Shapiro break;
6635b0945b5SGregory Neil Shapiro # endif /* T_TLSA */
6645b0945b5SGregory Neil Shapiro
6655b0945b5SGregory Neil Shapiro default:
6665b0945b5SGregory Neil Shapiro PUTSHORT(size, cp);
6675b0945b5SGregory Neil Shapiro (void) memcpy(cp, data, size);
6685b0945b5SGregory Neil Shapiro cp += size;
6695b0945b5SGregory Neil Shapiro break;
6705b0945b5SGregory Neil Shapiro }
6715b0945b5SGregory Neil Shapiro
6725b0945b5SGregory Neil Shapiro return (cp - buf);
6735b0945b5SGregory Neil Shapiro }
6745b0945b5SGregory Neil Shapiro
6755b0945b5SGregory Neil Shapiro /*
6765b0945b5SGregory Neil Shapiro ** SETHERRNOFROMSTRING -- set h_errno based on text
6775b0945b5SGregory Neil Shapiro **
6785b0945b5SGregory Neil Shapiro ** Parameters:
6795b0945b5SGregory Neil Shapiro ** str -- string which might contain h_errno text
6805b0945b5SGregory Neil Shapiro ** prc -- pointer to rcode (EX_*)
6815b0945b5SGregory Neil Shapiro **
6825b0945b5SGregory Neil Shapiro ** Returns:
6835b0945b5SGregory Neil Shapiro ** h_errno if found
6845b0945b5SGregory Neil Shapiro ** 0 otherwise
6855b0945b5SGregory Neil Shapiro */
6865b0945b5SGregory Neil Shapiro
6875b0945b5SGregory Neil Shapiro int
setherrnofromstring(str,prc)6885b0945b5SGregory Neil Shapiro setherrnofromstring(str, prc)
6895b0945b5SGregory Neil Shapiro const char *str;
6905b0945b5SGregory Neil Shapiro int *prc;
6915b0945b5SGregory Neil Shapiro {
6925b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(0);
6932fb4f839SGregory Neil Shapiro if (SM_IS_EMPTY(str))
6945b0945b5SGregory Neil Shapiro return 0;
6955b0945b5SGregory Neil Shapiro if (strstr(str, "herrno:") == NULL)
6965b0945b5SGregory Neil Shapiro return 0;
6975b0945b5SGregory Neil Shapiro if (prc != NULL)
6985b0945b5SGregory Neil Shapiro *prc = EX_NOHOST;
6995b0945b5SGregory Neil Shapiro if (strstr(str, "host_not_found"))
7005b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(HOST_NOT_FOUND);
7015b0945b5SGregory Neil Shapiro else if (strstr(str, "try_again"))
7025b0945b5SGregory Neil Shapiro {
7035b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(TRY_AGAIN);
7045b0945b5SGregory Neil Shapiro if (prc != NULL)
7055b0945b5SGregory Neil Shapiro *prc = EX_TEMPFAIL;
7065b0945b5SGregory Neil Shapiro }
7075b0945b5SGregory Neil Shapiro else if (strstr(str, "no_recovery"))
7085b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(NO_RECOVERY);
7095b0945b5SGregory Neil Shapiro else if (strstr(str, "no_data"))
7105b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(NO_DATA);
7115b0945b5SGregory Neil Shapiro else
7125b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(NETDB_INTERNAL);
7135b0945b5SGregory Neil Shapiro return h_errno;
7145b0945b5SGregory Neil Shapiro }
7155b0945b5SGregory Neil Shapiro
7165b0945b5SGregory Neil Shapiro /*
7175b0945b5SGregory Neil Shapiro ** GETTTLFROMSTRING -- extract ttl from a string
7185b0945b5SGregory Neil Shapiro **
7195b0945b5SGregory Neil Shapiro ** Parameters:
7205b0945b5SGregory Neil Shapiro ** str -- string which might contain ttl
7215b0945b5SGregory Neil Shapiro **
7225b0945b5SGregory Neil Shapiro ** Returns:
7235b0945b5SGregory Neil Shapiro ** ttl if found
7245b0945b5SGregory Neil Shapiro ** 0 otherwise
7255b0945b5SGregory Neil Shapiro */
7265b0945b5SGregory Neil Shapiro
7275b0945b5SGregory Neil Shapiro int
getttlfromstring(str)7285b0945b5SGregory Neil Shapiro getttlfromstring(str)
7295b0945b5SGregory Neil Shapiro const char *str;
7305b0945b5SGregory Neil Shapiro {
7312fb4f839SGregory Neil Shapiro if (SM_IS_EMPTY(str))
7325b0945b5SGregory Neil Shapiro return 0;
7335b0945b5SGregory Neil Shapiro #define TTL_PRE "ttl="
7345b0945b5SGregory Neil Shapiro if (strstr(str, TTL_PRE) == NULL)
7355b0945b5SGregory Neil Shapiro return 0;
7365b0945b5SGregory Neil Shapiro return strtoul(str + strlen(TTL_PRE), NULL, 10);
7375b0945b5SGregory Neil Shapiro }
7385b0945b5SGregory Neil Shapiro
7395b0945b5SGregory Neil Shapiro
7405b0945b5SGregory Neil Shapiro # if defined(T_TLSA)
7415b0945b5SGregory Neil Shapiro /*
7425b0945b5SGregory Neil Shapiro ** HEX2BIN -- convert hex string to binary TLSA RR
7435b0945b5SGregory Neil Shapiro **
7445b0945b5SGregory Neil Shapiro ** Parameters:
7455b0945b5SGregory Neil Shapiro ** p -- hex representation of TLSA RR
7465b0945b5SGregory Neil Shapiro ** size -- length of p
7475b0945b5SGregory Neil Shapiro **
7485b0945b5SGregory Neil Shapiro ** Returns:
7495b0945b5SGregory Neil Shapiro ** pointer to binary TLSA RR
7505b0945b5SGregory Neil Shapiro ** NULL: error
7515b0945b5SGregory Neil Shapiro */
7525b0945b5SGregory Neil Shapiro
7535b0945b5SGregory Neil Shapiro static char *
hex2bin(p,size)7545b0945b5SGregory Neil Shapiro hex2bin(p, size)
7555b0945b5SGregory Neil Shapiro const char *p;
7565b0945b5SGregory Neil Shapiro int size;
7575b0945b5SGregory Neil Shapiro {
7585b0945b5SGregory Neil Shapiro int i, pos, txtlen;
7595b0945b5SGregory Neil Shapiro char *tlsa;
7605b0945b5SGregory Neil Shapiro
7615b0945b5SGregory Neil Shapiro txtlen = size / 2;
7625b0945b5SGregory Neil Shapiro if (txtlen * 2 == size)
7635b0945b5SGregory Neil Shapiro {
7645b0945b5SGregory Neil Shapiro if (LogLevel > 5)
7655b0945b5SGregory Neil Shapiro sm_syslog(LOG_WARNING, NOQID,
7665b0945b5SGregory Neil Shapiro "ERROR: hex2bin: size %d wrong", size);
7675b0945b5SGregory Neil Shapiro return NULL;
7685b0945b5SGregory Neil Shapiro }
7695b0945b5SGregory Neil Shapiro tlsa = sm_malloc(txtlen + 1);
7705b0945b5SGregory Neil Shapiro if (tlsa == NULL)
7715b0945b5SGregory Neil Shapiro {
7725b0945b5SGregory Neil Shapiro if (tTd(8, 17))
7735b0945b5SGregory Neil Shapiro sm_dprintf("len=%d, tlsa=NULL\n", txtlen);
7745b0945b5SGregory Neil Shapiro return NULL;
7755b0945b5SGregory Neil Shapiro }
7765b0945b5SGregory Neil Shapiro
7775b0945b5SGregory Neil Shapiro #define CHAR2INT(c) (((c) <= '9') ? ((c) - '0') : (toupper(c) - 'A' + 10))
7785b0945b5SGregory Neil Shapiro for (i = 0, pos = 0; i + 1 < size && pos < txtlen; i += 2, pos++)
7795b0945b5SGregory Neil Shapiro tlsa[pos] = CHAR2INT(p[i]) * 16 + CHAR2INT(p[i+1]);
7805b0945b5SGregory Neil Shapiro
7815b0945b5SGregory Neil Shapiro return tlsa;
7825b0945b5SGregory Neil Shapiro }
7835b0945b5SGregory Neil Shapiro # endif /* T_TLSA */
7845b0945b5SGregory Neil Shapiro
7855b0945b5SGregory Neil Shapiro const char *
rr_type2tag(rr_type)7865b0945b5SGregory Neil Shapiro rr_type2tag(rr_type)
7875b0945b5SGregory Neil Shapiro int rr_type;
7885b0945b5SGregory Neil Shapiro {
7895b0945b5SGregory Neil Shapiro switch (rr_type)
7905b0945b5SGregory Neil Shapiro {
7915b0945b5SGregory Neil Shapiro case T_A:
7925b0945b5SGregory Neil Shapiro return "ipv4";
7935b0945b5SGregory Neil Shapiro # if NETINET6
7945b0945b5SGregory Neil Shapiro case T_AAAA:
7955b0945b5SGregory Neil Shapiro return "ipv6";
7965b0945b5SGregory Neil Shapiro # endif
7975b0945b5SGregory Neil Shapiro case T_CNAME:
7985b0945b5SGregory Neil Shapiro return "cname";
7995b0945b5SGregory Neil Shapiro case T_MX:
8005b0945b5SGregory Neil Shapiro return "mx";
8015b0945b5SGregory Neil Shapiro # ifdef T_TLSA
8025b0945b5SGregory Neil Shapiro case T_TLSA:
8035b0945b5SGregory Neil Shapiro return "tlsa";
8045b0945b5SGregory Neil Shapiro # endif
8055b0945b5SGregory Neil Shapiro }
8065b0945b5SGregory Neil Shapiro return NULL;
8075b0945b5SGregory Neil Shapiro }
8085b0945b5SGregory Neil Shapiro
8095b0945b5SGregory Neil Shapiro /*
8105b0945b5SGregory Neil Shapiro ** DNSCRTRR -- create DNS RR
8115b0945b5SGregory Neil Shapiro **
8125b0945b5SGregory Neil Shapiro ** Parameters:
8135b0945b5SGregory Neil Shapiro ** domain -- original query domain
8145b0945b5SGregory Neil Shapiro ** query -- name of query
8155b0945b5SGregory Neil Shapiro ** qtype -- resource record type of query
8165b0945b5SGregory Neil Shapiro ** value -- (list of) data to set
8175b0945b5SGregory Neil Shapiro ** rr_type -- resource record type
8185b0945b5SGregory Neil Shapiro ** flags -- flags how to handle various lookups
8195b0945b5SGregory Neil Shapiro ** herr -- (pointer to) h_errno (output if non-NULL)
8205b0945b5SGregory Neil Shapiro ** adp -- (pointer to) ad flag
8215b0945b5SGregory Neil Shapiro ** answer -- buffer for RRs
8225b0945b5SGregory Neil Shapiro ** anslen -- size of answer
8235b0945b5SGregory Neil Shapiro ** anspos -- current position in answer
8245b0945b5SGregory Neil Shapiro **
8255b0945b5SGregory Neil Shapiro ** Returns:
8265b0945b5SGregory Neil Shapiro ** >0: length of data in answer
8275b0945b5SGregory Neil Shapiro ** <0: error, check *herr
8285b0945b5SGregory Neil Shapiro */
8295b0945b5SGregory Neil Shapiro
8305b0945b5SGregory Neil Shapiro static int
dnscrtrr(domain,query,qtype,value,rr_type,flags,herr,adp,answer,anslen,anspos)8315b0945b5SGregory Neil Shapiro dnscrtrr(domain, query, qtype, value, rr_type, flags, herr, adp, answer, anslen, anspos)
8325b0945b5SGregory Neil Shapiro const char *domain;
8335b0945b5SGregory Neil Shapiro const char *query;
8345b0945b5SGregory Neil Shapiro int qtype;
8355b0945b5SGregory Neil Shapiro char *value;
8365b0945b5SGregory Neil Shapiro int rr_type;
8375b0945b5SGregory Neil Shapiro unsigned int flags;
8385b0945b5SGregory Neil Shapiro int *herr;
8395b0945b5SGregory Neil Shapiro int *adp;
8405b0945b5SGregory Neil Shapiro unsigned char *answer;
8415b0945b5SGregory Neil Shapiro int anslen;
8425b0945b5SGregory Neil Shapiro unsigned char *anspos;
8435b0945b5SGregory Neil Shapiro {
8445b0945b5SGregory Neil Shapiro SOCKADDR addr;
8455b0945b5SGregory Neil Shapiro int ttl, ad, rlen;
8465b0945b5SGregory Neil Shapiro char *p, *token;
8475b0945b5SGregory Neil Shapiro char data[IN6ADDRSZ];
8485b0945b5SGregory Neil Shapiro char rhs[MAXLINE];
8495b0945b5SGregory Neil Shapiro
8505b0945b5SGregory Neil Shapiro rlen = -1;
8512fb4f839SGregory Neil Shapiro if (SM_IS_EMPTY(value))
8525b0945b5SGregory Neil Shapiro return rlen;
8535b0945b5SGregory Neil Shapiro SM_REQUIRE(adp != NULL);
8545b0945b5SGregory Neil Shapiro (void) sm_strlcpy(rhs, value, sizeof(rhs));
8555b0945b5SGregory Neil Shapiro p = rhs;
8565b0945b5SGregory Neil Shapiro if (setherrnofromstring(p, NULL) != 0)
8575b0945b5SGregory Neil Shapiro {
8585b0945b5SGregory Neil Shapiro if (herr != NULL)
8595b0945b5SGregory Neil Shapiro *herr = h_errno;
8605b0945b5SGregory Neil Shapiro if (tTd(8, 16))
8615b0945b5SGregory Neil Shapiro sm_dprintf("dnscrtrr rhs=%s h_errno=%d (%s)\n",
8625b0945b5SGregory Neil Shapiro p, h_errno, herrno2txt(h_errno));
8635b0945b5SGregory Neil Shapiro return rlen;
8645b0945b5SGregory Neil Shapiro }
8655b0945b5SGregory Neil Shapiro
8665b0945b5SGregory Neil Shapiro ttl = 0;
8675b0945b5SGregory Neil Shapiro ad = 0;
8685b0945b5SGregory Neil Shapiro for (token = p; token != NULL && *token != '\0'; token = p)
8695b0945b5SGregory Neil Shapiro {
8705b0945b5SGregory Neil Shapiro rlen = 0;
8715b0945b5SGregory Neil Shapiro while (p != NULL && *p != '\0' && !SM_ISSPACE(*p))
8725b0945b5SGregory Neil Shapiro ++p;
8735b0945b5SGregory Neil Shapiro if (SM_ISSPACE(*p))
8745b0945b5SGregory Neil Shapiro *p++ = '\0';
8755b0945b5SGregory Neil Shapiro sm_dprintf("dnscrtrr: token=%s\n", token);
8765b0945b5SGregory Neil Shapiro if (strcmp(token, "ad") == 0)
8775b0945b5SGregory Neil Shapiro {
8785b0945b5SGregory Neil Shapiro bool adflag;
8795b0945b5SGregory Neil Shapiro
8805b0945b5SGregory Neil Shapiro adflag = (_res.options & RES_USE_DNSSEC) != 0;
8815b0945b5SGregory Neil Shapiro
8825b0945b5SGregory Neil Shapiro /* maybe print this only for the final RR? */
8835b0945b5SGregory Neil Shapiro if (tTd(8, 61))
8845b0945b5SGregory Neil Shapiro sm_dprintf("dnscrtrr: ad=1, adp=%d, adflag=%d\n",
8855b0945b5SGregory Neil Shapiro *adp, adflag);
8865b0945b5SGregory Neil Shapiro if (*adp != 0 && adflag)
8875b0945b5SGregory Neil Shapiro {
8885b0945b5SGregory Neil Shapiro *adp = 1;
8895b0945b5SGregory Neil Shapiro ad = 1;
8905b0945b5SGregory Neil Shapiro }
8915b0945b5SGregory Neil Shapiro continue;
8925b0945b5SGregory Neil Shapiro }
8935b0945b5SGregory Neil Shapiro if (ttl == 0 && (ttl = getttlfromstring(token)) > 0)
8945b0945b5SGregory Neil Shapiro {
8955b0945b5SGregory Neil Shapiro if (tTd(8, 61))
8965b0945b5SGregory Neil Shapiro sm_dprintf("dnscrtrr: ttl=%d\n", ttl);
8975b0945b5SGregory Neil Shapiro continue;
8985b0945b5SGregory Neil Shapiro }
8995b0945b5SGregory Neil Shapiro
9005b0945b5SGregory Neil Shapiro if (rr_type == T_A)
9015b0945b5SGregory Neil Shapiro {
9025b0945b5SGregory Neil Shapiro addr.sin.sin_addr.s_addr = inet_addr(token);
9035b0945b5SGregory Neil Shapiro (void) memmove(data, (void *)&addr.sin.sin_addr.s_addr,
9045b0945b5SGregory Neil Shapiro INADDRSZ);
9055b0945b5SGregory Neil Shapiro rlen = gen_dns_reply(answer, anslen, anspos,
9065b0945b5SGregory Neil Shapiro query, qtype, domain, C_IN, rr_type, ttl,
9075b0945b5SGregory Neil Shapiro INADDRSZ, data, 0, 0, ad);
9085b0945b5SGregory Neil Shapiro }
9095b0945b5SGregory Neil Shapiro
9105b0945b5SGregory Neil Shapiro # if NETINET6
9115b0945b5SGregory Neil Shapiro if (rr_type == T_AAAA)
9125b0945b5SGregory Neil Shapiro {
9135b0945b5SGregory Neil Shapiro anynet_pton(AF_INET6, token, &addr.sin6.sin6_addr);
9145b0945b5SGregory Neil Shapiro memmove(data, (void *)&addr.sin6.sin6_addr, IN6ADDRSZ);
9155b0945b5SGregory Neil Shapiro rlen = gen_dns_reply(answer, anslen, anspos,
9165b0945b5SGregory Neil Shapiro query, qtype, domain, C_IN, rr_type, ttl,
9175b0945b5SGregory Neil Shapiro IN6ADDRSZ, data, 0, 0, ad);
9185b0945b5SGregory Neil Shapiro }
9195b0945b5SGregory Neil Shapiro # endif /* NETINET6 */
9205b0945b5SGregory Neil Shapiro
9215b0945b5SGregory Neil Shapiro if (rr_type == T_MX)
9225b0945b5SGregory Neil Shapiro {
9235b0945b5SGregory Neil Shapiro char *endptr;
9245b0945b5SGregory Neil Shapiro int pref;
9255b0945b5SGregory Neil Shapiro
9265b0945b5SGregory Neil Shapiro pref = (int) strtoul(token, &endptr, 10);
9275b0945b5SGregory Neil Shapiro if (endptr == NULL || *endptr != ':')
9285b0945b5SGregory Neil Shapiro goto error;
9295b0945b5SGregory Neil Shapiro token = endptr + 1;
9305b0945b5SGregory Neil Shapiro rlen = gen_dns_reply(answer, anslen, anspos,
9315b0945b5SGregory Neil Shapiro query, qtype, domain, C_IN, rr_type, ttl,
9325b0945b5SGregory Neil Shapiro strlen(token) + 1, token, 0, pref, ad);
9335b0945b5SGregory Neil Shapiro if (tTd(8, 50))
9342fb4f839SGregory Neil Shapiro sm_dprintf("dnscrtrr: mx=%s, pref=%d, rlen=%d\n",
9352fb4f839SGregory Neil Shapiro token, pref, rlen);
9365b0945b5SGregory Neil Shapiro }
9375b0945b5SGregory Neil Shapiro
9385b0945b5SGregory Neil Shapiro # ifdef T_TLSA
9395b0945b5SGregory Neil Shapiro if (rr_type == T_TLSA)
9405b0945b5SGregory Neil Shapiro rlen = gen_dns_reply(answer, anslen, anspos,
9415b0945b5SGregory Neil Shapiro query, qtype, domain, C_IN, rr_type, ttl,
9425b0945b5SGregory Neil Shapiro strlen(token) + 1, token, 0, 0, ad);
9435b0945b5SGregory Neil Shapiro # endif
9445b0945b5SGregory Neil Shapiro
9455b0945b5SGregory Neil Shapiro if (rr_type == T_CNAME)
9465b0945b5SGregory Neil Shapiro rlen = gen_dns_reply(answer, anslen, anspos,
9475b0945b5SGregory Neil Shapiro query, qtype, domain, C_IN, rr_type, ttl,
9485b0945b5SGregory Neil Shapiro strlen(token), token, 0, 0, ad);
9495b0945b5SGregory Neil Shapiro if (rlen < 0)
9505b0945b5SGregory Neil Shapiro goto error;
9515b0945b5SGregory Neil Shapiro if (rlen > 0)
9525b0945b5SGregory Neil Shapiro anspos = answer + rlen;
9535b0945b5SGregory Neil Shapiro }
9545b0945b5SGregory Neil Shapiro
9555b0945b5SGregory Neil Shapiro if (ad != 1)
9565b0945b5SGregory Neil Shapiro *adp = 0;
9575b0945b5SGregory Neil Shapiro
9585b0945b5SGregory Neil Shapiro return rlen;
9595b0945b5SGregory Neil Shapiro
9605b0945b5SGregory Neil Shapiro error:
9615b0945b5SGregory Neil Shapiro if (herr != NULL && 0 == *herr)
9625b0945b5SGregory Neil Shapiro *herr = NO_RECOVERY;
9635b0945b5SGregory Neil Shapiro return -1;
9645b0945b5SGregory Neil Shapiro }
9655b0945b5SGregory Neil Shapiro
9665b0945b5SGregory Neil Shapiro /*
9675b0945b5SGregory Neil Shapiro ** TSTDNS_SEARCH -- replacement for res_search() for testing
9685b0945b5SGregory Neil Shapiro **
9695b0945b5SGregory Neil Shapiro ** Parameters:
9705b0945b5SGregory Neil Shapiro ** domain -- query domain
9715b0945b5SGregory Neil Shapiro ** class -- class
9725b0945b5SGregory Neil Shapiro ** type -- resource record type
9735b0945b5SGregory Neil Shapiro ** answer -- buffer for RRs
9745b0945b5SGregory Neil Shapiro ** anslen -- size of answer
9755b0945b5SGregory Neil Shapiro **
9765b0945b5SGregory Neil Shapiro ** Returns:
9775b0945b5SGregory Neil Shapiro ** >0: length of data in answer
9785b0945b5SGregory Neil Shapiro ** <0: error, check h_errno
9795b0945b5SGregory Neil Shapiro */
9805b0945b5SGregory Neil Shapiro
9815b0945b5SGregory Neil Shapiro int
tstdns_search(domain,class,type,answer,anslen)9825b0945b5SGregory Neil Shapiro tstdns_search(domain, class, type, answer, anslen)
9835b0945b5SGregory Neil Shapiro const char *domain;
9845b0945b5SGregory Neil Shapiro int class;
9855b0945b5SGregory Neil Shapiro int type;
9865b0945b5SGregory Neil Shapiro unsigned char *answer;
9875b0945b5SGregory Neil Shapiro int anslen;
9885b0945b5SGregory Neil Shapiro {
9895b0945b5SGregory Neil Shapiro int rlen, ad, maprcode, cnt, flags, herr;
9905b0945b5SGregory Neil Shapiro bool found_cname;
9915b0945b5SGregory Neil Shapiro const char *query;
9925b0945b5SGregory Neil Shapiro char *p;
9935b0945b5SGregory Neil Shapiro const char *tag;
9945b0945b5SGregory Neil Shapiro char *av[2];
9955b0945b5SGregory Neil Shapiro STAB *map;
9962fb4f839SGregory Neil Shapiro # if _FFR_8BITENVADDR
9972fb4f839SGregory Neil Shapiro char qbuf[MAXNAME_I];
9982fb4f839SGregory Neil Shapiro char *qdomain;
9992fb4f839SGregory Neil Shapiro # else
10002fb4f839SGregory Neil Shapiro # define qdomain domain
10012fb4f839SGregory Neil Shapiro # endif
10022fb4f839SGregory Neil Shapiro char key[MAXNAME_I + 16];
10035b0945b5SGregory Neil Shapiro char rhs[MAXLINE];
10045b0945b5SGregory Neil Shapiro unsigned char *anspos;
10055b0945b5SGregory Neil Shapiro
10065b0945b5SGregory Neil Shapiro rlen = -1;
10075b0945b5SGregory Neil Shapiro herr = 0;
10085b0945b5SGregory Neil Shapiro if (class != C_IN)
10095b0945b5SGregory Neil Shapiro goto error;
10102fb4f839SGregory Neil Shapiro if (SM_IS_EMPTY(domain))
10115b0945b5SGregory Neil Shapiro goto error;
10125b0945b5SGregory Neil Shapiro tag = rr_type2tag(type);
10135b0945b5SGregory Neil Shapiro if (tag == NULL)
10145b0945b5SGregory Neil Shapiro goto error;
10155b0945b5SGregory Neil Shapiro maprcode = EX_OK;
10165b0945b5SGregory Neil Shapiro ad = -1;
10175b0945b5SGregory Neil Shapiro flags = 0;
10182fb4f839SGregory Neil Shapiro # if _FFR_8BITENVADDR
10192fb4f839SGregory Neil Shapiro if (tTd(8, 62))
10202fb4f839SGregory Neil Shapiro sm_dprintf("domain=%s\n", domain);
10212fb4f839SGregory Neil Shapiro (void) dequote_internal_chars((char *)domain, qbuf, sizeof(qbuf));
10222fb4f839SGregory Neil Shapiro query = qbuf;
10232fb4f839SGregory Neil Shapiro qdomain = qbuf;
10242fb4f839SGregory Neil Shapiro if (tTd(8, 63))
10252fb4f839SGregory Neil Shapiro sm_dprintf("qdomain=%s\n", qdomain);
10262fb4f839SGregory Neil Shapiro # else
10275b0945b5SGregory Neil Shapiro query = domain;
10282fb4f839SGregory Neil Shapiro # endif /* _FFR_8BITENVADDR */
10295b0945b5SGregory Neil Shapiro anspos = NULL;
10305b0945b5SGregory Neil Shapiro
10315b0945b5SGregory Neil Shapiro map = stab("access", ST_MAP, ST_FIND);
10325b0945b5SGregory Neil Shapiro if (NULL == map)
10335b0945b5SGregory Neil Shapiro {
10345b0945b5SGregory Neil Shapiro sm_dprintf("access map not found\n");
10355b0945b5SGregory Neil Shapiro goto error;
10365b0945b5SGregory Neil Shapiro }
10375b0945b5SGregory Neil Shapiro if (!bitset(MF_OPEN, map->s_map.map_mflags) &&
10385b0945b5SGregory Neil Shapiro !openmap(&(map->s_map)))
10395b0945b5SGregory Neil Shapiro {
10405b0945b5SGregory Neil Shapiro sm_dprintf("access map open failed\n");
10415b0945b5SGregory Neil Shapiro goto error;
10425b0945b5SGregory Neil Shapiro }
10435b0945b5SGregory Neil Shapiro
10445b0945b5SGregory Neil Shapiro /*
10455b0945b5SGregory Neil Shapiro ** Look up tag:domain, if not found and domain does not end with a dot
10465b0945b5SGregory Neil Shapiro ** (and the proper debug level is selected), also try with trailing dot.
10475b0945b5SGregory Neil Shapiro */
10485b0945b5SGregory Neil Shapiro
10495b0945b5SGregory Neil Shapiro #define SM_LOOKUP2(tag) \
10505b0945b5SGregory Neil Shapiro do { \
10515b0945b5SGregory Neil Shapiro int len; \
10525b0945b5SGregory Neil Shapiro \
10532fb4f839SGregory Neil Shapiro len = strlen(qdomain); \
10545b0945b5SGregory Neil Shapiro av[0] = key; \
10555b0945b5SGregory Neil Shapiro av[1] = NULL; \
10562fb4f839SGregory Neil Shapiro snprintf(key, sizeof(key), "%s:%s", tag, qdomain); \
10575b0945b5SGregory Neil Shapiro p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \
10585b0945b5SGregory Neil Shapiro &maprcode); \
10595b0945b5SGregory Neil Shapiro if (p != NULL) \
10605b0945b5SGregory Neil Shapiro break; \
10612fb4f839SGregory Neil Shapiro if (!tTd(8, 112) || (len > 0 && '.' == qdomain[len - 1])) \
10625b0945b5SGregory Neil Shapiro break; \
10632fb4f839SGregory Neil Shapiro snprintf(key, sizeof(key), "%s:%s.", tag, qdomain); \
10645b0945b5SGregory Neil Shapiro p = (*map->s_map.map_class->map_lookup)(&map->s_map, key, av, \
10655b0945b5SGregory Neil Shapiro &maprcode); \
10665b0945b5SGregory Neil Shapiro } while (0)
10675b0945b5SGregory Neil Shapiro
10685b0945b5SGregory Neil Shapiro cnt = 0;
10695b0945b5SGregory Neil Shapiro found_cname = false;
10705b0945b5SGregory Neil Shapiro while (cnt < 6)
10715b0945b5SGregory Neil Shapiro {
10725b0945b5SGregory Neil Shapiro char *last;
10735b0945b5SGregory Neil Shapiro
10745b0945b5SGregory Neil Shapiro /* Should this try with/without trailing dot? */
10755b0945b5SGregory Neil Shapiro SM_LOOKUP2(tag);
10765b0945b5SGregory Neil Shapiro if (p != NULL)
10775b0945b5SGregory Neil Shapiro {
10785b0945b5SGregory Neil Shapiro sm_dprintf("access map lookup key=%s, value=%s\n", key,
10795b0945b5SGregory Neil Shapiro p);
10805b0945b5SGregory Neil Shapiro break;
10815b0945b5SGregory Neil Shapiro }
10825b0945b5SGregory Neil Shapiro if (NULL == p && (flags & RR_NO_CNAME) == 0)
10835b0945b5SGregory Neil Shapiro {
10845b0945b5SGregory Neil Shapiro sm_dprintf("access map lookup failed key=%s, try cname\n",
10855b0945b5SGregory Neil Shapiro key);
10865b0945b5SGregory Neil Shapiro SM_LOOKUP2("cname");
10875b0945b5SGregory Neil Shapiro if (p != NULL)
10885b0945b5SGregory Neil Shapiro {
10895b0945b5SGregory Neil Shapiro sm_dprintf("cname lookup key=%s, value=%s, ad=%d\n",
10905b0945b5SGregory Neil Shapiro key, p, ad);
10912fb4f839SGregory Neil Shapiro rlen = dnscrtrr(qdomain, query, type, p, T_CNAME,
10925b0945b5SGregory Neil Shapiro flags, &herr, &ad, answer,
10935b0945b5SGregory Neil Shapiro anslen, anspos);
10945b0945b5SGregory Neil Shapiro if (rlen < 0)
10955b0945b5SGregory Neil Shapiro goto error;
10965b0945b5SGregory Neil Shapiro if (rlen > 0)
10975b0945b5SGregory Neil Shapiro anspos = answer + rlen;
10985b0945b5SGregory Neil Shapiro found_cname = true;
10995b0945b5SGregory Neil Shapiro }
11005b0945b5SGregory Neil Shapiro }
11015b0945b5SGregory Neil Shapiro if (NULL == p)
11025b0945b5SGregory Neil Shapiro break;
11035b0945b5SGregory Neil Shapiro
11045b0945b5SGregory Neil Shapiro (void) sm_strlcpy(rhs, p, sizeof(rhs));
11055b0945b5SGregory Neil Shapiro p = rhs;
11065b0945b5SGregory Neil Shapiro
11075b0945b5SGregory Neil Shapiro /* skip (leading) ad/ttl: look for last ' ' */
11085b0945b5SGregory Neil Shapiro if ((last = strrchr(p, ' ')) != NULL && last[1] != '\0')
11092fb4f839SGregory Neil Shapiro qdomain = last + 1;
11105b0945b5SGregory Neil Shapiro else
11112fb4f839SGregory Neil Shapiro qdomain = p;
11125b0945b5SGregory Neil Shapiro ++cnt;
11135b0945b5SGregory Neil Shapiro }
11145b0945b5SGregory Neil Shapiro if (NULL == p)
11155b0945b5SGregory Neil Shapiro {
11165b0945b5SGregory Neil Shapiro int t;
11175b0945b5SGregory Neil Shapiro char *tags[] = { "ipv4", "mx", "tlsa",
11185b0945b5SGregory Neil Shapiro # if NETINET6
11195b0945b5SGregory Neil Shapiro "ipv6",
11205b0945b5SGregory Neil Shapiro # endif
11215b0945b5SGregory Neil Shapiro NULL
11225b0945b5SGregory Neil Shapiro };
11235b0945b5SGregory Neil Shapiro
11245b0945b5SGregory Neil Shapiro for (t = 0; tags[t] != NULL; t++)
11255b0945b5SGregory Neil Shapiro {
11265b0945b5SGregory Neil Shapiro if (strcmp(tag, tags[t]) == 0)
11275b0945b5SGregory Neil Shapiro continue;
11285b0945b5SGregory Neil Shapiro SM_LOOKUP2(tags[t]);
11295b0945b5SGregory Neil Shapiro if (p != NULL)
11305b0945b5SGregory Neil Shapiro {
11315b0945b5SGregory Neil Shapiro sm_dprintf("access map lookup failed key=%s:%s, but found key=%s\n",
11322fb4f839SGregory Neil Shapiro tag, qdomain, key);
11335b0945b5SGregory Neil Shapiro herr = NO_DATA;
11345b0945b5SGregory Neil Shapiro goto error;
11355b0945b5SGregory Neil Shapiro }
11365b0945b5SGregory Neil Shapiro }
11375b0945b5SGregory Neil Shapiro sm_dprintf("access map lookup failed key=%s\n", key);
11385b0945b5SGregory Neil Shapiro herr = HOST_NOT_FOUND;
11395b0945b5SGregory Neil Shapiro goto error;
11405b0945b5SGregory Neil Shapiro }
11415b0945b5SGregory Neil Shapiro if (found_cname && (flags & RR_ONLY_CNAME) != 0)
11425b0945b5SGregory Neil Shapiro return rlen;
11432fb4f839SGregory Neil Shapiro rlen = dnscrtrr(qdomain, query, type, p, type, flags, &herr, &ad,
11445b0945b5SGregory Neil Shapiro answer, anslen, anspos);
11455b0945b5SGregory Neil Shapiro if (rlen < 0)
11465b0945b5SGregory Neil Shapiro goto error;
11475b0945b5SGregory Neil Shapiro return rlen;
11485b0945b5SGregory Neil Shapiro
11495b0945b5SGregory Neil Shapiro error:
11505b0945b5SGregory Neil Shapiro if (0 == herr)
11515b0945b5SGregory Neil Shapiro herr = NO_RECOVERY;
11525b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(herr);
11535b0945b5SGregory Neil Shapiro sm_dprintf("rlen=%d, herr=%d\n", rlen, herr);
11545b0945b5SGregory Neil Shapiro return -1;
11555b0945b5SGregory Neil Shapiro }
11565b0945b5SGregory Neil Shapiro
11575b0945b5SGregory Neil Shapiro /*
11585b0945b5SGregory Neil Shapiro ** TSTDNS_QUERYDOMAIN -- replacement for res_querydomain() for testing
11595b0945b5SGregory Neil Shapiro **
11605b0945b5SGregory Neil Shapiro ** Parameters:
11615b0945b5SGregory Neil Shapiro ** name -- query name
11625b0945b5SGregory Neil Shapiro ** domain -- query domain
11635b0945b5SGregory Neil Shapiro ** class -- class
11645b0945b5SGregory Neil Shapiro ** type -- resource record type
11655b0945b5SGregory Neil Shapiro ** answer -- buffer for RRs
11665b0945b5SGregory Neil Shapiro ** anslen -- size of answer
11675b0945b5SGregory Neil Shapiro **
11685b0945b5SGregory Neil Shapiro ** Returns:
11695b0945b5SGregory Neil Shapiro ** >0: length of data in answer
11705b0945b5SGregory Neil Shapiro ** <0: error, check h_errno
11715b0945b5SGregory Neil Shapiro */
11725b0945b5SGregory Neil Shapiro
11735b0945b5SGregory Neil Shapiro int
tstdns_querydomain(name,domain,class,type,answer,anslen)11745b0945b5SGregory Neil Shapiro tstdns_querydomain(name, domain, class, type, answer, anslen)
11755b0945b5SGregory Neil Shapiro const char *name;
11765b0945b5SGregory Neil Shapiro const char *domain;
11775b0945b5SGregory Neil Shapiro int class;
11785b0945b5SGregory Neil Shapiro int type;
11795b0945b5SGregory Neil Shapiro unsigned char *answer;
11805b0945b5SGregory Neil Shapiro int anslen;
11815b0945b5SGregory Neil Shapiro {
11822fb4f839SGregory Neil Shapiro char query[MAXNAME_I];
11835b0945b5SGregory Neil Shapiro int len;
11845b0945b5SGregory Neil Shapiro
11855b0945b5SGregory Neil Shapiro if (NULL == name)
11865b0945b5SGregory Neil Shapiro goto error;
11872fb4f839SGregory Neil Shapiro if (SM_IS_EMPTY(domain))
11885b0945b5SGregory Neil Shapiro return tstdns_search(name, class, type, answer, anslen);
11895b0945b5SGregory Neil Shapiro
11905b0945b5SGregory Neil Shapiro len = snprintf(query, sizeof(query), "%s.%s", name, domain);
11915b0945b5SGregory Neil Shapiro if (len >= (int)sizeof(query))
11925b0945b5SGregory Neil Shapiro goto error;
11935b0945b5SGregory Neil Shapiro return tstdns_search(query, class, type, answer, anslen);
11945b0945b5SGregory Neil Shapiro
11955b0945b5SGregory Neil Shapiro error:
11965b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(NO_RECOVERY);
11975b0945b5SGregory Neil Shapiro return -1;
11985b0945b5SGregory Neil Shapiro }
11995b0945b5SGregory Neil Shapiro
12005b0945b5SGregory Neil Shapiro # endif /* DNSSEC_TEST */
12015b0945b5SGregory Neil Shapiro
12025b0945b5SGregory Neil Shapiro /*
12035b0945b5SGregory Neil Shapiro ** DNS_LOOKUP_INT -- perform DNS lookup
120440266059SGregory Neil Shapiro **
120540266059SGregory Neil Shapiro ** Parameters:
120640266059SGregory Neil Shapiro ** domain -- name to look up
120740266059SGregory Neil Shapiro ** rr_class -- resource record class
120840266059SGregory Neil Shapiro ** rr_type -- resource record type
120940266059SGregory Neil Shapiro ** retrans -- retransmission timeout
121040266059SGregory Neil Shapiro ** retry -- number of retries
12115b0945b5SGregory Neil Shapiro ** options -- DNS resolver options
12125b0945b5SGregory Neil Shapiro ** flags -- currently only passed to parse_dns_reply()
12135b0945b5SGregory Neil Shapiro ** err -- (pointer to) errno (output if non-NULL)
12145b0945b5SGregory Neil Shapiro ** herr -- (pointer to) h_errno (output if non-NULL)
121540266059SGregory Neil Shapiro **
121640266059SGregory Neil Shapiro ** Returns:
121740266059SGregory Neil Shapiro ** result of lookup if succeeded.
121840266059SGregory Neil Shapiro ** NULL otherwise.
121940266059SGregory Neil Shapiro */
122040266059SGregory Neil Shapiro
122140266059SGregory Neil Shapiro DNS_REPLY_T *
dns_lookup_int(domain,rr_class,rr_type,retrans,retry,options,flags,err,herr)12225b0945b5SGregory Neil Shapiro dns_lookup_int(domain, rr_class, rr_type, retrans, retry, options, flags, err, herr)
122340266059SGregory Neil Shapiro const char *domain;
122440266059SGregory Neil Shapiro int rr_class;
122540266059SGregory Neil Shapiro int rr_type;
122640266059SGregory Neil Shapiro time_t retrans;
122740266059SGregory Neil Shapiro int retry;
12285b0945b5SGregory Neil Shapiro unsigned int options;
12295b0945b5SGregory Neil Shapiro unsigned int flags;
12305b0945b5SGregory Neil Shapiro int *err;
12315b0945b5SGregory Neil Shapiro int *herr;
123240266059SGregory Neil Shapiro {
123340266059SGregory Neil Shapiro int len;
123440266059SGregory Neil Shapiro unsigned long old_options = 0;
123540266059SGregory Neil Shapiro time_t save_retrans = 0;
123640266059SGregory Neil Shapiro int save_retry = 0;
12375b0945b5SGregory Neil Shapiro DNS_REPLY_T *dr = NULL;
12386f9c8e5bSGregory Neil Shapiro querybuf reply_buf;
12396f9c8e5bSGregory Neil Shapiro unsigned char *reply;
12405b0945b5SGregory Neil Shapiro int (*resfunc) __P((const char *, int, int, u_char *, int));
12416f9c8e5bSGregory Neil Shapiro
12425b0945b5SGregory Neil Shapiro # define SMRBSIZE ((int) sizeof(reply_buf))
12436f9c8e5bSGregory Neil Shapiro # ifndef IP_MAXPACKET
12446f9c8e5bSGregory Neil Shapiro # define IP_MAXPACKET 65535
12456f9c8e5bSGregory Neil Shapiro # endif
124640266059SGregory Neil Shapiro
12475b0945b5SGregory Neil Shapiro resfunc = res_search;
12485b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
12495b0945b5SGregory Neil Shapiro if (tTd(8, 110))
12505b0945b5SGregory Neil Shapiro resfunc = tstdns_search;
12515b0945b5SGregory Neil Shapiro # endif
12525b0945b5SGregory Neil Shapiro
12535b0945b5SGregory Neil Shapiro old_options = _res.options;
12545b0945b5SGregory Neil Shapiro _res.options |= options;
12555b0945b5SGregory Neil Shapiro if (err != NULL)
12565b0945b5SGregory Neil Shapiro *err = 0;
12575b0945b5SGregory Neil Shapiro if (herr != NULL)
12585b0945b5SGregory Neil Shapiro *herr = 0;
125940266059SGregory Neil Shapiro if (tTd(8, 16))
126040266059SGregory Neil Shapiro {
126140266059SGregory Neil Shapiro _res.options |= RES_DEBUG;
12625b0945b5SGregory Neil Shapiro sm_dprintf("dns_lookup_int(%s, %d, %s, %x)\n", domain,
12635b0945b5SGregory Neil Shapiro rr_class, dns_type_to_string(rr_type), options);
126440266059SGregory Neil Shapiro }
12655b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
12665b0945b5SGregory Neil Shapiro if (tTd(8, 15))
12675b0945b5SGregory Neil Shapiro sm_dprintf("NS=%s, port=%d\n",
12685b0945b5SGregory Neil Shapiro inet_ntoa(_res.nsaddr_list[0].sin_addr),
12695b0945b5SGregory Neil Shapiro ntohs(_res.nsaddr_list[0].sin_port));
12705b0945b5SGregory Neil Shapiro # endif
127140266059SGregory Neil Shapiro if (retrans > 0)
127240266059SGregory Neil Shapiro {
127340266059SGregory Neil Shapiro save_retrans = _res.retrans;
127440266059SGregory Neil Shapiro _res.retrans = retrans;
127540266059SGregory Neil Shapiro }
127640266059SGregory Neil Shapiro if (retry > 0)
127740266059SGregory Neil Shapiro {
127840266059SGregory Neil Shapiro save_retry = _res.retry;
127940266059SGregory Neil Shapiro _res.retry = retry;
128040266059SGregory Neil Shapiro }
128140266059SGregory Neil Shapiro errno = 0;
128240266059SGregory Neil Shapiro SM_SET_H_ERRNO(0);
12836f9c8e5bSGregory Neil Shapiro reply = (unsigned char *)&reply_buf;
12845b0945b5SGregory Neil Shapiro len = (*resfunc)(domain, rr_class, rr_type, reply, SMRBSIZE);
12856f9c8e5bSGregory Neil Shapiro if (len >= SMRBSIZE)
12866f9c8e5bSGregory Neil Shapiro {
12876f9c8e5bSGregory Neil Shapiro if (len >= IP_MAXPACKET)
12886f9c8e5bSGregory Neil Shapiro {
12896f9c8e5bSGregory Neil Shapiro if (tTd(8, 4))
12906f9c8e5bSGregory Neil Shapiro sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response too long\n",
12915b0945b5SGregory Neil Shapiro domain, len, SMRBSIZE, IP_MAXPACKET);
12926f9c8e5bSGregory Neil Shapiro }
12936f9c8e5bSGregory Neil Shapiro else
12946f9c8e5bSGregory Neil Shapiro {
12956f9c8e5bSGregory Neil Shapiro if (tTd(8, 6))
12966f9c8e5bSGregory Neil Shapiro sm_dprintf("dns_lookup: domain=%s, length=%d, default_size=%d, max=%d, status=response longer than default size, resizing\n",
12975b0945b5SGregory Neil Shapiro domain, len, SMRBSIZE, IP_MAXPACKET);
12986f9c8e5bSGregory Neil Shapiro reply = (unsigned char *)sm_malloc(IP_MAXPACKET);
12996f9c8e5bSGregory Neil Shapiro if (reply == NULL)
13006f9c8e5bSGregory Neil Shapiro SM_SET_H_ERRNO(TRY_AGAIN);
13016f9c8e5bSGregory Neil Shapiro else
13025b0945b5SGregory Neil Shapiro {
13035b0945b5SGregory Neil Shapiro SM_SET_H_ERRNO(0);
13045b0945b5SGregory Neil Shapiro len = (*resfunc)(domain, rr_class, rr_type,
13056f9c8e5bSGregory Neil Shapiro reply, IP_MAXPACKET);
13066f9c8e5bSGregory Neil Shapiro }
13076f9c8e5bSGregory Neil Shapiro }
13085b0945b5SGregory Neil Shapiro }
13095b0945b5SGregory Neil Shapiro _res.options = old_options;
13105b0945b5SGregory Neil Shapiro if (len < 0)
13115b0945b5SGregory Neil Shapiro {
13125b0945b5SGregory Neil Shapiro if (err != NULL)
13135b0945b5SGregory Neil Shapiro *err = errno;
13145b0945b5SGregory Neil Shapiro if (herr != NULL)
13155b0945b5SGregory Neil Shapiro *herr = h_errno;
131640266059SGregory Neil Shapiro if (tTd(8, 16))
131740266059SGregory Neil Shapiro {
13185b0945b5SGregory Neil Shapiro sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d, errno=%d, h_errno=%d"
13195b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
13205b0945b5SGregory Neil Shapiro " (%s)"
13215b0945b5SGregory Neil Shapiro # endif
13225b0945b5SGregory Neil Shapiro "\n",
13235b0945b5SGregory Neil Shapiro domain, rr_class, dns_type_to_string(rr_type),
13245b0945b5SGregory Neil Shapiro options, len, errno, h_errno
13255b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
13265b0945b5SGregory Neil Shapiro , herrno2txt(h_errno)
13275b0945b5SGregory Neil Shapiro # endif
13285b0945b5SGregory Neil Shapiro );
13295b0945b5SGregory Neil Shapiro }
13305b0945b5SGregory Neil Shapiro }
13315b0945b5SGregory Neil Shapiro else if (tTd(8, 16))
13325b0945b5SGregory Neil Shapiro {
13335b0945b5SGregory Neil Shapiro sm_dprintf("dns_lookup_int(%s, %d, %s, %x)=%d\n",
13345b0945b5SGregory Neil Shapiro domain, rr_class, dns_type_to_string(rr_type),
13355b0945b5SGregory Neil Shapiro options, len);
133640266059SGregory Neil Shapiro }
13376f9c8e5bSGregory Neil Shapiro if (len >= 0 && len < IP_MAXPACKET && reply != NULL)
13385b0945b5SGregory Neil Shapiro dr = parse_dns_reply(reply, len, flags);
13396f9c8e5bSGregory Neil Shapiro if (reply != (unsigned char *)&reply_buf && reply != NULL)
13406f9c8e5bSGregory Neil Shapiro {
13416f9c8e5bSGregory Neil Shapiro sm_free(reply);
13426f9c8e5bSGregory Neil Shapiro reply = NULL;
13436f9c8e5bSGregory Neil Shapiro }
134440266059SGregory Neil Shapiro if (retrans > 0)
134540266059SGregory Neil Shapiro _res.retrans = save_retrans;
134640266059SGregory Neil Shapiro if (retry > 0)
134740266059SGregory Neil Shapiro _res.retry = save_retry;
13485b0945b5SGregory Neil Shapiro return dr;
134940266059SGregory Neil Shapiro }
135040266059SGregory Neil Shapiro
13515b0945b5SGregory Neil Shapiro /*
13525b0945b5SGregory Neil Shapiro ** DNS_LOOKUP_MAP -- perform DNS map lookup
13535b0945b5SGregory Neil Shapiro **
13545b0945b5SGregory Neil Shapiro ** Parameters:
13555b0945b5SGregory Neil Shapiro ** domain -- name to look up
13565b0945b5SGregory Neil Shapiro ** rr_class -- resource record class
13575b0945b5SGregory Neil Shapiro ** rr_type -- resource record type
13585b0945b5SGregory Neil Shapiro ** retrans -- retransmission timeout
13595b0945b5SGregory Neil Shapiro ** retry -- number of retries
13605b0945b5SGregory Neil Shapiro ** options -- DNS resolver options
13615b0945b5SGregory Neil Shapiro **
13625b0945b5SGregory Neil Shapiro ** Returns:
13635b0945b5SGregory Neil Shapiro ** result of lookup if succeeded.
13645b0945b5SGregory Neil Shapiro ** NULL otherwise.
13655b0945b5SGregory Neil Shapiro */
13665b0945b5SGregory Neil Shapiro
136740266059SGregory Neil Shapiro DNS_REPLY_T *
dns_lookup_map(domain,rr_class,rr_type,retrans,retry,options)13685b0945b5SGregory Neil Shapiro dns_lookup_map(domain, rr_class, rr_type, retrans, retry, options)
136940266059SGregory Neil Shapiro const char *domain;
13705b0945b5SGregory Neil Shapiro int rr_class;
13715b0945b5SGregory Neil Shapiro int rr_type;
137240266059SGregory Neil Shapiro time_t retrans;
137340266059SGregory Neil Shapiro int retry;
13745b0945b5SGregory Neil Shapiro unsigned int options;
137540266059SGregory Neil Shapiro {
13765b0945b5SGregory Neil Shapiro return dns_lookup_int(domain, rr_class, rr_type, retrans, retry,
13775b0945b5SGregory Neil Shapiro options, RR_AS_TEXT, NULL, NULL);
13785b0945b5SGregory Neil Shapiro }
137940266059SGregory Neil Shapiro
13805b0945b5SGregory Neil Shapiro # if DANE
13815b0945b5SGregory Neil Shapiro /*
13825b0945b5SGregory Neil Shapiro ** DNS2HE -- convert DNS_REPLY_T list to hostent struct
13835b0945b5SGregory Neil Shapiro **
13845b0945b5SGregory Neil Shapiro ** Parameters:
13855b0945b5SGregory Neil Shapiro ** dr -- DNS lookup result
13865b0945b5SGregory Neil Shapiro ** family -- address family
13875b0945b5SGregory Neil Shapiro **
13885b0945b5SGregory Neil Shapiro ** Returns:
13895b0945b5SGregory Neil Shapiro ** hostent struct if succeeded.
13905b0945b5SGregory Neil Shapiro ** NULL otherwise.
13915b0945b5SGregory Neil Shapiro **
13925b0945b5SGregory Neil Shapiro ** Note:
13935b0945b5SGregory Neil Shapiro ** this returns a pointer to a static struct!
13945b0945b5SGregory Neil Shapiro */
13955b0945b5SGregory Neil Shapiro
13965b0945b5SGregory Neil Shapiro struct hostent *
dns2he(dr,family)13975b0945b5SGregory Neil Shapiro dns2he(dr, family)
13985b0945b5SGregory Neil Shapiro DNS_REPLY_T *dr;
13995b0945b5SGregory Neil Shapiro int family;
140040266059SGregory Neil Shapiro {
14015b0945b5SGregory Neil Shapiro # define SM_MAX_ADDRS 256
14025b0945b5SGregory Neil Shapiro static struct hostent he;
14035b0945b5SGregory Neil Shapiro static char *he_aliases[1];
14045b0945b5SGregory Neil Shapiro static char *he_addr_list[SM_MAX_ADDRS];
14055b0945b5SGregory Neil Shapiro # ifdef IN6ADDRSZ
14065b0945b5SGregory Neil Shapiro # define IN_ADDRSZ IN6ADDRSZ
14075b0945b5SGregory Neil Shapiro # else
14085b0945b5SGregory Neil Shapiro # define IN_ADDRSZ INADDRSZ
14095b0945b5SGregory Neil Shapiro # endif
14105b0945b5SGregory Neil Shapiro static char he_addrs[SM_MAX_ADDRS * IN_ADDRSZ];
14112fb4f839SGregory Neil Shapiro static char he_name[MAXNAME_I];
14125b0945b5SGregory Neil Shapiro static bool he_init = false;
14135b0945b5SGregory Neil Shapiro struct hostent *h;
14145b0945b5SGregory Neil Shapiro int i;
14155b0945b5SGregory Neil Shapiro size_t sz;
14165b0945b5SGregory Neil Shapiro # if NETINET6 && DNSSEC_TEST
14175b0945b5SGregory Neil Shapiro struct in6_addr ia6;
14185b0945b5SGregory Neil Shapiro char buf6[INET6_ADDRSTRLEN];
14195b0945b5SGregory Neil Shapiro # endif
14205b0945b5SGregory Neil Shapiro RESOURCE_RECORD_T *rr;
14215b0945b5SGregory Neil Shapiro
14225b0945b5SGregory Neil Shapiro if (dr == NULL)
142340266059SGregory Neil Shapiro return NULL;
14245b0945b5SGregory Neil Shapiro
14255b0945b5SGregory Neil Shapiro h = &he;
14265b0945b5SGregory Neil Shapiro if (!he_init)
14275b0945b5SGregory Neil Shapiro {
14285b0945b5SGregory Neil Shapiro he_aliases[0] = NULL;
14295b0945b5SGregory Neil Shapiro he.h_aliases = he_aliases;
14305b0945b5SGregory Neil Shapiro he.h_addr_list = he_addr_list;
14315b0945b5SGregory Neil Shapiro he.h_name = he_name;
14325b0945b5SGregory Neil Shapiro he_init = true;
143340266059SGregory Neil Shapiro }
14345b0945b5SGregory Neil Shapiro h->h_addrtype = family;
14355b0945b5SGregory Neil Shapiro
14365b0945b5SGregory Neil Shapiro if (tTd(8, 17))
14375b0945b5SGregory Neil Shapiro sm_dprintf("dns2he: ad=%d\n", dr->dns_r_h.ad);
14385b0945b5SGregory Neil Shapiro
14395b0945b5SGregory Neil Shapiro /* do we want/need to copy the name? */
14405b0945b5SGregory Neil Shapiro rr = dr->dns_r_head;
14415b0945b5SGregory Neil Shapiro if (rr != NULL && rr->rr_domain != NULL)
14425b0945b5SGregory Neil Shapiro sm_strlcpy(h->h_name, rr->rr_domain, sizeof(he_name));
14435b0945b5SGregory Neil Shapiro else
14445b0945b5SGregory Neil Shapiro h->h_name[0] = '\0';
14455b0945b5SGregory Neil Shapiro
14465b0945b5SGregory Neil Shapiro sz = 0;
14475b0945b5SGregory Neil Shapiro # if NETINET
14485b0945b5SGregory Neil Shapiro if (family == AF_INET)
14495b0945b5SGregory Neil Shapiro sz = INADDRSZ;
14505b0945b5SGregory Neil Shapiro # endif
14515b0945b5SGregory Neil Shapiro # if NETINET6
14525b0945b5SGregory Neil Shapiro if (family == AF_INET6)
14535b0945b5SGregory Neil Shapiro sz = IN6ADDRSZ;
14545b0945b5SGregory Neil Shapiro # endif
14555b0945b5SGregory Neil Shapiro if (sz == 0)
14565b0945b5SGregory Neil Shapiro return NULL;
14575b0945b5SGregory Neil Shapiro h->h_length = sz;
14585b0945b5SGregory Neil Shapiro
14595b0945b5SGregory Neil Shapiro for (rr = dr->dns_r_head, i = 0; rr != NULL && i < SM_MAX_ADDRS - 1;
14605b0945b5SGregory Neil Shapiro rr = rr->rr_next)
14615b0945b5SGregory Neil Shapiro {
14625b0945b5SGregory Neil Shapiro h->h_addr_list[i] = he_addrs + i * h->h_length;
14635b0945b5SGregory Neil Shapiro switch (rr->rr_type)
14645b0945b5SGregory Neil Shapiro {
14655b0945b5SGregory Neil Shapiro # if NETINET
14665b0945b5SGregory Neil Shapiro case T_A:
14675b0945b5SGregory Neil Shapiro if (family != AF_INET)
14685b0945b5SGregory Neil Shapiro continue;
14695b0945b5SGregory Neil Shapiro memmove(h->h_addr_list[i], rr->rr_u.rr_a, INADDRSZ);
14705b0945b5SGregory Neil Shapiro ++i;
14715b0945b5SGregory Neil Shapiro break;
14725b0945b5SGregory Neil Shapiro # endif /* NETINET */
14735b0945b5SGregory Neil Shapiro # if NETINET6
14745b0945b5SGregory Neil Shapiro case T_AAAA:
14755b0945b5SGregory Neil Shapiro if (family != AF_INET6)
14765b0945b5SGregory Neil Shapiro continue;
14775b0945b5SGregory Neil Shapiro memmove(h->h_addr_list[i], rr->rr_u.rr_aaaa, IN6ADDRSZ);
14785b0945b5SGregory Neil Shapiro ++i;
14795b0945b5SGregory Neil Shapiro break;
14805b0945b5SGregory Neil Shapiro # endif /* NETINET6 */
14815b0945b5SGregory Neil Shapiro case T_CNAME:
14825b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
14835b0945b5SGregory Neil Shapiro if (tTd(8, 16))
14845b0945b5SGregory Neil Shapiro sm_dprintf("dns2he: cname: %s ttl=%d\n",
14855b0945b5SGregory Neil Shapiro rr->rr_u.rr_txt, rr->rr_ttl);
14865b0945b5SGregory Neil Shapiro # endif
14875b0945b5SGregory Neil Shapiro break;
14885b0945b5SGregory Neil Shapiro case T_MX:
14895b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
14905b0945b5SGregory Neil Shapiro if (tTd(8, 16))
14915b0945b5SGregory Neil Shapiro sm_dprintf("dns2he: mx: %d %s ttl=%d\n",
14925b0945b5SGregory Neil Shapiro rr->rr_u.rr_mx->mx_r_preference,
14935b0945b5SGregory Neil Shapiro rr->rr_u.rr_mx->mx_r_domain,
14945b0945b5SGregory Neil Shapiro rr->rr_ttl);
14955b0945b5SGregory Neil Shapiro # endif
14965b0945b5SGregory Neil Shapiro break;
14975b0945b5SGregory Neil Shapiro
14985b0945b5SGregory Neil Shapiro # if defined(T_TLSA)
14995b0945b5SGregory Neil Shapiro case T_TLSA:
15005b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
15015b0945b5SGregory Neil Shapiro if (tTd(8, 16))
15025b0945b5SGregory Neil Shapiro {
15035b0945b5SGregory Neil Shapiro char *tlsa;
15045b0945b5SGregory Neil Shapiro int len;
15055b0945b5SGregory Neil Shapiro
15065b0945b5SGregory Neil Shapiro len = bin2hex(&tlsa, rr->rr_u.rr_data,
15075b0945b5SGregory Neil Shapiro rr->rr_size, 4);
15085b0945b5SGregory Neil Shapiro if (len > 0)
15095b0945b5SGregory Neil Shapiro sm_dprintf("dns2he: tlsa: %s ttl=%d\n",
15105b0945b5SGregory Neil Shapiro tlsa, rr->rr_ttl);
151140266059SGregory Neil Shapiro }
15125b0945b5SGregory Neil Shapiro # endif
15135b0945b5SGregory Neil Shapiro break;
15145b0945b5SGregory Neil Shapiro # endif /* T_TLSA */
15155b0945b5SGregory Neil Shapiro }
15165b0945b5SGregory Neil Shapiro }
15175b0945b5SGregory Neil Shapiro
15185b0945b5SGregory Neil Shapiro /* complain if list is too long! */
15195b0945b5SGregory Neil Shapiro SM_ASSERT(i < SM_MAX_ADDRS);
15205b0945b5SGregory Neil Shapiro h->h_addr_list[i] = NULL;
15215b0945b5SGregory Neil Shapiro
15225b0945b5SGregory Neil Shapiro # if DNSSEC_TEST
15235b0945b5SGregory Neil Shapiro if (tTd(8, 16))
15245b0945b5SGregory Neil Shapiro {
15252fb4f839SGregory Neil Shapiro struct in_addr ia;
15262fb4f839SGregory Neil Shapiro
15275b0945b5SGregory Neil Shapiro for (i = 0; h->h_addr_list[i] != NULL && i < SM_MAX_ADDRS; i++)
15285b0945b5SGregory Neil Shapiro {
15295b0945b5SGregory Neil Shapiro char *addr;
15305b0945b5SGregory Neil Shapiro
15315b0945b5SGregory Neil Shapiro addr = NULL;
15325b0945b5SGregory Neil Shapiro # if NETINET6
15335b0945b5SGregory Neil Shapiro if (h->h_addrtype == AF_INET6)
15345b0945b5SGregory Neil Shapiro {
15355b0945b5SGregory Neil Shapiro memmove(&ia6, h->h_addr_list[i], IN6ADDRSZ);
15365b0945b5SGregory Neil Shapiro addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
15375b0945b5SGregory Neil Shapiro }
15385b0945b5SGregory Neil Shapiro else
15395b0945b5SGregory Neil Shapiro # endif /* NETINET6 */
15405b0945b5SGregory Neil Shapiro /* "else" in #if code above */
15415b0945b5SGregory Neil Shapiro {
15425b0945b5SGregory Neil Shapiro memmove(&ia, h->h_addr_list[i], INADDRSZ);
15435b0945b5SGregory Neil Shapiro addr = (char *) inet_ntoa(ia);
15445b0945b5SGregory Neil Shapiro }
15455b0945b5SGregory Neil Shapiro if (addr != NULL)
15465b0945b5SGregory Neil Shapiro sm_dprintf("dns2he: addr[%d]: %s\n", i, addr);
15475b0945b5SGregory Neil Shapiro }
15485b0945b5SGregory Neil Shapiro }
15495b0945b5SGregory Neil Shapiro # endif /* DNSSEC_TEST */
15505b0945b5SGregory Neil Shapiro return h;
15515b0945b5SGregory Neil Shapiro }
15525b0945b5SGregory Neil Shapiro # endif /* DANE */
15535b0945b5SGregory Neil Shapiro # endif /* DNSMAP || DANE */
1554*d39bd2c1SGregory Neil Shapiro
1555*d39bd2c1SGregory Neil Shapiro # if DNSSEC_TEST || _FFR_NAMESERVER
1556*d39bd2c1SGregory Neil Shapiro /*
1557*d39bd2c1SGregory Neil Shapiro ** DNS_ADDNS -- add one NS in resolver context
1558*d39bd2c1SGregory Neil Shapiro **
1559*d39bd2c1SGregory Neil Shapiro ** Parameters:
1560*d39bd2c1SGregory Neil Shapiro ** ns -- (IPv4 address of) nameserver
1561*d39bd2c1SGregory Neil Shapiro ** port -- nameserver port (host order)
1562*d39bd2c1SGregory Neil Shapiro **
1563*d39bd2c1SGregory Neil Shapiro ** Returns:
1564*d39bd2c1SGregory Neil Shapiro ** None.
1565*d39bd2c1SGregory Neil Shapiro */
1566*d39bd2c1SGregory Neil Shapiro
1567*d39bd2c1SGregory Neil Shapiro static void dns_addns __P((struct in_addr *, unsigned int));
1568*d39bd2c1SGregory Neil Shapiro static int nsidx = 0;
1569*d39bd2c1SGregory Neil Shapiro #ifndef MAXNS
1570*d39bd2c1SGregory Neil Shapiro # define MAXNS 3
1571*d39bd2c1SGregory Neil Shapiro #endif
1572*d39bd2c1SGregory Neil Shapiro static void
dns_addns(ns,port)1573*d39bd2c1SGregory Neil Shapiro dns_addns(ns, port)
1574*d39bd2c1SGregory Neil Shapiro struct in_addr *ns;
1575*d39bd2c1SGregory Neil Shapiro unsigned int port;
1576*d39bd2c1SGregory Neil Shapiro {
1577*d39bd2c1SGregory Neil Shapiro if (nsidx >= MAXNS)
1578*d39bd2c1SGregory Neil Shapiro syserr("too many NameServers defined (%d max)", MAXNS);
1579*d39bd2c1SGregory Neil Shapiro _res.nsaddr_list[nsidx].sin_family = AF_INET;
1580*d39bd2c1SGregory Neil Shapiro _res.nsaddr_list[nsidx].sin_addr = *ns;
1581*d39bd2c1SGregory Neil Shapiro if (port != 0)
1582*d39bd2c1SGregory Neil Shapiro _res.nsaddr_list[nsidx].sin_port = htons(port);
1583*d39bd2c1SGregory Neil Shapiro _res.nscount = ++nsidx;
1584*d39bd2c1SGregory Neil Shapiro if (tTd(8, 61))
1585*d39bd2c1SGregory Neil Shapiro sm_dprintf("dns_addns: nsidx=%d, ns=%s:%u\n",
1586*d39bd2c1SGregory Neil Shapiro nsidx - 1, inet_ntoa(*ns), port);
1587*d39bd2c1SGregory Neil Shapiro }
1588*d39bd2c1SGregory Neil Shapiro
1589*d39bd2c1SGregory Neil Shapiro /*
1590*d39bd2c1SGregory Neil Shapiro ** NSPORTIP -- parse port@IPv4 and set NS accordingly
1591*d39bd2c1SGregory Neil Shapiro **
1592*d39bd2c1SGregory Neil Shapiro ** Parameters:
1593*d39bd2c1SGregory Neil Shapiro ** p -- port@IPv4
1594*d39bd2c1SGregory Neil Shapiro **
1595*d39bd2c1SGregory Neil Shapiro ** Returns:
1596*d39bd2c1SGregory Neil Shapiro ** <0: error
1597*d39bd2c1SGregory Neil Shapiro ** >=0: ok
1598*d39bd2c1SGregory Neil Shapiro **
1599*d39bd2c1SGregory Neil Shapiro ** Side Effects:
1600*d39bd2c1SGregory Neil Shapiro ** sets NS for DNS lookups
1601*d39bd2c1SGregory Neil Shapiro */
1602*d39bd2c1SGregory Neil Shapiro
1603*d39bd2c1SGregory Neil Shapiro /*
1604*d39bd2c1SGregory Neil Shapiro ** There should be a generic function for this...
1605*d39bd2c1SGregory Neil Shapiro ** milter_open(), socket_map_open(), others?
1606*d39bd2c1SGregory Neil Shapiro */
1607*d39bd2c1SGregory Neil Shapiro
1608*d39bd2c1SGregory Neil Shapiro int
nsportip(p)1609*d39bd2c1SGregory Neil Shapiro nsportip(p)
1610*d39bd2c1SGregory Neil Shapiro char *p;
1611*d39bd2c1SGregory Neil Shapiro {
1612*d39bd2c1SGregory Neil Shapiro char *h;
1613*d39bd2c1SGregory Neil Shapiro int r;
1614*d39bd2c1SGregory Neil Shapiro unsigned short port;
1615*d39bd2c1SGregory Neil Shapiro struct in_addr nsip;
1616*d39bd2c1SGregory Neil Shapiro
1617*d39bd2c1SGregory Neil Shapiro if (SM_IS_EMPTY(p))
1618*d39bd2c1SGregory Neil Shapiro return -1;
1619*d39bd2c1SGregory Neil Shapiro
1620*d39bd2c1SGregory Neil Shapiro port = 0;
1621*d39bd2c1SGregory Neil Shapiro while (SM_ISSPACE(*p))
1622*d39bd2c1SGregory Neil Shapiro p++;
1623*d39bd2c1SGregory Neil Shapiro if (*p == '\0')
1624*d39bd2c1SGregory Neil Shapiro return -1;
1625*d39bd2c1SGregory Neil Shapiro h = strchr(p, '@');
1626*d39bd2c1SGregory Neil Shapiro if (h != NULL)
1627*d39bd2c1SGregory Neil Shapiro {
1628*d39bd2c1SGregory Neil Shapiro *h = '\0';
1629*d39bd2c1SGregory Neil Shapiro if (isascii(*p) && isdigit(*p))
1630*d39bd2c1SGregory Neil Shapiro port = atoi(p);
1631*d39bd2c1SGregory Neil Shapiro *h = '@';
1632*d39bd2c1SGregory Neil Shapiro p = h + 1;
1633*d39bd2c1SGregory Neil Shapiro }
1634*d39bd2c1SGregory Neil Shapiro h = strchr(p, ' ');
1635*d39bd2c1SGregory Neil Shapiro if (h != NULL)
1636*d39bd2c1SGregory Neil Shapiro *h = '\0';
1637*d39bd2c1SGregory Neil Shapiro r = inet_pton(AF_INET, p, &nsip);
1638*d39bd2c1SGregory Neil Shapiro if (r > 0)
1639*d39bd2c1SGregory Neil Shapiro {
1640*d39bd2c1SGregory Neil Shapiro if ((_res.options & RES_INIT) == 0)
1641*d39bd2c1SGregory Neil Shapiro (void) res_init();
1642*d39bd2c1SGregory Neil Shapiro dns_addns(&nsip, port);
1643*d39bd2c1SGregory Neil Shapiro }
1644*d39bd2c1SGregory Neil Shapiro if (h != NULL)
1645*d39bd2c1SGregory Neil Shapiro *h = ' ';
1646*d39bd2c1SGregory Neil Shapiro return r > 0 ? 0 : -1;
1647*d39bd2c1SGregory Neil Shapiro }
1648*d39bd2c1SGregory Neil Shapiro # endif /* DNSSEC_TEST || _FFR_NAMESERVER */
1649*d39bd2c1SGregory Neil Shapiro #endif /* NAMED_BIND */
1650