2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-09-02 07:05:27 +00:00

postfix-2.0.16-20031217

This commit is contained in:
Wietse Venema
2003-12-17 00:00:00 -05:00
committed by Viktor Dukhovni
parent 49328174e4
commit 92cfbcfea3
15 changed files with 346 additions and 219 deletions

View File

@@ -8871,9 +8871,19 @@ Apologies for any names omitted.
between short queue ID and message status). File: between short queue ID and message status). File:
showq/showq.c. showq/showq.c.
20031216-7
Cleanup: the SMTP client now moves on to the next MX host Cleanup: the SMTP client now moves on to the next MX host
when delivery fails in the middle of an SMTP session. or fallback relay when delivery fails in the middle of an
Files: smtp/smtp.c, smtp/smtp_connect.c. SMTP session. This includes not only broken connections
(easy) but also includes 4xx SMTP server replies (not easy).
Files: smtp/smtp.c, smtp/smtp_connect.c, smtp_trouble.c.
20031217
Update: LDAP client logging (Liviu Daia) and LDAP client
documentation (Victor Duchovni). Files: util/dict_ldap.c,
conf/sample-ldap.cf, README_FILES/LDAP_README.
Open problems: Open problems:

View File

@@ -93,7 +93,7 @@ parameters. Defaults are given in parentheses:
server_port = 778 server_port = 778
search_base (No default; you must configure this.) search_base (No default; you must configure this.)
The base at which to conduct the search, e.g. The RFC2253 base DN at which to conduct the search, e.g.
search_base = dc=your, dc=com search_base = dc=your, dc=com
timeout (10 seconds) timeout (10 seconds)
@@ -104,19 +104,23 @@ parameters. Defaults are given in parentheses:
The RFC2254 filter used to search the directory, where %s is a The RFC2254 filter used to search the directory, where %s is a
substitute for the address Postfix is trying to resolve, e.g. substitute for the address Postfix is trying to resolve, e.g.
query_filter = (&(mail=%s)(paid_up=true)) query_filter = (&(mail=%s)(paid_up=true))
See sample-ldap.cf for more details.
result_filter (%s) result_filter (%s)
Filter applied to result attributes. Supports the same expansions Format template applied to result attributes. Supports the same
as the query_filter, and can be easily used to append (or prepend) expansions as the query_filter, and can be easily used to append
text. (or prepend) text. See sample-ldap.cf for more details.
domain (Default is to ignore this.) domain (Default is no domain list.)
This is a list of domain names, paths to files, or dictionaries. This is a list of domain names, paths to files, or dictionaries.
If specified, only lookups for the domains on this list will be When specified, only fully qualified search keys with a
performed. This means that the LDAP map won't get searched for *non-empty* localpart and a matching domain are eligible for
'user', nor will it get searched for any domain not listed. This lookup: 'user' lookups, bare domain lookups and "@domain" lookups
can significantly reduce the query load on the LDAP server. are not performed. This can significantly reduce the query load
on the LDAP server.
domain = postfix.org, hash:/etc/postfix/searchdomains domain = postfix.org, hash:/etc/postfix/searchdomains
It is best not to use LDAP to store the domains eligible for LDAP
lookups.
result_attribute (maildrop) result_attribute (maildrop)
The attribute(s) Postfix will read from any directory entries The attribute(s) Postfix will read from any directory entries
@@ -127,6 +131,12 @@ parameters. Defaults are given in parentheses:
The attribute(s) of directory entries that can contain DNs or URLs. The attribute(s) of directory entries that can contain DNs or URLs.
If found, a recursive subsequent search is done using their values. If found, a recursive subsequent search is done using their values.
special_result_attribute = member special_result_attribute = member
DN recursion retrieves the same result_attributes as the main
query, including the special attributes for further recursion.
URI processing retrieves only those attributes that are included
in the URI definition and are *also* listed in "result_attribute".
If the URI lists any of the map's special result attributes, these
are also retrieved and used recursively.
scope (sub) scope (sub)
The LDAP search scope: sub, base, or one. These translate into The LDAP search scope: sub, base, or one. These translate into

View File

@@ -22,6 +22,13 @@ snapshot release). Patches change the patchlevel and the release
date. Snapshots change only the release date, unless they include date. Snapshots change only the release date, unless they include
the same bugfixes as a patch release. the same bugfixes as a patch release.
Major changes with Postfix snapshot 2.0.16-20031217
===================================================
The SMTP client now moves on to the next MX host (or fallback relay)
when delivery fails in the middle of a session. This includes both
broken connections as well as 4XX replies to SMTP commands.
Incompatible changes with Postfix snapshot 2.0.16-20031215 Incompatible changes with Postfix snapshot 2.0.16-20031215
========================================================== ==========================================================

View File

@@ -27,18 +27,62 @@
#version = 2 #version = 2
# The query_filter parameter specifies the filter used for queries. # The query_filter parameter specifies the filter used for queries.
# The replacement for "%s" is the address input into the map; e.g. #
# for alias maps, the "user" part (the RFC 2822 local-part) of # This parameter supports the following '%' expansions:
# "user@domain.com" for To: addresses destined for local delivery #
# (those matching $mydestination or a virtual domain), and all of # %s - This is replaced by the input key. RFC 2254 quoting is
# "user@domain.com" (the RFC 2822 addr-spec) for other addresses. # used to make sure that the input key does not add
# "%u" provides just the user portion of the input, and "%d" provides # unexpected metacharacters.
# just the hostname. #
# %u - When the input key is an address of the form user@domain,
# %u is replaced by the (2254) quoted local part of the address.
# if no domain is specified, %u is replaced by the entire search
# string.
#
# %d - When the input key is an address of the form user@domain,
# %d is replaced by the (2254) quoted domain part of the address.
# When the input key has no domain qualifier, %d is replaced by the
# entire search string.
#
# The "domain" parameter described below limits the input keys to
# addresses in matching domains. When the "domain parameter is non-empty,
# LDAP queries for unqualified addresses or addresses in non-matching
# domains are suppressed and return no results.
#
# A non-empty value must be specified explicitly for this parameter. The empty
# default will not work.
#
# NOTE: DO NOT put double-quotes around the query filter!
# #
#query_filter = (mailacceptinggeneralid=%s) #query_filter = (mailacceptinggeneralid=%s)
# The result_filter parameter specifies the filter to be applied # The result_filter parameter is printf-like format template that
# to the result attribute(s). See query_filter for valid expansions. # is applied separately to each result attribute of matching entries.
#
# This parameter supports the following '%' expansions:
#
# %s - This is replaced by the value of the result attribute.
#
# %u - When the result attribute is an address of the form user@domain,
# %u is replaced local part of the address, if the result attribute
# is unqualified, %u is replaced by the entire attribute value.
#
# %d - When a result attribute is an address of the form user@domain,
# %d is replaced by the domain part of the attribute value.
# If an attribute value is unqualified %d is replaced by the entire
# attribute value.
#
# For example, using "result_filter = smtp:[%s]" allows one to use a
# mailHost attribute as the basis of a transport(5) table. After applying
# the result filter, multiple values are concatenated as comma separated
# strings. The expansion_limit and size_limit parameters explained below
# allow one to restrict the number of values in the result, which is
# especially useful for maps that should return a single value.
#
# The default value %s (no quotes!) specifies that each attribute value
# should be used as is.
#
# NOTE: DO NOT put double-quotes around the result filter!
# #
#result_filter = %s #result_filter = %s
@@ -49,10 +93,23 @@
# The special_result_attribute lists the attribute(s) of an # The special_result_attribute lists the attribute(s) of an
# entry which contain links, either ldap url's or distinguished names. # entry which contain links, either ldap url's or distinguished names.
# The entries referenced by these links are (recursively) treated as if
# they were contained in the referencing entity.
# #
#special_result_attribute = # The entries referenced by these links are (recursively) treated as if
# they were contained in the referencing entity. The result_attributes
# of the referenced entries are retrieved and added to the query result.
# The special result attributes of the referenced entries are evaluated
# recursively.
#
# Note that for URI references, only the search base, scope, query filter
# and attributes are taken from the URI, the scheme, host and port are
# taken from the map definition. Extensions (even critical) are ignored.
# Of the attributes listed in the URI, only those listed in result_attribute
# are used in the search results, and only those listed in
# special_result_attribute are used for further recursion.
#
# The default value of this parameter is empty.
#
#special_result_attribute = uniquemember
# The scope parameter specifies the LDAP search scope: sub, base, or one. # The scope parameter specifies the LDAP search scope: sub, base, or one.
# #
@@ -113,7 +170,11 @@
#dereference = 0 #dereference = 0
# The domain parameter limits the LDAP searches to just things in # The domain parameter limits the LDAP searches to just things in
# (exactly) the specified list of domains. # (exactly) the specified list of domains. When the "domain" parameter
# is non-empty, LDAP queries for unqualified addresses or addresses in
# non-matching domains are suppressed and return no results. This includes
# queries for catchall addresses with no local part (i.e. @domain.tld),
# which are also skipped.
# #
#domain = #domain =

View File

@@ -20,7 +20,7 @@
* Patches change the patchlevel and the release date. Snapshots change the * Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release. * release date only, unless they include the same bugfix as a patch release.
*/ */
#define MAIL_RELEASE_DATE "20031216" #define MAIL_RELEASE_DATE "20031217"
#define VAR_MAIL_VERSION "mail_version" #define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE #define DEF_MAIL_VERSION "2.0.16-" MAIL_RELEASE_DATE

View File

@@ -75,11 +75,6 @@ smtp.o: ../../include/recipient_list.h
smtp.o: ../../include/mail_params.h smtp.o: ../../include/mail_params.h
smtp.o: ../../include/mail_conf.h smtp.o: ../../include/mail_conf.h
smtp.o: ../../include/debug_peer.h smtp.o: ../../include/debug_peer.h
smtp.o: ../../include/mail_error.h
smtp.o: ../../include/deliver_pass.h
smtp.o: ../../include/mail_proto.h
smtp.o: ../../include/iostuff.h
smtp.o: ../../include/attr.h
smtp.o: ../../include/mail_server.h smtp.o: ../../include/mail_server.h
smtp.o: smtp.h smtp.o: smtp.h
smtp.o: smtp_sasl.h smtp.o: smtp_sasl.h
@@ -94,12 +89,16 @@ smtp_addr.o: ../../include/stringops.h
smtp_addr.o: ../../include/myrand.h smtp_addr.o: ../../include/myrand.h
smtp_addr.o: ../../include/mail_params.h smtp_addr.o: ../../include/mail_params.h
smtp_addr.o: ../../include/own_inet_addr.h smtp_addr.o: ../../include/own_inet_addr.h
smtp_addr.o: ../../include/deliver_pass.h
smtp_addr.o: ../../include/deliver_request.h
smtp_addr.o: ../../include/vstream.h
smtp_addr.o: ../../include/recipient_list.h
smtp_addr.o: ../../include/mail_proto.h
smtp_addr.o: ../../include/iostuff.h
smtp_addr.o: ../../include/attr.h
smtp_addr.o: ../../include/dns.h smtp_addr.o: ../../include/dns.h
smtp_addr.o: smtp.h smtp_addr.o: smtp.h
smtp_addr.o: ../../include/vstream.h
smtp_addr.o: ../../include/argv.h smtp_addr.o: ../../include/argv.h
smtp_addr.o: ../../include/deliver_request.h
smtp_addr.o: ../../include/recipient_list.h
smtp_addr.o: smtp_addr.h smtp_addr.o: smtp_addr.h
smtp_chat.o: smtp_chat.c smtp_chat.o: smtp_chat.c
smtp_chat.o: ../../include/sys_defs.h smtp_chat.o: ../../include/sys_defs.h
@@ -137,6 +136,9 @@ smtp_connect.o: ../../include/host_port.h
smtp_connect.o: ../../include/sane_connect.h smtp_connect.o: ../../include/sane_connect.h
smtp_connect.o: ../../include/mail_params.h smtp_connect.o: ../../include/mail_params.h
smtp_connect.o: ../../include/own_inet_addr.h smtp_connect.o: ../../include/own_inet_addr.h
smtp_connect.o: ../../include/debug_peer.h
smtp_connect.o: ../../include/mail_error.h
smtp_connect.o: ../../include/name_mask.h
smtp_connect.o: ../../include/dns.h smtp_connect.o: ../../include/dns.h
smtp_connect.o: smtp.h smtp_connect.o: smtp.h
smtp_connect.o: ../../include/argv.h smtp_connect.o: ../../include/argv.h

View File

@@ -315,10 +315,8 @@ bool var_smtp_defer_mxaddr;
bool var_smtp_send_xforward; bool var_smtp_send_xforward;
/* /*
* Global variables. smtp_errno is set by the address lookup routines and by * Global variables.
* the connection management routines.
*/ */
int smtp_errno;
int smtp_host_lookup_mask; int smtp_host_lookup_mask;
/* deliver_message - deliver message with extreme prejudice */ /* deliver_message - deliver message with extreme prejudice */

View File

@@ -55,7 +55,8 @@ typedef struct SMTP_STATE {
off_t size_limit; /* server limit or unknown */ off_t size_limit; /* server limit or unknown */
int space_left; /* output length control */ int space_left; /* output length control */
struct MIME_STATE *mime_state; /* mime state machine */ struct MIME_STATE *mime_state; /* mime state machine */
int final; /* last possibility to deliver */ int final_server; /* final mail server */
int backup_server; /* relayhost or fallback relay */
} SMTP_STATE; } SMTP_STATE;
#define SMTP_FEATURE_ESMTP (1<<0) #define SMTP_FEATURE_ESMTP (1<<0)
@@ -73,7 +74,6 @@ typedef struct SMTP_STATE {
/* /*
* smtp.c * smtp.c
*/ */
extern int smtp_errno; /* XXX can we get rid of this? */
extern int smtp_host_lookup_mask; /* host lookup methods to use */ extern int smtp_host_lookup_mask; /* host lookup methods to use */
#define SMTP_MASK_DNS (1<<0) #define SMTP_MASK_DNS (1<<0)

View File

@@ -6,14 +6,13 @@
/* SYNOPSIS /* SYNOPSIS
/* #include "smtp_addr.h" /* #include "smtp_addr.h"
/* /*
/* DNS_RR *smtp_domain_addr(name, why, found_myself) /* DNS_RR *smtp_domain_addr(state, name)
/* SMTP_STATE *state;
/* char *name; /* char *name;
/* VSTRING *why;
/* int *found_myself;
/* /*
/* DNS_RR *smtp_host_addr(name, why) /* DNS_RR *smtp_host_addr(state, name)
/* SMTP_STATE *state;
/* char *name; /* char *name;
/* VSTRING *why;
/* DESCRIPTION /* DESCRIPTION
/* This module implements Internet address lookups. By default, /* This module implements Internet address lookups. By default,
/* lookups are done via the Internet domain name service (DNS). /* lookups are done via the Internet domain name service (DNS).
@@ -27,7 +26,7 @@
/* so that it contains only hosts that are more preferred than the /* so that it contains only hosts that are more preferred than the
/* local mail server itself. When the "best MX is local" feature /* local mail server itself. When the "best MX is local" feature
/* is enabled, the local system is allowed to be the best mail /* is enabled, the local system is allowed to be the best mail
/* exchanger, and the result is a null list pointer. Otherwise, /* exchanger, and mail is delivered accordingly. Otherwise,
/* mailer loops are treated as an error. /* mailer loops are treated as an error.
/* /*
/* When no mail exchanger is listed in the DNS for \fIname\fR, the /* When no mail exchanger is listed in the DNS for \fIname\fR, the
@@ -47,16 +46,7 @@
/* when DNS lookups are explicitly disabled. /* when DNS lookups are explicitly disabled.
/* /*
/* All routines either return a DNS_RR pointer, or return a null /* All routines either return a DNS_RR pointer, or return a null
/* pointer and set the \fIsmtp_errno\fR global variable accordingly: /* pointer and report any problems via the smtp_trouble(3) module.
/* .IP SMTP_RETRY
/* The request failed due to a soft error, and should be retried later.
/* .IP SMTP_FAIL
/* The request attempt failed due to a hard error.
/* .IP SMTP_OK
/* The local machine is the best mail exchanger.
/* .PP
/* In addition, a textual description of the problem is made available
/* via the \fIwhy\fR argument.
/* LICENSE /* LICENSE
/* .ad /* .ad
/* .fi /* .fi
@@ -119,6 +109,7 @@ static int h_errno = TRY_AGAIN;
#include <mail_params.h> #include <mail_params.h>
#include <own_inet_addr.h> #include <own_inet_addr.h>
#include <deliver_pass.h>
/* DNS library. */ /* DNS library. */
@@ -129,6 +120,9 @@ static int h_errno = TRY_AGAIN;
#include "smtp.h" #include "smtp.h"
#include "smtp_addr.h" #include "smtp_addr.h"
#define ERROR_CLASS_RETRY 450
#define ERROR_CLASS_FAIL 550
/* smtp_print_addr - print address list */ /* smtp_print_addr - print address list */
static void smtp_print_addr(char *what, DNS_RR *addr_list) static void smtp_print_addr(char *what, DNS_RR *addr_list)
@@ -152,7 +146,8 @@ static void smtp_print_addr(char *what, DNS_RR *addr_list)
/* smtp_addr_one - address lookup for one host name */ /* smtp_addr_one - address lookup for one host name */
static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why) static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref,
VSTRING *why, int *error_class)
{ {
char *myname = "smtp_addr_one"; char *myname = "smtp_addr_one";
struct in_addr inaddr; struct in_addr inaddr;
@@ -185,13 +180,13 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
addr_list = dns_rr_append(addr_list, addr); addr_list = dns_rr_append(addr_list, addr);
return (addr_list); return (addr_list);
default: default:
smtp_errno = SMTP_RETRY; *error_class = ERROR_CLASS_RETRY;
return (addr_list); return (addr_list);
case DNS_FAIL: case DNS_FAIL:
smtp_errno = SMTP_FAIL; *error_class = ERROR_CLASS_FAIL;
return (addr_list); return (addr_list);
case DNS_NOTFOUND: case DNS_NOTFOUND:
smtp_errno = SMTP_FAIL; *error_class = ERROR_CLASS_FAIL;
/* maybe gethostbyname() will succeed */ /* maybe gethostbyname() will succeed */
break; break;
} }
@@ -204,12 +199,13 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
memset((char *) &fixed, 0, sizeof(fixed)); memset((char *) &fixed, 0, sizeof(fixed));
if ((hp = gethostbyname(host)) == 0) { if ((hp = gethostbyname(host)) == 0) {
vstring_sprintf(why, "%s: %s", host, HSTRERROR(h_errno)); vstring_sprintf(why, "%s: %s", host, HSTRERROR(h_errno));
smtp_errno = (h_errno == TRY_AGAIN ? SMTP_RETRY : SMTP_FAIL); *error_class = (h_errno == TRY_AGAIN ?
ERROR_CLASS_RETRY : ERROR_CLASS_FAIL);
} else if (hp->h_addrtype != AF_INET) { } else if (hp->h_addrtype != AF_INET) {
vstring_sprintf(why, "%s: host not found", host); vstring_sprintf(why, "%s: host not found", host);
msg_warn("%s: unknown address family %d for %s", msg_warn("%s: unknown address family %d for %s",
myname, hp->h_addrtype, host); myname, hp->h_addrtype, host);
smtp_errno = SMTP_FAIL; *error_class = ERROR_CLASS_FAIL;
} else { } else {
while (hp->h_addr_list[0]) { while (hp->h_addr_list[0]) {
addr_list = dns_rr_append(addr_list, addr_list = dns_rr_append(addr_list,
@@ -230,16 +226,17 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
/* smtp_addr_list - address lookup for a list of mail exchangers */ /* smtp_addr_list - address lookup for a list of mail exchangers */
static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why) static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why, int *error_class)
{ {
DNS_RR *addr_list = 0; DNS_RR *addr_list = 0;
DNS_RR *rr; DNS_RR *rr;
/* /*
* As long as we are able to look up any host address, we ignore problems * As long as we are able to look up any host address, we ignore problems
* with DNS lookups. * with DNS lookups (except if we're backup MX, and all the better MX
* hosts can't be found).
* *
* XXX 2821: update smtp_errno (0->FAIL upon unrecoverable lookup error, * XXX 2821: update error_class (0->FAIL upon unrecoverable lookup error,
* any->RETRY upon temporary lookup error) so that we can correctly * any->RETRY upon temporary lookup error) so that we can correctly
* handle the case of no resolvable MX host. Currently this is always * handle the case of no resolvable MX host. Currently this is always
* treated as a soft error. RFC 2821 wants a more precise response. * treated as a soft error. RFC 2821 wants a more precise response.
@@ -247,7 +244,8 @@ static DNS_RR *smtp_addr_list(DNS_RR *mx_names, VSTRING *why)
for (rr = mx_names; rr; rr = rr->next) { for (rr = mx_names; rr; rr = rr->next) {
if (rr->type != T_MX) if (rr->type != T_MX)
msg_panic("smtp_addr_list: bad resource type: %d", rr->type); msg_panic("smtp_addr_list: bad resource type: %d", rr->type);
addr_list = smtp_addr_one(addr_list, (char *) rr->data, rr->pref, why); addr_list = smtp_addr_one(addr_list, (char *) rr->data, rr->pref,
why, error_class);
} }
return (addr_list); return (addr_list);
} }
@@ -330,13 +328,16 @@ static int smtp_compare_pref(DNS_RR *a, DNS_RR *b)
/* smtp_domain_addr - mail exchanger address lookup */ /* smtp_domain_addr - mail exchanger address lookup */
DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself) DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *name)
{ {
DELIVER_REQUEST *request = state->request;
DNS_RR *mx_names; DNS_RR *mx_names;
DNS_RR *addr_list = 0; DNS_RR *addr_list = 0;
DNS_RR *self = 0; DNS_RR *self = 0;
unsigned best_pref; unsigned best_pref;
unsigned best_found; unsigned best_found;
int error_class;
VSTRING *why = vstring_alloc(1);
/* /*
* Preferences from DNS use 0..32767, fall-backs use 32768+. * Preferences from DNS use 0..32767, fall-backs use 32768+.
@@ -390,26 +391,40 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
* that an IP address is listed only under one hostname. However, looking * that an IP address is listed only under one hostname. However, looking
* at hostnames provides a partial solution for MX hosts behind a NAT * at hostnames provides a partial solution for MX hosts behind a NAT
* gateway. * gateway.
*
* Defer host lookup errors if a) there are more mail servers or b) we are
* looking up a relayhost or fallback relay.
*/ */
#define DEFER_HOST_LOOKUP_ERROR(s) \
((s)->final_server == 0 || (s)->backup_server)
switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why)) { switch (dns_lookup(name, T_MX, 0, &mx_names, (VSTRING *) 0, why)) {
default: default:
smtp_errno = SMTP_RETRY;
if (var_ign_mx_lookup_err) if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(name, why); addr_list = smtp_host_addr(state, name);
else
smtp_site_fail(state, ERROR_CLASS_RETRY,
"%s: %s", request->queue_id, vstring_str(why));
break; break;
case DNS_FAIL: case DNS_FAIL:
smtp_errno = SMTP_FAIL;
if (var_ign_mx_lookup_err) if (var_ign_mx_lookup_err)
addr_list = smtp_host_addr(name, why); addr_list = smtp_host_addr(state, name);
else {
smtp_site_fail(state, DEFER_HOST_LOOKUP_ERROR(state) ?
ERROR_CLASS_RETRY : ERROR_CLASS_FAIL,
"%s: %s", request->queue_id, vstring_str(why));
}
break; break;
case DNS_OK: case DNS_OK:
mx_names = dns_rr_sort(mx_names, smtp_compare_pref); mx_names = dns_rr_sort(mx_names, smtp_compare_pref);
best_pref = (mx_names ? mx_names->pref : IMPOSSIBLE_PREFERENCE); best_pref = (mx_names ? mx_names->pref : IMPOSSIBLE_PREFERENCE);
addr_list = smtp_addr_list(mx_names, why); addr_list = smtp_addr_list(mx_names, why, &error_class);
dns_rr_free(mx_names); dns_rr_free(mx_names);
if (addr_list == 0) { if (addr_list == 0) {
if (var_smtp_defer_mxaddr) if (var_smtp_defer_mxaddr || DEFER_HOST_LOOKUP_ERROR(state))
smtp_errno = SMTP_RETRY; error_class = ERROR_CLASS_RETRY;
smtp_site_fail(state, error_class,
"%s: %s", request->queue_id, vstring_str(why));
msg_warn("no MX host for %s has a valid A record", name); msg_warn("no MX host for %s has a valid A record", name);
break; break;
} }
@@ -420,18 +435,23 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
addr_list = smtp_truncate_self(addr_list, self->pref); addr_list = smtp_truncate_self(addr_list, self->pref);
if (addr_list == 0) { if (addr_list == 0) {
if (best_pref != best_found) { if (best_pref != best_found) {
vstring_sprintf(why, "unable to find primary relay for %s", smtp_site_fail(state, ERROR_CLASS_RETRY,
name); "%s: unable to find primary relay for %s",
smtp_errno = SMTP_RETRY; request->queue_id, name);
} else if (*var_bestmx_transp != 0) { /* we're best MX */ } else if (*var_bestmx_transp != 0) { /* we're best MX */
smtp_errno = SMTP_OK; state->status =
deliver_pass_all(MAIL_CLASS_PRIVATE, var_bestmx_transp,
request);
state->final_server = 1;
} else { } else {
msg_warn("mailer loop: best MX host for %s is local", msg_warn("%s is best MX host for %s but no local, virtual "
name); "or remote delivery is configured for that domain",
vstring_sprintf(why, "mail for %s loops back to myself", var_myhostname, request->nexthop);
name); smtp_site_fail(state, ERROR_CLASS_FAIL,
smtp_errno = SMTP_FAIL; "%s: mail for %s loops back to myself",
request->queue_id, name);
} }
break;
} }
} }
if (addr_list && addr_list->next && var_smtp_rand_addr) { if (addr_list && addr_list->next && var_smtp_rand_addr) {
@@ -440,32 +460,43 @@ DNS_RR *smtp_domain_addr(char *name, VSTRING *why, int *found_myself)
} }
break; break;
case DNS_NOTFOUND: case DNS_NOTFOUND:
addr_list = smtp_host_addr(name, why); addr_list = smtp_host_addr(state, name);
break; break;
} }
/* /*
* Clean up. * Clean up.
*/ */
*found_myself = (self != 0); vstring_free(why);
return (addr_list); return (addr_list);
} }
/* smtp_host_addr - direct host lookup */ /* smtp_host_addr - direct host lookup */
DNS_RR *smtp_host_addr(char *host, VSTRING *why) DNS_RR *smtp_host_addr(SMTP_STATE *state, char *host)
{ {
DELIVER_REQUEST *request = state->request;
DNS_RR *addr_list; DNS_RR *addr_list;
int error_class;
VSTRING *why = vstring_alloc(1);
/* /*
* If the host is specified by numerical address, just convert the * If the host is specified by numerical address, just convert the
* address to internal form. Otherwise, the host is specified by name. * address to internal form. Otherwise, the host is specified by name.
*/ */
#define PREF0 0 #define PREF0 0
addr_list = smtp_addr_one((DNS_RR *) 0, host, PREF0, why); addr_list = smtp_addr_one((DNS_RR *) 0, host, PREF0, why, &error_class);
if (addr_list && addr_list->next && var_smtp_rand_addr) if (addr_list == 0) {
addr_list = dns_rr_shuffle(addr_list); if (DEFER_HOST_LOOKUP_ERROR(state))
if (msg_verbose) error_class = ERROR_CLASS_RETRY;
smtp_print_addr(host, addr_list); smtp_site_fail(state, error_class,
"%s: %s", request->queue_id, vstring_str(why));
} else {
if (addr_list->next && var_smtp_rand_addr)
addr_list = dns_rr_shuffle(addr_list);
if (msg_verbose)
smtp_print_addr(host, addr_list);
}
vstring_free(why);
return (addr_list); return (addr_list);
} }

View File

@@ -16,8 +16,8 @@
/* /*
* Internal interfaces. * Internal interfaces.
*/ */
extern DNS_RR *smtp_host_addr(char *, VSTRING *); extern DNS_RR *smtp_host_addr(SMTP_STATE *state, char *);
extern DNS_RR *smtp_domain_addr(char *, VSTRING *, int *); extern DNS_RR *smtp_domain_addr(SMTP_STATE *state, char *);
/* LICENSE /* LICENSE
/* .ad /* .ad

View File

@@ -2,7 +2,7 @@
/* NAME /* NAME
/* smtp_connect 3 /* smtp_connect 3
/* SUMMARY /* SUMMARY
/* connect to SMTP server /* connect to SMTP server and deliver
/* SYNOPSIS /* SYNOPSIS
/* #include "smtp.h" /* #include "smtp.h"
/* /*
@@ -81,7 +81,6 @@
#include <mail_params.h> #include <mail_params.h>
#include <own_inet_addr.h> #include <own_inet_addr.h>
#include <deliver_pass.h>
#include <debug_peer.h> #include <debug_peer.h>
#include <mail_error.h> #include <mail_error.h>
@@ -204,27 +203,6 @@ static SMTP_SESSION *smtp_connect_addr(SMTP_STATE *state, DNS_RR *addr,
} }
vstream_ungetc(stream, ch); vstream_ungetc(stream, ch);
/*
* Skip this host if it sends a 4xx greeting.
*/
if (ch == '4' && var_smtp_skip_4xx_greeting) {
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
"server refused mail service",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
vstream_fclose(stream);
return (0);
}
/*
* Skip this host if it sends a 5xx greeting.
*/
if (ch == '5' && var_smtp_skip_5xx_greeting) {
smtp_site_fail(state, 450, "connect to %s[%s] port %u: "
"server refused mail service",
addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
vstream_fclose(stream);
return (0);
}
return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr))); return (smtp_session_alloc(stream, addr->name, inet_ntoa(sin.sin_addr)));
} }
@@ -267,7 +245,6 @@ static char *smtp_parse_destination(char *destination, char *def_service,
int smtp_connect(SMTP_STATE *state) int smtp_connect(SMTP_STATE *state)
{ {
VSTRING *why = vstring_alloc(100);
DELIVER_REQUEST *request = state->request; DELIVER_REQUEST *request = state->request;
char *dest_buf; char *dest_buf;
char *host; char *host;
@@ -276,27 +253,41 @@ int smtp_connect(SMTP_STATE *state)
ARGV *sites; ARGV *sites;
char *dest; char *dest;
char **cpp; char **cpp;
int found_myself;
DNS_RR *addr_list; DNS_RR *addr_list;
DNS_RR *addr; DNS_RR *addr;
/* /*
* First try to deliver to the indicated destination, then try to deliver * First try to deliver to the indicated destination, then try to deliver
* to the optional fall-back relays. Sanity check in case we allow the * to the optional fall-back relays.
* primary destination to be a list (we did for some time in the past).
* *
* After a soft error, log recipient deferrals only when there are no * Future proofing: do a null destination sanity check in case we allow the
* further possibilities to deliver. * primary destination to be a list, as it could be just a bunch of
* separators.
*/ */
sites = argv_alloc(1); sites = argv_alloc(1);
argv_add(sites, request->nexthop, (char *) 0); argv_add(sites, request->nexthop, (char *) 0);
if (sites->argc == 0) if (sites->argc == 0)
msg_panic("null destination: \"%s\"", request->nexthop); msg_panic("null destination: \"%s\"", request->nexthop);
argv_split_append(sites, var_fallback_relay, ", \t\r\n"); if (*var_fallback_relay)
argv_split_append(sites, var_fallback_relay, ", \t\r\n");
/*
* Don't give up after any soft error until we have tried all servers.
*
* Don't give up after a hard host lookup error until we have tried the
* fallback relay servers.
*
* Don't bounce mail after host lookup problems with a relayhost or with
* fallback relays.
*
* All this means that error handling and error reporting depends on whether
* there are more mail servers (state->final_server), or whether we're
* looking up a relayhost or fallback relay (state->backup_server).
*/
for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) { for (cpp = sites->argv; (dest = *cpp) != 0; cpp++) {
found_myself = 0; state->final_server = (cpp[1] == 0);
state->final = (cpp[1] == 0); state->backup_server =
(cpp > sites->argv || strcmp(request->nexthop, var_relayhost) == 0);
/* /*
* Parse the destination. Default is to use the SMTP port. Look up * Parse the destination. Default is to use the SMTP port. Look up
@@ -307,59 +298,21 @@ int smtp_connect(SMTP_STATE *state)
if (msg_verbose) if (msg_verbose)
msg_info("connecting to \"%s\" port \"%d\"", host, ntohs(port)); msg_info("connecting to \"%s\" port \"%d\"", host, ntohs(port));
if (var_disable_dns || *dest == '[') { if (var_disable_dns || *dest == '[') {
addr_list = smtp_host_addr(host, why); addr_list = smtp_host_addr(state, host);
} else { } else {
addr_list = smtp_domain_addr(host, why, &found_myself); addr_list = smtp_domain_addr(state, host);
} }
myfree(dest_buf); myfree(dest_buf);
/* /*
* Handle host lookup problems. XXX It would be nice if the address * No address list. The mail has / has not been delivered. What to do
* lookup routines could do their own smtp_site_fail() calls instead * next (skip remaining hosts / try to deliver) is recorded in the
* of having us make sense of things from a distance. The * state->final_server attribute.
* complication is that an unrecoverable host lookup error may still
* be followed by an attempt to deliver via a fallback relay.
*/ */
if (addr_list == 0) { if (addr_list == 0) {
if (state->backup_server)
/* msg_warn("%s or %s configuration problem",
* Mail loops back to myself. An smtp_errno of OK means that we VAR_RELAYHOST, VAR_FALLBACK_RELAY);
* should hand off the mail to a local transport. This hand-off
* should not happen with fallback relays.
*/
if (smtp_errno == SMTP_OK && cpp == sites->argv) {
state->status =
deliver_pass_all(MAIL_CLASS_PRIVATE, var_bestmx_transp,
request);
break;
}
if (found_myself) {
smtp_site_fail(state, 450,
"%s: %s", request->queue_id, vstring_str(why));
break;
}
/*
* Pay attention to what could be configuration problems, and
* pretend that these are recoverable rather than bouncing the
* mail.
*/
if (strcmp(request->nexthop, var_relayhost) == 0) {
msg_warn("%s configuration problem: %s",
VAR_RELAYHOST, var_relayhost);
smtp_site_fail(state, 450,
"%s: %s", request->queue_id, vstring_str(why));
continue;
}
if (cpp > sites->argv && sites->argc > 1) {
msg_warn("%s problem: %s",
VAR_FALLBACK_RELAY, var_fallback_relay);
smtp_site_fail(state, 450,
"%s: %s", request->queue_id, vstring_str(why));
continue;
}
smtp_site_fail(state, cpp[1] || smtp_errno == SMTP_RETRY ? 450 : 550,
"%s: %s", request->queue_id, vstring_str(why));
} }
/* /*
@@ -371,10 +324,10 @@ int smtp_connect(SMTP_STATE *state)
*/ */
for (addr = addr_list; addr; addr = addr->next) { for (addr = addr_list; addr; addr = addr->next) {
if ((state->session = smtp_connect_addr(state, addr, port)) != 0) { if ((state->session = smtp_connect_addr(state, addr, port)) != 0) {
state->final_server = (cpp[1] == 0 && addr->next == 0);
state->status = 0; state->status = 0;
state->session->best = (addr->pref == addr_list->pref); state->session->best = (addr->pref == addr_list->pref);
debug_peer_check(state->session->host, state->session->addr); debug_peer_check(state->session->host, state->session->addr);
state->final = (cpp[1] == 0 && addr->next == 0);
if (smtp_helo(state) == 0) if (smtp_helo(state) == 0)
smtp_xfer(state); smtp_xfer(state);
if (state->history != 0 if (state->history != 0
@@ -384,17 +337,23 @@ int smtp_connect(SMTP_STATE *state)
/* XXX smtp_xfer() may abort in the middle of DATA. */ /* XXX smtp_xfer() may abort in the middle of DATA. */
smtp_session_free(state->session); smtp_session_free(state->session);
debug_peer_restore(); debug_peer_restore();
if (state->status == 0) if (state->status == 0 || state->final_server)
break; break;
} }
} }
dns_rr_free(addr_list); dns_rr_free(addr_list);
/*
* In case someone has raised the "final server" flag before we have
* tried all fallback servers.
*/
if (state->final_server)
break;
} }
/* /*
* Cleanup. * Cleanup.
*/ */
vstring_free(why);
argv_free(sites); argv_free(sites);
return (state->status); return (state->status);
} }

View File

@@ -197,10 +197,13 @@ int smtp_helo(SMTP_STATE *state)
/* /*
* Read and parse the server's SMTP greeting banner. * Read and parse the server's SMTP greeting banner.
*/ */
if (((resp = smtp_chat_resp(state))->code / 100) != 2) if ((resp = smtp_chat_resp(state))->code / 100 != 2) {
if (var_smtp_skip_5xx_greeting && resp->code / 100 == '5')
resp->code -= 100;
return (smtp_site_fail(state, resp->code, return (smtp_site_fail(state, resp->code,
"host %s refused to talk to me: %s", "host %s refused to talk to me: %s",
session->namaddr, translit(resp->str, "\n", " "))); session->namaddr, translit(resp->str, "\n", " ")));
}
/* /*
* XXX Some PIX firewall versions require flush before ".<CR><LF>" so it * XXX Some PIX firewall versions require flush before ".<CR><LF>" so it

View File

@@ -72,7 +72,8 @@ SMTP_STATE *smtp_state_alloc(void)
state->size_limit = 0; state->size_limit = 0;
state->space_left = 0; state->space_left = 0;
state->mime_state = 0; state->mime_state = 0;
state->final = 0; state->final_server = 0;
state->backup_server = 0;
return (state); return (state);
} }

View File

@@ -44,35 +44,53 @@
/* would suffer the same problem and just cause more trouble. /* would suffer the same problem and just cause more trouble.
/* /*
/* In case of a soft error, action depends on whether there are /* In case of a soft error, action depends on whether there are
/* more possibilities to deliver (log one generic record) or whether /* more mail servers (log an informational record only and try
/* the error happens with the last possibility (log each recipient). /* the other servers) or whether this is the final server (log
/* recipient delivery status records).
/*
/* In the case of a hard error that affects all recipients,
/* recipient delivery status records are logged, and the
/* final server flag is raised so that any remaining mail
/* servers are skipped.
/* /*
/* smtp_site_fail() handles the case where the program fails to /* smtp_site_fail() handles the case where the program fails to
/* complete the initial SMTP handshake: the server is not reachable, /* complete the initial SMTP handshake: the server is not reachable,
/* is not running, does not want talk to us, or we talk to ourselves. /* is not running, does not want talk to us, or we talk to ourselves.
/* The \fIcode\fR gives an error status code; the \fIformat\fR /* The \fIcode\fR gives an error status code; the \fIformat\fR
/* argument gives a textual description. The policy is: soft /* argument gives a textual description.
/* error: defer delivery of all messages to this domain; hard /* The policy is: soft error, non-final server: log an informational
/* error: bounce all recipients of this message. /* record why the host is being skipped; soft error, final server:
/* defer delivery of all remaining recipients; hard error: bounce all
/* remaining recipients and set the "final server" flag so that any
/* remaining mail servers will be skipped.
/* The result is non-zero. /* The result is non-zero.
/* /*
/* smtp_mesg_fail() handles the case where the smtp server /* smtp_mesg_fail() handles the case where the smtp server
/* does not accept the sender address or the message data. /* does not accept the sender address or the message data.
/* The policy is: soft errors: defer delivery of this message; /* The policy is: soft error, non-final server: log an informational
/* hard error: bounce all recipients of this message. /* record why the host is being skipped; soft error, final server:
/* defer delivery of all remaining recipients; hard error: bounce all
/* remaining recipients and set the "final server" flag so that any
/* remaining mail servers will be skipped.
/* The result is non-zero. /* The result is non-zero.
/* /*
/* smtp_rcpt_fail() handles the case where a recipient is not /* smtp_rcpt_fail() handles the case where a recipient is not
/* accepted by the server for reasons other than that the server /* accepted by the server for reasons other than that the server
/* recipient limit is reached. The policy is: soft error: defer /* recipient limit is reached.
/* delivery to this recipient; hard error: bounce this recipient. /* The policy is: soft error, non-final server: log an informational
/* record why the recipient is being skipped; soft error, final server:
/* defer delivery of this recipient; hard error: bounce this
/* recipient. This routine does not change the "final server" flag.
/* /*
/* smtp_stream_except() handles the exceptions generated by /* smtp_stream_except() handles the exceptions generated by
/* the smtp_stream(3) module (i.e. timeouts and I/O errors). /* the smtp_stream(3) module (i.e. timeouts and I/O errors).
/* The \fIexception\fR argument specifies the type of problem. /* The \fIexception\fR argument specifies the type of problem.
/* The \fIdescription\fR argument describes at what stage of /* The \fIdescription\fR argument describes at what stage of
/* the SMTP dialog the problem happened. The policy is to defer /* the SMTP dialog the problem happened.
/* delivery of all messages to the same domain. The result is non-zero. /* The policy is: non-final server: log an informational record
/* with the reason why the host is being skipped; final server:
/* defer delivery of all remaining recipients.
/* The result is non-zero.
/* DIAGNOSTICS /* DIAGNOSTICS
/* Panic: unknown exception code. /* Panic: unknown exception code.
/* SEE ALSO /* SEE ALSO
@@ -141,7 +159,7 @@ static void smtp_check_code(SMTP_STATE *state, int code)
state->error_mask |= MAIL_ERROR_PROTOCOL; state->error_mask |= MAIL_ERROR_PROTOCOL;
} }
/* smtp_site_fail - defer site or bounce recipients */ /* smtp_site_fail - skip site, defer all recipients, or bounce all recipients */
int smtp_site_fail(SMTP_STATE *state, int code, char *format,...) int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
{ {
@@ -162,17 +180,18 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
va_end(ap); va_end(ap);
/* /*
* Don't log deferred recipients yet when there are still untried * Don't defer the recipients just yet when there are still more mail
* possibilities to deliver. Just log why we're abandoning this host. * servers. Just log something informative to show why we're skipping
* this host.
*/ */
if (soft_error && state->final == 0) { if (soft_error && state->final_server == 0) {
msg_info("%s: %s", request->queue_id, vstring_str(why)); msg_info("%s: %s", request->queue_id, vstring_str(why));
state->status |= -1; state->status |= -1;
} }
/* /*
* If this is a soft error, postpone further deliveries to this domain. * Defer or bounce all the remaining recipients and raise the final mail
* Otherwise, generate a bounce record for each recipient. * server flag.
*/ */
else { else {
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) { for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
@@ -192,7 +211,9 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
} }
if (soft_error && request->hop_status == 0) if (soft_error && request->hop_status == 0)
request->hop_status = mystrdup(vstring_str(why)); request->hop_status = mystrdup(vstring_str(why));
state->final_server = 1;
} }
smtp_check_code(state, code);
/* /*
* Cleanup. * Cleanup.
@@ -201,7 +222,7 @@ int smtp_site_fail(SMTP_STATE *state, int code, char *format,...)
return (-1); return (-1);
} }
/* smtp_mesg_fail - defer message or bounce all recipients */ /* smtp_mesg_fail - skip site, defer all recipients, or bounce all recipients */
int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...) int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
{ {
@@ -222,17 +243,18 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
va_end(ap); va_end(ap);
/* /*
* Don't log deferred recipients yet when there are still untried * Don't defer the recipients just yet when there are still more mail
* possibilities to deliver. Just log why we're abandoning this host. * servers. Just log something informative to show why we're skipping
* this host.
*/ */
if (soft_error && state->final == 0) { if (soft_error && state->final_server == 0) {
msg_info("%s: %s", request->queue_id, vstring_str(why)); msg_info("%s: %s", request->queue_id, vstring_str(why));
state->status |= -1; state->status |= -1;
} }
/* /*
* If this is a soft error, postpone delivery of this message. Otherwise, * Defer or bounce all the remaining recipients and raise the final mail
* generate a bounce record for each recipient. * server flag.
*/ */
else { else {
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) { for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {
@@ -250,6 +272,7 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
} }
state->status |= status; state->status |= status;
} }
state->final_server = 1;
} }
smtp_check_code(state, code); smtp_check_code(state, code);
@@ -260,7 +283,7 @@ int smtp_mesg_fail(SMTP_STATE *state, int code, char *format,...)
return (-1); return (-1);
} }
/* smtp_rcpt_fail - defer or bounce recipient */ /* smtp_rcpt_fail - skip, defer, or bounce recipient */
void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt, void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
char *format,...) char *format,...)
@@ -272,10 +295,11 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
va_list ap; va_list ap;
/* /*
* Don't log deferred recipients yet when there are still untried * Don't defer this recipient record just yet when there are still more
* possibilities to deliver. * mail servers. Just log something informative to show why we're
* skipping this recipient now.
*/ */
if (soft_error && state->final == 0) { if (soft_error && state->final_server == 0) {
VSTRING *buf = vstring_alloc(10); VSTRING *buf = vstring_alloc(10);
va_start(ap, format); va_start(ap, format);
@@ -287,8 +311,15 @@ void smtp_rcpt_fail(SMTP_STATE *state, int code, RECIPIENT *rcpt,
} }
/* /*
* If this is a soft error, postpone delivery to this recipient. * Defer or bounce this specific recipient.
* Otherwise, generate a bounce record for this recipient. *
* If this is a hard error, we must not raise the final mail server flag. We
* may still make another SMTP connection to deliver deferred recipients.
*
* If this is a soft error, we got here because the final mail server flag
* was already set.
*
* So don't touch that final mail server flag!
*/ */
else { else {
va_start(ap, format); va_start(ap, format);
@@ -333,17 +364,16 @@ int smtp_stream_except(SMTP_STATE *state, int code, char *description)
} }
/* /*
* Don't log deferred recipients yet when there are still untried * Don't defer the recipients just yet when there are still more mail
* possibilities to deliver. Just log why we're abandoning this host. * servers. Just log why we're abandoning this host.
*/ */
if (state->final == 0) { if (state->final_server == 0) {
msg_info("%s: %s", request->queue_id, vstring_str(why)); msg_info("%s: %s", request->queue_id, vstring_str(why));
state->status |= -1; state->status |= -1;
} }
/* /*
* At this point, the status of individual recipients remains unresolved. * Final server. Defer all the remaining recipients.
* All we know is that we should stay away from this host for a while.
*/ */
else { else {
for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) { for (nrcpt = 0; nrcpt < request->rcpt_list.len; nrcpt++) {

View File

@@ -154,6 +154,7 @@
#include <lber.h> #include <lber.h>
#include <ldap.h> #include <ldap.h>
#include <string.h> #include <string.h>
#include <ctype.h>
/* /*
* Older APIs have weird memory freeing behavior. * Older APIs have weird memory freeing behavior.
@@ -259,8 +260,17 @@ static void dict_ldap_timeout(int unused_sig)
static void dict_ldap_logprint(LDAP_CONST char *data) static void dict_ldap_logprint(LDAP_CONST char *data)
{ {
char *myname = "dict_ldap_debug"; char *myname = "dict_ldap_debug";
char *buf,
*p;
msg_info("%s: %s", myname, data); buf = mystrdup(data);
if (*buf) {
p = buf + strlen(buf) - 1;
while (p - buf >= 0 && ISSPACE(*p))
*p-- = 0;
}
msg_info("%s: %s", myname, buf);
myfree(buf);
} }
@@ -481,6 +491,21 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
#endif #endif
#if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN)
if (dict_ldap->debuglevel > 0 &&
ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN,
(LDAP_CONST *) dict_ldap_logprint) != LBER_OPT_SUCCESS)
msg_warn("%s: Unable to set ber logprint function.", myname);
#if defined(LBER_OPT_DEBUG_LEVEL)
if (ber_set_option(NULL, LBER_OPT_DEBUG_LEVEL,
&(dict_ldap->debuglevel)) != LBER_OPT_SUCCESS)
msg_warn("%s: Unable to set BER debug level.", myname);
#endif
if (ldap_set_option(NULL, LDAP_OPT_DEBUG_LEVEL,
&(dict_ldap->debuglevel)) != LDAP_OPT_SUCCESS)
msg_warn("%s: Unable to set LDAP debug level.", myname);
#endif
dict_errno = 0; dict_errno = 0;
if (msg_verbose) if (msg_verbose)
@@ -573,16 +598,6 @@ static int dict_ldap_connect(DICT_LDAP *dict_ldap)
&(dict_ldap->dereference)) != LDAP_OPT_SUCCESS) &(dict_ldap->dereference)) != LDAP_OPT_SUCCESS)
msg_warn("%s: Unable to set dereference option.", myname); msg_warn("%s: Unable to set dereference option.", myname);
#if defined(LDAP_OPT_DEBUG_LEVEL) && defined(LBER_OPT_LOG_PRINT_FN)
if (dict_ldap->debuglevel > 0 &&
ber_set_option(NULL, LBER_OPT_LOG_PRINT_FN,
(LDAP_CONST *) dict_ldap_logprint) != LBER_OPT_SUCCESS)
msg_warn("%s: Unable to set ber logprint function.", myname);
if (ldap_set_option(dict_ldap->ld, LDAP_OPT_DEBUG_LEVEL,
&(dict_ldap->debuglevel)) != LDAP_OPT_SUCCESS)
msg_warn("%s: Unable to set LDAP debug level.", myname);
#endif
/* Chase referrals. */ /* Chase referrals. */
/* /*