]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-1.1.12-20021213
authorWietse Venema <wietse@porcupine.org>
Fri, 13 Dec 2002 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:28:33 +0000 (06:28 +0000)
20 files changed:
postfix/HISTORY
postfix/html/faq.html
postfix/src/bounce/bounce.c
postfix/src/cleanup/cleanup.c
postfix/src/flush/flush.c
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/master/mail_server.h
postfix/src/master/master_ent.c
postfix/src/master/multi_server.c
postfix/src/master/single_server.c
postfix/src/master/trigger_server.c
postfix/src/nqmgr/qmgr.c
postfix/src/nqmgr/qmgr_entry.c
postfix/src/pickup/pickup.c
postfix/src/qmgr/qmgr.c
postfix/src/qmgr/qmgr_entry.c
postfix/src/trivial-rewrite/resolve.c
postfix/src/trivial-rewrite/transport.c

index 9203896acea939bf3d5db114790911ec9a3ef796..14f135d5990b637eeb96aa379fee6d7347cbcba6 100644 (file)
@@ -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,
index c6226e5489878d0f215f937422950c3a1511b68c..68accfa7b93cd6010f8aa679a3bef74f110497e4 100644 (file)
@@ -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>
index 0e33b3d2b1a2641174fcc889b68f5dfe9588bf59..83a0273ab5922ba583974862cf30f1266b6d73e3 100644 (file)
@@ -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);
 }
index 21438aa5b89fde3a0d6d331125c0ffef1dcc5793..1dd7f9881b3ef6917a3780a3d26ff826991b4b3e 100644 (file)
@@ -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);
 }
index c4517a4927caf5d8b62bd6dcc2b6280ccd19e0c3..c55c5ddbd4d6d425d1b41cd8f9ec21c741bde5a4 100644 (file)
@@ -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);
 }
index fd27b82d4c52368a3953a32100cc3cb0cc1f1f44..62c849a822c0db10ccc7376d7570bf4328a92364 100644 (file)
@@ -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;
index e9f43b83a2f5976c9b3ba16dc45748b4d6f843b4..937224a27cd0fc0d873274a29dd82ffa708aaffb 100644 (file)
@@ -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
index e9cd06f5c0b6fdda91fbb27f7a2f12981ac1007b..1405ab0884128956c512c962ec34a8174eaff100 100644 (file)
@@ -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
index 47b8cfeeed28a163c9d794ccf4fec1e8c250301b..068354d5d3d6e777c9183bfc3243d2047bad36d6 100644 (file)
@@ -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
 
index 89aac56abfa9710d2b9d3ddacd0a8b07876b39bd..4412dff3b351a85ed4f09d1ac0498a28906e9196 100644 (file)
@@ -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);
index 927aa94d275ebc2a1df67c0ea3a07ee86ff726b6..4275c0c65682a543d54cb946f161052f07e6d626 100644 (file)
 /* .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);
        }
index d110e40102cce81f80180d4726cf16a26a1ba7e2..077d8cc702cdc065a9b9a74e70ec06be3488e24d 100644 (file)
 /* .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);
        }
index c84b8a8b5197000e09a3cfdbdbac60253759f718..08d42bf18cca43caee3d9ecaf7651b56123c7150 100644 (file)
 /* .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);
        }
index f0a5135ab92ccf2d246c1c4c0e308037ea0117ee..cd1e72b1e5d1224e24c8245f5167b99bbc8be8f0 100644 (file)
@@ -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);
 }
index 45c8b7f6199619e4cf532d58671335e45f21a2a9..5032a45563beac7f99f507e08b3ba41a7539575c 100644 (file)
@@ -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;
index e798de07cc2226b0b3168c9fce4646deead13ab3..40e1ab7141d8e6b11d259b64546fd7e26898624d 100644 (file)
@@ -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);
 }
index ab91a0fe426dd7da80e3dc0df60b544f7463a1a7..9ecfa116b5cc41bf5c1a725fd7cf0c3dbdb86bc9 100644 (file)
@@ -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);
 }
index 1c0772dbee93246eaf1158d8a1a73029d9c9cf81..57de8ebd602fae04092322ea4f3223706494590a 100644 (file)
@@ -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;
index 11872996ddad09e0dac56bb86d441a762435dbc8..69edaaafb31178f617b2b7178f24f846330753fd 100644 (file)
@@ -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;
index e67d9818c2f282598dc4290253c3874d0ddc2d34..d0c6211d0e07d557a6a3f91cefdd509e19f40ff0 100644 (file)
@@ -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);
     }