/*++ /* NAME /* smtp_addr 3 /* SUMMARY /* SMTP server address lookup /* SYNOPSIS /* #include "smtp_addr.h" /* /* DNS_RR *smtp_domain_addr(name, mxrr, misc_flags, why, found_myself) /* char *name; /* DNS_RR **mxrr; /* int misc_flags; /* DSN_BUF *why; /* int *found_myself; /* /* DNS_RR *smtp_host_addr(name, misc_flags, why) /* char *name; /* int misc_flags; /* DSN_BUF *why; /* /* DNS_RR *smtp_service_addr(name, service, mxrr, misc_flags, why, /* found_myself) /* const char *name; /* const char *service; /* DNS_RR **mxrr; /* int misc_flags; /* DSN_BUF *why; /* int *found_myself; /* DESCRIPTION /* This module implements Internet address lookups. By default, /* lookups are done via the Internet domain name service (DNS). /* A reasonable number of CNAME indirections is permitted. When /* DNS lookups are disabled, host address lookup is done with /* getnameinfo() or gethostbyname(). /* /* smtp_domain_addr() looks up the network addresses for mail /* exchanger hosts listed for the named domain. Addresses are /* returned in most-preferred first order. The result is truncated /* so that it contains only hosts that are more preferred than the /* local mail server itself. The found_myself result parameter /* is updated when the local MTA is MX host for the specified /* destination. If MX records were found, the rname, qname, /* and dnssec validation status of the MX RRset are returned /* via mxrr, which the caller must free with dns_rr_free(). /* Fallback from MX to address lookups is governed by RFC 2821, /* and by local policy (var_ign_mx_lookup_err). /* /* When no mail exchanger is listed in the DNS for \fIname\fR, the /* request is passed to smtp_host_addr(). /* /* It is an error to call smtp_domain_addr() when DNS lookups are /* disabled. /* /* smtp_host_addr() looks up all addresses listed for the named /* host. The host can be specified as a numerical Internet network /* address, or as a symbolic host name. /* /* smtp_service_addr() looks up addresses for hosts specified /* in SRV records for the specified domain and service. This /* supports the features of smtp_domain_addr() except that /* the order of SRV records is determined by RFC 2782, and /* that address records are not sorted by IP address family /* preference. Fallback from SRV to MX or address lookups is /* governed by local policy (var_ign_mx_lookup_err and /* var_allow_srv_fallback). /* /* Results from smtp_domain_addr(), smtp_host_addr(), and /* smtp_service_addr() are destroyed by dns_rr_free(), including /* null lists. /* DIAGNOSTICS /* Panics: interface violations. For example, calling smtp_domain_addr() /* when DNS lookups are explicitly disabled. /* /* All routines either return a DNS_RR pointer, or return a null /* pointer and update the \fIwhy\fR argument accordingly. /* LICENSE /* .ad /* .fi /* The Secure Mailer license must be distributed with this software. /* AUTHOR(S) /* Wietse Venema /* IBM T.J. Watson Research /* P.O. Box 704 /* Yorktown Heights, NY 10598, USA /* /* Wietse Venema /* Google, Inc. /* 111 8th Avenue /* New York, NY 10011, USA /* /* SRV Support by /* Tomas Korbar /* Red Hat, Inc.
/*--*/
/* *Findoutifthismailsystemislisteningonthisaddress.
*/ for (i = 0; i < self->used; i++) if (DNS_RR_EQ_SA(addr, (struct sockaddr *) (self->addrs + i))) { if (msg_verbose)
msg_info("%s: found self at pref %d", myname, addr->pref); return (addr);
}
/* *Findoutifthismailsystemhasaproxylisteningonthis *address.
*/ for (i = 0; i < proxy->used; i++) if (DNS_RR_EQ_SA(addr, (struct sockaddr *) (proxy->addrs + i))) { if (msg_verbose)
msg_info("%s: found proxy at pref %d", myname, addr->pref); return (addr);
}
}
/* *Didn'tfindmyself,ormyproxy.
*/ if (msg_verbose)
msg_info("%s: not found", myname); return (0);
}
/* smtp_truncate_self - truncate address list at self and equivalents */
for (last = 0, addr = addr_list; addr; last = addr, addr = addr->next) { if (pref == addr->pref) { if (msg_verbose)
smtp_print_addr("truncated", addr);
dns_rr_free(addr); if (last == 0) {
addr_list = 0;
} else {
last->next = 0;
} break;
}
} return (addr_list);
}
/* smtp_balance_inet_proto - balance IPv4/6 protocols within address limit */
static DNS_RR *smtp_balance_inet_proto(DNS_RR *addr_list, int misc_flags, int addr_limit)
{ constchar myname[] = "smtp_balance_inet_proto";
DNS_RR *rr;
DNS_RR *stripped_list;
DNS_RR *next; int v6_count; int v4_count; int v6_target, v4_target; int *p;
/* *Sanitycheck.
*/ if (smtp_dns_support == SMTP_DNS_DISABLED)
msg_panic("smtp_domain_addr: DNS lookup is disabled"); if (smtp_dns_support == SMTP_DNS_DNSSEC)
r |= RES_USE_DNSSEC;
/* *IDNAsupport.
*/ #ifndef NO_EAI if (!allascii(name) && (aname = midna_domain_to_ascii(name)) != 0) { if (msg_verbose)
msg_info("%s asciified to %s", name, aname);
} else #endif
aname = name;
/* *Lookupthemailexchangerhostslistedforthisname.Sortthe *resultsbypreference.Lookupthecorrespondinghostaddresses,and *truncatethelistsothatitcontainsonlyhoststhataremore *preferredthanmyself.WhennoMXresourcerecordsexist,lookupthe *addresseslistedforthisname. * *AccordingtoRFC974:"ItispossiblethatthelistofMXsinthe *responsetothequerywillbeempty.Thisisaspecialcase.Ifthe *listisempty,mailersshouldtreatitasifitcontainedoneRR,an *MXRRwithapreferencevalueof0,andahostnameofREMOTE.(I.e., *REMOTEisitsonlyMX).Inaddition,themailershoulddonofurther *processingonthelist,butshouldattempttodeliverthemessageto *REMOTE." * *NormallyitisOKifanMXhostcannotbefoundintheDNS;we'lljust *useabackupone,andsilentlyignorethebetterMXhost.However,if *thebestbackupthatwecanfindintheDNSisthelocalmachine,then *wemustrememberthatthelocalmachineisnottheprimaryMXhost,or *elsewewillclaimthatmailloopsback. * *XXXOptionallydoAlookupsevenwhentheMXlookupdidn'tcomplete. *UnfortunatelywithsomeDNSserversthisisnotatransientproblem. * *XXXIdeallywewouldperformAlookupsonlyasfarasneeded.Butaslong *aswe'relookingupallthehosts,itwouldbebettertolookupthe *leastpreferredhostfirst,sothatDNSlookuperrormessagesmake *moresense. * *XXX2821:RFC2821saysthatthesendermustshuffleequal-preferenceMX *hosts,whereasmultipleArecordsperhostnamemustbeusedinthe *orderasreceived.Theymakethebogusassumptionthatahostnamewith *multipleArecordscorrespondstoonemachinewithmultiplenetwork *interfaces. * *XXX2821:PostfixrecognizesthelocalmachinebylookingforitsownIP *addressinthelistofmailexchangers.RFC2821saysonehastolook *atthemailexchangerhostnameaswell,makingthebogusassumption *thatanIPaddressislistedonlyunderonehostname.However,looking *athostnamesprovidesapartialsolutionforMXhostsbehindaNAT *gateway.
*/ switch (dns_lookup(aname, T_MX, r, &mx_names, (VSTRING *) 0, why->reason)) { default:
dsb_status(why, "4.4.3"); if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(aname, misc_flags, why); break; case DNS_INVAL:
dsb_status(why, "5.4.4"); if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(aname, misc_flags, why); break; case DNS_NULLMX:
dsb_status(why, "5.1.0"); break; case DNS_POLICY:
dsb_status(why, "4.7.0"); break; case DNS_FAIL:
dsb_status(why, "5.4.3"); if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(aname, misc_flags, why); break; case DNS_OK:
mx_names = dns_rr_sort(mx_names, dns_rr_compare_pref_any);
best_pref = (mx_names ? mx_names->pref : IMPOSSIBLE_PREFERENCE);
addr_list = smtp_addr_list(mx_names, why); if (mxrr)
*mxrr = dns_rr_copy(mx_names); /* copies one record! */
dns_rr_free(mx_names); if (addr_list == 0) { /* Text does not change. */ if (var_smtp_defer_mxaddr) { /* Don't clobber the null terminator. */ if (SMTP_HAS_HARD_DSN(why))
SMTP_SET_SOFT_DSN(why); /* XXX */ /* Require some error status. */ elseif (!SMTP_HAS_SOFT_DSN(why))
msg_panic("smtp_domain_addr: bad status");
}
msg_warn("no MX host for %s has a valid address record", name); break;
}
best_found = (addr_list ? addr_list->pref : IMPOSSIBLE_PREFERENCE); if (msg_verbose)
smtp_print_addr(name, addr_list); if ((misc_flags & SMTP_MISC_FLAG_LOOP_DETECT)
&& (self = smtp_find_self(addr_list)) != 0) {
addr_list = smtp_truncate_self(addr_list, self->pref); if (addr_list == 0) { if (best_pref != best_found) {
dsb_simple(why, "4.4.4", "unable to find primary relay for %s", name);
} else {
dsb_simple(why, "5.4.6", "mail for %s loops back to myself",
name);
}
}
} #define SMTP_COMPARE_ADDR(flags) \
(((flags) & SMTP_MISC_FLAG_PREF_IPV6) ? dns_rr_compare_pref_ipv6 : \
((flags) & SMTP_MISC_FLAG_PREF_IPV4) ? dns_rr_compare_pref_ipv4 : \
dns_rr_compare_pref_any)
if (addr_list && addr_list->next) { if (var_smtp_rand_addr)
addr_list = dns_rr_shuffle(addr_list);
addr_list = dns_rr_sort(addr_list, SMTP_COMPARE_ADDR(misc_flags)); if (var_smtp_mxaddr_limit > 0 && var_smtp_balance_inet_proto)
addr_list = smtp_balance_inet_proto(addr_list, misc_flags,
var_smtp_mxaddr_limit);
} break; case DNS_NOTFOUND:
addr_list = smtp_host_addr(aname, misc_flags, why); break;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.