]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
snapshot-20010731
authorWietse Venema <wietse@porcupine.org>
Tue, 31 Jul 2001 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:27:24 +0000 (06:27 +0000)
26 files changed:
postfix/HISTORY
postfix/RELEASE_NOTES
postfix/conf/main.cf
postfix/html/cleanup.8.html
postfix/html/postalias.1.html
postfix/html/postmap.1.html
postfix/man/man1/postalias.1
postfix/man/man1/postmap.1
postfix/man/man8/cleanup.8
postfix/src/cleanup/cleanup.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/global/own_inet_addr.c
postfix/src/master/mail_flow.c
postfix/src/nqmgr/qmgr.c
postfix/src/nqmgr/qmgr_active.c
postfix/src/qmgr/qmgr.c
postfix/src/qmgr/qmgr_active.c
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_state.c
postfix/src/util/Makefile.in
postfix/src/util/inet_addr_list.c
postfix/src/util/inet_addr_list.h
postfix/src/util/inet_addr_list.in [new file with mode: 0644]
postfix/src/util/inet_addr_list.ref [new file with mode: 0644]

index bd9f61782486455db69f257050d287fef7f17f4e..0a42ce0b6c16b75af2cbf43e0092ca8b13825186 100644 (file)
@@ -5358,26 +5358,43 @@ Apologies for any names omitted.
        token when it adds mail to the incoming queue. If no token
        is available the cleanup server pauses for $in_flow_delay
        seconds and proceeds anyway. The delay allows mail sending
-       process to catch up and access the disk. Valid delays are
-       0..10 seconds.
+       process to catch up and access the disk while not blocking
+       inbound mail. Valid delays are 0..10 seconds.
 
 20010727
 
        Bugfix: updated LDAP client module from LaMont Jones, HP.
+       This also introduces new LDAP query filter patterns: %u
+       (address localpart) and %d (domain part). Files:
+       conf/sample-ldap.cf, util/dict_ldap.c.
 
 20010729
 
-       Bugfix: recursive restrictions could clobber non-reentrant
-       address resolving results. Problem found by Victor Duchovni,
-       morganstanley.com. In order to fix, introduced address
-       resolving caching, which shouls speed up UCE processing.
+       Bugfix: recursive smtpd_whatever_restrictions clobbered
+       intermediate results when switching between sender and
+       recipient address restrictions. Problem found by Victor
+       Duchovni, morganstanley.com. In order to fix, introduced
+       address resolver result caching, which should also help to
+       speed up sender/recipient address restriction processing.
 
-       Bugfix: the not yet published DUNNO table lookup result
-       did not prevent further partial key lookups in the same
-       table. Problem found by Victor Duchovni, morganstanley.com.
+       Bugfix: the not yet announced DUNNO access table lookup
+       result did not prevent lookups with substrings of the same
+       lookup key. Found by Victor Duchovni, morganstanley.com.
 
-20010729
+20010730
 
        Robustness: trim trailing whitespace from regexp and pcre
        right-hand sides, for consistency with DB/DBM tables.
        Files: util/dict_pcre.c, util/dict_regexp.c.
+
+20010731
+
+       Robustness: eliminate duplicate IP addresses after expansion
+       of hostnames in $inet_interfaces, so that Postfix does not
+       suddenly refuse to start up after someone changes the DNS.
+       Files:  util/inet_addr_list.c global/own_inet_addr.c.
+
+       Feature: specify "disable_verp_bounces = yes" to have
+       Postfix send one RFC-standard, non-VERP, bounce report for
+       multi-recipient mail, even when VERP style delivery is
+       requested.
index bc9f2771ec040d6980493f8e9f71597a329e4641..721d02f595840f5ff9555c086bb4d46423a74138 100644 (file)
@@ -1,3 +1,36 @@
+Incompatible changes with snapshot-20010731
+===========================================
+
+The protocol between Postfix master and child processes has changed.
+You must stop and start Postfix in order to switch between Snapshot
+20010731 and releases that implement the older protocol.
+
+Major changes with snapshot-20010731
+====================================
+
+Specify "disable_verp_bounces = yes" to have Postfix send one
+RFC-standard, non-VERP, bounce report for multi-recipient mail,
+even when VERP style delivery is requested.
+
+Variable coupling between message receiving rates and message
+delivery rates. When the message receiving rate exceeds the message
+delivery rate, an SMTP server will pause for $in_flow_delay seconds
+(default: 1) before accepting a message. This delay gives Postfix
+a chance catch up and access the disk, while still allowing new
+mail to arrive.
+
+The in_flow_delay feature has effect mainly when your system is
+being flooded port through a limited number of SMTP connections.
+This is also useful for mass-mailing applications, because it avoids
+the need to hand-tune the rate at which mail is sent into Postfix.
+
+The in_flow_delay feature has negligible effect when mail arrives
+via many different SMTP connections. With the default limit of 50
+SMTP server processes and with the default $in_flow_delay of 1
+second, total mail inflow is limited to 50 messages per second more
+than the number of messages that are delivered per second. Many
+systems saturate at values much smaller than 50 messages per second.
+
 Incompatible changes with snapshot-20010714
 ===========================================
 
index 8807373a4188f6bbaf4096f4dda9a6a8d58aba4a..5e6b2c4c8888a0e19f8b8a73f6c44085bd9ad47a 100644 (file)
@@ -44,9 +44,10 @@ daemon_directory = /usr/libexec/postfix
 #
 # The mail_owner parameter specifies the owner of the Postfix queue
 # and of most Postfix daemon processes.  Specify the name of a user
-# account THAT DOES NOT SHARE A GROUP WITH OTHER ACCOUNTS AND THAT
-# OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM.  In particular,
-# don't specify nobody or daemon. PLEASE USE A DEDICATED USER.
+# account THAT DOES NOT SHARE ITS USER OR GROUP ID WITH OTHER ACCOUNTS
+# AND THAT OWNS NO OTHER FILES OR PROCESSES ON THE SYSTEM.  In
+# particular, don't specify nobody or daemon. PLEASE USE A DEDICATED
+# USER.
 #
 mail_owner = postfix
 
@@ -238,6 +239,19 @@ mail_owner = postfix
 #
 #local_recipient_maps = $alias_maps unix:passwd.byname
 
+# INPUT RATE CONTROL
+#
+# The in_flow_delay configuration parameter implements mail input
+# flow control. By default, a Postfix process will pause for one
+# second before accepting a new message, when the message arrival
+# rate exceeds the message delivery rate. With the default 50 SMTP
+# server process limit, this limits the mail inflow to 50 messages
+# a second more than the number of messages delivered per second.
+# 
+# Specify 0 to disable the feature. Valid delays are 0..10.
+# 
+#in_flow_delay = 1
+
 # ADDRESS REWRITING
 #
 # Insert text from sample-rewrite.cf if you need to do address
index 3f55c1de4e8f910ef6db6ceda15bd827e96ae540..48ab1db87320db2ccb7b4ead7da3417a6e8bb4f0 100644 (file)
@@ -133,6 +133,11 @@ CLEANUP(8)                                             CLEANUP(8)
               Limit the amount of memory in bytes used to process
               a message header.
 
+       <b>in</b><i>_</i><b>flow</b><i>_</i><b>delay</b>
+              Amount of time to pause before accepting a message,
+              when the message arrival rate exceeds  the  message
+              delivery rate.
+
        <b>extract</b><i>_</i><b>recipient</b><i>_</i><b>limit</b>
               Limit  the amount of recipients extracted from mes-
               sage headers.
index c1f00012b844564c4c1b4c1c22c9c2a6350683c3..8fbe2ce8c2953cd1d72eef33abdd40c4e64ea5c2 100644 (file)
@@ -109,10 +109,6 @@ POSTALIAS(1)                                         POSTALIAS(1)
        cess (including successful <b>postmap</b> <b>-q</b> lookup)  and  termi-
        nates with non-zero exit status in case of failure.
 
-<b>BUGS</b>
-       The  "delete  key" support is limited to one delete opera-
-       tion per command invocation.
-
 <b>ENVIRONMENT</b>
        <b>MAIL</b><i>_</i><b>CONFIG</b>
               Directory with Postfix configuration files.
@@ -121,12 +117,12 @@ POSTALIAS(1)                                         POSTALIAS(1)
               Enable verbose logging for debugging purposes.
 
 <b>CONFIGURATION</b> <b>PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
-       to  this  program. See the Postfix <b>main.cf</b> file for syntax
+       The  following  <b>main.cf</b> parameters are especially relevant
+       to this program. See the Postfix <b>main.cf</b> file  for  syntax
        details and for default values.
 
        <b>database</b><i>_</i><b>type</b>
-              Default alias database type. On many UNIX  systems,
+              Default  alias database type. On many UNIX systems,
               the default type is either <b>dbm</b> or <b>hash</b>.
 
 <b>STANDARDS</b>
@@ -137,7 +133,7 @@ POSTALIAS(1)                                         POSTALIAS(1)
        <a href="sendmail.1.html">sendmail(1)</a> mail posting and compatibility interface.
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index eff9ea79a790dbd7a5c4381b075a22084140190e..9a43c2bbe668a75090f6216895709bf9969d007b 100644 (file)
@@ -127,10 +127,6 @@ POSTMAP(1)                                             POSTMAP(1)
        cess (including successful <b>postmap</b> <b>-q</b> lookup)  and  termi-
        nates with non-zero exit status in case of failure.
 
-<b>BUGS</b>
-       The  "delete  key" support is limited to one delete opera-
-       tion per command invocation.
-
 <b>ENVIRONMENT</b>
        <b>MAIL</b><i>_</i><b>CONFIG</b>
               Directory with Postfix configuration files.
@@ -140,12 +136,12 @@ POSTMAP(1)                                             POSTMAP(1)
 
 <b>CONFIGURATION</b> <b>PARAMETERS</b>
        <b>database</b><i>_</i><b>type</b>
-              Default output database type.  On  many  UNIX  sys-
-              tems,  the  default database type is either <b>hash</b> or
+              Default  output  database  type.  On many UNIX sys-
+              tems, the default database type is either  <b>hash</b>  or
               <b>dbm</b>.
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index 1e8b32833fa335fc46026cfc01698c5225091179..ac7da6d2e6befae9a32c918b86bc9b1877edf732 100644 (file)
@@ -98,11 +98,6 @@ flagged with a warning.
 \fBpostalias\fR terminates with zero exit status in case of success
 (including successful \fBpostmap -q\fR lookup) and terminates
 with non-zero exit status in case of failure.
-.SH BUGS
-.ad
-.fi
-The "delete key" support is limited to one delete operation
-per command invocation.
 .SH ENVIRONMENT
 .na
 .nf
index 2f0b9c6c158bfedb6a9f97aaa42d65ebd59bb92a..83f8cd4248f42ed1069573b9a833c0f202b7e626 100644 (file)
@@ -115,11 +115,6 @@ skipped and are flagged with a warning.
 \fBpostmap\fR terminates with zero exit status in case of success
 (including successful \fBpostmap -q\fR lookup) and terminates
 with non-zero exit status in case of failure.
-.SH BUGS
-.ad
-.fi
-The "delete key" support is limited to one delete operation
-per command invocation.
 .SH ENVIRONMENT
 .na
 .nf
index 2cbdb5a3ac51c1a0c39814a0aa363b35f61e54a3..098cc294236721cd1d32ca556706459000738190 100644 (file)
@@ -121,6 +121,9 @@ Address mapping lookup table for envelope recipient addresses.
 Limit the number of envelope recipients that are remembered.
 .IP \fBheader_size_limit\fR
 Limit the amount of memory in bytes used to process a message header.
+.IP \fBin_flow_delay\fR
+Amount of time to pause before accepting a message, when the
+message arrival rate exceeds the message delivery rate.
 .IP \fBextract_recipient_limit\fR
 Limit the amount of recipients extracted from message headers.
 .SH SEE ALSO
index 1d457753dab06b8b1b1d542325bc2ea37a693805..7e7b369ad9a2ea283caf39eac15891783fe96c86 100644 (file)
 /*     Limit the number of envelope recipients that are remembered.
 /* .IP \fBheader_size_limit\fR
 /*     Limit the amount of memory in bytes used to process a message header.
+/* .IP \fBin_flow_delay\fR
+/*     Amount of time to pause before accepting a message, when the
+/*     message arrival rate exceeds the message delivery rate.
 /* .IP \fBextract_recipient_limit\fR
 /*     Limit the amount of recipients extracted from message headers.
 /* SEE ALSO
index 45eaecaa4c9a2714b1d2af98d272a9a808085ea7..bf273b250822a4a1841068a23f55f6b1e413a158 100644 (file)
@@ -1283,6 +1283,10 @@ extern char *var_verp_delims;
 #define DEF_VERP_FILTER                        "-=+"
 extern char *var_verp_filter;
 
+#define VAR_VERP_BOUNCE_OFF            "disable_verp_bounces"
+#define DEF_VERP_BOUNCE_OFF            0
+extern bool var_verp_bounce_off;
+
  /*
   * Inbound mail flow control. This allows for a stiffer coupling between
   * receiving mail and sending mail. A sending process produces one token for
index 3079cb8ea862e621d91346f2f05d400a762f7bf8..234a54fe4de194ea999d0811f1305ed98484c2bd 100644 (file)
@@ -15,7 +15,7 @@
   * Version of this program.
   */
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "Snapshot-20010730"
+#define DEF_MAIL_VERSION       "Snapshot-20010731"
 extern char *var_mail_version;
 
 /* LICENSE
index f06232989c641b615553efa78a2a25cda901e5f0..1dc8aaf4fdb427e182c0e4dc0baf59df22782fe2 100644 (file)
@@ -107,6 +107,14 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
                          VAR_INET_INTERFACES, host);
        myfree(hosts);
 
+       /*
+        * Weed out duplicate IP addresses. Duplicates happen when the same
+        * IP address is listed under multiple hostnames. If we don't weed
+        * out duplicates, Postfix can suddenly stop working after the DNS is
+        * changed.
+        */
+       inet_addr_list_uniq(addr_list);
+
        inet_addr_list_init(&local_addrs);
        inet_addr_list_init(&local_masks);
        if (inet_addr_local(&local_addrs, &local_masks) == 0)
index 3a42df080a8e7ce6e6d285c6e46441579a97f2c7..292e84a4c9376899db095c2785beca49a8aa6221 100644 (file)
@@ -106,9 +106,11 @@ int     mail_flow_put(int len)
     /*
      * Write or discard N bytes.
      */
+    memset(buf, 0, len > BUFFER_SIZE ? BUFFER_SIZE : len);
+
     for (count = len; count > 0; count -= n)
        if ((n = write(MASTER_FLOW_WRITE, buf, count > BUFFER_SIZE ?
-                     BUFFER_SIZE : count)) < 0)
+                      BUFFER_SIZE : count)) < 0)
            return (-1);
     if (msg_verbose)
        msg_info("%s: %d %d", myname, len, len - count);
index 6185a0be9ccbb52a4e731443873e5d3ce8dbc8e5..438691b50752538d544f37922d836d0202e0f9f6 100644 (file)
@@ -336,6 +336,7 @@ bool    var_allow_min_user;
 int     var_local_con_lim;
 int     var_local_rcpt_lim;
 int     var_proc_limit;
+bool    var_verp_bounce_off;
 
 static QMGR_SCAN *qmgr_incoming;
 static QMGR_SCAN *qmgr_deferred;
@@ -514,7 +515,7 @@ static void qmgr_post_init(char *unused_name, char **unused_argv)
     qmgr_incoming = qmgr_scan_create(MAIL_QUEUE_INCOMING);
     qmgr_deferred = qmgr_scan_create(MAIL_QUEUE_DEFERRED);
     qmgr_scan_request(qmgr_incoming, QMGR_SCAN_START);
-    qmgr_deferred_run_event(0, (char *)0);
+    qmgr_deferred_run_event(0, (char *) 0);
 }
 
 /* main - the main program */
@@ -555,6 +556,7 @@ int     main(int argc, char **argv)
     };
     static CONFIG_BOOL_TABLE bool_table[] = {
        VAR_ALLOW_MIN_USER, DEF_ALLOW_MIN_USER, &var_allow_min_user,
+       VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off,
        0,
     };
 
index 6d22e806a90a4da298cd51d944b0dc94432109ad..8f28b068661a64d6e5df9a58eee36e8a35b67019 100644 (file)
@@ -275,7 +275,7 @@ void    qmgr_active_done(QMGR_MESSAGE *message)
        } else {
            if (msg_verbose)
                msg_info("%s: bounce %s", myname, message->queue_id);
-           if (message->verp_delims == 0)
+           if (message->verp_delims == 0 || var_verp_bounce_off)
                abounce_flush(BOUNCE_FLAG_KEEP,
                              message->queue_name,
                              message->queue_id,
@@ -362,7 +362,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
        if (event_time() > message->arrival_time + var_max_queue_time) {
            msg_info("%s: from=<%s>, status=expired, returned to sender",
                     message->queue_id, message->sender);
-           if (message->verp_delims == 0)
+           if (message->verp_delims == 0 || var_verp_bounce_off)
                adefer_flush(BOUNCE_FLAG_KEEP,
                             message->queue_name,
                             message->queue_id,
index a705aadc4ef09ed99296c80107b389d6ef66e14f..95a4e092a2a1a5e4478519eec97c217c7819eb04 100644 (file)
@@ -295,6 +295,7 @@ int     var_qmgr_hog;
 int     var_local_rcpt_lim;            /* XXX */
 int     var_local_con_lim;             /* XXX */
 int     var_proc_limit;
+bool    var_verp_bounce_off;
 
 static QMGR_SCAN *qmgr_incoming;
 static QMGR_SCAN *qmgr_deferred;
@@ -512,6 +513,7 @@ int     main(int argc, char **argv)
     };
     static CONFIG_BOOL_TABLE bool_table[] = {
        VAR_ALLOW_MIN_USER, DEF_ALLOW_MIN_USER, &var_allow_min_user,
+       VAR_VERP_BOUNCE_OFF, DEF_VERP_BOUNCE_OFF, &var_verp_bounce_off,
        0,
     };
 
index 6d22e806a90a4da298cd51d944b0dc94432109ad..8f28b068661a64d6e5df9a58eee36e8a35b67019 100644 (file)
@@ -275,7 +275,7 @@ void    qmgr_active_done(QMGR_MESSAGE *message)
        } else {
            if (msg_verbose)
                msg_info("%s: bounce %s", myname, message->queue_id);
-           if (message->verp_delims == 0)
+           if (message->verp_delims == 0 || var_verp_bounce_off)
                abounce_flush(BOUNCE_FLAG_KEEP,
                              message->queue_name,
                              message->queue_id,
@@ -362,7 +362,7 @@ static void qmgr_active_done_2_generic(QMGR_MESSAGE *message)
        if (event_time() > message->arrival_time + var_max_queue_time) {
            msg_info("%s: from=<%s>, status=expired, returned to sender",
                     message->queue_id, message->sender);
-           if (message->verp_delims == 0)
+           if (message->verp_delims == 0 || var_verp_bounce_off)
                adefer_flush(BOUNCE_FLAG_KEEP,
                             message->queue_name,
                             message->queue_id,
index 2031632ee7d985a52fdcb5995fb9d1af62d77077..73a26230671e98ad9543a2539d72c9275f01cd72 100644 (file)
@@ -171,6 +171,7 @@ smtpd_check.o: ../../include/mymalloc.h
 smtpd_check.o: ../../include/dict.h
 smtpd_check.o: ../../include/vstream.h
 smtpd_check.o: ../../include/htable.h
+smtpd_check.o: ../../include/ctable.h
 smtpd_check.o: ../../include/dns.h
 smtpd_check.o: ../../include/namadr_list.h
 smtpd_check.o: ../../include/domain_list.h
index feedc802097b384b64004de9cad35d586d1f745f..29fb3d2d743dd8b0cee2d23d2bd86d29b1691324 100644 (file)
@@ -67,7 +67,6 @@ typedef struct SMTPD_STATE {
     int     recursion;
     off_t   msg_size;
     int     junk_cmds;
-    VSTRING *error_text;
 #ifdef USE_SASL_AUTH
     char   *sasl_mechanism_list;
     char   *sasl_method;
index c22ebd5c8985969d18136d7cd7ab752214806727..ca492963487f621014c416b0e4630265033e54a0 100644 (file)
@@ -91,7 +91,6 @@ void    smtpd_state_init(SMTPD_STATE *state, VSTREAM *stream)
     state->recursion = 0;
     state->msg_size = 0;
     state->junk_cmds = 0;
-    state->error_text = vstring_alloc(100);
 
 #ifdef USE_SASL_AUTH
     if (SMTPD_STAND_ALONE(state))
@@ -124,7 +123,6 @@ void    smtpd_state_reset(SMTPD_STATE *state)
     if (state->buffer)
        vstring_free(state->buffer);
     smtpd_peer_reset(state);
-    vstring_free(state->error_text);
 
 #ifdef USE_SASL_AUTH
     if (var_smtpd_sasl_enable)
index d7e85a063d3124ee27eb6a27608e6e618efe0acd..04fa8037a8275143f6aaff296e8e49a7782db331 100644 (file)
@@ -80,7 +80,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        inet_addr_host inet_addr_local mac_parse make_dirs msg_syslog \
        mystrtok sigdelay translit valid_hostname vstream_popen \
        vstring vstring_vstream doze select_bug stream_test mac_expand \
-       watchdog unescape hex_quote name_mask rand_sleep sane_time ctable
+       watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
+       inet_addr_list
 
 LIB_DIR        = ../../lib
 INC_DIR        = ../../include
@@ -279,6 +280,11 @@ ctable: $(LIB)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
+inet_addr_list: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
        set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -291,7 +297,7 @@ stream_test: stream_test.c $(LIB)
        $(CC) $(CFLAGS)  -o $@ $@.c $(LIB) $(SYSLIBS)
 
 tests: valid_hostname_test mac_expand_test dict_test unescape_test \
-       hex_quote_test cache_test
+       hex_quote_test ctable_test inet_addr_list_test
 
 valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
        ./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
@@ -319,6 +325,11 @@ ctable_test: ctable
        diff ctable.ref ctable.tmp
        rm -f ctable.tmp
 
+inet_addr_list_test: inet_addr_list
+       ./inet_addr_list `cat inet_addr_list.in` >inet_addr_list.tmp 2>&1
+       diff inet_addr_list.ref inet_addr_list.tmp
+       rm -f inet_addr_list.tmp
+
 DB_TYPE        = `../postconf/postconf -h default_database_type`
 
 dict_test: dict_open testdb dict_test.in dict_test.ref
index d449e76c77db7122cf9e65e24e1f3f8eee6b2dd9..fa1cbd3990087202767b87488c6bf0d1977d738a 100644 (file)
@@ -13,6 +13,9 @@
 /*     INET_ADDR_LIST *list;
 /*     struct in_addr *addr;
 /*
+/*     void    inet_addr_list_uniq(list)
+/*     INET_ADDR_LIST *list;
+/*
 /*     void    inet_addr_list_free(list)
 /*     INET_ADDR_LIST *list;
 /* DESCRIPTION
@@ -25,6 +28,9 @@
 /*     inet_addr_list_append() appends the specified address to
 /*     the specified list, extending the list on the fly.
 /*
+/*     inet_addr_list_uniq() sorts the specified address list and
+/*     eliminates duplicates.
+/*
 /*     inet_addr_list_free() reclaims memory used for the
 /*     specified address list.
 /* LICENSE
@@ -43,6 +49,7 @@
 #include <sys_defs.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <stdlib.h>
 
 /* Utility library. */
 
@@ -77,9 +84,81 @@ void    inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
     list->addrs[list->used++] = *addr;
 }
 
+/* inet_addr_list_comp - compare addresses */
+
+static int inet_addr_list_comp(const void *a, const void *b)
+{
+    const struct in_addr *a_addr = (const struct in_addr *) a;
+    const struct in_addr *b_addr = (const struct in_addr *) b;
+
+    return (a_addr->s_addr - b_addr->s_addr);
+}
+
+/* inet_addr_list_uniq - weed out duplicates */
+
+void    inet_addr_list_uniq(INET_ADDR_LIST *list)
+{
+    int     n;
+    int     m;
+
+    /*
+     * Put the identical members right next to each other.
+     */
+    qsort((void *) list->addrs, list->used,
+         sizeof(list->addrs[0]), inet_addr_list_comp);
+
+    /*
+     * Nuke the duplicates. Postcondition after while loop: m is the largest
+     * index for which list->addrs[n] == list->addrs[m].
+     */
+    for (m = n = 0; m < list->used; m++, n++) {
+       if (m != n)
+           list->addrs[n] = list->addrs[m];
+       while (m + 1 < list->used
+              && inet_addr_list_comp((void *) &(list->addrs[n]),
+                                     (void *) &(list->addrs[m + 1])) == 0)
+           m += 1;
+    }
+    list->used = n;
+}
+
 /* inet_addr_list_free - destroy internet address list */
 
 void    inet_addr_list_free(INET_ADDR_LIST *list)
 {
     myfree((char *) list->addrs);
 }
+
+#ifdef TEST
+
+ /*
+  * Duplicate elimination needs to be tested.
+  */
+#include <inet_addr_host.h>
+
+static void inet_addr_list_print(INET_ADDR_LIST *list)
+{
+    int     n;
+
+    for (n = 0; n < list->used; n++)
+       msg_info("%s", inet_ntoa(list->addrs[n]));
+}
+
+int     main(int argc, char **argv)
+{
+    INET_ADDR_LIST list;
+
+    inet_addr_list_init(&list);
+    while (--argc && *++argv)
+       if (inet_addr_host(&list, *argv) == 0)
+           msg_fatal("host not found: %s", *argv);
+    msg_info("list before sort/uniq");
+    inet_addr_list_print(&list);
+    inet_addr_list_uniq(&list);
+    msg_info("list after sort/uniq");
+    inet_addr_list_print(&list);
+    inet_addr_list_free(&list);
+    return (0);
+}
+
+#endif
index 48a4c9712d51a14b9f4a52bc346d1a4897611836..372b3ccb76adc7fc15915a772cad9335bcf5989b 100644 (file)
@@ -27,6 +27,7 @@ typedef struct INET_ADDR_LIST {
 
 extern void inet_addr_list_init(INET_ADDR_LIST *);
 extern void inet_addr_list_free(INET_ADDR_LIST *);
+extern void inet_addr_list_uniq(INET_ADDR_LIST *);
 extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
 
 /* LICENSE
diff --git a/postfix/src/util/inet_addr_list.in b/postfix/src/util/inet_addr_list.in
new file mode 100644 (file)
index 0000000..742281f
--- /dev/null
@@ -0,0 +1,9 @@
+168.100.189.2
+168.100.189.2
+168.100.189.1
+168.100.189.3
+168.100.189.3
+168.100.189.3
+168.100.189.4
+168.100.189.1
+168.100.189.4
diff --git a/postfix/src/util/inet_addr_list.ref b/postfix/src/util/inet_addr_list.ref
new file mode 100644 (file)
index 0000000..0a8a56e
--- /dev/null
@@ -0,0 +1,15 @@
+unknown: list before sort/uniq
+unknown: 168.100.189.2
+unknown: 168.100.189.2
+unknown: 168.100.189.1
+unknown: 168.100.189.3
+unknown: 168.100.189.3
+unknown: 168.100.189.3
+unknown: 168.100.189.4
+unknown: 168.100.189.1
+unknown: 168.100.189.4
+unknown: list after sort/uniq
+unknown: 168.100.189.1
+unknown: 168.100.189.2
+unknown: 168.100.189.3
+unknown: 168.100.189.4