summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreric <eric@openbsd.org>2013-11-18 11:55:41 +0000
committereric <eric@openbsd.org>2013-11-18 11:55:41 +0000
commit1d08a4395dbb605d47a54a76130dbc97a0a5cad1 (patch)
treee02c5b9af21e8112e5cc7abfad26362b9209be68
parentchange dict_poproot() prototype: do not take key placeholder parameter as (diff)
downloadwireguard-openbsd-1d08a4395dbb605d47a54a76130dbc97a0a5cad1.tar.xz
wireguard-openbsd-1d08a4395dbb605d47a54a76130dbc97a0a5cad1.zip
When looking up a MX, parse the address if the domain is a "[ipaddr]" string.
-rw-r--r--usr.sbin/smtpd/dns.c91
1 files changed, 90 insertions, 1 deletions
diff --git a/usr.sbin/smtpd/dns.c b/usr.sbin/smtpd/dns.c
index 12f0012cedc..957785d495b 100644
--- a/usr.sbin/smtpd/dns.c
+++ b/usr.sbin/smtpd/dns.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dns.c,v 1.68 2013/10/26 12:27:59 eric Exp $ */
+/* $OpenBSD: dns.c,v 1.69 2013/11/18 11:55:41 eric Exp $ */
/*
* Copyright (c) 2008 Gilles Chehade <gilles@poolp.org>
@@ -103,6 +103,52 @@ dns_query_mx_preference(uint64_t id, const char *domain, const char *mx)
m_close(p_lka);
}
+static int
+domainname_is_addr(const char *s, struct sockaddr *sa, socklen_t *sl)
+{
+ struct addrinfo hints, *res;
+ socklen_t sl2;
+ size_t l;
+ char buf[SMTPD_MAXDOMAINPARTSIZE];
+ int i6, error;
+
+ if (*s != '[')
+ return (0);
+
+ i6 = (strncasecmp("[IPv6:", s, 6) == 0);
+ s += i6 ? 6 : 1;
+
+ l = strlcpy(buf, s, sizeof(buf));
+ if (l >= sizeof(buf) || l == 0 || buf[l - 1] != ']')
+ return (0);
+
+ buf[l - 1] = '\0';
+ bzero(&hints, sizeof(hints));
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_socktype = SOCK_STREAM;
+ if (i6)
+ hints.ai_family = AF_INET6;
+
+ res = NULL;
+ if ((error = getaddrinfo(buf, NULL, &hints, &res))) {
+ log_warnx("getaddrinfo: %s", gai_strerror(error));
+ }
+
+ if (!res)
+ return (0);
+
+ if (sa && sl) {
+ sl2 = *sl;
+ if (sl2 > res->ai_addrlen)
+ sl2 = res->ai_addrlen;
+ memmove(sa, res->ai_addr, sl2);
+ *sl = res->ai_addrlen;
+ }
+
+ freeaddrinfo(res);
+ return (1);
+}
+
void
dns_imsg(struct mproc *p, struct imsg *imsg)
{
@@ -112,6 +158,7 @@ dns_imsg(struct mproc *p, struct imsg *imsg)
struct async *as;
struct msg m;
const char *domain, *mx, *host;
+ socklen_t sl;
s = xcalloc(1, sizeof *s, "dns_imsg");
s->type = imsg->hdr.type;
@@ -141,7 +188,36 @@ dns_imsg(struct mproc *p, struct imsg *imsg)
m_get_string(&m, &domain);
m_end(&m);
strlcpy(s->name, domain, sizeof(s->name));
+
+ sa = (struct sockaddr *)&ss;
+ sl = sizeof(ss);
+
+ if (domainname_is_addr(domain, sa, &sl)) {
+ m_create(s->p, IMSG_DNS_HOST, 0, 0, -1);
+ m_add_id(s->p, s->reqid);
+ m_add_sockaddr(s->p, sa);
+ m_add_int(s->p, -1);
+ m_close(s->p);
+
+ m_create(s->p, IMSG_DNS_HOST_END, 0, 0, -1);
+ m_add_id(s->p, s->reqid);
+ m_add_int(s->p, DNS_OK);
+ m_close(s->p);
+ free(s);
+ return;
+ }
+
as = res_query_async(s->name, C_IN, T_MX, NULL);
+ if (as == NULL) {
+ log_warn("warn: req_query_async: %s", s->name);
+ m_create(s->p, IMSG_DNS_HOST_END, 0, 0, -1);
+ m_add_id(s->p, s->reqid);
+ m_add_int(s->p, DNS_EINVAL);
+ m_close(s->p);
+ free(s);
+ return;
+ }
+
async_run_event(as, dns_dispatch_mx, s);
return;
@@ -150,7 +226,20 @@ dns_imsg(struct mproc *p, struct imsg *imsg)
m_get_string(&m, &mx);
m_end(&m);
strlcpy(s->name, mx, sizeof(s->name));
+
+ sa = (struct sockaddr *)&ss;
+ sl = sizeof(ss);
+
as = res_query_async(domain, C_IN, T_MX, NULL);
+ if (as == NULL) {
+ m_create(s->p, IMSG_DNS_MX_PREFERENCE, 0, 0, -1);
+ m_add_id(s->p, s->reqid);
+ m_add_int(s->p, DNS_ENOTFOUND);
+ m_close(s->p);
+ free(s);
+ return;
+ }
+
async_run_event(as, dns_dispatch_mx_preference, s);
return;