diff --git a/postfix/HISTORY b/postfix/HISTORY
index d9edf263a..239401f75 100644
--- a/postfix/HISTORY
+++ b/postfix/HISTORY
@@ -7235,6 +7235,22 @@ Apologies for any names omitted.
send data into unauthorized ports. Files: *qmgr/qmgr_message.c,
trivial-rewrite/resolve.c.
+20021128
+
+ Feature: hashed hold queue support, with hashing turned on
+ by default. Omission spotted by Victor Duchovni, Morgan
+ Stanley. Files: global/hold_message.c, global/mail_params.h.
+
+ Bugfix: the LMTP client lost the port(service) information
+ when parsing host:port information. Victor Duchovni, Morgan
+ Stanley. Fix is to have a new host_port(3) module that does
+ the parsing for the SMTP and LMTP clients.
+
+ Cleanup: host_port() routine that parses host/port information
+ more consistently than the existing code in the LMTP and
+ SMTP clients. Files: smtp/smtp_connect.c, lmtp/lmtp_connect.c,
+ util/host_port.[hc].
+
Open problems:
Low: revise other local delivery agent duplicate filters.
diff --git a/postfix/conf/access b/postfix/conf/access
index 9810d5237..1d7e01e64 100644
--- a/postfix/conf/access
+++ b/postfix/conf/access
@@ -74,19 +74,18 @@
# Note: lookup of the null sender address is not possible
# with some types of lookup table. By default, Postfix uses
# <> as the lookup key for such addresses. The value is
-# specified with the workaround is to specify
-# smtpd_null_access_lookup_key parameter in the Postfix
-# main.cf file.
+# specified with the smtpd_null_access_lookup_key parameter
+# in the Postfix main.cf file.
#
# ADDRESS EXTENSION
# When a mail address localpart contains the optional recip-
-# ient delimiter (e.g., user+foo@domain), the lookup order
-# becomes: user+foo@domain, user@domain, domain, user+foo@,
+# ient delimiter (e.g., user+foo@domain), the lookup order
+# becomes: user+foo@domain, user@domain, domain, user+foo@,
# and user@.
#
# HOST NAME/ADDRESS PATTERNS
# With lookups from indexed files such as DB or DBM, or from
-# networked tables such as NIS, LDAP or SQL, the following
+# networked tables such as NIS, LDAP or SQL, the following
# lookup patterns are examined in the order as listed:
#
# domain.tld
@@ -94,9 +93,9 @@
#
# The pattern domain.tld also matches subdomains, but
# only when the string smtpd_access_maps is listed in
-# the Postfix parent_domain_matches_subdomains con-
+# the Postfix parent_domain_matches_subdomains con-
# figuration setting. Otherwise, specify .domain.tld
-# (note the initial dot) in order to match subdo-
+# (note the initial dot) in order to match subdo-
# mains.
#
# net.work.addr.ess
@@ -105,67 +104,67 @@
#
# net.work
#
-# net Matches any host address in the specified network.
-# A network address is a sequence of one or more
+# net Matches any host address in the specified network.
+# A network address is a sequence of one or more
# octets separated by ".".
#
# ACTIONS
# [45]NN text
-# Reject the address etc. that matches the pattern,
+# Reject the address etc. that matches the pattern,
# and respond with the numerical code and text.
#
# REJECT
#
# REJECT optional text...
-# Reject the address etc. that matches the pattern.
-# Reply with $reject_code optional text... when the
-# optional text is specified, otherwise reply with a
+# Reject the address etc. that matches the pattern.
+# Reply with $reject_code optional text... when the
+# optional text is specified, otherwise reply with a
# generic error response message.
#
# OK Accept the address etc. that matches the pattern.
#
# all-numerical
# An all-numerical result is treated as OK. This for-
-# mat is generated by address-based relay authoriza-
+# mat is generated by address-based relay authoriza-
# tion schemes.
#
-# DUNNO Pretend that the lookup key was not found in this
-# table, to prevents Postfix from trying substrings
-# of the lookup key (such as a subdomain name, or a
+# DUNNO Pretend that the lookup key was not found in this
+# table, to prevents Postfix from trying substrings
+# of the lookup key (such as a subdomain name, or a
# network address subnetwork).
#
# HOLD
#
# HOLD optional text...
-# Place the message on the hold queue, where it will
-# sit until someone either deletes it or releases it
-# for delivery. Log the optional text if specified,
+# Place the message on the hold queue, where it will
+# sit until someone either deletes it or releases it
+# for delivery. Log the optional text if specified,
# otherwise log a generic message.
#
-# Mail that is placed on hold can be examined with
-# the postcat(1) command, and can be destroyed or
+# Mail that is placed on hold can be examined with
+# the postcat(1) command, and can be destroyed or
# released with the postsuper(1) command.
#
-# Note: this action currently affects all recipients
+# Note: this action currently affects all recipients
# of the message.
#
# DISCARD
#
# DISCARD optional text...
-# Claim successful delivery and silently discard the
-# message. Log the optional text if specified, oth-
+# Claim successful delivery and silently discard the
+# message. Log the optional text if specified, oth-
# erwise log a generic message.
#
-# Note: this action currently affects all recipients
+# Note: this action currently affects all recipients
# of the message.
#
# FILTER transport:destination
-# After the message is queued, send the entire mes-
-# sage through a content filter. More information
+# After the message is queued, send the entire mes-
+# sage through a content filter. More information
# about content filters is in the Postfix FIL-
# TER_README file.
#
-# Note: this action currently affects all recipients
+# Note: this action currently affects all recipients
# of the message.
#
# restriction...
@@ -173,30 +172,30 @@
# reject_unauth_destination, and so on).
#
# REGULAR EXPRESSION TABLES
-# This section describes how the table lookups change when
+# This section describes how the table lookups change when
# the table is given in the form of regular expressions. For
-# a description of regular expression lookup table syntax,
+# a description of regular expression lookup table syntax,
# see regexp_table(5) or pcre_table(5).
#
-# Each pattern is a regular expression that is applied to
+# Each pattern is a regular expression that is applied to
# the entire string being looked up. Depending on the appli-
-# cation, that string is an entire client hostname, an
+# cation, that string is an entire client hostname, an
# entire client IP address, or an entire mail address. Thus,
# no parent domain or parent network search is done,
-# user@domain mail addresses are not broken up into their
+# user@domain mail addresses are not broken up into their
# user@ and domain constituent parts, nor is user+foo broken
# up into user and foo.
#
-# Patterns are applied in the order as specified in the
-# table, until a pattern is found that matches the search
+# Patterns are applied in the order as specified in the
+# table, until a pattern is found that matches the search
# string.
#
-# Actions are the same as with indexed file lookups, with
-# the additional feature that parenthesized substrings from
+# Actions are the same as with indexed file lookups, with
+# the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on.
#
# BUGS
-# The table format does not understand quoting conventions.
+# The table format does not understand quoting conventions.
#
# SEE ALSO
# postmap(1) create mapping table
@@ -205,7 +204,7 @@
# regexp_table(5) format of POSIX regular expression tables
#
# 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/access.5.html b/postfix/html/access.5.html
index 64186e76d..71f575c84 100644
--- a/postfix/html/access.5.html
+++ b/postfix/html/access.5.html
@@ -75,19 +75,18 @@ ACCESS(5) ACCESS(5)
Note: lookup of the null sender address is not possible
with some types of lookup table. By default, Postfix uses
<> as the lookup key for such addresses. The value is
- specified with the workaround is to specify
- smtpd_null_access_lookup_key parameter in the Postfix
- main.cf file.
+ specified with the smtpd_null_access_lookup_key parameter
+ in the Postfix main.cf file.
ADDRESS EXTENSION
When a mail address localpart contains the optional recip-
- ient delimiter (e.g., user+foo@domain), the lookup order
- becomes: user+foo@domain, user@domain, domain, user+foo@,
+ ient delimiter (e.g., user+foo@domain), the lookup order
+ becomes: user+foo@domain, user@domain, domain, user+foo@,
and user@.
HOST NAME/ADDRESS PATTERNS
With lookups from indexed files such as DB or DBM, or from
- networked tables such as NIS, LDAP or SQL, the following
+ networked tables such as NIS, LDAP or SQL, the following
lookup patterns are examined in the order as listed:
domain.tld
@@ -95,9 +94,9 @@ ACCESS(5) ACCESS(5)
The pattern domain.tld also matches subdomains, but
only when the string smtpd_access_maps is listed in
- the Postfix parent_domain_matches_subdomains con-
+ the Postfix parent_domain_matches_subdomains con-
figuration setting. Otherwise, specify .domain.tld
- (note the initial dot) in order to match subdo-
+ (note the initial dot) in order to match subdo-
mains.
net.work.addr.ess
@@ -106,67 +105,67 @@ ACCESS(5) ACCESS(5)
net.work
- net Matches any host address in the specified network.
- A network address is a sequence of one or more
+ net Matches any host address in the specified network.
+ A network address is a sequence of one or more
octets separated by ".".
ACTIONS
[45]NN text
- Reject the address etc. that matches the pattern,
+ Reject the address etc. that matches the pattern,
and respond with the numerical code and text.
REJECT
REJECT optional text...
- Reject the address etc. that matches the pattern.
- Reply with $reject_code optional text... when the
- optional text is specified, otherwise reply with a
+ Reject the address etc. that matches the pattern.
+ Reply with $reject_code optional text... when the
+ optional text is specified, otherwise reply with a
generic error response message.
OK Accept the address etc. that matches the pattern.
all-numerical
An all-numerical result is treated as OK. This for-
- mat is generated by address-based relay authoriza-
+ mat is generated by address-based relay authoriza-
tion schemes.
- DUNNO Pretend that the lookup key was not found in this
- table, to prevents Postfix from trying substrings
- of the lookup key (such as a subdomain name, or a
+ DUNNO Pretend that the lookup key was not found in this
+ table, to prevents Postfix from trying substrings
+ of the lookup key (such as a subdomain name, or a
network address subnetwork).
HOLD
HOLD optional text...
- Place the message on the hold queue, where it will
- sit until someone either deletes it or releases it
- for delivery. Log the optional text if specified,
+ Place the message on the hold queue, where it will
+ sit until someone either deletes it or releases it
+ for delivery. Log the optional text if specified,
otherwise log a generic message.
- Mail that is placed on hold can be examined with
- the postcat(1) command, and can be destroyed or
+ Mail that is placed on hold can be examined with
+ the postcat(1) command, and can be destroyed or
released with the postsuper(1) command.
- Note: this action currently affects all recipients
+ Note: this action currently affects all recipients
of the message.
DISCARD
DISCARD optional text...
- Claim successful delivery and silently discard the
- message. Log the optional text if specified, oth-
+ Claim successful delivery and silently discard the
+ message. Log the optional text if specified, oth-
erwise log a generic message.
- Note: this action currently affects all recipients
+ Note: this action currently affects all recipients
of the message.
FILTER transport:destination
- After the message is queued, send the entire mes-
- sage through a content filter. More information
+ After the message is queued, send the entire mes-
+ sage through a content filter. More information
about content filters is in the Postfix FIL-
TER_README file.
- Note: this action currently affects all recipients
+ Note: this action currently affects all recipients
of the message.
restriction...
@@ -174,30 +173,30 @@ ACCESS(5) ACCESS(5)
reject_unauth_destination, and so on).
REGULAR EXPRESSION TABLES
- This section describes how the table lookups change when
+ This section describes how the table lookups change when
the table is given in the form of regular expressions. For
- a description of regular expression lookup table syntax,
+ a description of regular expression lookup table syntax,
see regexp_table(5) or pcre_table(5).
- Each pattern is a regular expression that is applied to
+ Each pattern is a regular expression that is applied to
the entire string being looked up. Depending on the appli-
- cation, that string is an entire client hostname, an
+ cation, that string is an entire client hostname, an
entire client IP address, or an entire mail address. Thus,
no parent domain or parent network search is done,
- user@domain mail addresses are not broken up into their
+ user@domain mail addresses are not broken up into their
user@ and domain constituent parts, nor is user+foo broken
up into user and foo.
- Patterns are applied in the order as specified in the
- table, until a pattern is found that matches the search
+ Patterns are applied in the order as specified in the
+ table, until a pattern is found that matches the search
string.
- Actions are the same as with indexed file lookups, with
- the additional feature that parenthesized substrings from
+ Actions are the same as with indexed file lookups, with
+ the additional feature that parenthesized substrings from
the pattern can be interpolated as $1, $2 and so on.
BUGS
- The table format does not understand quoting conventions.
+ The table format does not understand quoting conventions.
SEE ALSO
postmap(1) create mapping table
@@ -206,7 +205,7 @@ ACCESS(5) ACCESS(5)
regexp_table(5) format of POSIX regular expression tables
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/man5/access.5 b/postfix/man/man5/access.5
index 23afae49b..54d9974da 100644
--- a/postfix/man/man5/access.5
+++ b/postfix/man/man5/access.5
@@ -73,8 +73,8 @@ Matches all mail addresses with the specified user part.
Note: lookup of the null sender address is not possible with
some types of lookup table. By default, Postfix uses \fB<>\fR
as the lookup key for such addresses. The value is specified with
-the workaround is to specify \fBsmtpd_null_access_lookup_key\fR
-parameter in the Postfix \fBmain.cf\fR file.
+the \fBsmtpd_null_access_lookup_key\fR parameter in the Postfix
+\fBmain.cf\fR file.
.SH ADDRESS EXTENSION
.na
.nf
diff --git a/postfix/proto/access b/postfix/proto/access
index 1fc1a6a42..d9e0d3680 100644
--- a/postfix/proto/access
+++ b/postfix/proto/access
@@ -63,8 +63,8 @@
# Note: lookup of the null sender address is not possible with
# some types of lookup table. By default, Postfix uses \fB<>\fR
# as the lookup key for such addresses. The value is specified with
-# the workaround is to specify \fBsmtpd_null_access_lookup_key\fR
-# parameter in the Postfix \fBmain.cf\fR file.
+# the \fBsmtpd_null_access_lookup_key\fR parameter in the Postfix
+# \fBmain.cf\fR file.
# ADDRESS EXTENSION
# .fi
# .ad
diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c
index 6464b4827..bb06cb1b6 100644
--- a/postfix/src/cleanup/cleanup_api.c
+++ b/postfix/src/cleanup/cleanup_api.c
@@ -213,7 +213,9 @@ int cleanup_flush(CLEANUP_STATE *state)
*/
if (state->errs == 0 && (state->flags & CLEANUP_FLAG_DISCARD) == 0) {
if ((state->flags & CLEANUP_FLAG_HOLD) != 0) {
- hold_message(state->temp1, state->queue_name, state->queue_id);
+ if (hold_message(state->temp1, state->queue_name, state->queue_id) < 0)
+ msg_fatal("%s: problem putting message on hold: %m",
+ state->queue_id);
junk = cleanup_path;
cleanup_path = mystrdup(vstring_str(state->temp1));
myfree(junk);
diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in
index 329991927..6cf7e66aa 100644
--- a/postfix/src/global/Makefile.in
+++ b/postfix/src/global/Makefile.in
@@ -532,6 +532,7 @@ hold_message.o: hold_message.c
hold_message.o: ../../include/sys_defs.h
hold_message.o: ../../include/msg.h
hold_message.o: ../../include/set_eugid.h
+hold_message.o: ../../include/sane_fsops.h
hold_message.o: mail_queue.h
hold_message.o: ../../include/vstring.h
hold_message.o: ../../include/vbuf.h
diff --git a/postfix/src/global/hold_message.c b/postfix/src/global/hold_message.c
index d360a3b63..9a79a1b95 100644
--- a/postfix/src/global/hold_message.c
+++ b/postfix/src/global/hold_message.c
@@ -6,7 +6,7 @@
/* SYNOPSIS
/* #include
/*
-/* void hold_message(path_buf, queue_name, queue_id)
+/* int hold_message(path_buf, queue_name, queue_id)
/* VSTRING *path_buf;
/* const char *queue_name;
/* const char *queue_id;
@@ -22,6 +22,8 @@
/* Queue name with the message that needs to be placed on hold.
/* .IP queue_id
/* Queue file name with the message that needs to be placed on hold.
+/* DIAGNOSTICS
+/* The result is -1 in case of failure, 0 in case of success.
/* LICENSE
/* .ad
/* .fi
@@ -45,6 +47,7 @@
#include
#include
+#include
/* Global library. */
@@ -56,13 +59,14 @@
/* hold_message - move message to hold queue */
-void hold_message(VSTRING *path_buf, const char *queue_name,
+int hold_message(VSTRING *path_buf, const char *queue_name,
const char *queue_id)
{
VSTRING *old_path = vstring_alloc(100);
VSTRING *new_path = 0;
uid_t saved_uid;
gid_t saved_gid;
+ int err;
/*
* If not running as the mail system, change privileges first.
@@ -79,20 +83,16 @@ void hold_message(VSTRING *path_buf, const char *queue_name,
new_path = path_buf = vstring_alloc(100);
/*
- * Grr. Don't do stupid things when this function is called multiple
- * times. sane_rename() would emit a bogus warning about spurious NFS
- * problems.
+ * This code duplicates mail_queue_rename(), except that it also returns
+ * the result pathname to the caller.
*/
(void) mail_queue_path(old_path, queue_name, queue_id);
(void) mail_queue_path(path_buf, MAIL_QUEUE_HOLD, queue_id);
- if (access(STR(old_path), F_OK) == 0) {
- if (rename(STR(old_path), STR(path_buf)) == 0
- || (access(STR(old_path), F_OK) < 0
- && access(STR(path_buf), F_OK) == 0)) {
- if (msg_verbose)
- msg_info("%s: placed on hold", queue_id);
- } else
- msg_warn("%s: could not place message on hold: %m", queue_id);
+ if ((err = sane_rename(STR(old_path), STR(path_buf))) == 0
+ || ((err = mail_queue_mkdirs(STR(path_buf)) == 0)
+ && (err = sane_rename(STR(old_path), STR(path_buf))) == 0)) {
+ if (msg_verbose)
+ msg_info("%s: placed on hold", queue_id);
}
/*
@@ -107,4 +107,6 @@ void hold_message(VSTRING *path_buf, const char *queue_name,
vstring_free(old_path);
if (new_path)
vstring_free(new_path);
+
+ return (err);
}
diff --git a/postfix/src/global/hold_message.h b/postfix/src/global/hold_message.h
index 0b30a0154..ff0728bf0 100644
--- a/postfix/src/global/hold_message.h
+++ b/postfix/src/global/hold_message.h
@@ -14,7 +14,7 @@
/*
* External interface.
*/
-extern void hold_message(VSTRING *, const char *, const char *);
+extern int hold_message(VSTRING *, const char *, const char *);
/* LICENSE
/* .ad
diff --git a/postfix/src/global/mail_params.h b/postfix/src/global/mail_params.h
index a7677b653..18e23e211 100644
--- a/postfix/src/global/mail_params.h
+++ b/postfix/src/global/mail_params.h
@@ -658,7 +658,7 @@ extern int var_debug_peer_level;
* subdirectories, and how deep the forest is.
*/
#define VAR_HASH_QUEUE_NAMES "hash_queue_names"
-#define DEF_HASH_QUEUE_NAMES "incoming,active,deferred,bounce,defer,flush"
+#define DEF_HASH_QUEUE_NAMES "incoming,active,deferred,bounce,defer,flush,hold"
extern char *var_hash_queue_names;
#define VAR_HASH_QUEUE_DEPTH "hash_queue_depth"
diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h
index 042980ca8..5da134b90 100644
--- a/postfix/src/global/mail_version.h
+++ b/postfix/src/global/mail_version.h
@@ -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 "20021124"
+#define MAIL_RELEASE_DATE "20021130"
#define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "1.1.12-" MAIL_RELEASE_DATE
diff --git a/postfix/src/lmtp/Makefile.in b/postfix/src/lmtp/Makefile.in
index ba92b2f78..41303b3bc 100644
--- a/postfix/src/lmtp/Makefile.in
+++ b/postfix/src/lmtp/Makefile.in
@@ -129,6 +129,7 @@ lmtp_connect.o: ../../include/mymalloc.h
lmtp_connect.o: ../../include/iostuff.h
lmtp_connect.o: ../../include/timed_connect.h
lmtp_connect.o: ../../include/stringops.h
+lmtp_connect.o: ../../include/host_port.h
lmtp_connect.o: ../../include/mail_params.h
lmtp_connect.o: ../../include/mail_proto.h
lmtp_connect.o: ../../include/attr.h
diff --git a/postfix/src/lmtp/lmtp_connect.c b/postfix/src/lmtp/lmtp_connect.c
index 6479d634d..35afabbba 100644
--- a/postfix/src/lmtp/lmtp_connect.c
+++ b/postfix/src/lmtp/lmtp_connect.c
@@ -92,6 +92,7 @@
#include
#include
#include
+#include
/* Global library. */
@@ -298,35 +299,21 @@ static char *lmtp_parse_destination(const char *destination, char *def_service,
{
char *myname = "lmtp_parse_destination";
char *buf = mystrdup(destination);
- char *host = buf;
char *service;
struct servent *sp;
char *protocol = "tcp"; /* XXX configurable? */
unsigned port;
+ const char *err;
if (msg_verbose)
msg_info("%s: %s %s", myname, destination, def_service);
/*
- * Strip quoting. We're working with a copy of the destination argument
- * so the stripping can be destructive.
+ * Parse the host/port information. We're working with a copy of the
+ * destination argument so the parsing can be destructive.
*/
- if (*host == '[') {
- host++;
- host[strcspn(host, "]")] = 0;
- }
-
- /*
- * Separate host and service information, or use the default service
- * specified by the caller. XXX the ":" character is used in the IPV6
- * address notation, so using split_at_right() is not sufficient. We'd
- * have to count the number of ":" instances.
- */
- if ((service = split_at_right(host, ':')) == 0 || *service == 0)
- service = def_service;
- if (*service == 0)
- msg_fatal("%s: empty service name: %s", myname, destination);
- *hostp = host;
+ if ((err = host_port(buf, hostp, &service, def_service)) != 0)
+ msg_fatal("%s in LMTP server description: %s", err, destination);
/*
* Convert service to port number, network byte order. Since most folks
diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in
index fcf2e243b..c518690ac 100644
--- a/postfix/src/smtp/Makefile.in
+++ b/postfix/src/smtp/Makefile.in
@@ -136,6 +136,7 @@ smtp_connect.o: ../../include/inet_addr_list.h
smtp_connect.o: ../../include/iostuff.h
smtp_connect.o: ../../include/timed_connect.h
smtp_connect.o: ../../include/stringops.h
+smtp_connect.o: ../../include/host_port.h
smtp_connect.o: ../../include/mail_params.h
smtp_connect.o: ../../include/own_inet_addr.h
smtp_connect.o: ../../include/dns.h
diff --git a/postfix/src/smtp/smtp_connect.c b/postfix/src/smtp/smtp_connect.c
index 38d769a7b..b0d3681c5 100644
--- a/postfix/src/smtp/smtp_connect.c
+++ b/postfix/src/smtp/smtp_connect.c
@@ -111,6 +111,7 @@
#include
#include
#include
+#include
/* Global library. */
@@ -325,49 +326,21 @@ static char *smtp_parse_destination(char *destination, char *def_service,
char **hostp, unsigned *portp)
{
char *buf = mystrdup(destination);
- char *host = buf;
char *service;
struct servent *sp;
char *protocol = "tcp"; /* XXX configurable? */
unsigned port;
- char *cruft;
+ const char *err;
if (msg_verbose)
msg_info("smtp_parse_destination: %s %s", destination, def_service);
/*
- * Strip quoting. We're working with a copy of the destination argument
- * so the stripping can be destructive.
+ * Parse the host/port information. We're working with a copy of the
+ * destination argument so the parsing can be destructive.
*/
- if (*host == '[') {
- host++;
- cruft = split_at(host, ']');
- } else
- cruft = 0;
-
- /*
- * Separate host and service information, or use the default service
- * specified by the caller. XXX the ":" character is used in the IPV6
- * address notation, so we will have to deprecate the use of [host:port]
- * in favor of [host]:port.
- */
- if (cruft && *cruft) {
- if ((service = split_at_right(cruft, ':')) == 0)
- service = def_service;
- } else {
- if ((service = split_at_right(host, ':')) == 0)
- service = def_service;
-#if 0
- else if (cruft) {
- msg_warn("old-style address form: %s", destination);
- msg_warn("support for [host:port] forms will go away");
- msg_warn("specify [host]:port instead");
- }
-#endif
- }
- if (*service == 0)
- msg_fatal("empty service name: %s", destination);
- *hostp = host;
+ if ((err = host_port(buf, hostp, &service, def_service)) != 0)
+ msg_fatal("%s in SMTP server description: %s", err, destination);
/*
* Convert service to port number, network byte order.
diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in
index 44c895691..bce2c74e6 100644
--- a/postfix/src/util/Makefile.in
+++ b/postfix/src/util/Makefile.in
@@ -26,7 +26,7 @@ SRCS = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
unix_connect.c unix_listen.c unix_trigger.c unsafe.c username.c \
valid_hostname.c vbuf.c vbuf_print.c vstream.c vstream_popen.c \
vstring.c vstring_vstream.c watchdog.c writable.c write_buf.c \
- write_wait.c strcasecmp.c nvtable.c
+ write_wait.c strcasecmp.c nvtable.c host_port.c
OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
@@ -54,7 +54,7 @@ OBJS = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
unix_connect.o unix_listen.o unix_trigger.o unsafe.o username.o \
valid_hostname.o vbuf.o vbuf_print.o vstream.o vstream_popen.o \
vstring.o vstring_vstream.o watchdog.o writable.o write_buf.o \
- write_wait.o nvtable.o $(STRCASE)
+ write_wait.o nvtable.o $(STRCASE) host_port.o
HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
connect.h ctable.h dict.h dict_db.h dict_dbm.h dict_env.h \
dict_ht.h dict_ldap.h dict_mysql.h dict_ni.h dict_nis.h \
@@ -72,7 +72,7 @@ HDRS = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
split_at.h stat_as.h stringops.h sys_defs.h timed_connect.h \
timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \
vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \
- nvtable.h
+ nvtable.h host_port.h
TESTSRC = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
stream_test.c dup2_pass_on_exec.c
WARN = -W -Wformat -Wimplicit -Wmissing-prototypes \
@@ -90,7 +90,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
vstring vstring_vstream doze select_bug stream_test mac_expand \
watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
inet_addr_list attr_print64 attr_scan64 base64_code attr_print0 \
- attr_scan0
+ attr_scan0 host_port
LIB_DIR = ../../lib
INC_DIR = ../../include
@@ -319,6 +319,11 @@ attr_scan0: $(LIB)
$(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
mv junk $@.o
+host_port: $(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 \
@@ -332,7 +337,7 @@ stream_test: stream_test.c $(LIB)
tests: valid_hostname_test mac_expand_test dict_test unescape_test \
hex_quote_test ctable_test inet_addr_list_test base64_code_test \
- attr_scan64_test attr_scan0_test dict_pcre_test
+ attr_scan64_test attr_scan0_test dict_pcre_test host_port_test
valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
./valid_hostname valid_hostname.tmp
@@ -398,6 +403,11 @@ dict_regexp_test: dict_open dict_regexp.in dict_regexp.map dict_regexp.ref
diff dict_regexp.ref dict_regexp.tmp
rm -f dict_regexp.tmp
+host_port_test: host_port host_port.in host_port.ref
+ ./host_port host_port.tmp 2>&1
+ diff host_port.ref host_port.tmp
+ rm -f host_port.tmp
+
# do not edit below this line - it is generated by 'make depend'
alldig.o: alldig.c
alldig.o: sys_defs.h
@@ -745,6 +755,15 @@ hex_quote.o: msg.h
hex_quote.o: vstring.h
hex_quote.o: vbuf.h
hex_quote.o: hex_quote.h
+host_port.o: host_port.c
+host_port.o: sys_defs.h
+host_port.o: msg.h
+host_port.o: split_at.h
+host_port.o: stringops.h
+host_port.o: vstring.h
+host_port.o: vbuf.h
+host_port.o: valid_hostname.h
+host_port.o: host_port.h
htable.o: htable.c
htable.o: sys_defs.h
htable.o: mymalloc.h
diff --git a/postfix/src/util/host_port.c b/postfix/src/util/host_port.c
new file mode 100644
index 000000000..d682918ea
--- /dev/null
+++ b/postfix/src/util/host_port.c
@@ -0,0 +1,139 @@
+/*++
+/* NAME
+/* host_port 3
+/* SUMMARY
+/* split string into host and port, destroy string
+/* SYNOPSIS
+/* #include
+/*
+/* const char *host_port(string, host, port, def_service)
+/* char *string;
+/* char **host;
+/* char **port;
+/* char *def_service;
+/* DESCRIPTION
+/* host_port() splits a string into substrings with the host
+/* name or address, and the service name or port number.
+/* The input string is modified.
+/* DIAGNOSTICS
+/* The result is a null pointer in case of success.
+/* In case of problems the result is a string pointer with
+/* the problem type.
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include
+#include
+#include
+
+/* Utility library. */
+
+#include
+#include
+#include
+#include
+
+/* Global library. */
+
+#include
+
+/* host_port - parse string into host and port, destroy string */
+
+const char *host_port(char *buf, char **host, char **port,
+ char *def_service)
+{
+ char *cp = buf;
+
+ /*
+ * [host]:port, [host]:, [host].
+ */
+ if (*cp == '[') {
+ *host = ++cp;
+ if ((cp = split_at(cp, ']')) == 0)
+ return ("missing \"]\"");
+ if (*cp && *cp++ != ':')
+ return ("garbage after \"]\"");
+ if (*cp == 0)
+ *port = def_service;
+ else
+ *port = cp;
+
+ /*
+ * [host:port], [host:]. These conflict with IPV6 address literals.
+ */
+#if 1
+ if (strchr(*host, ':')) {
+ msg_warn("old-style address form: [%s]", *host);
+ msg_warn("support for [host:port] forms will go away");
+ msg_warn("specify [host]:port instead");
+ return (host_port(buf + 1, host, port, def_service));
+ }
+#endif
+ }
+
+ /*
+ * host:port, host:, host.
+ */
+ else {
+ *host = cp;
+ if ((cp = split_at_right(cp, ':')) == 0 || *cp == 0)
+ *port = def_service;
+ else
+ *port = cp;
+ }
+
+ /*
+ * Final sanity checks. We're still sloppy, allowing bare numerical
+ * network addresses instead of requiring proper [ipaddress] forms.
+ */
+ if (!valid_hostname(*host, DONT_GRIPE)
+ && !valid_hostaddr(*host, DONT_GRIPE))
+ return ("valid hostname or network address required");
+ if (ISDIGIT(**port) && !alldig(*port))
+ return ("garbage after numerical service");
+ return (0);
+}
+
+#ifdef TEST
+
+#include
+#include
+#include
+
+#define STR(x) vstring_str(x)
+
+int main(int unused_argc, char **unused_argv)
+{
+ VSTRING *in_buf = vstring_alloc(10);
+ VSTRING *parse_buf = vstring_alloc(10);
+ char *host;
+ char *port;
+ const char *err;
+
+ while (vstring_fgets_nonl(in_buf, VSTREAM_IN)) {
+ vstream_printf(">> %s\n", STR(in_buf));
+ vstream_fflush(VSTREAM_OUT);
+ vstring_strcpy(parse_buf, STR(in_buf));
+ if ((err = host_port(STR(parse_buf), &host, &port, "default-service")) != 0) {
+ msg_warn("%s in %s", err, STR(in_buf));
+ } else {
+ vstream_printf("host %s port %s\n", host, port);
+ vstream_fflush(VSTREAM_OUT);
+ }
+ }
+ vstring_free(in_buf);
+ vstring_free(parse_buf);
+ return (0);
+}
+
+#endif
diff --git a/postfix/src/util/host_port.h b/postfix/src/util/host_port.h
new file mode 100644
index 000000000..629943a9c
--- /dev/null
+++ b/postfix/src/util/host_port.h
@@ -0,0 +1,29 @@
+#ifndef _HOST_PORT_H_INCLUDED_
+#define _HOST_PORT_H_INCLUDED_
+
+/*++
+/* NAME
+/* host_port 3h
+/* SUMMARY
+/* split string into host and port, destroy string
+/* SYNOPSIS
+/* #include
+/* DESCRIPTION
+/* .nf
+
+ /* External interface. */
+
+extern const char *host_port(char *, char **, char **, char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/* The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/* Wietse Venema
+/* IBM T.J. Watson Research
+/* P.O. Box 704
+/* Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/util/host_port.in b/postfix/src/util/host_port.in
new file mode 100644
index 000000000..34c834383
--- /dev/null
+++ b/postfix/src/util/host_port.in
@@ -0,0 +1,12 @@
+hhh:ppp
+hhh:
+hhh
+[hhh]:ppp
+[hhh]:
+[hhh]
+[hhh:ppp]
+[hhh:]
+hhh:1pp
+[hh.]
+hh.
+999
diff --git a/postfix/src/util/host_port.ref b/postfix/src/util/host_port.ref
new file mode 100644
index 000000000..fbf672170
--- /dev/null
+++ b/postfix/src/util/host_port.ref
@@ -0,0 +1,30 @@
+>> hhh:ppp
+host hhh port ppp
+>> hhh:
+host hhh port default-service
+>> hhh
+host hhh port default-service
+>> [hhh]:ppp
+host hhh port ppp
+>> [hhh]:
+host hhh port default-service
+>> [hhh]
+host hhh port default-service
+>> [hhh:ppp]
+unknown: warning: old-style address form: [hhh:ppp]
+unknown: warning: support for [host:port] forms will go away
+unknown: warning: specify [host]:port instead
+host hhh port ppp
+>> [hhh:]
+unknown: warning: old-style address form: [hhh:]
+unknown: warning: support for [host:port] forms will go away
+unknown: warning: specify [host]:port instead
+host hhh port default-service
+>> hhh:1pp
+unknown: warning: garbage after numerical service in hhh:1pp
+>> [hh.]
+unknown: warning: valid hostname or network address required in [hh.]
+>> hh.
+unknown: warning: valid hostname or network address required in hh.
+>> 999
+host 999 port default-service