mirror of
https://github.com/vdukhovni/postfix
synced 2025-08-31 14:17:41 +00:00
postfix-1.1.12-20021213
This commit is contained in:
committed by
Viktor Dukhovni
parent
230884f7d8
commit
ac8e713e62
@@ -7401,6 +7401,23 @@ Apologies for any names omitted.
|
||||
shooting a little easier. Files: smtpd/smtpd_check.c,
|
||||
trivial-rewrite/resolve.c.
|
||||
|
||||
20021213
|
||||
|
||||
Cleanup: transport map entries with null nexthop ignored
|
||||
relayhost settings. Making the code simpler also made it
|
||||
more correct. Files: trivial-rewrite/resolve.c,
|
||||
trivial-rewrite/transport.c.
|
||||
|
||||
Feature: "helpful_warnings" (default: yes) that can be
|
||||
turned off if you really know what you're doing and want
|
||||
to eliminate some unnecessary work.
|
||||
|
||||
Feature: enforcement of master.cf process limits for
|
||||
processes such as qmgr and pickup that must run alone, and
|
||||
processes such as cleanup and bounce that must run without
|
||||
explicit process count limit. If an incorrect process limit
|
||||
is specified in master.cf the service aborts.
|
||||
|
||||
Open problems:
|
||||
|
||||
Low: after successful delivery, per-queue window += 1/window,
|
||||
|
@@ -604,7 +604,7 @@ href="transport.5.html">transport</a> table lookups.
|
||||
|
||||
<p>
|
||||
|
||||
Important: do not specify a relayhost entry, or else mail for
|
||||
Important: do not specify a relayhost in main.cf, or else mail for
|
||||
internal destinations will still be given to the relayhost.
|
||||
|
||||
<p>
|
||||
|
@@ -443,5 +443,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_STR_TABLE, str_table,
|
||||
MAIL_SERVER_TIME_TABLE, time_table,
|
||||
MAIL_SERVER_POST_INIT, post_jail_init,
|
||||
MAIL_SERVER_UNLIMITED,
|
||||
0);
|
||||
}
|
||||
|
@@ -338,5 +338,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_POST_INIT, cleanup_post_jail,
|
||||
MAIL_SERVER_PRE_ACCEPT, pre_accept,
|
||||
MAIL_SERVER_IN_FLOW_DELAY,
|
||||
MAIL_SERVER_UNLIMITED,
|
||||
0);
|
||||
}
|
||||
|
@@ -675,5 +675,6 @@ int main(int argc, char **argv)
|
||||
single_server_main(argc, argv, flush_service,
|
||||
MAIL_SERVER_TIME_TABLE, time_table,
|
||||
MAIL_SERVER_PRE_INIT, pre_jail_init,
|
||||
MAIL_SERVER_UNLIMITED,
|
||||
0);
|
||||
}
|
||||
|
@@ -14,6 +14,7 @@
|
||||
/* char *var_transit_origin;
|
||||
/* char *var_transit_dest;
|
||||
/* char *var_mail_name;
|
||||
/* int var_helpful_warnings;
|
||||
/* char *var_syslog_name;
|
||||
/* char *var_mail_owner;
|
||||
/* uid_t var_owner_uid;
|
||||
@@ -167,6 +168,7 @@ char *var_relayhost;
|
||||
char *var_transit_origin;
|
||||
char *var_transit_dest;
|
||||
char *var_mail_name;
|
||||
int var_helpful_warnings;
|
||||
char *var_syslog_name;
|
||||
char *var_mail_owner;
|
||||
uid_t var_owner_uid;
|
||||
@@ -511,6 +513,7 @@ void mail_params_init()
|
||||
VAR_STRICT_ENCODING, DEF_STRICT_ENCODING, &var_strict_encoding,
|
||||
VAR_DISABLE_MIME_INPUT, DEF_DISABLE_MIME_INPUT, &var_disable_mime_input,
|
||||
VAR_DISABLE_MIME_OCONV, DEF_DISABLE_MIME_OCONV, &var_disable_mime_oconv,
|
||||
VAR_HELPFUL_WARNINGS, DEF_HELPFUL_WARNINGS, &var_helpful_warnings,
|
||||
0,
|
||||
};
|
||||
const char *cp;
|
||||
|
@@ -23,6 +23,13 @@ typedef int bool;
|
||||
#define DEF_MAIL_NAME "Postfix"
|
||||
extern char *var_mail_name;
|
||||
|
||||
/*
|
||||
* You want to be helped or not.
|
||||
*/
|
||||
#define VAR_HELPFUL_WARNINGS "helpful_warnings"
|
||||
#define DEF_HELPFUL_WARNINGS 1
|
||||
extern bool var_helpful_warnings;
|
||||
|
||||
/*
|
||||
* What problem classes should be reported to the postmaster via email.
|
||||
* Default is bad problems only. See mail_error(3). Even when mail notices
|
||||
|
@@ -20,7 +20,7 @@
|
||||
* Patches change the patchlevel and the release date. Snapshots change the
|
||||
* release date only, unless they include the same bugfix as a patch release.
|
||||
*/
|
||||
#define MAIL_RELEASE_DATE "20021212"
|
||||
#define MAIL_RELEASE_DATE "20021213"
|
||||
|
||||
#define VAR_MAIL_VERSION "mail_version"
|
||||
#define DEF_MAIL_VERSION "1.1.12-" MAIL_RELEASE_DATE
|
||||
|
@@ -27,6 +27,8 @@
|
||||
#define MAIL_SERVER_LOOP 12
|
||||
#define MAIL_SERVER_EXIT 13
|
||||
#define MAIL_SERVER_PRE_ACCEPT 14
|
||||
#define MAIL_SERVER_SOLITARY 15
|
||||
#define MAIL_SERVER_UNLIMITED 16
|
||||
|
||||
#define MAIL_SERVER_IN_FLOW_DELAY 20
|
||||
|
||||
|
@@ -402,6 +402,8 @@ MASTER_SERV *get_master_ent()
|
||||
argv_add(serv->args, command, (char *) 0);
|
||||
if (serv->max_proc == 1)
|
||||
argv_add(serv->args, "-l", (char *) 0);
|
||||
if (serv->max_proc == 0)
|
||||
argv_add(serv->args, "-z", (char *) 0);
|
||||
if (strcmp(basename(command), name) != 0)
|
||||
argv_add(serv->args, "-n", name, (char *) 0);
|
||||
argv_add(serv->args, "-t", transport, (char *) 0);
|
||||
|
@@ -98,6 +98,10 @@
|
||||
/* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)"
|
||||
/* Pause $in_flow_delay seconds when no "mail flow control token"
|
||||
/* is available. A token is consumed for each connection request.
|
||||
/* .IP MAIL_SERVER_SOLITARY
|
||||
/* This service must be configured with process limit of 1.
|
||||
/* .IP MAIL_SERVER_UNLIMITED
|
||||
/* This service must be configured with process limit of 0.
|
||||
/* .PP
|
||||
/* multi_server_disconnect() should be called by the application
|
||||
/* when a client disconnects.
|
||||
@@ -388,6 +392,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
||||
char *lock_path;
|
||||
VSTRING *why;
|
||||
int alone = 0;
|
||||
int zerolimit = 0;
|
||||
WATCHDOG *watchdog;
|
||||
char *oval;
|
||||
|
||||
@@ -436,7 +441,7 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
||||
* stderr, because no-one is going to see them.
|
||||
*/
|
||||
opterr = 0;
|
||||
while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) {
|
||||
while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uvz")) > 0) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
root_dir = "setme";
|
||||
@@ -477,6 +482,9 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
case 'z':
|
||||
zerolimit = 1;
|
||||
break;
|
||||
default:
|
||||
msg_fatal("invalid option: %c", c);
|
||||
break;
|
||||
@@ -527,6 +535,16 @@ NORETURN multi_server_main(int argc, char **argv, MULTI_SERVER_FN service,...)
|
||||
case MAIL_SERVER_IN_FLOW_DELAY:
|
||||
multi_server_in_flow_delay = 1;
|
||||
break;
|
||||
case MAIL_SERVER_SOLITARY:
|
||||
if (!alone)
|
||||
msg_fatal("service %s requires a process limit of 1",
|
||||
service_name);
|
||||
break;
|
||||
case MAIL_SERVER_UNLIMITED:
|
||||
if (!zerolimit)
|
||||
msg_fatal("service %s requires a process limit of 0",
|
||||
service_name);
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: unknown argument type: %d", myname, key);
|
||||
}
|
||||
|
@@ -95,6 +95,10 @@
|
||||
/* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)"
|
||||
/* Pause $in_flow_delay seconds when no "mail flow control token"
|
||||
/* is available. A token is consumed for each connection request.
|
||||
/* .IP MAIL_SERVER_SOLITARY
|
||||
/* This service must be configured with process limit of 1.
|
||||
/* .IP MAIL_SERVER_UNLIMITED
|
||||
/* This service must be configured with process limit of 0.
|
||||
/* .PP
|
||||
/* The var_use_limit variable limits the number of clients that
|
||||
/* a server can service before it commits suicide.
|
||||
@@ -235,7 +239,7 @@ static void single_server_wakeup(int fd)
|
||||
close_on_exec(fd, CLOSE_ON_EXEC);
|
||||
stream = vstream_fdopen(fd, O_RDWR);
|
||||
tmp = concatenate(single_server_name, " socket", (char *) 0);
|
||||
vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
|
||||
vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END);
|
||||
myfree(tmp);
|
||||
timed_ipc_setup(stream);
|
||||
if (master_notify(var_pid, MASTER_STAT_TAKEN) < 0)
|
||||
@@ -344,6 +348,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
||||
char *lock_path;
|
||||
VSTRING *why;
|
||||
int alone = 0;
|
||||
int zerolimit = 0;
|
||||
WATCHDOG *watchdog;
|
||||
char *oval;
|
||||
|
||||
@@ -392,7 +397,7 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
||||
* stderr, because no-one is going to see them.
|
||||
*/
|
||||
opterr = 0;
|
||||
while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) {
|
||||
while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uvz")) > 0) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
root_dir = "setme";
|
||||
@@ -433,6 +438,9 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
case 'z':
|
||||
zerolimit = 1;
|
||||
break;
|
||||
default:
|
||||
msg_fatal("invalid option: %c", c);
|
||||
break;
|
||||
@@ -483,6 +491,16 @@ NORETURN single_server_main(int argc, char **argv, SINGLE_SERVER_FN service,...)
|
||||
case MAIL_SERVER_IN_FLOW_DELAY:
|
||||
single_server_in_flow_delay = 1;
|
||||
break;
|
||||
case MAIL_SERVER_SOLITARY:
|
||||
if (!alone)
|
||||
msg_fatal("service %s requires a process limit of 1",
|
||||
service_name);
|
||||
break;
|
||||
case MAIL_SERVER_UNLIMITED:
|
||||
if (!zerolimit)
|
||||
msg_fatal("service %s requires a process limit of 0",
|
||||
service_name);
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: unknown argument type: %d", myname, key);
|
||||
}
|
||||
|
@@ -102,6 +102,10 @@
|
||||
/* .IP "MAIL_SERVER_IN_FLOW_DELAY (none)"
|
||||
/* Pause $in_flow_delay seconds when no "mail flow control token"
|
||||
/* is available. A token is consumed for each connection request.
|
||||
/* .IP MAIL_SERVER_SOLITARY
|
||||
/* This service must be configured with process limit of 1.
|
||||
/* .IP MAIL_SERVER_UNLIMITED
|
||||
/* This service must be configured with process limit of 0.
|
||||
/* .PP
|
||||
/* The var_use_limit variable limits the number of clients that
|
||||
/* a server can service before it commits suicide.
|
||||
@@ -340,6 +344,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
||||
char *lock_path;
|
||||
VSTRING *why;
|
||||
int alone = 0;
|
||||
int zerolimit = 0;
|
||||
WATCHDOG *watchdog;
|
||||
char *oval;
|
||||
|
||||
@@ -388,7 +393,7 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
||||
* stderr, because no-one is going to see them.
|
||||
*/
|
||||
opterr = 0;
|
||||
while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uv")) > 0) {
|
||||
while ((c = GETOPT(argc, argv, "cDi:lm:n:o:s:St:uvz")) > 0) {
|
||||
switch (c) {
|
||||
case 'c':
|
||||
root_dir = "setme";
|
||||
@@ -429,6 +434,9 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
||||
case 'v':
|
||||
msg_verbose++;
|
||||
break;
|
||||
case 'z':
|
||||
zerolimit = 1;
|
||||
break;
|
||||
default:
|
||||
msg_fatal("invalid option: %c", c);
|
||||
break;
|
||||
@@ -479,6 +487,16 @@ NORETURN trigger_server_main(int argc, char **argv, TRIGGER_SERVER_FN service,..
|
||||
case MAIL_SERVER_IN_FLOW_DELAY:
|
||||
trigger_server_in_flow_delay = 1;
|
||||
break;
|
||||
case MAIL_SERVER_SOLITARY:
|
||||
if (!alone)
|
||||
msg_fatal("service %s requires a process limit of 1",
|
||||
service_name);
|
||||
break;
|
||||
case MAIL_SERVER_UNLIMITED:
|
||||
if (!zerolimit)
|
||||
msg_fatal("service %s requires a process limit of 0",
|
||||
service_name);
|
||||
break;
|
||||
default:
|
||||
msg_panic("%s: unknown argument type: %d", myname, key);
|
||||
}
|
||||
|
@@ -569,5 +569,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_POST_INIT, qmgr_post_init,
|
||||
MAIL_SERVER_LOOP, qmgr_loop,
|
||||
MAIL_SERVER_PRE_ACCEPT, pre_accept,
|
||||
MAIL_SERVER_SOLITARY,
|
||||
0);
|
||||
}
|
||||
|
@@ -290,7 +290,7 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_PEER *peer, QMGR_MESSAGE *message)
|
||||
* XXX This code does not detect the case that the active queue is being
|
||||
* starved because incoming mail is pounding the disk.
|
||||
*/
|
||||
if (var_qmgr_clog_warn_time > 0) {
|
||||
if (var_helpful_warnings && var_qmgr_clog_warn_time > 0) {
|
||||
int queue_length = queue->todo_refcount + queue->busy_refcount;
|
||||
time_t now;
|
||||
QMGR_TRANSPORT *transport;
|
||||
|
@@ -521,5 +521,6 @@ int main(int argc, char **argv)
|
||||
trigger_server_main(argc, argv, pickup_service,
|
||||
MAIL_SERVER_STR_TABLE, str_table,
|
||||
MAIL_SERVER_POST_INIT, drop_privileges,
|
||||
MAIL_SERVER_SOLITARY,
|
||||
0);
|
||||
}
|
||||
|
@@ -515,5 +515,6 @@ int main(int argc, char **argv)
|
||||
MAIL_SERVER_POST_INIT, qmgr_post_init,
|
||||
MAIL_SERVER_LOOP, qmgr_loop,
|
||||
MAIL_SERVER_PRE_ACCEPT, pre_accept,
|
||||
MAIL_SERVER_SOLITARY,
|
||||
0);
|
||||
}
|
||||
|
@@ -229,7 +229,7 @@ QMGR_ENTRY *qmgr_entry_create(QMGR_QUEUE *queue, QMGR_MESSAGE *message)
|
||||
* XXX This code does not detect the case that the active queue is being
|
||||
* starved because incoming mail is pounding the disk.
|
||||
*/
|
||||
if (var_qmgr_clog_warn_time > 0) {
|
||||
if (var_helpful_warnings && var_qmgr_clog_warn_time > 0) {
|
||||
int queue_length = queue->todo_refcount + queue->busy_refcount;
|
||||
time_t now;
|
||||
QMGR_TRANSPORT *transport;
|
||||
|
@@ -230,9 +230,18 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
* With virtual, relay, or other non-local destinations, give the highest
|
||||
* precedence to delivery transport associated next-hop information.
|
||||
*
|
||||
* XXX With the virtual mailbox transport, set the nexthop information to
|
||||
* $myhostname, so that in default configurations the virtual delivery
|
||||
* agent will not use separate queues for every $virtual_mailbox_domains
|
||||
* domain name. That prevents anomalies where many low-traffic domains
|
||||
* starve a high-traffic domain.
|
||||
*
|
||||
* XXX Nag if the domain is listed in multiple domain lists. The effect is
|
||||
* implementation defined, and may break when internals change.
|
||||
*/
|
||||
#define VIRT_ALIAS_TRANSPORT var_error_transport
|
||||
#define VIRT_ALIAS_NEXTHOP "User unknown in virtual alias table"
|
||||
|
||||
dict_errno = 0;
|
||||
if (domain != 0) {
|
||||
tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL);
|
||||
@@ -242,12 +251,13 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
*flags |= RESOLVE_FLAG_ERROR;
|
||||
if (virt_alias_doms
|
||||
&& string_list_match(virt_alias_doms, STR(nexthop))) {
|
||||
if (virt_mailbox_doms
|
||||
if (var_helpful_warnings
|
||||
&& virt_mailbox_doms
|
||||
&& string_list_match(virt_mailbox_doms, STR(nexthop)))
|
||||
msg_warn("do not list domain %s in BOTH %s and %s",
|
||||
STR(nexthop), VAR_VIRT_ALIAS_DOMS, VAR_VIRT_MAILBOX_DOMS);
|
||||
vstring_strcpy(channel, var_error_transport);
|
||||
vstring_strcpy(nexthop, "User unknown in virtual alias table");
|
||||
vstring_strcpy(channel, VIRT_ALIAS_TRANSPORT);
|
||||
vstring_strcpy(nexthop, VIRT_ALIAS_NEXTHOP);
|
||||
blame = VAR_ERROR_TRANSPORT;
|
||||
*flags |= RESOLVE_CLASS_ALIAS;
|
||||
} else if (dict_errno != 0) {
|
||||
@@ -256,6 +266,7 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
} else if (virt_mailbox_doms
|
||||
&& string_list_match(virt_mailbox_doms, STR(nexthop))) {
|
||||
vstring_strcpy(channel, var_virt_transport);
|
||||
vstring_strcpy(nexthop, var_myhostname);
|
||||
blame = VAR_VIRT_TRANSPORT;
|
||||
*flags |= RESOLVE_CLASS_VIRTUAL;
|
||||
} else if (dict_errno != 0) {
|
||||
@@ -275,28 +286,38 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
blame = VAR_DEF_TRANSPORT;
|
||||
*flags |= RESOLVE_CLASS_DEFAULT;
|
||||
}
|
||||
if (*var_relayhost)
|
||||
if (*var_relayhost) {
|
||||
vstring_strcpy(nexthop, var_relayhost);
|
||||
lowercase(STR(nexthop));
|
||||
}
|
||||
}
|
||||
if ((destination = split_at(STR(channel), ':')) != 0 && *destination)
|
||||
if ((destination = split_at(STR(channel), ':')) != 0 && *destination) {
|
||||
vstring_strcpy(nexthop, destination);
|
||||
lowercase(STR(nexthop));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Local delivery. Set up the default local transport and the default
|
||||
* next-hop hostname (myself).
|
||||
*
|
||||
* XXX Set the nexthop information to myhostname, so that the local delivery
|
||||
* agent does not get a queue for every domain name in $mydestination or
|
||||
* for every network address in $inet_interfaces.
|
||||
*
|
||||
* XXX Nag if the domain is listed in multiple domain lists. The effect is
|
||||
* implementation defined, and may break when internals change.
|
||||
*/
|
||||
else {
|
||||
if ((rcpt_domain = strrchr(STR(nextrcpt), '@')) != 0) {
|
||||
rcpt_domain++;
|
||||
if (virt_alias_doms
|
||||
if (var_helpful_warnings
|
||||
&& virt_alias_doms
|
||||
&& string_list_match(virt_alias_doms, rcpt_domain))
|
||||
msg_warn("do not list domain %s in BOTH %s and %s",
|
||||
rcpt_domain, VAR_MYDEST, VAR_VIRT_ALIAS_DOMS);
|
||||
if (virt_mailbox_doms
|
||||
if (var_helpful_warnings
|
||||
&& virt_mailbox_doms
|
||||
&& string_list_match(virt_mailbox_doms, rcpt_domain))
|
||||
msg_warn("do not list domain %s in BOTH %s and %s",
|
||||
rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS);
|
||||
@@ -337,6 +358,20 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Kludge for virtual alias domains. Their next-hop info is arbitrary
|
||||
* text that must not be passed on to regular delivery agents. So, if the
|
||||
* transport was changed, but the nexthop was not, copy over the local
|
||||
* hostname instead.
|
||||
*/
|
||||
#define STREQ(x, y) (strcmp((x), (y)) == 0)
|
||||
|
||||
if ((*flags & RESOLVE_FLAG_FAIL) == 0
|
||||
&& (*flags & RESOLVE_CLASS_ALIAS) != 0
|
||||
&& !STREQ(STR(channel), VIRT_ALIAS_TRANSPORT)
|
||||
&& STREQ(STR(nexthop), VIRT_ALIAS_NEXTHOP))
|
||||
vstring_strcpy(nexthop, var_myhostname);
|
||||
|
||||
/*
|
||||
* Bounce recipients that have moved, regardless of domain address class.
|
||||
* The downside of doing this here is that this table has no effect on
|
||||
@@ -345,13 +380,13 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
|
||||
*/
|
||||
#define IGNORE_ADDR_EXTENSION ((char **) 0)
|
||||
|
||||
if ((*flags & RESOLVE_FLAG_FAIL) == 0 && *var_relocated_maps != 0) {
|
||||
if ((*flags & RESOLVE_FLAG_FAIL) == 0 && relocated_maps != 0) {
|
||||
const char *newloc;
|
||||
|
||||
if ((newloc = mail_addr_find(relocated_maps, STR(nextrcpt),
|
||||
IGNORE_ADDR_EXTENSION)) != 0) {
|
||||
vstring_strcpy(channel, var_error_transport);
|
||||
vstring_sprintf(nexthop, "user has moved to %s", newloc);
|
||||
vstring_sprintf(nexthop, "User has moved to %s", newloc);
|
||||
} else if (dict_errno != 0) {
|
||||
msg_warn("%s lookup failure", VAR_RELOCATED_MAPS);
|
||||
*flags |= RESOLVE_FLAG_FAIL;
|
||||
|
@@ -75,6 +75,15 @@ static int transport_match_parent_style;
|
||||
static VSTRING *wildcard_channel;
|
||||
static VSTRING *wildcard_nexthop;
|
||||
|
||||
#define STR(x) vstring_str(x)
|
||||
|
||||
/*
|
||||
* Macro for consistent updates of the transport and nexthop results.
|
||||
*/
|
||||
#define UPDATE_IF_SPECIFIED(dst, src) do { \
|
||||
if ((src) && *(src)) vstring_strcpy((dst), (src)); \
|
||||
} while (0)
|
||||
|
||||
/* transport_init - pre-jail initialization */
|
||||
|
||||
void transport_init(void)
|
||||
@@ -84,14 +93,12 @@ void transport_init(void)
|
||||
transport_path = maps_create("transport", var_transport_maps,
|
||||
DICT_FLAG_LOCK);
|
||||
transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS);
|
||||
|
||||
}
|
||||
|
||||
/* find_transport_entry - look up and parse transport table entry */
|
||||
|
||||
static int find_transport_entry(const char *key, int flags,
|
||||
VSTRING *channel, VSTRING *nexthop,
|
||||
const char *def_nexthop)
|
||||
VSTRING *channel, VSTRING *nexthop)
|
||||
{
|
||||
char *saved_value;
|
||||
const char *host;
|
||||
@@ -115,27 +122,14 @@ static int find_transport_entry(const char *key, int flags,
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't do transport:user@domain until we have a way to pass the
|
||||
* recipient back to the application, and until we have verified that
|
||||
* this does not open security holes via, for example, regexp maps.
|
||||
* Nothing is supposed to trust a transport name, envelope recipient
|
||||
* address or next-hop hostname, but to be on the safe side we probably
|
||||
* should add some syntax sanity checks.
|
||||
* Can't do transport:user@domain because the right-hand side can have
|
||||
* arbitrary content (especially in the case of the error mailer).
|
||||
*/
|
||||
else {
|
||||
saved_value = mystrdup(value);
|
||||
if ((host = split_at(saved_value, ':')) != 0 && *host != 0) {
|
||||
#if 0
|
||||
if ((ratsign = strrchr(host, '@'))) {
|
||||
vstring_strcpy(recipient, host);
|
||||
vstring_strcpy(nexthop, ratsign + 1);
|
||||
} else
|
||||
#endif
|
||||
vstring_strcpy(nexthop, host);
|
||||
} else if (def_nexthop != 0)
|
||||
vstring_strcpy(nexthop, def_nexthop);
|
||||
if (*saved_value != 0)
|
||||
vstring_strcpy(channel, saved_value);
|
||||
host = split_at(saved_value, ':');
|
||||
UPDATE_IF_SPECIFIED(nexthop, host);
|
||||
UPDATE_IF_SPECIFIED(channel, saved_value);
|
||||
myfree(saved_value);
|
||||
return (FOUND);
|
||||
}
|
||||
@@ -148,11 +142,21 @@ void transport_wildcard_init(void)
|
||||
VSTRING *channel = vstring_alloc(10);
|
||||
VSTRING *nexthop = vstring_alloc(10);
|
||||
|
||||
/*
|
||||
* Technically, the wildcard lookup pattern is redundant. A static map
|
||||
* (keys always match, result is fixed string) could achieve the same:
|
||||
*
|
||||
* transport_maps = hash:/etc/postfix/transport static:xxx:yyy
|
||||
*
|
||||
* But the user interface of such an approach would be less intuitive. We
|
||||
* tolerate the continued existence of wildcard lookup patterns because
|
||||
* of human interface considerations.
|
||||
*/
|
||||
#define WILDCARD "*"
|
||||
#define FULL 0
|
||||
#define PARTIAL DICT_FLAG_FIXED
|
||||
|
||||
if (find_transport_entry(WILDCARD, FULL, channel, nexthop, (char *) 0)) {
|
||||
if (find_transport_entry(WILDCARD, FULL, channel, nexthop)) {
|
||||
wildcard_channel = channel;
|
||||
wildcard_nexthop = nexthop;
|
||||
if (msg_verbose)
|
||||
@@ -174,7 +178,6 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
|
||||
const char *name;
|
||||
const char *next;
|
||||
int found;
|
||||
const char *def_nexthop = 0;
|
||||
|
||||
#define STREQ(x,y) (strcmp((x), (y)) == 0)
|
||||
#define DISCARD_EXTENSION ((char **) 0)
|
||||
@@ -193,7 +196,7 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
|
||||
* string. Specify the FULL flag to include regexp maps in the query.
|
||||
*/
|
||||
if (STREQ(full_addr, var_xport_null_key)) {
|
||||
if (find_transport_entry(full_addr, FULL, channel, nexthop, def_nexthop))
|
||||
if (find_transport_entry(full_addr, FULL, channel, nexthop))
|
||||
RETURN_FREE(FOUND);
|
||||
RETURN_FREE(NOTFOUND);
|
||||
}
|
||||
@@ -205,9 +208,7 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
|
||||
if ((ratsign = strrchr(full_addr, '@')) == 0 || ratsign[1] == 0)
|
||||
msg_panic("transport_lookup: bad address: \"%s\"", full_addr);
|
||||
|
||||
def_nexthop = ratsign + 1;
|
||||
|
||||
if (find_transport_entry(full_addr, FULL, channel, nexthop, def_nexthop))
|
||||
if (find_transport_entry(full_addr, FULL, channel, nexthop))
|
||||
RETURN_FREE(FOUND);
|
||||
|
||||
/*
|
||||
@@ -217,8 +218,8 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
|
||||
*/
|
||||
if ((stripped_addr = strip_addr(full_addr, DISCARD_EXTENSION,
|
||||
*var_rcpt_delim)) != 0) {
|
||||
if (find_transport_entry(stripped_addr, PARTIAL, channel, nexthop,
|
||||
def_nexthop)) {
|
||||
if (find_transport_entry(stripped_addr, PARTIAL,
|
||||
channel, nexthop)) {
|
||||
myfree(stripped_addr);
|
||||
RETURN_FREE(FOUND);
|
||||
} else {
|
||||
@@ -243,7 +244,7 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
|
||||
* with regular expressions.
|
||||
*/
|
||||
for (found = 0, name = ratsign + 1; /* void */ ; name = next) {
|
||||
if (find_transport_entry(name, PARTIAL, channel, nexthop, def_nexthop))
|
||||
if (find_transport_entry(name, PARTIAL, channel, nexthop))
|
||||
RETURN_FREE(FOUND);
|
||||
if ((next = strchr(name + 1, '.')) == 0)
|
||||
break;
|
||||
@@ -255,10 +256,8 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
|
||||
* Fall back to the wild-card entry.
|
||||
*/
|
||||
if (wildcard_channel) {
|
||||
if (*vstring_str(wildcard_channel))
|
||||
vstring_strcpy(channel, vstring_str(wildcard_channel));
|
||||
if (*vstring_str(wildcard_nexthop))
|
||||
vstring_strcpy(nexthop, vstring_str(wildcard_nexthop));
|
||||
UPDATE_IF_SPECIFIED(channel, STR(wildcard_channel));
|
||||
UPDATE_IF_SPECIFIED(nexthop, STR(wildcard_nexthop));
|
||||
RETURN_FREE(FOUND);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user