diff --git a/postfix/HISTORY b/postfix/HISTORY index 3cd0526eb..3857599e8 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -14569,3 +14569,43 @@ Apologies for any names omitted. legitimate configurations that deliver mail to a symbolic link in a directory with less restrictive permissions. +20080815 + + Feature: the milter_default_action parameter now accepts + the "quarantine" action. This works like "accept" but also + freezes the mail in the "hold" queue. File: milter/milter8.c. + + Robustness: transition from setjmp()/longjmp() to the signal + mask saving/restoring versions sigsetjmp()/siglongjmp(). + These functions have been around for 15 years, but they + have had bugs on supported platforms, so makedefs tests for + them. Files: makedefs, util/sys_defs.h, util/vstream.h. + +20080822 + + Cleanup: the proxymap_service_name and proxywrite_service_name + parameters make the proxymap service names configurable. + This paves the way for a future option where the proxymap + services are accessible via TCP so that they can be shared + among multiple Postfix hosts. File: global/dict_proxy.c. + + Feature: MacOS X support for kqueue style event handling, + with workaround for broken MacOS X versions. Files: + util/sys_defs.h, makedefs. + + Cleanup: the makedefs script now keeps its test programs + in a directory makedefs.d, instead of inlining them as + fragile "here documents". Files: makedefs, makedefs.d/*. + +20080823 + + Feature: IPv6 dns blocklist lookup. File: smtpd/smtpd_check.c. + +20080824 + + Cleanup: untangled the MacOS X version dependent sections + in the makedefs script, to make future updates easier. File: + makedefs. + + Cleanup: don't log multiple Milter "hold" actions for + the same message. File: cleanup/cleanup_milter.c. diff --git a/postfix/README_FILES/MILTER_README b/postfix/README_FILES/MILTER_README index a67fa044d..469144924 100644 --- a/postfix/README_FILES/MILTER_README +++ b/postfix/README_FILES/MILTER_README @@ -250,10 +250,12 @@ The milter_default_action parameter specifies how Postfix handles Milter application errors. The default action is to respond with a temporary error status, so that the client will try again later. Specify "accept" if you want to receive mail as if the filter does not exist, and "reject" to reject mail -with a permanent status. +with a permanent status. The "quarantine" action is like "accept" but freezes +the message in the "hold" queue, and is available with Postfix 2.6 or later. /etc/postfix/main.cf: - # What to do in case of errors? Specify accept, reject, or tempfail. + # What to do in case of errors? Specify accept, reject, tempfail, + # or quarantine (Postfix 2.6 or later). milter_default_action = tempfail MMiilltteerr pprroottooccooll vveerrssiioonn diff --git a/postfix/README_FILES/STRESS_README b/postfix/README_FILES/STRESS_README index dbdd3171f..11f519088 100644 --- a/postfix/README_FILES/STRESS_README +++ b/postfix/README_FILES/STRESS_README @@ -43,10 +43,17 @@ activity). Symptoms of Postfix SMTP mail server overload are: Postfix 2.1), and tell users to connect to this instead of the public SMTP service. + o NOTE: Broken DNS configurations also cause lengthy delays before + Postfix sends "220 hostname.example.com ...". In this case the delay + happens even when Postfix is not busy. + * The Postfix SMTP server logs an increased number of "lost connection after CONNECT" events. This happens because remote SMTP clients disconnect before Postfix answers the connection. + o NOTE: A portscan for open SMTP ports also results in "lost connection + ..." logfile messages. + * Postfix 2.3 and later logs a warning that all server ports are busy: Oct 3 20:39:27 spike postfix/master[28905]: warning: service "smtp" @@ -56,14 +63,6 @@ activity). Symptoms of Postfix SMTP mail server overload are: condition, increase the process count in master.cf or reduce the service time per client -NOTE: The first two symptoms may also happen without overload, for example: - - * Broken DNS also causes lengthy delays before "220 hostname.example.com ..." - while the Postfix SMTP server tries to look up the client's hostname. - - * A portscan for open SMTP ports also results in "lost connection ..." - logfile messages. - Legitimate mail that doesn't get through during an episode of overload is not necessarily lost. It should still arrive once the situation returns to normal, as long as the overload condition is temporary. @@ -86,7 +85,7 @@ keep up with the additional load. Linux epoll(4), or Solaris /dev/poll). * You can reduce the Postfix memory footprint by using cdb: lookup tables - instead of Berkeley DB. + instead of Berkeley DB's hash: or btree: tables. 1 /etc/postfix/main.cf: 2 # Raise the global process limit, 100 since Postfix 2.0. @@ -104,9 +103,11 @@ keep up with the additional load. the SMTP server's "maxproc" field in master.cf, SMTP server processes will report problems when connecting to policy server processes, because there aren't enough of them. Examples of errors are "connection refused" or - "operation timed out". To fix, edit master.cf and specify a zero "maxproc" - field in all policy server entries; see line 6 in the example below. Issue - a "postfix reload" command to make the change effective. + "operation timed out". + + To fix, edit master.cf and specify a zero "maxproc" field in all policy + server entries; see line 6 in the example below. Issue a "postfix reload" + command to make the change effective. 1 /etc/postfix/master.cf: 2 # ============================================================= @@ -121,7 +122,7 @@ SSppeenndd lleessss ttiimmee ppeerr SSMMTTPP cclliieenn When increasing the number of SMTP server processes is not practical, you can improve Postfix server responsiveness by eliminating unnecessary work. When Postfix spends less time per SMTP session, the same number of SMTP server -processes can service more clients in the same amount of time. +processes can service more clients. * Eliminate non-functional RBL lookups (blocklists that are no longer in operation). These lookups can degrade performance. Postfix logs a warning diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index abe791e03..5cd47296a 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -11,6 +11,14 @@ instead, a new snapshot is released. The mail_release_date configuration parameter (format: yyyymmdd) specifies the release date of a stable release or snapshot release. +Incompatibility with snapshot 20080814 +====================================== + +When a mailbox file is not owned by its recipient, the local and +virtual delivery agents now log a warning and defer delivery. +Specify "strict_mailbox_ownership = no" to ignore such ownership +discrepancies. + Incompatibility with snapshot 20080629 ====================================== diff --git a/postfix/WISHLIST b/postfix/WISHLIST index 3a5e6acc5..3badd2ce4 100644 --- a/postfix/WISHLIST +++ b/postfix/WISHLIST @@ -1,5 +1,5 @@ Wish list: - + Force a panic when the VDA patch reduces the file size limit under the message size. They break the code that marks a recipient as "done", when that recipient was added late @@ -37,11 +37,12 @@ Wish list: that it makes smtpd_mumble_restrictions available for local and remote mail; the disadvantage is that it makes local submissions more dependent on networking. One possibility - is to use "pickup -o content_filter=smtp:127.0.0.1". Another - is to have the pickup or cleanup server drive an SMTP client - directly; this would require extension of the mail_stream() - interface, plus a way to handle bounced/deferred recipients - intelligently. + is to use "pickup -o content_filter=smtp:127.0.0.1:10025"; + we could also to suppress "mail loop" detection for loopback + connections. Another is to have the pickup or cleanup + server drive an SMTP client directly; this would require + extension of the mail_stream() interface, plus a way to + handle bounced/deferred recipients intelligently. Consolidate duplicated code in *_server_accept_{pass,inet}(). diff --git a/postfix/html/MILTER_README.html b/postfix/html/MILTER_README.html index ce06e5ca2..c8539c523 100644 --- a/postfix/html/MILTER_README.html +++ b/postfix/html/MILTER_README.html @@ -425,12 +425,15 @@ Milter application errors. The default action is to respond with a temporary error status, so that the client will try again later. Specify "accept" if you want to receive mail as if the filter does not exist, and "reject" to reject mail with a permanent status. +The "quarantine" action is like "accept" but freezes the message +in the "hold" queue, and is available with Postfix 2.6 or later.

 /etc/postfix/main.cf:
-    # What to do in case of errors? Specify accept, reject, or tempfail.
+    # What to do in case of errors? Specify accept, reject, tempfail,
+    # or quarantine (Postfix 2.6 or later).
     milter_default_action = tempfail
 
diff --git a/postfix/html/STRESS_README.html b/postfix/html/STRESS_README.html index 1ea44d77b..4803d5388 100644 --- a/postfix/html/STRESS_README.html +++ b/postfix/html/STRESS_README.html @@ -77,10 +77,25 @@ this affects end-user mail clients, enable the "submission" service entry in master.cf (present since Postfix 2.1), and tell users to connect to this instead of the public SMTP service.

+ +
  • The Postfix SMTP server logs an increased number of "lost connection after CONNECT" events. This happens because remote SMTP clients disconnect before Postfix answers the connection.

    + +
  • Postfix 2.3 and later logs a warning that all server ports are busy:

    @@ -95,21 +110,6 @@ Oct 3 20:39:27 spike postfix/master[28905]: warning: to avoid this -

    NOTE: The first two symptoms may also happen without overload, -for example:

    - - -

    Legitimate mail that doesn't get through during an episode of overload is not necessarily lost. It should still arrive once the situation returns to normal, as long as the overload condition is @@ -138,7 +138,7 @@ filters (BSD kqueue(2), Linux epoll(4), or Solaris /dev/poll).

  • You can reduce the Postfix memory footprint by using cdb: -lookup tables instead of Berkeley DB.

    +lookup tables instead of Berkeley DB's hash: or btree: tables.

      1 /etc/postfix/main.cf:
    @@ -159,7 +159,9 @@ processes.  When you raise the SMTP server's "maxproc" field in
     master.cf, SMTP server processes will report problems when connecting
     to policy server processes, because there aren't enough of them.
     Examples of errors are "connection refused" or "operation timed
    -out".  To fix, edit master.cf and specify a zero "maxproc" field
    +out".  

    + +

    To fix, edit master.cf and specify a zero "maxproc" field in all policy server entries; see line 6 in the example below. Issue a "postfix reload" command to make the change effective.

    @@ -180,8 +182,7 @@ Issue a "postfix reload" command to make the change effective.

    When increasing the number of SMTP server processes is not practical, you can improve Postfix server responsiveness by eliminating unnecessary work. When Postfix spends less time per SMTP session, the -same number of SMTP server processes can service more clients in -the same amount of time.

    +same number of SMTP server processes can service more clients.

    -

    NOTE: The first two symptoms may also happen without overload, -for example:

    - -
      - -
    • Broken DNS also causes lengthy delays before "220 -hostname.example.com -..." while the Postfix SMTP server tries to look up the client's -hostname.

      - -
    • A portscan for open SMTP ports also results in "lost -connection ..." logfile messages.

      - -
    -

    Legitimate mail that doesn't get through during an episode of overload is not necessarily lost. It should still arrive once the situation returns to normal, as long as the overload condition is @@ -138,7 +138,7 @@ filters (BSD kqueue(2), Linux epoll(4), or Solaris /dev/poll).

  • You can reduce the Postfix memory footprint by using cdb: -lookup tables instead of Berkeley DB.

    +lookup tables instead of Berkeley DB's hash: or btree: tables.

      1 /etc/postfix/main.cf:
    @@ -159,7 +159,9 @@ processes.  When you raise the SMTP server's "maxproc" field in
     master.cf, SMTP server processes will report problems when connecting
     to policy server processes, because there aren't enough of them.
     Examples of errors are "connection refused" or "operation timed
    -out".  To fix, edit master.cf and specify a zero "maxproc" field
    +out".  

    + +

    To fix, edit master.cf and specify a zero "maxproc" field in all policy server entries; see line 6 in the example below. Issue a "postfix reload" command to make the change effective.

    @@ -180,8 +182,7 @@ Issue a "postfix reload" command to make the change effective.

    When increasing the number of SMTP server processes is not practical, you can improve Postfix server responsiveness by eliminating unnecessary work. When Postfix spends less time per SMTP session, the -same number of SMTP server processes can service more clients in -the same amount of time.

    +same number of SMTP server processes can service more clients.

      diff --git a/postfix/proto/postconf.proto b/postfix/proto/postconf.proto index 6db1f32f4..1b19fa2f7 100644 --- a/postfix/proto/postconf.proto +++ b/postfix/proto/postconf.proto @@ -8221,6 +8221,8 @@ The table is not searched by hostname for robustness reasons.

      The name of the scache(8) connection cache service. This service maintains a limited pool of cached sessions.

      +

      This feature is available in Postfix 2.2 and later.

      + %PARAM connection_cache_ttl_limit 2s

      The maximal time-to-live value that the scache(8) connection @@ -10401,6 +10403,9 @@ with a permanent status code.

      tempfail
      Reject all further commands in this session with a temporary status code.
      +
      quarantine
      Like "accept", but freeze the message in +the "hold" queue. Available with Postfix 2.6 and later.
      +

      This feature is available in Postfix 2.3 and later.

      @@ -11614,3 +11619,19 @@ details. The default setting is not backwards compatible.

      This feature is available in Postfix 2.5.3 and later.

      + +%PARAM proxymap_service_name proxymap + +

      The name of the proxymap read-only table lookup service. This +service is normally implemented by the proxymap(8) daemon.

      + +

      This feature is available in Postfix 2.6 and later.

      + +%PARAM proxywrite_service_name proxywrite + +

      The name of the proxywrite read-write table lookup service. +This service is normally implemented by the proxymap(8) daemon. +

      + +

      This feature is available in Postfix 2.6 and later.

      + diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 5e17f3107..4d1273222 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -927,7 +927,7 @@ void cleanup_message(CLEANUP_STATE *state, int type, const char *buf, ssize_t /* * XXX Workaround: truncate a long message header so that we don't exceed - * the Milter request size limit of 65535. + * the default Sendmail libmilter request size limit of 65535. */ #define KLUDGE_HEADER_LIMIT 60000 if ((cleanup_milters || state->milters) diff --git a/postfix/src/cleanup/cleanup_milter.c b/postfix/src/cleanup/cleanup_milter.c index c9423c73e..def810f14 100644 --- a/postfix/src/cleanup/cleanup_milter.c +++ b/postfix/src/cleanup/cleanup_milter.c @@ -1399,6 +1399,8 @@ static const char *cleanup_milter_apply(CLEANUP_STATE *state, const char *event, switch (resp[0]) { case 'H': /* XXX Should log the reason here. */ + if (state->flags & CLEANUP_FLAG_HOLD) + return (0); state->flags |= CLEANUP_FLAG_HOLD; action = "milter-hold"; text = "milter triggers HOLD action"; diff --git a/postfix/src/global/dict_proxy.c b/postfix/src/global/dict_proxy.c index 8005c8d36..78a5dd73e 100644 --- a/postfix/src/global/dict_proxy.c +++ b/postfix/src/global/dict_proxy.c @@ -308,38 +308,53 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) int server_flags; int status; const char *service; - const char *relative_path; + char *relative_path; char *kludge = 0; char *prefix; CLNT_STREAM **pstream; /* - * Sanity checks. + * If this map can't be proxied then we silently do a direct open. This + * allows sites to benefit from proxying the virtual mailbox maps without + * unnecessary pain. + */ + if (dict_flags & DICT_FLAG_NO_PROXY) + return (dict_open(map, open_flags, dict_flags)); + + /* + * Use a shared stream for proxied table lookups of the same type. * * XXX A complete implementation would also allow O_RDWR without O_CREAT. * But we must not pass on every possible set of flags to the proxy * server; only sets that make sense. For now, the flags are passed * implicitly by choosing between the proxymap or proxywrite service. + * + * XXX Use absolute pathname to make this work from non-daemon processes. */ if (open_flags == O_RDONLY) { pstream = &proxymap_stream; - service = MAIL_SERVICE_PROXYMAP; - relative_path = MAIL_CLASS_PRIVATE "/" MAIL_SERVICE_PROXYMAP; + service = var_proxymap_service; } else if (open_flags == (O_RDWR | O_CREAT)) { pstream = &proxywrite_stream; - service = MAIL_SERVICE_PROXYWRITE; - relative_path = MAIL_CLASS_PRIVATE "/" MAIL_SERVICE_PROXYWRITE; + service = var_proxywrite_service; } else msg_fatal("%s: %s map open requires O_RDONLY or O_RDWR|O_CREAT mode", map, DICT_TYPE_PROXY); - /* - * OK. If this map can't be proxied then we silently do a direct open. - * This allows sites to benefit from proxying the virtual mailbox maps - * without unnecessary pain. - */ - if (dict_flags & DICT_FLAG_NO_PROXY) - return (dict_open(map, open_flags, dict_flags)); + if (*pstream == 0) { + relative_path = concatenate(MAIL_CLASS_PRIVATE "/", + service, (char *) 0); + if (access(relative_path, F_OK) == 0) + prefix = MAIL_CLASS_PRIVATE; + else + prefix = kludge = concatenate(var_queue_dir, "/", + MAIL_CLASS_PRIVATE, (char *) 0); + *pstream = clnt_stream_create(prefix, service, var_ipc_idle_limit, + var_ipc_ttl_limit); + if (kludge) + myfree(kludge); + myfree(relative_path); + } /* * Local initialization. @@ -352,23 +367,6 @@ DICT *dict_proxy_open(const char *map, int open_flags, int dict_flags) dict_proxy->dict.close = dict_proxy_close; dict_proxy->in_flags = dict_flags; dict_proxy->result = vstring_alloc(10); - - /* - * Use a shared stream for proxied table lookups of the same type. - * - * XXX Use absolute pathname to make this work from non-daemon processes. - */ - if (*pstream == 0) { - if (access(relative_path, F_OK) == 0) - prefix = MAIL_CLASS_PRIVATE; - else - prefix = kludge = concatenate(var_queue_dir, "/", - MAIL_CLASS_PRIVATE, (char *) 0); - *pstream = clnt_stream_create(prefix, service, var_ipc_idle_limit, - var_ipc_ttl_limit); - if (kludge) - myfree(kludge); - } dict_proxy->clnt = *pstream; dict_proxy->service = service; diff --git a/postfix/src/global/mail_params.c b/postfix/src/global/mail_params.c index 2cb19631d..a8d9c11bd 100644 --- a/postfix/src/global/mail_params.c +++ b/postfix/src/global/mail_params.c @@ -91,6 +91,8 @@ /* char *var_flush_service; /* char *var_verify_service; /* char *var_trace_service; +/* char *var_proxymap_service; +/* char *var_proxywrite_service; /* int var_db_create_buf; /* int var_db_read_buf; /* int var_mime_maxdepth; @@ -266,6 +268,8 @@ char *var_error_service; char *var_flush_service; char *var_verify_service; char *var_trace_service; +char *var_proxymap_service; +char *var_proxywrite_service; int var_db_create_buf; int var_db_read_buf; int var_mime_maxdepth; @@ -541,6 +545,8 @@ void mail_params_init() VAR_FLUSH_SERVICE, DEF_FLUSH_SERVICE, &var_flush_service, 1, 0, VAR_VERIFY_SERVICE, DEF_VERIFY_SERVICE, &var_verify_service, 1, 0, VAR_TRACE_SERVICE, DEF_TRACE_SERVICE, &var_trace_service, 1, 0, + VAR_PROXYMAP_SERVICE, DEF_PROXYMAP_SERVICE, &var_proxymap_service, 1, 0, + VAR_PROXYWRITE_SERVICE, DEF_PROXYWRITE_SERVICE, &var_proxywrite_service, 1, 0, VAR_INT_FILT_CLASSES, DEF_INT_FILT_CLASSES, &var_int_filt_classes, 0, 0, 0, }; diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 54a330baf..559ea4680 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -2498,6 +2498,17 @@ extern char *var_vrfy_xport_maps; #define DEF_TRACE_SERVICE MAIL_SERVICE_TRACE extern char *var_trace_service; + /* + * Proxymappers. + */ +#define VAR_PROXYMAP_SERVICE "proxymap_service_name" +#define DEF_PROXYMAP_SERVICE MAIL_SERVICE_PROXYMAP +extern char *var_proxymap_service; + +#define VAR_PROXYWRITE_SERVICE "proxywrite_service_name" +#define DEF_PROXYWRITE_SERVICE MAIL_SERVICE_PROXYWRITE +extern char *var_proxywrite_service; + /* * Mailbox/maildir delivery errors that cause delivery to be tried again. */ diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 23eae8261..055986588 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change both the patchlevel and the release date. Snapshots have no * patchlevel; they change the release date only. */ -#define MAIL_RELEASE_DATE "20080814" +#define MAIL_RELEASE_DATE "20080824" #define MAIL_VERSION_NUMBER "2.6" #ifdef SNAPSHOT diff --git a/postfix/src/milter/milter8.c b/postfix/src/milter/milter8.c index 4a3abb96d..3d660a4b5 100644 --- a/postfix/src/milter/milter8.c +++ b/postfix/src/milter/milter8.c @@ -505,6 +505,8 @@ static int milter8_conf_error(MILTER8 *milter) } if (strcasecmp(milter->def_action, "accept") == 0) { reply = 0; + } else if (strcasecmp(milter->def_action, "quarantine") == 0) { + reply = "H"; } else { reply = "451 4.3.5 Server configuration problem - try again later"; } @@ -537,6 +539,8 @@ static int milter8_comm_error(MILTER8 *milter) reply = "550 5.5.0 Service unavailable"; } else if (strcasecmp(milter->def_action, "tempfail") == 0) { reply = "451 4.7.1 Service unavailable - try again later"; + } else if (strcasecmp(milter->def_action, "quarantine") == 0) { + reply = "H"; } else { msg_warn("milter %s: unrecognized default action: %s", milter->m.name, milter->def_action); diff --git a/postfix/src/milter/test-milter.c b/postfix/src/milter/test-milter.c index 23a0c37cb..8980f416e 100644 --- a/postfix/src/milter/test-milter.c +++ b/postfix/src/milter/test-milter.c @@ -19,6 +19,9 @@ /* .IP "\fB-a accept|tempfail|reject|discard|skip|\fIddd x.y.z text\fR" /* Specifies a non-default reply for the MTA command specified /* with \fB-c\fR. The default is \fBtempfail\fR. +/* .IP "\fB-A address\fR" +/* Add the specified recipient address. Multiple -A options +/* are supported. /* .IP "\fB-d\fI level\fR" /* Enable libmilter debugging at the specified level. /* .IP "\fB-c connect|helo|mail|rcpt|data|header|eoh|body|eom|unknown|close|abort\fR" @@ -146,6 +149,10 @@ static char *body_file; #endif +#define MAX_RCPT 10 +int rcpt_count = 0; +char *rcpt_addr[MAX_RCPT]; + static int test_reply(SMFICTX *ctx, int code) { (void) fflush(stdout); /* In case output redirected. */ @@ -288,12 +295,19 @@ static sfsistat test_eom(SMFICTX *ctx) #endif #ifdef SMFIR_INSHEADER if (ins_hdr && smfi_insheader(ctx, ins_idx, ins_hdr, ins_val) == MI_FAILURE) - fprintf(stderr, "smfi_insheader failed"); + fprintf(stderr, "smfi_insheader failed\n"); #endif #ifdef SMFIR_CHGHEADER if (chg_hdr && smfi_chgheader(ctx, chg_hdr, chg_idx, chg_val) == MI_FAILURE) - fprintf(stderr, "smfi_chgheader failed"); + fprintf(stderr, "smfi_chgheader failed\n"); #endif + { + int count; + + for (count = 0; count < rcpt_count; count++) + if (smfi_addrcpt(ctx, rcpt_addr[count]) == MI_FAILURE) + fprintf(stderr, "smfi_addrcpt `%s' failed\n", rcpt_addr[count]); + } return (test_reply(ctx, test_eom_reply)); } @@ -464,11 +478,18 @@ int main(int argc, char **argv) char *noreply = 0; const struct noproto_map *np; - while ((ch = getopt(argc, argv, "a:c:C:d:i:lm:M:n:N:p:r:R:v")) > 0) { + while ((ch = getopt(argc, argv, "a:A:c:C:d:i:lm:M:n:N:p:r:R:v")) > 0) { switch (ch) { case 'a': action = optarg; break; + case 'A': + if (rcpt_count >= MAX_RCPT) { + fprintf(stderr, "too many -A options\n"); + exit(1); + } + rcpt_addr[rcpt_count++] = optarg; + break; case 'c': command = optarg; break; diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index e8bdf3e11..cd7e27175 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -3115,27 +3115,49 @@ static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain, int i; SMTPD_RBL_STATE *rbl; const char *reply_addr; + struct addrinfo *res; + unsigned char *ipv6_addr; if (msg_verbose) msg_info("%s: %s %s", myname, reply_class, addr); - /* - * IPv4 / IPv6-mapped IPv4 (if supported) only for now - */ - if (valid_ipv6_hostaddr(addr, DONT_GRIPE)) - return SMTPD_CHECK_DUNNO; + query = vstring_alloc(100); /* - * Reverse the client IPV4 address, tack on the RBL domain name and query - * the DNS for an A record. + * Reverse the client IPV6 address, represented as 32 hexadecimal + * nibbles. We use the binary address to avoid tricky code. Asking for an + * AAAA record makes no sense here. Just like with IPv4 we use the lookup + * result as a bit mask, not as an IP address. */ - query = vstring_alloc(100); - octets = argv_split(addr, "."); - for (i = octets->argc - 1; i >= 0; i--) { - vstring_strcat(query, octets->argv[i]); - vstring_strcat(query, "."); +#ifdef PF_INET6 + if (valid_ipv6_hostaddr(addr, DONT_GRIPE)) { + if (hostaddr_to_sockaddr(addr, (char *) 0, 0, &res) != 0 + || res->ai_family != PF_INET6) + msg_fatal("%s: unable to convert address %s", myname, addr); + ipv6_addr = (unsigned char *) &SOCK_ADDR_IN6_ADDR(res->ai_addr); + for (i = sizeof(SOCK_ADDR_IN6_ADDR(res->ai_addr)) - 1; i >= 0; i--) + vstring_sprintf_append(query, "%x.%x.", + ipv6_addr[i] & 0xf, ipv6_addr[i] >> 4); + freeaddrinfo(res); + } else +#endif + + /* + * Reverse the client IPV4 address, represented as four decimal octet + * values. We use the textual address for convenience. + */ + { + octets = argv_split(addr, "."); + for (i = octets->argc - 1; i >= 0; i--) { + vstring_strcat(query, octets->argv[i]); + vstring_strcat(query, "."); + } + argv_free(octets); } - argv_free(octets); + + /* + * Tack on the RBL domain name and query the DNS for an A record. + */ vstring_strcat(query, rbl_domain); reply_addr = split_at(STR(query), '='); rbl = (SMTPD_RBL_STATE *) ctable_locate(smtpd_rbl_cache, STR(query)); diff --git a/postfix/src/util/auto_clnt.c b/postfix/src/util/auto_clnt.c index 626531cc0..0dba39b79 100644 --- a/postfix/src/util/auto_clnt.c +++ b/postfix/src/util/auto_clnt.c @@ -53,10 +53,16 @@ /* transport is currently limited to one of the following: /* .RS /* .IP inet -/* servername has the form "host:port". +/* servername has the form "inet:host:port". +/* .IP local +/* servername has the form "local:private/servicename" or +/* "local:public/servicename". This is the preferred way to +/* specify Postfix daemons that are configured as "unix" in +/* master.cf. /* .IP unix -/* servername has the form "private/servicename" or -/* "public/servicename". +/* servername has the form "unix:private/servicename" or +/* "unix:public/servicename". This does not work on Solaris, +/* where Postfix uses STREAMS instead of UNIX-domain sockets. /* .RE /* .IP timeout /* The time limit for sending, receiving, or for connecting diff --git a/postfix/src/util/stream_send_fd.c b/postfix/src/util/stream_send_fd.c index a056bb0a8..26116d886 100644 --- a/postfix/src/util/stream_send_fd.c +++ b/postfix/src/util/stream_send_fd.c @@ -54,14 +54,14 @@ int stream_send_fd(int fd, int sendfd) { +#ifdef STREAM_CONNECTIONS const char *myname = "stream_send_fd"; -#ifdef STREAM_CONNECTIONS if (ioctl(fd, I_SENDFD, sendfd) < 0) msg_fatal("%s: send file descriptor %d: %m", myname, sendfd); return (0); #else - msg_fatal("stream connections are not implemented"); + msg_fatal("stream connections are not implemented"); #endif } diff --git a/postfix/src/util/sys_defs.h b/postfix/src/util/sys_defs.h index 0c8f4d986..8f8f8f7b9 100644 --- a/postfix/src/util/sys_defs.h +++ b/postfix/src/util/sys_defs.h @@ -223,6 +223,11 @@ #define NATIVE_DAEMON_DIR "/usr/libexec/postfix" #define SOCKADDR_SIZE socklen_t #define SOCKOPT_SIZE socklen_t +#ifndef NO_KQUEUE +# define EVENTS_STYLE EVENTS_STYLE_KQUEUE +# define USE_SYSV_POLL +#endif + #endif /* @@ -1271,6 +1276,10 @@ extern int inet_pton(int, const char *, void *); #define EVENTS_STYLE_DEVPOLL 3 /* Solaris /dev/poll */ #define EVENTS_STYLE_EPOLL 4 /* Linux epoll */ +#if !defined(USE_SYSV_POLL) && (EVENTS_STYLE != EVENTS_STYLE_SELECT) +#error "need USE_SYSV_POLL with EVENTS_STYLE != EVENTS_STYLE_SELECT" +#endif + /* * Defaults for all systems. */ diff --git a/postfix/src/util/vstream.c b/postfix/src/util/vstream.c index 970beba62..b3b9fce56 100644 --- a/postfix/src/util/vstream.c +++ b/postfix/src/util/vstream.c @@ -1250,7 +1250,8 @@ void vstream_control(VSTREAM *stream, int name,...) break; case VSTREAM_CTL_EXCEPT: if (stream->jbuf == 0) - stream->jbuf = (jmp_buf *) mymalloc(sizeof(jmp_buf)); + stream->jbuf = + (VSTREAM_JMP_BUF *) mymalloc(sizeof(VSTREAM_JMP_BUF)); break; #ifdef VSTREAM_CTL_DUPFD diff --git a/postfix/src/util/vstream.h b/postfix/src/util/vstream.h index b8cdca7a5..845be337f 100644 --- a/postfix/src/util/vstream.h +++ b/postfix/src/util/vstream.h @@ -33,6 +33,12 @@ typedef ssize_t (*VSTREAM_FN) (int, void *, size_t, int, void *); typedef int (*VSTREAM_WAITPID_FN) (pid_t, WAIT_STATUS_T *, int); +#ifdef NO_SIGSETJMP +#define VSTREAM_JMP_BUF jmp_buf +#else +#define VSTREAM_JMP_BUF sigjmp_buf +#endif + typedef struct VSTREAM { VBUF buf; /* generic intelligent buffer */ int fd; /* file handle, no 256 limit */ @@ -48,7 +54,7 @@ typedef struct VSTREAM { pid_t pid; /* vstream_popen/close() */ VSTREAM_WAITPID_FN waitpid_fn; /* vstream_popen/close() */ int timeout; /* read/write timout */ - jmp_buf *jbuf; /* exception handling */ + VSTREAM_JMP_BUF *jbuf; /* exception handling */ struct timeval iotime; /* time of last fill/flush */ /* At bottom for Postfix 2.4 binary compatibility. */ ssize_t req_bufsize; /* write buffer size */ @@ -152,9 +158,18 @@ extern ssize_t vstream_peek(VSTREAM *); /* * Exception handling. We use pointer to jmp_buf to avoid a lot of unused * baggage for streams that don't need this functionality. + * + * XXX sigsetjmp()/siglongjmp() save and restore the signal mask which can + * avoid surprises in code that manipulates signals, but unfortunately some + * systems have bugs in their implementation. */ +#ifdef NO_SIGSETJMP #define vstream_setjmp(stream) setjmp((stream)->jbuf[0]) #define vstream_longjmp(stream, val) longjmp((stream)->jbuf[0], (val)) +#else +#define vstream_setjmp(stream) sigsetjmp((stream)->jbuf[0], 1) +#define vstream_longjmp(stream, val) siglongjmp((stream)->jbuf[0], (val)) +#endif /* * Tweaks and workarounds.