summaryrefslogtreecommitdiff
path: root/usr.sbin/smtpd/dns.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/smtpd/dns.c')
-rw-r--r--usr.sbin/smtpd/dns.c115
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);
}