diff options
Diffstat (limited to 'usr.sbin/smtpd/dns.c')
-rw-r--r-- | usr.sbin/smtpd/dns.c | 115 |
1 files changed, 48 insertions, 67 deletions
diff --git a/usr.sbin/smtpd/dns.c b/usr.sbin/smtpd/dns.c index 85e530f0822..f2abc42272d 100644 --- a/usr.sbin/smtpd/dns.c +++ b/usr.sbin/smtpd/dns.c @@ -1,4 +1,4 @@ -/* $OpenBSD: dns.c,v 1.48 2012/04/14 13:31:46 eric Exp $ */ +/* $OpenBSD: dns.c,v 1.49 2012/07/09 12:16:24 eric Exp $ */ /* * Copyright (c) 2008 Gilles Chehade <gilles@openbsd.org> @@ -26,6 +26,7 @@ #include <netinet/in.h> #include <arpa/inet.h> +#include <arpa/nameser.h> #include <event.h> #include <imsg.h> @@ -34,8 +35,7 @@ #include <string.h> #include "asr.h" -#include "dnsdefs.h" -#include "dnsutil.h" +#include "asr_private.h" #include "smtpd.h" #include "log.h" @@ -50,7 +50,7 @@ struct dnssession { u_int64_t id; struct dns query; struct event ev; - struct asr_query *aq; + struct async *as; struct mx mxarray[MAX_MX_COUNT]; size_t mxarraysz; size_t mxcurrent; @@ -67,7 +67,7 @@ SPLAY_PROTOTYPE(dnstree, dnssession, nodes, dnssession_cmp); static struct dnssession *dnssession_init(struct dns *); static void dnssession_destroy(struct dnssession *); static void dnssession_mx_insert(struct dnssession *, const char *, int); -static void dns_asr_event_set(struct dnssession *, struct asr_result *); +static void dns_asr_event_set(struct dnssession *, struct async_res *); static void dns_asr_handler(int, short, void *); static int dns_asr_error(int); static void dns_asr_dispatch_host(struct dnssession *); @@ -75,7 +75,7 @@ static void dns_asr_dispatch_mx(struct dnssession *); static void dns_asr_dispatch_cname(struct dnssession *); static void dns_reply(struct dns *, int); -struct asr *asr = NULL; +#define print_dname(a,b,c) asr_strdname(a, b, c) /* * User interface. @@ -128,11 +128,6 @@ dns_async(struct imsgev *asker, int type, struct dns *query) { struct dnssession *s; - if (asr == NULL && (asr = asr_resolver(NULL)) == NULL) { - log_warnx("dns_async: cannot create resolver"); - goto noasr; - } - query->type = type; query->asker = asker; s = dnssession_init(query); @@ -151,13 +146,15 @@ dns_async(struct imsgev *asker, int type, struct dns *query) } dnssession_mx_insert(s, query->host, 0); stat_increment(STATS_LKA_SESSION_HOST); + log_debug("dns: ready?"); dns_asr_dispatch_host(s); return; case IMSG_DNS_PTR: - s->aq = asr_query_cname(asr, (struct sockaddr*)&query->ss, - query->ss.ss_len); + s->as = getnameinfo_async((struct sockaddr*)&query->ss, + query->ss.ss_len, + s->query.host, sizeof(s->query.host), NULL, 0, 0, NULL); stat_increment(STATS_LKA_SESSION_CNAME); - if (s->aq == NULL) { + if (s->as == NULL) { log_debug("dns_async: asr_query_cname error"); break; } @@ -165,9 +162,9 @@ dns_async(struct imsgev *asker, int type, struct dns *query) return; case IMSG_DNS_MX: log_debug("dns: lookup mx \"%s\"", query->host); - s->aq = asr_query_dns(asr, T_MX, C_IN, query->host, 0); + s->as = res_query_async(query->host, C_IN, T_MX, NULL, 0, NULL); stat_increment(STATS_LKA_SESSION_MX); - if (s->aq == NULL) { + if (s->as == NULL) { log_debug("dns_async: asr_query_dns error"); break; } @@ -180,9 +177,6 @@ dns_async(struct imsgev *asker, int type, struct dns *query) stat_increment(STATS_LKA_FAILURE); dnssession_destroy(s); -noasr: - query->error = DNS_RETRY; - dns_reply(query, type != IMSG_DNS_PTR ? IMSG_DNS_HOST_END : type); } static void @@ -192,13 +186,13 @@ dns_reply(struct dns *query, int type) } static void -dns_asr_event_set(struct dnssession *s, struct asr_result *ar) +dns_asr_event_set(struct dnssession *s, struct async_res *ar) { struct timeval tv = { 0, 0 }; tv.tv_usec = ar->ar_timeout * 1000; event_set(&s->ev, ar->ar_fd, - ar->ar_cond == ASR_READ ? EV_READ : EV_WRITE, dns_asr_handler, s); + ar->ar_cond == ASYNC_READ ? EV_READ : EV_WRITE, dns_asr_handler, s); event_add(&s->ev, &tv); } @@ -226,10 +220,10 @@ static int dns_asr_error(int ar_err) { switch (ar_err) { - case ASR_OK: + case 0: return DNS_OK; - case EASR_FAMILY: - case EASR_NAME: + case NO_DATA: + case NO_RECOVERY: stat_increment(STATS_LKA_FAILURE); return DNS_EINVAL; default: @@ -241,22 +235,24 @@ static void dns_asr_dispatch_mx(struct dnssession *s) { struct dns *query = &s->query; - struct asr_result ar; + struct async_res ar; struct packed pack; struct header h; struct query q; struct rr rr; char buf[512]; - if (asr_run(s->aq, &ar) == ASR_COND) { + if (async_run(s->as, &ar) == ASYNC_COND) { dns_asr_event_set(s, &ar); return; } - if (ar.ar_err) { - query->error = dns_asr_error(ar.ar_err); + if (ar.ar_errno || ar.ar_h_errno || ar.ar_rcode == NXDOMAIN) { + query->error = ar.ar_rcode == NXDOMAIN ? \ + DNS_ENONAME : dns_asr_error(ar.ar_h_errno); dns_reply(query, IMSG_DNS_HOST_END); dnssession_destroy(s); + free(ar.ar_data); return; } @@ -264,15 +260,6 @@ dns_asr_dispatch_mx(struct dnssession *s) unpack_header(&pack, &h); unpack_query(&pack, &q); - /* check if the domain name exists */ - /* XXX what about other DNS error codes? */ - if (RCODE(h.flags) == ERR_NAME) { - query->error = DNS_ENONAME; - dns_reply(query, IMSG_DNS_HOST_END); - dnssession_destroy(s); - return; - } - if (h.ancount == 0) /* fallback to host if no MX is found. */ dnssession_mx_insert(s, query->host, 0); @@ -285,12 +272,11 @@ dns_asr_dispatch_mx(struct dnssession *s) } free(ar.ar_data); - ar.ar_data = NULL; /* Now we have a sorted list of MX to resolve. Simply "turn" this * MX session into a regular host session. */ - s->aq = NULL; + s->as = NULL; s->query.type = IMSG_DNS_HOST; dns_asr_dispatch_host(s); } @@ -300,8 +286,8 @@ dns_asr_dispatch_host(struct dnssession *s) { struct dns *query = &s->query; struct mx *mx; - struct asr_result ar; - int ret; + struct async_res ar; + struct addrinfo hints, *ai; /* default to notfound, override with retry or ok later */ if (s->mxcurrent == 0) @@ -309,7 +295,7 @@ dns_asr_dispatch_host(struct dnssession *s) next: /* query all listed hosts in turn */ - while (s->aq == NULL) { + while (s->as == NULL) { if (s->mxcurrent == s->mxarraysz) { if (s->mxfound) query->error = DNS_OK; @@ -317,26 +303,29 @@ next: dnssession_destroy(s); return; } - mx = s->mxarray + s->mxcurrent++; - s->aq = asr_query_host(asr, mx->host, AF_UNSPEC); - } - while ((ret = asr_run(s->aq, &ar)) == ASR_YIELD) { - free(ar.ar_cname); - memcpy(&query->ss, &ar.ar_sa.sa, ar.ar_sa.sa.sa_len); - dns_reply(query, IMSG_DNS_HOST); - s->mxfound++; + mx = s->mxarray + s->mxcurrent++; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = PF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + s->as = getaddrinfo_async(mx->host, NULL, &hints, NULL); } - if (ret == ASR_COND) { + if (async_run(s->as, &ar) == ASYNC_COND) { dns_asr_event_set(s, &ar); return; } - if (dns_asr_error(ar.ar_err) == DNS_RETRY) - query->error = DNS_RETRY; + if (ar.ar_gai_errno == 0) { + for (ai = ar.ar_addrinfo; ai; ai = ai->ai_next) { + memcpy(&query->ss, ai->ai_addr, ai->ai_addrlen); + dns_reply(query, IMSG_DNS_HOST); + s->mxfound++; + } + freeaddrinfo(ar.ar_addrinfo); + } - s->aq = NULL; + s->as = NULL; goto next; } @@ -344,23 +333,15 @@ static void dns_asr_dispatch_cname(struct dnssession *s) { struct dns *query = &s->query; - struct asr_result ar; + struct async_res ar; - switch (asr_run(s->aq, &ar)) { - case ASR_COND: + if (async_run(s->as, &ar) == ASYNC_COND) { dns_asr_event_set(s, &ar); return; - case ASR_YIELD: - /* Only return the first answer */ - query->error = DNS_OK; - strlcpy(query->host, ar.ar_cname, sizeof (query->host)); - asr_abort(s->aq); - free(ar.ar_cname); - break; - case ASR_DONE: - query->error = dns_asr_error(ar.ar_err); - break; } + + /* the error code could be more precise, but we don't currently care */ + query->error = ar.ar_gai_errno ? DNS_ENOTFOUND : DNS_OK; dns_reply(query, IMSG_DNS_PTR); dnssession_destroy(s); } |