2
0
mirror of https://github.com/vdukhovni/postfix synced 2025-08-30 05:38:06 +00:00

postfix-1.1.12-20021217

This commit is contained in:
Wietse Venema 2002-12-17 00:00:00 -05:00 committed by Viktor Dukhovni
parent 489633d139
commit 9491ceed2a
40 changed files with 1402 additions and 619 deletions

View File

@ -7426,8 +7426,58 @@ Apologies for any names omitted.
File: trivial-rewrite/resolve.c. File: trivial-rewrite/resolve.c.
Performance: don't do UCE checks (which may result in 4xx Performance: don't do UCE checks (which may result in 4xx
SMTP reply codes) when we already know that the recipient SMTP reply codes, and thus, repeated delivery attempts)
is undeliverable. Files: smtpd/smtpd.c, smtpd/smtpd_check.c. when we already know that the recipient does not exist.
Files: smtpd/smtpd.c, smtpd/smtpd_check.c.
20021215
Cleanup: further simplification of transport map handling
after some really fine hair splitting with Victor Duchovni.
Files: trivial-rewrite/resolve.c, trivial-rewrite/transport.c.
20021216
Workaround: transform the address local-part into unquoted
form only when the address domain is local and the local-part
contains routing operators. Otherwise, we may damage the
address local-part by inserting space between non-operator
tokens. Some people use weird addresses and expect them to
be handled without damage. File: trivial-rewrite/resolve.c.
Robustness: scan the resolved recipient address for routing
operators in the address local-part, even when the local
MTA does not recognize ! and % as valid operators. File:
trivial-rewrite/resolve.c.
Cleanup: the address rewriting code no longer tries to
rewrite broken user@ or user@. address forms into even more
broken forms. bother. File: trivial-rewrite/rewrite.c.
Cleanup: the address resolver code now treates forms ending
in @ in a more rational manner (because the address rewriting
code no longer messes up by appending .my.domain).
Bugfix: a null address local-part before @domain now is
properly quoted just like the null address. File:
global/quote_82[12]_local.c.
20021217
Cleanup: more work on the trivial-rewrite address rewriting
and address resolving code. New regression tests for address
rewriting and resolving that make some assumptions about
main.cf settings. Files: global/Makefile.in (assumptions),
global/rewrite_clnt.in, global/rewrite_clnt.ref,
global/resolve_clnt.in, global/resolve_clnt.ref.
Safety: configurable SMTPD reject codes for recipients not
in {local,relay}_recipient,virtual_{alias,mailbox}}_maps,
aptly named unknown_mumble_reject_code. Postfix installs
with unknown_local_recipient_reject_code=450, unless the
site already ran Postfix with local_recipient_maps enabled.
Files: smtpd/smtpd.c, smtpd/smtpd_check.c, conf/post-install.
Open problems: Open problems:

View File

@ -122,7 +122,9 @@ mail_owner = postfix
# machine considers itself the final destination for. # machine considers itself the final destination for.
# #
# These domains are routed to the delivery agent specified with the # These domains are routed to the delivery agent specified with the
# local_transport parameter setting. # local_transport parameter setting. By default, that is the UNIX
# compatible delivery agent that lookups all recipients in /etc/passwd
# and /etc/aliases or their equivalent.
# #
# The default is $myhostname + localhost.$mydomain. On a mail domain # The default is $myhostname + localhost.$mydomain. On a mail domain
# gateway, you should also include $mydomain. # gateway, you should also include $mydomain.
@ -145,12 +147,14 @@ mail_owner = postfix
# a name matches a lookup key (the right-hand side is ignored). # a name matches a lookup key (the right-hand side is ignored).
# Continue long lines by starting the next line with whitespace. # Continue long lines by starting the next line with whitespace.
# #
# See also below, section "REJECTING MAIL FOR UNKNOWN LOCAL USERS".
#
#mydestination = $myhostname, localhost.$mydomain #mydestination = $myhostname, localhost.$mydomain
#mydestination = $myhostname, localhost.$mydomain $mydomain #mydestination = $myhostname, localhost.$mydomain $mydomain
#mydestination = $myhostname, localhost.$mydomain, $mydomain, #mydestination = $myhostname, localhost.$mydomain, $mydomain,
# mail.$mydomain, www.$mydomain, ftp.$mydomain # mail.$mydomain, www.$mydomain, ftp.$mydomain
# REJECTING UNKNOWN LOCAL USERS # REJECTING MAIL FOR UNKNOWN LOCAL USERS
# #
# The local_recipient_maps parameter specifies optional lookup tables # The local_recipient_maps parameter specifies optional lookup tables
# with all names or addresses of users that are local with respect # with all names or addresses of users that are local with respect
@ -159,6 +163,9 @@ mail_owner = postfix
# If this parameter is defined, then the SMTP server will reject # If this parameter is defined, then the SMTP server will reject
# mail for unknown local users. This parameter is defined by default. # mail for unknown local users. This parameter is defined by default.
# #
# To turn off local recipient checking in the SMTP server, specify
# local_recipient_maps = (i.e. empty).
#
# The default setting assumes that you use the default Postfix local # The default setting assumes that you use the default Postfix local
# delivery agent for local delivery. You need to update the # delivery agent for local delivery. You need to update the
# local_recipient_maps setting if: # local_recipient_maps setting if:
@ -175,11 +182,24 @@ mail_owner = postfix
# - You use the "luser_relay", "mailbox_transport", or "fallback_transport" # - You use the "luser_relay", "mailbox_transport", or "fallback_transport"
# feature of the Postfix local delivery agent (see sample-local.cf). # feature of the Postfix local delivery agent (see sample-local.cf).
# #
# Beware: if the Postfix SMTP server runs chrooted, you may have to # Beware: if the Postfix SMTP server runs chrooted, you probably have
# copy the passwd (not shadow) database into the jail. This is # to copy the passwd (not shadow) database into the jail, and perhaps
# system dependent. # other files. This is system dependent.
# #
local_recipient_maps = unix:passwd.byname $alias_maps #local_recipient_maps = unix:passwd.byname $alias_maps
#local_recipient_maps =
# The unknown_local_recipient_reject_code specifies the SMTP server
# response code when a recipient domain matches $mydestination or
# $inet_interfaces, while $local_recipient_maps is non-empty and the
# recipient address or address local-part is not found.
#
# The default setting is 550 (reject mail) but it is safer to start
# with 450 (try again later) until you are certain that your
# local_recipient_maps settings are OK.
#
#unknown_local_recipient_reject_code = 550
unknown_local_recipient_reject_code = 450
# TRUST AND RELAY CONTROL # TRUST AND RELAY CONTROL
@ -282,7 +302,7 @@ local_recipient_maps = unix:passwd.byname $alias_maps
# with all addresses in the domains that match $relay_domains. # with all addresses in the domains that match $relay_domains.
# #
# If this parameter is defined, then the SMTP server will reject # If this parameter is defined, then the SMTP server will reject
# mail for unknown relay users. # mail for unknown relay users. This feature is off by default.
# #
#relay_recipient_maps = hash:/etc/postfix/relay_recipients #relay_recipient_maps = hash:/etc/postfix/relay_recipients

View File

@ -498,7 +498,7 @@ EOF
} }
done done
# With 10000 active queue files, the active queue directory should # With 20000 active queue files, the active queue directory should
# be hashed, and so should the other directories, because they # be hashed, and so should the other directories, because they
# can contain even more mail. # can contain even more mail.
# #
@ -520,6 +520,21 @@ EOF
$POSTCONF -c $config_directory -e hash_queue_names="$found$missing" || $POSTCONF -c $config_directory -e hash_queue_names="$found$missing" ||
exit 1 exit 1
} }
# Turn on safety nets for new features that could bounce mail that
# would be accepted by a previous Postfix version.
unknown_local=unknown_local_recipient_reject_code
has_lrm=`$POSTCONF -n local_recipient_maps`
has_lrjc=`$POSTCONF -n $unknown_local`
if [ -z "$has_lrm" -a -z "$has_lrjc" ]
then
echo SAFETY: editing main.cf, setting $unknown_local=450.
echo See the RELEASE_NOTES and $config_directory/main.cf for details.
$POSTCONF -e "$unknown_local = 450" || exit 1
fi
} }
# A reminder if this is the first time Postfix is being installed. # A reminder if this is the first time Postfix is being installed.

View File

@ -200,7 +200,9 @@ max_use = 100
# machine considers itself the final destination for. # machine considers itself the final destination for.
# #
# These domains are routed to the delivery agent specified with the # These domains are routed to the delivery agent specified with the
# local_transport parameter setting. # local_transport parameter setting. By default, that is the UNIX
# compatible delivery agent that lookups all recipients in /etc/passwd
# and /etc/aliases or their equivalent.
# #
# The default is $myhostname + localhost.$mydomain. On a mail domain # The default is $myhostname + localhost.$mydomain. On a mail domain
# gateway, you should also include $mydomain. # gateway, you should also include $mydomain.
@ -223,6 +225,11 @@ max_use = 100
# a name matches a lookup key. Continue long lines by starting the # a name matches a lookup key. Continue long lines by starting the
# next line with whitespace. # next line with whitespace.
# #
# See sample-local.cf for a description of the local_recipient_maps
# and unknown_local_recipient_reject_code parameters. By default,
# the SMTP server rejects mail for recipients not listed with the
# local_recipient_maps parameter.
#
#mydestination = $myhostname, localhost.$mydomain $mydomain #mydestination = $myhostname, localhost.$mydomain $mydomain
#mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain #mydestination = $myhostname, localhost.$mydomain www.$mydomain, ftp.$mydomain
mydestination = $myhostname, localhost.$mydomain mydestination = $myhostname, localhost.$mydomain

View File

@ -434,6 +434,14 @@ allow_untrusted_routing = no
# #
relay_domains = $mydestination relay_domains = $mydestination
# The relay_recipient_maps parameter specifies optional lookup tables
# with all addresses in the domains that match $relay_domains.
#
# If this parameter is defined, then the SMTP server will reject
# mail to unknown relay users. This feature is off by default.
#
#relay_recipient_maps = hash:/etc/postfix/relay_recipients
# #
# RESPONSE CODES # RESPONSE CODES
# #

View File

@ -30,15 +30,15 @@
# Alternatively, the table can be provided as a regular- # Alternatively, the table can be provided as a regular-
# expression map where patterns are given as regular expres- # expression map where patterns are given as regular expres-
# sions. In that case, the lookups are done in a slightly # sions. In that case, the lookups are done in a slightly
# different way as described in the section titled "REGULAR # different way as described in section "REGULAR EXPRESSION
# EXPRESSION TABLES". # TABLES".
# #
# TABLE FORMAT # TABLE FORMAT
# The format of the transport table is as follows: # The format of the transport table is as follows:
# #
# pattern result # pattern result
# When pattern matches the domain, use the corre- # When pattern matches the recipient address or
# sponding result. # domain, use the corresponding result.
# #
# blank lines and comments # blank lines and comments
# Empty lines and whitespace-only lines are ignored, # Empty lines and whitespace-only lines are ignored,
@ -50,45 +50,17 @@
# line that starts with whitespace continues a logi- # line that starts with whitespace continues a logi-
# cal line. # cal line.
# #
# In an indexed file, a pattern of `*' matches everything. # The pattern specifies an email address, a domain name, or
# a domain name hierarchy, as described in section "TABLE
# LOOKUP".
# #
# The result is of the form transport:nexthop. The trans- # The result is of the form transport:nexthop. The trans-
# port field specifies a mail delivery transport such as # port field specifies a mail delivery transport such as
# smtp or local. The nexthop field specifies where and how # smtp or local. The nexthop field specifies where and how
# to deliver mail. A null transport or nexthop field means # to deliver mail. More details are given in section "RESULT
# "do not change": use the delivery transport and nexthop # FORMAT".
# information that would be used if no match were found.
# #
# TRANSPORT FIELD # TABLE LOOKUP
# The transport field specifies the name of a mail delivery
# transport (the first name of a mail delivery service entry
# in the Postfix master.cf file).
#
# When a null transport field is specified, Postfix uses one
# of the following transports:
#
# $local_transport
# The domain matches $mydestination or $inet_inter-
# faces.
#
# $virtual_transport
# The domain matches $virtual_mailbox_domains.
#
# $relay_transport
# The domain matches $relay_transport.
#
# $default_transport
# All other non-local, non-virtual destinations.
#
# NEXTHOP FIELD
# The interpretation of the nexthop field is transport
# dependent. In the case of SMTP, specify host:service for a
# non-default server port, and use [host] or [host]:port in
# order to disable MX (mail exchanger) DNS lookups. The []
# form can also be used with IP addresses instead of host-
# names.
#
# LOOKUP ORDER
# With lookups from indexed files such as DB or DBM, or from # With lookups from indexed files such as DB or DBM, or from
# networked tables such as NIS, LDAP or SQL, patterns are # networked tables such as NIS, LDAP or SQL, patterns are
# tried in the order as listed below: # tried in the order as listed below:
@ -113,96 +85,139 @@
# ting. Otherwise, a domain name matches itself and # ting. Otherwise, a domain name matches itself and
# its subdomains. # its subdomains.
# #
# NOTE # Note 1: the special pattern * represents any address (i.e.
# The special pattern <> represents the null address, and # it functions as the wild-card pattern).
# the special pattern * represents any address (i.e. it #
# functions as the wild-card pattern). # Note 2: the null recipient address is looked up as the
# local mailer-daemon address (mailer-daemon@fully-quali-
# fied-domain-name).
#
# RESULT FORMAT
# A null transport and null nexthop result means "do not
# change": use the delivery transport and nexthop informa-
# tion that would be used when the entire transport table
# did not exist.
#
# A non-null transport field with a null nexthop field
# resets the nexthop information to the recipient domain.
#
# A null transport field with non-null nexthop field does
# not modify the transport information.
#
# TRANSPORT FIELD
# The transport field specifies the name of a mail delivery
# transport (the first name of a mail delivery service entry
# in the Postfix master.cf file).
#
# When a null transport field is specified, Postfix uses one
# of the following transports:
#
# $local_transport
# The domain matches $mydestination or $inet_inter-
# faces.
#
# $virtual_transport
# The domain matches $virtual_mailbox_domains.
#
# $relay_transport
# The domain matches $relay_transport.
#
# $default_transport
# All other non-local, non-virtual destinations.
#
# NEXTHOP FIELD
# The interpretation of the nexthop field is transport
# dependent. In the case of SMTP, specify host:service for a
# non-default server port, and use [host] or [host]:port in
# order to disable MX (mail exchanger) DNS lookups. The []
# form can also be used with IP addresses instead of host-
# names.
# #
# EXAMPLES # EXAMPLES
# In order to deliver internal mail directly, while using a # In order to deliver internal mail directly, while using a
# mail relay for all other mail, specify a null entry for # mail relay for all other mail, specify a null entry for
# internal destinations (do not change the delivery trans- # internal destinations (do not change the delivery trans-
# port or the nexthop information) and specify a wildcard # port or the nexthop information) and specify a wildcard
# for all other destinations. Note that for this trick to # for all other destinations. Note that for this trick to
# work you should not specify a relayhost in the main.cf # work you should not specify a relayhost in the main.cf
# file. # file.
# #
# my.domain : # my.domain :
# .my.domain : # .my.domain :
# * smtp:outbound-relay.my.domain # * smtp:outbound-relay.my.domain
# #
# In order to send mail for foo.org and its subdomains via # In order to send mail for foo.org and its subdomains via
# the uucp transport to the UUCP host named foo: # the uucp transport to the UUCP host named foo:
# #
# foo.org uucp:foo # foo.org uucp:foo
# .foo.org uucp:foo # .foo.org uucp:foo
# #
# When no nexthop host name is specified, the destination # When no nexthop host name is specified, the destination
# domain name is used instead. For example, the following # domain name is used instead. For example, the following
# directs mail for user@foo.org via the slow transport to a # directs mail for user@foo.org via the slow transport to a
# mail exchanger for foo.org. The slow transport could be # mail exchanger for foo.org. The slow transport could be
# something that runs at most one delivery process at a # something that runs at most one delivery process at a
# time: # time:
# #
# foo.org slow: # foo.org slow:
# #
# When no transport is specified, Postfix uses the transport # When no transport is specified, Postfix uses the transport
# that matches the address domain class (see TRANSPORT FIELD # that matches the address domain class (see TRANSPORT FIELD
# discussion above). The following sends all mail for # discussion above). The following sends all mail for
# foo.org and its subdomains to host gateway.foo.org: # foo.org and its subdomains to host gateway.foo.org:
# #
# foo.org :[gateway.foo.org] # foo.org :[gateway.foo.org]
# .foo.org :[gateway.foo.org] # .foo.org :[gateway.foo.org]
# #
# In the above example, the [] are used to suppress MX # In the above example, the [] are used to suppress MX
# lookups. The result would likely point to your local # lookups. The result would likely point to your local
# machine. # machine.
# #
# In the case of delivery via SMTP, one may specify host- # In the case of delivery via SMTP, one may specify host-
# name:service instead of just a host: # name:service instead of just a host:
# #
# foo.org smtp:bar.org:2025 # foo.org smtp:bar.org:2025
# #
# This directs mail for user@foo.org to host bar.org port # This directs mail for user@foo.org to host bar.org port
# 2025. Instead of a numerical port a symbolic name may be # 2025. Instead of a numerical port a symbolic name may be
# used. Specify [] around the hostname in order to disable # used. Specify [] around the hostname in order to disable
# MX lookups. # MX lookups.
# #
# The error mailer can be used to bounce mail: # The error mailer can be used to bounce mail:
# #
# .foo.org error:mail for *.foo.org is not deliv- # .foo.org error:mail for *.foo.org is not deliv-
# erable # erable
# #
# This causes all mail for user@anything.foo.org to be # This causes all mail for user@anything.foo.org to be
# bounced. # bounced.
# #
# REGULAR EXPRESSION TABLES # 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 # 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). # 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 domain being looked up. Thus, some.domain.hier- # the entire domain being looked up. Thus, some.domain.hier-
# archy is not broken up into parent domains. # archy is not broken up into parent domains.
# #
# Patterns are applied in the order as specified in the # Patterns are applied in the order as specified in the
# table, until a pattern is found that matches the search # table, until a pattern is found that matches the search
# string. # string.
# #
# Results are the same as with indexed file lookups, with # Results are the same as with indexed file lookups, with
# the additional feature that parenthesized substrings from # the additional feature that parenthesized substrings from
# the pattern can be interpolated as $1, $2 and so on. # the pattern can be interpolated as $1, $2 and so on.
# #
# CONFIGURATION PARAMETERS # CONFIGURATION PARAMETERS
# The following main.cf parameters are especially relevant # The following main.cf parameters are especially relevant
# to this topic. See the Postfix main.cf file for syntax # to this topic. See the Postfix main.cf file for syntax
# details and for default values. Use the postfix reload # details and for default values. Use the postfix reload
# command after a configuration change. # command after a configuration change.
# #
# parent_domain_matches_subdomains # parent_domain_matches_subdomains
# List of Postfix features that use domain.tld pat- # List of Postfix features that use domain.tld pat-
# terns to match sub.domain.tld (as opposed to # terns to match sub.domain.tld (as opposed to
# requiring .domain.tld patterns). # requiring .domain.tld patterns).
# #
# transport_maps # transport_maps
@ -212,7 +227,7 @@
# #
# local_transport # local_transport
# The default mail delivery transport when the desti- # The default mail delivery transport when the desti-
# nation matches $mydestination or $inet_interfaces. # nation matches $mydestination or $inet_interfaces.
# #
# virtual_transport # virtual_transport
# The default mail delivery transport when the desti- # The default mail delivery transport when the desti-
@ -224,7 +239,7 @@
# #
# default_transport # default_transport
# The default mail delivery transport when the desti- # The default mail delivery transport when the desti-
# nation does not match a local, virtual or relay # nation does not match a local, virtual or relay
# destination. # destination.
# #
# mydestination # mydestination
@ -243,7 +258,7 @@
# regexp_table(5) format of POSIX regular expression tables # regexp_table(5) format of POSIX regular expression tables
# #
# LICENSE # LICENSE
# The Secure Mailer license must be distributed with this # The Secure Mailer license must be distributed with this
# software. # software.
# #
# AUTHOR(S) # AUTHOR(S)

View File

@ -145,18 +145,6 @@ SMTPD(8) SMTPD(8)
<b>hopcount</b><i>_</i><b>limit</b> <b>hopcount</b><i>_</i><b>limit</b>
Limit the number of <b>Received:</b> message headers. Limit the number of <b>Received:</b> message headers.
<b>local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b>
List of maps with user names that are local to
<b>$myorigin</b> or <b>$inet</b><i>_</i><b>interfaces</b>. If this parameter is
defined, then the SMTP server rejects mail for
unknown local users.
<b>relay</b><i>_</i><b>recipient</b><i>_</i><b>maps</b>
List of maps that define all the email addresses in
the domains that match <b>$relay</b><i>_</i><b>domains</b>. If this
parameter is defined, then the SMTP server rejects
mail for unknown relay recipients.
<b>notify</b><i>_</i><b>classes</b> <b>notify</b><i>_</i><b>classes</b>
List of error classes. Of special interest are: List of error classes. Of special interest are:
@ -195,9 +183,35 @@ SMTPD(8) SMTPD(8)
The characters that Postfix accepts as VERP delim- The characters that Postfix accepts as VERP delim-
iter characters. iter characters.
<b>Known</b> <b>versus</b> <b>unknown</b> <b>recipients</b>
<b>unknown</b><i>_</i><b>local</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
ent whose domain matches <b>$mydestination</b> or
<b>$inet</b><i>_</i><b>interfaces</b>, while <b>$local</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is
non-empty and does not list the recipient address
or address local-part.
<b>unknown</b><i>_</i><b>relay</b><i>_</i><b>recipient</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
ent whose domain matches <b>$relay</b><i>_</i><b>domains</b>, while
<b>$relay</b><i>_</i><b>recipient</b><i>_</i><b>maps</b> is non-empty and does not
list the recipient address.
<b>unknown</b><i>_</i><b>virtual</b><i>_</i><b>alias</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
ent whose domain matches <b>$virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b>,
while the recipient is not listed in <b>$vir-</b>
<b>tual</b><i>_</i><b>alias</b><i>_</i><b>maps</b>.
<b>unknown</b><i>_</i><b>virtual</b><i>_</i><b>mailbox</b><i>_</i><b>reject</b><i>_</i><b>code</b>
The response code when a client specifies a recipi-
ent whose domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>,
while the recipient is not listed in <b>$virtual</b><i>_</i><b>mail-</b>
<b>box</b><i>_</i><b>maps</b>.
<b>Resource</b> <b>controls</b> <b>Resource</b> <b>controls</b>
<b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b> <b>line</b><i>_</i><b>length</b><i>_</i><b>limit</b>
Limit the amount of memory in bytes used for the Limit the amount of memory in bytes used for the
handling of partial input lines. handling of partial input lines.
<b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b> <b>message</b><i>_</i><b>size</b><i>_</i><b>limit</b>
@ -205,8 +219,8 @@ SMTPD(8) SMTPD(8)
ing on-disk storage for envelope information. ing on-disk storage for envelope information.
<b>queue</b><i>_</i><b>minfree</b> <b>queue</b><i>_</i><b>minfree</b>
Minimal amount of free space in bytes in the queue Minimal amount of free space in bytes in the queue
file system for the SMTP server to accept any mail file system for the SMTP server to accept any mail
at all. at all.
<b>smtpd</b><i>_</i><b>history</b><i>_</i><b>flush</b><i>_</i><b>threshold</b> <b>smtpd</b><i>_</i><b>history</b><i>_</i><b>flush</b><i>_</i><b>threshold</b>
@ -221,23 +235,23 @@ SMTPD(8) SMTPD(8)
<b>smtpd</b><i>_</i><b>soft</b><i>_</i><b>error</b><i>_</i><b>limit</b> <b>smtpd</b><i>_</i><b>soft</b><i>_</i><b>error</b><i>_</i><b>limit</b>
When an SMTP client has made this number of errors, When an SMTP client has made this number of errors,
wait <i>error_count</i> seconds before responding to any wait <i>error_count</i> seconds before responding to any
client request. client request.
<b>smtpd</b><i>_</i><b>hard</b><i>_</i><b>error</b><i>_</i><b>limit</b> <b>smtpd</b><i>_</i><b>hard</b><i>_</i><b>error</b><i>_</i><b>limit</b>
Disconnect after a client has made this number of Disconnect after a client has made this number of
errors. errors.
<b>smtpd</b><i>_</i><b>junk</b><i>_</i><b>command</b><i>_</i><b>limit</b> <b>smtpd</b><i>_</i><b>junk</b><i>_</i><b>command</b><i>_</i><b>limit</b>
Limit the number of times a client can issue a junk Limit the number of times a client can issue a junk
command such as NOOP, VRFY, ETRN or RSET in one command such as NOOP, VRFY, ETRN or RSET in one
SMTP session before it is penalized with tarpit SMTP session before it is penalized with tarpit
delays. delays.
<b>UCE</b> <b>control</b> <b>restrictions</b> <b>UCE</b> <b>control</b> <b>restrictions</b>
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b> <b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b>
List of Postfix features that use <i>domain.tld</i> pat- List of Postfix features that use <i>domain.tld</i> pat-
terns to match <i>sub.domain.tld</i> (as opposed to terns to match <i>sub.domain.tld</i> (as opposed to
requiring <i>.domain.tld</i> patterns). requiring <i>.domain.tld</i> patterns).
<b>smtpd</b><i>_</i><b>client</b><i>_</i><b>restrictions</b> <b>smtpd</b><i>_</i><b>client</b><i>_</i><b>restrictions</b>
@ -245,19 +259,19 @@ SMTPD(8) SMTPD(8)
tem. tem.
<b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>required</b> <b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>required</b>
Require that clients introduce themselves at the Require that clients introduce themselves at the
beginning of an SMTP session. beginning of an SMTP session.
<b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>restrictions</b> <b>smtpd</b><i>_</i><b>helo</b><i>_</i><b>restrictions</b>
Restrict what client hostnames are allowed in <b>HELO</b> Restrict what client hostnames are allowed in <b>HELO</b>
and <b>EHLO</b> commands. and <b>EHLO</b> commands.
<b>smtpd</b><i>_</i><b>sender</b><i>_</i><b>restrictions</b> <b>smtpd</b><i>_</i><b>sender</b><i>_</i><b>restrictions</b>
Restrict what sender addresses are allowed in <b>MAIL</b> Restrict what sender addresses are allowed in <b>MAIL</b>
<b>FROM</b> commands. <b>FROM</b> commands.
<b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>restrictions</b> <b>smtpd</b><i>_</i><b>recipient</b><i>_</i><b>restrictions</b>
Restrict what recipient addresses are allowed in Restrict what recipient addresses are allowed in
<b>RCPT</b> <b>TO</b> commands. <b>RCPT</b> <b>TO</b> commands.
<b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b> <b>smtpd</b><i>_</i><b>etrn</b><i>_</i><b>restrictions</b>
@ -265,73 +279,73 @@ SMTPD(8) SMTPD(8)
mands, and what clients may issue <b>ETRN</b> commands. mands, and what clients may issue <b>ETRN</b> commands.
<b>smtpd</b><i>_</i><b>data</b><i>_</i><b>restrictions</b> <b>smtpd</b><i>_</i><b>data</b><i>_</i><b>restrictions</b>
Restrictions on the <b>DATA</b> command. Currently, the Restrictions on the <b>DATA</b> command. Currently, the
only restriction that makes sense here is only restriction that makes sense here is
<b>reject</b><i>_</i><b>unauth</b><i>_</i><b>pipelining</b>. <b>reject</b><i>_</i><b>unauth</b><i>_</i><b>pipelining</b>.
<b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b> <b>allow</b><i>_</i><b>untrusted</b><i>_</i><b>routing</b>
Allow untrusted clients to specify addresses with Allow untrusted clients to specify addresses with
sender-specified routing. Enabling this opens up sender-specified routing. Enabling this opens up
nasty relay loopholes involving trusted backup MX nasty relay loopholes involving trusted backup MX
hosts. hosts.
<b>smtpd</b><i>_</i><b>restriction</b><i>_</i><b>classes</b> <b>smtpd</b><i>_</i><b>restriction</b><i>_</i><b>classes</b>
Declares the name of zero or more parameters that Declares the name of zero or more parameters that
contain a list of UCE restrictions. The names of contain a list of UCE restrictions. The names of
these parameters can then be used instead of the these parameters can then be used instead of the
restriction lists that they represent. restriction lists that they represent.
<b>smtpd</b><i>_</i><b>null</b><i>_</i><b>access</b><i>_</i><b>lookup</b><i>_</i><b>key</b> <b>smtpd</b><i>_</i><b>null</b><i>_</i><b>access</b><i>_</i><b>lookup</b><i>_</i><b>key</b>
The lookup key to be used in SMTPD access tables The lookup key to be used in SMTPD access tables
instead of the null sender address. A null sender instead of the null sender address. A null sender
address cannot be looked up. address cannot be looked up.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> (deprecated) <b>maps</b><i>_</i><b>rbl</b><i>_</i><b>domains</b> (deprecated)
List of DNS domains that publish the addresses of List of DNS domains that publish the addresses of
blacklisted hosts. This is used with the deprecated blacklisted hosts. This is used with the deprecated
<b>reject</b><i>_</i><b>maps</b><i>_</i><b>rbl</b> restriction. <b>reject</b><i>_</i><b>maps</b><i>_</i><b>rbl</b> restriction.
<b>permit</b><i>_</i><b>mx</b><i>_</i><b>backup</b><i>_</i><b>networks</b> <b>permit</b><i>_</i><b>mx</b><i>_</i><b>backup</b><i>_</i><b>networks</b>
Only domains whose primary MX hosts match the Only domains whose primary MX hosts match the
listed networks are eligible for the <b>per-</b> listed networks are eligible for the <b>per-</b>
<b>mit</b><i>_</i><b>mx</b><i>_</i><b>backup</b> feature. <b>mit</b><i>_</i><b>mx</b><i>_</i><b>backup</b> feature.
<b>relay</b><i>_</i><b>domains</b> <b>relay</b><i>_</i><b>domains</b>
Restrict what domains this mail system will relay Restrict what domains this mail system will relay
mail to. The domains are routed to the delivery mail to. The domains are routed to the delivery
agent specified with the <b>relay</b><i>_</i><b>transport</b> setting. agent specified with the <b>relay</b><i>_</i><b>transport</b> setting.
<b>UCE</b> <b>control</b> <b>responses</b> <b>UCE</b> <b>control</b> <b>responses</b>
<b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>access</b><i>_</i><b>map</b><i>_</i><b>reject</b><i>_</i><b>code</b>
Response code when a client violates an access Response code when a client violates an access
database restriction. database restriction.
<b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b> <b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b>
Default template reply when a request is RBL black- Default template reply when a request is RBL black-
listed. This template is used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b> listed. This template is used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b>
and <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also: and <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
<b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>. <b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
<b>defer</b><i>_</i><b>code</b> <b>defer</b><i>_</i><b>code</b>
Response code when a client request is rejected by Response code when a client request is rejected by
the <b>defer</b> restriction. the <b>defer</b> restriction.
<b>invalid</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>invalid</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
Response code when a client violates the Response code when a client violates the
<b>reject</b><i>_</i><b>invalid</b><i>_</i><b>hostname</b> restriction. <b>reject</b><i>_</i><b>invalid</b><i>_</i><b>hostname</b> restriction.
<b>maps</b><i>_</i><b>rbl</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>maps</b><i>_</i><b>rbl</b><i>_</i><b>reject</b><i>_</i><b>code</b>
Response code when a request is RBL blacklisted. Response code when a request is RBL blacklisted.
<b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b> <b>rbl</b><i>_</i><b>reply</b><i>_</i><b>maps</b>
Table with template responses for RBL blacklisted Table with template responses for RBL blacklisted
requests, indexed by RBL domain name. These tem- requests, indexed by RBL domain name. These tem-
plates are used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b> and plates are used by the <b>reject</b><i>_</i><b>rbl</b><i>_</i><b>*</b> and
<b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also: <b>reject</b><i>_</i><b>rhsbl</b><i>_</i><b>*</b> restrictions. See also:
<b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>. <b>default</b><i>_</i><b>rbl</b><i>_</i><b>reply</b> and <b>smtpd</b><i>_</i><b>expansion</b><i>_</i><b>filter</b>.
<b>reject</b><i>_</i><b>code</b> <b>reject</b><i>_</i><b>code</b>
Response code when the client matches a <b>reject</b> Response code when the client matches a <b>reject</b>
restriction. restriction.
<b>relay</b><i>_</i><b>domains</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>relay</b><i>_</i><b>domains</b><i>_</i><b>reject</b><i>_</i><b>code</b>
@ -339,7 +353,7 @@ SMTPD(8) SMTPD(8)
mail relay policy. mail relay policy.
<b>unknown</b><i>_</i><b>address</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>unknown</b><i>_</i><b>address</b><i>_</i><b>reject</b><i>_</i><b>code</b>
Response code when a client violates the Response code when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>address</b> restriction. <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>address</b> restriction.
<b>unknown</b><i>_</i><b>client</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>unknown</b><i>_</i><b>client</b><i>_</i><b>reject</b><i>_</i><b>code</b>
@ -348,7 +362,7 @@ SMTPD(8) SMTPD(8)
tion. tion.
<b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b> <b>unknown</b><i>_</i><b>hostname</b><i>_</i><b>reject</b><i>_</i><b>code</b>
Response code when a client violates the Response code when a client violates the
<b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction. <b>reject</b><i>_</i><b>unknown</b><i>_</i><b>hostname</b> restriction.
<b>SEE</b> <b>ALSO</b> <b>SEE</b> <b>ALSO</b>
@ -358,7 +372,7 @@ SMTPD(8) SMTPD(8)
syslogd(8) system logging syslogd(8) system logging
<b>LICENSE</b> <b>LICENSE</b>
The Secure Mailer license must be distributed with this The Secure Mailer license must be distributed with this
software. software.
<b>AUTHOR(S)</b> <b>AUTHOR(S)</b>

View File

@ -31,15 +31,15 @@ TRANSPORT(5) TRANSPORT(5)
Alternatively, the table can be provided as a regular- Alternatively, the table can be provided as a regular-
expression map where patterns are given as regular expres- expression map where patterns are given as regular expres-
sions. In that case, the lookups are done in a slightly sions. In that case, the lookups are done in a slightly
different way as described in the section titled "REGULAR different way as described in section "REGULAR EXPRESSION
EXPRESSION TABLES". TABLES".
<b>TABLE</b> <b>FORMAT</b> <b>TABLE</b> <b>FORMAT</b>
The format of the transport table is as follows: The format of the transport table is as follows:
<i>pattern</i> <i>result</i> <i>pattern</i> <i>result</i>
When <i>pattern</i> matches the domain, use the corre- When <i>pattern</i> matches the recipient address or
sponding <i>result</i>. domain, use the corresponding <i>result</i>.
blank lines and comments blank lines and comments
Empty lines and whitespace-only lines are ignored, Empty lines and whitespace-only lines are ignored,
@ -51,45 +51,17 @@ TRANSPORT(5) TRANSPORT(5)
line that starts with whitespace continues a logi- line that starts with whitespace continues a logi-
cal line. cal line.
In an indexed file, a pattern of `<b>*</b>' matches everything. The <i>pattern</i> specifies an email address, a domain name, or
a domain name hierarchy, as described in section "TABLE
LOOKUP".
The <i>result</i> is of the form <i>transport</i><b>:</b><i>nexthop</i>. The <i>trans-</i> The <i>result</i> is of the form <i>transport</i><b>:</b><i>nexthop</i>. The <i>trans-</i>
<i>port</i> field specifies a mail delivery transport such as <i>port</i> field specifies a mail delivery transport such as
<b>smtp</b> or <b>local</b>. The <i>nexthop</i> field specifies where and how <b>smtp</b> or <b>local</b>. The <i>nexthop</i> field specifies where and how
to deliver mail. A null <i>transport</i> or <i>nexthop</i> field means to deliver mail. More details are given in section "RESULT
"do not change": use the delivery transport and nexthop FORMAT".
information that would be used if no match were found.
<b>TRANSPORT</b> <b>FIELD</b> <b>TABLE</b> <b>LOOKUP</b>
The transport field specifies the name of a mail delivery
transport (the first name of a mail delivery service entry
in the Postfix <b>master.cf</b> file).
When a null transport field is specified, Postfix uses one
of the following transports:
<b>$local</b><i>_</i><b>transport</b>
The domain matches <b>$mydestination</b> or <b>$inet</b><i>_</i><b>inter-</b>
<b>faces</b>.
<b>$virtual</b><i>_</i><b>transport</b>
The domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>.
<b>$relay</b><i>_</i><b>transport</b>
The domain matches <b>$relay</b><i>_</i><b>transport</b>.
<b>$default</b><i>_</i><b>transport</b>
All other non-local, non-virtual destinations.
<b>NEXTHOP</b> <b>FIELD</b>
The interpretation of the nexthop field is transport
dependent. In the case of SMTP, specify <i>host</i>:<i>service</i> for a
non-default server port, and use [<i>host</i>] or [<i>host</i>]:<i>port</i> in
order to disable MX (mail exchanger) DNS lookups. The []
form can also be used with IP addresses instead of host-
names.
<b>LOOKUP</b> <b>ORDER</b>
With lookups from indexed files such as DB or DBM, or from With lookups from indexed files such as DB or DBM, or from
networked tables such as NIS, LDAP or SQL, patterns are networked tables such as NIS, LDAP or SQL, patterns are
tried in the order as listed below: tried in the order as listed below:
@ -114,96 +86,139 @@ TRANSPORT(5) TRANSPORT(5)
ting. Otherwise, a domain name matches itself and ting. Otherwise, a domain name matches itself and
its subdomains. its subdomains.
<b>NOTE</b> Note 1: the special pattern <b>*</b> represents any address (i.e.
The special pattern &lt;&gt; represents the null address, and it functions as the wild-card pattern).
the special pattern <b>*</b> represents any address (i.e. it
functions as the wild-card pattern). Note 2: the null recipient address is looked up as the
local mailer-daemon address (mailer-daemon@fully-quali-
fied-domain-name).
<b>RESULT</b> <b>FORMAT</b>
A null <i>transport</i> and null <i>nexthop</i> result means "do not
change": use the delivery transport and nexthop informa-
tion that would be used when the entire transport table
did not exist.
A non-null <i>transport</i> field with a null <i>nexthop</i> field
resets the nexthop information to the recipient domain.
A null <i>transport</i> field with non-null <i>nexthop</i> field does
not modify the transport information.
<b>TRANSPORT</b> <b>FIELD</b>
The transport field specifies the name of a mail delivery
transport (the first name of a mail delivery service entry
in the Postfix <b>master.cf</b> file).
When a null transport field is specified, Postfix uses one
of the following transports:
<b>$local</b><i>_</i><b>transport</b>
The domain matches <b>$mydestination</b> or <b>$inet</b><i>_</i><b>inter-</b>
<b>faces</b>.
<b>$virtual</b><i>_</i><b>transport</b>
The domain matches <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>.
<b>$relay</b><i>_</i><b>transport</b>
The domain matches <b>$relay</b><i>_</i><b>transport</b>.
<b>$default</b><i>_</i><b>transport</b>
All other non-local, non-virtual destinations.
<b>NEXTHOP</b> <b>FIELD</b>
The interpretation of the nexthop field is transport
dependent. In the case of SMTP, specify <i>host</i>:<i>service</i> for a
non-default server port, and use [<i>host</i>] or [<i>host</i>]:<i>port</i> in
order to disable MX (mail exchanger) DNS lookups. The []
form can also be used with IP addresses instead of host-
names.
<b>EXAMPLES</b> <b>EXAMPLES</b>
In order to deliver internal mail directly, while using a In order to deliver internal mail directly, while using a
mail relay for all other mail, specify a null entry for mail relay for all other mail, specify a null entry for
internal destinations (do not change the delivery trans- internal destinations (do not change the delivery trans-
port or the nexthop information) and specify a wildcard port or the nexthop information) and specify a wildcard
for all other destinations. Note that for this trick to for all other destinations. Note that for this trick to
work you should not specify a <b>relayhost</b> in the <b>main.cf</b> work you should not specify a <b>relayhost</b> in the <b>main.cf</b>
file. file.
<b>my.domain</b> <b>:</b> <b>my.domain</b> <b>:</b>
<b>.my.domain</b> <b>:</b> <b>.my.domain</b> <b>:</b>
<b>*</b> <b>smtp:outbound-relay.my.domain</b> <b>*</b> <b>smtp:outbound-relay.my.domain</b>
In order to send mail for <b>foo.org</b> and its subdomains via In order to send mail for <b>foo.org</b> and its subdomains via
the <b>uucp</b> transport to the UUCP host named <b>foo</b>: the <b>uucp</b> transport to the UUCP host named <b>foo</b>:
<b>foo.org</b> <b>uucp:foo</b> <b>foo.org</b> <b>uucp:foo</b>
<b>.foo.org</b> <b>uucp:foo</b> <b>.foo.org</b> <b>uucp:foo</b>
When no nexthop host name is specified, the destination When no nexthop host name is specified, the destination
domain name is used instead. For example, the following domain name is used instead. For example, the following
directs mail for <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a directs mail for <i>user</i>@<b>foo.org</b> via the <b>slow</b> transport to a
mail exchanger for <b>foo.org</b>. The <b>slow</b> transport could be mail exchanger for <b>foo.org</b>. The <b>slow</b> transport could be
something that runs at most one delivery process at a something that runs at most one delivery process at a
time: time:
<b>foo.org</b> <b>slow:</b> <b>foo.org</b> <b>slow:</b>
When no transport is specified, Postfix uses the transport When no transport is specified, Postfix uses the transport
that matches the address domain class (see TRANSPORT FIELD that matches the address domain class (see TRANSPORT FIELD
discussion above). The following sends all mail for discussion above). The following sends all mail for
<b>foo.org</b> and its subdomains to host <b>gateway.foo.org</b>: <b>foo.org</b> and its subdomains to host <b>gateway.foo.org</b>:
<b>foo.org</b> <b>:[gateway.foo.org]</b> <b>foo.org</b> <b>:[gateway.foo.org]</b>
<b>.foo.org</b> <b>:[gateway.foo.org]</b> <b>.foo.org</b> <b>:[gateway.foo.org]</b>
In the above example, the [] are used to suppress MX In the above example, the [] are used to suppress MX
lookups. The result would likely point to your local lookups. The result would likely point to your local
machine. machine.
In the case of delivery via SMTP, one may specify <i>host-</i> In the case of delivery via SMTP, one may specify <i>host-</i>
<i>name</i>:<i>service</i> instead of just a host: <i>name</i>:<i>service</i> instead of just a host:
<b>foo.org</b> <b>smtp:bar.org:2025</b> <b>foo.org</b> <b>smtp:bar.org:2025</b>
This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b> port This directs mail for <i>user</i>@<b>foo.org</b> to host <b>bar.org</b> port
<b>2025</b>. Instead of a numerical port a symbolic name may be <b>2025</b>. Instead of a numerical port a symbolic name may be
used. Specify [] around the hostname in order to disable used. Specify [] around the hostname in order to disable
MX lookups. MX lookups.
The error mailer can be used to bounce mail: The error mailer can be used to bounce mail:
<b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliv-</b> <b>.foo.org</b> <b>error:mail</b> <b>for</b> <b>*.foo.org</b> <b>is</b> <b>not</b> <b>deliv-</b>
<b>erable</b> <b>erable</b>
This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b> to be This causes all mail for <i>user</i>@<i>anything</i><b>.foo.org</b> to be
bounced. bounced.
<b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b> <b>REGULAR</b> <b>EXPRESSION</b> <b>TABLES</b>
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 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 <a href="regexp_table.5.html"><b>regexp</b><i>_</i><b>table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>. see <a href="regexp_table.5.html"><b>regexp</b><i>_</i><b>table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre</b><i>_</i><b>table</b>(5)</a>.
Each pattern is a regular expression that is applied to Each pattern is a regular expression that is applied to
the entire domain being looked up. Thus, <i>some.domain.hier-</i> the entire domain being looked up. Thus, <i>some.domain.hier-</i>
<i>archy</i> is not broken up into parent domains. <i>archy</i> is not broken up into parent domains.
Patterns are applied in the order as specified in the Patterns are applied in the order as specified in the
table, until a pattern is found that matches the search table, until a pattern is found that matches the search
string. string.
Results are the same as with indexed file lookups, with Results are the same as with indexed file lookups, with
the additional feature that parenthesized substrings from the additional feature that parenthesized substrings from
the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on. the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
<b>CONFIGURATION</b> <b>PARAMETERS</b> <b>CONFIGURATION</b> <b>PARAMETERS</b>
The following <b>main.cf</b> parameters are especially relevant The following <b>main.cf</b> parameters are especially relevant
to this topic. See the Postfix <b>main.cf</b> file for syntax to this topic. See the Postfix <b>main.cf</b> file for syntax
details and for default values. Use the <b>postfix</b> <b>reload</b> details and for default values. Use the <b>postfix</b> <b>reload</b>
command after a configuration change. command after a configuration change.
<b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b> <b>parent</b><i>_</i><b>domain</b><i>_</i><b>matches</b><i>_</i><b>subdomains</b>
List of Postfix features that use <i>domain.tld</i> pat- List of Postfix features that use <i>domain.tld</i> pat-
terns to match <i>sub.domain.tld</i> (as opposed to terns to match <i>sub.domain.tld</i> (as opposed to
requiring <i>.domain.tld</i> patterns). requiring <i>.domain.tld</i> patterns).
<b>transport</b><i>_</i><b>maps</b> <b>transport</b><i>_</i><b>maps</b>
@ -213,7 +228,7 @@ TRANSPORT(5) TRANSPORT(5)
<b>local</b><i>_</i><b>transport</b> <b>local</b><i>_</i><b>transport</b>
The default mail delivery transport when the desti- The default mail delivery transport when the desti-
nation matches <b>$mydestination</b> or <b>$inet</b><i>_</i><b>interfaces</b>. nation matches <b>$mydestination</b> or <b>$inet</b><i>_</i><b>interfaces</b>.
<b>virtual</b><i>_</i><b>transport</b> <b>virtual</b><i>_</i><b>transport</b>
The default mail delivery transport when the desti- The default mail delivery transport when the desti-
@ -225,7 +240,7 @@ TRANSPORT(5) TRANSPORT(5)
<b>default</b><i>_</i><b>transport</b> <b>default</b><i>_</i><b>transport</b>
The default mail delivery transport when the desti- The default mail delivery transport when the desti-
nation does not match a local, virtual or relay nation does not match a local, virtual or relay
destination. destination.
<b>mydestination</b> <b>mydestination</b>
@ -244,7 +259,7 @@ TRANSPORT(5) TRANSPORT(5)
<a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables <a href="regexp_table.5.html">regexp_table(5)</a> format of POSIX regular expression tables
<b>LICENSE</b> <b>LICENSE</b>
The Secure Mailer license must be distributed with this The Secure Mailer license must be distributed with this
software. software.
<b>AUTHOR(S)</b> <b>AUTHOR(S)</b>

View File

@ -127,17 +127,6 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional. details. The :<i>nexthop</i> part is optional.
<b>error</b><i>_</i><b>transport</b>
Where to deliver mail for non-existent recipients
in domains that match <b>virtual</b><i>_</i><b>alias</b><i>_</i><b>domains</b> (all
recipients in simulated virtual domains must be
aliased to some other local or remote domain), or
for recipients that have moved. The default trans-
port is <b>error</b>.
Syntax is <i>transport</i>:<i>nexthop</i>; see <a href="transport.5.html"><b>transport</b>(5)</a> for
details. The :<i>nexthop</i> part is optional.
<b>virtual</b><i>_</i><b>transport</b> <b>virtual</b><i>_</i><b>transport</b>
Where to deliver mail for non-local domains that Where to deliver mail for non-local domains that
match <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>. The default trans- match <b>$virtual</b><i>_</i><b>mailbox</b><i>_</i><b>domains</b>. The default trans-
@ -178,9 +167,6 @@ TRIVIAL-REWRITE(8) TRIVIAL-REWRITE(8)
List of tables with <i>domain</i> to (<i>transport,</i> <i>nexthop</i>) List of tables with <i>domain</i> to (<i>transport,</i> <i>nexthop</i>)
mappings. mappings.
<b>transport</b><i>_</i><b>null</b><i>_</i><b>address</b><i>_</i><b>lookup</b><i>_</i><b>key</b>
Lookup key to be used for the null address.
<b>SEE</b> <b>ALSO</b> <b>SEE</b> <b>ALSO</b>
<a href="master.8.html">master(8)</a> process manager <a href="master.8.html">master(8)</a> process manager
syslogd(8) system logging syslogd(8) system logging

View File

@ -33,7 +33,7 @@ or SQL, the same lookups are done as for ordinary indexed files.
Alternatively, the table can be provided as a regular-expression Alternatively, the table can be provided as a regular-expression
map where patterns are given as regular expressions. In that case, map where patterns are given as regular expressions. In that case,
the lookups are done in a slightly different way as described the lookups are done in a slightly different way as described
in the section titled "REGULAR EXPRESSION TABLES". in section "REGULAR EXPRESSION TABLES".
.SH TABLE FORMAT .SH TABLE FORMAT
.na .na
.nf .nf
@ -41,8 +41,8 @@ in the section titled "REGULAR EXPRESSION TABLES".
.fi .fi
The format of the transport table is as follows: The format of the transport table is as follows:
.IP "\fIpattern result\fR" .IP "\fIpattern result\fR"
When \fIpattern\fR matches the domain, use the corresponding When \fIpattern\fR matches the recipient address or domain, use the
\fIresult\fR. corresponding \fIresult\fR.
.IP "blank lines and comments" .IP "blank lines and comments"
Empty lines and whitespace-only lines are ignored, as Empty lines and whitespace-only lines are ignored, as
are lines whose first non-whitespace character is a `#'. are lines whose first non-whitespace character is a `#'.
@ -50,15 +50,55 @@ are lines whose first non-whitespace character is a `#'.
A logical line starts with non-whitespace text. A line that A logical line starts with non-whitespace text. A line that
starts with whitespace continues a logical line. starts with whitespace continues a logical line.
.PP .PP
In an indexed file, a pattern of `\fB*\fR' matches everything. The \fIpattern\fR specifies an email address, a domain name, or
.PP a domain name hierarchy, as described in section "TABLE LOOKUP".
The \fIresult\fR is of the form \fItransport\fB:\fInexthop\fR. The \fIresult\fR is of the form \fItransport\fB:\fInexthop\fR.
The \fItransport\fR field specifies a mail delivery transport The \fItransport\fR field specifies a mail delivery transport
such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field
specifies where and how to deliver mail. A null \fItransport\fR specifies where and how to deliver mail. More details are given
or \fInexthop\fR field means "do not change": use the delivery in section "RESULT FORMAT".
transport and nexthop information that would be used if no .SH TABLE LOOKUP
match were found. .ad
.fi
With lookups from indexed files such as DB or DBM, or from networked
tables such as NIS, LDAP or SQL, patterns are tried in the order as
listed below:
.IP "\fIuser+extension@domain transport\fR:\fInexthop\fR"
Mail for \fIuser+extension@domain\fR is delivered through
\fItransport\fR to
\fInexthop\fR.
.IP "\fIuser@domain transport\fR:\fInexthop\fR"
Mail for \fIuser@domain\fR is delivered through \fItransport\fR to
\fInexthop\fR.
.IP "\fIdomain transport\fR:\fInexthop\fR"
Mail for \fIdomain\fR is delivered through \fItransport\fR to
\fInexthop\fR.
.IP "\fI.domain transport\fR:\fInexthop\fR"
Mail for any subdomain of \fIdomain\fR is delivered through
\fItransport\fR to \fInexthop\fR. This applies only when the
string \fBtransport_maps\fR is not listed in the
\fBparent_domain_matches_subdomains\fR configuration setting.
Otherwise, a domain name matches itself and its subdomains.
.PP
Note 1: the special pattern \fB*\fR represents any address (i.e. it
functions as the wild-card pattern).
Note 2: the null recipient address is looked up as the local
mailer-daemon address (mailer-daemon@fully-qualified-domain-name).
.SH RESULT FORMAT
.ad
.fi
A null \fItransport\fR and null \fInexthop\fR result means "do
not change": use the delivery transport and nexthop information
that would be used when the entire transport table did not exist.
A non-null \fItransport\fR field with a null \fInexthop\fR field
resets the nexthop information to the recipient domain.
A null \fItransport\fR field with non-null \fInexthop\fR field
does not modify the transport information.
.SH TRANSPORT FIELD .SH TRANSPORT FIELD
.ad .ad
.fi .fi
@ -84,37 +124,6 @@ dependent. In the case of SMTP, specify \fIhost\fR:\fIservice\fR for a
non-default server port, and use [\fIhost\fR] or [\fIhost\fR]:\fIport\fR non-default server port, and use [\fIhost\fR] or [\fIhost\fR]:\fIport\fR
in order to disable MX (mail exchanger) DNS lookups. The [] form in order to disable MX (mail exchanger) DNS lookups. The [] form
can also be used with IP addresses instead of hostnames. can also be used with IP addresses instead of hostnames.
.SH LOOKUP ORDER
.ad
.fi
With lookups from indexed files such as DB or DBM, or from networked
tables such as NIS, LDAP or SQL, patterns are tried in the order as
listed below:
.IP "\fIuser+extension@domain transport\fR:\fInexthop\fR"
Mail for \fIuser+extension@domain\fR is delivered through
\fItransport\fR to
\fInexthop\fR.
.IP "\fIuser@domain transport\fR:\fInexthop\fR"
Mail for \fIuser@domain\fR is delivered through \fItransport\fR to
\fInexthop\fR.
.IP "\fIdomain transport\fR:\fInexthop\fR"
Mail for \fIdomain\fR is delivered through \fItransport\fR to
\fInexthop\fR.
.IP "\fI.domain transport\fR:\fInexthop\fR"
Mail for any subdomain of \fIdomain\fR is delivered through
\fItransport\fR to \fInexthop\fR. This applies only when the
string \fBtransport_maps\fR is not listed in the
\fBparent_domain_matches_subdomains\fR configuration setting.
Otherwise, a domain name matches itself and its subdomains.
.PP
.SH NOTE
.na
.nf
.ad
.fi
The special pattern \fB<>\fR represents the null address, and the
special pattern \fB*\fR represents any address (i.e. it functions
as the wild-card pattern).
.SH EXAMPLES .SH EXAMPLES
.na .na
.nf .nf

View File

@ -132,14 +132,6 @@ XVERP command is specified without explicit delimiters.
Recipient of protocol/policy/resource/software error notices. Recipient of protocol/policy/resource/software error notices.
.IP \fBhopcount_limit\fR .IP \fBhopcount_limit\fR
Limit the number of \fBReceived:\fR message headers. Limit the number of \fBReceived:\fR message headers.
.IP \fBlocal_recipient_maps\fR
List of maps with user names that are local to \fB$myorigin\fR
or \fB$inet_interfaces\fR. If this parameter is defined,
then the SMTP server rejects mail for unknown local users.
.IP \fBrelay_recipient_maps\fR
List of maps that define all the email addresses in the domains
that match \fB$relay_domains\fR. If this parameter is defined,
then the SMTP server rejects mail for unknown relay recipients.
.IP \fBnotify_classes\fR .IP \fBnotify_classes\fR
List of error classes. Of special interest are: List of error classes. Of special interest are:
.RS .RS
@ -167,6 +159,26 @@ Change hard (5xx) reject responses into soft (4xx) reject responses.
This can be useful for testing purposes. This can be useful for testing purposes.
.IP \fBverp_delimiter_filter\fR .IP \fBverp_delimiter_filter\fR
The characters that Postfix accepts as VERP delimiter characters. The characters that Postfix accepts as VERP delimiter characters.
.SH "Known versus unknown recipients"
.ad
.fi
.IP \fBunknown_local_recipient_reject_code\fR
The response code when a client specifies a recipient whose domain
matches \fB$mydestination\fR or \fB$inet_interfaces\fR, while
\fB$local_recipient_maps\fR is non-empty and does not list
the recipient address or address local-part.
.IP \fBunknown_relay_recipient_reject_code\fR
The response code when a client specifies a recipient whose domain
matches \fB$relay_domains\fR, while \fB$relay_recipient_maps\fR
is non-empty and does not list the recipient address.
.IP \fBunknown_virtual_alias_reject_code\fR
The response code when a client specifies a recipient whose domain
matches \fB$virtual_alias_domains\fR, while the recipient is not
listed in \fB$virtual_alias_maps\fR.
.IP \fBunknown_virtual_mailbox_reject_code\fR
The response code when a client specifies a recipient whose domain
matches \fB$virtual_mailbox_domains\fR, while the recipient is not
listed in \fB$virtual_mailbox_maps\fR.
.SH "Resource controls" .SH "Resource controls"
.ad .ad
.fi .fi

View File

@ -117,15 +117,6 @@ The default transport is \fBlocal\fR.
.sp .sp
Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5) Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5)
for details. The :\fInexthop\fR part is optional. for details. The :\fInexthop\fR part is optional.
.IP \fBerror_transport\fR
Where to deliver mail for non-existent recipients in domains
that match \fBvirtual_alias_domains\fR (all recipients
in simulated virtual domains must be aliased to some other
local or remote domain), or for recipients that have moved.
The default transport is \fBerror\fR.
.sp
Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5)
for details. The :\fInexthop\fR part is optional.
.IP \fBvirtual_transport\fR .IP \fBvirtual_transport\fR
Where to deliver mail for non-local domains that match Where to deliver mail for non-local domains that match
\fB$virtual_mailbox_domains\fR. \fB$virtual_mailbox_domains\fR.
@ -160,8 +151,6 @@ to the destination's mail exchanger.
.IP \fBtransport_maps\fR .IP \fBtransport_maps\fR
List of tables with \fIdomain\fR to (\fItransport, nexthop\fR) List of tables with \fIdomain\fR to (\fItransport, nexthop\fR)
mappings. mappings.
.IP \fBtransport_null_address_lookup_key\fR
Lookup key to be used for the null address.
.SH SEE ALSO .SH SEE ALSO
.na .na
.nf .nf

View File

@ -27,14 +27,14 @@
# Alternatively, the table can be provided as a regular-expression # Alternatively, the table can be provided as a regular-expression
# map where patterns are given as regular expressions. In that case, # map where patterns are given as regular expressions. In that case,
# the lookups are done in a slightly different way as described # the lookups are done in a slightly different way as described
# in the section titled "REGULAR EXPRESSION TABLES". # in section "REGULAR EXPRESSION TABLES".
# TABLE FORMAT # TABLE FORMAT
# .ad # .ad
# .fi # .fi
# The format of the transport table is as follows: # The format of the transport table is as follows:
# .IP "\fIpattern result\fR" # .IP "\fIpattern result\fR"
# When \fIpattern\fR matches the domain, use the corresponding # When \fIpattern\fR matches the recipient address or domain, use the
# \fIresult\fR. # corresponding \fIresult\fR.
# .IP "blank lines and comments" # .IP "blank lines and comments"
# Empty lines and whitespace-only lines are ignored, as # Empty lines and whitespace-only lines are ignored, as
# are lines whose first non-whitespace character is a `#'. # are lines whose first non-whitespace character is a `#'.
@ -42,15 +42,55 @@
# A logical line starts with non-whitespace text. A line that # A logical line starts with non-whitespace text. A line that
# starts with whitespace continues a logical line. # starts with whitespace continues a logical line.
# .PP # .PP
# In an indexed file, a pattern of `\fB*\fR' matches everything. # The \fIpattern\fR specifies an email address, a domain name, or
# .PP # a domain name hierarchy, as described in section "TABLE LOOKUP".
#
# The \fIresult\fR is of the form \fItransport\fB:\fInexthop\fR. # The \fIresult\fR is of the form \fItransport\fB:\fInexthop\fR.
# The \fItransport\fR field specifies a mail delivery transport # The \fItransport\fR field specifies a mail delivery transport
# such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field # such as \fBsmtp\fR or \fBlocal\fR. The \fInexthop\fR field
# specifies where and how to deliver mail. A null \fItransport\fR # specifies where and how to deliver mail. More details are given
# or \fInexthop\fR field means "do not change": use the delivery # in section "RESULT FORMAT".
# transport and nexthop information that would be used if no # .SH TABLE LOOKUP
# match were found. # .ad
# .fi
# With lookups from indexed files such as DB or DBM, or from networked
# tables such as NIS, LDAP or SQL, patterns are tried in the order as
# listed below:
# .IP "\fIuser+extension@domain transport\fR:\fInexthop\fR"
# Mail for \fIuser+extension@domain\fR is delivered through
# \fItransport\fR to
# \fInexthop\fR.
# .IP "\fIuser@domain transport\fR:\fInexthop\fR"
# Mail for \fIuser@domain\fR is delivered through \fItransport\fR to
# \fInexthop\fR.
# .IP "\fIdomain transport\fR:\fInexthop\fR"
# Mail for \fIdomain\fR is delivered through \fItransport\fR to
# \fInexthop\fR.
# .IP "\fI.domain transport\fR:\fInexthop\fR"
# Mail for any subdomain of \fIdomain\fR is delivered through
# \fItransport\fR to \fInexthop\fR. This applies only when the
# string \fBtransport_maps\fR is not listed in the
# \fBparent_domain_matches_subdomains\fR configuration setting.
# Otherwise, a domain name matches itself and its subdomains.
# .PP
# Note 1: the special pattern \fB*\fR represents any address (i.e. it
# functions as the wild-card pattern).
#
# Note 2: the null recipient address is looked up as the local
# mailer-daemon address (mailer-daemon@fully-qualified-domain-name).
# .SH RESULT FORMAT
# .ad
# .fi
#
# A null \fItransport\fR and null \fInexthop\fR result means "do
# not change": use the delivery transport and nexthop information
# that would be used when the entire transport table did not exist.
#
# A non-null \fItransport\fR field with a null \fInexthop\fR field
# resets the nexthop information to the recipient domain.
#
# A null \fItransport\fR field with non-null \fInexthop\fR field
# does not modify the transport information.
# .SH TRANSPORT FIELD # .SH TRANSPORT FIELD
# .ad # .ad
# .fi # .fi
@ -76,35 +116,6 @@
# non-default server port, and use [\fIhost\fR] or [\fIhost\fR]:\fIport\fR # non-default server port, and use [\fIhost\fR] or [\fIhost\fR]:\fIport\fR
# in order to disable MX (mail exchanger) DNS lookups. The [] form # in order to disable MX (mail exchanger) DNS lookups. The [] form
# can also be used with IP addresses instead of hostnames. # can also be used with IP addresses instead of hostnames.
# .SH LOOKUP ORDER
# .ad
# .fi
# With lookups from indexed files such as DB or DBM, or from networked
# tables such as NIS, LDAP or SQL, patterns are tried in the order as
# listed below:
# .IP "\fIuser+extension@domain transport\fR:\fInexthop\fR"
# Mail for \fIuser+extension@domain\fR is delivered through
# \fItransport\fR to
# \fInexthop\fR.
# .IP "\fIuser@domain transport\fR:\fInexthop\fR"
# Mail for \fIuser@domain\fR is delivered through \fItransport\fR to
# \fInexthop\fR.
# .IP "\fIdomain transport\fR:\fInexthop\fR"
# Mail for \fIdomain\fR is delivered through \fItransport\fR to
# \fInexthop\fR.
# .IP "\fI.domain transport\fR:\fInexthop\fR"
# Mail for any subdomain of \fIdomain\fR is delivered through
# \fItransport\fR to \fInexthop\fR. This applies only when the
# string \fBtransport_maps\fR is not listed in the
# \fBparent_domain_matches_subdomains\fR configuration setting.
# Otherwise, a domain name matches itself and its subdomains.
# .PP
# NOTE
# .ad
# .fi
# The special pattern \fB<>\fR represents the null address, and the
# special pattern \fB*\fR represents any address (i.e. it functions
# as the wild-card pattern).
# EXAMPLES # EXAMPLES
# .ad # .ad
# .fi # .fi

View File

@ -298,6 +298,27 @@ virtual8_test: virtual8_maps virtual8_map virtual8.in virtual8.ref \
diff virtual8.ref virtual8.tmp diff virtual8.ref virtual8.tmp
rm -f virtual8.tmp virtual8_map.db rm -f virtual8.tmp virtual8_map.db
# Requires: Postfix running, root privileges
rewrite_clnt_test: rewrite_clnt rewrite_clnt.in rewrite_clnt.ref
./rewrite_clnt <rewrite_clnt.in >rewrite_clnt.tmp
sed "s/MYDOMAIN/`postconf -h mydomain`/" rewrite_clnt.ref | \
diff - rewrite_clnt.tmp
rm -f rewrite_clnt.tmp
# Requires: Postfix, root, myorigin=$myhostname, relayhost=$mydomain,
# no transport map
resolve_clnt_test: resolve_clnt resolve_clnt.in resolve_clnt.ref
sed -e "s/MYDOMAIN/`postconf -h mydomain`/g" \
-e "s/MYHOSTNAME/`postconf -h myhostname`/g" \
resolve_clnt.in | ./resolve_clnt >resolve_clnt.tmp
sed -e "s/MYDOMAIN/`postconf -h mydomain`/g" \
-e "s/MYHOSTNAME/`postconf -h myhostname`/g" \
-e "s/RELAYHOST/`postconf -h mydomain`/g" \
resolve_clnt.ref | diff - resolve_clnt.tmp
rm -f resolve_clnt.tmp
printfck: $(OBJS) $(PROG) printfck: $(OBJS) $(PROG)
rm -rf printfck rm -rf printfck
mkdir printfck mkdir printfck

View File

@ -96,7 +96,7 @@ extern char *var_mydomain;
* The default local delivery transport. * The default local delivery transport.
*/ */
#define VAR_LOCAL_TRANSPORT "local_transport" #define VAR_LOCAL_TRANSPORT "local_transport"
#define DEF_LOCAL_TRANSPORT "local" #define DEF_LOCAL_TRANSPORT MAIL_SERVICE_LOCAL ":$myhostname"
extern char *var_local_transport; extern char *var_local_transport;
/* /*
@ -293,10 +293,6 @@ extern bool var_disable_vrfy_cmd;
/* /*
* trivial rewrite/resolve service: mapping tables. * trivial rewrite/resolve service: mapping tables.
*/ */
#define VAR_ERROR_TRANSPORT "error_transport"
#define DEF_ERROR_TRANSPORT MAIL_SERVICE_ERROR
extern char *var_error_transport;
#define VAR_VIRT_ALIAS_MAPS "virtual_alias_maps" #define VAR_VIRT_ALIAS_MAPS "virtual_alias_maps"
#define DEF_VIRT_ALIAS_MAPS "$virtual_maps" /* Compatibility! */ #define DEF_VIRT_ALIAS_MAPS "$virtual_maps" /* Compatibility! */
extern char *var_virt_alias_maps; extern char *var_virt_alias_maps;
@ -305,6 +301,10 @@ extern char *var_virt_alias_maps;
#define DEF_VIRT_ALIAS_DOMS "$virtual_alias_maps" #define DEF_VIRT_ALIAS_DOMS "$virtual_alias_maps"
extern char *var_virt_alias_doms; extern char *var_virt_alias_doms;
#define VAR_VIRT_ALIAS_CODE "unknown_virtual_alias_reject_code"
#define DEF_VIRT_ALIAS_CODE 550
extern int var_virt_alias_code;
#define VAR_CANONICAL_MAPS "canonical_maps" #define VAR_CANONICAL_MAPS "canonical_maps"
#define DEF_CANONICAL_MAPS "" #define DEF_CANONICAL_MAPS ""
extern char *var_canonical_maps; extern char *var_canonical_maps;
@ -1126,6 +1126,10 @@ extern char *var_relay_transport;
#define DEF_RELAY_RCPT_MAPS "" #define DEF_RELAY_RCPT_MAPS ""
extern char *var_relay_rcpt_maps; extern char *var_relay_rcpt_maps;
#define VAR_RELAY_RCPT_CODE "unknown_relay_recipient_reject_code"
#define DEF_RELAY_RCPT_CODE 550
extern int var_relay_rcpt_code;
#define VAR_CLIENT_CHECKS "smtpd_client_restrictions" #define VAR_CLIENT_CHECKS "smtpd_client_restrictions"
#define DEF_CLIENT_CHECKS "" #define DEF_CLIENT_CHECKS ""
extern char *var_client_checks; extern char *var_client_checks;
@ -1279,12 +1283,16 @@ abcdefghijklmnopqrstuvwxyz{|}~"
extern char *var_smtpd_exp_filter; extern char *var_smtpd_exp_filter;
/* /*
* Heuristic to reject most unknown recipients at the SMTP port. * Heuristic to reject unknown local recipients at the SMTP port.
*/ */
#define VAR_LOCAL_RCPT_MAPS "local_recipient_maps" #define VAR_LOCAL_RCPT_MAPS "local_recipient_maps"
#define DEF_LOCAL_RCPT_MAPS "unix:passwd.byname $alias_maps" #define DEF_LOCAL_RCPT_MAPS "unix:passwd.byname $alias_maps"
extern char *var_local_rcpt_maps; extern char *var_local_rcpt_maps;
#define VAR_LOCAL_RCPT_CODE "unknown_local_recipient_reject_code"
#define DEF_LOCAL_RCPT_CODE 550
extern int var_local_rcpt_code;
/* /*
* Other. * Other.
*/ */
@ -1375,6 +1383,10 @@ extern char *var_virt_mailbox_maps;
#define DEF_VIRT_MAILBOX_DOMS "$virtual_mailbox_maps" #define DEF_VIRT_MAILBOX_DOMS "$virtual_mailbox_maps"
extern char *var_virt_mailbox_doms; extern char *var_virt_mailbox_doms;
#define VAR_VIRT_MAILBOX_CODE "unknown_virtual_mailbox_reject_code"
#define DEF_VIRT_MAILBOX_CODE 550
extern int var_virt_mailbox_code;
#define VAR_VIRT_UID_MAPS "virtual_uid_maps" #define VAR_VIRT_UID_MAPS "virtual_uid_maps"
#define DEF_VIRT_UID_MAPS "" #define DEF_VIRT_UID_MAPS ""
extern char *var_virt_uid_maps; extern char *var_virt_uid_maps;

View File

@ -20,7 +20,7 @@
* Patches change the patchlevel and the release date. Snapshots change the * Patches change the patchlevel and the release date. Snapshots change the
* release date only, unless they include the same bugfix as a patch release. * release date only, unless they include the same bugfix as a patch release.
*/ */
#define MAIL_RELEASE_DATE "20021214" #define MAIL_RELEASE_DATE "20021217"
#define VAR_MAIL_VERSION "mail_version" #define VAR_MAIL_VERSION "mail_version"
#define DEF_MAIL_VERSION "1.1.12-" MAIL_RELEASE_DATE #define DEF_MAIL_VERSION "1.1.12-" MAIL_RELEASE_DATE

View File

@ -82,7 +82,7 @@ static int is_821_dot_string(char *local_part, char *end, int flags)
* lookup tables to speed up some of the work, but hey, how large can a * lookup tables to speed up some of the work, but hey, how large can a
* local-part be anyway? * local-part be anyway?
*/ */
if (local_part[0] == 0 || local_part[0] == '.') if (local_part == end || local_part[0] == 0 || local_part[0] == '.')
return (NO); return (NO);
for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
if (ch == '.' && cp[1] == '.') if (ch == '.' && cp[1] == '.')

View File

@ -95,7 +95,7 @@ static int is_822_dot_string(const char *local_part, const char *end, int flags)
* RFC 822 expects 7-bit data. Rather than quoting every 8-bit character * RFC 822 expects 7-bit data. Rather than quoting every 8-bit character
* (and still passing it on as 8-bit data) we leave 8-bit data alone. * (and still passing it on as 8-bit data) we leave 8-bit data alone.
*/ */
if (local_part[0] == 0 || local_part[0] == '.') if (local_part == end || local_part[0] == 0 || local_part[0] == '.')
return (NO); return (NO);
for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) { for (cp = local_part; cp < end && (ch = *(unsigned char *) cp) != 0; cp++) {
if (ch == '.' && (cp + 1) < end && cp[1] == '.') if (ch == '.' && (cp + 1) < end && cp[1] == '.')

View File

@ -70,7 +70,7 @@
/* authorized mail relay destination. /* authorized mail relay destination.
/* .IP RESOLVE_CLASS_DEFAULT /* .IP RESOLVE_CLASS_DEFAULT
/* The address matches none of the above. Access to this domain /* The address matches none of the above. Access to this domain
/* should be limited to authorized senders only. /* should be limited to authorized senders only.
/* .PP /* .PP
/* For convenience, the constant RESOLVE_CLASS_FINAL includes all /* For convenience, the constant RESOLVE_CLASS_FINAL includes all
/* cases where the local machine is the final destination. /* cases where the local machine is the final destination.
@ -178,7 +178,7 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
*/ */
if (rewrite_clnt_stream == 0) if (rewrite_clnt_stream == 0)
rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE, rewrite_clnt_stream = clnt_stream_create(MAIL_CLASS_PRIVATE,
var_rewrite_service, var_ipc_idle_limit); var_rewrite_service, var_ipc_idle_limit);
for (;;) { for (;;) {
stream = clnt_stream_access(rewrite_clnt_stream); stream = clnt_stream_access(rewrite_clnt_stream);
@ -247,6 +247,24 @@ static NORETURN usage(char *myname)
static void resolve(char *addr, RESOLVE_REPLY *reply) static void resolve(char *addr, RESOLVE_REPLY *reply)
{ {
struct RESOLVE_FLAG_TABLE {
int flag;
const char *name;
};
struct RESOLVE_FLAG_TABLE resolve_flag_table[] = {
RESOLVE_FLAG_FINAL, "FLAG_FINAL",
RESOLVE_FLAG_ROUTED, "FLAG_ROUTED",
RESOLVE_FLAG_ERROR, "FLAG_ERROR",
RESOLVE_FLAG_FAIL, "FLAG_FAIL",
RESOLVE_CLASS_LOCAL, "CLASS_LOCAL",
RESOLVE_CLASS_ALIAS, "CLASS_ALIAS",
RESOLVE_CLASS_VIRTUAL, "CLASS_VIRTUAL",
RESOLVE_CLASS_RELAY, "CLASS_RELAY",
RESOLVE_CLASS_DEFAULT, "CLASS_DEFAULT",
0,
};
struct RESOLVE_FLAG_TABLE *fp;
resolve_clnt_query(addr, reply); resolve_clnt_query(addr, reply);
if (reply->flags & RESOLVE_FLAG_FAIL) { if (reply->flags & RESOLVE_FLAG_FAIL) {
vstream_printf("request failed\n"); vstream_printf("request failed\n");
@ -256,6 +274,16 @@ static void resolve(char *addr, RESOLVE_REPLY *reply)
vstream_printf("%-10s %s\n", "nexthop", *STR(reply->nexthop) ? vstream_printf("%-10s %s\n", "nexthop", *STR(reply->nexthop) ?
STR(reply->nexthop) : "[none]"); STR(reply->nexthop) : "[none]");
vstream_printf("%-10s %s\n", "recipient", STR(reply->recipient)); vstream_printf("%-10s %s\n", "recipient", STR(reply->recipient));
vstream_printf("%-10s ", "flags");
for (fp = resolve_flag_table; fp->name; fp++) {
if (reply->flags & fp->flag) {
vstream_printf("%s ", fp->name);
reply->flags &= ~fp->flag;
}
}
if (reply->flags != 0)
vstream_printf("Unknown flag 0x%x", reply->flags);
vstream_printf("\n");
vstream_fflush(VSTREAM_OUT); vstream_fflush(VSTREAM_OUT);
} }
} }
@ -297,6 +325,7 @@ int main(int argc, char **argv)
vstring_free(buffer); vstring_free(buffer);
} }
resolve_clnt_free(&reply); resolve_clnt_free(&reply);
exit(0);
} }
#endif #endif

View File

@ -0,0 +1,45 @@
@
@@
@a.
@..
@.@.
!
a!
!b
a!b
!@
a!@
!b@
a!b@
%
a%
%b
a%b
%@
a%@
%b@
@@
a@@
@b@
a@b@
a%b@
a%b@MYHOSTNAME
a!b@MYHOSTNAME
a@b@MYHOSTNAME
a[b]@MYHOSTNAME@MYHOSTNAME
a[b]%MYHOSTNAME@MYHOSTNAME
a[b]%MYHOSTNAME%MYHOSTNAME
MYHOSTNAME!a[b]@MYHOSTNAME
MYHOSTNAME!a[b]%MYHOSTNAME
MYHOSTNAME!MYHOSTNAME!a[b]
user@dom.ain1@dom.ain2
user%dom.ain1@dom.ain2
dom.ain1!user@dom.ain2
user@[1.2.3.4]@dom.ain2
user%[1.2.3.4]@dom.ain2
[1.2.3.4]!user@dom.ain2
user@localhost.MYDOMAIN
user@[321.1.2.3]
user@1.2.3
user@host:port

View File

@ -0,0 +1,225 @@
address
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address @
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address @@
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address @a.
transport smtp
nexthop RELAYHOST
recipient @a
flags CLASS_DEFAULT
address @..
transport smtp
nexthop RELAYHOST
recipient @..
flags FLAG_ERROR CLASS_DEFAULT
address @.@.
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address !
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address a!
transport smtp
nexthop RELAYHOST
recipient @a.MYDOMAIN
flags CLASS_DEFAULT
address !b
transport local
nexthop MYHOSTNAME
recipient b@MYHOSTNAME
flags CLASS_LOCAL
address a!b
transport smtp
nexthop RELAYHOST
recipient b@a.MYDOMAIN
flags CLASS_DEFAULT
address !@
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address a!@
transport smtp
nexthop RELAYHOST
recipient @a.MYDOMAIN
flags CLASS_DEFAULT
address !b@
transport local
nexthop MYHOSTNAME
recipient b@MYHOSTNAME
flags CLASS_LOCAL
address a!b@
transport smtp
nexthop RELAYHOST
recipient b@a.MYDOMAIN
flags CLASS_DEFAULT
address %
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address a%
transport local
nexthop MYHOSTNAME
recipient a@MYHOSTNAME
flags CLASS_LOCAL
address %b
transport smtp
nexthop RELAYHOST
recipient @b.MYDOMAIN
flags CLASS_DEFAULT
address a%b
transport smtp
nexthop RELAYHOST
recipient a@b.MYDOMAIN
flags CLASS_DEFAULT
address %@
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address a%@
transport local
nexthop MYHOSTNAME
recipient a@MYHOSTNAME
flags CLASS_LOCAL
address %b@
transport smtp
nexthop RELAYHOST
recipient @b.MYDOMAIN
flags CLASS_DEFAULT
address @@
transport local
nexthop MYHOSTNAME
recipient MAILER-DAEMON@MYHOSTNAME
flags CLASS_LOCAL
address a@@
transport local
nexthop MYHOSTNAME
recipient a@MYHOSTNAME
flags CLASS_LOCAL
address @b@
transport smtp
nexthop RELAYHOST
recipient @b.MYDOMAIN
flags CLASS_DEFAULT
address a@b@
transport smtp
nexthop RELAYHOST
recipient a@b.MYDOMAIN
flags CLASS_DEFAULT
address a%b@
transport smtp
nexthop RELAYHOST
recipient a@b.MYDOMAIN
flags CLASS_DEFAULT
address a%b@MYHOSTNAME
transport smtp
nexthop RELAYHOST
recipient a@b.MYDOMAIN
flags CLASS_DEFAULT
address a!b@MYHOSTNAME
transport smtp
nexthop RELAYHOST
recipient b@a.MYDOMAIN
flags CLASS_DEFAULT
address a@b@MYHOSTNAME
transport smtp
nexthop RELAYHOST
recipient a@b.MYDOMAIN
flags CLASS_DEFAULT
address a[b]@MYHOSTNAME@MYHOSTNAME
transport local
nexthop MYHOSTNAME
recipient a[b]@MYHOSTNAME
flags CLASS_LOCAL
address a[b]%MYHOSTNAME@MYHOSTNAME
transport local
nexthop MYHOSTNAME
recipient a[b]@MYHOSTNAME
flags CLASS_LOCAL
address a[b]%MYHOSTNAME%MYHOSTNAME
transport local
nexthop MYHOSTNAME
recipient a[b]@MYHOSTNAME
flags CLASS_LOCAL
address MYHOSTNAME!a[b]@MYHOSTNAME
transport local
nexthop MYHOSTNAME
recipient a [b]@MYHOSTNAME
flags CLASS_LOCAL
address MYHOSTNAME!a[b]%MYHOSTNAME
transport local
nexthop MYHOSTNAME
recipient a [b]@MYHOSTNAME
flags CLASS_LOCAL
address MYHOSTNAME!MYHOSTNAME!a[b]
transport local
nexthop MYHOSTNAME
recipient a [b]@MYHOSTNAME
flags CLASS_LOCAL
address user@dom.ain1@dom.ain2
transport smtp
nexthop RELAYHOST
recipient user@dom.ain1@dom.ain2
flags FLAG_ROUTED CLASS_DEFAULT
address user%dom.ain1@dom.ain2
transport smtp
nexthop RELAYHOST
recipient user%dom.ain1@dom.ain2
flags FLAG_ROUTED CLASS_DEFAULT
address dom.ain1!user@dom.ain2
transport smtp
nexthop RELAYHOST
recipient dom.ain1!user@dom.ain2
flags FLAG_ROUTED CLASS_DEFAULT
address user@[1.2.3.4]@dom.ain2
transport smtp
nexthop RELAYHOST
recipient user@[1.2.3.4]@dom.ain2
flags FLAG_ROUTED CLASS_DEFAULT
address user%[1.2.3.4]@dom.ain2
transport smtp
nexthop RELAYHOST
recipient user%[1.2.3.4]@dom.ain2
flags FLAG_ROUTED CLASS_DEFAULT
address [1.2.3.4]!user@dom.ain2
transport smtp
nexthop RELAYHOST
recipient [1.2.3.4]!user@dom.ain2
flags FLAG_ROUTED CLASS_DEFAULT
address user@localhost.MYDOMAIN
transport local
nexthop MYHOSTNAME
recipient user@localhost.MYDOMAIN
flags CLASS_LOCAL
address user@[321.1.2.3]
transport smtp
nexthop RELAYHOST
recipient user@[321.1.2.3]
flags FLAG_ERROR CLASS_DEFAULT
address user@1.2.3
transport smtp
nexthop RELAYHOST
recipient user@1.2.3
flags CLASS_DEFAULT
address user@host:port
transport smtp
nexthop RELAYHOST
recipient user@host:port
flags FLAG_ERROR CLASS_DEFAULT

View File

@ -242,6 +242,7 @@ int main(int argc, char **argv)
vstring_free(buffer); vstring_free(buffer);
} }
vstring_free(reply); vstring_free(reply);
exit(0);
} }
#endif #endif

View File

@ -0,0 +1,13 @@
x !
x a!
x !b
x a!b
x %
x a%
x %b
x a%b
x @
x a@
x a@.
x a@b
x a@b.

View File

@ -0,0 +1,39 @@
rule x
address !
result ""@
rule x
address a!
result ""@a.MYDOMAIN
rule x
address !b
result b@
rule x
address a!b
result b@a.MYDOMAIN
rule x
address %
result ""@
rule x
address a%
result a@
rule x
address %b
result ""@b.MYDOMAIN
rule x
address a%b
result a@b.MYDOMAIN
rule x
address @
result ""
rule x
address a@
result a@
rule x
address a@.
result a@.
rule x
address a@b
result a@b.MYDOMAIN
rule x
address a@b.
result a@b.

View File

@ -185,7 +185,6 @@ qmgr_message.o: ../../include/rec_type.h
qmgr_message.o: ../../include/sent.h qmgr_message.o: ../../include/sent.h
qmgr_message.o: ../../include/deliver_completed.h qmgr_message.o: ../../include/deliver_completed.h
qmgr_message.o: ../../include/opened.h qmgr_message.o: ../../include/opened.h
qmgr_message.o: ../../include/resolve_local.h
qmgr_message.o: ../../include/verp_sender.h qmgr_message.o: ../../include/verp_sender.h
qmgr_message.o: ../../include/mail_proto.h qmgr_message.o: ../../include/mail_proto.h
qmgr_message.o: ../../include/iostuff.h qmgr_message.o: ../../include/iostuff.h

View File

@ -119,7 +119,6 @@
#include <sent.h> #include <sent.h>
#include <deliver_completed.h> #include <deliver_completed.h>
#include <opened.h> #include <opened.h>
#include <resolve_local.h>
#include <verp_sender.h> #include <verp_sender.h>
#include <mail_proto.h> #include <mail_proto.h>
@ -768,8 +767,11 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
* system can run without a local delivery agent. They'd still have * system can run without a local delivery agent. They'd still have
* to configure something for mail directed to the local postmaster, * to configure something for mail directed to the local postmaster,
* though, but that is an RFC requirement anyway. * though, but that is an RFC requirement anyway.
*
* XXX This lookup should be done in the resolver, and the mail should
* be directed to a general-purpose null delivery agent.
*/ */
if (at == 0 || resolve_local(at + 1)) { if (reply.flags & RESOLVE_CLASS_LOCAL) {
if (strncasecmp(STR(reply.recipient), var_double_bounce_sender, if (strncasecmp(STR(reply.recipient), var_double_bounce_sender,
len) == 0 len) == 0
&& !var_double_bounce_sender[len]) { && !var_double_bounce_sender[len]) {

View File

@ -172,7 +172,6 @@ qmgr_message.o: ../../include/rec_type.h
qmgr_message.o: ../../include/sent.h qmgr_message.o: ../../include/sent.h
qmgr_message.o: ../../include/deliver_completed.h qmgr_message.o: ../../include/deliver_completed.h
qmgr_message.o: ../../include/opened.h qmgr_message.o: ../../include/opened.h
qmgr_message.o: ../../include/resolve_local.h
qmgr_message.o: ../../include/verp_sender.h qmgr_message.o: ../../include/verp_sender.h
qmgr_message.o: ../../include/mail_proto.h qmgr_message.o: ../../include/mail_proto.h
qmgr_message.o: ../../include/iostuff.h qmgr_message.o: ../../include/iostuff.h

View File

@ -110,7 +110,6 @@
#include <sent.h> #include <sent.h>
#include <deliver_completed.h> #include <deliver_completed.h>
#include <opened.h> #include <opened.h>
#include <resolve_local.h>
#include <verp_sender.h> #include <verp_sender.h>
#include <mail_proto.h> #include <mail_proto.h>
@ -648,8 +647,11 @@ static void qmgr_message_resolve(QMGR_MESSAGE *message)
* system can run without a local delivery agent. They'd still have * system can run without a local delivery agent. They'd still have
* to configure something for mail directed to the local postmaster, * to configure something for mail directed to the local postmaster,
* though, but that is an RFC requirement anyway. * though, but that is an RFC requirement anyway.
*
* XXX This lookup should be done in the resolver, and the mail should
* be directed to a general-purpose null delivery agent.
*/ */
if (at == 0 || resolve_local(at + 1)) { if (reply.flags & RESOLVE_CLASS_LOCAL) {
if (strncasecmp(STR(reply.recipient), var_double_bounce_sender, if (strncasecmp(STR(reply.recipient), var_double_bounce_sender,
len) == 0 len) == 0
&& !var_double_bounce_sender[len]) { && !var_double_bounce_sender[len]) {

View File

@ -118,14 +118,6 @@
/* Recipient of protocol/policy/resource/software error notices. /* Recipient of protocol/policy/resource/software error notices.
/* .IP \fBhopcount_limit\fR /* .IP \fBhopcount_limit\fR
/* Limit the number of \fBReceived:\fR message headers. /* Limit the number of \fBReceived:\fR message headers.
/* .IP \fBlocal_recipient_maps\fR
/* List of maps with user names that are local to \fB$myorigin\fR
/* or \fB$inet_interfaces\fR. If this parameter is defined,
/* then the SMTP server rejects mail for unknown local users.
/* .IP \fBrelay_recipient_maps\fR
/* List of maps that define all the email addresses in the domains
/* that match \fB$relay_domains\fR. If this parameter is defined,
/* then the SMTP server rejects mail for unknown relay recipients.
/* .IP \fBnotify_classes\fR /* .IP \fBnotify_classes\fR
/* List of error classes. Of special interest are: /* List of error classes. Of special interest are:
/* .RS /* .RS
@ -153,6 +145,26 @@
/* This can be useful for testing purposes. /* This can be useful for testing purposes.
/* .IP \fBverp_delimiter_filter\fR /* .IP \fBverp_delimiter_filter\fR
/* The characters that Postfix accepts as VERP delimiter characters. /* The characters that Postfix accepts as VERP delimiter characters.
/* .SH "Known versus unknown recipients"
/* .ad
/* .fi
/* .IP \fBunknown_local_recipient_reject_code\fR
/* The response code when a client specifies a recipient whose domain
/* matches \fB$mydestination\fR or \fB$inet_interfaces\fR, while
/* \fB$local_recipient_maps\fR is non-empty and does not list
/* the recipient address or address local-part.
/* .IP \fBunknown_relay_recipient_reject_code\fR
/* The response code when a client specifies a recipient whose domain
/* matches \fB$relay_domains\fR, while \fB$relay_recipient_maps\fR
/* is non-empty and does not list the recipient address.
/* .IP \fBunknown_virtual_alias_reject_code\fR
/* The response code when a client specifies a recipient whose domain
/* matches \fB$virtual_alias_domains\fR, while the recipient is not
/* listed in \fB$virtual_alias_maps\fR.
/* .IP \fBunknown_virtual_mailbox_reject_code\fR
/* The response code when a client specifies a recipient whose domain
/* matches \fB$virtual_mailbox_domains\fR, while the recipient is not
/* listed in \fB$virtual_mailbox_maps\fR.
/* .SH "Resource controls" /* .SH "Resource controls"
/* .ad /* .ad
/* .fi /* .fi
@ -413,12 +425,11 @@ char *var_smtpd_null_key;
int var_smtpd_hist_thrsh; int var_smtpd_hist_thrsh;
char *var_smtpd_exp_filter; char *var_smtpd_exp_filter;
char *var_def_rbl_reply; char *var_def_rbl_reply;
char *var_def_transport;
char *var_error_transport;
char *var_local_transport;
char *var_relay_transport;
char *var_virt_transport;
char *var_relay_rcpt_maps; char *var_relay_rcpt_maps;
int var_local_rcpt_code;
int var_virt_alias_code;
int var_virt_mailbox_code;
int var_relay_rcpt_code;
/* /*
* Silly little macros. * Silly little macros.
@ -1619,6 +1630,10 @@ int main(int argc, char **argv)
VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 0, 0, VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, 0, 0,
VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0, VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit, 1, 0,
VAR_SMTPD_HIST_THRSH, DEF_SMTPD_HIST_THRSH, &var_smtpd_hist_thrsh, 1, 0, VAR_SMTPD_HIST_THRSH, DEF_SMTPD_HIST_THRSH, &var_smtpd_hist_thrsh, 1, 0,
VAR_LOCAL_RCPT_CODE, DEF_LOCAL_RCPT_CODE, &var_local_rcpt_code, 0, 0,
VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code, 0, 0,
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code, 0, 0,
VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code, 0, 0,
0, 0,
}; };
static CONFIG_TIME_TABLE time_table[] = { static CONFIG_TIME_TABLE time_table[] = {
@ -1663,11 +1678,6 @@ int main(int argc, char **argv)
VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0, VAR_SMTPD_SND_AUTH_MAPS, DEF_SMTPD_SND_AUTH_MAPS, &var_smtpd_snd_auth_maps, 0, 0,
VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0, VAR_SMTPD_NOOP_CMDS, DEF_SMTPD_NOOP_CMDS, &var_smtpd_noop_cmds, 0, 0,
VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0, VAR_SMTPD_NULL_KEY, DEF_SMTPD_NULL_KEY, &var_smtpd_null_key, 0, 0,
VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport, 1, 0,
VAR_ERROR_TRANSPORT, DEF_ERROR_TRANSPORT, &var_error_transport, 1, 0,
VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport, 1, 0,
VAR_RELAY_TRANSPORT, DEF_RELAY_TRANSPORT, &var_relay_transport, 1, 0,
VAR_VIRT_TRANSPORT, DEF_VIRT_TRANSPORT, &var_virt_transport, 1, 0,
VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 0, 0, VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, 0, 0,
0, 0,
}; };

View File

@ -3149,9 +3149,11 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
* unknown recipients in simulated virtual domains will both resolve to * unknown recipients in simulated virtual domains will both resolve to
* "error:user unknown". * "error:user unknown".
*/ */
if (strcmp(STR(reply->transport), var_error_transport) == 0) { if (strcmp(STR(reply->transport), MAIL_SERVICE_ERROR) == 0) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: %s", 550, "%d <%s>: %s",
(reply->flags & RESOLVE_CLASS_ALIAS) ?
var_virt_alias_code : 550,
recipient, STR(reply->nexthop)); recipient, STR(reply->nexthop));
SMTPD_CHECK_RCPT_RETURN(STR(error_text)); SMTPD_CHECK_RCPT_RETURN(STR(error_text));
} }
@ -3170,13 +3172,10 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
*/ */
if ((reply->flags & RESOLVE_CLASS_LOCAL) if ((reply->flags & RESOLVE_CLASS_LOCAL)
&& *var_local_rcpt_maps && *var_local_rcpt_maps
#if 0
&& strcmp(STR(reply->transport), var_local_transport) == 0
#endif
&& NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) { && NOMATCH(local_rcpt_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown in local recipient table", "%d <%s>: User unknown in local recipient table",
550, recipient); var_local_rcpt_code, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text)); SMTPD_CHECK_RCPT_RETURN(STR(error_text));
} }
@ -3184,13 +3183,10 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
* Reject mail to unknown addresses in virtual mailbox domains. * Reject mail to unknown addresses in virtual mailbox domains.
*/ */
if ((reply->flags & RESOLVE_CLASS_VIRTUAL) if ((reply->flags & RESOLVE_CLASS_VIRTUAL)
#if 0
&& strcmp(STR(reply->transport), var_virt_transport) == 0
#endif
&& NOMATCHV8(virt_mailbox_maps, CONST_STR(reply->recipient))) { && NOMATCHV8(virt_mailbox_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown in virtual mailbox table", "%d <%s>: User unknown in virtual mailbox table",
550, recipient); var_virt_mailbox_code, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text)); SMTPD_CHECK_RCPT_RETURN(STR(error_text));
} }
@ -3199,13 +3195,10 @@ char *smtpd_check_rcptmap(SMTPD_STATE *state, char *recipient)
*/ */
if ((reply->flags & RESOLVE_CLASS_RELAY) if ((reply->flags & RESOLVE_CLASS_RELAY)
&& *var_relay_rcpt_maps && *var_relay_rcpt_maps
#if 0
&& strcmp(STR(reply->transport), var_relay_transport) == 0
#endif
&& NOMATCH(relay_rcpt_maps, CONST_STR(reply->recipient))) { && NOMATCH(relay_rcpt_maps, CONST_STR(reply->recipient))) {
(void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE, (void) smtpd_check_reject(state, MAIL_ERROR_BOUNCE,
"%d <%s>: User unknown in relay recipient table", "%d <%s>: User unknown in relay recipient table",
550, recipient); var_relay_rcpt_code, recipient);
SMTPD_CHECK_RCPT_RETURN(STR(error_text)); SMTPD_CHECK_RCPT_RETURN(STR(error_text));
} }
@ -3365,11 +3358,6 @@ char *var_double_bounce_sender;
char *var_rbl_reply_maps; char *var_rbl_reply_maps;
char *var_smtpd_exp_filter; char *var_smtpd_exp_filter;
char *var_def_rbl_reply; char *var_def_rbl_reply;
char *var_local_transport;
char *var_error_transport;
char *var_virt_transport;
char *var_relay_transport;
char *var_def_transport;
char *var_relay_rcpt_maps; char *var_relay_rcpt_maps;
typedef struct { typedef struct {
@ -3408,11 +3396,6 @@ static STRING_TABLE string_table[] = {
VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps, VAR_RBL_REPLY_MAPS, DEF_RBL_REPLY_MAPS, &var_rbl_reply_maps,
VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter, VAR_SMTPD_EXP_FILTER, DEF_SMTPD_EXP_FILTER, &var_smtpd_exp_filter,
VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply, VAR_DEF_RBL_REPLY, DEF_DEF_RBL_REPLY, &var_def_rbl_reply,
VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport,
VAR_ERROR_TRANSPORT, DEF_ERROR_TRANSPORT, &var_error_transport,
VAR_VIRT_TRANSPORT, DEF_VIRT_TRANSPORT, &var_virt_transport,
VAR_RELAY_TRANSPORT, DEF_RELAY_TRANSPORT, &var_relay_transport,
VAR_DEF_TRANSPORT, DEF_DEF_TRANSPORT, &var_def_transport,
VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps, VAR_RELAY_RCPT_MAPS, DEF_RELAY_RCPT_MAPS, &var_relay_rcpt_maps,
0, 0,
}; };
@ -3465,6 +3448,10 @@ int var_defer_code;
int var_non_fqdn_code; int var_non_fqdn_code;
int var_smtpd_delay_reject; int var_smtpd_delay_reject;
int var_allow_untrust_route; int var_allow_untrust_route;
int var_local_rcpt_code;
int var_relay_rcpt_code;
int var_virt_mailbox_code;
int var_virt_alias_code;
static INT_TABLE int_table[] = { static INT_TABLE int_table[] = {
"msg_verbose", 0, &msg_verbose, "msg_verbose", 0, &msg_verbose,
@ -3480,6 +3467,10 @@ static INT_TABLE int_table[] = {
VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code, VAR_NON_FQDN_CODE, DEF_NON_FQDN_CODE, &var_non_fqdn_code,
VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject, VAR_SMTPD_DELAY_REJECT, DEF_SMTPD_DELAY_REJECT, &var_smtpd_delay_reject,
VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route, VAR_ALLOW_UNTRUST_ROUTE, DEF_ALLOW_UNTRUST_ROUTE, &var_allow_untrust_route,
VAR_LOCAL_RCPT_CODE, DEF_LOCAL_RCPT_CODE, &var_local_rcpt_code,
VAR_RELAY_RCPT_CODE, DEF_RELAY_RCPT_CODE, &var_relay_rcpt_code,
VAR_VIRT_ALIAS_CODE, DEF_VIRT_ALIAS_CODE, &var_virt_alias_code,
VAR_VIRT_MAILBOX_CODE, DEF_VIRT_MAILBOX_CODE, &var_virt_mailbox_code,
0, 0,
}; };
@ -3633,23 +3624,23 @@ void resolve_clnt_query(const char *addr, RESOLVE_REPLY *reply)
domain += 1; domain += 1;
if (resolve_local(domain)) { if (resolve_local(domain)) {
reply->flags = RESOLVE_CLASS_LOCAL; reply->flags = RESOLVE_CLASS_LOCAL;
vstring_strcpy(reply->transport, var_local_transport); vstring_strcpy(reply->transport, MAIL_SERVICE_LOCAL);
vstring_strcpy(reply->nexthop, domain); vstring_strcpy(reply->nexthop, domain);
} else if (string_list_match(virt_alias_doms, domain)) { } else if (string_list_match(virt_alias_doms, domain)) {
reply->flags = RESOLVE_CLASS_ALIAS; reply->flags = RESOLVE_CLASS_ALIAS;
vstring_strcpy(reply->transport, var_error_transport); vstring_strcpy(reply->transport, MAIL_SERVICE_ERROR);
vstring_strcpy(reply->nexthop, "user unknown"); vstring_strcpy(reply->nexthop, "user unknown");
} else if (string_list_match(virt_mailbox_doms, domain)) { } else if (string_list_match(virt_mailbox_doms, domain)) {
reply->flags = RESOLVE_CLASS_VIRTUAL; reply->flags = RESOLVE_CLASS_VIRTUAL;
vstring_strcpy(reply->transport, var_virt_transport); vstring_strcpy(reply->transport, MAIL_SERVICE_VIRTUAL);
vstring_strcpy(reply->nexthop, domain); vstring_strcpy(reply->nexthop, domain);
} else if (domain_list_match(relay_domains, domain)) { } else if (domain_list_match(relay_domains, domain)) {
reply->flags = RESOLVE_CLASS_RELAY; reply->flags = RESOLVE_CLASS_RELAY;
vstring_strcpy(reply->transport, var_relay_transport); vstring_strcpy(reply->transport, MAIL_SERVICE_RELAY);
vstring_strcpy(reply->nexthop, domain); vstring_strcpy(reply->nexthop, domain);
} else { } else {
reply->flags = RESOLVE_CLASS_DEFAULT; reply->flags = RESOLVE_CLASS_DEFAULT;
vstring_strcpy(reply->transport, var_def_transport); vstring_strcpy(reply->transport, MAIL_SERVICE_SMTP);
vstring_strcpy(reply->nexthop, domain); vstring_strcpy(reply->nexthop, domain);
} }
vstring_strcpy(reply->recipient, addr); vstring_strcpy(reply->recipient, addr);

View File

@ -71,6 +71,7 @@ resolve.o: ../../include/vstring_vstream.h
resolve.o: ../../include/split_at.h resolve.o: ../../include/split_at.h
resolve.o: ../../include/valid_hostname.h resolve.o: ../../include/valid_hostname.h
resolve.o: ../../include/stringops.h resolve.o: ../../include/stringops.h
resolve.o: ../../include/mymalloc.h
resolve.o: ../../include/mail_params.h resolve.o: ../../include/mail_params.h
resolve.o: ../../include/mail_proto.h resolve.o: ../../include/mail_proto.h
resolve.o: ../../include/iostuff.h resolve.o: ../../include/iostuff.h
@ -127,6 +128,9 @@ transport.o: ../../include/mail_params.h
transport.o: ../../include/maps.h transport.o: ../../include/maps.h
transport.o: ../../include/match_parent_style.h transport.o: ../../include/match_parent_style.h
transport.o: ../../include/match_ops.h transport.o: ../../include/match_ops.h
transport.o: ../../include/mail_proto.h
transport.o: ../../include/iostuff.h
transport.o: ../../include/attr.h
transport.o: transport.h transport.o: transport.h
trivial-rewrite.o: trivial-rewrite.c trivial-rewrite.o: trivial-rewrite.c
trivial-rewrite.o: ../../include/sys_defs.h trivial-rewrite.o: ../../include/sys_defs.h

View File

@ -63,6 +63,7 @@
#include <split_at.h> #include <split_at.h>
#include <valid_hostname.h> #include <valid_hostname.h>
#include <stringops.h> #include <stringops.h>
#include <mymalloc.h>
/* Global library. */ /* Global library. */
@ -117,19 +118,12 @@
* nexthop information (or vice versa) may produce surprising results. In * nexthop information (or vice versa) may produce surprising results. In
* particular, the free text nexthop information for the error transport is * particular, the free text nexthop information for the error transport is
* likely to confuse regular delivery agents; and conversely, a hostname or * likely to confuse regular delivery agents; and conversely, a hostname or
* socket pathname is not a useful reason for non-delivery. * socket pathname is not an adequate text as reason for non-delivery.
* *
* In the code below, the class_domain variable specifies the domain name that * In the code below, rcpt_domain specifies the domain name that we will use
* we will use when (the class transport is the error transport and the * when the transport table specifies a non-default channel but no nexthop
* class transport is replaced by a transport map lookup result) but the * information (we use a generic text when that non-default channel is the
* nexthop information is not updated. * error transport).
*
* For the sake of completeness, we also take action when the reverse happens:
* replacing the class transport by the error transport without updating the
* nexthop information.
*
* The ability to specify "error:reason for non-delivery" in main.cf and in
* transport maps is just too convenient to take it away.
*/ */
#define STR vstring_str #define STR vstring_str
@ -141,13 +135,6 @@ static DOMAIN_LIST *relay_domains;
static STRING_LIST *virt_alias_doms; static STRING_LIST *virt_alias_doms;
static STRING_LIST *virt_mailbox_doms; static STRING_LIST *virt_mailbox_doms;
/*
* Saved address domain class information.
*/
static VSTRING *saved_class_channel;
static VSTRING *saved_class_nexthop;
static VSTRING *saved_class_domain;
static MAPS *relocated_maps; static MAPS *relocated_maps;
/* resolve_addr - resolve address according to rule set */ /* resolve_addr - resolve address according to rule set */
@ -157,50 +144,109 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
{ {
char *myname = "resolve_addr"; char *myname = "resolve_addr";
VSTRING *addr_buf = vstring_alloc(100); VSTRING *addr_buf = vstring_alloc(100);
TOK822 *tree; TOK822 *tree = 0;
TOK822 *saved_domain = 0; TOK822 *saved_domain = 0;
TOK822 *domain = 0; TOK822 *domain = 0;
char *destination; char *destination;
const char *blame = 0; const char *blame = 0;
const char *rcpt_domain; const char *rcpt_domain;
int addr_len;
int loop_count;
int loop_max;
char *local;
char *oper;
char *junk;
vstring_strcpy(saved_class_domain, "UNINITIALIZED SAVED_CLASS_DOMAIN");
*flags = 0; *flags = 0;
vstring_strcpy(channel, "CHANNEL NOT UPDATED");
vstring_strcpy(nexthop, "NEXTHOP NOT UPDATED");
vstring_strcpy(nextrcpt, "NEXTRCPT NOT UPDATED");
/* /*
* The address is in internalized (unquoted) form, so we must externalize * The address is in internalized (unquoted) form.
* it first before we can parse it.
* *
* While quoting the address local part, do not treat @ as a special * In an ideal world we would parse the externalized address form as given
* character. This allows us to detect extra @ characters and block * to us by the sender.
* source routed relay attempts.
* *
* But practically, we have to look at the unquoted form so that routing * However, in the real world we have to look for routing characters like
* characters like @ remain visible, in order to stop user@domain@domain * %@! in the address local-part, even when that information is quoted
* relay attempts when forwarding mail to a primary Sendmail MX host. * due to the presence of special characters or whitespace. Although
* technically incorrect, this is needed to stop user@domain@domain relay
* attempts when forwarding mail to a Sendmail MX host.
*
* This suggests that we parse the address in internalized (unquoted) form.
* Unfortunately, if we do that, the unparser generates incorrect white
* space between adjacent non-operator tokens. Example: ``first last''
* needs white space, but ``stuff[stuff]'' does not. This is is not a
* problem when unparsing the result from parsing externalized forms,
* because the parser/unparser were designed for valid externalized forms
* where ``stuff[stuff]'' does not happen.
*
* As a workaround we start with the quoted form and then dequote the
* local-part only where needed. This will do the right thing in most
* (but not all) cases.
*/ */
if (var_resolve_dequoted) { addr_len = strlen(addr);
tree = tok822_scan_addr(addr); quote_822_local(addr_buf, addr);
} else { tree = tok822_scan_addr(vstring_str(addr_buf));
quote_822_local(addr_buf, addr);
tree = tok822_scan_addr(vstring_str(addr_buf)); /*
* Let the optimizer replace multiple expansions of this macro by a GOTO
* to a single instance.
*/
#define FREE_MEMORY_AND_RETURN { \
if (saved_domain) \
tok822_free_tree(saved_domain); \
if(tree) \
tok822_free_tree(tree); \
if (addr_buf) \
vstring_free(addr_buf); \
} }
/* /*
* Preliminary resolver: strip off all instances of the local domain. * Preliminary resolver: strip off all instances of the local domain.
* Terminate when no destination domain is left over, or when the * Terminate when no destination domain is left over, or when the
* destination domain is remote. * destination domain is remote.
*
* XXX To whom it may concern. If you change the resolver loop below, or
* quote_822_local.c, or tok822_parse.c, be sure to re-run the tests
* under "make resolve_clnt_test" in the global directory.
*/ */
#define RESOLVE_LOCAL(domain) \ #define RESOLVE_LOCAL(domain) \
resolve_local(STR(tok822_internalize(addr_buf, domain, TOK822_STR_DEFL))) resolve_local(STR(tok822_internalize(addr_buf, domain, TOK822_STR_DEFL)))
while (tree->head) { dict_errno = 0;
for (loop_count = 0, loop_max = addr_len + 100; /* void */ ; loop_count++) {
/*
* Grr. resolve_local() table lookups may fail. It may be OK for
* local file lookup code to abort upon failure, but with
* network-based tables it is preferable to return an error
* indication to the requestor.
*/
if (dict_errno) {
*flags |= RESOLVE_FLAG_FAIL;
FREE_MEMORY_AND_RETURN;
}
/*
* XXX Should never happen, but if this happens with some
* pathological address, then that is not sufficient reason to
* disrupt the operation of an MTA.
*/
if (loop_count > loop_max) {
msg_warn("resolve_addr: <%s>: giving up after %d iterations",
addr, loop_count);
break;
}
/* /*
* Strip trailing dot at end of domain, but not dot-dot. This merely * Strip trailing dot at end of domain, but not dot-dot. This merely
* makes diagnostics more accurate by leaving bogus addresses alone. * makes diagnostics more accurate by leaving bogus addresses alone.
*/ */
if (tree->tail->type == '.' if (tree->tail
&& tree->tail->type == '.'
&& tok822_rfind_type(tree->tail, '@') != 0 && tok822_rfind_type(tree->tail, '@') != 0
&& tree->tail->prev->type != '.') && tree->tail->prev->type != '.')
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail)); tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
@ -208,26 +254,15 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
/* /*
* Strip trailing @. * Strip trailing @.
*/ */
if (tree->tail->type == '@') { if (tree->tail
&& tree->tail->type == '@')
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail)); tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
continue;
}
/*
* A lone empty string becomes the postmaster.
*/
if (tree->head == tree->tail && tree->head->type == TOK822_QSTRING
&& VSTRING_LEN(tree->head->vstr) == 0) {
tok822_free(tree->head);
tree->head = tok822_scan(MAIL_ADDR_POSTMASTER, &tree->tail);
rewrite_tree(REWRITE_CANON, tree);
}
/* /*
* Strip (and save) @domain if local. * Strip (and save) @domain if local.
*/ */
if ((domain = tok822_rfind_type(tree->tail, '@')) != 0) { if ((domain = tok822_rfind_type(tree->tail, '@')) != 0) {
if (RESOLVE_LOCAL(domain->next) == 0) if (domain->next && RESOLVE_LOCAL(domain->next) == 0)
break; break;
tok822_sub_keep_before(tree, domain); tok822_sub_keep_before(tree, domain);
if (saved_domain) if (saved_domain)
@ -239,32 +274,65 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
* After stripping the local domain, if any, replace foo%bar by * After stripping the local domain, if any, replace foo%bar by
* foo@bar, site!user by user@site, rewrite to canonical form, and * foo@bar, site!user by user@site, rewrite to canonical form, and
* retry. * retry.
*
* Otherwise we're done.
*/ */
if (tok822_rfind_type(tree->tail, '@') if (tok822_rfind_type(tree->tail, '@')
|| (var_swap_bangpath && tok822_rfind_type(tree->tail, '!')) || (var_swap_bangpath && tok822_rfind_type(tree->tail, '!'))
|| (var_percent_hack && tok822_rfind_type(tree->tail, '%'))) { || (var_percent_hack && tok822_rfind_type(tree->tail, '%'))) {
rewrite_tree(REWRITE_CANON, tree); rewrite_tree(REWRITE_CANON, tree);
} else { continue;
domain = 0;
break;
} }
/*
* If the local-part is a quoted string, crack it open when we're
* permitted to do so and look for routing operators. This is
* technically incorrect, but is needed to stop relaying problems.
*
* XXX Do another feeble attempt to keep local-part info quoted.
*/
if (var_resolve_dequoted
&& tree->head && tree->head == tree->tail
&& tree->head->type == TOK822_QSTRING
&& ((oper = strrchr(local = STR(tree->head->vstr), '@')) != 0
|| (var_percent_hack && (oper = strrchr(local, '%')) != 0)
|| (var_swap_bangpath && (oper = strrchr(local, '!')) != 0))) {
if (*oper == '%')
*oper = '@';
tok822_internalize(addr_buf, tree->head, TOK822_STR_DEFL);
if (*oper == '@') {
junk = mystrdup(STR(addr_buf));
quote_822_local(addr_buf, junk);
myfree(junk);
}
tok822_free(tree->head);
tree->head = tok822_scan(STR(addr_buf), &tree->tail);
rewrite_tree(REWRITE_CANON, tree);
continue;
}
/*
* An empty local-part or an empty quoted string local-part becomes
* the local MAILER-DAEMON, for consistency with our own From:
* message headers.
*/
if (tree->head && tree->head == tree->tail
&& tree->head->type == TOK822_QSTRING
&& VSTRING_LEN(tree->head->vstr) == 0) {
tok822_free(tree->head);
tree->head = 0;
}
if (tree->head == 0)
tree->head = tok822_scan(MAIL_ADDR_MAIL_DAEMON, &tree->tail);
/*
* We're done. There are no domains left to strip off the address,
* and all null local-part information is sanitized.
*/
domain = 0;
break;
} }
/* vstring_free(addr_buf);
* If the destination is non-local, recognize routing operators in the addr_buf = 0;
* address localpart. This is needed to prevent backup MX hosts from
* relaying third-party destinations through primary MX hosts, otherwise
* the backup host could end up on black lists. Ignore local
* swap_bangpath and percent_hack settings because we can't know how the
* primary MX host is set up.
*/
if (domain && domain->prev)
if (tok822_rfind_type(domain->prev, '@') != 0
|| tok822_rfind_type(domain->prev, '!') != 0
|| tok822_rfind_type(domain->prev, '%') != 0)
*flags |= RESOLVE_FLAG_ROUTED;
/* /*
* Make sure the resolved envelope recipient has the user@domain form. If * Make sure the resolved envelope recipient has the user@domain form. If
@ -275,105 +343,134 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
if (saved_domain) { if (saved_domain) {
tok822_sub_append(tree, saved_domain); tok822_sub_append(tree, saved_domain);
saved_domain = 0; saved_domain = 0;
} else { /* Aargh! Always! */ } else {
tok822_sub_append(tree, tok822_alloc('@', (char *) 0)); tok822_sub_append(tree, tok822_alloc('@', (char *) 0));
tok822_sub_append(tree, tok822_scan(var_myhostname, (TOK822 **) 0)); tok822_sub_append(tree, tok822_scan(var_myhostname, (TOK822 **) 0));
} }
} }
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
/* /*
* With relay or other non-local destinations, the relayhost setting * Transform the recipient address back to internal form.
* overrides the destination domain name.
* *
* With virtual, relay, or other non-local destinations, give the highest * XXX This may produce incorrect results if we cracked open a quoted
* precedence to delivery transport associated next-hop information. * local-part with routing operators; see discussion above at the top of
* the big loop.
*/
tok822_internalize(nextrcpt, tree, TOK822_STR_DEFL);
rcpt_domain = strrchr(STR(nextrcpt), '@') + 1;
if (*rcpt_domain == '[' ? !valid_hostliteral(rcpt_domain, DONT_GRIPE) :
!valid_hostname(rcpt_domain, DONT_GRIPE))
*flags |= RESOLVE_FLAG_ERROR;
tok822_free_tree(tree);
tree = 0;
/*
* Recognize routing operators in the local-part, even when we do not
* recognize ! or % as valid routing operators locally. This is needed to
* prevent backup MX hosts from relaying third-party destinations through
* primary MX hosts, otherwise the backup host could end up on black
* lists. Ignore local swap_bangpath and percent_hack settings because we
* can't know how the next MX host is set up.
*/
if (strcmp(STR(nextrcpt) + strcspn(STR(nextrcpt), "@!%") + 1, rcpt_domain))
*flags |= RESOLVE_FLAG_ROUTED;
/*
* With local, virtual, relay, or other non-local destinations, give the
* highest precedence to transport associated nexthop information.
* *
* XXX With the virtual mailbox transport, set the nexthop information to * Otherwise, with relay or other non-local destinations, the relayhost
* $myhostname, so that in default configurations the virtual delivery * setting overrides the destination domain name.
* agent will not use separate queues for every $virtual_mailbox_domains
* domain name. That prevents anomalies where many low-traffic domains
* starve a high-traffic domain.
* *
* XXX Nag if the domain is listed in multiple domain lists. The effect is * XXX Nag if the recipient domain is listed in multiple domain lists. The
* implementation defined, and may break when internals change. * result is implementation defined, and may break when internals change.
*
* For now, we distinguish only a fixed number of address classes.
* Eventually this may become extensible, so that new classes can be
* configured with their own domain list, delivery transport, and
* recipient table.
*/ */
#define STREQ(x,y) (strcmp((x), (y)) == 0) #define STREQ(x,y) (strcmp((x), (y)) == 0)
dict_errno = 0; dict_errno = 0;
if (domain != 0) { if (domain != 0) {
tok822_internalize(nexthop, domain->next, TOK822_STR_DEFL);
vstring_strcpy(saved_class_domain, STR(nexthop)); /*
if (STR(nexthop)[strspn(STR(nexthop), "[]0123456789.")] != 0 * Virtual alias domain.
&& valid_hostname(STR(nexthop), DONT_GRIPE) == 0) */
*flags |= RESOLVE_FLAG_ERROR;
if (virt_alias_doms if (virt_alias_doms
&& string_list_match(virt_alias_doms, STR(nexthop))) { && string_list_match(virt_alias_doms, rcpt_domain)) {
if (var_helpful_warnings if (var_helpful_warnings
&& virt_mailbox_doms && virt_mailbox_doms
&& string_list_match(virt_mailbox_doms, STR(nexthop))) && string_list_match(virt_mailbox_doms, rcpt_domain))
msg_warn("do not list domain %s in BOTH %s and %s", msg_warn("do not list domain %s in BOTH %s and %s",
STR(nexthop), VAR_VIRT_ALIAS_DOMS, VAR_VIRT_MAILBOX_DOMS); rcpt_domain, VAR_VIRT_ALIAS_DOMS,
vstring_strcpy(channel, var_error_transport); VAR_VIRT_MAILBOX_DOMS);
vstring_strcpy(channel, MAIL_SERVICE_ERROR);
vstring_strcpy(nexthop, "User unknown in virtual alias table"); vstring_strcpy(nexthop, "User unknown in virtual alias table");
vstring_strcpy(saved_class_domain, var_myhostname);
blame = VAR_ERROR_TRANSPORT;
*flags |= RESOLVE_CLASS_ALIAS; *flags |= RESOLVE_CLASS_ALIAS;
} else if (dict_errno != 0) { } else if (dict_errno != 0) {
msg_warn("%s lookup failure", VAR_VIRT_ALIAS_DOMS); msg_warn("%s lookup failure", VAR_VIRT_ALIAS_DOMS);
*flags |= RESOLVE_FLAG_FAIL; *flags |= RESOLVE_FLAG_FAIL;
} else if (virt_mailbox_doms FREE_MEMORY_AND_RETURN;
&& string_list_match(virt_mailbox_doms, STR(nexthop))) { }
/*
* Virtual mailbox domain.
*/
else if (virt_mailbox_doms
&& string_list_match(virt_mailbox_doms, rcpt_domain)) {
vstring_strcpy(channel, var_virt_transport); vstring_strcpy(channel, var_virt_transport);
vstring_strcpy(nexthop, var_myhostname); vstring_strcpy(nexthop, rcpt_domain);
vstring_strcpy(saved_class_domain, var_myhostname);
blame = VAR_VIRT_TRANSPORT; blame = VAR_VIRT_TRANSPORT;
*flags |= RESOLVE_CLASS_VIRTUAL; *flags |= RESOLVE_CLASS_VIRTUAL;
} else if (dict_errno != 0) { } else if (dict_errno != 0) {
msg_warn("%s lookup failure", VAR_VIRT_MAILBOX_DOMS); msg_warn("%s lookup failure", VAR_VIRT_MAILBOX_DOMS);
*flags |= RESOLVE_FLAG_FAIL; *flags |= RESOLVE_FLAG_FAIL;
FREE_MEMORY_AND_RETURN;
} else { } else {
/*
* Off-host relay destination.
*/
if (relay_domains if (relay_domains
&& domain_list_match(relay_domains, STR(nexthop))) { && domain_list_match(relay_domains, rcpt_domain)) {
vstring_strcpy(channel, var_relay_transport); vstring_strcpy(channel, var_relay_transport);
blame = VAR_RELAY_TRANSPORT; blame = VAR_RELAY_TRANSPORT;
*flags |= RESOLVE_CLASS_RELAY; *flags |= RESOLVE_CLASS_RELAY;
} else if (dict_errno != 0) { } else if (dict_errno != 0) {
msg_warn("%s lookup failure", VAR_RELAY_DOMAINS); msg_warn("%s lookup failure", VAR_RELAY_DOMAINS);
*flags |= RESOLVE_FLAG_FAIL; *flags |= RESOLVE_FLAG_FAIL;
} else { FREE_MEMORY_AND_RETURN;
}
/*
* Other off-host destination.
*/
else {
vstring_strcpy(channel, var_def_transport); vstring_strcpy(channel, var_def_transport);
blame = VAR_DEF_TRANSPORT; blame = VAR_DEF_TRANSPORT;
*flags |= RESOLVE_CLASS_DEFAULT; *flags |= RESOLVE_CLASS_DEFAULT;
} }
if (*var_relayhost) {
/*
* With off-host delivery, relayhost overrides recipient domain.
*/
if (*var_relayhost)
vstring_strcpy(nexthop, var_relayhost); vstring_strcpy(nexthop, var_relayhost);
if (!STREQ(STR(channel), var_error_transport)) else
vstring_strcpy(saved_class_domain, STR(nexthop)); vstring_strcpy(nexthop, rcpt_domain);
}
}
if ((destination = split_at(STR(channel), ':')) != 0 && *destination) {
vstring_strcpy(nexthop, destination);
if (!STREQ(STR(channel), var_error_transport))
vstring_strcpy(saved_class_domain, STR(nexthop));
} }
} }
/* /*
* Local delivery. Set up the default local transport and the default * Local delivery.
* next-hop hostname (myself).
*
* XXX Set the nexthop information to myhostname, so that the local delivery
* agent does not get a queue for every domain name in $mydestination or
* for every network address in $inet_interfaces.
* *
* XXX Nag if the domain is listed in multiple domain lists. The effect is * XXX Nag if the domain is listed in multiple domain lists. The effect is
* implementation defined, and may break when internals change. * implementation defined, and may break when internals change.
*/ */
else { else {
if (var_helpful_warnings if (var_helpful_warnings) {
&& (rcpt_domain = strrchr(STR(nextrcpt), '@')) != 0) {
rcpt_domain++;
if (virt_alias_doms if (virt_alias_doms
&& string_list_match(virt_alias_doms, rcpt_domain)) && string_list_match(virt_alias_doms, rcpt_domain))
msg_warn("do not list domain %s in BOTH %s and %s", msg_warn("do not list domain %s in BOTH %s and %s",
@ -384,56 +481,67 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS); rcpt_domain, VAR_MYDEST, VAR_VIRT_MAILBOX_DOMS);
} }
vstring_strcpy(channel, var_local_transport); vstring_strcpy(channel, var_local_transport);
vstring_strcpy(nexthop, rcpt_domain);
blame = VAR_LOCAL_TRANSPORT; blame = VAR_LOCAL_TRANSPORT;
if ((destination = split_at(STR(channel), ':')) == 0
|| *destination == 0)
destination = var_myhostname;
vstring_strcpy(nexthop, destination);
if (!STREQ(STR(channel), var_error_transport))
vstring_strcpy(saved_class_domain, STR(nexthop));
else
vstring_strcpy(saved_class_domain, var_myhostname);
*flags |= RESOLVE_CLASS_LOCAL; *flags |= RESOLVE_CLASS_LOCAL;
} }
/* /*
* Sanity checks. * An explicit main.cf transport:nexthop setting overrides the nexthop.
*
* XXX We depend on this mechanism to enforce per-recipient concurrencies
* for local recipients. With "local_transport = local:$myhostname" we
* force mail for any domain in $mydestination/$inet_interfaces to share
* the same queue.
*/ */
if ((*flags & RESOLVE_FLAG_FAIL) == 0) { if ((destination = split_at(STR(channel), ':')) != 0 && *destination)
if (*STR(channel) == 0) { vstring_strcpy(nexthop, destination);
if (blame == 0)
msg_panic("%s: null blame", myname);
msg_warn("file %s/%s: parameter %s: null transport is not allowed",
var_config_dir, MAIN_CONF_FILE, blame);
*flags |= RESOLVE_FLAG_FAIL;
}
if (*STR(nexthop) == 0)
msg_panic("%s: null nexthop", myname);
}
/* /*
* The transport map overrides any transport and next-hop host info that * Sanity checks.
* is set up above.
*
* With error transports, the nexthop info is arbitrary text that must not
* be passed on to regular delivery agents. When the transport map
* overrides an error transport without overriding the nexthop
* information, or vice versa, update the nexthop information
* appropriately.
*/ */
if ((*flags & RESOLVE_FLAG_FAIL) == 0 && *var_transport_maps) { if (*STR(channel) == 0) {
vstring_strcpy(saved_class_channel, STR(channel)); if (blame == 0)
vstring_strcpy(saved_class_nexthop, STR(nexthop)); msg_panic("%s: null blame", myname);
msg_warn("file %s/%s: parameter %s: null transport is not allowed",
var_config_dir, MAIN_CONF_FILE, blame);
*flags |= RESOLVE_FLAG_FAIL;
FREE_MEMORY_AND_RETURN;
}
if (*STR(nexthop) == 0)
msg_panic("%s: null nexthop", myname);
if (transport_lookup(STR(nextrcpt), channel, nexthop) != 0) { /*
if (!STREQ(STR(saved_class_channel), STR(channel)) * The transport map can selectively override any transport and/or
&& STREQ(STR(saved_class_nexthop), STR(nexthop))) { * nexthop host info that is set up above. Unfortunately, the syntax for
vstring_strcpy(nexthop, STREQ(STR(channel), var_error_transport) ? * nexthop information is transport specific. We therefore need sane and
"Address is not deliverable" : STR(saved_class_domain)); * intuitive semantics for transport map entries that specify a channel
} * but no nexthop.
} else if (dict_errno != 0) { *
* With non-error transports, the initial nexthop information is the
* recipient domain. However, specific main.cf transport definitions may
* specify a transport-specific destination, such as a host + TCP socket,
* or the pathname of a UNIX-domain socket. With less precedence than
* main.cf transport definitions, a main.cf relayhost definition may also
* override nexthop information for off-host deliveries.
*
* With the error transport, the nexthop information is free text that
* specifies the reason for non-delivery.
*
* Because nexthop syntax is transport specific we reset the nexthop
* information to the recipient domain when the transport table specifies
* a transport without also specifying the nexthop information.
*
* Subtle note: reset nexthop even when the transport table does not change
* the transport. Otherwise it is hard to get rid of main.cf specified
* nexthop information.
*/
if (*var_transport_maps) {
if (transport_lookup(STR(nextrcpt), rcpt_domain, channel, nexthop) == 0
&& dict_errno != 0) {
msg_warn("%s lookup failure", VAR_TRANSPORT_MAPS); msg_warn("%s lookup failure", VAR_TRANSPORT_MAPS);
*flags |= RESOLVE_FLAG_FAIL; *flags |= RESOLVE_FLAG_FAIL;
FREE_MEMORY_AND_RETURN;
} }
} }
@ -448,26 +556,24 @@ void resolve_addr(char *addr, VSTRING *channel, VSTRING *nexthop,
*/ */
#define IGNORE_ADDR_EXTENSION ((char **) 0) #define IGNORE_ADDR_EXTENSION ((char **) 0)
if ((*flags & RESOLVE_FLAG_FAIL) == 0 && relocated_maps != 0) { if (relocated_maps != 0) {
const char *newloc; const char *newloc;
if ((newloc = mail_addr_find(relocated_maps, STR(nextrcpt), if ((newloc = mail_addr_find(relocated_maps, STR(nextrcpt),
IGNORE_ADDR_EXTENSION)) != 0) { IGNORE_ADDR_EXTENSION)) != 0) {
vstring_strcpy(channel, var_error_transport); vstring_strcpy(channel, MAIL_SERVICE_ERROR);
vstring_sprintf(nexthop, "User has moved to %s", newloc); vstring_sprintf(nexthop, "User has moved to %s", newloc);
} else if (dict_errno != 0) { } else if (dict_errno != 0) {
msg_warn("%s lookup failure", VAR_RELOCATED_MAPS); msg_warn("%s lookup failure", VAR_RELOCATED_MAPS);
*flags |= RESOLVE_FLAG_FAIL; *flags |= RESOLVE_FLAG_FAIL;
FREE_MEMORY_AND_RETURN;
} }
} }
/* /*
* Clean up. * Clean up.
*/ */
if (saved_domain) FREE_MEMORY_AND_RETURN;
tok822_free_tree(saved_domain);
tok822_free_tree(tree);
vstring_free(addr_buf);
} }
/* Static, so they can be used by the network protocol interface only. */ /* Static, so they can be used by the network protocol interface only. */
@ -516,9 +622,6 @@ void resolve_init(void)
channel = vstring_alloc(100); channel = vstring_alloc(100);
nexthop = vstring_alloc(100); nexthop = vstring_alloc(100);
nextrcpt = vstring_alloc(100); nextrcpt = vstring_alloc(100);
saved_class_channel = vstring_alloc(100);
saved_class_nexthop = vstring_alloc(100);
saved_class_domain = vstring_alloc(100);
if (*var_virt_alias_doms) if (*var_virt_alias_doms)
virt_alias_doms = virt_alias_doms =

View File

@ -90,6 +90,12 @@ void rewrite_tree(char *unused_ruleset, TOK822 *tree)
TOK822 *bang; TOK822 *bang;
TOK822 *local; TOK822 *local;
/*
* XXX If you change this module, quote_822_local.c, or tok822_parse.c,
* be sure to re-run the tests under "make rewrite_clnt_test" and "make
* resolve_clnt_test" in the global directory.
*/
/* /*
* Sanity check. * Sanity check.
*/ */
@ -158,10 +164,13 @@ void rewrite_tree(char *unused_ruleset, TOK822 *tree)
} }
/* /*
* Append missing .domain * Append missing .domain, but leave broken forms ending in @ alone. This
* merely makes diagnostics more accurate by leaving bogus addresses
* alone.
*/ */
if (var_append_dot_mydomain != 0 if (var_append_dot_mydomain != 0
&& (domain = tok822_rfind_type(tree->tail, '@')) != 0 && (domain = tok822_rfind_type(tree->tail, '@')) != 0
&& domain != tree->tail
&& tok822_find_type(domain, TOK822_DOMLIT) == 0 && tok822_find_type(domain, TOK822_DOMLIT) == 0
&& tok822_find_type(domain, '.') == 0) { && tok822_find_type(domain, '.') == 0) {
tok822_sub_append(tree, tok822_alloc('.', (char *) 0)); tok822_sub_append(tree, tok822_alloc('.', (char *) 0));
@ -169,13 +178,17 @@ void rewrite_tree(char *unused_ruleset, TOK822 *tree)
} }
/* /*
* Strip trailing dot at end of domain, but not dot-dot. This merely * Strip trailing dot at end of domain, but not dot-dot or @-dot. This
* makes diagnostics more accurate by leaving bogus addresses alone. * merely makes diagnostics more accurate by leaving bogus addresses
* alone.
*/ */
#if 0
if (tree->tail->type == '.' if (tree->tail->type == '.'
&& tok822_rfind_type(tree->tail, '@') != 0 && tree->tail->prev
&& tree->tail->prev->type != '.') && tree->tail->prev->type != '.'
&& tree->tail->prev->type != '@')
tok822_free_tree(tok822_sub_keep_before(tree, tree->tail)); tok822_free_tree(tok822_sub_keep_before(tree, tree->tail));
#endif
} }
/* rewrite_addr - rewrite address according to rule set */ /* rewrite_addr - rewrite address according to rule set */

View File

@ -8,8 +8,9 @@
/* /*
/* void transport_init() /* void transport_init()
/* /*
/* int transport_lookup(address, channel, nexthop) /* int transport_lookup(address, rcpt_domain, channel, nexthop)
/* const char *address; /* const char *address;
/* const char *rcpt_domain;
/* VSTRING *channel; /* VSTRING *channel;
/* VSTRING *nexthop; /* VSTRING *nexthop;
/* DESCRIPTION /* DESCRIPTION
@ -65,6 +66,7 @@
#include <mail_params.h> #include <mail_params.h>
#include <maps.h> #include <maps.h>
#include <match_parent_style.h> #include <match_parent_style.h>
#include <mail_proto.h>
/* Application-specific. */ /* Application-specific. */
@ -77,13 +79,6 @@ static VSTRING *wildcard_nexthop;
#define STR(x) vstring_str(x) #define STR(x) vstring_str(x)
/*
* Macro for consistent updates of the transport and nexthop results.
*/
#define UPDATE_IF_SPECIFIED(dst, src) do { \
if ((src) && *(src)) vstring_strcpy((dst), (src)); \
} while (0)
/* transport_init - pre-jail initialization */ /* transport_init - pre-jail initialization */
void transport_init(void) void transport_init(void)
@ -95,15 +90,52 @@ void transport_init(void)
transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS); transport_match_parent_style = match_parent_style(VAR_TRANSPORT_MAPS);
} }
/* update_entry - update from transport table entry */
static void update_entry(const char *new_channel, const char *new_nexthop,
const char *rcpt_domain, VSTRING *channel,
VSTRING *nexthop)
{
/*
* :[nexthop] means don't change the channel, and don't change the
* nexthop unless a non-default nexthop is specified. Thus, a right-hand
* side of ":" is the transport table equivalent of a NOOP.
*/
if (*new_channel == 0) { /* :[nexthop] */
if (*new_nexthop != 0)
vstring_strcpy(nexthop, new_nexthop);
}
/*
* transport[:[nexthop]] means change the channel, and reset the nexthop
* to the default unless a non-default nexthop is specified.
*/
else {
vstring_strcpy(channel, new_channel);
if (*new_nexthop != 0)
vstring_strcpy(nexthop, new_nexthop);
else if (strcmp(STR(channel), MAIL_SERVICE_ERROR) != 0)
vstring_strcpy(nexthop, rcpt_domain);
else
vstring_strcpy(nexthop, "Address is undeliverable");
}
}
/* find_transport_entry - look up and parse transport table entry */ /* find_transport_entry - look up and parse transport table entry */
static int find_transport_entry(const char *key, int flags, static int find_transport_entry(const char *key, const char *rcpt_domain,
VSTRING *channel, VSTRING *nexthop) int flags, VSTRING *channel, VSTRING *nexthop)
{ {
char *saved_value; char *saved_value;
const char *host; const char *host;
const char *value; const char *value;
/*
* Reset previous error history.
*/
dict_errno = 0;
#define FOUND 1 #define FOUND 1
#define NOTFOUND 0 #define NOTFOUND 0
@ -115,11 +147,8 @@ static int find_transport_entry(const char *key, int flags,
* *
* XXX Should report lookup failure status to caller instead of aborting. * XXX Should report lookup failure status to caller instead of aborting.
*/ */
if ((value = maps_find(transport_path, key, flags)) == 0) { if ((value = maps_find(transport_path, key, flags)) == 0)
if (dict_errno != 0)
msg_fatal("transport table lookup problem.");
return (NOTFOUND); return (NOTFOUND);
}
/* /*
* It would be great if we could specify a recipient address in the * It would be great if we could specify a recipient address in the
@ -131,8 +160,8 @@ static int find_transport_entry(const char *key, int flags,
else { else {
saved_value = mystrdup(value); saved_value = mystrdup(value);
host = split_at(saved_value, ':'); host = split_at(saved_value, ':');
UPDATE_IF_SPECIFIED(nexthop, host); update_entry(saved_value, host ? host : "", rcpt_domain,
UPDATE_IF_SPECIFIED(channel, saved_value); channel, nexthop);
myfree(saved_value); myfree(saved_value);
return (FOUND); return (FOUND);
} }
@ -159,13 +188,15 @@ void transport_wildcard_init(void)
#define FULL 0 #define FULL 0
#define PARTIAL DICT_FLAG_FIXED #define PARTIAL DICT_FLAG_FIXED
if (find_transport_entry(WILDCARD, FULL, channel, nexthop)) { if (find_transport_entry(WILDCARD, "", FULL, channel, nexthop)) {
wildcard_channel = channel; wildcard_channel = channel;
wildcard_nexthop = nexthop; wildcard_nexthop = nexthop;
if (msg_verbose) if (msg_verbose)
msg_info("wildcard_{chan:hop}={%s:%s}", msg_info("wildcard_{chan:hop}={%s:%s}",
vstring_str(wildcard_channel), vstring_str(wildcard_nexthop)); vstring_str(wildcard_channel), vstring_str(wildcard_nexthop));
} else { } else {
if (dict_errno != 0)
msg_fatal("transport table initialization problem.");
vstring_free(channel); vstring_free(channel);
vstring_free(nexthop); vstring_free(nexthop);
} }
@ -173,9 +204,10 @@ void transport_wildcard_init(void)
/* transport_lookup - map a transport domain */ /* transport_lookup - map a transport domain */
int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop) int transport_lookup(const char *addr, const char *rcpt_domain,
VSTRING *channel, VSTRING *nexthop)
{ {
char *full_addr = lowercase(mystrdup(*addr ? addr : var_xport_null_key)); char *full_addr;
char *stripped_addr; char *stripped_addr;
char *ratsign = 0; char *ratsign = 0;
const char *name; const char *name;
@ -185,6 +217,15 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
#define STREQ(x,y) (strcmp((x), (y)) == 0) #define STREQ(x,y) (strcmp((x), (y)) == 0)
#define DISCARD_EXTENSION ((char **) 0) #define DISCARD_EXTENSION ((char **) 0)
/*
* The null recipient is rewritten to the local mailer daemon address.
*/
if (*addr == 0) {
msg_warn("transport_lookup: null address - skipping table lookup");
return (NOTFOUND);
}
full_addr = lowercase(mystrdup(addr));
/* /*
* The optimizer will replace multiple instances of this macro expansion * The optimizer will replace multiple instances of this macro expansion
* by gotos to a single instance that does the same thing. * by gotos to a single instance that does the same thing.
@ -194,16 +235,6 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
return (x); \ return (x); \
} }
/*
* If this is a special address such as <> do only one lookup of the full
* string. Specify the FULL flag to include regexp maps in the query.
*/
if (STREQ(full_addr, var_xport_null_key)) {
if (find_transport_entry(full_addr, FULL, channel, nexthop))
RETURN_FREE(FOUND);
RETURN_FREE(NOTFOUND);
}
/* /*
* Look up the full address with the FULL flag to include regexp maps in * Look up the full address with the FULL flag to include regexp maps in
* the query. * the query.
@ -211,8 +242,10 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
if ((ratsign = strrchr(full_addr, '@')) == 0 || ratsign[1] == 0) if ((ratsign = strrchr(full_addr, '@')) == 0 || ratsign[1] == 0)
msg_panic("transport_lookup: bad address: \"%s\"", full_addr); msg_panic("transport_lookup: bad address: \"%s\"", full_addr);
if (find_transport_entry(full_addr, FULL, channel, nexthop)) if (find_transport_entry(full_addr, rcpt_domain, FULL, channel, nexthop))
RETURN_FREE(FOUND); RETURN_FREE(FOUND);
if (dict_errno != 0)
RETURN_FREE(NOTFOUND);
/* /*
* If the full address did not match, and there is an address extension, * If the full address did not match, and there is an address extension,
@ -221,13 +254,14 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
*/ */
if ((stripped_addr = strip_addr(full_addr, DISCARD_EXTENSION, if ((stripped_addr = strip_addr(full_addr, DISCARD_EXTENSION,
*var_rcpt_delim)) != 0) { *var_rcpt_delim)) != 0) {
if (find_transport_entry(stripped_addr, PARTIAL, found = find_transport_entry(stripped_addr, rcpt_domain, PARTIAL,
channel, nexthop)) { channel, nexthop);
myfree(stripped_addr);
myfree(stripped_addr);
if (found)
RETURN_FREE(FOUND); RETURN_FREE(FOUND);
} else { if (dict_errno != 0)
myfree(stripped_addr); RETURN_FREE(NOTFOUND);
}
} }
/* /*
@ -246,9 +280,11 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
* Specify that the lookup key is partial, to avoid matching partial keys * Specify that the lookup key is partial, to avoid matching partial keys
* with regular expressions. * with regular expressions.
*/ */
for (found = 0, name = ratsign + 1; /* void */ ; name = next) { for (name = ratsign + 1; /* void */ ; name = next) {
if (find_transport_entry(name, PARTIAL, channel, nexthop)) if (find_transport_entry(name, rcpt_domain, PARTIAL, channel, nexthop))
RETURN_FREE(FOUND); RETURN_FREE(FOUND);
if (dict_errno != 0)
RETURN_FREE(NOTFOUND);
if ((next = strchr(name + 1, '.')) == 0) if ((next = strchr(name + 1, '.')) == 0)
break; break;
if (transport_match_parent_style == MATCH_FLAG_PARENT) if (transport_match_parent_style == MATCH_FLAG_PARENT)
@ -259,8 +295,8 @@ int transport_lookup(const char *addr, VSTRING *channel, VSTRING *nexthop)
* Fall back to the wild-card entry. * Fall back to the wild-card entry.
*/ */
if (wildcard_channel) { if (wildcard_channel) {
UPDATE_IF_SPECIFIED(channel, STR(wildcard_channel)); update_entry(STR(wildcard_channel), STR(wildcard_nexthop),
UPDATE_IF_SPECIFIED(nexthop, STR(wildcard_nexthop)); rcpt_domain, channel, nexthop);
RETURN_FREE(FOUND); RETURN_FREE(FOUND);
} }

View File

@ -18,7 +18,7 @@
*/ */
extern void transport_init(void); extern void transport_init(void);
extern void transport_wildcard_init(void); extern void transport_wildcard_init(void);
extern int transport_lookup(const char *, VSTRING *, VSTRING *); extern int transport_lookup(const char *, const char *, VSTRING *, VSTRING *);
/* LICENSE /* LICENSE
/* .ad /* .ad

View File

@ -101,15 +101,6 @@
/* .sp /* .sp
/* Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5) /* Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5)
/* for details. The :\fInexthop\fR part is optional. /* for details. The :\fInexthop\fR part is optional.
/* .IP \fBerror_transport\fR
/* Where to deliver mail for non-existent recipients in domains
/* that match \fBvirtual_alias_domains\fR (all recipients
/* in simulated virtual domains must be aliased to some other
/* local or remote domain), or for recipients that have moved.
/* The default transport is \fBerror\fR.
/* .sp
/* Syntax is \fItransport\fR:\fInexthop\fR; see \fBtransport\fR(5)
/* for details. The :\fInexthop\fR part is optional.
/* .IP \fBvirtual_transport\fR /* .IP \fBvirtual_transport\fR
/* Where to deliver mail for non-local domains that match /* Where to deliver mail for non-local domains that match
/* \fB$virtual_mailbox_domains\fR. /* \fB$virtual_mailbox_domains\fR.
@ -144,8 +135,6 @@
/* .IP \fBtransport_maps\fR /* .IP \fBtransport_maps\fR
/* List of tables with \fIdomain\fR to (\fItransport, nexthop\fR) /* List of tables with \fIdomain\fR to (\fItransport, nexthop\fR)
/* mappings. /* mappings.
/* .IP \fBtransport_null_address_lookup_key\fR
/* Lookup key to be used for the null address.
/* SEE ALSO /* SEE ALSO
/* master(8) process manager /* master(8) process manager
/* syslogd(8) system logging /* syslogd(8) system logging
@ -208,11 +197,9 @@ bool var_append_dot_mydomain;
bool var_append_at_myorigin; bool var_append_at_myorigin;
bool var_percent_hack; bool var_percent_hack;
char *var_local_transport; char *var_local_transport;
char *var_error_transport;
char *var_virt_transport; char *var_virt_transport;
char *var_relay_transport; char *var_relay_transport;
int var_resolve_dequoted; int var_resolve_dequoted;
char *var_xport_null_key;
char *var_virt_alias_maps; /* XXX virtual_alias_domains */ char *var_virt_alias_maps; /* XXX virtual_alias_domains */
char *var_virt_mailbox_maps; /* XXX virtual_mailbox_domains */ char *var_virt_mailbox_maps; /* XXX virtual_mailbox_domains */
char *var_virt_alias_doms; char *var_virt_alias_doms;
@ -284,10 +271,8 @@ int main(int argc, char **argv)
static CONFIG_STR_TABLE str_table[] = { static CONFIG_STR_TABLE str_table[] = {
VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0, VAR_TRANSPORT_MAPS, DEF_TRANSPORT_MAPS, &var_transport_maps, 0, 0,
VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport, 1, 0, VAR_LOCAL_TRANSPORT, DEF_LOCAL_TRANSPORT, &var_local_transport, 1, 0,
VAR_ERROR_TRANSPORT, DEF_ERROR_TRANSPORT, &var_error_transport, 1, 0,
VAR_VIRT_TRANSPORT, DEF_VIRT_TRANSPORT, &var_virt_transport, 1, 0, VAR_VIRT_TRANSPORT, DEF_VIRT_TRANSPORT, &var_virt_transport, 1, 0,
VAR_RELAY_TRANSPORT, DEF_RELAY_TRANSPORT, &var_relay_transport, 1, 0, VAR_RELAY_TRANSPORT, DEF_RELAY_TRANSPORT, &var_relay_transport, 1, 0,
VAR_XPORT_NULL_KEY, DEF_XPORT_NULL_KEY, &var_xport_null_key, 1, 0,
VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0, VAR_VIRT_ALIAS_MAPS, DEF_VIRT_ALIAS_MAPS, &var_virt_alias_maps, 0, 0,
VAR_VIRT_ALIAS_DOMS, DEF_VIRT_ALIAS_DOMS, &var_virt_alias_doms, 0, 0, VAR_VIRT_ALIAS_DOMS, DEF_VIRT_ALIAS_DOMS, &var_virt_alias_doms, 0, 0,
VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0, VAR_VIRT_MAILBOX_MAPS, DEF_VIRT_MAILBOX_MAPS, &var_virt_mailbox_maps, 0, 0,

View File

@ -13,6 +13,10 @@
/* int valid_hostaddr(addr, gripe) /* int valid_hostaddr(addr, gripe)
/* const char *addr; /* const char *addr;
/* int gripe; /* int gripe;
/*
/* int valid_hostliteral(addr, gripe)
/* const char *addr;
/* int gripe;
/* DESCRIPTION /* DESCRIPTION
/* valid_hostname() scrutinizes a hostname: the name should be no /* valid_hostname() scrutinizes a hostname: the name should be no
/* longer than VALID_HOSTNAME_LEN characters, should contain only /* longer than VALID_HOSTNAME_LEN characters, should contain only
@ -20,9 +24,11 @@
/* no leading or trailing dots or hyphens, no labels longer than /* no leading or trailing dots or hyphens, no labels longer than
/* VALID_LABEL_LEN characters, and no numeric top-level domain. /* VALID_LABEL_LEN characters, and no numeric top-level domain.
/* /*
/* valid_hostaddr() requirs that the input is a valid string /* valid_hostaddr() requires that the input is a valid string
/* representation of an internet network address. /* representation of an internet network address.
/* /*
/* valid_hostliteral() requires an address enclosed in [].
/*
/* These routines operate silently unless the gripe parameter /* These routines operate silently unless the gripe parameter
/* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE /* specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
/* provide suitable constants. /* provide suitable constants.
@ -192,6 +198,39 @@ int valid_hostaddr(const char *addr, int gripe)
return (1); return (1);
} }
/* valid_hostliteral - validate address literal */
int valid_hostliteral(const char *addr, int gripe)
{
const char *myname = "valid_hostliteral";
char buf[100];
const char *last;
if (*addr != '[') {
if (gripe)
msg_warn("%s: '[' expected at start: %.100s", myname, addr);
return (0);
}
if ((last = strchr(addr, ']')) == 0) {
if (gripe)
msg_warn("%s: ']' expected at end: %.100s", myname, addr);
return (0);
}
if (last[1]) {
if (gripe)
msg_warn("%s: unexpected text after ']': %.100s", myname, addr);
return (0);
}
if (last - addr >= sizeof(buf)) {
if (gripe)
msg_warn("%s: too much text: %.100s", myname, addr);
return (0);
}
strncpy(buf, addr + 1, last - addr - 1);
buf[last - addr - 1] = 0;
return (valid_hostaddr(buf, gripe));
}
#ifdef TEST #ifdef TEST
/* /*
@ -216,6 +255,7 @@ int main(int unused_argc, char **argv)
msg_info("testing: \"%s\"", vstring_str(buffer)); msg_info("testing: \"%s\"", vstring_str(buffer));
valid_hostname(vstring_str(buffer), DO_GRIPE); valid_hostname(vstring_str(buffer), DO_GRIPE);
valid_hostaddr(vstring_str(buffer), DO_GRIPE); valid_hostaddr(vstring_str(buffer), DO_GRIPE);
valid_hostliteral(vstring_str(buffer), DO_GRIPE);
} }
exit(0); exit(0);
} }

View File

@ -21,6 +21,7 @@
extern int valid_hostname(const char *, int); extern int valid_hostname(const char *, int);
extern int valid_hostaddr(const char *, int); extern int valid_hostaddr(const char *, int);
extern int valid_hostliteral(const char *, int);
/* LICENSE /* LICENSE
/* .ad /* .ad

View File

@ -36,3 +36,8 @@ a.bb-.b
a.b.-bb a.b.-bb
a.b.bb- a.b.bb-
a-a.b-b a-a.b-b
[1.2.3.4]
[321.255.255.255]
[1.2.3.4
[1.2.3.4]foo
[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]

View File

@ -1,101 +1,158 @@
./valid_hostname: testing: "123456789012345678901234567890123456789012345678901234567890123" ./valid_hostname: testing: "123456789012345678901234567890123456789012345678901234567890123"
./valid_hostname: warning: valid_hostname: numeric hostname: 123456789012345678901234567890123456789012345678901234567890123 ./valid_hostname: warning: valid_hostname: numeric hostname: 123456789012345678901234567890123456789012345678901234567890123
./valid_hostname: warning: valid_hostaddr: invalid octet value: 123456789012345678901234567890123456789012345678901234567890123 ./valid_hostname: warning: valid_hostaddr: invalid octet value: 123456789012345678901234567890123456789012345678901234567890123
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 123456789012345678901234567890123456789012345678901234567890123
./valid_hostname: testing: "1234567890123456789012345678901234567890123456789012345678901234" ./valid_hostname: testing: "1234567890123456789012345678901234567890123456789012345678901234"
./valid_hostname: warning: valid_hostname: hostname label too long: 1234567890123456789012345678901234567890123456789012345678901234 ./valid_hostname: warning: valid_hostname: hostname label too long: 1234567890123456789012345678901234567890123456789012345678901234
./valid_hostname: warning: valid_hostaddr: invalid octet value: 1234567890123456789012345678901234567890123456789012345678901234 ./valid_hostname: warning: valid_hostaddr: invalid octet value: 1234567890123456789012345678901234567890123456789012345678901234
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1234567890123456789012345678901234567890123456789012345678901234
./valid_hostname: testing: "a.123456789012345678901234567890123456789012345678901234567890123.b" ./valid_hostname: testing: "a.123456789012345678901234567890123456789012345678901234567890123.b"
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.123456789012345678901234567890123456789012345678901234567890123.b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.123456789012345678901234567890123456789012345678901234567890123.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.123456789012345678901234567890123456789012345678901234567890123.b
./valid_hostname: testing: "a.1234567890123456789012345678901234567890123456789012345678901234.b" ./valid_hostname: testing: "a.1234567890123456789012345678901234567890123456789012345678901234.b"
./valid_hostname: warning: valid_hostname: hostname label too long: a.1234567890123456789012345678901234567890123456789012345678901234.b ./valid_hostname: warning: valid_hostname: hostname label too long: a.1234567890123456789012345678901234567890123456789012345678901234.b
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.1234567890123456789012345678901234567890123456789012345678901234.b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.1234567890123456789012345678901234567890123456789012345678901234.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.1234567890123456789012345678901234567890123456789012345678901234.b
./valid_hostname: testing: "1.2.3.4" ./valid_hostname: testing: "1.2.3.4"
./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3.4 ./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.4
./valid_hostname: testing: "321.255.255.255" ./valid_hostname: testing: "321.255.255.255"
./valid_hostname: warning: valid_hostname: numeric hostname: 321.255.255.255 ./valid_hostname: warning: valid_hostname: numeric hostname: 321.255.255.255
./valid_hostname: warning: valid_hostaddr: invalid octet value: 321.255.255.255 ./valid_hostname: warning: valid_hostaddr: invalid octet value: 321.255.255.255
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 321.255.255.255
./valid_hostname: testing: "0.0.0.0" ./valid_hostname: testing: "0.0.0.0"
./valid_hostname: warning: valid_hostname: numeric hostname: 0.0.0.0 ./valid_hostname: warning: valid_hostname: numeric hostname: 0.0.0.0
./valid_hostname: warning: valid_hostaddr: bad initial octet value: 0.0.0.0 ./valid_hostname: warning: valid_hostaddr: bad initial octet value: 0.0.0.0
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 0.0.0.0
./valid_hostname: testing: "255.255.255.255" ./valid_hostname: testing: "255.255.255.255"
./valid_hostname: warning: valid_hostname: numeric hostname: 255.255.255.255 ./valid_hostname: warning: valid_hostname: numeric hostname: 255.255.255.255
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 255.255.255.255
./valid_hostname: testing: "0.255.255.255" ./valid_hostname: testing: "0.255.255.255"
./valid_hostname: warning: valid_hostname: numeric hostname: 0.255.255.255 ./valid_hostname: warning: valid_hostname: numeric hostname: 0.255.255.255
./valid_hostname: warning: valid_hostaddr: bad initial octet value: 0.255.255.255 ./valid_hostname: warning: valid_hostaddr: bad initial octet value: 0.255.255.255
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 0.255.255.255
./valid_hostname: testing: "1.2.3.321" ./valid_hostname: testing: "1.2.3.321"
./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3.321 ./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3.321
./valid_hostname: warning: valid_hostaddr: invalid octet value: 1.2.3.321 ./valid_hostname: warning: valid_hostaddr: invalid octet value: 1.2.3.321
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.321
./valid_hostname: testing: "1.2.3" ./valid_hostname: testing: "1.2.3"
./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3 ./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3
./valid_hostname: warning: valid_hostaddr: invalid octet count: 1.2.3 ./valid_hostname: warning: valid_hostaddr: invalid octet count: 1.2.3
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3
./valid_hostname: testing: "1.2.3.4.5" ./valid_hostname: testing: "1.2.3.4.5"
./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3.4.5 ./valid_hostname: warning: valid_hostname: numeric hostname: 1.2.3.4.5
./valid_hostname: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5 ./valid_hostname: warning: valid_hostaddr: invalid octet count: 1.2.3.4.5
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.4.5
./valid_hostname: testing: "1..2.3.4" ./valid_hostname: testing: "1..2.3.4"
./valid_hostname: warning: valid_hostname: misplaced delimiter: 1..2.3.4 ./valid_hostname: warning: valid_hostname: misplaced delimiter: 1..2.3.4
./valid_hostname: warning: valid_hostaddr: misplaced dot: 1..2.3.4 ./valid_hostname: warning: valid_hostaddr: misplaced dot: 1..2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1..2.3.4
./valid_hostname: testing: ".1.2.3.4" ./valid_hostname: testing: ".1.2.3.4"
./valid_hostname: warning: valid_hostname: misplaced delimiter: .1.2.3.4 ./valid_hostname: warning: valid_hostname: misplaced delimiter: .1.2.3.4
./valid_hostname: warning: valid_hostaddr: misplaced dot: .1.2.3.4 ./valid_hostname: warning: valid_hostaddr: misplaced dot: .1.2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: .1.2.3.4
./valid_hostname: testing: "1.2.3.4.5." ./valid_hostname: testing: "1.2.3.4.5."
./valid_hostname: warning: valid_hostname: misplaced delimiter: 1.2.3.4.5. ./valid_hostname: warning: valid_hostname: misplaced delimiter: 1.2.3.4.5.
./valid_hostname: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5. ./valid_hostname: warning: valid_hostaddr: misplaced dot: 1.2.3.4.5.
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.4.5.
./valid_hostname: testing: "1" ./valid_hostname: testing: "1"
./valid_hostname: warning: valid_hostname: numeric hostname: 1 ./valid_hostname: warning: valid_hostname: numeric hostname: 1
./valid_hostname: warning: valid_hostaddr: invalid octet count: 1 ./valid_hostname: warning: valid_hostaddr: invalid octet count: 1
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1
./valid_hostname: testing: "." ./valid_hostname: testing: "."
./valid_hostname: warning: valid_hostname: misplaced delimiter: . ./valid_hostname: warning: valid_hostname: misplaced delimiter: .
./valid_hostname: warning: valid_hostaddr: misplaced dot: . ./valid_hostname: warning: valid_hostaddr: misplaced dot: .
./valid_hostname: warning: valid_hostliteral: '[' expected at start: .
./valid_hostname: testing: "" ./valid_hostname: testing: ""
./valid_hostname: warning: valid_hostname: empty hostname ./valid_hostname: warning: valid_hostname: empty hostname
./valid_hostname: warning: valid_hostaddr: empty address ./valid_hostname: warning: valid_hostaddr: empty address
./valid_hostname: warning: valid_hostliteral: '[' expected at start:
./valid_hostname: testing: "321" ./valid_hostname: testing: "321"
./valid_hostname: warning: valid_hostname: numeric hostname: 321 ./valid_hostname: warning: valid_hostname: numeric hostname: 321
./valid_hostname: warning: valid_hostaddr: invalid octet value: 321 ./valid_hostname: warning: valid_hostaddr: invalid octet value: 321
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 321
./valid_hostname: testing: "f" ./valid_hostname: testing: "f"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f
./valid_hostname: warning: valid_hostliteral: '[' expected at start: f
./valid_hostname: testing: "f.2.3.4" ./valid_hostname: testing: "f.2.3.4"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f.2.3.4 ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f.2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: f.2.3.4
./valid_hostname: testing: "1f.2.3.4" ./valid_hostname: testing: "1f.2.3.4"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1f.2.3.4 ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1f.2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1f.2.3.4
./valid_hostname: testing: "f1.2.3.4" ./valid_hostname: testing: "f1.2.3.4"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f1.2.3.4 ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f1.2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: f1.2.3.4
./valid_hostname: testing: "1.2f.3.4" ./valid_hostname: testing: "1.2f.3.4"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2f.3.4 ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2f.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2f.3.4
./valid_hostname: testing: "1.f2.3.4" ./valid_hostname: testing: "1.f2.3.4"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.f2.3.4 ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.f2.3.4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.f2.3.4
./valid_hostname: testing: "1.2.3.4f" ./valid_hostname: testing: "1.2.3.4f"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.4f ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.4f
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.4f
./valid_hostname: testing: "1.2.3.f4" ./valid_hostname: testing: "1.2.3.f4"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.f4 ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.f4
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.f4
./valid_hostname: testing: "1.2.3.f" ./valid_hostname: testing: "1.2.3.f"
./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.f ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.f
./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1.2.3.f
./valid_hostname: testing: "-.a.b" ./valid_hostname: testing: "-.a.b"
./valid_hostname: warning: valid_hostname: misplaced hyphen: -.a.b ./valid_hostname: warning: valid_hostname: misplaced hyphen: -.a.b
./valid_hostname: warning: valid_hostaddr: invalid character 45(decimal): -.a.b ./valid_hostname: warning: valid_hostaddr: invalid character 45(decimal): -.a.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: -.a.b
./valid_hostname: testing: "a.-.b" ./valid_hostname: testing: "a.-.b"
./valid_hostname: warning: valid_hostname: misplaced hyphen: a.-.b ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.-.b
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.-.b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.-.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.-.b
./valid_hostname: testing: "a.b.-" ./valid_hostname: testing: "a.b.-"
./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.- ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.-
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.- ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.-
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.b.-
./valid_hostname: testing: "-aa.b.b" ./valid_hostname: testing: "-aa.b.b"
./valid_hostname: warning: valid_hostname: misplaced hyphen: -aa.b.b ./valid_hostname: warning: valid_hostname: misplaced hyphen: -aa.b.b
./valid_hostname: warning: valid_hostaddr: invalid character 45(decimal): -aa.b.b ./valid_hostname: warning: valid_hostaddr: invalid character 45(decimal): -aa.b.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: -aa.b.b
./valid_hostname: testing: "aa-.b.b" ./valid_hostname: testing: "aa-.b.b"
./valid_hostname: warning: valid_hostname: misplaced hyphen: aa-.b.b ./valid_hostname: warning: valid_hostname: misplaced hyphen: aa-.b.b
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): aa-.b.b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): aa-.b.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: aa-.b.b
./valid_hostname: testing: "a.-bb.b" ./valid_hostname: testing: "a.-bb.b"
./valid_hostname: warning: valid_hostname: misplaced hyphen: a.-bb.b ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.-bb.b
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.-bb.b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.-bb.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.-bb.b
./valid_hostname: testing: "a.bb-.b" ./valid_hostname: testing: "a.bb-.b"
./valid_hostname: warning: valid_hostname: misplaced hyphen: a.bb-.b ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.bb-.b
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.bb-.b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.bb-.b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.bb-.b
./valid_hostname: testing: "a.b.-bb" ./valid_hostname: testing: "a.b.-bb"
./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.-bb ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.-bb
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.-bb ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.-bb
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.b.-bb
./valid_hostname: testing: "a.b.bb-" ./valid_hostname: testing: "a.b.bb-"
./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.bb- ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.bb-
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.bb- ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.bb-
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a.b.bb-
./valid_hostname: testing: "a-a.b-b" ./valid_hostname: testing: "a-a.b-b"
./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a-a.b-b ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a-a.b-b
./valid_hostname: warning: valid_hostliteral: '[' expected at start: a-a.b-b
./valid_hostname: testing: "[1.2.3.4]"
./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [1.2.3.4]
./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [1.2.3.4]
./valid_hostname: testing: "[321.255.255.255]"
./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [321.255.255.255]
./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [321.255.255.255]
./valid_hostname: warning: valid_hostaddr: invalid octet value: 321.255.255.255
./valid_hostname: testing: "[1.2.3.4"
./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [1.2.3.4
./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [1.2.3.4
./valid_hostname: warning: valid_hostliteral: ']' expected at end: [1.2.3.4
./valid_hostname: testing: "[1.2.3.4]foo"
./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [1.2.3.4]foo
./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [1.2.3.4]foo
./valid_hostname: warning: valid_hostliteral: unexpected text after ']': [1.2.3.4]foo
./valid_hostname: testing: "[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]"
./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
./valid_hostname: warning: valid_hostliteral: too much text: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx