74 #include <sys/socket.h>
75 #include <netinet/in.h>
76 #include <arpa/inet.h>
112 static void smtp_print_addr(
const char *what,
DNS_RR *addr_list)
117 msg_info(
"begin %s address list", what);
118 for (addr = addr_list; addr; addr = addr->
next) {
127 msg_info(
"end %s address list", what);
132 static DNS_RR *smtp_addr_one(
DNS_RR *addr_list,
const char *host,
int res_opt,
135 const char *myname =
"smtp_addr_one";
139 struct addrinfo *res0;
140 struct addrinfo *res;
146 msg_info(
"%s: host %s", myname, host);
152 if (strchr((
char *) proto_family_list, res0->ai_family) != 0) {
153 if ((addr =
dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
154 msg_fatal(
"host %s: conversion error for address family "
155 "%d: %m", host, res0->ai_addr->sa_family);
175 for (rr = addr; rr; rr = rr->
next)
204 #define RETRY_AI_ERROR(e) \
205 ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
207 #define DSN_NOHOST(e) \
208 ((e) == EAI_AGAIN || (e) == EAI_NODATA || (e) == EAI_NONAME)
210 #define DSN_NOHOST(e) \
211 ((e) == EAI_AGAIN || (e) == EAI_NONAME)
219 "unable to look up host %s: %s",
222 for (found = 0, res = res0; res != 0; res = res->ai_next) {
223 if (strchr((
char *) proto_family_list, res->ai_family) == 0) {
224 msg_info(
"skipping address family %d for host %s",
225 res->ai_family, host);
229 if ((addr =
dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
230 msg_fatal(
"host %s: conversion error for address family "
231 "%d: %m", host, res0->ai_addr->sa_family);
237 "%s: host not found", host);
260 else if (smtp_tls_insecure_mx_policy >
TLS_LEV_MAY)
285 for (rr = mx_names; rr; rr = rr->
next) {
286 if (rr->
type != T_MX)
287 msg_panic(
"smtp_addr_list: bad resource type: %d", rr->
type);
288 addr_list = smtp_addr_one(addr_list, (
char *) rr->
data, res_opt,
298 const char *myname =
"smtp_find_self";
307 for (addr = addr_list; addr; addr = addr->
next) {
312 for (i = 0; i <
self->used; i++)
313 if (
DNS_RR_EQ_SA(addr, (
struct sockaddr *) (self->addrs + i))) {
315 msg_info(
"%s: found self at pref %d", myname, addr->
pref);
323 for (i = 0; i < proxy->
used; i++)
326 msg_info(
"%s: found proxy at pref %d", myname, addr->
pref);
341 static DNS_RR *smtp_truncate_self(
DNS_RR *addr_list,
unsigned pref)
346 for (last = 0, addr = addr_list; addr; last = addr, addr = addr->
next) {
347 if (pref == addr->pref) {
349 smtp_print_addr(
"truncated", addr);
364 static DNS_RR *smtp_balance_inet_proto(
DNS_RR *addr_list,
int misc_flags,
367 const char myname[] =
"smtp_balance_inet_proto";
387 for (v4_count = v6_count = 0, rr = addr_list; rr != 0; rr = rr->
next) {
388 if (rr->
type == T_A) {
390 }
else if (rr->
type == T_AAAA) {
393 msg_panic(
"%s: unexpected record type: %s",
409 if (v4_count > 0 && v6_count > 0 && v4_count + v6_count > addr_limit) {
433 if (v6_count <= addr_limit / 2) {
434 v6_target = v6_count;
435 v4_target = addr_limit - v6_target;
436 }
else if (v4_count <= addr_limit / 2) {
437 v4_target = v4_count;
438 v6_target = addr_limit - v4_target;
441 v4_target = (addr_limit + (addr_list->
type == T_A)) / 2;
442 v6_target = addr_limit - v4_target;
445 msg_info(
"v6_target=%d, v4_target=%d", v6_target, v4_target);
449 for (rr = addr_list; rr != 0; rr = next) {
452 if (rr->
type == T_A) {
454 }
else if (rr->
type == T_AAAA) {
457 msg_panic(
"%s: unexpected record type: %s",
467 if (v4_target > 0 || v6_target > 0)
468 msg_panic(
"%s: bad target count: v4_target=%d, v6_target=%d",
469 myname, v4_target, v6_target);
471 smtp_print_addr(
"smtp_balance_inet_proto result", stripped_list);
472 return (stripped_list);
481 DSN_BUF *why,
int *found_myself)
496 #define IMPOSSIBLE_PREFERENCE (~0)
502 msg_panic(
"smtp_domain_addr: DNS lookup is disabled");
512 msg_info(
"%s asciified to %s", name, aname);
584 addr_list = smtp_addr_list(mx_names, why);
588 if (addr_list == 0) {
596 msg_panic(
"smtp_domain_addr: bad status");
598 msg_warn(
"no MX host for %s has a valid address record", name);
603 smtp_print_addr(name, addr_list);
605 && (
self = smtp_find_self(addr_list)) != 0) {
606 addr_list = smtp_truncate_self(addr_list, self->
pref);
607 if (addr_list == 0) {
608 if (best_pref != best_found) {
610 "unable to find primary relay for %s", name);
612 dsb_simple(why,
"5.4.6",
"mail for %s loops back to myself",
617 #define SMTP_COMPARE_ADDR(flags) \
618 (((flags) & SMTP_MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
619 ((flags) & SMTP_MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
620 dns_rr_compare_pref_any)
622 if (addr_list && addr_list->
next) {
627 addr_list = smtp_balance_inet_proto(addr_list, misc_flags,
639 *found_myself |= (
self != 0);
662 msg_info(
"%s asciified to %s", host, ahost);
672 addr_list = smtp_addr_one((
DNS_RR *) 0, ahost, res_opt,
PREF0, why);
675 && smtp_find_self(addr_list) != 0) {
677 dsb_simple(why,
"5.4.6",
"mail for %s loops back to myself", host);
680 if (addr_list && addr_list->
next) {
687 addr_list = smtp_balance_inet_proto(addr_list, misc_flags,
691 smtp_print_addr(host, addr_list);
const char * dns_strtype(unsigned)
#define SMTP_HAS_SOFT_DSN(why)
void freeaddrinfo(struct addrinfo *ai)
#define SMTP_SET_SOFT_DSN(why)
bool var_smtp_defer_mxaddr
NORETURN msg_panic(const char *fmt,...)
bool var_ign_mx_lookup_err
#define inet_proto_info()
#define hostname_to_sockaddr(host, serv, sock, res)
struct sockaddr_storage * addrs
void dsb_reset(DSN_BUF *dsb)
int smtp_host_lookup_mask
int hostaddr_to_sockaddr(const char *hostaddr, const char *service, int socktype, struct addrinfo **res)
#define SMTP_HOST_FLAG_DNS
#define dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype)
const char * dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *)
char buf[MAI_HOSTADDR_STRSIZE]
INET_ADDR_LIST * proxy_inet_addr_list(void)
int var_smtp_mxaddr_limit
#define SMTP_HAS_HARD_DSN(why)
void msg_warn(const char *fmt,...)
#define SMTP_HOST_FLAG_NATIVE
DNS_RR * smtp_domain_addr(const char *name, DNS_RR **mxrr, int misc_flags, DSN_BUF *why, int *found_myself)
DNS_RR * dns_rr_shuffle(DNS_RR *)
DNS_RR * dns_rr_copy(DNS_RR *)
unsigned char * sa_family_list
DNS_RR * dns_sa_to_rr(const char *, unsigned, struct sockaddr *)
unsigned smtp_dns_res_opt
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
NORETURN msg_fatal(const char *fmt,...)
#define IMPOSSIBLE_PREFERENCE
int dns_rr_compare_pref_any(DNS_RR *, DNS_RR *)
DNS_RR * dns_rr_append(DNS_RR *, DNS_RR *)
DNS_RR * smtp_host_addr(const char *host, int misc_flags, DSN_BUF *why)
DSN_BUF * dsb_status(DSN_BUF *dsb, const char *status)
INET_ADDR_LIST * own_inet_addr_list(void)
const char * midna_domain_to_ascii(const char *name)
#define SMTP_DNS_DISABLED
unsigned int dnssec_valid
bool var_smtp_balance_inet_proto
DNS_RR * dns_rr_sort(DNS_RR *, int(*)(DNS_RR *, DNS_RR *))
#define SMTP_MISC_FLAG_LOOP_DETECT
#define DNS_REQ_FLAG_NONE
#define RETRY_AI_ERROR(e)
void dns_rr_free(DNS_RR *)
#define dns_lookup(name, type, rflags, list, fqdn, why)
#define DNS_RR_EQ_SA(rr, sa)
unsigned int * dns_atype_list
#define SMTP_COMPARE_ADDR(flags)
void msg_info(const char *fmt,...)