diff --git a/postfix/HISTORY b/postfix/HISTORY index bd9f61782..0a42ce0b6 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -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. diff --git a/postfix/RELEASE_NOTES b/postfix/RELEASE_NOTES index bc9f2771e..721d02f59 100644 --- a/postfix/RELEASE_NOTES +++ b/postfix/RELEASE_NOTES @@ -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 =========================================== diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index 8807373a4..5e6b2c4c8 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -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 diff --git a/postfix/html/cleanup.8.html b/postfix/html/cleanup.8.html index 3f55c1de4..48ab1db87 100644 --- a/postfix/html/cleanup.8.html +++ b/postfix/html/cleanup.8.html @@ -133,6 +133,11 @@ CLEANUP(8) CLEANUP(8) Limit the amount of memory in bytes used to process a message header. + in_flow_delay + Amount of time to pause before accepting a message, + when the message arrival rate exceeds the message + delivery rate. + extract_recipient_limit Limit the amount of recipients extracted from mes- sage headers. diff --git a/postfix/html/postalias.1.html b/postfix/html/postalias.1.html index c1f00012b..8fbe2ce8c 100644 --- a/postfix/html/postalias.1.html +++ b/postfix/html/postalias.1.html @@ -109,10 +109,6 @@ POSTALIAS(1) POSTALIAS(1) cess (including successful postmap -q lookup) and termi- nates with non-zero exit status in case of failure. -BUGS - The "delete key" support is limited to one delete opera- - tion per command invocation. - ENVIRONMENT MAIL_CONFIG Directory with Postfix configuration files. @@ -121,12 +117,12 @@ POSTALIAS(1) POSTALIAS(1) Enable verbose logging for debugging purposes. CONFIGURATION PARAMETERS - The following main.cf parameters are especially relevant - to this program. See the Postfix main.cf file for syntax + The following main.cf parameters are especially relevant + to this program. See the Postfix main.cf file for syntax details and for default values. database_type - Default alias database type. On many UNIX systems, + Default alias database type. On many UNIX systems, the default type is either dbm or hash. STANDARDS @@ -137,7 +133,7 @@ POSTALIAS(1) POSTALIAS(1) sendmail(1) mail posting and compatibility interface. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/html/postmap.1.html b/postfix/html/postmap.1.html index eff9ea79a..9a43c2bbe 100644 --- a/postfix/html/postmap.1.html +++ b/postfix/html/postmap.1.html @@ -127,10 +127,6 @@ POSTMAP(1) POSTMAP(1) cess (including successful postmap -q lookup) and termi- nates with non-zero exit status in case of failure. -BUGS - The "delete key" support is limited to one delete opera- - tion per command invocation. - ENVIRONMENT MAIL_CONFIG Directory with Postfix configuration files. @@ -140,12 +136,12 @@ POSTMAP(1) POSTMAP(1) CONFIGURATION PARAMETERS database_type - Default output database type. On many UNIX sys- - tems, the default database type is either hash or + Default output database type. On many UNIX sys- + tems, the default database type is either hash or dbm. LICENSE - The Secure Mailer license must be distributed with this + The Secure Mailer license must be distributed with this software. AUTHOR(S) diff --git a/postfix/man/man1/postalias.1 b/postfix/man/man1/postalias.1 index 1e8b32833..ac7da6d2e 100644 --- a/postfix/man/man1/postalias.1 +++ b/postfix/man/man1/postalias.1 @@ -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 diff --git a/postfix/man/man1/postmap.1 b/postfix/man/man1/postmap.1 index 2f0b9c6c1..83f8cd424 100644 --- a/postfix/man/man1/postmap.1 +++ b/postfix/man/man1/postmap.1 @@ -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 diff --git a/postfix/man/man8/cleanup.8 b/postfix/man/man8/cleanup.8 index 2cbdb5a3a..098cc2942 100644 --- a/postfix/man/man8/cleanup.8 +++ b/postfix/man/man8/cleanup.8 @@ -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 diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index 1d457753d..7e7b369ad 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -107,6 +107,9 @@ /* 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 diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h index 45eaecaa4..bf273b250 100644 --- a/postfix/src/global/mail_params.h +++ b/postfix/src/global/mail_params.h @@ -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 diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 3079cb8ea..234a54fe4 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -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 diff --git a/postfix/src/global/own_inet_addr.c b/postfix/src/global/own_inet_addr.c index f06232989..1dc8aaf4f 100644 --- a/postfix/src/global/own_inet_addr.c +++ b/postfix/src/global/own_inet_addr.c @@ -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) diff --git a/postfix/src/master/mail_flow.c b/postfix/src/master/mail_flow.c index 3a42df080..292e84a4c 100644 --- a/postfix/src/master/mail_flow.c +++ b/postfix/src/master/mail_flow.c @@ -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); diff --git a/postfix/src/nqmgr/qmgr.c b/postfix/src/nqmgr/qmgr.c index 6185a0be9..438691b50 100644 --- a/postfix/src/nqmgr/qmgr.c +++ b/postfix/src/nqmgr/qmgr.c @@ -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, }; diff --git a/postfix/src/nqmgr/qmgr_active.c b/postfix/src/nqmgr/qmgr_active.c index 6d22e806a..8f28b0686 100644 --- a/postfix/src/nqmgr/qmgr_active.c +++ b/postfix/src/nqmgr/qmgr_active.c @@ -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, diff --git a/postfix/src/qmgr/qmgr.c b/postfix/src/qmgr/qmgr.c index a705aadc4..95a4e092a 100644 --- a/postfix/src/qmgr/qmgr.c +++ b/postfix/src/qmgr/qmgr.c @@ -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, }; diff --git a/postfix/src/qmgr/qmgr_active.c b/postfix/src/qmgr/qmgr_active.c index 6d22e806a..8f28b0686 100644 --- a/postfix/src/qmgr/qmgr_active.c +++ b/postfix/src/qmgr/qmgr_active.c @@ -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, diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 2031632ee..73a262306 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -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 diff --git a/postfix/src/smtpd/smtpd.h b/postfix/src/smtpd/smtpd.h index feedc8020..29fb3d2d7 100644 --- a/postfix/src/smtpd/smtpd.h +++ b/postfix/src/smtpd/smtpd.h @@ -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; diff --git a/postfix/src/smtpd/smtpd_state.c b/postfix/src/smtpd/smtpd_state.c index c22ebd5c8..ca4929634 100644 --- a/postfix/src/smtpd/smtpd_state.c +++ b/postfix/src/smtpd/smtpd_state.c @@ -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) diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index d7e85a063..04fa8037a 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -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.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 diff --git a/postfix/src/util/inet_addr_list.c b/postfix/src/util/inet_addr_list.c index d449e76c7..fa1cbd399 100644 --- a/postfix/src/util/inet_addr_list.c +++ b/postfix/src/util/inet_addr_list.c @@ -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 #include #include +#include /* 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 + +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 diff --git a/postfix/src/util/inet_addr_list.h b/postfix/src/util/inet_addr_list.h index 48a4c9712..372b3ccb7 100644 --- a/postfix/src/util/inet_addr_list.h +++ b/postfix/src/util/inet_addr_list.h @@ -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 index 000000000..742281fae --- /dev/null +++ b/postfix/src/util/inet_addr_list.in @@ -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 index 000000000..0a8a56e1a --- /dev/null +++ b/postfix/src/util/inet_addr_list.ref @@ -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