/*
+ * Copyright (c) 2008-2014, Simon Schubert <2@0x2c.org>.
* Copyright (c) 2008 The DragonFly Project. All rights reserved.
*
* This code is derived from software contributed to The DragonFly Project
- * by Simon 'corecode' Schubert <corecode@fs.ei.tum.de>
+ * by Simon Schubert <2@0x2c.org>.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
*/
#include <sys/types.h>
+#include <sys/param.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <arpa/nameser.h>
struct addrinfo hints, *res, *res0 = NULL;
char servname[10];
struct mx_hostentry *p;
- size_t onhosts;
const int count_inc = 10;
- int err;
-
- onhosts = *ps;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_protocol = IPPROTO_TCP;
snprintf(servname, sizeof(servname), "%d", port);
- err = getaddrinfo(host, servname, &hints, &res0);
- if (err)
- return (-1);
+ switch (getaddrinfo(host, servname, &hints, &res0)) {
+ case 0:
+ break;
+ case EAI_AGAIN:
+ case EAI_NONAME:
+ /*
+ * EAI_NONAME gets returned for:
+ * SMARTHOST set but DNS server not reachable -> defer
+ * SMARTHOST set but DNS server returns "host does not exist"
+ * -> buggy configuration
+ * -> either defer or bounce would be ok -> defer
+ * MX entry was returned by DNS server but name doesn't resolve
+ * -> hopefully transient situation -> defer
+ * all other DNS problems should have been caught earlier
+ * in dns_get_mx_list().
+ */
+ goto out;
+ default:
+ return(-1);
+ }
for (res = res0; res != NULL; res = res->ai_next) {
if (*ps + 1 >= roundup(*ps, count_inc)) {
}
freeaddrinfo(res0);
- return (*ps - onhosts);
+ return (0);
out:
if (res0 != NULL)
freeaddrinfo(res0);
- return (-1);
+ return (1);
}
int
size_t anssz;
int pref;
int cname_recurse;
+ int have_mx = 0;
int err;
int i;
switch (ns_rr_type(rr)) {
case ns_t_mx:
+ have_mx = 1;
pref = ns_get16(cp);
cp += 2;
err = ns_name_uncompress(ns_msg_base(msg), ns_msg_end(msg),
if (err < 0)
goto transerr;
- add_host(pref, outname, port, &hosts, &nhosts);
+ err = add_host(pref, outname, port, &hosts, &nhosts);
+ if (err == -1)
+ goto err;
break;
case ns_t_cname:
free(ans);
- if (!err) {
- /*
- * If we didn't find any MX, use the hostname instead.
- */
- if (nhosts == 0)
- add_host(0, searchhost, port, &hosts, &nhosts);
-
- qsort(hosts, nhosts, sizeof(*hosts), sort_pref);
+ if (err == 0) {
+ if (!have_mx) {
+ /*
+ * If we didn't find any MX, use the hostname instead.
+ */
+ err = add_host(0, host, port, &hosts, &nhosts);
+ } else if (nhosts == 0) {
+ /*
+ * We did get MX, but couldn't resolve any of them
+ * due to transient errors.
+ */
+ err = 1;
+ }
}
if (nhosts > 0) {
+ qsort(hosts, nhosts, sizeof(*hosts), sort_pref);
/* terminate list */
*hosts[nhosts].host = 0;
} else {