]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.2-20050117
authorWietse Venema <wietse@porcupine.org>
Mon, 17 Jan 2005 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 06:30:23 +0000 (06:30 +0000)
215 files changed:
postfix/.indent.pro
postfix/COMPATIBILITY
postfix/HISTORY
postfix/IPv6-ChangeLog [new file with mode: 0644]
postfix/Makefile.in
postfix/README_FILES/AAAREADME
postfix/README_FILES/FILTER_README
postfix/README_FILES/IPV6_README [new file with mode: 0644]
postfix/README_FILES/SMTPD_POLICY_README
postfix/RELEASE_NOTES
postfix/conf/access
postfix/conf/post-install
postfix/conf/postfix-files
postfix/conf/postfix-script
postfix/html/FILTER_README.html
postfix/html/IPV6_README.html [new file with mode: 0644]
postfix/html/SASL_README.html
postfix/html/SMTPD_POLICY_README.html
postfix/html/access.5.html
postfix/html/cidr_table.5.html
postfix/html/index.html
postfix/html/master.8.html
postfix/html/postconf.5.html
postfix/html/postqueue.1.html
postfix/html/qmqp-sink.1.html
postfix/html/qmqp-source.1.html
postfix/html/qmqpd.8.html
postfix/html/sendmail.1.html
postfix/html/smtp-sink.1.html
postfix/html/smtp-source.1.html
postfix/html/smtp.8.html
postfix/html/smtpd.8.html
postfix/makedefs
postfix/man/man1/postqueue.1
postfix/man/man1/qmqp-sink.1
postfix/man/man1/qmqp-source.1
postfix/man/man1/sendmail.1
postfix/man/man1/smtp-sink.1
postfix/man/man1/smtp-source.1
postfix/man/man5/access.5
postfix/man/man5/cidr_table.5
postfix/man/man5/postconf.5
postfix/man/man8/master.8
postfix/man/man8/qmqpd.8
postfix/man/man8/smtp.8
postfix/man/man8/smtpd.8
postfix/mantools/ccformat
postfix/mantools/makereadme
postfix/mantools/postlink
postfix/mantools/xpostdef
postfix/proto/FILTER_README.html
postfix/proto/IPV6_README.html [new file with mode: 0644]
postfix/proto/Makefile.in
postfix/proto/SMTPD_POLICY_README.html
postfix/proto/SMTPD_PROXY_README.html
postfix/proto/access
postfix/proto/cidr_table
postfix/proto/postconf.proto
postfix/proto/stop
postfix/src/anvil/Makefile.in
postfix/src/bounce/Makefile.in
postfix/src/cleanup/Makefile.in
postfix/src/discard/Makefile.in
postfix/src/dns/Makefile.in
postfix/src/dns/dns.h
postfix/src/dns/dns_lookup.c
postfix/src/dns/dns_rr.c
postfix/src/dns/dns_rr_eq_sa.c [new file with mode: 0644]
postfix/src/dns/dns_rr_eq_sa.in [new file with mode: 0644]
postfix/src/dns/dns_rr_eq_sa.ref [new file with mode: 0644]
postfix/src/dns/dns_rr_to_pa.c [new file with mode: 0644]
postfix/src/dns/dns_rr_to_pa.in [new file with mode: 0644]
postfix/src/dns/dns_rr_to_pa.ref [new file with mode: 0644]
postfix/src/dns/dns_rr_to_sa.c [new file with mode: 0644]
postfix/src/dns/dns_rr_to_sa.in [new file with mode: 0644]
postfix/src/dns/dns_rr_to_sa.ref [new file with mode: 0644]
postfix/src/dns/dns_sa_to_rr.c [new file with mode: 0644]
postfix/src/dns/dns_sa_to_rr.in [new file with mode: 0644]
postfix/src/dns/dns_sa_to_rr.ref [new file with mode: 0644]
postfix/src/dns/test_dns_lookup.c
postfix/src/error/Makefile.in
postfix/src/flush/Makefile.in
postfix/src/fsstone/Makefile.in
postfix/src/global/Makefile.in
postfix/src/global/mail_params.c
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/global/mime_state.c
postfix/src/global/mynetworks.c
postfix/src/global/namadr_list.in [new file with mode: 0644]
postfix/src/global/namadr_list.ref [new file with mode: 0644]
postfix/src/global/own_inet_addr.c
postfix/src/global/own_inet_addr.h
postfix/src/global/resolve_local.c
postfix/src/global/smtp_stream.c
postfix/src/global/valid_mailhost_addr.c [new file with mode: 0644]
postfix/src/global/valid_mailhost_addr.h [new file with mode: 0644]
postfix/src/global/wildcard_inet_addr.c [new file with mode: 0644]
postfix/src/global/wildcard_inet_addr.h [new file with mode: 0644]
postfix/src/global/xtext.c
postfix/src/lmtp/Makefile.in
postfix/src/lmtp/lmtp_addr.c
postfix/src/lmtp/lmtp_connect.c
postfix/src/local/Makefile.in
postfix/src/master/Makefile.in
postfix/src/master/master.c
postfix/src/master/master_ent.c
postfix/src/master/master_listen.c
postfix/src/master/master_vars.c
postfix/src/oqmgr/Makefile.in
postfix/src/pickup/Makefile.in
postfix/src/pipe/Makefile.in
postfix/src/postalias/Makefile.in
postfix/src/postcat/Makefile.in
postfix/src/postconf/Makefile.in
postfix/src/postconf/postconf.c
postfix/src/postdrop/Makefile.in
postfix/src/postfix/Makefile.in
postfix/src/postkick/Makefile.in
postfix/src/postlock/Makefile.in
postfix/src/postlog/Makefile.in
postfix/src/postmap/Makefile.in
postfix/src/postqueue/Makefile.in
postfix/src/postqueue/postqueue.c
postfix/src/postsuper/Makefile.in
postfix/src/proxymap/Makefile.in
postfix/src/qmgr/Makefile.in
postfix/src/qmqpd/Makefile.in
postfix/src/qmqpd/qmqpd.c
postfix/src/qmqpd/qmqpd.h
postfix/src/qmqpd/qmqpd_peer.c
postfix/src/scache/Makefile.in
postfix/src/sendmail/Makefile.in
postfix/src/sendmail/sendmail.c
postfix/src/showq/Makefile.in
postfix/src/smtp/Makefile.in
postfix/src/smtp/smtp.c
postfix/src/smtp/smtp_addr.c
postfix/src/smtp/smtp_connect.c
postfix/src/smtp/smtp_reuse.c
postfix/src/smtp/smtp_session.c
postfix/src/smtp/smtp_unalias.c
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd.h
postfix/src/smtpd/smtpd_backup.in [new file with mode: 0644]
postfix/src/smtpd/smtpd_backup.ref [new file with mode: 0644]
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_check.in
postfix/src/smtpd/smtpd_check.ref
postfix/src/smtpd/smtpd_peer.c
postfix/src/smtpd/smtpd_xforward.c
postfix/src/smtpstone/Makefile.in
postfix/src/smtpstone/qmqp-sink.c
postfix/src/smtpstone/qmqp-source.c
postfix/src/smtpstone/smtp-sink.c
postfix/src/smtpstone/smtp-source.c
postfix/src/spawn/Makefile.in
postfix/src/trivial-rewrite/Makefile.in
postfix/src/trivial-rewrite/resolve.c
postfix/src/util/Makefile.in
postfix/src/util/argv.h
postfix/src/util/cidr_match.c [new file with mode: 0644]
postfix/src/util/cidr_match.h [new file with mode: 0644]
postfix/src/util/dict_alloc.c
postfix/src/util/dict_cidr.c
postfix/src/util/dict_cidr.in
postfix/src/util/dict_cidr.map
postfix/src/util/dict_cidr.ref
postfix/src/util/exec_command.c
postfix/src/util/find_inet.c
postfix/src/util/hex_quote.c
postfix/src/util/host_port.c
postfix/src/util/host_port.h
postfix/src/util/host_port.in
postfix/src/util/host_port.ref
postfix/src/util/inet_addr_host.c
postfix/src/util/inet_addr_list.c
postfix/src/util/inet_addr_list.h
postfix/src/util/inet_addr_local.c
postfix/src/util/inet_addr_local.h
postfix/src/util/inet_connect.c
postfix/src/util/inet_listen.c
postfix/src/util/inet_proto.c [new file with mode: 0644]
postfix/src/util/inet_proto.h [new file with mode: 0644]
postfix/src/util/inet_util.c [deleted file]
postfix/src/util/mac_parse.c
postfix/src/util/make_dirs.c
postfix/src/util/mask_addr.c [new file with mode: 0644]
postfix/src/util/mask_addr.h [moved from postfix/src/util/inet_util.h with 55% similarity]
postfix/src/util/match_list.c
postfix/src/util/match_ops.c
postfix/src/util/msg_syslog.c
postfix/src/util/myaddrinfo.c [new file with mode: 0644]
postfix/src/util/myaddrinfo.h [new file with mode: 0644]
postfix/src/util/myaddrinfo.ref [new file with mode: 0644]
postfix/src/util/myaddrinfo.ref2 [new file with mode: 0644]
postfix/src/util/myaddrinfo4.ref [new file with mode: 0644]
postfix/src/util/myaddrinfo4.ref2 [new file with mode: 0644]
postfix/src/util/name_mask.c
postfix/src/util/sock_addr.c [new file with mode: 0644]
postfix/src/util/sock_addr.h [new file with mode: 0644]
postfix/src/util/stream_send_fd.c
postfix/src/util/sys_compat.c
postfix/src/util/sys_defs.h
postfix/src/util/valid_hostname.c
postfix/src/util/valid_hostname.h
postfix/src/util/valid_hostname.in
postfix/src/util/valid_hostname.ref
postfix/src/util/vstring.c
postfix/src/util/vstring_vstream.c
postfix/src/util/watchdog.c
postfix/src/verify/Makefile.in
postfix/src/verify/verify.c
postfix/src/virtual/Makefile.in

index 8536d0b576866e990f6789721e9e4327d3b3d330..a6844755a88d39048583f86a4193bd7015eb4647 100644 (file)
@@ -1,4 +1,5 @@
 -TABOUNCE
+-TADDR_PATTERN
 -TALIAS_TOKEN
 -TANVIL_CLNT
 -TANVIL_LOCAL
@@ -16,6 +17,7 @@
 -TBOUNCE_LOG
 -TBOUNCE_STAT
 -TCFG_PARSER
+-TCIDR_MATCH
 -TCLEANUP_STATE
 -TCLIENT_LIST
 -TCLNT_STREAM
@@ -81,6 +83,7 @@
 -THTABLE
 -THTABLE_INFO
 -TINET_ADDR_LIST
+-TINET_PROTO_INFO
 -TINTV
 -TINT_TABLE
 -TJMP_BUF_WRAPPER
 -TMAIL_PRINT
 -TMAIL_SCAN
 -TMAIL_STREAM
+-TMAI_HOSTADDR_STR
+-TMAI_HOSTNAME_STR
+-TMAI_SERVNAME_STR
+-TMAI_SERVPORT_STR
 -TMAPS
 -TMASTER_PROC
 -TMASTER_SERV
index 9bda1ac9b0d4d5ba18f102459951fa16ba488a2e..4ee0668defdcd9fb99a40e1babcf4abb8c642175 100644 (file)
@@ -3,7 +3,6 @@
 /usr/spool/mail        yes (compile time option)
 /var/mail      yes (compile time option)
 /var/spool/mail        yes (compile time option)
-8bit->7bit MIME        yes
 :include:      yes (mail to /file and |command is off by default)
 address probing        yes (optional persistent database)
 aliases                yes (can enable/disable mail to /file or |command)
@@ -23,7 +22,7 @@ genericstable no  (to be done)
 greylist       yes (delegated policy script)
 home mailbox   yes
 ident lookup   no
-ipv6           no  (to be done, patches exist)
+ipv6           yes (compatibility for ipv4-only kernels/libraries)
 ldap tables    yes (contributed)
 lmtp support   yes (client)
 luser relay    yes
@@ -35,12 +34,11 @@ mailertable yes (it's called transport)
 mailq          yes
 majordomo      yes (edit approve script to delete /^delivered-to:/i)
 mime           yes (including 8bit to quoted-printable conversion)
-mime conversion        not yet; postfix uses just-send-eight
 mysql tables   yes (contributed)
 netinfo tables yes (contributed)
 newaliases     yes (main alias database only)
 nis tables     yes
-nis+ tables    yes
+nis+ tables    yes (contributed)
 no <> in smtp  yes (most common address forms)
 pgsql tables   yes (contributed)
 pipeline option        yes (server and client)
@@ -62,7 +60,7 @@ session caching       yes (SMTP shared multi-session; LMTP non-shared single-session)
 size option    yes, server and client
 smarthost      yes (specify relayhost in main.cf)
 spf            yes (delegated policy script)
-starttls        yes (third party patch)
+starttls        yes
 tcp wrapper    no (use built-in blacklist facility)
 user+extension yes (also: .forward+extension)
 user-extension yes (also: .forward-extension)
index eef5f5c67ebca570187bbaea2233d6656903dc40..4fa3e13fdb2a4559b19a27f69d32ba8ab142d3a3 100644 (file)
@@ -9993,6 +9993,32 @@ Apologies for any names omitted.
 
        Bugfix: further postcat corner cases.
 
+20041221-9
+
+       Infrastructure: unified IPv4/IPv6 name/address API so that
+       Postfix can support IPv6 without #ifdef INET6 everywhere.
+       In particular, we allow #ifdef in libraries but avoid it
+       in applications.  Files:  util/myaddrinfo.[hc],
+       util/sock_addr.[hc], dns/dns_rr_to_pa.c, dns/dns_sa_to_rr.c,
+       dns/dns_rr_eq_sa.c, dns/dns_rr_to_sa.c, inet_proto.[hc].
+
+       Postfix no longer attempts to deliver mail via IPv6 when
+       the system has no IPv6 connectivity.  Network protocol
+       support is now selected with the "inet_protocols" configuration
+       parameter, instead of "inet_interfaces". The "inet_protocols"
+       parameter also controls what DNS lookups Postfix will do.
+
+       Infrastructure: eliminated two host/port parsing routines.
+       Only one survives: host_port(), in an extended form that
+       allows for missing host or missing service information but
+       not both. File: util/host_port.c.
+
+20041229
+
+       Milestone: Postfix with the unified IPv4/IPv6 socket/name
+       API builds without compiler error on IPv4-only system and
+       actually works.
+
 20041228
 
        Bugfix: SMTPD_PROXY_README incorrectly claimed that ":port"
@@ -10000,8 +10026,145 @@ Apologies for any names omitted.
        without exposing the service to the network.  Instead,
        ":port" causes a client to connect to "localhost".
 
+20041231
+
+       Linux workaround:  when mynetworks isn't set, a chrooted
+       process could not read the IPv6 address information from
+       /proc.  We now invoke own_inet_addr() before chrooting,
+       while processing main.cf. File: global/mail_params.c.
+
+20050101
+
+       Workaround for (Linux) systems without IPV6_V6ONLY support
+       (RFC 3493).  When Postfix listened on an IPv4 wild-card
+       smtp socket, the IPv6 wild-card smtp listener would fail
+       with EADDRINUSE (and vice versa).  File: util/myaddrinfo.c.
+
+20050103
+
+       Safety: when the IPV6 netmask can't be determined, assume
+       /128 (host only). File: util/inet_addr_local.c.
+
+20050104
+
+       Re-implemented IPv6 support for net/mask pattern matching.
+       Files:  util/cidr_match.[hc], util/dict_cidr.c,
+       util/match_ops.[hc], proto/cidr_table.
+
+20050105
+
+       Moved mask_addr() to its own module so that it could also
+       be called by mynetworks() and inet_addr_local() to remove
+       non-zero host bits from IPv6 network/mask patterns. File:
+       util/mask_addr.c.
+
+20050108
+
+       Re-implemented IPv6 support for network interface lookup
+       via the Linux /proc file system. File:  util/inet_addr_local.c.
+
+20050111
+
+       Feature: specify "inet_interfaces = loopback-only" for
+       servers that must listen on local interfaces only, without
+       having to specify IPv4 and/or IPv6 addresses in main.cf or
+       master.cf.  File:  global/own_inet_addr.c.
+
+       Workaround: AIX 5.1 getaddrinfo() can't handle a null host
+       argument with AI_PASSIVE. Instead we specify an explicit
+       protocol family, a host of "::" or "0.0.0.0", and turn off
+       IPV6_V6ONLY. Files: util_myaddrinfo.c, util/inet_listen.c.
+
+       Workaround: AIX 5.1 getaddrinfo() can't handle a "0" service
+       argument. Instead we specify "1".  Files: util/inet_addr_host.c.
+
+20040513
+
+       Cleanup: now that the over-all structure is proving itself,
+       clean up some internal APIs to increase robustness and get
+       rid of some clumsiness. Mainly, the getaddrinfo(3) interface.
+
+       Start-up performance: the hash_queue_names default setting
+       is reduced from eight directories to just defer and deferred.
+       This reduces time for checking the Postfix queue. Files:
+       conf/post-install, global/mail_params.h.
+
+20040514
+
+       Further cleanup: eliminate duplicate IPv6 results when the
+       mynetworks value is generated by Postfix. More documentation
+       of the new internal APIs.
+
+       Performance: reduced start-up delay by moving warning-only
+       startup checks into the background; they now start after
+       one minute to allow the system to finish booting. File:
+       conf/postfix-script.
+
+20050115
+
+       Further hardening of the IPv6 support: don't trust system
+       libraries to protect Postfix against malformed IPv6 address
+       literals. Their syntax is complex enough that errors are
+       likely. Files: global/resolve_local.c, util/valid_hostname.c.
+
+       Further cleanup: RFC 2821 requires the IPv6: prefix with
+       IPv6 address strings.  The smtp and qmqp servers maintain
+       separate address instances, the bare address and the RFC
+       2821 compatible form, and use each where appropriate.  This
+       strict separation simplifies address syntax checks as well
+       as the implementation of XCLIENT and XFORWARD.
+
+20050116
+
+       Infrastructure: new valid_mailhost_addr() routine to verify
+       that an address literal satisfies RFC 2821. An IPv4 address
+       is in dotted-quad decimal form, and an IPv6 address is in
+       hexadecimal form, with the "IPv6:" prefix. Files:
+       global/valid_mailhost_addr.[hc].
+
+       Further cleanup: valid_hostname() no longer allows network
+       addresses or numerical domain names. While it made some
+       sense with IPv4 dotted quad decimal forms, with IPv6 it
+       just made no sense anymore.  Again, being stricter actually
+       simplifies code. Files:  util/valid_hostname.c and a
+       surprisingly small number of valid_hostname() callers that
+       did not reject numerical forms.
+
+       Bugfix: in the Postfix 2.2 SMTP client, the debug_peer_init()
+       call was moved to the after-chroot initialization.
+
+20050117
+
+       Milestone: first non-non-production snapshot with IPv6.
+
 Open problems:
 
+       Med: transform IPv4-in-IPv6 address literals to IPv4 form
+       when comparing against local IP addresses?
+
+       Med: transform IPv4-in-IPv6 address literals to IPv4 form
+       when eliminating MX mailer loops?
+
+       Med: Postfix requires [] around IPv6 address information
+       in match lists such as mynetworks, debug_peer_list etc.,
+       but the [] must not be specified in access(5) maps. Other
+       places don't care.  For now, this gotcha is documented in
+       IPV6_README and in postconf(5) with each feature that may
+       use IPv6 address information. The general recommendation
+       is not to use [] unless absolutely necessary.
+
+       Med: the partial address matching of IPv6 addresses in
+       access(5) maps is a bit lame: it repeatedly truncates the
+       last ":octetpair" from the printable address representation
+       until a match is found or until truncation is no longer
+       possible.  Since one or more ":" are usually omitted from
+       the printable IPv6 address representation, this does not
+       really try all the possibilities that one might expect to
+       be tried. For now, this gotcha is documented in access(5).
+
+       Low: cap bounce queue life time with regular queue life
+       time.
+
        Med: implement ${name[?:]value} in main.cf or update the
        postconf(5) manual.
 
diff --git a/postfix/IPv6-ChangeLog b/postfix/IPv6-ChangeLog
new file mode 100644 (file)
index 0000000..ed55e64
--- /dev/null
@@ -0,0 +1,483 @@
+ChangeLog for Dean Strik's IPv6 patch for Postfix. The patch is based on
+PLD's patch, which in turn seems to be based on KAME's. For more information:
+
+       http://www.ipnet6.org/postfix/
+
+---------------------------------------------------------------------
+
+Version 1.25   Postfix release 2.1.3
+               Postfix release 2.0.20
+               Postfix snapshot 2.2-20040616
+
+       Bugfix: Misplaced myfree() caused a small memory leak. Reported
+       by Christian von Roques.
+       File: util/match_ops.c
+
+       Removed the colon (:) from the characters XFORWARD replaces by
+       a question mark (IPv6 addresses looked like 2001?610?1108?5010??1
+       in logging). Reported by Philipp Morger.
+       File: smtpd/smtpd.c
+
+Version 1.24   Postfix release 2.1.1
+               Postfix release 2.0.20
+               Postfix snapshot 2.0.19-20040312
+               Postfix snapshot 2.2-20040504
+
+       Bugfix: Prefixlen non-null host portion validation (in CIDR maps
+       for example) yielded incorrect results sometimes because signed
+       arithmetic was used instead of unsigned.
+       File: util/match_ops.c
+
+       Patch correction: The TLS+IPv6 patch for Postfix 2.1.0 missed
+       the master.cf update (used for new installations). Added it
+       back.
+
+Version 1.23   Postfix release 2.1.0
+               Postfix release 2.0.20
+               Postfix snapshot 2.0.19-20040312
+
+       Patch fixes: Several code fixes to make the patch compile
+       and work correctly when compiled without IPv6 support.
+
+       Bugfix (Solaris only?): address family length was not updated
+       which could cause client hostname validation errors.
+       File: smtpd/smtpd_peer.c
+
+       Portability: added support for Darwin 7.3+. This may need
+       some further testing.
+
+       Cleanup: Restructure and redocument interface address
+       retrieval functions. (This reduced the number of preprocessor
+       statements from 99 to 93 ;)
+       File: util/inet_addr_local.c
+
+       Cleanup: make several explicit casts to have compilers shut
+       their pie holes about uninteresting things.
+
+Version 1.22   Postfix release 2.0.19
+               Postfix snapshot 2.0.19-20040312
+
+       Feature: Support "inet_interfaces = IPv4:all" and
+       "inet_interfaces = IPv6:all", to restrict postfix to use
+       either IPv4-only or IPv6-only. A more complete implementation
+       will be part of a future patch. (Slightly modified) patch by
+       Michal Ludvig, SuSE.
+       Files: util/interfaces_to_af.[ch], util/inet_addr_local.c,
+       global/own_inet_addr.c, global/wildcard_inet_addr.[ch],
+       master/master_ent.ch
+
+       Bugfix: In Postfix snapshots, a #define was misplaced with
+       the effect that IPv6 subnets were not included in auto-
+       generated $mynetworks (i.e., mynetworks not defined in main.cf,
+       when also mynetworks_style=subnet) on Linux 2.x systems.
+       File: utils/sys_defs.h
+
+Version 1.21a  Postfix snapshots 2.0.18-2004{0122,0205,0209}
+                                 2.0.19-20040312
+
+       TLS/snapshot version: Update TLS patch to 0.8.18-20040122.
+       Performed as a total repatch. 0.8.18 is cleaner with tls_*
+       variables if TLS is not actually compiled in.
+
+Version 1.21   Postfix releases 2.0.18 - 2.0.19
+               Postfix snapshot 2.0.16-20031231
+
+       Bugfix: The SMTP client could fail to setup a connection,
+       erroring with a bogus "getaddrinfo(...): hostname nor servname
+       provided" warning, because the wrong address was selected.
+       File: smtp/smtp_connect.c
+
+       Safety: in dynamically growing data structures, update the
+       length info after (instead of before) updating the data size.
+       File: util/inet_addr_list.c
+
+Version 1.20   Postfix release 2.0.16
+               Postfix snapshot 2.0.16-20031207
+
+       Bugfix: The SMTP client would abort when binding to specific
+       IPv6 addresses.
+       File: smtp/smtp_connect.c
+
+       Synchronisation/bugfix: LMTP source address binding is identical
+       to the SMTP source binding setup, avoiding the need for
+       lmtp_bind_address(6) if inet_interfaces is set to a single
+       host for an address family.
+       File: lmtp/lmtp_connect.c
+
+Version 1.19   Postfix release 2.0.16
+               Postfix snapshot 2.0.16-20031207
+
+       Bugfix: Synchronisation of TLS patches in snapshots of 1.18[ab]
+       was not complete, causing a crash of smtpd if used with the new
+       proxy agent.
+       File: smtpd/smtpd.c
+
+       Bugfix: SMTP source address binding based on a single hostname
+       in inet_interfaces did not work since the code counted IPv4 and
+       IPv6 addresses instead of only the used address family. Fixed,
+       thereby no longer requiring exact specification of
+       smtp_bind_address(6) in this case.
+       File: smtp/smtp_connect.c
+
+       Bugfix: The QMQP sink server did not compile correctly. This
+       program, part of smtpstone tools, is not compiled or installed
+       by default.
+       File: smtpstone/qmqp-sink.c
+
+       Bugfix: NI_WITHSCOPEID was not correctly defined everywhere,
+       which could result in EAI_BADFLAGS. Changed location of
+       definition to correct it.
+       Files: util/sys_defs.h, util/inet_addr_list.h
+
+Version 1.18b  Postfix snapshot 2.0.16-20030921
+
+       IPv6 support: Added IPv6-enabled code to the new snapshot
+       check_*_{ns,mx}_access restrictions.
+       File: smtpd/smtpd_check.c
+
+Version 1.18a  Postfix release 2.0.16
+
+       Update (TLS patches): Updated Lutz Jaenicke's TLS patch to
+       version 0.8.16. See pfixtls/ChangeLog for details.
+       Diff contributed by Tuomo Soini.
+
+       The TLS+IPv6 patch now contains the original TLS patch
+       documentation from Lutz Jaenicke.
+
+Version 1.18   Postfix releases 2.0.14 - 2.0.15
+               Postfix snapshot 2.0.14-20030812
+
+       Bugfix: Perform actual hostname verification in the SMTP
+       and QMTP servers. This was never supported in the IPv6
+       patch. Reported by Wolfgang S. Rupprecht.
+       Files: smtpd/smtpd_peer.c, qmqpd/qmqpd_peer.c
+
+       IPv6 address ranges using address/prefixlength (e.g. in
+       mynetworks and access maps) should be written as
+       [ipv6:addr:ess]/plen (e.g. [fec0:10:20::]/48). The old
+       supported syntax, [ipv6:addr:ess/plen] is deprecated and
+       support will be removed in a later version.
+       Thanks to Dr. Peter Bieringer and Pekka Savola for discussion.
+       Files: util/match_ops.c, global/mynetworks.c
+
+       Explicitly prefer IPv6 over IPv4 addresses when delivering
+       to a host when MX lookups are disabled when SMTP address
+       randomization is on (default).
+       File: smtp/smtp_addr.c
+
+       Compliance: write IPv6 address literals in mail headers 
+       as [IPv6:addr] instead of [addr] as per RFC 2821:4.1.3
+       tagging requirement, for example [IPv6:fec0:10:20::1].
+       Pointed out by Dr. Peter Bieringer.
+       Files: smtpd/smtpd{,_peer,_state}.c, smtpd/smtpd.h
+
+Version 1.17   Postfix release 2.0.13, 2.0.14
+               Postfix snapshot 2.0.13-20030706, 2.0.14-20030812
+
+       Bugfix: Two memory allocation/deallocation bugs were
+       introduced in patch 1.16. The impact of these bugs could
+       be 'arbitrary' memory corruption.
+       File: util/match_ops.c
+
+Version 1.16   Postfix release 2.0.13
+               Postfix snapshot 2.0.13-20030706
+
+       Cleanup: rewrote match_ops.c. This rewrite is partly based on
+       patch by Takahiro Igarashi. The rewrite enables some better
+       handling of scoped addresses, and drops all GPL code from the
+       patch, easying license considerations. Also, allowed for
+       use of this code by the CIDR maps.
+       Files: util/match_ops.[ch]
+
+       Bugfix: correctly relay for scoped unicast addresses when
+       applicable. Until now, while Postfix was able to recognize
+       scoped addresses, it was not able to see e.g. fe80::10%fxp0
+       as local in mynetworks validation.  KAME-only code.
+       (I've never heard of people using scoped addresses (think
+       link-local addresses) for mail relaying though...)
+       Files: util/inet_addr_list.[ch]
+
+       Feature (snapshot only): rewrote CIDR maps code to support
+       IPv6 addresses, using new match_ops code. Allow the use
+       of [::/0] since it allows one to easily disable further
+       checks for IPv6 addresses.
+       File: util/dict_cidr.c
+
+       Consistency: require IPv6 addresses in inet_interfaces to
+       be enclosed in square brackets.
+       File: util/inet_addr_host.c
+
+       Bugfix: (Linux2-only) A #define was misspelled. This could
+       lead to Postfix being unable to read the system's local IPv6
+       addresses (e.g. when using inet_interfaces).
+       Spotted by Jochen Friedrich.
+       File: util/sys_defs.h
+
+       Cleanup: require non-null host portion in CIDR /
+       prefixlength notations for IPv6 (was IPv4-only).
+
+Version 1.15a  Postfix release 2.0.13
+
+       Update (TLS patches): Updated Lutz Jaenicke's TLS patch
+       to version 0.8.15. This version introduces new options
+       for managing SASL mechanisms. More information at:
+       http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/
+       Diff contributed by Tuomo Soini.
+
+Version 1.15   Postfix release 2.0.12, 2.0.13
+               Postfix snapshot 2.0.12-20030621
+
+       Bugfix (TLS-snapshots only): a change in Postfix snapshot
+       2.0.11-20030609 broke initialisation of TLS in smtpd,
+       causing TLS to both be unadvertised and unaccepted.
+       This was fixed again by reordering initialisation.
+       File: smtpd/smtpd.c
+
+       Update (TLS patches): Updated Lutz Jaenicke's TLS patch
+       to version 0.8.14. This version introduces a few fixes and
+       uses USE_SSL instead of HAS_SSL. More information at:
+       http://www.aet.tu-cottbus.de/personen/jaenicke/pfixtls/
+       Diff contributed by Tuomo Soini.
+
+       Bugfix (Postfix releases only - this was already added to
+       the snapshots in patch 1.14). KAME derived systems only.
+       Correctly decode scoped addresses, including network
+       interface specifiers.
+       File: util/inet_addr_local.c
+
+Version 1.14   Postfix releases 2.0.9, 2.0.10, 2.0.11, 2.0.12
+               Postfix snapshots 2.0.9-20030424, 2.0.10-20030521,
+                                 2.0.11-20030609, 2.0.12-20030611
+
+       Patch change: made the patch available as an IPv6-only
+       patch (i.e., without the TLS code). This on popular
+       request by users and packagers.
+       A TLS+IPv6 version is still available of course.
+
+       Bugfix: correctly decode scoped addresses from now on
+       (KAME derived systems only). I think the original code
+       was written by Itojun, so I'm rather puzzled that it
+       didn't work...
+       File: util/inet_addr_local.c
+
+       Bugfix/portability: Recent KAME snapshots return both
+       TCP and SCTP address information on getaddrinfo() if
+       no protocol was specified. This causes the socket counts
+       to be wrong, confusing child processes.
+       Merged patch by JINMEI Tatuya of KAME to fix this.
+       Files: master/master.h, master/master_{ent,conf}.[ch],
+               util/inet_listen.c
+
+       Documentation: added an IPV6_README file to the patch.
+       This file contains the primary documentation. Also,
+       added a sample-ipv6.cf to describe the (currently few)
+       IPv6 related main.cf parameters.
+
+       Bugfix: the netmask structures for the *unsupported*
+       platforms (boldly assume /64) were added to the wrong
+       list (addresses instead of masks). This bug did not affect
+       any supported platform though.
+       File: util/inet_addr_local.c
+
+       Portability: added support for HP/Compaq Tru64Unix V5.1
+       and later. (compiled with CompaqCC only).
+       Thanks to Sten Spans for providing root access to an
+       IPv6-connected Tru64 testing machine.
+
+Version 1.13   Postfix releases 2.0.4 - 2.0.9
+               Postfix snapshots 2.0.3-20030126 - 2.0.7-20030319
+
+       Bugfix: Due to a missing storage pointer, DNS lookup
+       results in the permit_mx_backups code were not processed,
+       and smtpd would likely crash.
+       Thanks to Wouter de Jong for reporting the crashes.
+       File: smtpd/smtpd_check.c
+
+       Incompatible change: The addresses given to the parameters
+       smtp_bind_address6 and lmtp_bind_address6 now need to be
+       enclosed in square brackets for consistency.
+       Files: [ls]mtp/[ls]mtp_connect.c
+
+Version 1.12   Postfix releases 2.0.2, 2.0.3
+               Postfix snapshots 2.0.2-20030115, 2.0.3-20030126
+
+       Bugfix/workaround (Solaris): A simplified comparison
+       function for Solaris' qsort() function, would result
+       in corruption of network addresses in the SMTP client.
+       Fixed. Reported with possible fix by Edvard Tuinder.
+       File: smtp/smtp_addr.c
+
+Version 1.11   Postfix releases 2.0.0.x, 2.0.1, 2.0.2
+               Postfix snapshots 2.0.0-20030105, 2.0.1-20030112
+                       2.0.2-20030115
+
+       Bugfix (Solaris): Properly initialize lifconf structure
+       when requesting host interface addresses. If you get
+       warnings about SIOCGLIFCONF with earlier versions,
+       please upgrade.
+       File: util/inet_addr_local.c
+
+       Patch fix: fixed compilation errors in case the patch is
+       applied but built without IPv6 support (i.e., on unsupported
+       platforms).
+
+Version 1.10   Postfix snapshots 1.1.12-200212{19,21}
+               Postfix releases 2.0.0, 2.0.0.{1,2}
+               Postfix snapshots 2.0.0-20021223 - 2.0.0-20030101
+
+       'Bugfix': don't show spurious warnings on Linux systems
+       about missing /proc/net/if_inet6 unless verbose mode
+       is enabled.
+       File: util/inet_addr_local.c
+
+       Bugfix: If unable to create a socket for a specific adress
+       in the SMTP client (e.g., when trying to create an IPv6
+       connection while the local host has no configured IPv6
+       addresses), then stop the attempt.
+       File: smtp/smtp_connect.c
+
+       Small bugfix: never query DNS for <localpart@[domain.tld]>.
+       This syntax now correctly generates an error immediately.
+       File: global/resolve_local.c
+
+       Updated TLS patch to 0.8.12-1.1.12-20021219-0.9.6h, fixing
+       a bug with "sendmail -bs".
+
+Version 1.9    Postfix version 1.1.11-20021115
+               Postfix version 1.1.12-2002{1124,1209-1213}
+
+       Bugfix: with getifaddrs() code (*BSD, linux-USAGI), IPv4
+       netmasks were set to /32 effectively. Work around broken
+       netmask data structures (*BSD only perhaps).
+
+       Bugfix: same data corruption in another place created
+       entirely wrong IPv4 netmasks. Work around broken
+       SIOCGIFNETMASK structure.
+
+       New code was added for correct IPv6 netmasks. The original
+       code did not contain IPv6 netmask support at all!
+       For Solaris, use SIOCGLIF*; Linux: /proc/net/if_inet6.
+       Getifaddrs() support is used otherwise. This should cover
+       all supported systems. Other systems also work, prefix
+       length is always set to /64 then.
+
+       Since there are no classes (context: Class A, class B etc
+       networks) with IPv6, default to IPv6 subnet style if the
+       mynetworks style is 'class'. I recommend against this style
+       anyway.
+
+       Added support to display IPv6 nets mynetworks output.
+
+Version 1.8    Postfix version 1.1.11-200211{01,15}
+
+       An earlier author of the patch made a typo in the GAI_STRERROR()
+       macro, resulting in bogus error messages when checking for
+       PTR records. Fixed.
+
+       IPv4-mapped addresses in the smtpd are converted to true IPv4
+       addresses just after the connection has been made. This means
+       that all IPv4-mapped addresses are now logged as true IPv4
+       addresses. Hence beside RBL checks, also access maps now treat
+       IPv4-mapped addresses as native IPv4. Note that ::ffff:...
+       entries in your access tables will no longer work.
+
+       You can now specify IPv6 'parent' networks in your access maps,
+       e.g. to reject all mail from 3ffe:200:... nodes, add the line
+               3ffe:200        REJECT
+       Use of trailing colons is discouraged because postmap will
+       warn about it possibly being an alias...
+       NOTE: I'll soon obsolete this again in favor of the more
+       common address/len notation. This was just so trivial to add
+       that it didn't hurt and I needed it :)
+
+       For easy reference, the version of the TLS/IPv6 patch can be
+       dynamically queried using the  tls_ipv6_version  variable.
+       This gives the short version (like, "1.8").
+
+       The service bind address for 'inet' sockets in master.cf (e.g.,
+       smtpd), must be enclosed in square brackets '[..]' for IPv6
+       addresses. The old style (without brackets) still works but is
+       unsupported and may be removed in the future. Example
+           [::1]:smtp inet n - n - - smtpd
+
+Version 1.7    Postfix version 1.1.11-20021029 - 1.1.11-20021101
+
+       Postfix' SMTP client performs randomization of MX addresses
+       when sending mail. This however could result in A records
+       being used before AAAA records. This has been corrected.
+
+       Note that from Postfix version 1.1.11-20021029 on, there is
+       a  proxy_interfaces  parameter. This has of course not been
+       ported to IPv6 addresses...
+
+Version 1.6    Postfix version 1.1.11-20020928
+
+       Added IPv6 support for backup_mx_networks feature; also the
+       behaviour when DNS lookups fail when checking whether the
+       local host is an MX for a domain conforms to the IPv4 case:
+       defer rather than allow.
+
+Version 1.5    Postfix version 1.1.11-20020917
+
+       I introduced two bugs when I rewrote my older LMTP IPv6 patch.
+       These bugs effectively rendered LMTP useless. Now fixed.
+       Bugs spotted by Kaj Niemi.
+
+       Now supports Solaris 8 and 9. Due to lack of testing equipment,
+       this has been only tested in production on Solaris 9, both
+       with gcc and the Sun Workshop Compiler.
+
+Version 1.4    Postfix version 1.1.11-20020822 - 1.1.11-20020917
+
+       OpenBSD (>=200003) and FreeBSD release 4 and up now use
+        getifaddrs(). This makes for cleaner code. The old code
+       seems to be bug-ridden anyway.
+
+       Got rid of some compiler warnings. Should be cleaner on
+       Alpha as well now. Thanks to Sten Spans for providing me
+       access to an Alpha running FreeBSD4.
+
+       Fixed an old bug in smtpd memory alloation if you compiled
+       without IPv6 support (the wrong buffer size was used. This
+       was harmless for IPv6-enabled compiles since the sizes were
+       equal then).
+
+       Added ChangeLog to the patch (as IPv6-ChangeLog) (this
+       was absent in 1.3 contrary to docs).
+
+Version 1.3    Postfix version 1.1.11-20020613 - 1.1.11-20020718
+
+       FYI: In postfix version 1.1.11-20020718, DNS lookups for
+       AAAA can be done natively. The code matches the code in
+       the patch (though the #ifdef changed from INET6 to T_AAAA).
+       This change causes the patch for 1.1.11-20020718 to be a
+       bit smaller.
+
+Version 1.2    Postfix version 1.1.11-20020613
+
+       Added IPv6 support for the LMTP client.
+
+       Added lmtp_bind_address and lmtp_bind_address6 parameters,
+       similar to those for smtp.
+
+       Added IPv6 support for the QMQP server.
+
+Version 1.1    Postfix version 1.1.11-20020602 - 1.1.11-20020613
+
+       Added parameter smtp_bind_address6. By using this parameter,
+       it is possible to bind to an IPv6 address, independently of
+       IPv4 address binding.
+
+       Lutz fixed a bug in his TLS patch regarding SASL. Incorporated.
+
+Version 1.0.x  Postfix version 1.1.8-20020505 - 1.1.11-20020602
+
+       Patch derived from PLD's IPv6 patch for Postfix, revision 1.10
+       which applied to early Postfix snapshots 1.1.x. Updated this
+       patch to apply to 1.1.8-20020505.
+
+       Added compile-time checks for SS_LEN. Some Linux installations,
+       and maybe other systems, do define SA_LEN, but not SS_LEN.
+
+       Several updates of postfix snapshots.
+
index a4b9e964e77ea813108c2b7f9e01d39c10221fb5..e2a77297637c60fd215d21278edb4da636522f90 100644 (file)
@@ -13,14 +13,14 @@ MANDIRS     = proto man html
 default: update
 
 makefiles Makefiles:
+       (echo "# Do not edit -- this file documents how Postfix was built for your machine."; $(SHELL) makedefs) >makedefs.tmp
+       set +e; if cmp makedefs.tmp conf/makedefs.out; then rm makedefs.tmp; \
+       else mv makedefs.tmp conf/makedefs.out; fi >/dev/null 2>/dev/null
        set -e; for i in $(DIRS); do \
         (set -e; echo "[$$i]"; cd $$i; rm -f Makefile; \
         $(MAKE) -f Makefile.in Makefile MAKELEVEL=) || exit 1; \
        done;
-       rm -f Makefile; (set -e; $(SHELL) makedefs && cat Makefile.in) >Makefile
-       (echo "# Do not edit -- this file documents how Postfix was built for your machine."; $(SHELL) makedefs) >makedefs.tmp
-       set +e; if cmp makedefs.tmp conf/makedefs.out; then rm makedefs.tmp; \
-       else mv makedefs.tmp conf/makedefs.out; fi >/dev/null 2>/dev/null
+       rm -f Makefile; (tail +2 conf/makedefs.out; cat Makefile.in) >Makefile
 
 update printfck tests:
        set -e; for i in $(DIRS); do \
index 1496a490d5fadeb29180db9f4390182097d9e9df..c2d8e4263a30001d6283546969465dd3595e744c 100644 (file)
@@ -8,6 +8,7 @@ G\bGe\ben\bne\ber\bra\bal\bl c\bco\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
   * ADDRESS_REWRITING_README: Address rewriting
   * VIRTUAL_README: Virtual domain hosting
   * SASL_README: SASL Authentication
+  * IPV6_README: IP Version 6 Support
   * INSTALL: Installation from source code
 
 P\bPr\bro\bob\bbl\ble\bem\bm s\bso\bol\blv\bvi\bin\bng\bg
index 62efdb70f7193ad9168258c98c185597ab847a43..ed4a84dc0e6b96c47cdb92690ae9b1513e4d3788 100644 (file)
@@ -473,7 +473,7 @@ server IP addresses in master.cf:
         #                   (yes)   (yes)   (yes)   (never) (100)
         # =================================================================
         1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
-            -o content_filter=foo:bar
+            -o content_filter=filter-service:filter-destination
             -o receive_override_options=no_address_mappings
 
 After this, you can follow the same procedure as outlined in the "advanced" or
@@ -492,14 +492,14 @@ content filter service.
         # service     type  private unpriv  chroot  wakeup  maxproc command
         #                   (yes)   (yes)   (yes)   (never) (100)
         # =================================================================
-        # SMTP service for domains that are content filtered with foo:bar
+        # SMTP service for domains that are filtered with service1:dest1
         1.2.3.4:smtp  inet  n       -       n       -       -       smtpd
-            -o content_filter=foo:bar
+            -o content_filter=service1:dest1
             -o receive_override_options=no_address_mappings
 
-        # SMTP service for domains that are content filtered with xxx:yyy
+        # SMTP service for domains that are filtered with service2:dest2
         1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
-            -o content_filter=xxx:yyy
+            -o content_filter=service2:dest2
             -o receive_override_options=no_address_mappings
 
 After this, you can follow the same procedure as outlined in the "advanced" or
diff --git a/postfix/README_FILES/IPV6_README b/postfix/README_FILES/IPV6_README
new file mode 100644 (file)
index 0000000..ee03468
--- /dev/null
@@ -0,0 +1,250 @@
+P\bPo\bos\bst\btf\bfi\bix\bx I\bIP\bPv\bv6\b6 S\bSu\bup\bpp\bpo\bor\brt\bt
+
+-------------------------------------------------------------------------------
+
+I\bIn\bnt\btr\bro\bod\bdu\buc\bct\bti\bio\bon\bn
+
+Postfix 2.2 introduces support for the IPv6 (IP version 6) protocol, whose main
+feature of interest is that it uses 128-bit IP addresses instead of the 32-bit
+addresses used by IPv4.
+
+With this, Postfix can use the same SMTP protocol over IPv6 as it already uses
+over the older IPv4 network, and Postfix can do AAAA record lookups in the DNS
+in addition to the older A records. Information about IPv6 can be found at
+http://www.ipv6.org/.
+
+This document provides information on the following topics:
+
+  * Supported platforms
+  * Configuration
+  * Known limitations
+  * Compatibility with Postfix <2.2 IPv6 support
+  * IPv6 Support for unsupported platforms
+  * Credits
+
+S\bSu\bup\bpp\bpo\bor\brt\bte\bed\bd P\bPl\bla\bat\btf\bfo\bor\brm\bms\bs
+
+Postfix version 2.2 supports IPv4 and IPv6 on the following platforms:
+
+  * AIX 5.1+
+  * Darwin 7.3+
+  * FreeBSD 4+
+  * Linux 2.4+
+  * NetBSD 1.5+
+  * OpenBSD 2+
+  * Solaris 8+
+  * Tru64Unix V5.1+
+
+On other platforms Postfix will simply use IPv4 as it has always done.
+
+See below for tips how to port Postfix IPv6 support to other environments.
+
+C\bCo\bon\bnf\bfi\big\bgu\bur\bra\bat\bti\bio\bon\bn
+
+Postfix IPv6 support introduces two new main.cf configuration parameters, and
+introduces an important change in address syntax notation in match lists such
+as mynetworks or debug_peer_list.
+
+Postfix IPv6 address syntax is a little tricky, because there are a few places
+where you must enclose IPv6 address inside [] characters, and a few places
+where you must not. It is a good idea to use [] only in the few places where
+you have to. Check out the postconf(5) manual whenever you do IPv6 related
+configuration work with Postfix.
+
+  * The new inet_protocols parameter specifies what IP protocols Postfix will
+    use. This parameter also controls what DNS lookups Postfix will do.
+
+        /etc/postfix/main.cf:
+            # You must stop/start Postfix after changing this parameter.
+            inet_protocols = ipv4       (DEFAULT: enable IPv4 only)
+            inet_protocols = all        (enable both IPv4 and IPv6)
+            inet_protocols = ipv4, ipv6 (enable both IPv4 and IPv6)
+            inet_protocols = ipv6       (enable IPv6 only)
+
+    By default, Postfix uses IPv4 only, because most systems aren't attached to
+    an IPv6 network.
+
+      o On systems with combined IPv4/IPv6 stacks, attempts to deliver mail via
+        IPv6 would always fail with "network unreachable", and those attempts
+        would only slow down Postfix.
+
+      o Linux kernels don't even load IPv6 protocol support by default. Any
+        attempt to use it would fail immediately.
+
+    Note 1: you must stop and start Postfix after changing the inet_protocols
+    configuration parameter.
+
+    Note 2: if you see error messages like the following, then you're running
+    Linux and need to turn on IPv6 in the kernel: see http://www.ipv6.org/ for
+    hints and tips. Unlike other systems, Linux does not have a combined stack
+    for IPv4 and IPv6, and IPv6 protocol support is not loaded by default.
+
+        postconf: warning: inet_protocols: IPv6 support is disabled: Address
+        family not supported by protocol
+        postconf: warning: inet_protocols: configuring for IPv4 support only
+
+    Note 3: on older Linux and Solaris systems, the setting "inet_protocols =
+    ipv6" will not prevent Postfix from accepting IPv4 connections. Postfix
+    will present the client IP addresses in IPv6 format, though. In all other
+    cases, Postfix always presents IPv4 client IP addresses in the traditional
+    dotted quad IPv4 format.
+
+  * The other new parameter is smtp_bind_address6. This sets the local
+    interface address for outgoing IPv6 SMTP connections, just like the
+    smtp_bind_address parameter does for IPv4:
+
+        /etc/postfix/main.cf:
+            smtp_bind_address6 = 2001:240:5c7:0:250:56ff:fe89:1
+
+  * If you left the value of the mynetworks parameter at its default (i.e. no
+    mynetworks setting in main.cf) Postfix will figure out by itself what its
+    network addresses are. This is what a typical setting looks like:
+
+        % postconf mynetworks
+        mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [fe80::]/10 [2001:
+        240:5c7::]/64
+
+    If you did specify the mynetworks parameter value in main.cf, you need
+    update the mynetworks value to include the IPv6 networks the system is in.
+    Be sure to specify IPv6 address information inside [], like this:
+
+        /etc/postfix/main.cf:
+            mynetworks = ...IPv4 networks... [::1]/128 [2001:240:5c7::]/64 ...
+
+N\bNO\bOT\bTE\bE:\b: w\bwh\bhe\ben\bn c\bco\bon\bnf\bfi\big\bgu\bur\bri\bin\bng\bg P\bPo\bos\bst\btf\bfi\bix\bx m\bma\bat\btc\bch\bh l\bli\bis\bst\bts\bs s\bsu\buc\bch\bh a\bas\bs m\bmy\byn\bne\bet\btw\bwo\bor\brk\bks\bs o\bor\br
+d\bde\beb\bbu\bug\bg_\b_p\bpe\bee\ber\br_\b_l\bli\bis\bst\bt,\b, y\byo\bou\bu m\bmu\bus\bst\bt s\bsp\bpe\bec\bci\bif\bfy\by I\bIP\bPv\bv6\b6 a\bad\bdd\bdr\bre\bes\bss\bs i\bin\bnf\bfo\bor\brm\bma\bat\bti\bio\bon\bn i\bin\bns\bsi\bid\bde\be [\b[]\b] i\bin\bn t\bth\bhe\be
+m\bma\bai\bin\bn.\b.c\bcf\bf p\bpa\bar\bra\bam\bme\bet\bte\ber\br v\bva\bal\blu\bue\be a\ban\bnd\bd i\bin\bn f\bfi\bil\ble\bes\bs s\bsp\bpe\bec\bci\bif\bfi\bie\bed\bd w\bwi\bit\bth\bh a\ba "\b"/\b/f\bfi\bil\ble\be/\b/n\bna\bam\bme\be"\b" p\bpa\bat\btt\bte\ber\brn\bn.\b.
+I\bIP\bPv\bv6\b6 a\bad\bdd\bdr\bre\bes\bss\bse\bes\bs c\bco\bon\bnt\bta\bai\bin\bn t\bth\bhe\be "\b":\b:"\b" c\bch\bha\bar\bra\bac\bct\bte\ber\br,\b, a\ban\bnd\bd w\bwo\bou\bul\bld\bd o\bot\bth\bhe\ber\brw\bwi\bis\bse\be b\bbe\be c\bco\bon\bnf\bfu\bus\bse\bed\bd w\bwi\bit\bth\bh
+a\ba "\b"t\bty\byp\bpe\be:\b:t\bta\bab\bbl\ble\be"\b" p\bpa\bat\btt\bte\ber\brn\bn.\b.
+
+K\bKn\bno\bow\bwn\bn L\bLi\bim\bmi\bit\bta\bat\bti\bio\bon\bns\bs
+
+  * The order of IPv6/IPv4 outgoing connection attempts is not yet
+    configurable. Currently, IPv6 is tried before IPv4.
+
+  * Postfix currently does not support DNSBL (real-time blackhole list) lookups
+    for IPv6 client IP addresses; currently there are no blacklists that cover
+    the IPv6 address space.
+
+  * IPv6 does not have class A, B, C, etc. networks. With IPv6 networks, the
+    setting "mynetworks_style = class" has the same effect as the setting
+    "mynetworks_style = subnet".
+
+  * On Tru64Unix, Postfix can't figure out the local subnet mask and always
+    assumes a /128 network. This is a problem only with "mynetworks_style =
+    subnet" and no explicit mynetworks setting in main.cf.
+
+C\bCo\bom\bmp\bpa\bat\bti\bib\bbi\bil\bli\bit\bty\by w\bwi\bit\bth\bh P\bPo\bos\bst\btf\bfi\bix\bx <\b<2\b2.\b.2\b2 I\bIP\bPv\bv6\b6 s\bsu\bup\bpp\bpo\bor\brt\bt
+
+Postfix version 2.2 IPv6 support is based on the Postfix/IPv6 patch by Dean
+Strik and others, but differs in a few minor ways.
+
+  * main.cf: The inet_interfaces parameter does not support the notation "ipv6:
+    all" or "ipv4:all". Use the inet_protocols parameter instead.
+
+  * main.cf: Specify "inet_protocols = all" or "inet_protocols = ipv4, ipv6" in
+    order to enable both IPv4 and IPv6 support.
+
+  * main.cf: The inet_protocols parameter also controls what DNS lookups
+    Postfix will attempt to make when delivering or receiving mail.
+
+  * main.cf: Specify "inet_interfaces = loopback-only" to listen on loopback
+    network interfaces only.
+
+  * The lmtp_bind_address and lmtp_bind_address6 features were omitted. The
+    Postfix LMTP client will be absorbed into the SMTP client, so there is no
+    reason to keep adding features to the LMTP client.
+
+  * The SMTP server now requires that IPv6 addresses in SMTP commands are
+    specified as [ipv6:ipv6address], as described in RFC 2821.
+
+  * The IPv6 network address matching code was rewritten from the ground up,
+    and is expected to be closer to the specification. The result may be
+    incompatible with the Postfix/IPv6 patch.
+
+I\bIP\bPv\bv6\b6 S\bSu\bup\bpp\bpo\bor\brt\bt f\bfo\bor\br u\bun\bns\bsu\bup\bpp\bpo\bor\brt\bte\bed\bd p\bpl\bla\bat\btf\bfo\bor\brm\bms\bs
+
+Getting Postfix IPv6 working on other platforms involves the following steps:
+
+  * Specify how Postfix should find the local network interfaces. Postfix needs
+    this information to avoid mailer loops and to find out if mail for user@
+    [ipaddress] is a local or remote destination.
+
+    If your system has the getifaddrs() routine then add the following to your
+    platform-specific section in src/util/sys_defs.h:
+
+        #ifndef NO_IPV6
+        # define HAS_IPV6
+        # define HAVE_GETIFADDRS
+        #endif
+
+    Otherwise, if your system has the SIOCGLIF ioctl() command in /usr/include/
+    */*.h, add the following to your platform-specific section in src/util/
+    sys_defs.h:
+
+        #ifndef NO_IPV6
+        # define HAS_IPV6
+        # define HAS_SIOCGLIF
+        #endif
+
+    Otherwise, Postfix will have to use the old SIOCGIF commands and get along
+    with reduced IPv6 functionality (it won't be able to figure out your IPv6
+    netmasks, which are needed for "mynetworks_style = subnet". Add this to
+    your platform-specific section in src/util/sys_defs.h:
+
+        #ifndef NO_IPV6
+        # define HAS_IPV6
+        #endif
+
+  * Test if Postfix can figure out its interface information.
+
+    After compiling Postfix in the usual manner, step into the src/util
+    directory and type "make inet_addr_local". Running this file by hand should
+    produce all the interface addresses and network masks, for example:
+
+        % make
+        % cd src/util
+        % make inet_addr_local
+        [... some messages ...]
+        % ./inet_addr_local
+        [... some messages ...]
+        ./inet_addr_local: inet_addr_local: configured 2 IPv4 addresses
+        ./inet_addr_local: inet_addr_local: configured 4 IPv6 addresses
+        168.100.189.2/255.255.255.224
+        127.0.0.1/255.0.0.0
+        fe80:1::2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
+        2001:240:5c7:0:2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
+        fe80:5::1/ffff:ffff:ffff:ffff::
+        ::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+
+    The above is for an old FreeBSD machine. Other systems produce slightly
+    different results, but you get the idea.
+
+If none of all this produces a usable result, send email to the postfix-
+users@postfix.org mailing list and we'll try to help you through this.
+
+C\bCr\bre\bed\bdi\bit\bts\bs
+
+The following information is in part based on information that was compiled by
+Dean Strik.
+
+  * Mark Huizer wrote the original Postfix IPv6 patch.
+
+  * Jun-ichiro 'itojun' Hagino of the KAME project made substantial
+    improvements. Since then, we speak of the KAME patch.
+
+  * The PLD Linux Distribution ported the code to other stacks (notably USAGI).
+    We speak of the PLD patch. A very important feature of the PLD patch was
+    that it can work with Lutz Jaenicke's TLS patch for Postfix.
+
+  * Dean Strik extended IPv6 support to platforms other than KAME and USAGI,
+    updated the patch to keep up with Postfix development, and provided a
+    combined IPv6 + TLS patch. Information about his effort can be found on
+    Dean Strik's Postfix website at http://www.ipnet6.org/postfix/.
+
+  * Wietse Venema took Dean Strik's IPv6 patch, merged it into Postfix 2.2, and
+    took the opportunity to eliminate all IPv4-specific code from Postfix that
+    could be removed. For systems without IPv6 support in the kernel and system
+    libraries, Postfix has a simple compatibility layer, so that it will use
+    IPv4 as before.
+
index 34ef8ba2c042eaf2f8d3b71209b1c8ed69509e61..2b1b4561f6a384302aeee96a54e006e67790380c 100644 (file)
@@ -69,6 +69,9 @@ Notes:
   * When an attribute value is unavailable, the client either does not send the
     attribute, or sends the attribute with an empty value ("name=").
 
+  * The client address is an IPv4 dotted quad in the form 1.2.3.4 or it is an
+    IPv6 address in the form 1:2:3::4:5:6.
+
   * An attribute name must not contain "=", null or newline, and an attribute
     value must not contain null or newline.
 
index aa1c541498363990e385dd3880d0d2af840d4b8a..bc4123a1fe2d98179becb7da5b09b5527d0254dc 100644 (file)
@@ -7,6 +7,54 @@ snapshot release).  Patches are issued for the official release
 and change the patchlevel and the release date. Patches are never
 issued for snapshot releases.
 
+Incompatible changes with snapshot Postfix-2.2-20050117
+=======================================================
+
+Only the deferred and defer queue directories are hashed by default,
+instead of eight queue directories.  With modern file systems, this
+speeds up Postfix boot time without compromising performance under
+high load too much. Hashing is now turned on only for the defer and
+deferred queue directories, because those contain lots of mail when
+undeliverable mail is backing up.
+
+In order to speed up start-up, some Postfix file permission checks
+are run in the background after Postfix is started.
+
+The SMTP server now requires that IPv6 addresses in SMTP commands
+are specified as [ipv6:ipv6address], as described in RFC 2821.
+
+Incompatible changes with snapshot Postfix-2.2-20050111+IPV6
+============================================================
+
+Postfix version 2.2 IP version 6 support is based on the Postfix/IPv6
+patch by Dean Strik, but differs in a few minor ways.
+
+- Network protocol support including DNS lookup is selected with
+the inet_protocols parameter instead of the inet_interfaces parameter.
+This is needed so that Postfix will not attempt to deliver mail
+via IPv6 when the system has no IPv6 connectivity.
+
+- The lmtp_bind_address6 feature was omitted. The Postfix LMTP
+client will be absorbed into the SMTP client, so there is no reason
+to keep adding features to the LMTP client.
+
+- The cidr-based address matching code was rewritten.  The new
+behavior is believed to be closer to expectation. The results may
+be incompatible with that of the Postfix/IPv6 patch.
+
+Major changes with snapshot Postfix-2.2-20050111+IPV6
+=====================================================
+
+Postfix version 2.2 IP version 6 support based on the Postfix/IPv6
+patch by Dean Strik and others. IP version 6 support is selected
+in main.cf; it is not selected at compile time as with TLS or SASL.
+
+IP version 6 support is always compiled into Postfix on systems
+that have Postfix compatible IP version 6 support. On other systems
+Postfix will simply use IP version 4 just like it did before. See
+the IPV6_README document for what systems are supported, and how
+to turn on IPv6 in main.cf.
+
 Major changes with snapshot Postfix-2.2-20041218
 ================================================
 
index dd10ffd9722e8225c4e09e44ca6c74511bf05cf3..48f5532ef24fbeb28ff6fd7c63aa336368ea78f0 100644 (file)
@@ -14,7 +14,7 @@
 #        The  optional access table directs the Postfix SMTP server
 #        to selectively  reject  or  accept  mail.  Access  can  be
 #        allowed  or  denied for specific host names, domain names,
-#        networks, host network addresses or mail addresses.
+#        networks, host addresses or mail addresses.
 # 
 #        For an example, see the EXAMPLE section at the end of this
 #        manual page.
 # 
 #        net.work
 # 
-#        net    Matches  any host address in the specified network.
-#               A network address is a  sequence  of  one  or  more
-#               octets separated by ".".
+#        net    Matches  the specified IPv4 host address or subnet-
+#               work. An IPv4 host address is a  sequence  of  four
+#               decimal octets separated by ".".
 # 
-#               NOTE:  use  the  cidr  lookup table type to specify
+#               Subnetworks  are  matched  by repeatedly truncating
+#               the last ".octet" from the remote IPv4 host address
+#               string  until a match is found in the access table,
+#               or until further truncation is not possible.
+# 
+#               NOTE 1: The information in the access map should be
+#               in canonical form, with unnecessary null characters
+#               eliminated.   Address  information  must   not   be
+#               enclosed with "[]" characters.
+# 
+#               NOTE  2:  use the cidr lookup table type to specify
 #               network/netmask  patterns.  See  cidr_table(5)  for
 #               details.
 # 
+#        net:work:addr:ess
+# 
+#        net:work:addr
+# 
+#        net:work
+# 
+#        net    Matches  the specified IPv6 host address or subnet-
+#               work. An IPv6 host address is a sequence  of  three
+#               to  eight hexadecimal octet pairs separated by ":".
+# 
+#               Subnetworks are matched  by  repeatedly  truncating
+#               the  last  ":octetpair"  from  the remote IPv6 host
+#               address string until a match is found in the access
+#               table, or until further truncation is not possible.
+# 
+#               NOTE 1: the truncation and comparison are done with
+#               the string representation of the IPv6 host address.
+#               Thus, not all the ":" subnetworks will be tried.
+# 
+#               NOTE 2: The information in the access map should be
+#               in canonical form, with unnecessary null characters
+#               eliminated.   Address  information  must   not   be
+#               enclosed with "[]" characters.
+# 
+#               NOTE  3:  use the cidr lookup table type to specify
+#               network/netmask  patterns.  See  cidr_table(5)  for
+#               details.
+# 
+#               IPv6 support is available in Postfix 2.2 and later.
+# 
 # ACCEPT ACTIONS
 #        OK     Accept the address etc. that matches the pattern.
 # 
 #        all-numerical
 #               An all-numerical result is treated as OK. This for-
-#               mat is generated by address-based relay  authoriza-
+#               mat  is generated by address-based relay authoriza-
 #               tion schemes.
 # 
 # REJECT ACTIONS
 #        4NN text
 # 
 #        5NN text
-#               Reject  the  address etc. that matches the pattern,
+#               Reject the address etc. that matches  the  pattern,
 #               and respond with the numerical three-digit code and
-#               text.  4NN means "try again later", while 5NN means
+#               text. 4NN means "try again later", while 5NN  means
 #               "do not try again".
 # 
 #        REJECT optional text...
-#               Reject the address etc. that matches  the  pattern.
-#               Reply  with  $reject_code optional text... when the
-#               optional text is specified, otherwise reply with  a
+#               Reject  the  address etc. that matches the pattern.
+#               Reply with $reject_code optional text...  when  the
+#               optional  text is specified, otherwise reply with a
 #               generic error response message.
 # 
 #        DEFER_IF_REJECT optional text...
-#               Defer  the  request if some later restriction would
+#               Defer the request if some later  restriction  would
 #               result in a REJECT action. Reply with "450 optional
 #               text... when the optional text is specified, other-
 #               wise reply with a generic error response message.
 #               This feature is available in Postfix 2.1 and later.
 # 
 #        DEFER_IF_PERMIT optional text...
-#               Defer  the  request if some later restriction would
-#               result in a an explicit or implicit PERMIT  action.
-#               Reply  with "450 optional text... when the optional
-#               text is specified, otherwise reply with  a  generic
+#               Defer the request if some later  restriction  would
+#               result  in a an explicit or implicit PERMIT action.
+#               Reply with "450 optional text... when the  optional
+#               text  is  specified, otherwise reply with a generic
 #               error response message.
 # 
 #               This feature is available in Postfix 2.1 and later.
 #               reject_unauth_destination, and so on).
 # 
 #        DISCARD optional text...
-#               Claim  successful delivery and silently discard the
-#               message.  Log the optional text if specified,  oth-
+#               Claim successful delivery and silently discard  the
+#               message.   Log the optional text if specified, oth-
 #               erwise log a generic message.
 # 
-#               Note:  this action currently affects all recipients
+#               Note: this action currently affects all  recipients
 #               of the message.
 # 
 #               This feature is available in Postfix 2.0 and later.
 # 
-#        DUNNO  Pretend  that  the  lookup  key was not found. This
-#               prevents Postfix  from  trying  substrings  of  the
-#               lookup  key (such as a subdomain name, or a network
+#        DUNNO  Pretend that the lookup key  was  not  found.  This
+#               prevents  Postfix  from  trying  substrings  of the
+#               lookup key (such as a subdomain name, or a  network
 #               address subnetwork).
 # 
 #               This feature is available in Postfix 2.0 and later.
 # 
 #        FILTER transport:destination
-#               After  the  message is queued, send the entire mes-
+#               After the message is queued, send the  entire  mes-
 #               sage through the specified external content filter.
-#               The  transport:destination  syntax  is described in
-#               the transport(5)  manual  page.   More  information
-#               about  external  content  filters is in the Postfix
+#               The transport:destination syntax  is  described  in
+#               the  transport(5)  manual  page.   More information
+#               about external content filters is  in  the  Postfix
 #               FILTER_README file.
 # 
-#               Note:  this  action  overrides  the  main.cf   con-
+#               Note:   this  action  overrides  the  main.cf  con-
 #               tent_filter  setting,  and  currently  affects  all
 #               recipients of the message.
 # 
 #               This feature is available in Postfix 2.0 and later.
 # 
 #        HOLD optional text...
-#               Place  the message on the hold queue, where it will
-#               sit until someone either deletes it or releases  it
-#               for  delivery.  Log the optional text if specified,
+#               Place the message on the hold queue, where it  will
+#               sit  until someone either deletes it or releases it
+#               for delivery.  Log the optional text if  specified,
 #               otherwise log a generic message.
 # 
-#               Mail that is placed on hold can  be  examined  with
-#               the  postcat(1)  command,  and  can be destroyed or
+#               Mail  that  is  placed on hold can be examined with
+#               the postcat(1) command, and  can  be  destroyed  or
 #               released with the postsuper(1) command.
 # 
-#               Note: use "postsuper -r" to release mail  that  was
-#               kept  on  hold for a significant fraction of $maxi-
+#               Note:  use  "postsuper -r" to release mail that was
+#               kept on hold for a significant fraction  of  $maxi-
 #               mal_queue_lifetime  or  $bounce_queue_lifetime,  or
 #               longer.
 # 
-#               Note:  this action currently affects all recipients
+#               Note: this action currently affects all  recipients
 #               of the message.
 # 
 #               This feature is available in Postfix 2.0 and later.
 # 
 #        PREPEND headername: headervalue
-#               Prepend  the  specified  message header to the mes-
+#               Prepend the specified message header  to  the  mes-
 #               sage.  When this action is used multiple times, the
-#               first  prepended  header  appears before the second
+#               first prepended header appears  before  the  second
 #               etc. prepended header.
 # 
-#               Note: this action does not support multi-line  mes-
+#               Note:  this action does not support multi-line mes-
 #               sage headers.
 # 
 #               This feature is available in Postfix 2.1 and later.
 # 
 #        REDIRECT user@domain
-#               After the message is queued, send  the  message  to
+#               After  the  message  is queued, send the message to
 #               the  specified  address  instead  of  the  intended
 #               recipient(s).
 # 
-#               Note: this action overrides the FILTER action,  and
+#               Note:  this action overrides the FILTER action, and
 #               currently affects all recipients of the message.
 # 
 #               This feature is available in Postfix 2.1 and later.
 # 
 #        WARN optional text...
 #               Log a warning with the optional text, together with
-#               client  information  and  if  available, with helo,
+#               client information and  if  available,  with  helo,
 #               sender, recipient and protocol information.
 # 
 #               This feature is available in Postfix 2.1 and later.
 # 
 # REGULAR EXPRESSION TABLES
-#        This  section  describes how the table lookups change when
+#        This section describes how the table lookups  change  when
 #        the table is given in the form of regular expressions. For
-#        a  description  of regular expression lookup table syntax,
+#        a description of regular expression lookup  table  syntax,
 #        see regexp_table(5) or pcre_table(5).
 # 
-#        Each pattern is a regular expression that  is  applied  to
+#        Each  pattern  is  a regular expression that is applied to
 #        the entire string being looked up. Depending on the appli-
-#        cation, that string  is  an  entire  client  hostname,  an
+#        cation,  that  string  is  an  entire  client hostname, an
 #        entire client IP address, or an entire mail address. Thus,
 #        no  parent  domain  or  parent  network  search  is  done,
-#        user@domain  mail  addresses  are not broken up into their
+#        user@domain mail addresses are not broken  up  into  their
 #        user@ and domain constituent parts, nor is user+foo broken
 #        up into user and foo.
 # 
-#        Patterns  are  applied  in  the  order as specified in the
-#        table, until a pattern is found that  matches  the  search
+#        Patterns are applied in the  order  as  specified  in  the
+#        table,  until  a  pattern is found that matches the search
 #        string.
 # 
-#        Actions  are  the  same as with indexed file lookups, with
-#        the additional feature that parenthesized substrings  from
+#        Actions are the same as with indexed  file  lookups,  with
+#        the  additional feature that parenthesized substrings from
 #        the pattern can be interpolated as $1, $2 and so on.
 # 
 # TCP-BASED TABLES
-#        This  section  describes how the table lookups change when
+#        This section describes how the table lookups  change  when
 #        lookups are directed to a TCP-based server. For a descrip-
-#        tion   of  the  TCP  client/server  lookup  protocol,  see
-#        tcp_table(5).  This feature is not  available  in  Postfix
+#        tion  of  the  TCP  client/server  lookup  protocol,   see
+#        tcp_table(5).   This  feature  is not available in Postfix
 #        version 2.1.
 # 
-#        Each  lookup  operation uses the entire query string once.
-#        Depending on the application, that  string  is  an  entire
+#        Each lookup operation uses the entire query  string  once.
+#        Depending  on  the  application,  that string is an entire
 #        client hostname, an entire client IP address, or an entire
-#        mail address.  Thus, no parent domain  or  parent  network
-#        search  is done, user@domain mail addresses are not broken
-#        up into their user@ and domain constituent parts,  nor  is
+#        mail  address.   Thus,  no parent domain or parent network
+#        search is done, user@domain mail addresses are not  broken
+#        up  into  their user@ and domain constituent parts, nor is
 #        user+foo broken up into user and foo.
 # 
 #        Actions are the same as with indexed file lookups.
 # 
 # EXAMPLE
-#        The  following  example  uses an indexed file, so that the
-#        order of table entries does not matter. The  example  per-
-#        mits  access  by the client at address 1.2.3.4 but rejects
-#        all other clients in 1.2.3.0/24. Instead  of  hash  lookup
-#        tables,  some  systems use dbm.  Use the command "postconf
-#        -m" to find out what lookup  tables  Postfix  supports  on
+#        The following example uses an indexed file,  so  that  the
+#        order  of  table entries does not matter. The example per-
+#        mits access by the client at address 1.2.3.4  but  rejects
+#        all  other  clients  in 1.2.3.0/24. Instead of hash lookup
+#        tables, some systems use dbm.  Use the  command  "postconf
+#        -m"  to  find  out  what lookup tables Postfix supports on
 #        your system.
 # 
 #        /etc/postfix/main.cf:
 #        editing the file.
 # 
 # BUGS
-#        The  table format does not understand quoting conventions.
+#        The table format does not understand quoting  conventions.
 # 
 # SEE ALSO
 #        postmap(1), Postfix lookup table manager
 #        transport(5), transport:nexthop syntax
 # 
 # README FILES
-#        Use "postconf readme_directory" or  "postconf  html_direc-
+#        Use  "postconf  readme_directory" or "postconf html_direc-
 #        tory" to locate this information.
 #        SMTPD_ACCESS_README, built-in SMTP server access control
 #        DATABASE_README, Postfix lookup table overview
 # 
 # LICENSE
-#        The  Secure  Mailer  license must be distributed with this
+#        The Secure Mailer license must be  distributed  with  this
 #        software.
 # 
 # AUTHOR(S)
index abb106e8aa84ea11c6f3baf5338cb5c4675105f8..8a2f65aa995c2979c9a925c51eed6c693d7d5327 100644 (file)
@@ -564,22 +564,13 @@ EOF
        }
     done
 
-    # With 20000 active queue files, the active queue directory should
-    # be hashed, and so should the other directories, because they
-    # can contain even more mail.
-    #
-    # Unfortunately, this sucks mailq performance on unloaded systems.
-    #
-    # If you don't want slow mailq, be sure to hash defer and deferred,
-    # because those two directories can contain lots of files.
+    # File systems have improved since Postfix came out, and all we
+    # require now is that defer and deferred are hashed because those
+    # can contain lots of files.
 
     found=`$POSTCONF -c $config_directory -h hash_queue_names`
     missing=
-    (echo "$found" | grep active >/dev/null) || missing="$missing active"
-    (echo "$found" | grep bounce >/dev/null) || missing="$missing bounce"
     (echo "$found" | grep defer >/dev/null)  || missing="$missing defer"
-    (echo "$found" | grep flush >/dev/null)  || missing="$missing flush"
-    (echo "$found" | grep incoming>/dev/null)|| missing="$missing incoming"
     (echo "$found" | grep deferred>/dev/null)|| missing="$missing deferred"
     test -n "$missing" && {
        echo fixing main.cf hash_queue_names for missing $missing
index d477ba4743f8a2d3dceb7f2599b03b3e283aecbb..e7f1e5b8446158dc1a66a1931282fdde2f3f470f 100644 (file)
@@ -186,6 +186,7 @@ $sample_directory/sample-compatibility.cf:f:root:-:644:o
 $sample_directory/sample-debug.cf:f:root:-:644:o
 $sample_directory/sample-filter.cf:f:root:-:644:o:o
 $sample_directory/sample-flush.cf:f:root:-:644:o
+$sample_directory/sample-ipv6.cf:f:root:-:644:o
 $sample_directory/sample-ldap.cf:f:root:-:644:o
 $sample_directory/sample-lmtp.cf:f:root:-:644:o
 $sample_directory/sample-local.cf:f:root:-:644:o
@@ -224,6 +225,7 @@ $readme_directory/ETRN_README:f:root:-:644
 $readme_directory/FILTER_README:f:root:-:644
 $readme_directory/HOSTING_README:f:root:-:644:o
 $readme_directory/INSTALL:f:root:-:644
+$readme_directory/IPV6_README:f:root:-:644
 $readme_directory/LDAP_README:f:root:-:644
 $readme_directory/LINUX_README:f:root:-:644
 $readme_directory/LMTP_README:f:root:-:644
@@ -267,6 +269,7 @@ $html_directory/DEBUG_README.html:f:root:-:644
 $html_directory/ETRN_README.html:f:root:-:644
 $html_directory/FILTER_README.html:f:root:-:644
 $html_directory/INSTALL.html:f:root:-:644
+$html_directory/IPV6_README.html:f:root:-:644
 $html_directory/LDAP_README.html:f:root:-:644
 $html_directory/LINUX_README.html:f:root:-:644
 $html_directory/LMTP_README.html:f:root:-:644
index d3457d6643924001e5957813019f3bfc320ecc29..f18116473cfb5d8dcb7359e392204dfe3de8339c 100644 (file)
@@ -90,10 +90,18 @@ start)
                $FATAL the Postfix mail system is already running
                exit 1
        }
-       $config_directory/postfix-script check || {
-               $FATAL Postfix integrity check failed!
-               exit 1
-       }
+       if [ -f $queue_directory/quick-start ]
+       then
+               rm -f $queue_directory/quick-start
+       else
+               $config_directory/postfix-script check-fatal || {
+                       $FATAL Postfix integrity check failed!
+                       exit 1
+               }
+               # Warning checks proceed in the background.
+               $INFO starting background file permission checks in 60 seconds
+               (sleep 60; $config_directory/postfix-script check-warn) &
+       fi
        $INFO starting the Postfix mail system
        $daemon_directory/master &
        ;;
@@ -108,6 +116,12 @@ drain)
        kill -9 `sed 1q pid/master.pid`
        ;;
 
+quick-stop)
+
+       $config_directory/postfix-script stop
+       touch $queue_directory/quick-start
+       ;;
+
 stop)
 
        $daemon_directory/master -t 2>/dev/null && {
@@ -151,6 +165,37 @@ flush)
 
 check)
 
+       $config_directory/postfix-script check-fatal || exit 1
+       $config_directory/postfix-script check-warn
+       exit 0
+       ;;
+
+check-fatal)
+       # This command is NOT part of the public interface.
+
+       $SHELL $config_directory/post-install create-missing || {
+               $WARN unable to create missing queue directories
+               exit 1
+       }
+
+       # Look for incomplete installations.
+
+       test -f $config_directory/master.cf || {
+               $FATAL no $config_directory/master.cf file found
+               exit 1
+       }
+
+       # See if all queue files are in the right place. This is slow.
+       # We must scan all queues for mis-named queue files before the
+       # mail system can run.
+
+       $command_directory/postsuper || exit 1
+       exit 0
+       ;;
+
+check-warn)
+       # This command is NOT part of the public interface.
+
        for dir in $daemon_directory $config_directory $queue_directory
        do
                ls -lLd $dir | (grep " root " >/dev/null ||
@@ -164,11 +209,6 @@ check)
                \( -perm -020 -o -perm -002 \) -type f \
                -exec $WARN group or other writable: {} \;
 
-       $SHELL $config_directory/post-install create-missing || {
-               $WARN unable to create missing queue directories
-               exit 1
-       }
-
        find `ls -d $queue_directory/* | \
            egrep '/(incoming|active|defer|deferred|bounce|hold|trace|corrupt|public|private|flush)$'` \
            ! \( -type p -o -type s \) ! -user $mail_owner \
@@ -207,19 +247,6 @@ check)
                done
        done
 
-       # Look for incomplete installations.
-
-       test -f $config_directory/master.cf || {
-               $FATAL no $config_directory/master.cf file found
-               exit 1
-       }
-
-       # See if all queue files are in the right place. This is slow.
-       # We must scan all queues for mis-named queue files before the
-       # mail system can run.
-
-       $command_directory/postsuper || exit 1
-
        find corrupt -type f -exec $WARN damaged message: {} \;
 
        # XXX also: look for weird stuff, weird permissions, etc.
index 0978d3384552f3f20796af10c663e7cc80e44a4c..7d61f4a59070694e1490b3df520226749f5f1900 100644 (file)
@@ -802,7 +802,7 @@ content filtering turned on. </p>
     #                   (yes)   (yes)   (yes)   (never) (100)
     # =================================================================
     1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#content_filter">content_filter</a>=foo:bar 
+        -o <a href="postconf.5.html#content_filter">content_filter</a>=filter-service:filter-destination 
         -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 </pre>
 
@@ -828,14 +828,14 @@ address provides a different content filter service. </p>
     # service     type  private unpriv  chroot  wakeup  maxproc command
     #                   (yes)   (yes)   (yes)   (never) (100)
     # =================================================================
-    # SMTP service for domains that are content filtered with foo:bar
+    # SMTP service for domains that are filtered with service1:dest1
     1.2.3.4:smtp  inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#content_filter">content_filter</a>=foo:bar 
+        -o <a href="postconf.5.html#content_filter">content_filter</a>=service1:dest1 
         -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 
-    # SMTP service for domains that are content filtered with xxx:yyy
+    # SMTP service for domains that are filtered with service2:dest2
     1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
-        -o <a href="postconf.5.html#content_filter">content_filter</a>=xxx:yyy 
+        -o <a href="postconf.5.html#content_filter">content_filter</a>=service2:dest2
         -o <a href="postconf.5.html#receive_override_options">receive_override_options</a>=<a href="postconf.5.html#no_address_mappings">no_address_mappings</a>
 </pre>
 </blockquote>
diff --git a/postfix/html/IPV6_README.html b/postfix/html/IPV6_README.html
new file mode 100644 (file)
index 0000000..91b41f3
--- /dev/null
@@ -0,0 +1,370 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix IPv6 Support</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
+IPv6 Support</h1>
+
+<hr>
+
+<h2>Introduction</h2>
+
+<p> Postfix 2.2 introduces support for the IPv6 (IP version 6)
+protocol, whose main feature of interest is that it uses 128-bit
+IP addresses instead of the 32-bit addresses used by IPv4.  </p>
+
+<p> With this, Postfix can use the same SMTP protocol over IPv6 as
+it already uses over the older IPv4 network, and Postfix can do
+AAAA record lookups in the DNS in addition to the older A records.
+Information about IPv6 can be found at <a href="http://www.ipv6.org/">http://www.ipv6.org/</a>. </p>
+
+<p> This document provides information on the following topics:
+</p>
+
+<ul>
+
+<li><a href="#platforms">Supported platforms</a>
+
+<li><a href="#configuration">Configuration</a>
+
+<li><a href="#limitations">Known limitations</a>
+
+<li><a href="#compat">Compatibility with Postfix &lt;2.2 IPv6 support</a>
+
+<li><a href="#porting">IPv6 Support for unsupported platforms</a>
+
+<li><a href="#credits">Credits</a>
+
+</ul>
+
+<h2><a name="platforms">Supported Platforms</a></h2>
+
+<p> Postfix version 2.2 supports IPv4 and IPv6 on the following
+platforms:  </p>
+
+<ul>
+
+<li> AIX 5.1+
+<li> Darwin 7.3+
+<li> FreeBSD 4+
+<li> Linux 2.4+
+<li> NetBSD 1.5+
+<li> OpenBSD 2+
+<li> Solaris 8+
+<li> Tru64Unix V5.1+
+
+</ul>
+
+<p> On other platforms Postfix will simply use IPv4 as it has always
+done. </p>
+
+<p> See <a href="#porting">below</a> for tips how to port Postfix
+IPv6 support to other environments.  </p>
+
+<h2><a name="configuration">Configuration</a></h2>
+
+<p> Postfix IPv6 support introduces two new main.cf configuration
+parameters, and introduces an important change in address syntax
+notation in match lists such as <tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt> or
+<tt><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></tt>. </p>
+
+<p> Postfix IPv6 address syntax is a little tricky, because there
+are a few places where you must enclose IPv6 address inside
+<tt>[]</tt> characters, and a few places where you must not. It is
+a good idea to use <tt>[]</tt> only in the few places where you
+have to. Check out the <a href="postconf.5.html">postconf(5)</a> manual whenever you do IPv6
+related configuration work with Postfix.  </p>
+
+<ul>
+
+<li> <p> The new <tt><a href="postconf.5.html#inet_protocols">inet_protocols</a></tt> parameter specifies what
+IP protocols Postfix will use.  This parameter also controls what
+DNS lookups Postfix will do. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    # You must stop/start Postfix after changing this parameter.
+    <a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4       (DEFAULT: enable IPv4 only)
+    <a href="postconf.5.html#inet_protocols">inet_protocols</a> = all        (enable both IPv4 and IPv6)
+    <a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4, ipv6 (enable both IPv4 and IPv6)
+    <a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv6       (enable IPv6 only)
+</pre>
+</blockquote>
+
+<p> By default, Postfix uses IPv4 only, because most systems aren't
+attached to an IPv6 network. </p>
+
+<ul>
+
+<li> <p> On systems with combined IPv4/IPv6 stacks, attempts to
+deliver mail via IPv6 would always fail with "network unreachable",
+and those attempts would only slow down Postfix. </p>
+
+<li> <p> Linux kernels don't even load IPv6 protocol support by
+default. Any attempt to use it would fail immediately. </p>
+
+</ul>
+
+<p> Note 1: you must stop and start Postfix after changing the
+<tt><a href="postconf.5.html#inet_protocols">inet_protocols</a></tt> configuration parameter. </p>
+
+<p> Note 2: if you see error messages like the following, then
+you're running Linux and need to turn on IPv6 in the kernel: see
+<a href="http://www.ipv6.org/">http://www.ipv6.org/</a> for hints and tips. Unlike other systems,
+Linux does not have a combined stack for IPv4 and IPv6, and IPv6
+protocol support is not loaded by default.  </p>
+
+<blockquote>
+<pre>
+postconf: warning: <a href="postconf.5.html#inet_protocols">inet_protocols</a>: IPv6 support is disabled: Address family not supported by protocol
+postconf: warning: <a href="postconf.5.html#inet_protocols">inet_protocols</a>: configuring for IPv4 support only
+</pre>
+</blockquote>
+
+<p> Note 3: on older Linux and Solaris systems, the setting
+"<tt><a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv6</tt>" will not prevent Postfix from
+accepting IPv4 connections.  Postfix will present the client IP
+addresses in IPv6 format, though. In all other cases, Postfix always
+presents IPv4 client IP addresses in the traditional dotted quad
+IPv4 format.  </p>
+
+<li> <p> The other new parameter is <tt><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a></tt>.
+This sets the local interface address for outgoing IPv6 SMTP
+connections, just like the <tt><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a></tt> parameter
+does for IPv4: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> = 2001:240:5c7:0:250:56ff:fe89:1
+</pre>
+</blockquote>
+
+<li> <p> If you left the value of the <tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt> parameter at its
+default (i.e. no <tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt> setting in main.cf) Postfix will figure
+out by itself what its network addresses are. This is what a typical
+setting looks like: </p>
+
+<blockquote>
+<pre>
+% postconf <a href="postconf.5.html#mynetworks">mynetworks</a>
+<a href="postconf.5.html#mynetworks">mynetworks</a> = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [fe80::]/10 [2001:240:5c7::]/64 
+</pre>
+</blockquote>
+
+<p> If you did specify the <tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt> parameter value in
+main.cf, you need update the <tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt> value to include
+the IPv6 networks the system is in. Be sure to specify IPv6 address
+information inside <tt>[]</tt>, like this: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    <a href="postconf.5.html#mynetworks">mynetworks</a> = ...<i>IPv4 networks</i>... [::1]/128 [2001:240:5c7::]/64 ...
+</pre>
+</blockquote>
+
+</ul>
+
+<p> <b> NOTE: when configuring Postfix match lists such as
+<tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt> or <tt><a href="postconf.5.html#debug_peer_list">debug_peer_list</a></tt>, you must specify
+IPv6 address information inside <tt>[]</tt> in the main.cf parameter
+value and in files specified with a "<i>/file/name</i>" pattern.
+IPv6 addresses contain the ":" character, and would otherwise be
+confused with a "<i>type:table</i>" pattern. </b>  </p>
+
+<h2><a name="limitations">Known Limitations</a></h2>
+
+<ul>
+
+<li> <p> The order of IPv6/IPv4 outgoing connection attempts is
+not yet configurable.  Currently, IPv6 is tried before IPv4. </p>
+
+<li> <p> Postfix currently does not support DNSBL (real-time
+blackhole list) lookups for IPv6 client IP addresses; currently
+there are no blacklists that cover the IPv6 address space. </p>
+
+<li> <p> IPv6 does not have class A, B, C, etc. networks. With IPv6
+networks, the setting "<tt><a href="postconf.5.html#mynetworks_style">mynetworks_style</a> = class</tt>" has the
+same effect as the setting "<tt><a href="postconf.5.html#mynetworks_style">mynetworks_style</a> = subnet</tt>".
+</p>
+
+<li> <p> On Tru64Unix, Postfix can't figure out the local subnet mask
+and always assumes a /128 network. This is a problem only with
+"<tt><a href="postconf.5.html#mynetworks_style">mynetworks_style</a> = subnet</tt>" and no explicit <tt><a href="postconf.5.html#mynetworks">mynetworks</a></tt>
+setting in main.cf. </p>
+
+</ul>
+
+<h2> <a name="compat">Compatibility with Postfix &lt;2.2 IPv6 support</a>
+</h2>
+
+<p> Postfix version 2.2 IPv6 support is based on the Postfix/IPv6 patch
+by Dean Strik and others, but differs in a few minor ways. </p>
+
+<ul>
+
+<li> <p> main.cf: The <tt><a href="postconf.5.html#inet_interfaces">inet_interfaces</a></tt> parameter does not support
+the notation  "<tt>ipv6:all</tt>" or "<tt>ipv4:all</tt>". Use the
+<tt><a href="postconf.5.html#inet_protocols">inet_protocols</a></tt> parameter instead. </p>
+
+<li> <p> main.cf: Specify "<tt><a href="postconf.5.html#inet_protocols">inet_protocols</a> = all</tt>" or
+"<tt><a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4, ipv6</tt>" in order to enable both IPv4
+and IPv6 support. </p>
+
+<li> <p> main.cf: The <tt><a href="postconf.5.html#inet_protocols">inet_protocols</a></tt> parameter also controls
+what DNS lookups Postfix will attempt to make when delivering or
+receiving mail. </p>
+
+<li> <p> main.cf: Specify "<tt><a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = loopback-only</tt>"
+to listen on loopback network interfaces only. </p>
+
+<li> <p> The <tt>lmtp_bind_address</tt> and <tt>lmtp_bind_address6</tt>
+features were omitted. The Postfix LMTP client will be absorbed
+into the SMTP client, so there is no reason to keep adding features
+to the LMTP client. </p>
+
+<li> <p> The SMTP server now requires that IPv6 addresses in SMTP
+commands are specified as <tt>[ipv6:<i>ipv6address</i>]</tt>, as
+described in <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC 2821</a>. </p>
+
+<li> <p> The IPv6 network address matching code was rewritten from
+the ground up, and is expected to be closer to the specification.
+The result may be incompatible with the Postfix/IPv6 patch.
+</p>
+
+</ul>
+
+<h2><a name="porting">IPv6 Support for unsupported platforms</a></h2>
+
+<p> Getting Postfix IPv6 working on other platforms involves the
+following steps: </p>
+
+<ul>
+
+<li> <p> Specify how Postfix should find the local network interfaces.
+Postfix needs this information to avoid mailer loops and to find out
+if mail for <i>user@[ipaddress]</i> is a local or remote destination. </p>
+
+<p> If your system has the <tt>getifaddrs()</tt> routine then add
+the following to your platform-specific section in
+<tt>src/util/sys_defs.h</tt>:  </p>
+
+<blockquote>
+<pre>
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAVE_GETIFADDRS
+#endif
+</pre>
+</blockquote>
+
+<p> Otherwise, if your system has the SIOCGLIF <tt>ioctl()</tt>
+command in <tt>/usr/include/*/*.h</tt>, add the following to your
+platform-specific section in <tt>src/util/sys_defs.h</tt>: </p>
+
+<blockquote>
+<pre>
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAS_SIOCGLIF
+#endif
+</pre> 
+</blockquote>
+
+<p> Otherwise, Postfix will have to use the old SIOCGIF commands
+and get along with reduced IPv6 functionality (it won't be able to
+figure out your IPv6 netmasks, which are needed for "<tt><a href="postconf.5.html#mynetworks_style">mynetworks_style</a>
+= subnet</tt>". Add this to your platform-specific section in
+<tt>src/util/sys_defs.h</tt>: </p>
+
+<blockquote>
+<pre>
+#ifndef NO_IPV6
+# define HAS_IPV6
+#endif
+</pre> 
+</blockquote>
+
+<li> <p> Test if Postfix can figure out its interface information. </p>
+
+<p> After compiling Postfix in the usual manner, step into the
+<tt>src/util</tt> directory and type "<tt>make inet_addr_local</tt>".
+Running this file by hand should produce all the interface addresses
+and network masks, for example: </p>
+
+<blockquote>
+<pre>
+% make
+% cd src/util
+% make inet_addr_local
+[... some messages ...]
+% ./inet_addr_local
+[... some messages ...]
+./inet_addr_local: inet_addr_local: configured 2 IPv4 addresses
+./inet_addr_local: inet_addr_local: configured 4 IPv6 addresses
+168.100.189.2/255.255.255.224
+127.0.0.1/255.0.0.0
+fe80:1::2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
+fe80:5::1/ffff:ffff:ffff:ffff::
+::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+</pre>
+</blockquote>
+
+<p> The above is for an old FreeBSD machine. Other systems produce
+slightly different results, but you get the idea. </p>
+
+</ul>
+
+<p> If none of all this produces a usable result, send email to the
+postfix-users@postfix.org mailing list and we'll try to help you
+through this. </p>
+
+<h2><a name="credits">Credits</a></h2>
+
+<p> The following information is in part based on information that
+was compiled by Dean Strik. </p>
+
+<ul>
+
+<li> <p> Mark Huizer wrote the original Postfix IPv6 patch. </p>
+
+<li> <p> Jun-ichiro 'itojun' Hagino of the KAME project made
+substantial improvements. Since then, we speak of the KAME patch.
+</p>
+
+<li> <p> The PLD Linux Distribution ported the code to other stacks
+(notably USAGI).  We speak of the PLD patch. A very important
+feature of the PLD patch was that it can work with Lutz Jaenicke's
+TLS patch for Postfix.  </p>
+
+<li> <p> Dean Strik extended IPv6 support to platforms other than
+KAME and USAGI, updated the patch to keep up with Postfix development,
+and provided a combined IPv6 + TLS patch.  Information about his
+effort can be found on Dean Strik's Postfix website at
+<a href="http://www.ipnet6.org/postfix/">http://www.ipnet6.org/postfix/</a>. </p>
+
+<li> <p> Wietse Venema took Dean Strik's IPv6 patch, merged it into
+Postfix 2.2, and took the opportunity to eliminate all IPv4-specific
+code from Postfix that could be removed.  For systems without IPv6
+support in the kernel and system libraries, Postfix has a simple
+compatibility layer, so that it will use IPv4 as before.  </p>
+
+</ul>
+
+</body>
+
+</html>
index 355a503a5406f66217a3a036583dec6735e104f6..2370362a098b85d2077ecf647dc16cf301d7a0af 100644 (file)
@@ -34,7 +34,7 @@ the Postfix SMTP client to a remote SMTP server.  </p>
 
 <p> When receiving mail, Postfix logs the client-provided username,
 authentication method, and sender address to the maillog file, and
-optionally grants mail access via the permit_sasl_authenticated
+optionally grants mail access via the <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a>
 UCE restriction. </p>
 
 <p> Postfix does not record the client's SASL authentication
@@ -187,7 +187,7 @@ SMTP server</a></h2>
 <pre>
 /etc/postfix/main.cf:
     <a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a> = 
-        <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a> permit_sasl_authenticated ...
+        <a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a> <a href="postconf.5.html#permit_sasl_authenticated">permit_sasl_authenticated</a> ...
 </pre>
 </blockquote>
 
index 3ee8625278d71090696e8810fbe45654e1e015ee..8400be65954b9491ec93a19ae16e52ec2d1ff84a 100644 (file)
@@ -108,6 +108,10 @@ size=12345
     either does not send the attribute, or sends the attribute with
     an empty value ("name="). </p>
 
+    <li> <p> The client address is an IPv4 dotted quad in the form
+    1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6.
+    </p>
+
     <li> <p> An attribute name must not contain "=", null or newline,
     and an attribute value must not contain null or newline. </p>
 
index 96e15a7f7409aa9055d7ecd982bd01ae747fa3a2..b22042fffda80f1bd930744a2288d2f5101214f4 100644 (file)
@@ -20,7 +20,7 @@ ACCESS(5)                                               ACCESS(5)
        The  optional <b>access</b> table directs the Postfix SMTP server
        to selectively  reject  or  accept  mail.  Access  can  be
        allowed  or  denied for specific host names, domain names,
-       networks, host network addresses or mail addresses.
+       networks, host addresses or mail addresses.
 
        For an example, see the EXAMPLE section at the end of this
        manual page.
@@ -116,39 +116,79 @@ ACCESS(5)                                               ACCESS(5)
 
        <i>net.work</i>
 
-       <i>net</i>    Matches  any host address in the specified network.
-              A network address is a  sequence  of  one  or  more
-              octets separated by ".".
+       <i>net</i>    Matches  the specified IPv4 host address or subnet-
+              work. An IPv4 host address is a  sequence  of  four
+              decimal octets separated by ".".
 
-              NOTE:  use  the  <b>cidr</b>  lookup table type to specify
+              Subnetworks  are  matched  by repeatedly truncating
+              the last ".octet" from the remote IPv4 host address
+              string  until a match is found in the access table,
+              or until further truncation is not possible.
+
+              NOTE 1: The information in the access map should be
+              in canonical form, with unnecessary null characters
+              eliminated.   Address  information  must   not   be
+              enclosed with "[]" characters.
+
+              NOTE  2:  use the <b>cidr</b> lookup table type to specify
               network/netmask  patterns.  See  <a href="cidr_table.5.html">cidr_table(5)</a>  for
               details.
 
+       <i>net:work:addr:ess</i>
+
+       <i>net:work:addr</i>
+
+       <i>net:work</i>
+
+       <i>net</i>    Matches  the specified IPv6 host address or subnet-
+              work. An IPv6 host address is a sequence  of  three
+              to  eight hexadecimal octet pairs separated by ":".
+
+              Subnetworks are matched  by  repeatedly  truncating
+              the  last  ":octetpair"  from  the remote IPv6 host
+              address string until a match is found in the access
+              table, or until further truncation is not possible.
+
+              NOTE 1: the truncation and comparison are done with
+              the string representation of the IPv6 host address.
+              Thus, not all the ":" subnetworks will be tried.
+
+              NOTE 2: The information in the access map should be
+              in canonical form, with unnecessary null characters
+              eliminated.   Address  information  must   not   be
+              enclosed with "[]" characters.
+
+              NOTE  3:  use the <b>cidr</b> lookup table type to specify
+              network/netmask  patterns.  See  <a href="cidr_table.5.html">cidr_table(5)</a>  for
+              details.
+
+              IPv6 support is available in Postfix 2.2 and later.
+
 <b>ACCEPT ACTIONS</b>
        <b>OK</b>     Accept the address etc. that matches the pattern.
 
        <i>all-numerical</i>
               An all-numerical result is treated as OK. This for-
-              mat is generated by address-based relay  authoriza-
+              mat  is generated by address-based relay authoriza-
               tion schemes.
 
 <b>REJECT ACTIONS</b>
        <b>4</b><i>NN text</i>
 
        <b>5</b><i>NN text</i>
-              Reject  the  address etc. that matches the pattern,
+              Reject the address etc. that matches  the  pattern,
               and respond with the numerical three-digit code and
-              text.  <b>4</b><i>NN</i> means "try again later", while <b>5</b><i>NN</i> means
+              text. <b>4</b><i>NN</i> means "try again later", while <b>5</b><i>NN</i>  means
               "do not try again".
 
        <b>REJECT</b> <i>optional text...</i>
-              Reject the address etc. that matches  the  pattern.
-              Reply  with  <i>$reject</i><b>_</b><i>code optional text...</i> when the
-              optional text is specified, otherwise reply with  a
+              Reject  the  address etc. that matches the pattern.
+              Reply with <i>$reject</i><b>_</b><i>code optional text...</i>  when  the
+              optional  text is specified, otherwise reply with a
               generic error response message.
 
        <b>DEFER_IF_REJECT</b> <i>optional text...</i>
-              Defer  the  request if some later restriction would
+              Defer the request if some later  restriction  would
               result in a REJECT action. Reply with "<b>450</b> <i>optional</i>
               <i>text...</i> when the optional text is specified, other-
               wise reply with a generic error response message.
@@ -156,10 +196,10 @@ ACCESS(5)                                               ACCESS(5)
               This feature is available in Postfix 2.1 and later.
 
        <b>DEFER_IF_PERMIT</b> <i>optional text...</i>
-              Defer  the  request if some later restriction would
-              result in a an explicit or implicit PERMIT  action.
-              Reply  with "<b>450</b> <i>optional text...</i> when the optional
-              text is specified, otherwise reply with  a  generic
+              Defer the request if some later  restriction  would
+              result  in a an explicit or implicit PERMIT action.
+              Reply with "<b>450</b> <i>optional text...</i> when the  optional
+              text  is  specified, otherwise reply with a generic
               error response message.
 
               This feature is available in Postfix 2.1 and later.
@@ -170,131 +210,131 @@ ACCESS(5)                                               ACCESS(5)
               <b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a></b>, and so on).
 
        <b>DISCARD</b> <i>optional text...</i>
-              Claim  successful delivery and silently discard the
-              message.  Log the optional text if specified,  oth-
+              Claim successful delivery and silently discard  the
+              message.   Log the optional text if specified, oth-
               erwise log a generic message.
 
-              Note:  this action currently affects all recipients
+              Note: this action currently affects all  recipients
               of the message.
 
               This feature is available in Postfix 2.0 and later.
 
-       <b>DUNNO</b>  Pretend  that  the  lookup  key was not found. This
-              prevents Postfix  from  trying  substrings  of  the
-              lookup  key (such as a subdomain name, or a network
+       <b>DUNNO</b>  Pretend that the lookup key  was  not  found.  This
+              prevents  Postfix  from  trying  substrings  of the
+              lookup key (such as a subdomain name, or a  network
               address subnetwork).
 
               This feature is available in Postfix 2.0 and later.
 
        <b>FILTER</b> <i>transport:destination</i>
-              After  the  message is queued, send the entire mes-
+              After the message is queued, send the  entire  mes-
               sage through the specified external content filter.
-              The  <i>transport:destination</i>  syntax  is described in
-              the <a href="transport.5.html">transport(5)</a>  manual  page.   More  information
-              about  external  content  filters is in the Postfix
+              The <i>transport:destination</i> syntax  is  described  in
+              the  <a href="transport.5.html">transport(5)</a>  manual  page.   More information
+              about external content filters is  in  the  Postfix
               <a href="FILTER_README.html">FILTER_README</a> file.
 
-              Note:  this  action  overrides  the  <b>main.cf   <a href="postconf.5.html#content_filter">con</a>-</b>
+              Note:   this  action  overrides  the  <b>main.cf  <a href="postconf.5.html#content_filter">con</a>-</b>
               <b><a href="postconf.5.html#content_filter">tent_filter</a></b>  setting,  and  currently  affects  all
               recipients of the message.
 
               This feature is available in Postfix 2.0 and later.
 
        <b>HOLD</b> <i>optional text...</i>
-              Place  the message on the <b>hold</b> queue, where it will
-              sit until someone either deletes it or releases  it
-              for  delivery.  Log the optional text if specified,
+              Place the message on the <b>hold</b> queue, where it  will
+              sit  until someone either deletes it or releases it
+              for delivery.  Log the optional text if  specified,
               otherwise log a generic message.
 
-              Mail that is placed on hold can  be  examined  with
-              the  <a href="postcat.1.html"><b>postcat</b>(1)</a>  command,  and  can be destroyed or
+              Mail  that  is  placed on hold can be examined with
+              the <a href="postcat.1.html"><b>postcat</b>(1)</a> command, and  can  be  destroyed  or
               released with the <a href="postsuper.1.html"><b>postsuper</b>(1)</a> command.
 
-              Note: use "<b>postsuper -r</b>" to release mail  that  was
-              kept  on  hold for a significant fraction of <b>$<a href="postconf.5.html#maximal_queue_lifetime">maxi</a>-</b>
+              Note:  use  "<b>postsuper -r</b>" to release mail that was
+              kept on hold for a significant fraction  of  <b>$<a href="postconf.5.html#maximal_queue_lifetime">maxi</a>-</b>
               <b><a href="postconf.5.html#maximal_queue_lifetime">mal_queue_lifetime</a></b>  or  <b>$<a href="postconf.5.html#bounce_queue_lifetime">bounce_queue_lifetime</a></b>,  or
               longer.
 
-              Note:  this action currently affects all recipients
+              Note: this action currently affects all  recipients
               of the message.
 
               This feature is available in Postfix 2.0 and later.
 
        <b>PREPEND</b> <i>headername: headervalue</i>
-              Prepend  the  specified  message header to the mes-
+              Prepend the specified message header  to  the  mes-
               sage.  When this action is used multiple times, the
-              first  prepended  header  appears before the second
+              first prepended header appears  before  the  second
               etc. prepended header.
 
-              Note: this action does not support multi-line  mes-
+              Note:  this action does not support multi-line mes-
               sage headers.
 
               This feature is available in Postfix 2.1 and later.
 
        <b>REDIRECT</b> <i>user@domain</i>
-              After the message is queued, send  the  message  to
+              After  the  message  is queued, send the message to
               the  specified  address  instead  of  the  intended
               recipient(s).
 
-              Note: this action overrides the FILTER action,  and
+              Note:  this action overrides the FILTER action, and
               currently affects all recipients of the message.
 
               This feature is available in Postfix 2.1 and later.
 
        <b>WARN</b> <i>optional text...</i>
               Log a warning with the optional text, together with
-              client  information  and  if  available, with helo,
+              client information and  if  available,  with  helo,
               sender, recipient and protocol information.
 
               This feature is available in Postfix 2.1 and later.
 
 <b>REGULAR EXPRESSION 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
-       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_table</b>(5)</a> or <a href="pcre_table.5.html"><b>pcre_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 string being looked up. Depending on the appli-
-       cation, that string  is  an  entire  client  hostname,  an
+       cation,  that  string  is  an  entire  client hostname, an
        entire client IP address, or an entire mail address. Thus,
        no  parent  domain  or  parent  network  search  is  done,
-       <i>user@domain</i>  mail  addresses  are not broken up into their
+       <i>user@domain</i> mail addresses are not broken  up  into  their
        <i>user@</i> and <i>domain</i> constituent parts, nor is <i>user+foo</i> broken
        up into <i>user</i> and <i>foo</i>.
 
-       Patterns  are  applied  in  the  order as specified in the
-       table, until a pattern is found that  matches  the  search
+       Patterns are applied in the  order  as  specified  in  the
+       table,  until  a  pattern is found that matches the search
        string.
 
-       Actions  are  the  same as with indexed file lookups, with
-       the additional feature that parenthesized substrings  from
+       Actions are the same as with indexed  file  lookups,  with
+       the  additional feature that parenthesized substrings from
        the pattern can be interpolated as <b>$1</b>, <b>$2</b> and so on.
 
 <b>TCP-BASED TABLES</b>
-       This  section  describes how the table lookups change when
+       This section describes how the table lookups  change  when
        lookups are directed to a TCP-based server. For a descrip-
-       tion   of  the  TCP  client/server  lookup  protocol,  see
-       <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.  This feature is not  available  in  Postfix
+       tion  of  the  TCP  client/server  lookup  protocol,   see
+       <a href="tcp_table.5.html"><b>tcp_table</b>(5)</a>.   This  feature  is not available in Postfix
        version 2.1.
 
-       Each  lookup  operation uses the entire query string once.
-       Depending on the application, that  string  is  an  entire
+       Each lookup operation uses the entire query  string  once.
+       Depending  on  the  application,  that string is an entire
        client hostname, an entire client IP address, or an entire
-       mail address.  Thus, no parent domain  or  parent  network
-       search  is done, <i>user@domain</i> mail addresses are not broken
-       up into their <i>user@</i> and <i>domain</i> constituent parts,  nor  is
+       mail  address.   Thus,  no parent domain or parent network
+       search is done, <i>user@domain</i> mail addresses are not  broken
+       up  into  their <i>user@</i> and <i>domain</i> constituent parts, nor is
        <i>user+foo</i> broken up into <i>user</i> and <i>foo</i>.
 
        Actions are the same as with indexed file lookups.
 
 <b>EXAMPLE</b>
-       The  following  example  uses an indexed file, so that the
-       order of table entries does not matter. The  example  per-
-       mits  access  by the client at address 1.2.3.4 but rejects
-       all other clients in 1.2.3.0/24. Instead  of  <b>hash</b>  lookup
-       tables,  some  systems use <b>dbm</b>.  Use the command "<b>postconf</b>
-       <b>-m</b>" to find out what lookup  tables  Postfix  supports  on
+       The following example uses an indexed file,  so  that  the
+       order  of  table entries does not matter. The example per-
+       mits access by the client at address 1.2.3.4  but  rejects
+       all  other  clients  in 1.2.3.0/24. Instead of <b>hash</b> lookup
+       tables, some systems use <b>dbm</b>.  Use the  command  "<b>postconf</b>
+       <b>-m</b>"  to  find  out  what lookup tables Postfix supports on
        your system.
 
        /etc/postfix/main.cf:
@@ -309,7 +349,7 @@ ACCESS(5)                                               ACCESS(5)
        editing the file.
 
 <b>BUGS</b>
-       The  table format does not understand quoting conventions.
+       The table format does not understand quoting  conventions.
 
 <b>SEE ALSO</b>
        <a href="postmap.1.html">postmap(1)</a>, Postfix lookup table manager
@@ -322,7 +362,7 @@ ACCESS(5)                                               ACCESS(5)
        <a href="DATABASE_README.html">DATABASE_README</a>, Postfix lookup table overview
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 96f701bbc31d7f1b58df7fb6d83793b5776c4a14..bfdbe7d44ac3c1186bcc7bf050e9c035deb0632e 100644 (file)
@@ -32,25 +32,31 @@ CIDR_TABLE(5)                                       CIDR_TABLE(5)
        <i>network</i><b>_</b><i>address</i><b>/</b><i>network</i><b>_</b><i>mask     result</i>
               When a search string matches the specified  network
               block,  use the corresponding <i>result</i> value. Specify
-              0.0.0.0/0 to match every address.
+              0.0.0.0/0 to match every IPv4 address, and ::/0  to
+              match every IPv6 address.
+
+              Note:  address  information  may be enclosed inside
+              "[]" but this form is not recommended.
+
+              IPv6 support is available in Postfix 2.2 and later.
 
        <i>network</i><b>_</b><i>address     result</i>
-              When a search string matches the specified  network
+              When  a search string matches the specified network
               address, use the corresponding <i>result</i> value.
 
        blank lines and comments
-              Empty  lines and whitespace-only lines are ignored,
-              as are lines whose first  non-whitespace  character
+              Empty lines and whitespace-only lines are  ignored,
+              as  are  lines whose first non-whitespace character
               is a `#'.
 
        multi-line text
-              A  logical  line starts with non-whitespace text. A
-              line that starts with whitespace continues a  logi-
+              A logical line starts with non-whitespace  text.  A
+              line  that starts with whitespace continues a logi-
               cal line.
 
 <b>SEARCH ORDER</b>
-       Patterns  are  applied  in  the  order as specified in the
-       table, until a pattern is found that  matches  the  search
+       Patterns are applied in the  order  as  specified  in  the
+       table,  until  a  pattern is found that matches the search
        string.
 
 <b>EXAMPLE SMTPD ACCESS MAP</b>
index 61fe3ba8e355f9cdf537a96c447ad4e727c038f1..520e3bed62cbcb3d8311fae3ae7dc8745063110a 100644 (file)
@@ -38,6 +38,8 @@ configuration examples </a>
 
 <li> <a href="SASL_README.html"> SASL Authentication </a>
 
+<li> <a href="IPV6_README.html"> IP Version 6 Support </a>
+
 <li> <a href="INSTALL.html"> Installation from source code </a>
 
 </ul>
index 81ef977092a2be2eaa51a6b5ea27b0bf4b753f95..8b4ad00d08afa377b51a64764a888fa7430c062f 100644 (file)
@@ -94,11 +94,6 @@ MASTER(8)                                               MASTER(8)
        <b>postfix reload</b> command after a configuration change.
 
 <b>RESOURCE AND RATE CONTROLS</b>
-       <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How  much time a Postfix daemon process may take to
-              handle a request  before  it  is  terminated  by  a
-              built-in watchdog timer.
-
        <b><a href="postconf.5.html#default_process_limit">default_process_limit</a> (100)</b>
               The  default  maximal  number of Postfix child pro-
               cesses that provide a given service.
@@ -133,9 +128,13 @@ MASTER(8)                                               MASTER(8)
               The network interface addresses that this mail sys-
               tem receives mail on.
 
+       <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
+              The Internet protocols Postfix will attempt to  use
+              when making or accepting connections.
+
        <b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
-              The list of environment parameters that  a  Postfix
-              process  will import from a non-Postfix parent pro-
+              The  list  of environment parameters that a Postfix
+              process will import from a non-Postfix parent  pro-
               cess.
 
        <b><a href="postconf.5.html#mail_owner">mail_owner</a> (postfix)</b>
@@ -143,22 +142,22 @@ MASTER(8)                                               MASTER(8)
               and most Postfix daemon processes.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The  process ID of a Postfix command or daemon pro-
+              The process ID of a Postfix command or daemon  pro-
               cess.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The process name of a  Postfix  command  or  daemon
+              The  process  name  of  a Postfix command or daemon
               process.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The  location of the Postfix top-level queue direc-
+              The location of the Postfix top-level queue  direc-
               tory.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The mail system name that is prepended to the  pro-
+              The  mail system name that is prepended to the pro-
               cess  name  in  syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
 
@@ -175,7 +174,7 @@ MASTER(8)                                               MASTER(8)
        syslogd(8), system logging
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index e771364c9f9794b6883d454ea06006943ad1f169..1b6ca7b5fc5e18f1e67e24912855a27e3a0e0e34 100644 (file)
@@ -842,6 +842,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace. </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#authorized_verp_clients">authorized_verp_clients</a> value, and in files
+specified with "/file/name".  IP version 6 addresses contain the
+":" character, and would otherwise be confused with a "<a href="DATABASE_README.html">type:table</a>"
+pattern.  </p>
+
 
 </DD>
 
@@ -2323,13 +2329,19 @@ execute the command "<b>postfix reload</b>".
 </DD>
 
 <DT><b><a name="hash_queue_names">hash_queue_names</a>
-(default: see "postconf -d" output)</b></DT><DD>
+(default: deferred, defer)</b></DT><DD>
 
 <p>
 The names of queue directories that are split across multiple
 subdirectory levels.
 </p>
 
+<p> Before Postfix version 2.2, the default list of hashed queues
+was significantly larger. Claims about improvements in file system
+technology suggest that hashing of the <a href="QSHAPE_README.html#incoming_queue">incoming</a> and <a href="QSHAPE_README.html#active_queue">active queues</a>
+is no longer needed. Fewer hashed directories speed up the time
+needed to restart Postfix. </p>
+
 <p>
 After changing the <a href="postconf.5.html#hash_queue_names">hash_queue_names</a> or <a href="postconf.5.html#hash_queue_depth">hash_queue_depth</a> parameter,
 execute the command "<b>postfix reload</b>".
@@ -2518,42 +2530,102 @@ Specify 0 to disable the feature. Valid delays are 0..10.
 <DT><b><a name="inet_interfaces">inet_interfaces</a>
 (default: all)</b></DT><DD>
 
+<p> The network interface addresses that this mail system receives
+mail on.  By default, the software claims all active interfaces on
+the machine; with Postfix 2.2 and later, specify "<b>loopback-only</b>"
+to select only local interfaces.  The parameter also controls
+delivery of mail to user@[ip.address].  </p>
+
 <p>
-The network interface addresses that this mail system receives mail
-on.  By default, the software claims all active interfaces on the
-machine. The parameter also controls delivery of mail to
-user@[ip.address].
+Note: you need to stop and start Postfix when this parameter changes.
 </p>
 
-<p>
-When <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> consists of just one IP address that is not a
-loopback (net 127) address, the Postfix SMTP client will use this address
-as the IP source address for outbound mail. </p>
+<p> When <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies just one IPv4 and/or IPv6 address
+that is not a loopback address, the Postfix SMTP client will use
+this address as the IP source address for outbound mail. </p>
 
 <p>
 On a multi-homed firewall with separate Postfix instances listening on the
 "inside" and "outside" interfaces, this can prevent each instance from
 being able to reach servers on the "other side" of the firewall. Setting
-<a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> to 0.0.0.0 avoids the potential problem. </p>
+<a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> to 0.0.0.0 avoids the potential problem for
+IPv4, and setting <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> to :: solves the problem
+for IPv6. </p>
 
 <p>
-A better solution is to leave <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> at the default value
+A better solution for multi-homed firewalls is to leave <a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
+at the default value
 and instead use explicit IP addresses in master.cf. This preserves SMTP
 loop detection, by ensuring that each side of the firewall knows that the
 other IP address is still the same host. Setting $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> to a
-single IP address is primarily useful with virtual hosting of domains on
+single IPv4 and/or IPV6 address is primarily useful with virtual
+hosting of domains on
 secondary IP addresses, when each IP address serves a different domain
 (and has a different $<a href="postconf.5.html#myhostname">myhostname</a> setting). </p>
 
 <p>
 See also the <a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> parameter, for network addresses that
-are forwarded to us by way of a proxy or address translator.
+are forwarded to Postfix by way of a proxy or address translator.
 </p>
 
 <p>
-Note: you need to stop and start Postfix when this parameter changes.
+Examples:
+</p>
+
+<pre>
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = all (DEFAULT)
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = loopback-only
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = 127.0.0.1
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> = 192.168.1.2, 127.0.0.1
+</pre>
+
+
+</DD>
+
+<DT><b><a name="inet_protocols">inet_protocols</a>
+(default: ipv4)</b></DT><DD>
+
+<p> The Internet protocols Postfix will attempt to use when making
+or accepting connections. Specify one or more of "ipv4" or "ipv6",
+separated by whitespace or commas. The form "all" is equivalent to
+"ipv4, ipv6". </p>
+
+<p> Note: you MUST stop and start Postfix after changing this
+parameter. </p>
+
+<p> On systems that pre-date IPV6_V6ONLY support (<a href="http://www.faqs.org/rfcs/rfc3493.html">RFC 3493</a>), an
+IPv6 server will also accept IPv4 connections, even when IPv4 is
+turned off with the <a href="postconf.5.html#inet_protocols">inet_protocols</a> parameter.  On systems with
+IPV6_V6ONLY support, Postfix will use separate server sockets for
+IPv6 and IPv4, and each will accept only connections for the
+corresponding protocol.  </p>
+
+<p> When IPv4 support is enabled via the <a href="postconf.5.html#inet_protocols">inet_protocols</a> parameter,
+Postfix will to DNS type A record lookups, and will convert
+IPv4-in-IPv6 client IP addresses (::ffff:1.2.3.4) to their original
+IPv4 form (1.2.3.4).  The latter is needed on hosts that pre-date
+IPV6_V6ONLY support (<a href="http://www.faqs.org/rfcs/rfc3493.html">RFC 3493</a>). </p>
+
+<p> When IPv6 support is enabled via the <a href="postconf.5.html#inet_protocols">inet_protocols</a> parameter,
+Postfix will do DNS type AAAA record lookups. </p>
+
+<p> When both IPv4 and IPv6 support are enabled, the Postfix SMTP
+client will attempt to connect via IPv6 before attempting to use
+IPv4.  </p>
+
+<p> This feature is available in Postfix version 2.2 and later. </p>
+
+<p>
+Examples:
 </p>
 
+<pre>
+<a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4 (DEFAULT)
+<a href="postconf.5.html#inet_protocols">inet_protocols</a> = all
+<a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv6
+<a href="postconf.5.html#inet_protocols">inet_protocols</a> = ipv4, ipv6
+</pre>
+
 
 </DD>
 
@@ -4070,11 +4142,17 @@ lookup string (the lookup result is ignored). </p>
 first match.  Specify "!pattern" to exclude an address or network
 block from the list.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#mynetworks">mynetworks</a> value, and in files specified with
+"/file/name".  IP version 6 addresses contain the ":" character,
+and would otherwise be confused with a "<a href="DATABASE_README.html">type:table</a>" pattern.  </p>
+
 <p> Examples:  </p>
 
 <pre>
-<a href="postconf.5.html#mynetworks">mynetworks</a> = 168.100.189.0/28, 127.0.0.0/8
+<a href="postconf.5.html#mynetworks">mynetworks</a> = 127.0.0.0/8 168.100.189.0/28
 <a href="postconf.5.html#mynetworks">mynetworks</a> = !192.168.0.1, 192.168.0.0/28
+<a href="postconf.5.html#mynetworks">mynetworks</a> = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:5c7::]/64
 <a href="postconf.5.html#mynetworks">mynetworks</a> = $<a href="postconf.5.html#config_directory">config_directory</a>/mynetworks
 <a href="postconf.5.html#mynetworks">mynetworks</a> = hash:/etc/postfix/network_table
 </pre>
@@ -5451,7 +5529,7 @@ the word "ESMTP" appears in the server greeting banner (example:
 
 <p>
 An optional numerical network address that the SMTP client should
-bind to when making a connection.
+bind to when making an IPv4 connection.
 </p>
 
 <p>
@@ -5465,11 +5543,47 @@ for example:
         smtp ... smtp -o <a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a>=11.22.33.44
 </pre>
 
-<p> Note: when <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies exactly one address that
-is a non-loopback address, it is automatically used as the
-<a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a>.  This supports virtual IP hosting, but can be
-a problem on multi-homed firewalls. See the <a href="postconf.5.html#inet_interfaces">inet_interfaces</a>
-documentation for more detail. </p>
+<p> Note 1: when <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies no more than one IPv4
+address, and that address is a non-loopback address, it is
+automatically used as the <a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a>.  This supports virtual
+IP hosting, but can be a problem on multi-homed firewalls. See the
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> documentation for more detail. </p>
+
+<p> Note 2: address information may be enclosed inside <tt>[]</tt>,
+but this form is not recommended. </p>
+
+
+</DD>
+
+<DT><b><a name="smtp_bind_address6">smtp_bind_address6</a>
+(default: empty)</b></DT><DD>
+
+<p>
+An optional numerical network address that the SMTP client should
+bind to when making an IPv6 connection.
+</p>
+
+<p>
+This can be specified in the main.cf file for all SMTP clients, or
+it can be specified in the master.cf file for a specific client,
+for example:
+</p>
+
+<pre>
+  /etc/postfix/master.cf:
+        smtp ... smtp -o <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a>=1:2:3:4:5:6:7:8
+</pre>
+
+<p> Note 1: when <a href="postconf.5.html#inet_interfaces">inet_interfaces</a> specifies no more than one IPv6
+address, and that address is a non-loopback address, it is
+automatically used as the <a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a>.  This supports virtual
+IP hosting, but can be a problem on multi-homed firewalls. See the
+<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> documentation for more detail. </p>
+
+<p> Note 2: address information may be enclosed inside <tt>[]</tt>,
+but this form is not recommended. </p>
+
+<p> This feature is available in Postfix version 2.2 and later. </p>
 
 
 </DD>
@@ -6211,6 +6325,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#smtpd_authorized_verp_clients">smtpd_authorized_verp_clients</a> value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "<a href="DATABASE_README.html">type:table</a>"
+pattern.  </p>
+
 
 </DD>
 
@@ -6244,6 +6364,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#smtpd_authorized_xclient_hosts">smtpd_authorized_xclient_hosts</a> value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "<a href="DATABASE_README.html">type:table</a>"
+pattern.  </p>
+
 
 </DD>
 
@@ -6276,6 +6402,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#smtpd_authorized_xforward_hosts">smtpd_authorized_xforward_hosts</a> value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "<a href="DATABASE_README.html">type:table</a>"
+pattern.  </p>
+
 
 </DD>
 
@@ -6381,6 +6513,12 @@ list of network blocks, hostnames or .domain names (the initial
 dot causes the domain to match any name below it).
 </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> value, and
+in files specified with "/file/name".  IP version 6 addresses
+contain the ":" character, and would otherwise be confused with a
+"<a href="DATABASE_README.html">type:table</a>" pattern.  </p>
+
 <p>
 This feature is available in Postfix 2.2 and later.
 </p>
@@ -7533,6 +7671,12 @@ contents; a "<a href="DATABASE_README.html">type:table</a>" lookup table is matc
 matches a lookup string (the lookup result is ignored).  Continue
 long lines by starting the next line with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the <a href="postconf.5.html#smtpd_sasl_exceptions_networks">smtpd_sasl_exceptions_networks</a> value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "<a href="DATABASE_README.html">type:table</a>"
+pattern.  </p>
+
 <p>
 Example:
 </p>
@@ -8664,7 +8808,7 @@ it will open the table directly. Before Postfix version 2.2, the
 <p> Optional lookup tables with a) names of domains for which all
 addresses are aliased to addresses in other local or remote domains,
 and b) addresses that are aliased to addresses in other local or
-remote domains.  Available before Postfix version 2.0. With Postfix 2.1
+remote domains.  Available before Postfix version 2.0. With Postfix 2.0
 and later, this is replaced by separate controls: <a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>
 and <a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>. </p>
 
index 0772461a84f510ec07a2b4e71da927a8fb2adeb8..46ff22d76bad617ec7035dac2f98b0024ff1a1c5 100644 (file)
@@ -62,89 +62,92 @@ POSTQUEUE(1)                                         POSTQUEUE(1)
 
        <b>-s</b> <i>site</i>
               Schedule immediate delivery of  all  mail  that  is
-              queued  for the named <i>site</i>. The site must be eligi-
-              ble for the "fast flush" service.  See <a href="flush.8.html"><b>flush</b>(8)</a> for
-              more information about the "fast flush" service.
-
-              This  option  implements  the  traditional <b>sendmail</b>
+              queued for the named <i>site</i>. A numerical site must be
+              specified as  a  valid  <a href="http://www.faqs.org/rfcs/rfc2821.html">RFC  2821</a>  address  literal
+              enclosed  in [], just like in email addresses.  The
+              site must be eligible for the "fast flush" service.
+              See  <a href="flush.8.html"><b>flush</b>(8)</a>  for more information about the "fast
+              flush" service.
+
+              This option  implements  the  traditional  <b>sendmail</b>
               <b>-qR</b><i>site</i> command, by contacting the Postfix <a href="flush.8.html"><b>flush</b>(8)</a>
               daemon.
 
        <b>-v</b>     Enable verbose logging for debugging purposes. Mul-
-              tiple <b>-v</b> options  make  the  software  increasingly
+              tiple  <b>-v</b>  options  make  the software increasingly
               verbose.
 
 <b>SECURITY</b>
-       This  program  is designed to run with set-group ID privi-
+       This program is designed to run with set-group  ID  privi-
        leges, so that it can connect to Postfix daemon processes.
 
 <b>DIAGNOSTICS</b>
-       Problems  are  logged  to  <b>syslogd</b>(8)  and to the standard
+       Problems are logged to  <b>syslogd</b>(8)  and  to  the  standard
        error stream.
 
 <b>ENVIRONMENT</b>
        MAIL_CONFIG
-              Directory with the <b>main.cf</b> file. In order to  avoid
-              exploitation  of  set-group  ID  privileges, a non-
+              Directory  with the <b>main.cf</b> file. In order to avoid
+              exploitation of set-group  ID  privileges,  a  non-
               standard directory is allowed only if:
 
-              <b>o</b>      The name is listed in the  standard  <b>main.cf</b>
-                     file  with  the <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
+              <b>o</b>      The  name  is listed in the standard <b>main.cf</b>
+                     file with  the  <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a></b>
                      configuration parameter.
 
               <b>o</b>      The command is invoked by the super-user.
 
 <b>CONFIGURATION PARAMETERS</b>
-       The following <b>main.cf</b> parameters are  especially  relevant
+       The  following  <b>main.cf</b> parameters are especially relevant
        to this program.  The text below provides only a parameter
-       summary. See <a href="postconf.5.html">postconf(5)</a> for more details including  exam-
+       summary.  See <a href="postconf.5.html">postconf(5)</a> for more details including exam-
        ples.
 
        <b><a href="postconf.5.html#alternate_config_directories">alternate_config_directories</a> (empty)</b>
-              A  list of non-default Postfix configuration direc-
+              A list of non-default Postfix configuration  direc-
               tories that may be specified with "-c <a href="postconf.5.html#config_directory">config_direc</a>-
-              <a href="postconf.5.html#config_directory">tory</a>"  on  the command line, or via the MAIL_CONFIG
+              <a href="postconf.5.html#config_directory">tory</a>" on the command line, or via  the  MAIL_CONFIG
               environment parameter.
 
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
+              The  default  location  of  the Postfix main.cf and
               master.cf configuration files.
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
-              The  location  of  all  postfix administrative com-
+              The location of  all  postfix  administrative  com-
               mands.
 
        <b><a href="postconf.5.html#fast_flush_domains">fast_flush_domains</a> ($<a href="postconf.5.html#relay_domains">relay_domains</a>)</b>
               Optional list of destinations that are eligible for
-              per-destination  logfiles  with mail that is queued
+              per-destination logfiles with mail that  is  queued
               to those destinations.
 
        <b><a href="postconf.5.html#import_environment">import_environment</a> (see 'postconf -d' output)</b>
-              The list of environment parameters that  a  Postfix
-              process  will import from a non-Postfix parent pro-
+              The  list  of environment parameters that a Postfix
+              process will import from a non-Postfix parent  pro-
               cess.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The location of the Postfix top-level queue  direc-
+              The  location of the Postfix top-level queue direc-
               tory.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The  mail system name that is prepended to the pro-
+              The mail system name that is prepended to the  pro-
               cess  name  in  syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
 
        <b><a href="postconf.5.html#trigger_timeout">trigger_timeout</a> (10s)</b>
-              The  time  limit for sending a trigger to a Postfix
-              daemon (for example, the <a href="pickup.8.html">pickup(8)</a> or <a href="qmgr.8.html">qmgr(8)</a>  dae-
+              The time limit for sending a trigger to  a  Postfix
+              daemon  (for example, the <a href="pickup.8.html">pickup(8)</a> or <a href="qmgr.8.html">qmgr(8)</a> dae-
               mon).
 
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#authorized_flush_users">authorized_flush_users</a> (static:anyone)</b>
-              List  of  users  who  are  authorized  to flush the
+              List of users  who  are  authorized  to  flush  the
               queue.
 
        <b><a href="postconf.5.html#authorized_mailq_users">authorized_mailq_users</a> (static:anyone)</b>
@@ -164,11 +167,11 @@ POSTQUEUE(1)                                         POSTQUEUE(1)
        <a href="ETRN_README.html">ETRN_README</a>, Postfix ETRN howto
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>HISTORY</b>
-       The  postqueue command was introduced with Postfix version
+       The postqueue command was introduced with Postfix  version
        1.1.
 
 <b>AUTHOR(S)</b>
index d0fd4d95314a027adb1560978596f5701c54ef27..99892adac286a5a57892a11f14d06a4f2d2a88d4 100644 (file)
@@ -10,18 +10,24 @@ QMQP-SINK(1)                                         QMQP-SINK(1)
        qmqp-sink - multi-threaded QMQP test server
 
 <b>SYNOPSIS</b>
-       <b>qmqp-sink</b> [<b>-cv</b>] [<b>-x</b> <i>time</i>] [<b>inet:</b>][<i>host</i>]:<i>port backlog</i>
+       <b>qmqp-sink</b> [<b>-46cv</b>] [<b>-x</b> <i>time</i>] [<b>inet:</b>][<i>host</i>]:<i>port backlog</i>
 
-       <b>qmqp-sink</b> [<b>-cv</b>] [<b>-x</b> <i>time</i>] <b>unix:</b><i>pathname backlog</i>
+       <b>qmqp-sink</b> [<b>-46cv</b>] [<b>-x</b> <i>time</i>] <b>unix:</b><i>pathname backlog</i>
 
 <b>DESCRIPTION</b>
        <b>qmqp-sink</b> listens on the named host (or address) and port.
        It receives messages from  the  network  and  throws  them
        away.   The purpose is to measure QMQP client performance,
        not protocol compliance.  Connections can be  accepted  on
-       IPV4  endpoints  or  UNIX-domain  sockets.   IPV4  is  the
-       default.  This program is  the  complement  of  the  <a href="qmqp-source.1.html"><b>qmqp-</b></a>
-       <a href="qmqp-source.1.html"><b>source</b>(1)</a> program.
+       IPv4  or  IPv6 endpoints, or on UNIX-domain sockets.  IPv4
+       and IPv6 are the default.  This program is the  complement
+       of the <a href="qmqp-source.1.html"><b>qmqp-source</b>(1)</a> program.
+
+       <b>-4</b>     Support  IPv4  only. This option has no effect when
+              Postfix is built without IPv6 support.
+
+       <b>-6</b>     Support IPv6 only. This  option  is  not  available
+              when Postfix is built without IPv6 support.
 
        <b>-c</b>     Display  a running counter that is updated whenever
               a delivery is completed.
index ed8d3b6c9f01f09fba166d61c0c46d41cb124660..49b22607ac5c36e4338226ab27a913efe8a67b75 100644 (file)
@@ -18,11 +18,18 @@ QMQP-SOURCE(1)                                     QMQP-SOURCE(1)
        <b>qmqp-source</b>  connects  to  the  named  host  and  TCP port
        (default 628) and sends one or more messages to it, either
        sequentially  or  in parallel. The program speaks the QMQP
-       protocol.  Connections can be made to UNIX-domain and IPV4
-       servers.  IPV4 is the default.
+       protocol.  Connections can be made to UNIX-domain and IPv4
+       or IPv6 servers.  IPv4 and IPv6 are the default.
 
        Options:
 
+       <b>-4</b>     Connect to the server with IPv4. This option has no
+              effect when Postfix is built without IPv6  support.
+
+       <b>-6</b>     Connect to the server with IPv6. This option is not
+              available when Postfix is built without  IPv6  sup-
+              port.
+
        <b>-c</b>     Display  a running counter that is incremented each
               time a delivery completes.
 
index 26a06d764fd87f1272e72676c9a3f01d3c383c42..bf94ce6c09c9eb3c027ed9c11b302f8ab076b59c 100644 (file)
@@ -57,7 +57,7 @@ QMQPD(8)                                                 QMQPD(8)
 
        <b><a href="postconf.5.html#receive_override_options">receive_override_options</a> (empty)</b>
               Enable  or  disable  recipient validation, built-in
-              content filtering, or address rewriting.
+              content filtering, or address mapping.
 
 <b>RESOURCE AND RATE CONTROLS</b>
        <b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
index 38e052cc50ed0e492ddd82500414866f605e118b..39caa1660df06183b17131746e65bd2fa0155cbf 100644 (file)
@@ -153,6 +153,9 @@ SENDMAIL(1)                                           SENDMAIL(1)
               Non-default alias  database.  Specify  <i>pathname</i>  or
               <i>type</i>:<i>pathname</i>. See <a href="postalias.1.html"><b>postalias</b>(1)</a> for details.
 
+       <b>-O</b> <i>option=value</i> (ignored)
+              Backwards compatibility.
+
        <b>-o7</b> (ignored)
 
        <b>-o8</b> (ignored)
index 41b36d94dc873629bc924930ff4637dd5b90cac6..b131650e6e92f3c94ba8a04d18953187f7979b59 100644 (file)
@@ -20,15 +20,22 @@ SMTP-SINK(1)                                         SMTP-SINK(1)
        away.   The  purpose is to measure client performance, not
        protocol compliance.
 
-       Connections can be accepted on  IPV4  endpoints  or  UNIX-
-       domain sockets.  IPV4 is the default.  This program is the
-       complement of the <a href="smtp-source.1.html"><b>smtp-source</b>(1)</a> program.
+       Connections can be accepted on IPv4 or IPv6 endpoints,  or
+       on  UNIX-domain  sockets.   IPv4 and IPv6 are the default.
+       This program is the complement of the <a href="smtp-source.1.html"><b>smtp-source</b>(1)</a>  pro-
+       gram.
 
        Arguments:
 
+       <b>-4</b>     Support  IPv4  only. This option has no effect when
+              Postfix is built without IPv6 support.
+
+       <b>-6</b>     Support IPv6 only. This  option  is  not  available
+              when Postfix is built without IPv6 support.
+
        <b>-a</b>     Do not announce SASL authentication support.
 
-       <b>-c</b>     Display a running counter that is updated  whenever
+       <b>-c</b>     Display  a running counter that is updated whenever
               an SMTP QUIT command is executed.
 
        <b>-C</b>     Disable XCLIENT support.
@@ -36,14 +43,14 @@ SMTP-SINK(1)                                         SMTP-SINK(1)
        <b>-e</b>     Do not announce ESMTP support.
 
        <b>-f</b> <i>command,command,...</i>
-              Reject  the  specified  commands  with a hard (5xx)
+              Reject the specified commands  with  a  hard  (5xx)
               error code.
 
        <b>-F</b>     Disable XFORWARD support.
 
        <b>-h</b> <i>hostname</i>
-              Use <i>hostname</i> in the  SMTP  greeting,  in  the  HELO
-              response,  and  in  the  EHLO response. The default
+              Use  <i>hostname</i>  in  the  SMTP  greeting, in the HELO
+              response, and in the  EHLO  response.  The  default
               hostname is "smtp-sink".
 
        <b>-L</b>     Enable LMTP instead of SMTP.
@@ -52,26 +59,26 @@ SMTP-SINK(1)                                         SMTP-SINK(1)
               Terminate after <i>count</i> sessions. This is for testing
               purposes.
 
-       <b>-p</b>     Do  not announce support for ESMTP command pipelin-
+       <b>-p</b>     Do not announce support for ESMTP command  pipelin-
               ing.
 
-       <b>-P</b>     Change the server greeting so that  it  appears  to
+       <b>-P</b>     Change  the  server  greeting so that it appears to
               come through a CISCO PIX system. Implies <b>-e</b>.
 
        <b>-q</b> <i>command,command,...</i>
-              Disconnect  (without  replying) after receiving one
+              Disconnect (without replying) after  receiving  one
               of the specified commands.
 
        <b>-r</b> <i>command,command,...</i>
-              Reject the specified commands  with  a  soft  (4xx)
+              Reject  the  specified  commands  with a soft (4xx)
               error code.
 
        <b>-s</b> <i>command,command,...</i>
-              Log  the  named  commands  to syslogd.  Examples of
-              commands that can be logged are HELO,  EHLO,  LHLO,
-              MAIL,  RCPT,  VRFY,  RSET, NOOP, and QUIT. Separate
-              command names by white space  or  commas,  and  use
-              quotes  to protect white space from the shell. Com-
+              Log the named commands  to  syslogd.   Examples  of
+              commands  that  can be logged are HELO, EHLO, LHLO,
+              MAIL, RCPT, VRFY, RSET, NOOP,  and  QUIT.  Separate
+              command  names  by  white  space or commas, and use
+              quotes to protect white space from the shell.  Com-
               mand names are case-insensitive.
 
        <b>-v</b>     Show the SMTP conversations.
@@ -83,7 +90,7 @@ SMTP-SINK(1)                                         SMTP-SINK(1)
        <b>-8</b>     Do not announce 8BITMIME support.
 
        [<b>inet:</b>][<i>host</i>]:<i>port</i>
-              Listen  on  network  interface  <i>host</i>  (default: any
+              Listen on  network  interface  <i>host</i>  (default:  any
               interface) TCP port <i>port</i>. Both <i>host</i> and <i>port</i> may be
               specified in numeric or symbolic form.
 
@@ -91,14 +98,14 @@ SMTP-SINK(1)                                         SMTP-SINK(1)
               Listen on the UNIX-domain socket at <i>pathname</i>.
 
        <i>backlog</i>
-              The  maximum  length  the  queue of pending connec-
+              The maximum length the  queue  of  pending  connec-
               tions, as defined by the listen(2) call.
 
 <b>SEE ALSO</b>
        <a href="smtp-source.1.html">smtp-source(1)</a>, SMTP/LMTP message generator
 
 <b>LICENSE</b>
-       The Secure Mailer license must be  distributed  with  this
+       The  Secure  Mailer  license must be distributed with this
        software.
 
 <b>AUTHOR(S)</b>
index ca2477b07623cac0c9b1409b1481220868baa03a..df2e821417397af6a38fe4a0f77dd3e03480fb0b 100644 (file)
@@ -18,33 +18,41 @@ SMTP-SOURCE(1)                                     SMTP-SOURCE(1)
        <b>smtp-source</b>  connects  to  the  named  <i>host</i>  and  TCP <i>port</i>
        (default: port 25) and sends one or more messages  to  it,
        either  sequentially  or  in  parallel. The program speaks
-       either SMTP (default) or LMTP. Connections can be made  to
-       UNIX-domain and IPV4 servers.  IPV4 is the default.
+       either SMTP (default) or LMTP.  Connections can be made to
+       UNIX-domain  and  IPv4 or IPv6 servers.  IPv4 and IPv6 are
+       the default.
 
        Arguments:
 
-       <b>-c</b>     Display  a running counter that is incremented each
+       <b>-4</b>     Connect to the server with IPv4. This option has no
+              effect  when Postfix is built without IPv6 support.
+
+       <b>-6</b>     Connect to the server with IPv6. This option is not
+              available  when  Postfix is built without IPv6 sup-
+              port.
+
+       <b>-c</b>     Display a running counter that is incremented  each
               time an SMTP DATA command completes.
 
        <b>-C</b> <i>count</i>
-              When a host sends RESET  instead  of  SYN|ACK,  try
-              <i>count</i>  times before giving up. The default count is
+              When  a  host  sends  RESET instead of SYN|ACK, try
+              <i>count</i> times before giving up. The default count  is
               1. Specify a larger count in order to work around a
               problem with TCP/IP stacks that send RESET when the
               listen queue is full.
 
-       <b>-d</b>     Don't disconnect after sending a message; send  the
+       <b>-d</b>     Don't  disconnect after sending a message; send the
               next message over the same connection.
 
        <b>-f</b> <i>from</i>
-              Use   the   specified   sender   address  (default:
+              Use  the   specified   sender   address   (default:
               &lt;foo@<a href="postconf.5.html#myhostname">myhostname</a>&gt;).
 
-       <b>-o</b>     Old mode: don't send HELO, and don't  send  message
+       <b>-o</b>     Old  mode:  don't send HELO, and don't send message
               headers.
 
        <b>-l</b> <i>length</i>
-              Send  <i>length</i>  bytes  as message payload. The length
+              Send <i>length</i> bytes as message  payload.  The  length
               does not include message headers.
 
        <b>-L</b>     Speak LMTP rather than SMTP.
@@ -52,15 +60,15 @@ SMTP-SOURCE(1)                                     SMTP-SOURCE(1)
        <b>-m</b> <i>message</i><b>_</b><i>count</i>
               Send the specified number of messages (default: 1).
 
-       <b>-N</b>     Prepend  a  non-repeating  sequence  number to each
-              recipient address. This avoids the artificial  100%
-              hit  rate  in the resolve and rewrite client caches
-              and exercises the  trivial-rewrite  daemon,  better
-              approximating  Postfix  performance under real-life
+       <b>-N</b>     Prepend a non-repeating  sequence  number  to  each
+              recipient  address. This avoids the artificial 100%
+              hit rate in the resolve and rewrite  client  caches
+              and  exercises  the  trivial-rewrite daemon, better
+              approximating Postfix performance  under  real-life
               work-loads.
 
        <b>-r</b> <i>recipient</i><b>_</b><i>count</i>
-              Send the specified number of recipients per  trans-
+              Send  the specified number of recipients per trans-
               action (default: 1).  Recipient names are generated
               by prepending a number to the recipient address.
 
@@ -69,15 +77,15 @@ SMTP-SOURCE(1)                                     SMTP-SOURCE(1)
               lel (default: 1).
 
        <b>-S</b> <i>subject</i>
-              Send  mail  with  the  named subject line (default:
+              Send mail with the  named  subject  line  (default:
               none).
 
-       <b>-t</b> <i>to</i>  Use  the  specified  recipient  address   (default:
+       <b>-t</b> <i>to</i>  Use   the  specified  recipient  address  (default:
               &lt;foo@<a href="postconf.5.html#myhostname">myhostname</a>&gt;).
 
        <b>-R</b> <i>interval</i>
               Wait for a random period of time 0 &lt;= n &lt;= interval
-              between messages.  Suspending one thread  does  not
+              between  messages.   Suspending one thread does not
               affect other delivery threads.
 
        <b>-w</b> <i>interval</i>
@@ -85,7 +93,7 @@ SMTP-SOURCE(1)                                     SMTP-SOURCE(1)
               thread does not affect other delivery threads.
 
        [<b>inet:</b>]<i>host</i>[:<i>port</i>]
-              Connect via  TCP  to  host  <i>host</i>,  port  <i>port</i>.  The
+              Connect  via  TCP  to  host  <i>host</i>,  port  <i>port</i>. The
               default port is <b>smtp</b>.
 
        <b>unix:</b><i>pathname</i>
@@ -98,7 +106,7 @@ SMTP-SOURCE(1)                                     SMTP-SOURCE(1)
        <a href="smtp-sink.1.html">smtp-sink(1)</a>, SMTP/LMTP message dump
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 2d764607d6d96315f5f8119166d8a1b2582e7224..de553093b05925f5d338fd1e9f6966451b855425 100644 (file)
@@ -330,37 +330,47 @@ SMTP(8)                                                   SMTP(8)
               The network interface addresses that this mail sys-
               tem receives mail on.
 
+       <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
+              The  Internet protocols Postfix will attempt to use
+              when making or accepting connections.
+
        <b><a href="postconf.5.html#ipc_timeout">ipc_timeout</a> (3600s)</b>
               The time limit for sending or receiving information
               over an internal communication channel.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The maximum amount of time  that  an  idle  Postfix
-              daemon  process  waits for the next service request
+              The  maximum  amount  of  time that an idle Postfix
+              daemon process waits for the next  service  request
               before exiting.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The maximal number of connection requests before  a
+              The  maximal number of connection requests before a
               Postfix daemon process terminates.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The  process ID of a Postfix command or daemon pro-
+              The process ID of a Postfix command or daemon  pro-
               cess.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The process name of a  Postfix  command  or  daemon
+              The  process  name  of  a Postfix command or daemon
               process.
 
        <b><a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a> (empty)</b>
               The network interface addresses that this mail sys-
-              tem receives mail on by way of a proxy  or  network
+              tem  receives  mail on by way of a proxy or network
               address translation unit.
 
        <b><a href="postconf.5.html#smtp_bind_address">smtp_bind_address</a> (empty)</b>
               An optional numerical network address that the SMTP
-              client should bind to when making a connection.
+              client  should  bind to when making an IPv4 connec-
+              tion.
+
+       <b><a href="postconf.5.html#smtp_bind_address6">smtp_bind_address6</a> (empty)</b>
+              An optional numerical network address that the SMTP
+              client  should  bind to when making an IPv6 connec-
+              tion.
 
-       <b><a href="postconf.5.html#<a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a>"><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a></a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
+       <b><a href="postconf.5.html#smtp_helo_name">smtp_helo_name</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The hostname to send in the SMTP EHLO or HELO  com-
               mand.
 
index bc6fb70e469ce984604a4d3cecd81e194f76769c..112cb5ef79d4a1b91a9f659e44937efaec9e23f4 100644 (file)
@@ -323,182 +323,186 @@ SMTPD(8)                                                 SMTPD(8)
               tem  receives  mail on by way of a proxy or network
               address translation unit.
 
+       <b><a href="postconf.5.html#inet_protocols">inet_protocols</a> (ipv4)</b>
+              The Internet protocols Postfix will attempt to  use
+              when making or accepting connections.
+
        <b><a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>             (<a href="proxymap.8.html">proxy</a>:unix:passwd.byname</b>
        <b>$<a href="postconf.5.html#alias_maps">alias_maps</a>)</b>
-              Lookup tables with all names or addresses of  local
-              recipients:  a  recipient address is local when its
-              domain matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a>  or
+              Lookup  tables with all names or addresses of local
+              recipients: a recipient address is local  when  its
+              domain  matches $<a href="postconf.5.html#mydestination">mydestination</a>, $<a href="postconf.5.html#inet_interfaces">inet_interfaces</a> or
               $<a href="postconf.5.html#proxy_interfaces">proxy_interfaces</a>.
 
        <b><a href="postconf.5.html#unknown_local_recipient_reject_code">unknown_local_recipient_reject_code</a> (550)</b>
-              The  numerical  Postfix  SMTP  server response code
-              when   a   recipient   address   is   local,    and
-              $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a>  specifies  a  list of lookup
+              The numerical Postfix  SMTP  server  response  code
+              when    a   recipient   address   is   local,   and
+              $<a href="postconf.5.html#local_recipient_maps">local_recipient_maps</a> specifies a  list  of  lookup
               tables that does not match the recipient.
 
-       Parameters concerning known/unknown  recipients  of  relay
+       Parameters  concerning  known/unknown  recipients of relay
        destinations:
 
        <b><a href="postconf.5.html#relay_domains">relay_domains</a> ($<a href="postconf.5.html#mydestination">mydestination</a>)</b>
-              What  destination  domains (and subdomains thereof)
+              What destination domains (and  subdomains  thereof)
               this system will relay mail to.
 
        <b><a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> (empty)</b>
-              Optional lookup tables with all valid addresses  in
+              Optional  lookup tables with all valid addresses in
               the domains that match $<a href="postconf.5.html#relay_domains">relay_domains</a>.
 
        <b><a href="postconf.5.html#unknown_relay_recipient_reject_code">unknown_relay_recipient_reject_code</a> (550)</b>
               The numerical Postfix SMTP server reply code when a
-              recipient  address  matches   $<a href="postconf.5.html#relay_domains">relay_domains</a>,   and
-              <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a>  specifies  a  list  of lookup
+              recipient   address   matches  $<a href="postconf.5.html#relay_domains">relay_domains</a>,  and
+              <a href="postconf.5.html#relay_recipient_maps">relay_recipient_maps</a> specifies  a  list  of  lookup
               tables that does not match the recipient address.
 
-       Parameters concerning known/unknown recipients in  virtual
+       Parameters  concerning known/unknown recipients in virtual
        alias domains:
 
        <b><a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a> ($<a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a>)</b>
               Postfix is final destination for the specified list
-              of virtual alias  domains,  that  is,  domains  for
-              which  all  addresses  are  aliased to addresses in
+              of  virtual  alias  domains,  that  is, domains for
+              which all addresses are  aliased  to  addresses  in
               other local or remote domains.
 
        <b><a href="postconf.5.html#virtual_alias_maps">virtual_alias_maps</a> ($<a href="postconf.5.html#virtual_maps">virtual_maps</a>)</b>
-              Optional lookup tables  that  alias  specific  mail
-              addresses  or  domains  to  other  local  or remote
+              Optional  lookup  tables  that  alias specific mail
+              addresses or  domains  to  other  local  or  remote
               address.
 
        <b><a href="postconf.5.html#unknown_virtual_alias_reject_code">unknown_virtual_alias_reject_code</a> (550)</b>
               The SMTP server reply code when a recipient address
-              matches     $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>,    and    $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
-              <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a> specifies a list of  lookup  tables
+              matches    $<a href="postconf.5.html#virtual_alias_domains">virtual_alias_domains</a>,    and     $<a href="postconf.5.html#virtual_alias_maps">vir</a>-
+              <a href="postconf.5.html#virtual_alias_maps">tual_alias_maps</a>  specifies  a list of lookup tables
               that does not match the recipient address.
 
-       Parameters  concerning known/unknown recipients in virtual
+       Parameters concerning known/unknown recipients in  virtual
        mailbox domains:
 
        <b><a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a> ($<a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a>)</b>
               Postfix is final destination for the specified list
-              of   domains;  mail  is  delivered  via  the  $<a href="postconf.5.html#virtual_transport">vir</a>-
+              of  domains;  mail  is  delivered  via  the   $<a href="postconf.5.html#virtual_transport">vir</a>-
               <a href="postconf.5.html#virtual_transport">tual_transport</a> mail delivery transport.
 
        <b><a href="postconf.5.html#virtual_mailbox_maps">virtual_mailbox_maps</a> (empty)</b>
-              Optional lookup tables with all valid addresses  in
+              Optional  lookup tables with all valid addresses in
               the domains that match $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>.
 
        <b><a href="postconf.5.html#unknown_virtual_mailbox_reject_code">unknown_virtual_mailbox_reject_code</a> (550)</b>
               The SMTP server reply code when a recipient address
-              matches   $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>,    and    $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
+              matches    $<a href="postconf.5.html#virtual_mailbox_domains">virtual_mailbox_domains</a>,    and   $<a href="postconf.5.html#virtual_mailbox_maps">vir</a>-
               <a href="postconf.5.html#virtual_mailbox_maps">tual_mailbox_maps</a> specifies a list of lookup tables
               that does not match the recipient address.
 
 <b>RESOURCE AND RATE CONTROLS</b>
-       The following parameters limit resource usage by the  SMTP
+       The  following parameters limit resource usage by the SMTP
        server and/or control client request rates.
 
        <b><a href="postconf.5.html#line_length_limit">line_length_limit</a> (2048)</b>
-              Upon  input,  long lines are chopped up into pieces
-              of at most this length; upon delivery,  long  lines
+              Upon input, long lines are chopped up  into  pieces
+              of  at  most this length; upon delivery, long lines
               are reconstructed.
 
        <b><a href="postconf.5.html#queue_minfree">queue_minfree</a> (0)</b>
-              The  minimal  amount  of free space in bytes in the
+              The minimal amount of free space in  bytes  in  the
               queue file system that is needed to receive mail.
 
        <b><a href="postconf.5.html#message_size_limit">message_size_limit</a> (10240000)</b>
-              The maximal size in bytes of a  message,  including
+              The  maximal  size in bytes of a message, including
               envelope information.
 
        <b><a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a> (1000)</b>
-              The  maximal  number of recipients that the Postfix
+              The maximal number of recipients that  the  Postfix
               SMTP server accepts per message delivery request.
 
        <b><a href="postconf.5.html#smtpd_timeout">smtpd_timeout</a> (300s)</b>
-              The time limit for sending a  Postfix  SMTP  server
-              response  and  for  receiving  a remote SMTP client
+              The  time  limit  for sending a Postfix SMTP server
+              response and for receiving  a  remote  SMTP  client
               request.
 
        <b><a href="postconf.5.html#smtpd_history_flush_threshold">smtpd_history_flush_threshold</a> (100)</b>
-              The maximal number of lines  in  the  Postfix  SMTP
-              server  command  history  before it is flushed upon
+              The  maximal  number  of  lines in the Postfix SMTP
+              server command history before it  is  flushed  upon
               receipt of EHLO, RSET, or end of DATA.
 
        The per SMTP client connection count and request rate lim-
        its are implemented in co-operation with the <a href="anvil.8.html">anvil(8)</a> ser-
-       vice, and are available in Postfix version 2.2 and  later.
+       vice,  and are available in Postfix version 2.2 and later.
 
        <b><a href="postconf.5.html#smtpd_client_connection_count_limit">smtpd_client_connection_count_limit</a> (50)</b>
-              How  many  simultaneous  connections  any client is
+              How many simultaneous  connections  any  client  is
               allowed to make to this service.
 
        <b><a href="postconf.5.html#smtpd_client_connection_rate_limit">smtpd_client_connection_rate_limit</a> (0)</b>
               The  maximal  number  of  connection  attempts  any
-              client  is allowed to make to this service per time
+              client is allowed to make to this service per  time
               unit.
 
        <b><a href="postconf.5.html#smtpd_client_message_rate_limit">smtpd_client_message_rate_limit</a> (0)</b>
-              The maximal number  of  message  delivery  requests
-              that  any client is allowed to make to this service
+              The  maximal  number  of  message delivery requests
+              that any client is allowed to make to this  service
               per time unit, regardless of whether or not Postfix
               actually accepts those messages.
 
        <b><a href="postconf.5.html#smtpd_client_recipient_rate_limit">smtpd_client_recipient_rate_limit</a> (0)</b>
-              The  maximal number of recipient addresses that any
-              client is allowed to send to this service per  time
+              The maximal number of recipient addresses that  any
+              client  is allowed to send to this service per time
               unit, regardless of whether or not Postfix actually
               accepts those recipients.
 
        <b><a href="postconf.5.html#smtpd_client_event_limit_exceptions">smtpd_client_event_limit_exceptions</a> ($<a href="postconf.5.html#mynetworks">mynetworks</a>)</b>
-              Clients that are excluded  from  connection  count,
-              connection  rate,  message  rate  or recipient rate
+              Clients  that  are  excluded from connection count,
+              connection rate, message  rate  or  recipient  rate
               restrictions.
 
 <b>TARPIT CONTROLS</b>
-       When a remote SMTP client makes errors, the  Postfix  SMTP
-       server  can insert delays before responding. This can help
-       to slow down run-away  software.   The  behavior  is  con-
-       trolled  by  an  error  counter  that counts the number of
-       errors within an SMTP session that a client makes  without
+       When  a  remote SMTP client makes errors, the Postfix SMTP
+       server can insert delays before responding. This can  help
+       to  slow  down  run-away  software.   The behavior is con-
+       trolled by an error counter  that  counts  the  number  of
+       errors  within an SMTP session that a client makes without
        delivering mail.
 
        <b><a href="postconf.5.html#smtpd_error_sleep_time">smtpd_error_sleep_time</a> (1s)</b>
-              With   Postfix  2.1  and  later:  the  SMTP  server
-              response delay after a client has  made  more  than
-              $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a>   errors,  and  fewer  than
-              $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> errors, without  delivering
+              With  Postfix  2.1  and  later:  the  SMTP   server
+              response  delay  after  a client has made more than
+              $<a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a>  errors,  and  fewer   than
+              $<a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a>  errors, without delivering
               mail.
 
        <b><a href="postconf.5.html#smtpd_soft_error_limit">smtpd_soft_error_limit</a> (10)</b>
-              The  number  of  errors  a  remote  SMTP  client is
-              allowed to make without delivering mail before  the
+              The number  of  errors  a  remote  SMTP  client  is
+              allowed  to make without delivering mail before the
               Postfix SMTP server slows down all its responses.
 
        <b><a href="postconf.5.html#smtpd_hard_error_limit">smtpd_hard_error_limit</a> (20)</b>
-              The  maximal  number of errors a remote SMTP client
+              The maximal number of errors a remote  SMTP  client
               is allowed to make without delivering mail.
 
        <b><a href="postconf.5.html#smtpd_junk_command_limit">smtpd_junk_command_limit</a> (100)</b>
-              The number of junk commands (NOOP,  VRFY,  ETRN  or
+              The  number  of  junk commands (NOOP, VRFY, ETRN or
               RSET) that a remote SMTP client can send before the
-              Postfix SMTP server starts to increment  the  error
+              Postfix  SMTP  server starts to increment the error
               counter with each junk command.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#smtpd_recipient_overshoot_limit">smtpd_recipient_overshoot_limit</a> (1000)</b>
-              The  number of recipients that a remote SMTP client
-              can send in excess  of  the  limit  specified  with
+              The number of recipients that a remote SMTP  client
+              can  send  in  excess  of  the limit specified with
               $<a href="postconf.5.html#smtpd_recipient_limit">smtpd_recipient_limit</a>,  before  the  Postfix  SMTP
-              server increments the per-session error  count  for
+              server  increments  the per-session error count for
               each excess recipient.
 
 <b>ACCESS POLICY DELEGATION CONTROLS</b>
-       As  of  version 2.1, Postfix can be configured to delegate
-       access policy decisions to an external  server  that  runs
-       outside  Postfix.   See  the  file <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a> for
+       As of version 2.1, Postfix can be configured  to  delegate
+       access  policy  decisions  to an external server that runs
+       outside Postfix.  See  the  file  <a href="SMTPD_POLICY_README.html">SMTPD_POLICY_README</a>  for
        more information.
 
        <b><a href="postconf.5.html#smtpd_policy_service_max_idle">smtpd_policy_service_max_idle</a> (300s)</b>
-              The time after which an idle SMTPD  policy  service
+              The  time  after which an idle SMTPD policy service
               connection is closed.
 
        <b><a href="postconf.5.html#smtpd_policy_service_max_ttl">smtpd_policy_service_max_ttl</a> (1000s)</b>
@@ -506,161 +510,161 @@ SMTPD(8)                                                 SMTPD(8)
               connection is closed.
 
        <b><a href="postconf.5.html#smtpd_policy_service_timeout">smtpd_policy_service_timeout</a> (100s)</b>
-              The time limit for connecting  to,  writing  to  or
+              The  time  limit  for  connecting to, writing to or
               receiving from a delegated SMTPD policy server.
 
 <b>ACCESS CONTROLS</b>
-       The  <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction to
+       The <a href="SMTPD_ACCESS_README.html">SMTPD_ACCESS_README</a> document gives an introduction  to
        all the SMTP server access control features.
 
        <b><a href="postconf.5.html#smtpd_delay_reject">smtpd_delay_reject</a> (yes)</b>
-              Wait until the RCPT TO  command  before  evaluating
+              Wait  until  the  RCPT TO command before evaluating
               $<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a>,    $smtpd_helo_restric-
               tions and $<a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a>, or wait until
-              the      ETRN     command     before     evaluating
+              the     ETRN     command     before      evaluating
               $<a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> and $smtpd_helo_restric-
               tions.
 
-       <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a>  (see  'postconf -d' out-</b>
+       <b><a href="postconf.5.html#parent_domain_matches_subdomains">parent_domain_matches_subdomains</a> (see 'postconf  -d'  out-</b>
        <b>put)</b>
               What   Postfix   features   match   subdomains   of
               "domain.tld" automatically, instead of requiring an
               explicit ".domain.tld" pattern.
 
        <b><a href="postconf.5.html#smtpd_client_restrictions">smtpd_client_restrictions</a> (empty)</b>
-              Optional  SMTP  server  access  restrictions in the
+              Optional SMTP server  access  restrictions  in  the
               context of a client SMTP connection request.
 
        <b><a href="postconf.5.html#smtpd_helo_required">smtpd_helo_required</a> (no)</b>
               Require that a remote SMTP client introduces itself
-              at  the  beginning of an SMTP session with the HELO
+              at the beginning of an SMTP session with  the  HELO
               or EHLO command.
 
        <b><a href="postconf.5.html#smtpd_helo_restrictions">smtpd_helo_restrictions</a> (empty)</b>
-              Optional restrictions that the Postfix SMTP  server
+              Optional  restrictions that the Postfix SMTP server
               applies in the context of the SMTP HELO command.
 
        <b><a href="postconf.5.html#smtpd_sender_restrictions">smtpd_sender_restrictions</a> (empty)</b>
-              Optional  restrictions that the Postfix SMTP server
+              Optional restrictions that the Postfix SMTP  server
               applies in the context of the MAIL FROM command.
 
        <b><a href="postconf.5.html#smtpd_recipient_restrictions">smtpd_recipient_restrictions</a>           (<a href="postconf.5.html#permit_mynetworks">permit_mynetworks</a>,</b>
        <b><a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a>)</b>
               The  access  restrictions  that  the  Postfix  SMTP
-              server  applies  in the context of the RCPT TO com-
+              server applies in the context of the RCPT  TO  com-
               mand.
 
        <b><a href="postconf.5.html#smtpd_etrn_restrictions">smtpd_etrn_restrictions</a> (empty)</b>
-              Optional SMTP server  access  restrictions  in  the
+              Optional  SMTP  server  access  restrictions in the
               context of a client ETRN request.
 
        <b><a href="postconf.5.html#allow_untrusted_routing">allow_untrusted_routing</a> (no)</b>
-              Forward    mail   with   sender-specified   routing
-              (user[@%!]remote[@%!]site) from  untrusted  clients
+              Forward   mail   with   sender-specified    routing
+              (user[@%!]remote[@%!]site)  from  untrusted clients
               to destinations matching $<a href="postconf.5.html#relay_domains">relay_domains</a>.
 
        <b><a href="postconf.5.html#smtpd_restriction_classes">smtpd_restriction_classes</a> (empty)</b>
-              User-defined  aliases for groups of access restric-
+              User-defined aliases for groups of access  restric-
               tions.
 
        <b><a href="postconf.5.html#smtpd_null_access_lookup_key">smtpd_null_access_lookup_key</a> (</b>&lt;&gt;<b>)</b>
-              The lookup key to be used in SMTP <a href="access.5.html">access(5)</a>  tables
+              The  lookup key to be used in SMTP <a href="access.5.html">access(5)</a> tables
               instead of the null sender address.
 
        <b><a href="postconf.5.html#permit_mx_backup_networks">permit_mx_backup_networks</a> (empty)</b>
               Restrict  the  use  of  the  <a href="postconf.5.html#permit_mx_backup">permit_mx_backup</a>  SMTP
-              access feature to only  domains  whose  primary  MX
+              access  feature  to  only  domains whose primary MX
               hosts match the listed networks.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#smtpd_data_restrictions">smtpd_data_restrictions</a> (empty)</b>
-              Optional  access restrictions that the Postfix SMTP
+              Optional access restrictions that the Postfix  SMTP
               server applies in the context of the SMTP DATA com-
               mand.
 
        <b><a href="postconf.5.html#smtpd_expansion_filter">smtpd_expansion_filter</a> (see 'postconf -d' output)</b>
-              What  characters are allowed in $name expansions of
+              What characters are allowed in $name expansions  of
               RBL reply templates.
 
        Available in Postfix version 2.1 and later:
 
        <b><a href="postconf.5.html#smtpd_reject_unlisted_sender">smtpd_reject_unlisted_sender</a> (no)</b>
-              Request that the Postfix SMTP server  rejects  mail
-              from   unknown   sender  addresses,  even  when  no
-              explicit <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access  restriction
+              Request  that  the Postfix SMTP server rejects mail
+              from  unknown  sender  addresses,  even   when   no
+              explicit  <a href="postconf.5.html#reject_unlisted_sender">reject_unlisted_sender</a> access restriction
               is specified.
 
        <b><a href="postconf.5.html#smtpd_reject_unlisted_recipient">smtpd_reject_unlisted_recipient</a> (yes)</b>
-              Request  that  the Postfix SMTP server rejects mail
+              Request that the Postfix SMTP server  rejects  mail
               for  unknown  recipient  addresses,  even  when  no
-              explicit  <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access restric-
+              explicit <a href="postconf.5.html#reject_unlisted_recipient">reject_unlisted_recipient</a> access  restric-
               tion is specified.
 
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#smtpd_end_of_data_restrictions">smtpd_end_of_data_restrictions</a> (empty)</b>
-              Optional access restrictions that the Postfix  SMTP
-              server  applies  in the context of the SMTP END-OF-
+              Optional  access restrictions that the Postfix SMTP
+              server applies in the context of the  SMTP  END-OF-
               DATA command.
 
 <b>SENDER AND RECIPIENT ADDRESS VERIFICATION CONTROLS</b>
-       Postfix  version  2.1  introduces  sender  and   recipient
-       address  verification.   This  feature  is  implemented by
-       sending probe email messages that are not actually  deliv-
-       ered.   This  feature  is requested via the <a href="postconf.5.html#reject_unverified_sender">reject_unveri</a>-
-       <a href="postconf.5.html#reject_unverified_sender">fied_sender</a>   and    <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a>    access
-       restrictions.   The status of verification probes is main-
+       Postfix   version  2.1  introduces  sender  and  recipient
+       address verification.   This  feature  is  implemented  by
+       sending  probe email messages that are not actually deliv-
+       ered.  This feature is requested  via  the  <a href="postconf.5.html#reject_unverified_sender">reject_unveri</a>-
+       <a href="postconf.5.html#reject_unverified_sender">fied_sender</a>    and    <a href="postconf.5.html#reject_unverified_recipient">reject_unverified_recipient</a>   access
+       restrictions.  The status of verification probes is  main-
        tained by the <a href="verify.8.html">verify(8)</a> server.  See the file ADDRESS_VER-
-       <a href="IFICATION_README.html">IFICATION_README</a>  for  information  about how to configure
+       <a href="IFICATION_README.html">IFICATION_README</a> for information about  how  to  configure
        and operate the Postfix sender/recipient address verifica-
        tion service.
 
        <b><a href="postconf.5.html#address_verify_poll_count">address_verify_poll_count</a> (3)</b>
-              How  many  times to query the <a href="verify.8.html">verify(8)</a> service for
-              the completion of an address  verification  request
+              How many times to query the <a href="verify.8.html">verify(8)</a>  service  for
+              the  completion  of an address verification request
               in progress.
 
        <b><a href="postconf.5.html#address_verify_poll_delay">address_verify_poll_delay</a> (3s)</b>
-              The  delay between queries for the completion of an
+              The delay between queries for the completion of  an
               address verification request in progress.
 
        <b><a href="postconf.5.html#address_verify_sender">address_verify_sender</a> (postmaster)</b>
-              The sender address to use in  address  verification
+              The  sender  address to use in address verification
               probes.
 
        <b><a href="postconf.5.html#unverified_sender_reject_code">unverified_sender_reject_code</a> (450)</b>
-              The  numerical  Postfix  SMTP  server response code
-              when  a  recipient  address  is  rejected  by   the
+              The numerical Postfix  SMTP  server  response  code
+              when   a  recipient  address  is  rejected  by  the
               <a href="postconf.5.html#reject_unverified_sender">reject_unverified_sender</a> restriction.
 
        <b><a href="postconf.5.html#unverified_recipient_reject_code">unverified_recipient_reject_code</a> (450)</b>
-              The  numerical  Postfix SMTP server response when a
+              The numerical Postfix SMTP server response  when  a
               recipient address is rejected by the <a href="postconf.5.html#reject_unverified_recipient">reject_unveri</a>-
               <a href="postconf.5.html#reject_unverified_recipient">fied_recipient</a> restriction.
 
 <b>ACCESS CONTROL RESPONSES</b>
-       The  following  parameters  control  numerical  SMTP reply
+       The following  parameters  control  numerical  SMTP  reply
        codes and/or text responses.
 
        <b><a href="postconf.5.html#access_map_reject_code">access_map_reject_code</a> (554)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when  a  client  is  rejected  by  an <a href="access.5.html">access(5)</a> map
+              The  numerical  Postfix  SMTP  server response code
+              when a client  is  rejected  by  an  <a href="access.5.html">access(5)</a>  map
               restriction.
 
        <b><a href="postconf.5.html#defer_code">defer_code</a> (450)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when  a  remote  SMTP client request is rejected by
+              The  numerical  Postfix  SMTP  server response code
+              when a remote SMTP client request  is  rejected  by
               the "defer" restriction.
 
        <b><a href="postconf.5.html#invalid_hostname_reject_code">invalid_hostname_reject_code</a> (501)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when  the  client HELO or EHLO command parameter is
-              rejected by  the  <a href="postconf.5.html#reject_invalid_hostname">reject_invalid_hostname</a>  restric-
+              The  numerical  Postfix  SMTP  server response code
+              when the client HELO or EHLO command  parameter  is
+              rejected  by  the  <a href="postconf.5.html#reject_invalid_hostname">reject_invalid_hostname</a> restric-
               tion.
 
        <b><a href="postconf.5.html#maps_rbl_reject_code">maps_rbl_reject_code</a> (554)</b>
-              The  numerical  Postfix  SMTP  server response code
+              The numerical Postfix  SMTP  server  response  code
               when a remote SMTP client request is blocked by the
               <a href="postconf.5.html#reject_rbl_client">reject_rbl_client</a>,             <a href="postconf.5.html#reject_rhsbl_client">reject_rhsbl_client</a>,
               <a href="postconf.5.html#reject_rhsbl_sender">reject_rhsbl_sender</a>    or    <a href="postconf.5.html#reject_rhsbl_recipient">reject_rhsbl_recipient</a>
@@ -668,47 +672,47 @@ SMTPD(8)                                                 SMTPD(8)
 
        <b><a href="postconf.5.html#non_fqdn_reject_code">non_fqdn_reject_code</a> (504)</b>
               The numerical Postfix SMTP server reply code when a
-              client    request    is     rejected     by     the
+              client     request     is     rejected    by    the
               <a href="postconf.5.html#reject_non_fqdn_hostname">reject_non_fqdn_hostname</a>, <a href="postconf.5.html#reject_non_fqdn_sender">reject_non_fqdn_sender</a> or
               <a href="postconf.5.html#reject_non_fqdn_recipient">reject_non_fqdn_recipient</a> restriction.
 
        <b><a href="postconf.5.html#reject_code">reject_code</a> (554)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when  a  remote  SMTP client request is rejected by
+              The  numerical  Postfix  SMTP  server response code
+              when a remote SMTP client request  is  rejected  by
               the "<b>reject</b>" restriction.
 
        <b><a href="postconf.5.html#relay_domains_reject_code">relay_domains_reject_code</a> (554)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when   a   client   request   is  rejected  by  the
+              The  numerical  Postfix  SMTP  server response code
+              when  a  client  request   is   rejected   by   the
               <a href="postconf.5.html#reject_unauth_destination">reject_unauth_destination</a> recipient restriction.
 
        <b><a href="postconf.5.html#unknown_address_reject_code">unknown_address_reject_code</a> (450)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when  a  sender or recipient address is rejected by
+              The  numerical  Postfix  SMTP  server response code
+              when a sender or recipient address is  rejected  by
               the         <a href="postconf.5.html#reject_unknown_sender_domain">reject_unknown_sender_domain</a>         or
               <a href="postconf.5.html#reject_unknown_recipient_domain">reject_unknown_recipient_domain</a> restriction.
 
        <b><a href="postconf.5.html#unknown_client_reject_code">unknown_client_reject_code</a> (450)</b>
-              The  numerical  Postfix  SMTP  server response code
-              when a client without valid address &lt;=&gt;  name  map-
-              ping   is  rejected  by  the  <a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a>
+              The numerical Postfix  SMTP  server  response  code
+              when  a  client without valid address &lt;=&gt; name map-
+              ping  is  rejected  by  the   <a href="postconf.5.html#reject_unknown_client">reject_unknown_client</a>
               restriction.
 
        <b><a href="postconf.5.html#unknown_hostname_reject_code">unknown_hostname_reject_code</a> (450)</b>
-              The numerical Postfix  SMTP  server  response  code
-              when  the  hostname specified with the HELO or EHLO
-              command is rejected by the  <a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a>
+              The  numerical  Postfix  SMTP  server response code
+              when the hostname specified with the HELO  or  EHLO
+              command  is rejected by the <a href="postconf.5.html#reject_unknown_hostname">reject_unknown_hostname</a>
               restriction.
 
        Available in Postfix version 2.0 and later:
 
        <b><a href="postconf.5.html#default_rbl_reply">default_rbl_reply</a> (see 'postconf -d' output)</b>
-              The  default  SMTP  server  response template for a
-              request that is rejected by an  RBL-based  restric-
+              The default SMTP server  response  template  for  a
+              request  that  is rejected by an RBL-based restric-
               tion.
 
        <b><a href="postconf.5.html#multi_recipient_bounce_reject_code">multi_recipient_bounce_reject_code</a> (550)</b>
-              The  numerical  Postfix  SMTP  server response code
+              The numerical Postfix  SMTP  server  response  code
               when a remote SMTP client request is blocked by the
               <a href="postconf.5.html#reject_multi_recipient_bounce">reject_multi_recipient_bounce</a> restriction.
 
@@ -717,16 +721,16 @@ SMTPD(8)                                                 SMTPD(8)
 
 <b>MISCELLANEOUS CONTROLS</b>
        <b><a href="postconf.5.html#config_directory">config_directory</a> (see 'postconf -d' output)</b>
-              The default location of  the  Postfix  main.cf  and
+              The  default  location  of  the Postfix main.cf and
               master.cf configuration files.
 
        <b><a href="postconf.5.html#daemon_timeout">daemon_timeout</a> (18000s)</b>
-              How  much time a Postfix daemon process may take to
-              handle a request  before  it  is  terminated  by  a
+              How much time a Postfix daemon process may take  to
+              handle  a  request  before  it  is  terminated by a
               built-in watchdog timer.
 
        <b><a href="postconf.5.html#command_directory">command_directory</a> (see 'postconf -d' output)</b>
-              The  location  of  all  postfix administrative com-
+              The location of  all  postfix  administrative  com-
               mands.
 
        <b><a href="postconf.5.html#double_bounce_sender">double_bounce_sender</a> (double-bounce)</b>
@@ -747,36 +751,36 @@ SMTPD(8)                                                 SMTPD(8)
               and most Postfix daemon processes.
 
        <b><a href="postconf.5.html#max_idle">max_idle</a> (100s)</b>
-              The  maximum  amount  of  time that an idle Postfix
-              daemon process waits for the next  service  request
+              The maximum amount of time  that  an  idle  Postfix
+              daemon  process  waits for the next service request
               before exiting.
 
        <b><a href="postconf.5.html#max_use">max_use</a> (100)</b>
-              The  maximal number of connection requests before a
+              The maximal number of connection requests before  a
               Postfix daemon process terminates.
 
        <b><a href="postconf.5.html#myhostname">myhostname</a> (see 'postconf -d' output)</b>
               The internet hostname of this mail system.
 
        <b><a href="postconf.5.html#mynetworks">mynetworks</a> (see 'postconf -d' output)</b>
-              The list of "trusted" SMTP clients that  have  more
+              The  list  of "trusted" SMTP clients that have more
               privileges than "strangers".
 
        <b><a href="postconf.5.html#myorigin">myorigin</a> ($<a href="postconf.5.html#myhostname">myhostname</a>)</b>
               The domain name that locally-posted mail appears to
-              come from, and that locally posted mail  is  deliv-
+              come  from,  and that locally posted mail is deliv-
               ered to.
 
        <b><a href="postconf.5.html#process_id">process_id</a> (read-only)</b>
-              The  process ID of a Postfix command or daemon pro-
+              The process ID of a Postfix command or daemon  pro-
               cess.
 
        <b><a href="postconf.5.html#process_name">process_name</a> (read-only)</b>
-              The process name of a  Postfix  command  or  daemon
+              The  process  name  of  a Postfix command or daemon
               process.
 
        <b><a href="postconf.5.html#queue_directory">queue_directory</a> (see 'postconf -d' output)</b>
-              The  location of the Postfix top-level queue direc-
+              The location of the Postfix top-level queue  direc-
               tory.
 
        <b><a href="postconf.5.html#recipient_delimiter">recipient_delimiter</a> (empty)</b>
@@ -784,22 +788,22 @@ SMTPD(8)                                                 SMTPD(8)
               sions (user+foo).
 
        <b><a href="postconf.5.html#smtpd_banner">smtpd_banner</a> ($<a href="postconf.5.html#myhostname">myhostname</a> ESMTP $<a href="postconf.5.html#mail_name">mail_name</a>)</b>
-              The  text  that  follows the 220 status code in the
+              The text that follows the 220 status  code  in  the
               SMTP greeting banner.
 
        <b><a href="postconf.5.html#syslog_facility">syslog_facility</a> (mail)</b>
               The syslog facility of Postfix logging.
 
        <b><a href="postconf.5.html#syslog_name">syslog_name</a> (postfix)</b>
-              The mail system name that is prepended to the  pro-
+              The  mail system name that is prepended to the pro-
               cess  name  in  syslog  records,  so  that  "smtpd"
               becomes, for example, "postfix/smtpd".
 
        Available in Postfix version 2.2 and later:
 
        <b><a href="postconf.5.html#smtpd_forbidden_commands">smtpd_forbidden_commands</a> (CONNECT, GET, POST)</b>
-              List of  commands  that  causes  the  Postfix  SMTP
-              server  to immediately terminate the session with a
+              List  of  commands  that  causes  the  Postfix SMTP
+              server to immediately terminate the session with  a
               221 code.
 
 <b>SEE ALSO</b>
@@ -826,7 +830,7 @@ SMTPD(8)                                                 SMTPD(8)
        <a href="XFORWARD_README.html">XFORWARD_README</a>, Postfix XFORWARD extension
 
 <b>LICENSE</b>
-       The  Secure  Mailer  license must be distributed with this
+       The Secure Mailer license must be  distributed  with  this
        software.
 
 <b>AUTHOR(S)</b>
index 3065eab80e437a789eaa1b5b92d657aae2bb7121..42a0528e866790c6283d0b943e0d331f199a123b 100644 (file)
@@ -125,6 +125,9 @@ case "$SYSTEM.$RELEASE" in
                # Use the native compiler by default
                : ${CC=cc}
                : ${DEBUG="-g3"}
+               case $RELEASE in
+               V[0-4].*) CCARGS="$CCARGS -DNO_IPV6";;
+               esac
                ;;
     SunOS.4*)  SYSTYPE=SUNOS4
                SYSLIBS=-lresolv
@@ -132,14 +135,17 @@ case "$SYSTEM.$RELEASE" in
     SunOS.5*)  SYSTYPE=SUNOS5
                RANLIB=echo
                SYSLIBS="-lresolv -lsocket -lnsl"
+               # Solaris 8 added usleep() and POSIX regular expressions
                case $RELEASE in
-                   5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP";;
-                         *) CCARGS="$CCARGS -DHAS_POSIX_REGEXP";;
+                   5.[0-4]) CCARGS="$CCARGS -DMISSING_USLEEP -DNO_POSIX_REGEXP";;
+               esac
+               # Solaris 8 added IPv6
+               case $RELEASE in
+                   5.[0-7]) CCARGS="$CCARGS -DNO_IPV6";;
                esac
-               CCARGS="$CCARGS -DCANT_WRITE_BEFORE_SENDING_FD"
                # Solaris 9 added closefrom()
                case $RELEASE in
-                   5.9*|5.[1-9][0-9]*) CCARGS="$CCARGS -DHAS_CLOSEFROM";;
+                   5.[0-8]) CCARGS="$CCARGS -DNO_CLOSEFROM";;
                esac
                # Work around broken str*casecmp(). Do it all here instead
                # of having half the solution in the sys_defs.h file.
@@ -236,6 +242,9 @@ case "$SYSTEM.$RELEASE" in
                        }
                    done
                done
+               case "$RELEASE" in
+               2.[0-3].*) CCARGS="$CCARGS -DNO_IPV6";;
+               esac
                ;;
      IRIX*.5.*)        SYSTYPE=IRIX5
                # Use the native compiler by default
@@ -280,8 +289,10 @@ Rhapsody.5*|Darwin.*)
                : ${CC=cc}
                case $RELEASE in
                 1.[0-3]) AWK=gawk
+                         CCARGS="$CCARGS -DNO_IPV6"
                          ;;
                 [2-6].*) AWK=awk
+                         CCARGS="$CCARGS -DNO_IPV6"
                          SYSLIBS=-flat_namespace
                          ;;
                       *) AWK=awk
index c5af918020662eb2323a3d9adaf4736e4470fcee..682fd4585a00f222d2abcf91d9686e62dfb1fc55 100644 (file)
@@ -57,7 +57,9 @@ attempt will be made until the mail is taken off hold.
 .RE
 .IP "\fB-s \fIsite\fR"
 Schedule immediate delivery of all mail that is queued for the named
-\fIsite\fR. The site must be eligible for the "fast flush" service.
+\fIsite\fR. A numerical site must be specified as a valid RFC 2821
+address literal enclosed in [], just like in email addresses.
+The site must be eligible for the "fast flush" service.
 See \fBflush\fR(8) for more information about the "fast flush"
 service.
 
index d80b28080d5c8f3058e28b2f52bad0e453852d2f..07f6ad0e522974e2e4374e8bcb0e8aba6c3f5ce7 100644 (file)
@@ -9,10 +9,10 @@ multi-threaded QMQP test server
 .na
 .nf
 .fi
-\fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
+\fBqmqp-sink\fR [\fB-46cv\fR] [\fB-x \fItime\fR]
 [\fBinet:\fR][\fIhost\fR]:\fIport\fR \fIbacklog\fR
 
-\fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
+\fBqmqp-sink\fR [\fB-46cv\fR] [\fB-x \fItime\fR]
 \fBunix:\fR\fIpathname\fR \fIbacklog\fR
 .SH DESCRIPTION
 .ad
@@ -21,9 +21,16 @@ multi-threaded QMQP test server
 It receives messages from the network and throws them away.
 The purpose is to measure QMQP client performance, not protocol
 compliance.
-Connections can be accepted on IPV4 endpoints or UNIX-domain sockets.
-IPV4 is the default.
+Connections can be accepted on IPv4 or IPv6 endpoints, or on
+UNIX-domain sockets.
+IPv4 and IPv6 are the default.
 This program is the complement of the \fBqmqp-source\fR(1) program.
+.IP \fB-4\fR
+Support IPv4 only. This option has no effect when
+Postfix is built without IPv6 support.
+.IP \fB-6\fR
+Support IPv6 only. This option is not available when
+Postfix is built without IPv6 support.
 .IP \fB-c\fR
 Display a running counter that is updated whenever a delivery
 is completed.
index 8c09df5c7bbc34f90b9a969768a77a1e70fedc20..31455c45db2e58274b6b28918934c82cdc3f3294 100644 (file)
@@ -18,10 +18,16 @@ multi-threaded QMQP test generator
 \fBqmqp-source\fR connects to the named host and TCP port (default 628)
 and sends one or more messages to it, either sequentially
 or in parallel. The program speaks the QMQP protocol.
-Connections can be made to UNIX-domain and IPV4 servers.
-IPV4 is the default.
+Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
+IPv4 and IPv6 are the default.
 
 Options:
+.IP \fB-4\fR
+Connect to the server with IPv4. This option has no effect when
+Postfix is built without IPv6 support.
+.IP \fB-6\fR
+Connect to the server with IPv6. This option is not available when
+Postfix is built without IPv6 support.
 .IP \fB-c\fR
 Display a running counter that is incremented each time
 a delivery completes.
index f82837eeb375b9dfd8dc2ab66ed14173fff6032a..f35a4529bfb79ab479770249ee5c78d52620f394 100644 (file)
@@ -125,6 +125,8 @@ Backwards compatibility.
 Non-default alias database. Specify \fIpathname\fR or
 \fItype\fR:\fIpathname\fR. See \fBpostalias\fR(1) for
 details.
+.IP "\fB-O \fIoption=value\fR (ignored)"
+Backwards compatibility.
 .IP "\fB-o7\fR (ignored)"
 .IP "\fB-o8\fR (ignored)"
 To send 8-bit or binary content, use an appropriate MIME encapsulation
index 6b1262dca257e832598462e752be5c6b56aa6eb3..0a2ac75755278ae7978588ebab91cc32c0484d9c 100644 (file)
@@ -21,11 +21,18 @@ It takes SMTP messages from the network and throws them away.
 The purpose is to measure client performance, not protocol
 compliance.
 
-Connections can be accepted on IPV4 endpoints or UNIX-domain sockets.
-IPV4 is the default.
+Connections can be accepted on IPv4 or IPv6 endpoints, or on
+UNIX-domain sockets.
+IPv4 and IPv6 are the default.
 This program is the complement of the \fBsmtp-source\fR(1) program.
 
 Arguments:
+.IP \fB-4\fR
+Support IPv4 only. This option has no effect when
+Postfix is built without IPv6 support.
+.IP \fB-6\fR
+Support IPv6 only. This option is not available when
+Postfix is built without IPv6 support.
 .IP \fB-a\fR
 Do not announce SASL authentication support.
 .IP \fB-c\fR
index 7ecff03518cc4e6b31eaf8b3870fdd7e8a30f427..2b588bdd27338f3a93bfa5652a435873a655ed04 100644 (file)
@@ -19,10 +19,17 @@ multi-threaded SMTP/LMTP test generator
 (default: port 25)
 and sends one or more messages to it, either sequentially
 or in parallel. The program speaks either SMTP (default) or
-LMTP. Connections can be made to UNIX-domain and IPV4 servers.
-IPV4 is the default.
+LMTP.
+Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
+IPv4 and IPv6 are the default.
 
 Arguments:
+.IP \fB-4\fR
+Connect to the server with IPv4. This option has no effect when
+Postfix is built without IPv6 support.
+.IP \fB-6\fR
+Connect to the server with IPv6. This option is not available when
+Postfix is built without IPv6 support.
 .IP \fB-c\fR
 Display a running counter that is incremented each time
 an SMTP DATA command completes.
index 57e90dcdc32078d79408d9ae1c4d0d84b4c75f26..5a4c816aa9a9578269db149ef99a34a2c0b3d42f 100644 (file)
@@ -19,7 +19,7 @@ format of Postfix access table
 The optional \fBaccess\fR table directs the Postfix SMTP server
 to selectively reject or accept mail. Access can be allowed or
 denied for specific host names, domain names, networks, host
-network addresses or mail addresses.
+addresses or mail addresses.
 
 For an example, see the EXAMPLE section at the end of this
 manual page.
@@ -110,11 +110,46 @@ order to match subdomains.
 .IP \fInet.work.addr\fR
 .IP \fInet.work\fR
 .IP \fInet\fR
-Matches any host address in the specified network. A network
-address is a sequence of one or more octets separated by ".".
+Matches the specified IPv4 host address or subnetwork. An
+IPv4 host address is a sequence of four decimal octets
+separated by ".".
 
-NOTE: use the \fBcidr\fR lookup table type to specify
+Subnetworks are matched by repeatedly truncating the last
+".octet" from the remote IPv4 host address string until a
+match is found in the access table, or until further
+truncation is not possible.
+
+NOTE 1: The information in the access map should be in
+canonical form, with unnecessary null characters eliminated.
+Address information must not be enclosed with "[]" characters.
+
+NOTE 2: use the \fBcidr\fR lookup table type to specify
 network/netmask patterns. See cidr_table(5) for details.
+.IP \fInet:work:addr:ess\fR
+.IP \fInet:work:addr\fR
+.IP \fInet:work\fR
+.IP \fInet\fR
+Matches the specified IPv6 host address or subnetwork. An
+IPv6 host address is a sequence of three to eight hexadecimal
+octet pairs separated by ":".
+
+Subnetworks are matched by repeatedly truncating the last
+":octetpair" from the remote IPv6 host address string until
+a match is found in the access table, or until further
+truncation is not possible.
+
+NOTE 1: the truncation and comparison are done with the
+string representation of the IPv6 host address. Thus, not
+all the ":" subnetworks will be tried.
+
+NOTE 2: The information in the access map should be in
+canonical form, with unnecessary null characters eliminated.
+Address information must not be enclosed with "[]" characters.
+
+NOTE 3: use the \fBcidr\fR lookup table type to specify
+network/netmask patterns. See cidr_table(5) for details.
+
+IPv6 support is available in Postfix 2.2 and later.
 .SH "ACCEPT ACTIONS"
 .na
 .nf
index ae6ef06cc2c1b31bd0b849a24c21b7820faacd67..7428a468deb1ec9f2894df4cdae1db3d97c5bf44 100644 (file)
@@ -33,7 +33,13 @@ The general form of a Postfix CIDR table is:
 .IP "\fInetwork_address\fB/\fInetwork_mask     result\fR"
 When a search string matches the specified network block,
 use the corresponding \fIresult\fR value. Specify
-0.0.0.0/0 to match every address.
+0.0.0.0/0 to match every IPv4 address, and ::/0 to match
+every IPv6 address.
+
+Note: address information may be enclosed inside "[]" but
+this form is not recommended.
+
+IPv6 support is available in Postfix 2.2 and later.
 .IP "\fInetwork_address     result\fR"
 When a search string matches the specified network address,
 use the corresponding \fIresult\fR value.
index 3e1559eed24d06200f5ff5d845332e1129bd2ce4..01dd03408a97564ae751f5f3a56cce3a03d1fecf 100644 (file)
@@ -461,6 +461,12 @@ pattern is replaced by its contents; a "type:table" lookup table
 is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.
+.PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the authorized_verp_clients value, and in files
+specified with "/file/name".  IP version 6 addresses contain the
+":" character, and would otherwise be confused with a "type:table"
+pattern.
 .SH backwards_bounce_logfile_compatibility (default: yes)
 Produce additional bounce(8) logfile records that can be read by
 older Postfix versions. The current and more extensible "name =
@@ -1191,10 +1197,16 @@ the hash_queue_names parameter.
 .PP
 After changing the hash_queue_names or hash_queue_depth parameter,
 execute the command "\fBpostfix reload\fR".
-.SH hash_queue_names (default: see "postconf -d" output)
+.SH hash_queue_names (default: deferred, defer)
 The names of queue directories that are split across multiple
 subdirectory levels.
 .PP
+Before Postfix version 2.2, the default list of hashed queues
+was significantly larger. Claims about improvements in file system
+technology suggest that hashing of the incoming and active queues
+is no longer needed. Fewer hashed directories speed up the time
+needed to restart Postfix.
+.PP
 After changing the hash_queue_names or hash_queue_depth parameter,
 execute the command "\fBpostfix reload\fR".
 .SH header_address_token_limit (default: 10240)
@@ -1276,32 +1288,93 @@ number of messages delivered per second.
 .PP
 Specify 0 to disable the feature. Valid delays are 0..10.
 .SH inet_interfaces (default: all)
-The network interface addresses that this mail system receives mail
-on.  By default, the software claims all active interfaces on the
-machine. The parameter also controls delivery of mail to
-user@[ip.address].
+The network interface addresses that this mail system receives
+mail on.  By default, the software claims all active interfaces on
+the machine; with Postfix 2.2 and later, specify "\fBloopback-only\fR"
+to select only local interfaces.  The parameter also controls
+delivery of mail to user@[ip.address].
 .PP
-When inet_interfaces consists of just one IP address that is not a
-loopback (net 127) address, the Postfix SMTP client will use this address
-as the IP source address for outbound mail.
+Note: you need to stop and start Postfix when this parameter changes.
+.PP
+When inet_interfaces specifies just one IPv4 and/or IPv6 address
+that is not a loopback address, the Postfix SMTP client will use
+this address as the IP source address for outbound mail.
 .PP
 On a multi-homed firewall with separate Postfix instances listening on the
 "inside" and "outside" interfaces, this can prevent each instance from
 being able to reach servers on the "other side" of the firewall. Setting
-smtp_bind_address to 0.0.0.0 avoids the potential problem.
+smtp_bind_address to 0.0.0.0 avoids the potential problem for
+IPv4, and setting smtp_bind_address6 to :: solves the problem
+for IPv6.
 .PP
-A better solution is to leave inet_interfaces at the default value
+A better solution for multi-homed firewalls is to leave inet_interfaces
+at the default value
 and instead use explicit IP addresses in master.cf. This preserves SMTP
 loop detection, by ensuring that each side of the firewall knows that the
 other IP address is still the same host. Setting $inet_interfaces to a
-single IP address is primarily useful with virtual hosting of domains on
+single IPv4 and/or IPV6 address is primarily useful with virtual
+hosting of domains on
 secondary IP addresses, when each IP address serves a different domain
 (and has a different $myhostname setting).
 .PP
 See also the proxy_interfaces parameter, for network addresses that
-are forwarded to us by way of a proxy or address translator.
+are forwarded to Postfix by way of a proxy or address translator.
 .PP
-Note: you need to stop and start Postfix when this parameter changes.
+Examples:
+.PP
+.nf
+.na
+.ft C
+inet_interfaces = all (DEFAULT)
+inet_interfaces = loopback-only
+inet_interfaces = 127.0.0.1
+inet_interfaces = 192.168.1.2, 127.0.0.1
+.fi
+.ad
+.ft R
+.SH inet_protocols (default: ipv4)
+The Internet protocols Postfix will attempt to use when making
+or accepting connections. Specify one or more of "ipv4" or "ipv6",
+separated by whitespace or commas. The form "all" is equivalent to
+"ipv4, ipv6".
+.PP
+Note: you MUST stop and start Postfix after changing this
+parameter.
+.PP
+On systems that pre-date IPV6_V6ONLY support (RFC 3493), an
+IPv6 server will also accept IPv4 connections, even when IPv4 is
+turned off with the inet_protocols parameter.  On systems with
+IPV6_V6ONLY support, Postfix will use separate server sockets for
+IPv6 and IPv4, and each will accept only connections for the
+corresponding protocol.
+.PP
+When IPv4 support is enabled via the inet_protocols parameter,
+Postfix will to DNS type A record lookups, and will convert
+IPv4-in-IPv6 client IP addresses (::ffff:1.2.3.4) to their original
+IPv4 form (1.2.3.4).  The latter is needed on hosts that pre-date
+IPV6_V6ONLY support (RFC 3493).
+.PP
+When IPv6 support is enabled via the inet_protocols parameter,
+Postfix will do DNS type AAAA record lookups.
+.PP
+When both IPv4 and IPv6 support are enabled, the Postfix SMTP
+client will attempt to connect via IPv6 before attempting to use
+IPv4.
+.PP
+This feature is available in Postfix version 2.2 and later.
+.PP
+Examples:
+.PP
+.nf
+.na
+.ft C
+inet_protocols = ipv4 (DEFAULT)
+inet_protocols = all
+inet_protocols = ipv6
+inet_protocols = ipv4, ipv6
+.fi
+.ad
+.ft R
 .SH initial_destination_concurrency (default: 5)
 The initial per-destination concurrency level for parallel delivery
 to the same destination. This limit applies to delivery via smtp(8),
@@ -2150,13 +2223,19 @@ The list is matched left to right, and the search stops on the
 first match.  Specify "!pattern" to exclude an address or network
 block from the list.
 .PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the mynetworks value, and in files specified with
+"/file/name".  IP version 6 addresses contain the ":" character,
+and would otherwise be confused with a "type:table" pattern.
+.PP
 Examples:
 .PP
 .nf
 .na
 .ft C
-mynetworks = 168.100.189.0/28, 127.0.0.0/8
+mynetworks = 127.0.0.0/8 168.100.189.0/28
 mynetworks = !192.168.0.1, 192.168.0.0/28
+mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:5c7::]/64
 mynetworks = $config_directory/mynetworks
 mynetworks = hash:/etc/postfix/network_table
 .fi
@@ -2924,7 +3003,7 @@ the word "ESMTP" appears in the server greeting banner (example:
 220 spike.porcupine.org ESMTP Postfix).
 .SH smtp_bind_address (default: empty)
 An optional numerical network address that the SMTP client should
-bind to when making a connection.
+bind to when making an IPv4 connection.
 .PP
 This can be specified in the main.cf file for all SMTP clients, or
 it can be specified in the master.cf file for a specific client,
@@ -2939,11 +3018,41 @@ for example:
 .ad
 .ft R
 .PP
-Note: when inet_interfaces specifies exactly one address that
-is a non-loopback address, it is automatically used as the
-smtp_bind_address.  This supports virtual IP hosting, but can be
-a problem on multi-homed firewalls. See the inet_interfaces
-documentation for more detail.
+Note 1: when inet_interfaces specifies no more than one IPv4
+address, and that address is a non-loopback address, it is
+automatically used as the smtp_bind_address.  This supports virtual
+IP hosting, but can be a problem on multi-homed firewalls. See the
+inet_interfaces documentation for more detail.
+.PP
+Note 2: address information may be enclosed inside <tt>[]</tt>,
+but this form is not recommended.
+.SH smtp_bind_address6 (default: empty)
+An optional numerical network address that the SMTP client should
+bind to when making an IPv6 connection.
+.PP
+This can be specified in the main.cf file for all SMTP clients, or
+it can be specified in the master.cf file for a specific client,
+for example:
+.PP
+.nf
+.na
+.ft C
+  /etc/postfix/master.cf:
+        smtp ... smtp -o smtp_bind_address6=1:2:3:4:5:6:7:8
+.fi
+.ad
+.ft R
+.PP
+Note 1: when inet_interfaces specifies no more than one IPv6
+address, and that address is a non-loopback address, it is
+automatically used as the smtp_bind_address6.  This supports virtual
+IP hosting, but can be a problem on multi-homed firewalls. See the
+inet_interfaces documentation for more detail.
+.PP
+Note 2: address information may be enclosed inside <tt>[]</tt>,
+but this form is not recommended.
+.PP
+This feature is available in Postfix version 2.2 and later.
 .SH smtp_connect_timeout (default: 30s)
 The SMTP client time limit for completing a TCP connection, or
 zero (use the operating system built-in time limit).
@@ -3321,6 +3430,12 @@ pattern is replaced by its contents; a "type:table" lookup table
 is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.
+.PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_authorized_verp_clients value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.
 .SH smtpd_authorized_xclient_hosts (default: empty)
 What SMTP clients are allowed to use the XCLIENT feature.  This
 command overrides SMTP client information that is used for access
@@ -3341,6 +3456,12 @@ pattern is replaced by its contents; a "type:table" lookup table
 is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.
+.PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_authorized_xclient_hosts value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.
 .SH smtpd_authorized_xforward_hosts (default: empty)
 What SMTP clients are allowed to use the XFORWARD feature.  This
 command forwards information that is used to improve logging after
@@ -3360,6 +3481,12 @@ pattern is replaced by its contents; a "type:table" lookup table
 is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.
+.PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_authorized_xforward_hosts value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.
 .SH smtpd_banner (default: $myhostname ESMTP $mail_name)
 The text that follows the 220 status code in the SMTP greeting
 banner. Some people like to see the mail version advertised. By
@@ -3420,6 +3547,12 @@ By default, clients in trusted networks are excluded. Specify a
 list of network blocks, hostnames or .domain names (the initial
 dot causes the domain to match any name below it).
 .PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_client_event_limit_exceptions value, and
+in files specified with "/file/name".  IP version 6 addresses
+contain the ":" character, and would otherwise be confused with a
+"type:table" pattern.
+.PP
 This feature is available in Postfix 2.2 and later.
 .SH smtpd_client_message_rate_limit (default: 0)
 The maximal number of message delivery requests that any client is
@@ -4140,6 +4273,12 @@ contents; a "type:table" lookup table is matched when a table entry
 matches a lookup string (the lookup result is ignored).  Continue
 long lines by starting the next line with whitespace.
 .PP
+Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_sasl_exceptions_networks value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.
+.PP
 Example:
 .PP
 .nf
@@ -4766,7 +4905,7 @@ virtual(8) delivery agent will terminate with a fatal error.
 Optional lookup tables with a) names of domains for which all
 addresses are aliased to addresses in other local or remote domains,
 and b) addresses that are aliased to addresses in other local or
-remote domains.  Available before Postfix version 2.0. With Postfix 2.1
+remote domains.  Available before Postfix version 2.0. With Postfix 2.0
 and later, this is replaced by separate controls: virtual_alias_domains
 and virtual_alias_maps.
 .SH virtual_minimum_uid (default: 100)
index 399f0a47c9f5e1fdcf5421b7aac73eadbb330022..6812e568ac067d8f5bfdce166dbdbf07e6536f54 100644 (file)
@@ -92,9 +92,6 @@ Use the \fBpostfix reload\fR command after a configuration change.
 .nf
 .ad
 .fi
-.IP "\fBdaemon_timeout (18000s)\fR"
-How much time a Postfix daemon process may take to handle a
-request before it is terminated by a built-in watchdog timer.
 .IP "\fBdefault_process_limit (100)\fR"
 The default maximal number of Postfix child processes that provide
 a given service.
@@ -123,6 +120,9 @@ invoked with the -D option.
 .IP "\fBinet_interfaces (all)\fR"
 The network interface addresses that this mail system receives mail
 on.
+.IP "\fBinet_protocols (ipv4)\fR"
+The Internet protocols Postfix will attempt to use when making
+or accepting connections.
 .IP "\fBimport_environment (see 'postconf -d' output)\fR"
 The list of environment parameters that a Postfix process will
 import from a non-Postfix parent process.
index ab485206f731097f613fe0f7cd5c4be1ed40bea0..52f3d570139a6612b286bfc861d7617dfcdc37a7 100644 (file)
@@ -65,7 +65,7 @@ The name of a mail delivery transport that filters mail after
 it is queued.
 .IP "\fBreceive_override_options (empty)\fR"
 Enable or disable recipient validation, built-in content
-filtering, or address rewriting.
+filtering, or address mapping.
 .SH "RESOURCE AND RATE CONTROLS"
 .na
 .nf
index 806325d560057c7356079ed2159c3622fa39770e..303b11d944d31ef94b0553ecfb8f7fd531989cd2 100644 (file)
@@ -279,8 +279,11 @@ Disable DNS lookups in the Postfix SMTP and LMTP clients.
 Optional list of relay hosts for SMTP destinations that can't be
 found or that are unreachable.
 .IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives mail
-on.
+The network interface addresses that this mail system receives
+mail on.
+.IP "\fBinet_protocols (ipv4)\fR"
+The Internet protocols Postfix will attempt to use when making
+or accepting connections.
 .IP "\fBipc_timeout (3600s)\fR"
 The time limit for sending or receiving information over an internal
 communication channel.
@@ -299,7 +302,10 @@ The network interface addresses that this mail system receives mail
 on by way of a proxy or network address translation unit.
 .IP "\fBsmtp_bind_address (empty)\fR"
 An optional numerical network address that the SMTP client should
-bind to when making a connection.
+bind to when making an IPv4 connection.
+.IP "\fBsmtp_bind_address6 (empty)\fR"
+An optional numerical network address that the SMTP client should
+bind to when making an IPv6 connection.
 .IP "\fBsmtp_helo_name ($myhostname)\fR"
 The hostname to send in the SMTP EHLO or HELO command.
 .IP "\fBsmtp_host_lookup (dns)\fR"
index bc774a3ffe3ca1292ae555a901846c84043bae53..5a37a5c3d9b8466a296ca8358da92bbe869d54e4 100644 (file)
@@ -290,11 +290,14 @@ Parameters concerning known/unknown local recipients:
 The list of domains that are delivered via the $local_transport
 mail delivery transport.
 .IP "\fBinet_interfaces (all)\fR"
-The network interface addresses that this mail system receives mail
-on.
+The network interface addresses that this mail system receives
+mail on.
 .IP "\fBproxy_interfaces (empty)\fR"
 The network interface addresses that this mail system receives mail
 on by way of a proxy or network address translation unit.
+.IP "\fBinet_protocols (ipv4)\fR"
+The Internet protocols Postfix will attempt to use when making
+or accepting connections.
 .IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR"
 Lookup tables with all names or addresses of local recipients:
 a recipient address is local when its domain matches $mydestination,
index 83e1550b3da50256644f4b88d752b6a38132e1e9..3573a6dc8f32c5ef52dcc52c52ce0bc8b5390962 100755 (executable)
@@ -17,7 +17,7 @@ TMPF=/tmp/ccformat.$$
 ERROR=
 TROFF=
 BCK=
-FLAGS="-st -di8 -npsl -bap -bad -bbb -bc -i4 -d0 -nip -nfc1 -cd41 -c49"
+FLAGS="-st -di8 -npsl -bap -bad -bbb -nbc -i4 -d0 -nip -nfc1 -cd41 -c49"
 
 trap 'rm -f .ind.$$ $TMPF; exit 1' 1 2 3 15
 
index e6a063d9005814a083c41f238cd50e11edd70bd2..de066c1e01d7f985ecefc4f30868dbfec16d9300 100755 (executable)
@@ -4,7 +4,7 @@ sed '
        s/<\/*table[^>]*>//g
        s/<\/th[^>]*>//g
        s/<\/td[^>]*>//g
-       s/"\([A-Z_]*\)\.html">/&\1:/
+       s/"\([A-Z0-9_]*\)\.html">/&\1:/
        s/All main.cf parameters/postconf(5): &/
        /All Postfix manual pages/d
 ' "$@"
index 86fce3dcb10670a0df30e7c3c886f4cf7fe250b6..fcb5bda729829ef7b09621ccd3b21e79809a0315 100755 (executable)
@@ -181,6 +181,7 @@ while (<>) {
     s;\bimport_environment\b;<a href="postconf.5.html#import_environment">$&</a>;g;
     s;\bin_flow_delay\b;<a href="postconf.5.html#in_flow_delay">$&</a>;g;
     s;\binet_interfaces\b;<a href="postconf.5.html#inet_interfaces">$&</a>;g;
+    s;\binet_protocols\b;<a href="postconf.5.html#inet_protocols">$&</a>;g;
     s;\binitial_destination_concurrency\b;<a href="postconf.5.html#initial_destination_concurrency">$&</a>;g;
     s;\binvalid_hostname_reject_code\b;<a href="postconf.5.html#invalid_hostname_reject_code">$&</a>;g;
     s;\bipc_idle\b;<a href="postconf.5.html#ipc_idle">$&</a>;g;
@@ -310,6 +311,7 @@ while (<>) {
     s;\bshowq_service_name\b;<a href="postconf.5.html#showq_service_name">$&</a>;g;
     s;\bsmtp_always_send_ehlo\b;<a href="postconf.5.html#smtp_always_send_ehlo">$&</a>;g;
     s;\bsmtp_bind_address\b;<a href="postconf.5.html#smtp_bind_address">$&</a>;g;
+    s;\bsmtp_bind_address6\b;<a href="postconf.5.html#smtp_bind_address6">$&</a>;g;
     s;\bsmtp_connect_timeout\b;<a href="postconf.5.html#smtp_connect_timeout">$&</a>;g;
 
     s;\bsmtp_connection_cache_on_demand\b;<a href="postconf.5.html#smtp_connection_cache_on_demand">$&</a>;g;
index 05361073422d6914bc1439aaf686b8849922a123..b3820ddc20c8b7f9bb070cf8fe2913cbadafde1d 100755 (executable)
@@ -40,7 +40,6 @@ execution_directory_expansion_filter
 export_environment
 forward_expansion_filter
 forward_path
-hash_queue_names
 html_directory
 import_environment
 mail_release_date
index e2e4109276c7f63a90e9ee19df5d8e66e64e4d71..cdd9e5dfc01da414ac1fef3216ae1a38b79fb3ea 100644 (file)
@@ -802,7 +802,7 @@ content filtering turned on. </p>
     #                   (yes)   (yes)   (yes)   (never) (100)
     # =================================================================
     1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
-        -o content_filter=foo:bar 
+        -o content_filter=filter-service:filter-destination 
         -o receive_override_options=no_address_mappings
 </pre>
 
@@ -828,14 +828,14 @@ address provides a different content filter service. </p>
     # service     type  private unpriv  chroot  wakeup  maxproc command
     #                   (yes)   (yes)   (yes)   (never) (100)
     # =================================================================
-    # SMTP service for domains that are content filtered with foo:bar
+    # SMTP service for domains that are filtered with service1:dest1
     1.2.3.4:smtp  inet  n       -       n       -       -       smtpd
-        -o content_filter=foo:bar 
+        -o content_filter=service1:dest1 
         -o receive_override_options=no_address_mappings
 
-    # SMTP service for domains that are content filtered with xxx:yyy
+    # SMTP service for domains that are filtered with service2:dest2
     1.2.3.5:smtp  inet  n       -       n       -       -       smtpd
-        -o content_filter=xxx:yyy 
+        -o content_filter=service2:dest2
         -o receive_override_options=no_address_mappings
 </pre>
 </blockquote>
diff --git a/postfix/proto/IPV6_README.html b/postfix/proto/IPV6_README.html
new file mode 100644 (file)
index 0000000..88cf580
--- /dev/null
@@ -0,0 +1,370 @@
+<!doctype html public "-//W3C//DTD HTML 4.01 Transitional//EN"
+        "http://www.w3.org/TR/html4/loose.dtd">
+
+<html>
+
+<head>
+
+<title>Postfix IPv6 Support</title>
+
+<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
+
+</head>
+
+<body>
+
+<h1><img src="postfix-logo.jpg" width="203" height="98" ALT="">Postfix
+IPv6 Support</h1>
+
+<hr>
+
+<h2>Introduction</h2>
+
+<p> Postfix 2.2 introduces support for the IPv6 (IP version 6)
+protocol, whose main feature of interest is that it uses 128-bit
+IP addresses instead of the 32-bit addresses used by IPv4.  </p>
+
+<p> With this, Postfix can use the same SMTP protocol over IPv6 as
+it already uses over the older IPv4 network, and Postfix can do
+AAAA record lookups in the DNS in addition to the older A records.
+Information about IPv6 can be found at http://www.ipv6.org/. </p>
+
+<p> This document provides information on the following topics:
+</p>
+
+<ul>
+
+<li><a href="#platforms">Supported platforms</a>
+
+<li><a href="#configuration">Configuration</a>
+
+<li><a href="#limitations">Known limitations</a>
+
+<li><a href="#compat">Compatibility with Postfix &lt;2.2 IPv6 support</a>
+
+<li><a href="#porting">IPv6 Support for unsupported platforms</a>
+
+<li><a href="#credits">Credits</a>
+
+</ul>
+
+<h2><a name="platforms">Supported Platforms</a></h2>
+
+<p> Postfix version 2.2 supports IPv4 and IPv6 on the following
+platforms:  </p>
+
+<ul>
+
+<li> AIX 5.1+
+<li> Darwin 7.3+
+<li> FreeBSD 4+
+<li> Linux 2.4+
+<li> NetBSD 1.5+
+<li> OpenBSD 2+
+<li> Solaris 8+
+<li> Tru64Unix V5.1+
+
+</ul>
+
+<p> On other platforms Postfix will simply use IPv4 as it has always
+done. </p>
+
+<p> See <a href="#porting">below</a> for tips how to port Postfix
+IPv6 support to other environments.  </p>
+
+<h2><a name="configuration">Configuration</a></h2>
+
+<p> Postfix IPv6 support introduces two new main.cf configuration
+parameters, and introduces an important change in address syntax
+notation in match lists such as <tt>mynetworks</tt> or
+<tt>debug_peer_list</tt>. </p>
+
+<p> Postfix IPv6 address syntax is a little tricky, because there
+are a few places where you must enclose IPv6 address inside
+<tt>[]</tt> characters, and a few places where you must not. It is
+a good idea to use <tt>[]</tt> only in the few places where you
+have to. Check out the postconf(5) manual whenever you do IPv6
+related configuration work with Postfix.  </p>
+
+<ul>
+
+<li> <p> The new <tt>inet_protocols</tt> parameter specifies what
+IP protocols Postfix will use.  This parameter also controls what
+DNS lookups Postfix will do. </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    # You must stop/start Postfix after changing this parameter.
+    inet_protocols = ipv4       (DEFAULT: enable IPv4 only)
+    inet_protocols = all        (enable both IPv4 and IPv6)
+    inet_protocols = ipv4, ipv6 (enable both IPv4 and IPv6)
+    inet_protocols = ipv6       (enable IPv6 only)
+</pre>
+</blockquote>
+
+<p> By default, Postfix uses IPv4 only, because most systems aren't
+attached to an IPv6 network. </p>
+
+<ul>
+
+<li> <p> On systems with combined IPv4/IPv6 stacks, attempts to
+deliver mail via IPv6 would always fail with "network unreachable",
+and those attempts would only slow down Postfix. </p>
+
+<li> <p> Linux kernels don't even load IPv6 protocol support by
+default. Any attempt to use it would fail immediately. </p>
+
+</ul>
+
+<p> Note 1: you must stop and start Postfix after changing the
+<tt>inet_protocols</tt> configuration parameter. </p>
+
+<p> Note 2: if you see error messages like the following, then
+you're running Linux and need to turn on IPv6 in the kernel: see
+http://www.ipv6.org/ for hints and tips. Unlike other systems,
+Linux does not have a combined stack for IPv4 and IPv6, and IPv6
+protocol support is not loaded by default.  </p>
+
+<blockquote>
+<pre>
+postconf: warning: inet_protocols: IPv6 support is disabled: Address family not supported by protocol
+postconf: warning: inet_protocols: configuring for IPv4 support only
+</pre>
+</blockquote>
+
+<p> Note 3: on older Linux and Solaris systems, the setting
+"<tt>inet_protocols = ipv6</tt>" will not prevent Postfix from
+accepting IPv4 connections.  Postfix will present the client IP
+addresses in IPv6 format, though. In all other cases, Postfix always
+presents IPv4 client IP addresses in the traditional dotted quad
+IPv4 format.  </p>
+
+<li> <p> The other new parameter is <tt>smtp_bind_address6</tt>.
+This sets the local interface address for outgoing IPv6 SMTP
+connections, just like the <tt>smtp_bind_address</tt> parameter
+does for IPv4: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    smtp_bind_address6 = 2001:240:5c7:0:250:56ff:fe89:1
+</pre>
+</blockquote>
+
+<li> <p> If you left the value of the <tt>mynetworks</tt> parameter at its
+default (i.e. no <tt>mynetworks</tt> setting in main.cf) Postfix will figure
+out by itself what its network addresses are. This is what a typical
+setting looks like: </p>
+
+<blockquote>
+<pre>
+% postconf mynetworks
+mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [fe80::]/10 [2001:240:5c7::]/64 
+</pre>
+</blockquote>
+
+<p> If you did specify the <tt>mynetworks</tt> parameter value in
+main.cf, you need update the <tt>mynetworks</tt> value to include
+the IPv6 networks the system is in. Be sure to specify IPv6 address
+information inside <tt>[]</tt>, like this: </p>
+
+<blockquote>
+<pre>
+/etc/postfix/main.cf:
+    mynetworks = ...<i>IPv4 networks</i>... [::1]/128 [2001:240:5c7::]/64 ...
+</pre>
+</blockquote>
+
+</ul>
+
+<p> <b> NOTE: when configuring Postfix match lists such as
+<tt>mynetworks</tt> or <tt>debug_peer_list</tt>, you must specify
+IPv6 address information inside <tt>[]</tt> in the main.cf parameter
+value and in files specified with a "<i>/file/name</i>" pattern.
+IPv6 addresses contain the ":" character, and would otherwise be
+confused with a "<i>type:table</i>" pattern. </b>  </p>
+
+<h2><a name="limitations">Known Limitations</a></h2>
+
+<ul>
+
+<li> <p> The order of IPv6/IPv4 outgoing connection attempts is
+not yet configurable.  Currently, IPv6 is tried before IPv4. </p>
+
+<li> <p> Postfix currently does not support DNSBL (real-time
+blackhole list) lookups for IPv6 client IP addresses; currently
+there are no blacklists that cover the IPv6 address space. </p>
+
+<li> <p> IPv6 does not have class A, B, C, etc. networks. With IPv6
+networks, the setting "<tt>mynetworks_style = class</tt>" has the
+same effect as the setting "<tt>mynetworks_style = subnet</tt>".
+</p>
+
+<li> <p> On Tru64Unix, Postfix can't figure out the local subnet mask
+and always assumes a /128 network. This is a problem only with
+"<tt>mynetworks_style = subnet</tt>" and no explicit <tt>mynetworks</tt>
+setting in main.cf. </p>
+
+</ul>
+
+<h2> <a name="compat">Compatibility with Postfix &lt;2.2 IPv6 support</a>
+</h2>
+
+<p> Postfix version 2.2 IPv6 support is based on the Postfix/IPv6 patch
+by Dean Strik and others, but differs in a few minor ways. </p>
+
+<ul>
+
+<li> <p> main.cf: The <tt>inet_interfaces</tt> parameter does not support
+the notation  "<tt>ipv6:all</tt>" or "<tt>ipv4:all</tt>". Use the
+<tt>inet_protocols</tt> parameter instead. </p>
+
+<li> <p> main.cf: Specify "<tt>inet_protocols = all</tt>" or
+"<tt>inet_protocols = ipv4, ipv6</tt>" in order to enable both IPv4
+and IPv6 support. </p>
+
+<li> <p> main.cf: The <tt>inet_protocols</tt> parameter also controls
+what DNS lookups Postfix will attempt to make when delivering or
+receiving mail. </p>
+
+<li> <p> main.cf: Specify "<tt>inet_interfaces = loopback-only</tt>"
+to listen on loopback network interfaces only. </p>
+
+<li> <p> The <tt>lmtp_bind_address</tt> and <tt>lmtp_bind_address6</tt>
+features were omitted. The Postfix LMTP client will be absorbed
+into the SMTP client, so there is no reason to keep adding features
+to the LMTP client. </p>
+
+<li> <p> The SMTP server now requires that IPv6 addresses in SMTP
+commands are specified as <tt>[ipv6:<i>ipv6address</i>]</tt>, as
+described in RFC 2821. </p>
+
+<li> <p> The IPv6 network address matching code was rewritten from
+the ground up, and is expected to be closer to the specification.
+The result may be incompatible with the Postfix/IPv6 patch.
+</p>
+
+</ul>
+
+<h2><a name="porting">IPv6 Support for unsupported platforms</a></h2>
+
+<p> Getting Postfix IPv6 working on other platforms involves the
+following steps: </p>
+
+<ul>
+
+<li> <p> Specify how Postfix should find the local network interfaces.
+Postfix needs this information to avoid mailer loops and to find out
+if mail for <i>user@[ipaddress]</i> is a local or remote destination. </p>
+
+<p> If your system has the <tt>getifaddrs()</tt> routine then add
+the following to your platform-specific section in
+<tt>src/util/sys_defs.h</tt>:  </p>
+
+<blockquote>
+<pre>
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAVE_GETIFADDRS
+#endif
+</pre>
+</blockquote>
+
+<p> Otherwise, if your system has the SIOCGLIF <tt>ioctl()</tt>
+command in <tt>/usr/include/*/*.h</tt>, add the following to your
+platform-specific section in <tt>src/util/sys_defs.h</tt>: </p>
+
+<blockquote>
+<pre>
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAS_SIOCGLIF
+#endif
+</pre> 
+</blockquote>
+
+<p> Otherwise, Postfix will have to use the old SIOCGIF commands
+and get along with reduced IPv6 functionality (it won't be able to
+figure out your IPv6 netmasks, which are needed for "<tt>mynetworks_style
+= subnet</tt>". Add this to your platform-specific section in
+<tt>src/util/sys_defs.h</tt>: </p>
+
+<blockquote>
+<pre>
+#ifndef NO_IPV6
+# define HAS_IPV6
+#endif
+</pre> 
+</blockquote>
+
+<li> <p> Test if Postfix can figure out its interface information. </p>
+
+<p> After compiling Postfix in the usual manner, step into the
+<tt>src/util</tt> directory and type "<tt>make inet_addr_local</tt>".
+Running this file by hand should produce all the interface addresses
+and network masks, for example: </p>
+
+<blockquote>
+<pre>
+% make
+% cd src/util
+% make inet_addr_local
+[... some messages ...]
+% ./inet_addr_local
+[... some messages ...]
+./inet_addr_local: inet_addr_local: configured 2 IPv4 addresses
+./inet_addr_local: inet_addr_local: configured 4 IPv6 addresses
+168.100.189.2/255.255.255.224
+127.0.0.1/255.0.0.0
+fe80:1::2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7/ffff:ffff:ffff:ffff::
+fe80:5::1/ffff:ffff:ffff:ffff::
+::1/ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff
+</pre>
+</blockquote>
+
+<p> The above is for an old FreeBSD machine. Other systems produce
+slightly different results, but you get the idea. </p>
+
+</ul>
+
+<p> If none of all this produces a usable result, send email to the
+postfix-users@postfix.org mailing list and we'll try to help you
+through this. </p>
+
+<h2><a name="credits">Credits</a></h2>
+
+<p> The following information is in part based on information that
+was compiled by Dean Strik. </p>
+
+<ul>
+
+<li> <p> Mark Huizer wrote the original Postfix IPv6 patch. </p>
+
+<li> <p> Jun-ichiro 'itojun' Hagino of the KAME project made
+substantial improvements. Since then, we speak of the KAME patch.
+</p>
+
+<li> <p> The PLD Linux Distribution ported the code to other stacks
+(notably USAGI).  We speak of the PLD patch. A very important
+feature of the PLD patch was that it can work with Lutz Jaenicke's
+TLS patch for Postfix.  </p>
+
+<li> <p> Dean Strik extended IPv6 support to platforms other than
+KAME and USAGI, updated the patch to keep up with Postfix development,
+and provided a combined IPv6 + TLS patch.  Information about his
+effort can be found on Dean Strik's Postfix website at
+http://www.ipnet6.org/postfix/. </p>
+
+<li> <p> Wietse Venema took Dean Strik's IPv6 patch, merged it into
+Postfix 2.2, and took the opportunity to eliminate all IPv4-specific
+code from Postfix that could be removed.  For systems without IPv6
+support in the kernel and system libraries, Postfix has a simple
+compatibility layer, so that it will use IPv4 as before.  </p>
+
+</ul>
+
+</body>
+
+</html>
index 2b8b84007b10512a1eb316f5cecdc9f2b4b8f3e3..c5e18f55ed9d0de76a3ff7e91d28c214ee8ef095 100644 (file)
@@ -17,7 +17,8 @@ HTML  = ../html/ADDRESS_CLASS_README.html \
        ../html/DATABASE_README.html ../html/DB_README.html \
        ../html/DEBUG_README.html \
        ../html/ETRN_README.html ../html/FILTER_README.html \
-       ../html/INSTALL.html ../html/LDAP_README.html \
+       ../html/INSTALL.html ../html/IPV6_README.html \
+       ../html/LDAP_README.html \
        ../html/LINUX_README.html ../html/LMTP_README.html \
        ../html/LOCAL_RECIPIENT_README.html ../html/MAILDROP_README.html \
        ../html/MYSQL_README.html ../html/NFS_README.html \
@@ -48,7 +49,8 @@ README        = ../README_FILES/ADDRESS_CLASS_README \
        ../README_FILES/DATABASE_README ../README_FILES/DB_README \
        ../README_FILES/DEBUG_README \
        ../README_FILES/ETRN_README ../README_FILES/FILTER_README \
-       ../README_FILES/INSTALL ../README_FILES/LDAP_README \
+       ../README_FILES/INSTALL ../README_FILES/IPV6_README \
+       ../README_FILES/LDAP_README \
        ../README_FILES/LINUX_README ../README_FILES/LMTP_README \
        ../README_FILES/LOCAL_RECIPIENT_README ../README_FILES/MAILDROP_README \
        ../README_FILES/MYSQL_README ../README_FILES/NFS_README \
@@ -157,6 +159,9 @@ clobber:
 ../html/INSTALL.html: INSTALL.html
        $(POSTLINK) $? >$@
 
+../html/IPV6_README.html: IPV6_README.html
+       $(POSTLINK) $? >$@
+
 ../html/LDAP_README.html: LDAP_README.html
        $(POSTLINK) $? >$@
 
@@ -283,6 +288,9 @@ clobber:
 ../README_FILES/INSTALL: INSTALL.html
        $(HT2READ) $? >$@
 
+../README_FILES/IPV6_README: IPV6_README.html
+       $(HT2READ) $? >$@
+
 ../README_FILES/LDAP_README: LDAP_README.html
        $(HT2READ) $? >$@
 
index 65ab323fac9c11f3690737b1887ae4e0ff0b0fa8..8ba7c9c264bae08f58edcf57b8afb46415c13be1 100644 (file)
@@ -108,6 +108,10 @@ size=12345
     either does not send the attribute, or sends the attribute with
     an empty value ("name="). </p>
 
+    <li> <p> The client address is an IPv4 dotted quad in the form
+    1.2.3.4 or it is an IPv6 address in the form 1:2:3::4:5:6.
+    </p>
+
     <li> <p> An attribute name must not contain "=", null or newline,
     and an attribute value must not contain null or newline. </p>
 
index 7a39abe3e613edc812723f59761e102b57ba0bbb..58a04913f97f8d4cd30d46ebff1a6442e0166354 100644 (file)
@@ -315,7 +315,7 @@ can't control when the remote SMTP client times out. </p>
 
 <li> <p> smtpd_proxy_filter (syntax: host:port): The host and TCP
 port of the before-queue content filter.  When no host or host:
-is specified in client context, localhost is assumed. </p>
+is specified here, localhost is assumed. </p>
 
 <li> <p> smtpd_proxy_timeout (default: 100s): Timeout for connecting
 to the before-queue content filter and for sending and receiving
index e4d3efb7a0dd280116e4d14f1a9213c2f02f7070..cadcfdb812ecfed1856755a9505a9af25a0ed5b8 100644 (file)
@@ -13,7 +13,7 @@
 #      The optional \fBaccess\fR table directs the Postfix SMTP server
 #      to selectively reject or accept mail. Access can be allowed or
 #      denied for specific host names, domain names, networks, host
-#      network addresses or mail addresses.
+#      addresses or mail addresses.
 #
 #      For an example, see the EXAMPLE section at the end of this
 #      manual page.
 # .IP \fInet.work.addr\fR
 # .IP \fInet.work\fR
 # .IP \fInet\fR
-#      Matches any host address in the specified network. A network
-#      address is a sequence of one or more octets separated by ".".
+#      Matches the specified IPv4 host address or subnetwork. An
+#      IPv4 host address is a sequence of four decimal octets
+#      separated by ".".
 #
-#      NOTE: use the \fBcidr\fR lookup table type to specify
+#      Subnetworks are matched by repeatedly truncating the last
+#      ".octet" from the remote IPv4 host address string until a
+#      match is found in the access table, or until further
+#      truncation is not possible.
+#
+#      NOTE 1: The information in the access map should be in
+#      canonical form, with unnecessary null characters eliminated.
+#      Address information must not be enclosed with "[]" characters.
+#
+#      NOTE 2: use the \fBcidr\fR lookup table type to specify
 #      network/netmask patterns. See cidr_table(5) for details.
+# .IP \fInet:work:addr:ess\fR
+# .IP \fInet:work:addr\fR
+# .IP \fInet:work\fR
+# .IP \fInet\fR
+#      Matches the specified IPv6 host address or subnetwork. An
+#      IPv6 host address is a sequence of three to eight hexadecimal
+#      octet pairs separated by ":".
+#
+#      Subnetworks are matched by repeatedly truncating the last
+#      ":octetpair" from the remote IPv6 host address string until
+#      a match is found in the access table, or until further
+#      truncation is not possible.
+#
+#      NOTE 1: the truncation and comparison are done with the
+#      string representation of the IPv6 host address. Thus, not
+#      all the ":" subnetworks will be tried.
+#
+#      NOTE 2: The information in the access map should be in
+#      canonical form, with unnecessary null characters eliminated.
+#      Address information must not be enclosed with "[]" characters.
+#
+#      NOTE 3: use the \fBcidr\fR lookup table type to specify
+#      network/netmask patterns. See cidr_table(5) for details.
+#
+#      IPv6 support is available in Postfix 2.2 and later.
 # ACCEPT ACTIONS
 # .ad
 # .fi
index 5a8df4c546d8e085e668629e3cd366eb17ca537f..50e3a1e38b7be9e8e8a8bbccce13e0eeef06d880 100644 (file)
 # .IP "\fInetwork_address\fB/\fInetwork_mask     result\fR"
 #      When a search string matches the specified network block,
 #      use the corresponding \fIresult\fR value. Specify
-#      0.0.0.0/0 to match every address.
+#      0.0.0.0/0 to match every IPv4 address, and ::/0 to match
+#      every IPv6 address.
+#
+#      Note: address information may be enclosed inside "[]" but
+#      this form is not recommended.
+#
+#      IPv6 support is available in Postfix 2.2 and later.
 # .IP "\fInetwork_address     result\fR"
 #      When a search string matches the specified network address,
 #      use the corresponding \fIresult\fR value.
index f1134870cbe22158730390642009126b166dc093..2cc9fa1d8c7f5d3715703e2f092cf635932207a9 100644 (file)
@@ -1406,13 +1406,19 @@ After changing the hash_queue_names or hash_queue_depth parameter,
 execute the command "<b>postfix reload</b>".
 </p>
 
-%PARAM hash_queue_names see "postconf -d" output
+%PARAM hash_queue_names deferred, defer
 
 <p>
 The names of queue directories that are split across multiple
 subdirectory levels.
 </p>
 
+<p> Before Postfix version 2.2, the default list of hashed queues
+was significantly larger. Claims about improvements in file system
+technology suggest that hashing of the incoming and active queues
+is no longer needed. Fewer hashed directories speed up the time
+needed to restart Postfix. </p>
+
 <p>
 After changing the hash_queue_names or hash_queue_depth parameter,
 execute the command "<b>postfix reload</b>".
@@ -1540,42 +1546,98 @@ Specify 0 to disable the feature. Valid delays are 0..10.
 
 %PARAM inet_interfaces all
 
+<p> The network interface addresses that this mail system receives
+mail on.  By default, the software claims all active interfaces on
+the machine; with Postfix 2.2 and later, specify "<b>loopback-only</b>"
+to select only local interfaces.  The parameter also controls
+delivery of mail to user@[ip.address].  </p>
+
 <p>
-The network interface addresses that this mail system receives mail
-on.  By default, the software claims all active interfaces on the
-machine. The parameter also controls delivery of mail to
-user@[ip.address].
+Note: you need to stop and start Postfix when this parameter changes.
 </p>
 
-<p>
-When inet_interfaces consists of just one IP address that is not a
-loopback (net 127) address, the Postfix SMTP client will use this address
-as the IP source address for outbound mail. </p>
+<p> When inet_interfaces specifies just one IPv4 and/or IPv6 address
+that is not a loopback address, the Postfix SMTP client will use
+this address as the IP source address for outbound mail. </p>
 
 <p>
 On a multi-homed firewall with separate Postfix instances listening on the
 "inside" and "outside" interfaces, this can prevent each instance from
 being able to reach servers on the "other side" of the firewall. Setting
-smtp_bind_address to 0.0.0.0 avoids the potential problem. </p>
+smtp_bind_address to 0.0.0.0 avoids the potential problem for
+IPv4, and setting smtp_bind_address6 to :: solves the problem
+for IPv6. </p>
 
 <p>
-A better solution is to leave inet_interfaces at the default value
+A better solution for multi-homed firewalls is to leave inet_interfaces
+at the default value
 and instead use explicit IP addresses in master.cf. This preserves SMTP
 loop detection, by ensuring that each side of the firewall knows that the
 other IP address is still the same host. Setting $inet_interfaces to a
-single IP address is primarily useful with virtual hosting of domains on
+single IPv4 and/or IPV6 address is primarily useful with virtual
+hosting of domains on
 secondary IP addresses, when each IP address serves a different domain
 (and has a different $myhostname setting). </p>
 
 <p>
 See also the proxy_interfaces parameter, for network addresses that
-are forwarded to us by way of a proxy or address translator.
+are forwarded to Postfix by way of a proxy or address translator.
 </p>
 
 <p>
-Note: you need to stop and start Postfix when this parameter changes.
+Examples:
+</p>
+
+<pre>
+inet_interfaces = all (DEFAULT)
+inet_interfaces = loopback-only
+inet_interfaces = 127.0.0.1
+inet_interfaces = 192.168.1.2, 127.0.0.1
+</pre>
+
+%PARAM inet_protocols ipv4
+
+<p> The Internet protocols Postfix will attempt to use when making
+or accepting connections. Specify one or more of "ipv4" or "ipv6",
+separated by whitespace or commas. The form "all" is equivalent to
+"ipv4, ipv6". </p>
+
+<p> Note: you MUST stop and start Postfix after changing this
+parameter. </p>
+
+<p> On systems that pre-date IPV6_V6ONLY support (RFC 3493), an
+IPv6 server will also accept IPv4 connections, even when IPv4 is
+turned off with the inet_protocols parameter.  On systems with
+IPV6_V6ONLY support, Postfix will use separate server sockets for
+IPv6 and IPv4, and each will accept only connections for the
+corresponding protocol.  </p>
+
+<p> When IPv4 support is enabled via the inet_protocols parameter,
+Postfix will to DNS type A record lookups, and will convert
+IPv4-in-IPv6 client IP addresses (::ffff:1.2.3.4) to their original
+IPv4 form (1.2.3.4).  The latter is needed on hosts that pre-date
+IPV6_V6ONLY support (RFC 3493). </p>
+
+<p> When IPv6 support is enabled via the inet_protocols parameter,
+Postfix will do DNS type AAAA record lookups. </p>
+
+<p> When both IPv4 and IPv6 support are enabled, the Postfix SMTP
+client will attempt to connect via IPv6 before attempting to use
+IPv4.  </p>
+
+<p> This feature is available in Postfix version 2.2 and later. </p>
+
+<p>
+Examples:
 </p>
 
+<pre>
+inet_protocols = ipv4 (DEFAULT)
+inet_protocols = all
+inet_protocols = ipv6
+inet_protocols = ipv4, ipv6
+</pre>
+
 %PARAM initial_destination_concurrency 5
 
 <p>
@@ -2530,11 +2592,17 @@ lookup string (the lookup result is ignored). </p>
 first match.  Specify "!pattern" to exclude an address or network
 block from the list.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the mynetworks value, and in files specified with
+"/file/name".  IP version 6 addresses contain the ":" character,
+and would otherwise be confused with a "type:table" pattern.  </p>
+
 <p> Examples:  </p>
 
 <pre> 
-mynetworks = 168.100.189.0/28, 127.0.0.0/8
+mynetworks = 127.0.0.0/8 168.100.189.0/28
 mynetworks = !192.168.0.1, 192.168.0.0/28
+mynetworks = 127.0.0.0/8 168.100.189.0/28 [::1]/128 [2001:240:5c7::]/64 
 mynetworks = $config_directory/mynetworks
 mynetworks = hash:/etc/postfix/network_table
 </pre>
@@ -3256,7 +3324,7 @@ the word "ESMTP" appears in the server greeting banner (example:
 
 <p>
 An optional numerical network address that the SMTP client should
-bind to when making a connection.
+bind to when making an IPv4 connection.
 </p>
 
 <p>
@@ -3270,11 +3338,43 @@ for example:
         smtp ... smtp -o smtp_bind_address=11.22.33.44
 </pre>
 
-<p> Note: when inet_interfaces specifies exactly one address that
-is a non-loopback address, it is automatically used as the
-smtp_bind_address.  This supports virtual IP hosting, but can be
-a problem on multi-homed firewalls. See the inet_interfaces
-documentation for more detail. </p>
+<p> Note 1: when inet_interfaces specifies no more than one IPv4
+address, and that address is a non-loopback address, it is
+automatically used as the smtp_bind_address.  This supports virtual
+IP hosting, but can be a problem on multi-homed firewalls. See the
+inet_interfaces documentation for more detail. </p>
+
+<p> Note 2: address information may be enclosed inside <tt>[]</tt>,
+but this form is not recommended. </p>
+
+%PARAM smtp_bind_address6 
+
+<p>
+An optional numerical network address that the SMTP client should
+bind to when making an IPv6 connection.
+</p>
+
+<p>
+This can be specified in the main.cf file for all SMTP clients, or
+it can be specified in the master.cf file for a specific client,
+for example:
+</p>
+
+<pre>
+  /etc/postfix/master.cf:
+        smtp ... smtp -o smtp_bind_address6=1:2:3:4:5:6:7:8
+</pre>
+
+<p> Note 1: when inet_interfaces specifies no more than one IPv6
+address, and that address is a non-loopback address, it is
+automatically used as the smtp_bind_address6.  This supports virtual
+IP hosting, but can be a problem on multi-homed firewalls. See the
+inet_interfaces documentation for more detail. </p>
+
+<p> Note 2: address information may be enclosed inside <tt>[]</tt>,
+but this form is not recommended. </p>
+
+<p> This feature is available in Postfix version 2.2 and later. </p>
 
 %PARAM smtp_connection_cache_time_limit 2s
 
@@ -3881,6 +3981,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace. </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the authorized_verp_clients value, and in files
+specified with "/file/name".  IP version 6 addresses contain the
+":" character, and would otherwise be confused with a "type:table"
+pattern.  </p>
+
 %PARAM smtpd_authorized_verp_clients $authorized_verp_clients
 
 <p> What SMTP clients are allowed to specify the XVERP command.
@@ -3902,6 +4008,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_authorized_verp_clients value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.  </p>
+
 %PARAM smtpd_authorized_xclient_hosts 
 
 <p>
@@ -3931,6 +4043,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_authorized_xclient_hosts value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.  </p>
+
 %PARAM smtpd_authorized_xforward_hosts 
 
 <p>
@@ -3959,6 +4077,12 @@ is matched when a table entry matches a lookup string (the lookup
 result is ignored).  Continue long lines by starting the next line
 with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_authorized_xforward_hosts value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.  </p>
+
 %PARAM smtpd_banner $myhostname ESMTP $mail_name
 
 <p>
@@ -4014,6 +4138,12 @@ list of network blocks, hostnames or .domain names (the initial
 dot causes the domain to match any name below it).
 </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_client_event_limit_exceptions value, and
+in files specified with "/file/name".  IP version 6 addresses
+contain the ":" character, and would otherwise be confused with a
+"type:table" pattern.  </p>
+
 <p>
 This feature is available in Postfix 2.2 and later.
 </p>
@@ -4916,6 +5046,12 @@ contents; a "type:table" lookup table is matched when a table entry
 matches a lookup string (the lookup result is ignored).  Continue
 long lines by starting the next line with whitespace.  </p>
 
+<p> Note: IP version 6 address information must be specified inside
+<tt>[]</tt> in the smtpd_sasl_exceptions_networks value, and in
+files specified with "/file/name".  IP version 6 addresses contain
+the ":" character, and would otherwise be confused with a "type:table"
+pattern.  </p>
+
 <p>
 Example:
 </p>
@@ -7255,7 +7391,7 @@ parameter in the default main.cf file.  </p>
 <p> Optional lookup tables with a) names of domains for which all
 addresses are aliased to addresses in other local or remote domains,
 and b) addresses that are aliased to addresses in other local or
-remote domains.  Available before Postfix version 2.0. With Postfix 2.1
+remote domains.  Available before Postfix version 2.0. With Postfix 2.0
 and later, this is replaced by separate controls: virtual_alias_domains
 and virtual_alias_maps. </p>
 
index e7f75c98d87237476f9d6f24b81019d2c721bc37..3cffb4fb5edcaafe3df3f0877aae3bc8aa57274d 100644 (file)
@@ -835,3 +835,27 @@ Verisign
 Verisign's
 dd
 itd
+AAAA
+DNSBL
+GETIFADDRS
+Hagino
+Huizer
+Jaenicke's
+Lutz
+PLD
+SIOCGIF
+SIOCGLIF
+Strik
+Strik's
+Tru
+USAGI
+compat
+ff
+ffff
+getifaddrs
+ichiro
+ifndef
+ipnet
+ipv
+itojun
+netmasks
index 23d6d3062750d0133ff0464e632ae133f201e40e..911e49ef319163c982a5a82188e961402b785f39 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 86030bf3d4a53d4b1896526501d8efb6ca047d01..64c4c4b5cfd8fd7dbfb76da3a73e50307c106006 100644 (file)
@@ -20,7 +20,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index e2f2c8691793303f0a1f727c7db96298ce2c62fe..d2d4025bb63c01e1e7ac1ac0732b690f7bf04deb 100644 (file)
@@ -24,7 +24,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -189,7 +189,6 @@ cleanup_envelope.o: ../../include/mymalloc.h
 cleanup_envelope.o: ../../include/stringops.h
 cleanup_envelope.o: ../../include/nvtable.h
 cleanup_envelope.o: ../../include/htable.h
-cleanup_envelope.o: ../../include/name_code.h
 cleanup_envelope.o: ../../include/record.h
 cleanup_envelope.o: ../../include/rec_type.h
 cleanup_envelope.o: ../../include/cleanup_user.h
index 7d5ef4c972b37a86f576860da895279bf5ebce43..d59a3cf51a928c74d2d8c339b53ccdbdc7e00da1 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index bdbad7385abbcddf2bf341a8b1ea660e89b61dde..3cc0fb71a17ac977f0e37cd725b5272a9c3df52c 100644 (file)
@@ -1,13 +1,15 @@
 SHELL  = /bin/sh
-SRCS   = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c
-OBJS   = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o
+SRCS   = dns_lookup.c dns_rr.c dns_strerror.c dns_strtype.c dns_rr_to_pa.c \
+       dns_sa_to_rr.c dns_rr_eq_sa.c dns_rr_to_sa.c
+OBJS   = dns_lookup.o dns_rr.o dns_strerror.o dns_strtype.o dns_rr_to_pa.o \
+       dns_sa_to_rr.o dns_rr_eq_sa.o dns_rr_to_sa.o
 HDRS   = dns.h
 TESTSRC        = test_dns_lookup.c test_alias_token.c
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
 INCL   =
 LIB    = libdns.a
-TESTPROG= test_dns_lookup
+TESTPROG= test_dns_lookup dns_rr_to_pa dns_rr_to_sa dns_sa_to_rr dns_rr_eq_sa
 LIBS   = ../../lib/libutil.a
 LIB_DIR        = ../../lib
 INC_DIR        = ../../include
@@ -17,11 +19,12 @@ INC_DIR     = ../../include
 all: $(LIB)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
-tests: test
+tests: test dns_rr_to_pa_test dns_rr_to_sa_test dns_sa_to_rr_test \
+       dns_rr_eq_sa_test
 
 $(LIB):        $(OBJS)
        $(AR) $(ARFL) $(LIB) $?
@@ -41,6 +44,46 @@ update: $(LIB_DIR)/$(LIB) $(HDRS)
 test_dns_lookup: test_dns_lookup.c $(LIB) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
 
+dns_rr_to_pa: $(LIB) $(LIBS)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+       mv junk $@.o
+
+dns_rr_to_sa: $(LIB) $(LIBS)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+       mv junk $@.o
+
+dns_sa_to_rr: $(LIB) $(LIBS)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+       mv junk $@.o
+
+dns_rr_eq_sa: $(LIB) $(LIBS)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+       mv junk $@.o
+
+dns_rr_to_pa_test: dns_rr_to_pa dns_rr_to_pa.in dns_rr_to_pa.ref
+       ./dns_rr_to_pa `cat dns_rr_to_pa.in` >dns_rr_to_pa.tmp
+       diff dns_rr_to_pa.ref dns_rr_to_pa.tmp
+       rm -f dns_rr_to_pa.tmp
+
+dns_rr_to_sa_test: dns_rr_to_sa dns_rr_to_sa.in dns_rr_to_sa.ref
+       ./dns_rr_to_sa `cat dns_rr_to_sa.in` >dns_rr_to_sa.tmp
+       diff dns_rr_to_sa.ref dns_rr_to_sa.tmp
+       rm -f dns_rr_to_sa.tmp
+
+dns_sa_to_rr_test: dns_sa_to_rr dns_sa_to_rr.in dns_sa_to_rr.ref
+       ./dns_sa_to_rr `cat dns_sa_to_rr.in` >dns_sa_to_rr.tmp
+       diff dns_sa_to_rr.ref dns_sa_to_rr.tmp
+       rm -f dns_sa_to_rr.tmp
+
+dns_rr_eq_sa_test: dns_rr_eq_sa dns_rr_eq_sa.in dns_rr_eq_sa.ref
+       ./dns_rr_eq_sa `cat dns_rr_eq_sa.in` >dns_rr_eq_sa.tmp
+       diff dns_rr_eq_sa.ref dns_rr_eq_sa.tmp
+       rm -f dns_rr_eq_sa.tmp
+
 printfck: $(OBJS) $(PROG)
        rm -rf printfck
        mkdir printfck
@@ -76,6 +119,8 @@ dns_lookup.o: ../../include/msg.h
 dns_lookup.o: ../../include/valid_hostname.h
 dns_lookup.o: ../../include/stringops.h
 dns_lookup.o: dns.h
+dns_lookup.o: ../../include/sock_addr.h
+dns_lookup.o: ../../include/myaddrinfo.h
 dns_rr.o: dns_rr.c
 dns_rr.o: ../../include/sys_defs.h
 dns_rr.o: ../../include/msg.h
@@ -84,16 +129,54 @@ dns_rr.o: ../../include/myrand.h
 dns_rr.o: dns.h
 dns_rr.o: ../../include/vstring.h
 dns_rr.o: ../../include/vbuf.h
+dns_rr.o: ../../include/sock_addr.h
+dns_rr.o: ../../include/myaddrinfo.h
+dns_rr_eq_sa.o: dns_rr_eq_sa.c
+dns_rr_eq_sa.o: ../../include/sys_defs.h
+dns_rr_eq_sa.o: ../../include/msg.h
+dns_rr_eq_sa.o: ../../include/sock_addr.h
+dns_rr_eq_sa.o: dns.h
+dns_rr_eq_sa.o: ../../include/vstring.h
+dns_rr_eq_sa.o: ../../include/vbuf.h
+dns_rr_eq_sa.o: ../../include/myaddrinfo.h
+dns_rr_to_pa.o: dns_rr_to_pa.c
+dns_rr_to_pa.o: ../../include/sys_defs.h
+dns_rr_to_pa.o: ../../include/msg.h
+dns_rr_to_pa.o: dns.h
+dns_rr_to_pa.o: ../../include/vstring.h
+dns_rr_to_pa.o: ../../include/vbuf.h
+dns_rr_to_pa.o: ../../include/sock_addr.h
+dns_rr_to_pa.o: ../../include/myaddrinfo.h
+dns_rr_to_sa.o: dns_rr_to_sa.c
+dns_rr_to_sa.o: ../../include/sys_defs.h
+dns_rr_to_sa.o: ../../include/msg.h
+dns_rr_to_sa.o: dns.h
+dns_rr_to_sa.o: ../../include/vstring.h
+dns_rr_to_sa.o: ../../include/vbuf.h
+dns_rr_to_sa.o: ../../include/sock_addr.h
+dns_rr_to_sa.o: ../../include/myaddrinfo.h
+dns_sa_to_rr.o: dns_sa_to_rr.c
+dns_sa_to_rr.o: ../../include/sys_defs.h
+dns_sa_to_rr.o: ../../include/msg.h
+dns_sa_to_rr.o: dns.h
+dns_sa_to_rr.o: ../../include/vstring.h
+dns_sa_to_rr.o: ../../include/vbuf.h
+dns_sa_to_rr.o: ../../include/sock_addr.h
+dns_sa_to_rr.o: ../../include/myaddrinfo.h
 dns_strerror.o: dns_strerror.c
 dns_strerror.o: ../../include/sys_defs.h
 dns_strerror.o: ../../include/vstring.h
 dns_strerror.o: ../../include/vbuf.h
 dns_strerror.o: dns.h
+dns_strerror.o: ../../include/sock_addr.h
+dns_strerror.o: ../../include/myaddrinfo.h
 dns_strtype.o: dns_strtype.c
 dns_strtype.o: ../../include/sys_defs.h
 dns_strtype.o: ../../include/vstring.h
 dns_strtype.o: ../../include/vbuf.h
 dns_strtype.o: dns.h
+dns_strtype.o: ../../include/sock_addr.h
+dns_strtype.o: ../../include/myaddrinfo.h
 test_dns_lookup.o: test_dns_lookup.c
 test_dns_lookup.o: ../../include/sys_defs.h
 test_dns_lookup.o: ../../include/vstring.h
@@ -102,3 +185,5 @@ test_dns_lookup.o: ../../include/msg.h
 test_dns_lookup.o: ../../include/msg_vstream.h
 test_dns_lookup.o: ../../include/vstream.h
 test_dns_lookup.o: dns.h
+test_dns_lookup.o: ../../include/sock_addr.h
+test_dns_lookup.o: ../../include/myaddrinfo.h
index 014536b6e235065d528a44d2b6bc54dac4afc0e6..90a45b82c7c3dfb7995200b3b2a00e33a700877e 100644 (file)
@@ -59,6 +59,8 @@
   * Utility library.
   */
 #include <vstring.h>
+#include <sock_addr.h>
+#include <myaddrinfo.h>
 
  /*
   * Structure for fixed resource record data.
@@ -99,7 +101,8 @@ extern unsigned dns_type(const char *);
  /*
   * dns_rr.c
   */
-extern DNS_RR *dns_rr_create(const char *, DNS_FIXED *, unsigned,
+extern DNS_RR *dns_rr_create(const char *, ushort, ushort,
+                                    unsigned, unsigned,
                                     const char *, unsigned);
 extern void dns_rr_free(DNS_RR *);
 extern DNS_RR *dns_rr_copy(DNS_RR *);
@@ -108,13 +111,54 @@ extern DNS_RR *dns_rr_sort(DNS_RR *, int (*) (DNS_RR *, DNS_RR *));
 extern DNS_RR *dns_rr_shuffle(DNS_RR *);
 extern DNS_RR *dns_rr_remove(DNS_RR *, DNS_RR *);
 
+ /*
+  * dns_rr_to_pa.c
+  */
+extern const char *dns_rr_to_pa(DNS_RR *, MAI_HOSTADDR_STR *);
+
+ /*
+  * dns_sa_to_rr.c
+  */
+extern DNS_RR *dns_sa_to_rr(const char *, unsigned, struct sockaddr *);
+
+ /*
+  * dns_rr_to_sa.c
+  */
+extern int dns_rr_to_sa(DNS_RR *, unsigned, struct sockaddr *, SOCKADDR_SIZE *);
+
+ /*
+  * dns_rr_eq_sa.c
+  */
+extern int dns_rr_eq_sa(DNS_RR *, struct sockaddr *);
+
+#ifdef HAS_IPV6
+#define DNS_RR_EQ_SA(rr, sa) \
+    ((SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \
+     && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr) \
+    || (SOCK_ADDR_IN_FAMILY(sa) == AF_INET6 && (rr)->type == T_AAAA \
+       && memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)), \
+                 (rr)->data, (rr)->data_len) == 0))
+#else
+#define DNS_RR_EQ_SA(rr, sa) \
+    (SOCK_ADDR_IN_FAMILY(sa) == AF_INET && (rr)->type == T_A \
+     && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR((rr)->data).s_addr)
+#endif
+
  /*
   * dns_lookup.c
   */
 extern int dns_lookup(const char *, unsigned, unsigned, DNS_RR **,
                              VSTRING *, VSTRING *);
-extern int dns_lookup_types(const char *, unsigned, DNS_RR **,
-                                   VSTRING *, VSTRING *,...);
+extern int dns_lookup_l(const char *, unsigned, DNS_RR **, VSTRING *,
+                               VSTRING *, int,...);
+extern int dns_lookup_v(const char *, unsigned, DNS_RR **, VSTRING *,
+                               VSTRING *, int, unsigned *);
+
+ /*
+  * Request flags.
+  */
+#define DNS_REQ_FLAG_ANY       (1<<0)
+#define DNS_REQ_FLAG_ALL       (1<<1)
 
  /*
   * Status codes. Failures must have negative codes so they will not collide
index 03b4aaf5ff32a5ca11b2c0c475493121f2e7fda0..da1a14a50149e1c13bccaa401f43bf8582b710a6 100644 (file)
@@ -6,21 +6,31 @@
 /* SYNOPSIS
 /*     #include <dns.h>
 /*
-/*     int     dns_lookup(name, type, flags, list, fqdn, why)
+/*     int     dns_lookup(name, type, rflags, list, fqdn, why)
 /*     const char *name;
 /*     unsigned type;
-/*     unsigned flags;
+/*     unsigned rflags;
 /*     DNS_RR  **list;
 /*     VSTRING *fqdn;
 /*     VSTRING *why;
 /*
-/*     int     dns_lookup_types(name, flags, list, fqdn, why, type, ...)
+/*     int     dns_lookup_l(name, rflags, list, fqdn, why, lflags, ltype, ...)
 /*     const char *name;
-/*     unsigned flags;
+/*     unsigned rflags;
 /*     DNS_RR  **list;
 /*     VSTRING *fqdn;
 /*     VSTRING *why;
-/*     unsigned type;
+/*     int     lflags;
+/*     unsigned ltype;
+/*
+/*     int     dns_lookup_v(name, rflags, list, fqdn, why, lflags, ltype)
+/*     const char *name;
+/*     unsigned rflags;
+/*     DNS_RR  **list;
+/*     VSTRING *fqdn;
+/*     VSTRING *why;
+/*     int     lflags;
+/*     unsigned *ltype;
 /* DESCRIPTION
 /*     dns_lookup() looks up DNS resource records. When requested to
 /*     look up data other than type CNAME, it will follow a limited
 /*     All name results are validated by \fIvalid_hostname\fR();
 /*     an invalid name is reported as a transient error.
 /*
-/*     dns_lookup_types() allows the user to specify a null-terminated
-/*     list of resource types. This function calls dns_lookup() for each
-/*     listed type in the specified order, until the list is exhausted or
-/*     until the search result becomes not equal to DNS_NOTFOUND.
+/*     dns_lookup_l() and dns_lookup_v() allow the user to specify
+/*     a list of resource types. 
 /* INPUTS
 /* .ad
 /* .fi
@@ -40,8 +48,8 @@
 /*     The name to be looked up in the domain name system.
 /* .IP type
 /*     The resource record type to be looked up (T_A, T_MX etc.).
-/* .IP flags
-/*     A bitwise OR of:
+/* .IP rflags
+/*     Resolver flags. These are a bitwise OR of:
 /* .RS
 /* .IP RES_DEBUG
 /*     Print debugging information.
 /* .IP RES_DEFNAMES
 /*     Append local domain to unqualified names.
 /* .RE
+/* .IP lflags
+/*     Multi-type request control for dns_lookup_l() and
+/*     dns_lookup_v(). This is one of the following:
+/* .RS
+/* .IP DNS_REQ_FLAG_ANY
+/*     Call dns_lookup() for each specified resource record type
+/*     in the specified order, until the list is exhausted or
+/*     until some result is DNS_OK.
+/* .IP DNS_REQ_FLAG_ALL
+/*     Call dns_lookup() for all specified resource record types
+/*     in the specified order, and merge their results.
+/* .RE
+/* .IP ltype
+/*     The resource record types to be looked up. In the case of
+/*     dns_lookup_l(), this is a null-terminated argument list.
+/*     In the case of dns_lookup_v(), this is a null-terminated
+/*     integer array.
 /* OUTPUTS
 /* .ad
 /* .fi
 
 #include <sys_defs.h>
 #include <netdb.h>
-#include <stdlib.h>                    /* BSDI stdarg.h uses abort() */
-#include <stdarg.h>
 #include <string.h>
 #include <ctype.h>
 
 #include <msg.h>
 #include <valid_hostname.h>
 #include <stringops.h>
-#include <valid_hostname.h>
 
 /* DNS library. */
 
@@ -375,7 +397,8 @@ static DNS_RR *dns_get_rr(DNS_REPLY *reply, unsigned char *pos,
        *dst = 0;
        break;
     }
-    return (dns_rr_create(rr_name, fixed, pref, temp, data_len));
+    return (dns_rr_create(rr_name, fixed->type, fixed->class, fixed->ttl,
+                         pref, temp, data_len));
 }
 
 /* dns_get_alias - extract CNAME from name server reply */
@@ -507,9 +530,9 @@ int     dns_lookup(const char *name, unsigned type, unsigned flags,
     int     status;
 
     /*
-     * The Linux resolver misbehaves when given an invalid domain name.
+     * DJBDNS produces a bogus A record when given a numerical hostname.
      */
-    if (!valid_hostname(name, DONT_GRIPE)) {
+    if (valid_hostaddr(name, DONT_GRIPE)) {
        if (why)
            vstring_sprintf(why,
                   "Name service error for %s: invalid host or domain name",
@@ -519,9 +542,9 @@ int     dns_lookup(const char *name, unsigned type, unsigned flags,
     }
 
     /*
-     * DJBDNS produces a bogus A record when given a numerical hostname.
+     * The Linux resolver misbehaves when given an invalid domain name.
      */
-    if (valid_hostaddr(name, DONT_GRIPE)) {
+    if (!valid_hostname(name, DONT_GRIPE)) {
        if (why)
            vstring_sprintf(why,
                   "Name service error for %s: invalid host or domain name",
@@ -568,26 +591,70 @@ int     dns_lookup(const char *name, unsigned type, unsigned flags,
     return (DNS_NOTFOUND);
 }
 
-/* dns_lookup_types - DNS lookup interface with multiple types */
+/* dns_lookup_l - DNS lookup interface with types list */
 
-int     dns_lookup_types(const char *name, unsigned flags, DNS_RR **rrlist,
-                                VSTRING *fqdn, VSTRING *why,...)
+int     dns_lookup_l(const char *name, unsigned flags, DNS_RR **rrlist,
+                            VSTRING *fqdn, VSTRING *why, int lflags,...)
 {
     va_list ap;
     unsigned type;
     int     status = DNS_NOTFOUND;
+    DNS_RR *rr;
+    int     non_err = 0;
     int     soft_err = 0;
 
-    va_start(ap, why);
+    if (rrlist)
+       *rrlist = 0;
+    va_start(ap, lflags);
     while ((type = va_arg(ap, unsigned)) != 0) {
        if (msg_verbose)
-           msg_info("lookup %s type %d flags %d", name, type, flags);
-       status = dns_lookup(name, type, flags, rrlist, fqdn, why);
-       if (status == DNS_OK)
-           break;
-       if (status == DNS_RETRY)
+           msg_info("lookup %s type %s flags %d",
+                    name, dns_strtype(type), flags);
+       status = dns_lookup(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
+                           fqdn, why);
+       if (status == DNS_OK) {
+           non_err = 1;
+           if (rrlist)
+               *rrlist = dns_rr_append(*rrlist, rr);
+           if (lflags == DNS_REQ_FLAG_ANY)
+               break;
+       } else if (status == DNS_RETRY) {
            soft_err = 1;
+       }
     }
     va_end(ap);
-    return ((status == DNS_OK || soft_err == 0) ? status : DNS_RETRY);
+    return (non_err ? DNS_OK : soft_err ? DNS_RETRY : status);
+}
+
+/* dns_lookup_v - DNS lookup interface with types vector */
+
+int     dns_lookup_v(const char *name, unsigned flags, DNS_RR **rrlist,
+                            VSTRING *fqdn, VSTRING *why, int lflags,
+                            unsigned *types)
+{
+    unsigned type;
+    int     status = DNS_NOTFOUND;
+    DNS_RR *rr;
+    int     non_err = 0;
+    int     soft_err = 0;
+
+    if (rrlist)
+       *rrlist = 0;
+    while ((type = *types++) != 0) {
+       if (msg_verbose)
+           msg_info("lookup %s type %s flags %d",
+                    name, dns_strtype(type), flags);
+       status = dns_lookup(name, type, flags, rrlist ? &rr : (DNS_RR **) 0,
+                           fqdn, why);
+       if (status == DNS_OK) {
+           non_err = 1;
+           if (rrlist)
+               *rrlist = dns_rr_append(*rrlist, rr);
+           if (lflags == DNS_REQ_FLAG_ANY)
+               break;
+       } else if (status == DNS_RETRY) {
+           soft_err = 1;
+       }
+    }
+    return (non_err ? DNS_OK : soft_err ? DNS_RETRY : status);
 }
index a00a738d0ee8aaba4c5c67a001158e05b7d22b95..a52d2813d1105ae9030bc69d5e21f8dbddd98059 100644 (file)
@@ -6,9 +6,12 @@
 /* SYNOPSIS
 /*     #include <dns.h>
 /*
-/*     DNS_RR  *dns_rr_create(name, fixed, preference, data, data_len)
+/*     DNS_RR  *dns_rr_create(name, type, class, ttl, preference, 
+/*                             data, data_len)
 /*     const char *name;
-/*     DNS_FIXED *fixed;
+/*     unsigned short type;
+/*     unsigned short class;
+/*     unsigned int ttl;
 /*     unsigned preference;
 /*     const char *data;
 /*     unsigned len;
@@ -39,8 +42,6 @@
 /*
 /*     dns_rr_create() creates and initializes one resource record.
 /*     The \fIname\fR record specifies the record name.
-/*     The \fIfixed\fR argument specifies generic resource record
-/*     information such as resource type and time to live;
 /*     \fIpreference\fR is used for MX records; \fIdata\fR is a null
 /*     pointer or specifies optional resource-specific data;
 /*     \fIdata_len\fR is the amount of resource-specific data.
 
 /* dns_rr_create - fill in resource record structure */
 
-DNS_RR *dns_rr_create(const char *name, DNS_FIXED *fixed, unsigned pref,
+DNS_RR *dns_rr_create(const char *name, ushort type, ushort class,
+                             unsigned int ttl, unsigned pref,
                              const char *data, unsigned data_len)
 {
     DNS_RR *rr;
 
     rr = (DNS_RR *) mymalloc(sizeof(*rr) + data_len - 1);
     rr->name = mystrdup(name);
-    rr->type = fixed->type;
-    rr->class = fixed->class;
-    rr->ttl = fixed->ttl;
+    rr->type = type;
+    rr->class = class;
+    rr->ttl = ttl;
     rr->pref = pref;
     if (data && data_len > 0)
        memcpy(rr->data, data, data_len);
@@ -255,7 +257,7 @@ DNS_RR *dns_rr_shuffle(DNS_RR *list)
 
 DNS_RR *dns_rr_remove(DNS_RR *list, DNS_RR *record)
 {
-    if (list == 0) 
+    if (list == 0)
        msg_panic("dns_rr_remove: record not found");
 
     if (list == record) {
diff --git a/postfix/src/dns/dns_rr_eq_sa.c b/postfix/src/dns/dns_rr_eq_sa.c
new file mode 100644 (file)
index 0000000..27495fc
--- /dev/null
@@ -0,0 +1,137 @@
+/*++
+/* NAME
+/*     dns_rr_eq_sa 3
+/* SUMMARY
+/*     compare resource record with socket address
+/* SYNOPSIS
+/*     #include <dns.h>
+/*
+/*     int     dns_rr_eq_sa(DNS_RR *rr, struct sockaddr *sa)
+/*     DNS_RR  *rr;
+/*     struct sockaddr *sa;
+/*
+/*     int     DNS_RR_EQ_SA(DNS_RR *rr, struct sockaddr *sa)
+/*     DNS_RR  *rr;
+/*     struct sockaddr *sa;
+/* DESCRIPTION
+/*     dns_rr_eq_sa() compares a DNS resource record with a socket
+/*     address.  The result is non-zero when the resource type
+/*     matches the socket address family, and when the network
+/*     address information is identical.
+/*
+/*     DNS_RR_EQ_SA() is an unsafe macro version for those who live fast.
+/*
+/*     Arguments:
+/* .IP rr
+/*     DNS resource record pointer.
+/* .IP sa
+/*     Binary address pointer.
+/* DIAGNOSTICS
+/*     Panic: unknown socket address family.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System libraries. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <sock_addr.h>
+
+/* DNS library. */
+
+#include <dns.h>
+
+/* dns_rr_eq_sa - compare resource record with socket address */
+
+int     dns_rr_eq_sa(DNS_RR *rr, struct sockaddr * sa)
+{
+    const char *myname = "dns_rr_eq_sa";
+
+    if (sa->sa_family == AF_INET) {
+       return (rr->type == T_A
+               && SOCK_ADDR_IN_ADDR(sa).s_addr == IN_ADDR(rr->data).s_addr);
+#ifdef HAS_IPV6
+    } else if (sa->sa_family == AF_INET6) {
+       return (rr->type == T_AAAA
+               && memcmp((char *) &SOCK_ADDR_IN6_ADDR(sa),
+                         rr->data, rr->data_len) == 0);
+#endif
+    } else {
+       msg_panic("%s: unsupported socket address family type: %d",
+                 myname, sa->sa_family);
+    }
+}
+
+ /*
+  * Stand-alone test program.
+  */
+#ifdef TEST
+#include <vstream.h>
+#include <myaddrinfo.h>
+#include <inet_proto.h>
+
+static const char *myname;
+
+static NORETURN usage(void)
+{
+    msg_fatal("usage: %s hostname address", myname);
+}
+
+int     main(int argc, char **argv)
+{
+    MAI_HOSTADDR_STR hostaddr;
+    DNS_RR *rr;
+    struct addrinfo *res0;
+    struct addrinfo *res1;
+    struct addrinfo *res;
+    int     aierr;
+
+    myname = argv[0];
+
+    if (argc < 3)
+       usage();
+
+    inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
+
+    while (*++argv) {
+       if (argv[1] == 0)
+           usage();
+
+       if ((aierr = hostaddr_to_sockaddr(argv[1], (char *) 0, 0, &res1)) != 0)
+           msg_fatal("host address %s: %s", argv[1], MAI_STRERROR(aierr));
+       if ((rr = dns_sa_to_rr(argv[1], 0, res1->ai_addr)) == 0)
+           msg_fatal("dns_sa_to_rr: %m");
+       freeaddrinfo(res1);
+
+       if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0)
+           msg_fatal("host name %s: %s", argv[0], MAI_STRERROR(aierr));
+       for (res = res0; res != 0; res = res->ai_next) {
+           SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
+                                &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+           vstream_printf("%s =?= %s\n", hostaddr.buf, argv[1]);
+           vstream_printf("tested by function: %s\n",
+                          dns_rr_eq_sa(rr, res->ai_addr) ?
+                          "yes" : "no");
+           vstream_printf("tested by macro:    %s\n",
+                          DNS_RR_EQ_SA(rr, res->ai_addr) ?
+                          "yes" : "no");
+       }
+       dns_rr_free(rr);
+       freeaddrinfo(res0);
+       vstream_fflush(VSTREAM_OUT);
+       argv += 1;
+    }
+}
+
+#endif
diff --git a/postfix/src/dns/dns_rr_eq_sa.in b/postfix/src/dns/dns_rr_eq_sa.in
new file mode 100644 (file)
index 0000000..be10f96
--- /dev/null
@@ -0,0 +1,4 @@
+spike.porcupine.org 168.100.189.2
+spike.porcupine.org 168.100.189.3
+spike.porcupine.org 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+spike.porcupine.org 2001:240:5c7:0:2d0:b7ff:febe:ca9f
diff --git a/postfix/src/dns/dns_rr_eq_sa.ref b/postfix/src/dns/dns_rr_eq_sa.ref
new file mode 100644 (file)
index 0000000..8df8d74
--- /dev/null
@@ -0,0 +1,24 @@
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7 =?= 168.100.189.2
+tested by function: no
+tested by macro:    no
+168.100.189.2 =?= 168.100.189.2
+tested by function: yes
+tested by macro:    yes
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7 =?= 168.100.189.3
+tested by function: no
+tested by macro:    no
+168.100.189.2 =?= 168.100.189.3
+tested by function: no
+tested by macro:    no
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7 =?= 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+tested by function: yes
+tested by macro:    yes
+168.100.189.2 =?= 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+tested by function: no
+tested by macro:    no
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7 =?= 2001:240:5c7:0:2d0:b7ff:febe:ca9f
+tested by function: no
+tested by macro:    no
+168.100.189.2 =?= 2001:240:5c7:0:2d0:b7ff:febe:ca9f
+tested by function: no
+tested by macro:    no
diff --git a/postfix/src/dns/dns_rr_to_pa.c b/postfix/src/dns/dns_rr_to_pa.c
new file mode 100644 (file)
index 0000000..bfd93a0
--- /dev/null
@@ -0,0 +1,113 @@
+/*++
+/* NAME
+/*     dns_rr_to_pa 3
+/* SUMMARY
+/*     resource record to printable address
+/* SYNOPSIS
+/*     #include <dns.h>
+/*
+/*     const char *dns_rr_to_pa(rr, hostaddr)
+/*     DNS_RR  *rr;
+/*     MAI_HOSTADDR_STR *hostaddr;
+/* DESCRIPTION
+/*     dns_rr_to_pa() converts the address in a DNS resource record
+/*     into printable form and returns a pointer to the result.
+/*
+/*     Arguments:
+/* .IP rr
+/*     The DNS resource record.
+/* .IP hostaddr
+/*     Storage for the printable address.
+/* DIAGNOSTICS
+/*     The result is null in case of problems, with errno set
+/*     to indicate the nature of the problem.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System libraries. */
+
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* DNS library. */
+
+#include <dns.h>
+
+/* dns_rr_to_pa - resource record to printable address */
+
+const char *dns_rr_to_pa(DNS_RR *rr, MAI_HOSTADDR_STR *hostaddr)
+{
+    if (rr->type == T_A) {
+       return (inet_ntop(AF_INET, rr->data, hostaddr->buf,
+                         sizeof(hostaddr->buf)));
+#ifdef HAS_IPV6
+    } else if (rr->type == T_AAAA) {
+       return (inet_ntop(AF_INET6, rr->data, hostaddr->buf,
+                         sizeof(hostaddr->buf)));
+#endif
+    } else {
+       errno = EAFNOSUPPORT;
+       return (0);
+    }
+}
+
+ /*
+  * Stand-alone test program.
+  */
+#ifdef TEST
+#include <vstream.h>
+#include <myaddrinfo.h>
+
+static const char *myname;
+
+static NORETURN usage(void)
+{
+    msg_fatal("usage: %s dnsaddrtype hostname", myname);
+}
+
+int     main(int argc, char **argv)
+{
+    DNS_RR *rr;
+    MAI_HOSTADDR_STR hostaddr;
+    VSTRING *why;
+    int     type;
+
+    myname = argv[0];
+    if (argc < 3)
+       usage();
+    why = vstring_alloc(1);
+
+    while (*++argv) {
+       if (argv[1] == 0)
+           usage();
+       if ((type = dns_type(argv[0])) == 0)
+           usage();
+       if (dns_lookup(argv[1], type, 0, &rr, (VSTRING *) 0, why) != DNS_OK)
+           msg_fatal("%s: %s", argv[1], vstring_str(why));
+       if (dns_rr_to_pa(rr, &hostaddr) == 0)
+           msg_fatal("dns_rr_to_sa: %m");
+       vstream_printf("%s -> %s\n", argv[1], hostaddr.buf);
+       vstream_fflush(VSTREAM_OUT);
+       argv += 1;
+       dns_rr_free(rr);
+    }
+    vstring_free(why);
+    return (0);
+}
+
+#endif
diff --git a/postfix/src/dns/dns_rr_to_pa.in b/postfix/src/dns/dns_rr_to_pa.in
new file mode 100644 (file)
index 0000000..28d0e77
--- /dev/null
@@ -0,0 +1,2 @@
+a spike.porcupine.org
+aaaa spike.porcupine.org
diff --git a/postfix/src/dns/dns_rr_to_pa.ref b/postfix/src/dns/dns_rr_to_pa.ref
new file mode 100644 (file)
index 0000000..d32e213
--- /dev/null
@@ -0,0 +1,2 @@
+spike.porcupine.org -> 168.100.189.2
+spike.porcupine.org -> 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
diff --git a/postfix/src/dns/dns_rr_to_sa.c b/postfix/src/dns/dns_rr_to_sa.c
new file mode 100644 (file)
index 0000000..4611fda
--- /dev/null
@@ -0,0 +1,163 @@
+/*++
+/* NAME
+/*     dns_rr_to_sa 3
+/* SUMMARY
+/*     resource record to socket address
+/* SYNOPSIS
+/*     #include <dns.h>
+/*
+/*     int     dns_rr_to_sa(rr, port, sa, sa_len)
+/*     DNS_RR  *rr;
+/*     unsigned port;
+/*     struct sockaddr *sa;
+/*     SOCKADDR_SIZE *sa_len;
+/* DESCRIPTION
+/*     dns_rr_to_sa() converts the address in a DNS resource record into
+/*     a socket address of the corresponding type.
+/*
+/*     Arguments:
+/* .IP rr
+/*     DNS resource record pointer.
+/* .IP port
+/*     TCP or UDP port, network byte order.
+/* .IP sa
+/*     Socket address pointer.
+/* .IP sa_len
+/*     On input, the available socket address storage space.
+/*     On output, the amount of space actually used.
+/* DIAGNOSTICS
+/*     The result is non-zero in case of problems, with the
+/*     error type returned via the errno variable.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System libraries. */
+
+#include <sys_defs.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* DNS library. */
+
+#include <dns.h>
+
+/* dns_rr_to_sa - resource record to socket address */
+
+int     dns_rr_to_sa(DNS_RR *rr, unsigned port, struct sockaddr * sa,
+                            SOCKADDR_SIZE *sa_len)
+{
+    SOCKADDR_SIZE sock_addr_len;
+
+    if (rr->type == T_A) {
+       if (rr->data_len != sizeof(SOCK_ADDR_IN_ADDR(sa))) {
+           errno = EINVAL;
+           return (-1);
+       } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN_PTR(sa))) > *sa_len) {
+           errno = ENOSPC;
+           return (-1);
+       } else {
+           memset((char *) SOCK_ADDR_IN_PTR(sa), 0, sock_addr_len);
+           SOCK_ADDR_IN_FAMILY(sa) = AF_INET;
+           SOCK_ADDR_IN_PORT(sa) = port;
+           SOCK_ADDR_IN_ADDR(sa) = IN_ADDR(rr->data);
+#ifdef HAS_SA_LEN
+           sa->sa_len = sock_addr_len;
+#endif
+           *sa_len = sock_addr_len;
+           return (0);
+       }
+#ifdef HAS_IPV6
+    } else if (rr->type == T_AAAA) {
+       if (rr->data_len != sizeof(SOCK_ADDR_IN6_ADDR(sa))) {
+           errno = EINVAL;
+           return (-1);
+       } else if ((sock_addr_len = sizeof(*SOCK_ADDR_IN6_PTR(sa))) > *sa_len) {
+           errno = ENOSPC;
+           return (-1);
+       } else {
+           memset((char *) SOCK_ADDR_IN6_PTR(sa), 0, sock_addr_len);
+           SOCK_ADDR_IN6_FAMILY(sa) = AF_INET6;
+           SOCK_ADDR_IN6_PORT(sa) = port;
+           SOCK_ADDR_IN6_ADDR(sa) = IN6_ADDR(rr->data);
+#ifdef HAS_SA_LEN
+           sa->sa_len = sock_addr_len;
+#endif
+           *sa_len = sock_addr_len;
+           return (0);
+       }
+#endif
+    } else {
+       errno = EAFNOSUPPORT;
+       return (-1);
+    }
+}
+
+ /*
+  * Stand-alone test program.
+  */
+#ifdef TEST
+#include <stdlib.h>
+
+#include <stringops.h>
+#include <vstream.h>
+#include <myaddrinfo.h>
+
+static const char *myname;
+
+static NORETURN usage(void)
+{
+    msg_fatal("usage: %s dnsaddrtype hostname portnumber", myname);
+}
+
+int     main(int argc, char **argv)
+{
+    DNS_RR *rr;
+    MAI_HOSTADDR_STR hostaddr;
+    MAI_SERVPORT_STR portnum;
+    struct sockaddr_storage ss;
+    struct sockaddr *sa = (struct sockaddr *) & ss;
+    SOCKADDR_SIZE sa_len = sizeof(ss);
+    VSTRING *why;
+    int     type;
+    int     port;
+
+    myname = argv[0];
+    if (argc < 4)
+       usage();
+    why = vstring_alloc(1);
+
+    while (*++argv) {
+       if (argv[1] == 0 || argv[2] == 0)
+           usage();
+       if ((type = dns_type(argv[0])) == 0)
+           usage();
+       if (!alldig(argv[2]) || (port = atoi(argv[2])) > 65535)
+           usage();
+       if (dns_lookup(argv[1], type, 0, &rr, (VSTRING *) 0, why) != DNS_OK)
+           msg_fatal("%s: %s", argv[1], vstring_str(why));
+       sa_len = sizeof(ss);
+       if (dns_rr_to_sa(rr, htons(port), sa, &sa_len) != 0)
+           msg_fatal("dns_rr_to_sa: %m");
+       SOCKADDR_TO_HOSTADDR(sa, sa_len, &hostaddr, &portnum, 0);
+       vstream_printf("%s %s -> %s %s\n",
+                      argv[1], argv[2], hostaddr.buf, portnum.buf);
+       vstream_fflush(VSTREAM_OUT);
+       argv += 2;
+       dns_rr_free(rr);
+    }
+    vstring_free(why);
+    return (0);
+}
+
+#endif
diff --git a/postfix/src/dns/dns_rr_to_sa.in b/postfix/src/dns/dns_rr_to_sa.in
new file mode 100644 (file)
index 0000000..1fff6c0
--- /dev/null
@@ -0,0 +1,2 @@
+a spike.porcupine.org 25
+aaaa spike.porcupine.org 25
diff --git a/postfix/src/dns/dns_rr_to_sa.ref b/postfix/src/dns/dns_rr_to_sa.ref
new file mode 100644 (file)
index 0000000..2f23cc6
--- /dev/null
@@ -0,0 +1,2 @@
+spike.porcupine.org 25 -> 168.100.189.2 25
+spike.porcupine.org 25 -> 2001:240:5c7:0:2d0:b7ff:fe88:2ca7 25
diff --git a/postfix/src/dns/dns_sa_to_rr.c b/postfix/src/dns/dns_sa_to_rr.c
new file mode 100644 (file)
index 0000000..da8aa9e
--- /dev/null
@@ -0,0 +1,118 @@
+/*++
+/* NAME
+/*     dns_sa_to_rr 3
+/* SUMMARY
+/*     socket address to resource record
+/* SYNOPSIS
+/*     #include <dns.h>
+/*
+/*     DNS_RR  *dns_sa_to_rr(hostname, pref, sa)
+/*     const char *hostname;
+/*     unsigned pref;
+/*     struct sockaddr *sa;
+/* DESCRIPTION
+/*     dns_sa_to_rr() converts a socket address into a DNS resource record.
+/*
+/*     Arguments:
+/* .IP hostname
+/*     The resource record host name.
+/* .IP pref
+/*     The resource record MX host preference, if applicable.
+/* .IP sa
+/*     Binary address.
+/* DIAGNOSTICS
+/*     The result is a null pointer in case of problems, with the
+/*     errno variable set to indicate the problem type.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System libraries. */
+
+#include <sys_defs.h>
+#include <errno.h>
+
+/* Utility library. */
+
+#include <msg.h>
+
+/* DNS library. */
+
+#include <dns.h>
+
+/* dns_sa_to_rr - socket address to resource record */
+
+DNS_RR *dns_sa_to_rr(const char *hostname, unsigned pref, struct sockaddr * sa)
+{
+#define DUMMY_TTL      0
+
+    if (sa->sa_family == AF_INET) {
+       return (dns_rr_create(hostname, T_A, C_IN, DUMMY_TTL, pref,
+                             (char *) &SOCK_ADDR_IN_ADDR(sa),
+                             sizeof(SOCK_ADDR_IN_ADDR(sa))));
+#ifdef HAS_IPV6
+    } else if (sa->sa_family == AF_INET6) {
+       return (dns_rr_create(hostname, T_AAAA, C_IN, DUMMY_TTL, pref,
+                             (char *) &SOCK_ADDR_IN6_ADDR(sa),
+                             sizeof(SOCK_ADDR_IN6_ADDR(sa))));
+#endif
+    } else {
+       errno = EAFNOSUPPORT;
+       return (0);
+    }
+}
+
+ /*
+  * Stand-alone test program.
+  */
+#ifdef TEST
+#include <vstream.h>
+#include <myaddrinfo.h>
+#include <inet_proto.h>
+
+static const char *myname;
+
+static NORETURN usage(void)
+{
+    msg_fatal("usage: %s hostname", myname);
+}
+
+int     main(int argc, char **argv)
+{
+    MAI_HOSTADDR_STR hostaddr;
+    struct addrinfo *res0;
+    struct addrinfo *res;
+    DNS_RR *rr;
+    int     aierr;
+
+    myname = argv[0];
+    if (argc < 2)
+       usage();
+
+    inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
+
+    while (*++argv) {
+       if ((aierr = hostname_to_sockaddr(argv[0], (char *) 0, 0, &res0)) != 0)
+           msg_fatal("%s: %s", argv[0], MAI_STRERROR(aierr));
+       for (res = res0; res != 0; res = res->ai_next) {
+           if ((rr = dns_sa_to_rr(argv[0], 0, res->ai_addr)) == 0)
+               msg_fatal("dns_sa_to_rr: %m");
+           if (dns_rr_to_pa(rr, &hostaddr) == 0)
+               msg_fatal("dns_rr_to_pa: %m");
+           vstream_printf("%s -> %s\n", argv[0], hostaddr.buf);
+           vstream_fflush(VSTREAM_OUT);
+           dns_rr_free(rr);
+       }
+       freeaddrinfo(res0);
+    }
+    return (0);
+}
+
+#endif
diff --git a/postfix/src/dns/dns_sa_to_rr.in b/postfix/src/dns/dns_sa_to_rr.in
new file mode 100644 (file)
index 0000000..4f83a7d
--- /dev/null
@@ -0,0 +1 @@
+spike.porcupine.org
diff --git a/postfix/src/dns/dns_sa_to_rr.ref b/postfix/src/dns/dns_sa_to_rr.ref
new file mode 100644 (file)
index 0000000..40f5fc8
--- /dev/null
@@ -0,0 +1,2 @@
+spike.porcupine.org -> 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+spike.porcupine.org -> 168.100.189.2
index aabdd98ec44e5e7eb383953680d819d4bb232671..8d32387e891ebc2faa803c5d8c08c19c1bb9f3da 100644 (file)
 
 static void print_rr(DNS_RR *rr)
 {
-    struct in_addr addr;
+    MAI_HOSTADDR_STR host;
 
     while (rr) {
        printf("%s: ttl: %9d ", rr->name, rr->ttl);
        switch (rr->type) {
        case T_A:
-           memcpy((char *) &addr.s_addr, rr->data, sizeof(addr.s_addr));
-           printf("%s: %s\n", dns_strtype(rr->type), inet_ntoa(addr));
+#ifdef T_AAAA
+       case T_AAAA:
+#endif
+           if (dns_rr_to_pa(rr, &host) == 0)
+               msg_fatal("conversion error for resource record type %s: %m",
+                         dns_strtype(rr->type));
+           printf("%s: %s\n", dns_strtype(rr->type), host.buf);
            break;
        case T_CNAME:
        case T_MB:
@@ -85,7 +90,8 @@ int     main(int argc, char **argv)
        msg_fatal("invalid query type: %s", argv[1]);
     name = argv[2];
     msg_verbose = 1;
-    switch (dns_lookup_types(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why, type, 0)) {
+    switch (dns_lookup_l(name, RES_DEFNAMES | RES_DEBUG, &rr, fqdn, why,
+                        DNS_REQ_FLAG_ALL, type, 0)) {
     default:
        msg_fatal("%s", vstring_str(why));
     case DNS_OK:
index bbeb61947526739866ec9dd8e6bd81854d83ec44..166f7084d59971ddefe7b148beb7f443de0d0c8f 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 194a5673821613ad7bc49c785de506e02a6965f0..2092d48e5e34123ed11aa998fdc0543df0d6e1eb 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 9956378003470323f95214cb3a667ca70ede2957..a7f491a62bf3daa798136b65a6a487a71e99f847 100644 (file)
@@ -15,7 +15,7 @@ LIBS  = ../../lib/libglobal.a ../../lib/libutil.a
 all:   $(PROG)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 fsstone: fsstone.o $(LIBS)
        $(CC) $(CFLAGS) -o $@ fsstone.o $(LIBS) $(SYSLIBS)
index 6c8b786cc39513ac382245b654b8698cc8221425..b33801f42e237f4297d860301a868a384b5f0401 100644 (file)
@@ -24,7 +24,8 @@ SRCS  = abounce.c anvil_clnt.c been_here.c bounce.c bounce_log.c \
        tok822_resolve.c tok822_rewrite.c tok822_tree.c trace.c verify.c \
        verify_clnt.c verp_sender.c virtual8_maps.c xtext.c scache_single.c \
        scache_clnt.c scache_multi.c user_acl.c mkmap_cdb.c mkmap_sdbm.c \
-       ehlo_mask.c
+       ehlo_mask.c \
+       wildcard_inet_addr.c valid_mailhost_addr.c
 OBJS   = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        canon_addr.o cfg_parser.o cleanup_strerror.o cleanup_strflags.o \
        clnt_stream.o debug_peer.o debug_process.o defer.o \
@@ -50,7 +51,8 @@ OBJS  = abounce.o anvil_clnt.o been_here.o bounce.o bounce_log.o \
        tok822_resolve.o tok822_rewrite.o tok822_tree.o trace.o verify.o \
        verify_clnt.o verp_sender.o virtual8_maps.o xtext.o scache_single.o \
        scache_clnt.o scache_multi.o user_acl.o mkmap_cdb.o mkmap_sdbm.o \
-       ehlo_mask.o
+       ehlo_mask.o \
+       wildcard_inet_addr.o valid_mailhost_addr.o
 HDRS   = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        canon_addr.h cfg_parser.h cleanup_user.h clnt_stream.h config.h \
        debug_peer.h debug_process.h defer.h deliver_completed.h \
@@ -71,7 +73,8 @@ HDRS  = abounce.h anvil_clnt.h been_here.h bounce.h bounce_log.h \
        resolve_local.h rewrite_clnt.h sent.h smtp_stream.h split_addr.h \
        string_list.h strip_addr.h sys_exits.h timed_ipc.h tok822.h \
        trace.h verify.h verify_clnt.h verp_sender.h virtual8_maps.h \
-       xtext.h scache.h user_acl.h ehlo_mask.h
+       xtext.h scache.h user_acl.h ehlo_mask.h \
+       wildcard_inet_addr.h valid_mailhost_addr.h
 TESTSRC        = rec2stream.c stream2rec.c recdump.c
 DEFS   = -I. -I$(INC_DIR) -D$(SYSTYPE)
 CFLAGS = $(DEBUG) $(OPT) $(DEFS)
@@ -82,7 +85,8 @@ TESTPROG= domain_list dot_lockfile mail_addr_crunch mail_addr_find \
        off_cvt quote_822_local rec2stream recdump resolve_clnt \
        resolve_local rewrite_clnt stream2rec string_list tok822_parse \
        quote_821_local mail_conf_time mime_state strip_addr \
-       virtual8_maps verify_clnt xtext anvil_clnt scache ehlo_mask
+       virtual8_maps verify_clnt xtext anvil_clnt scache ehlo_mask \
+       valid_mailhost_addr
 
 LIBS   = ../../lib/libutil.a
 LIB_DIR        = ../../lib
@@ -94,7 +98,7 @@ MAKES =
 all: $(LIB)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -256,9 +260,13 @@ scache: scache.c $(LIB) $(LIBS)
 ehlo_mask: ehlo_mask.c $(LIB) $(LIBS)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
 
+valid_mailhost_addr: valid_mailhost_addr.c $(LIB) $(LIBS)
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(LIBS) $(SYSLIBS)
+
 tests: tok822_test mime_test mime_nest mime_8bit mime_dom mime_trunc \
        mime_cvt mime_cvt2 mime_cvt3 strip_addr_test tok822_limit_test \
-       virtual8_test xtext_test scache_multi_test ehlo_mask_test
+       virtual8_test xtext_test scache_multi_test ehlo_mask_test \
+       namadr_list_test
 
 tok822_test: tok822_parse tok822_parse.in tok822_parse.ref
        ./tok822_parse <tok822_parse.in >tok822_parse.tmp 2>&1
@@ -362,6 +370,11 @@ ehlo_mask_test: ehlo_mask ehlo_mask.in ehlo_mask.ref
        diff ehlo_mask.ref ehlo_mask.tmp
        rm -f ehlo_mask.tmp
 
+namadr_list_test: namadr_list namadr_list.in namadr_list.ref
+       -sh namadr_list.in >namadr_list.tmp 2>&1
+       diff namadr_list.ref namadr_list.tmp
+       rm -f namadr_list.tmp
+
 printfck: $(OBJS) $(PROG)
        rm -rf printfck
        mkdir printfck
@@ -896,6 +909,7 @@ mail_params.o: ../../include/dict_db.h
 mail_params.o: ../../include/dict.h
 mail_params.o: ../../include/vstream.h
 mail_params.o: ../../include/argv.h
+mail_params.o: ../../include/inet_proto.h
 mail_params.o: mynetworks.h
 mail_params.o: mail_conf.h
 mail_params.o: mail_version.h
@@ -903,6 +917,9 @@ mail_params.o: mail_proto.h
 mail_params.o: ../../include/iostuff.h
 mail_params.o: ../../include/attr.h
 mail_params.o: verp_sender.h
+mail_params.o: own_inet_addr.h
+mail_params.o: ../../include/inet_addr_list.h
+mail_params.o: ../../include/myaddrinfo.h
 mail_params.o: mail_params.h
 mail_pathname.o: mail_pathname.c
 mail_pathname.o: ../../include/sys_defs.h
@@ -1107,10 +1124,15 @@ mynetworks.o: ../../include/msg.h
 mynetworks.o: ../../include/vstring.h
 mynetworks.o: ../../include/vbuf.h
 mynetworks.o: ../../include/inet_addr_list.h
+mynetworks.o: ../../include/myaddrinfo.h
 mynetworks.o: ../../include/name_mask.h
+mynetworks.o: ../../include/mask_addr.h
+mynetworks.o: ../../include/argv.h
 mynetworks.o: own_inet_addr.h
 mynetworks.o: mail_params.h
 mynetworks.o: mynetworks.h
+mynetworks.o: ../../include/sock_addr.h
+mynetworks.o: been_here.h
 mypwd.o: mypwd.c
 mypwd.o: ../../include/sys_defs.h
 mypwd.o: ../../include/mymalloc.h
@@ -1140,11 +1162,14 @@ own_inet_addr.o: ../../include/sys_defs.h
 own_inet_addr.o: ../../include/msg.h
 own_inet_addr.o: ../../include/mymalloc.h
 own_inet_addr.o: ../../include/inet_addr_list.h
+own_inet_addr.o: ../../include/myaddrinfo.h
 own_inet_addr.o: ../../include/inet_addr_local.h
 own_inet_addr.o: ../../include/inet_addr_host.h
 own_inet_addr.o: ../../include/stringops.h
 own_inet_addr.o: ../../include/vstring.h
 own_inet_addr.o: ../../include/vbuf.h
+own_inet_addr.o: ../../include/sock_addr.h
+own_inet_addr.o: ../../include/inet_proto.h
 own_inet_addr.o: mail_params.h
 own_inet_addr.o: own_inet_addr.h
 pipe_command.o: pipe_command.c
@@ -1259,10 +1284,13 @@ resolve_local.o: ../../include/mymalloc.h
 resolve_local.o: string_list.h
 resolve_local.o: ../../include/match_list.h
 resolve_local.o: ../../include/match_ops.h
+resolve_local.o: ../../include/myaddrinfo.h
+resolve_local.o: valid_mailhost_addr.h
+resolve_local.o: ../../include/valid_hostname.h
 resolve_local.o: mail_params.h
 resolve_local.o: own_inet_addr.h
+resolve_local.o: ../../include/inet_addr_list.h
 resolve_local.o: resolve_local.h
-resolve_local.o: match_parent_style.h
 rewrite_clnt.o: rewrite_clnt.c
 rewrite_clnt.o: ../../include/sys_defs.h
 rewrite_clnt.o: ../../include/msg.h
@@ -1455,6 +1483,12 @@ user_acl.o: ../../include/match_ops.h
 user_acl.o: mypwd.h
 user_acl.o: mail_params.h
 user_acl.o: user_acl.h
+valid_mailhost_addr.o: valid_mailhost_addr.c
+valid_mailhost_addr.o: ../../include/sys_defs.h
+valid_mailhost_addr.o: ../../include/msg.h
+valid_mailhost_addr.o: ../../include/myaddrinfo.h
+valid_mailhost_addr.o: valid_mailhost_addr.h
+valid_mailhost_addr.o: ../../include/valid_hostname.h
 verify.o: verify.c
 verify.o: ../../include/sys_defs.h
 verify.o: ../../include/msg.h
@@ -1502,6 +1536,13 @@ virtual8_maps.o: ../../include/argv.h
 virtual8_maps.o: mail_params.h
 virtual8_maps.o: strip_addr.h
 virtual8_maps.o: virtual8_maps.h
+wildcard_inet_addr.o: wildcard_inet_addr.c
+wildcard_inet_addr.o: ../../include/sys_defs.h
+wildcard_inet_addr.o: ../../include/msg.h
+wildcard_inet_addr.o: ../../include/inet_addr_list.h
+wildcard_inet_addr.o: ../../include/myaddrinfo.h
+wildcard_inet_addr.o: ../../include/inet_addr_host.h
+wildcard_inet_addr.o: wildcard_inet_addr.h
 xtext.o: xtext.c
 xtext.o: ../../include/sys_defs.h
 xtext.o: ../../include/msg.h
index abdd56bd1b4d7920afe70eb559628f0cf78cd5fd..b05755355abda70d2775493ac98599dec27518e1 100644 (file)
@@ -39,6 +39,7 @@
 /*     int     var_dont_remove;
 /*     char    *var_inet_interfaces;
 /*     char    *var_proxy_interfaces;
+/*     char    *var_inet_protocols;
 /*     char    *var_mynetworks;
 /*     char    *var_double_bounce_sender;
 /*     int     var_line_limit;
 #ifdef HAS_DB
 #include <dict_db.h>
 #endif
+#include <inet_proto.h>
 
 /* Global library. */
 
-#include "mynetworks.h"
-#include "mail_conf.h"
-#include "mail_version.h"
-#include "mail_proto.h"
-#include "verp_sender.h"
-#include "mail_params.h"
+#include <mynetworks.h>
+#include <mail_conf.h>
+#include <mail_version.h>
+#include <mail_proto.h>
+#include <verp_sender.h>
+#include <own_inet_addr.h>
+#include <mail_params.h>
 
  /*
   * Special configuration variables.
@@ -198,6 +201,7 @@ char   *var_pid_dir;
 int     var_dont_remove;
 char   *var_inet_interfaces;
 char   *var_proxy_interfaces;
+char   *var_inet_protocols;
 char   *var_mynetworks;
 char   *var_double_bounce_sender;
 int     var_line_limit;
@@ -428,6 +432,7 @@ void    mail_params_init()
 {
     static CONFIG_STR_TABLE first_str_defaults[] = {
        VAR_SYSLOG_FACILITY, DEF_SYSLOG_FACILITY, &var_syslog_facility, 1, 0,
+       VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 1, 0,
        0,
     };
     static CONFIG_STR_FN_TABLE function_str_defaults[] = {
@@ -532,6 +537,7 @@ void    mail_params_init()
        0,
     };
     const char *cp;
+    INET_PROTO_INFO *proto_info;
 
     /*
      * Extract syslog_facility early, so that from here on all errors are
@@ -544,6 +550,12 @@ void    mail_params_init()
                  var_config_dir, MAIN_CONF_FILE,
                  VAR_SYSLOG_FACILITY, var_syslog_facility);
 
+    /*
+     * What protocols should we attempt to support? The result is stored in
+     * the global inet_proto_table variable.
+     */
+    proto_info = inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
+
     /*
      * Variables whose defaults are determined at runtime. Some sites use
      * short hostnames in the host table; some sites name their system after
@@ -582,6 +594,13 @@ void    mail_params_init()
      */
     get_mail_conf_str_fn_table(function_str_defaults_2);
 
+    /*
+     * FIX 200412 The IPv6 patch did not call own_inet_addr_list() before
+     * entering the chroot jail on Linux IPv6 systems. Linux has the IPv6
+     * interface list in /proc, which is not available after chrooting.
+     */
+    (void) own_inet_addr_list();
+
     /*
      * The PID variable cannot be set from the configuration file!!
      */
index 14d1f0dd2e15c72236d2f5dc0570e3484c95f80d..afcce39accde9c91826b7ea4453c99c01b3f0d26 100644 (file)
@@ -146,7 +146,9 @@ extern char *var_error_rcpt;
   * Virtual host support. Default is to listen on all machine interfaces.
   */
 #define VAR_INET_INTERFACES    "inet_interfaces"       /* listen addresses */
-#define DEF_INET_INTERFACES    "all"
+#define INET_INTERFACES_ALL    "all"
+#define INET_INTERFACES_LOCAL  "loopback-only"
+#define DEF_INET_INTERFACES    INET_INTERFACES_ALL
 extern char *var_inet_interfaces;
 
 #define VAR_PROXY_INTERFACES   "proxy_interfaces"      /* proxies, NATs */
@@ -784,13 +786,22 @@ extern int var_debug_peer_level;
   * subdirectories, and how deep the forest is.
   */
 #define VAR_HASH_QUEUE_NAMES   "hash_queue_names"
-#define DEF_HASH_QUEUE_NAMES   "incoming, active, deferred, bounce, defer, flush, hold, trace"
+#define DEF_HASH_QUEUE_NAMES   "deferred, defer"
 extern char *var_hash_queue_names;
 
 #define VAR_HASH_QUEUE_DEPTH   "hash_queue_depth"
 #define DEF_HASH_QUEUE_DEPTH   1
 extern int var_hash_queue_depth;
 
+ /*
+  * Multi-protocol support.
+  */
+#define INET_PROTO_NAME_IPV4   "ipv4"
+#define INET_PROTO_NAME_IPV6   "ipv6"
+#define INET_PROTO_NAME_ALL    "all"
+#define VAR_INET_PROTOCOLS     "inet_protocols"
+extern char *var_inet_protocols;
+
  /*
   * SMTP client. Timeouts inspired by RFC 1123. The SMTP recipient limit
   * determines how many recipient addresses the SMTP client sends along with
@@ -894,6 +905,10 @@ extern bool var_smtp_never_ehlo;
 #define DEF_SMTP_BIND_ADDR     ""
 extern char *var_smtp_bind_addr;
 
+#define VAR_SMTP_BIND_ADDR6    "smtp_bind_address6"
+#define DEF_SMTP_BIND_ADDR6    ""
+extern char *var_smtp_bind_addr6;
+
 #define VAR_SMTP_HELO_NAME     "smtp_helo_name"
 #define DEF_SMTP_HELO_NAME     "$myhostname"
 extern char *var_smtp_helo_name;
index b0254a5643a2ba88604daad553fd6e2c085ad905..eeb73cdb430502981e401b35fcfd43aee974d8de 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only.
   */
-#define MAIL_RELEASE_DATE      "20041230"
+#define MAIL_RELEASE_DATE      "20050117"
 #define MAIL_VERSION_NUMBER    "2.2"
 
 #define VAR_MAIL_VERSION       "mail_version"
index 7beba3aab93eda810e8b577ee66336d70e5d513e..f5bd56056d12a182044d26fff04db030c0b77d36 100644 (file)
@@ -1086,7 +1086,7 @@ static void body_end(void *context)
     vstream_fprintf(stream, "BODY END\n");
 }
 
-static void err_print(void *context, int err_flag, const char *text)
+static void err_print(void *unused_context, int err_flag, const char *text)
 {
     msg_warn("%s: %.100s", mime_state_error(err_flag), text);
 }
index a40fea4d0ef6f1e2735308966284cb10b45d6f16..d698be7fc80a75084ee51350a8490d83b08a80c6 100644 (file)
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Dean C. Strik
+/*     Department ICT Services
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB  Eindhoven, Netherlands
+/*     E-mail: <dean@ipnet6.org>
 /*--*/
 
 /* System library. */
 #define IN_CLASSD_NSHIFT       28
 #endif
 
-#define BITS_PER_ADDR          32
-
 /* Utility library. */
 
 #include <msg.h>
 #include <vstring.h>
 #include <inet_addr_list.h>
 #include <name_mask.h>
+#include <myaddrinfo.h>
+#include <mask_addr.h>
+#include <argv.h>
 
 /* Global library. */
 
 #include <own_inet_addr.h>
 #include <mail_params.h>
 #include <mynetworks.h>
+#include <sock_addr.h>
+#include <been_here.h>
 
 /* Application-specific. */
 
@@ -80,13 +90,16 @@ const char *mynetworks(void)
        char   *myname = "mynetworks";
        INET_ADDR_LIST *my_addr_list;
        INET_ADDR_LIST *my_mask_list;
-       unsigned long addr;
-       unsigned long mask;
-       struct in_addr net;
        int     shift;
        int     junk;
        int     i;
        int     mask_style;
+       struct sockaddr_storage *sa;
+       struct sockaddr_storage *ma;
+       int     net_mask_count = 0;
+       ARGV   *argv;
+       BH_TABLE *dup_filter;
+       char  **cpp;
 
        mask_style = name_mask("mynetworks mask style", mask_styles,
                               var_mynetworks_style);
@@ -106,59 +119,155 @@ const char *mynetworks(void)
        my_addr_list = own_inet_addr_list();
        my_mask_list = own_inet_mask_list();
 
-       for (i = 0; i < my_addr_list->used; i++) {
-           addr = ntohl(my_addr_list->addrs[i].s_addr);
-           mask = ntohl(my_mask_list->addrs[i].s_addr);
-
-           switch (mask_style) {
-
-               /*
-                * Natural mask. This is dangerous if you're customer of an
-                * ISP who gave you a small portion of their network.
-                */
-           case MASK_STYLE_CLASS:
-               if (IN_CLASSA(addr)) {
-                   mask = IN_CLASSA_NET;
-                   shift = IN_CLASSA_NSHIFT;
-               } else if (IN_CLASSB(addr)) {
-                   mask = IN_CLASSB_NET;
-                   shift = IN_CLASSB_NSHIFT;
-               } else if (IN_CLASSC(addr)) {
-                   mask = IN_CLASSC_NET;
-                   shift = IN_CLASSC_NSHIFT;
-               } else if (IN_CLASSD(addr)) {
-                   mask = IN_CLASSD_NET;
-                   shift = IN_CLASSD_NSHIFT;
-               } else {
-                   msg_fatal("%s: bad address class: %s",
-                             myname, inet_ntoa(my_addr_list->addrs[i]));
+       for (sa = my_addr_list->addrs, ma = my_mask_list->addrs;
+            sa < my_addr_list->addrs + my_addr_list->used;
+            sa++, ma++) {
+           unsigned long addr;
+           unsigned long mask;
+           struct in_addr net;
+
+           if (SOCK_ADDR_FAMILY(sa) == AF_INET) {
+               addr = ntohl(SOCK_ADDR_IN_ADDR(sa).s_addr);
+               mask = ntohl(SOCK_ADDR_IN_ADDR(ma).s_addr);
+
+               switch (mask_style) {
+
+                   /*
+                    * Natural mask. This is dangerous if you're customer of
+                    * an ISP who gave you a small portion of their network.
+                    */
+               case MASK_STYLE_CLASS:
+                   if (IN_CLASSA(addr)) {
+                       mask = IN_CLASSA_NET;
+                       shift = IN_CLASSA_NSHIFT;
+                   } else if (IN_CLASSB(addr)) {
+                       mask = IN_CLASSB_NET;
+                       shift = IN_CLASSB_NSHIFT;
+                   } else if (IN_CLASSC(addr)) {
+                       mask = IN_CLASSC_NET;
+                       shift = IN_CLASSC_NSHIFT;
+                   } else if (IN_CLASSD(addr)) {
+                       mask = IN_CLASSD_NET;
+                       shift = IN_CLASSD_NSHIFT;
+                   } else {
+                       msg_fatal("%s: unknown address class: %s",
+                                 myname, inet_ntoa(SOCK_ADDR_IN_ADDR(sa)));
+                   }
+                   break;
+
+                   /*
+                    * Subnet mask. This is less unsafe, but still bad if
+                    * you're connected to a large subnet.
+                    */
+               case MASK_STYLE_SUBNET:
+                   for (junk = mask, shift = MAI_V4ADDR_BITS; junk != 0;
+                        shift--, junk <<= 1)
+                        /* void */ ;
+                   break;
+
+                   /*
+                    * Host only. Do not relay authorize other hosts.
+                    */
+               case MASK_STYLE_HOST:
+                   mask = ~0;
+                   shift = 0;
+                   break;
+
+               default:
+                   msg_panic("unknown mynetworks mask style: %s",
+                             var_mynetworks_style);
                }
-               break;
-
-               /*
-                * Subnet mask. This is safe, but breaks backwards
-                * compatibility when used as default setting.
-                */
-           case MASK_STYLE_SUBNET:
-               for (junk = mask, shift = BITS_PER_ADDR; junk != 0; shift--, (junk <<= 1))
-                    /* void */ ;
-               break;
-
-               /*
-                * Host only. Do not relay authorize other hosts.
-                */
-           case MASK_STYLE_HOST:
-               mask = ~0;
-               shift = 0;
-               break;
-
-           default:
-               msg_panic("unknown mynetworks mask style: %s",
-                         var_mynetworks_style);
+               net.s_addr = htonl(addr & mask);
+               vstring_sprintf_append(result, "%s/%d ",
+                                  inet_ntoa(net), MAI_V4ADDR_BITS - shift);
+               net_mask_count++;
+               continue;
+           }
+#ifdef HAS_IPV6
+           else if (SOCK_ADDR_FAMILY(sa) == AF_INET6) {
+               MAI_HOSTADDR_STR hostaddr;
+               unsigned char *ac;
+               unsigned char *end;
+               unsigned char ch;
+               struct sockaddr_in6 net6;
+
+               switch (mask_style) {
+
+                   /*
+                    * There are no classes for IPv6. We default to subnets
+                    * instead.
+                    */
+               case MASK_STYLE_CLASS:
+
+                   /* FALLTHROUGH */
+
+                   /*
+                    * Subnet mask.
+                    */
+               case MASK_STYLE_SUBNET:
+                   ac = (unsigned char *) &SOCK_ADDR_IN6_ADDR(ma);
+                   end = ac + sizeof(SOCK_ADDR_IN6_ADDR(ma));
+                   shift = MAI_V6ADDR_BITS;
+                   while (ac < end) {
+                       if ((ch = *ac++) == (unsigned char) -1) {
+                           shift -= CHAR_BIT;
+                           continue;
+                       } else {
+                           while (ch != 0)
+                               shift--, ch <<= 1;
+                           break;
+                       }
+                   }
+                   break;
+
+                   /*
+                    * Host only. Do not relay authorize other hosts.
+                    */
+               case MASK_STYLE_HOST:
+                   shift = 0;
+                   break;
+
+               default:
+                   msg_panic("unknown mynetworks mask style: %s",
+                             var_mynetworks_style);
+               }
+               /* FIX 200501: IPv6 patch did not clear host bits. */
+               net6 = *SOCK_ADDR_IN6_PTR(sa);
+               mask_addr((unsigned char *) &net6.sin6_addr,
+                         sizeof(net6.sin6_addr),
+                         MAI_V6ADDR_BITS - shift);
+               SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(&net6), SOCK_ADDR_LEN(&net6),
+                                    &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+               vstring_sprintf_append(result, "[%s]/%d ",
+                                    hostaddr.buf, MAI_V6ADDR_BITS - shift);
+               net_mask_count++;
+               continue;
+           }
+#endif
+           else {
+               msg_warn("%s: skipping unknown address family %d",
+                        myname, SOCK_ADDR_FAMILY(sa));
+               continue;
            }
-           net.s_addr = htonl(addr & mask);
-           vstring_sprintf_append(result, "%s/%d ",
-                                  inet_ntoa(net), BITS_PER_ADDR - shift);
+       }
+
+       /*
+        * FIX 200501 IPv6 patch produced repeated results. Some systems
+        * report the same interface multiple times, notably multi-homed
+        * systems with IPv6 link-local or site-local addresses. A
+        * straight-forward sort+uniq produces ugly results, though. Instead
+        * we preserve the original order and use a duplicate filter to
+        * suppress repeated information.
+        */
+       if (net_mask_count > 1) {
+           argv = argv_split(vstring_str(result), " ");
+           VSTRING_RESET(result);
+           dup_filter = been_here_init(net_mask_count, BH_FLAG_NONE);
+           for (cpp = argv->argv; cpp < argv->argv + argv->argc; cpp++)
+               if (!been_here_fixed(dup_filter, *cpp))
+                   vstring_sprintf_append(result, "%s ", *cpp);
+           argv_free(argv);
+           been_here_free(dup_filter);
        }
        if (msg_verbose)
            msg_info("%s: %s", myname, vstring_str(result));
@@ -167,17 +276,22 @@ const char *mynetworks(void)
 }
 
 #ifdef TEST
+#include <inet_proto.h>
 
 char   *var_inet_interfaces;
 char   *var_mynetworks_style;
 
 int     main(int argc, char **argv)
 {
-    if (argc != 3)
-       msg_fatal("usage: %s mask_style interface_list", argv[0]);
+    INET_PROTO_INFO *proto_info;
+
+    if (argc != 4)
+       msg_fatal("usage: %s protocols mask_style interface_list (e.g. \"all subnet all\")",
+                 argv[0]);
     msg_verbose = 10;
-    var_inet_interfaces = argv[2];
-    var_mynetworks_style = argv[1];
+    proto_info = inet_proto_init(argv[0], argv[1]);
+    var_mynetworks_style = argv[2];
+    var_inet_interfaces = argv[3];
     mynetworks();
 }
 
diff --git a/postfix/src/global/namadr_list.in b/postfix/src/global/namadr_list.in
new file mode 100644 (file)
index 0000000..a19a452
--- /dev/null
@@ -0,0 +1,17 @@
+./namadr_list 168.100.189.0/28 dummy 168.100.189.2
+./namadr_list 168.100.189.0/28 dummy 168.100.189.16
+./namadr_list 168.100.189.0/98 dummy 168.100.189.16
+./namadr_list 168.100.589.0/28 dummy 168.100.189.16
+./namadr_list 168.100.189.0/28 dummy 168.100.989.16
+./namadr_list 2001:240:5c7:0:2d0:b7ff:fe88:2ca7 dummy 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+./namadr_list '[2001:240:5c7:0:2d0:b7ff:fe88:2ca7]' dummy 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+./namadr_list '[2001:240:5c7:0:2d0:b7ff:fe88:2ca7]' dummy 2001:240:5c7:0:2d0:b7ff:fe88:2ca8
+./namadr_list '[2001:240:5c7:0:2d0:b7ff:fe88:2ca7]/64' dummy 2001:240:5c7:0:2d0:b7ff:fe88:2ca8
+./namadr_list '[2001:240:5c7::]/64' dummy 2001:240:5c7:0:2d0:b7ff:fe88:2ca8
+./namadr_list '[2001:240:5c7::]/64' dummy 2001:24:5c7:0:2d0:b7ff:fe88:2ca8
+./namadr_list '[2001:24:5c7:0:2d0:b7ff:fe88:2ca8]' dummy 2001:24:5c7:0:2d0:b7ff:fe88:2ca8
+./namadr_list '[2001:24:5c7:0:2d0:b7ff:fe88:2ca8]' dummy 2001:24:5c7:0:2d0:b7ff:fe88:2ca7
+./namadr_list 168.100.189.2 dummy 168.100.189.2
+./namadr_list 168.100.189.2 dummy 168.100.189.3
+./namadr_list '[168.100.189.2]' dummy 168.100.189.2
+./namadr_list '[168.100.189.2]' dummy 168.100.189.3
diff --git a/postfix/src/global/namadr_list.ref b/postfix/src/global/namadr_list.ref
new file mode 100644 (file)
index 0000000..fd6d702
--- /dev/null
@@ -0,0 +1,17 @@
+dummy/168.100.189.2: YES
+dummy/168.100.189.16: NO
+./namadr_list: fatal: bad net/mask pattern: "168.100.189.0/98"
+./namadr_list: fatal: bad net/mask pattern: "168.100.589.0/28"
+dummy/168.100.989.16: NO
+./namadr_list: fatal: unsupported dictionary type: 2001
+dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca7: YES
+dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: NO
+./namadr_list: fatal: non-null host address bits in "2001:240:5c7:0:2d0:b7ff:fe88:2ca7/64", perhaps you should use "2001:240:5c7::/64" instead
+dummy/2001:240:5c7:0:2d0:b7ff:fe88:2ca8: YES
+dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: NO
+dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca8: YES
+dummy/2001:24:5c7:0:2d0:b7ff:fe88:2ca7: NO
+dummy/168.100.189.2: YES
+dummy/168.100.189.3: NO
+dummy/168.100.189.2: YES
+dummy/168.100.189.3: NO
index 3239d6e560b95c840f1d305f293dc158726d5a2b..d3b7d5aec9548273123363a16cd468ddede3c01e 100644 (file)
 /* System library. */
 
 #include <sys_defs.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
 #include <string.h>
 
-#ifdef STRCASECMP_IN_STRINGS_H
-#include <strings.h>
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
@@ -63,6 +57,9 @@
 #include <inet_addr_local.h>
 #include <inet_addr_host.h>
 #include <stringops.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -88,6 +85,9 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
     char   *bufp;
     int     nvirtual;
     int     nlocal;
+    MAI_HOSTADDR_STR hostaddr;
+    struct sockaddr_storage *sa;
+    struct sockaddr_storage *ma;
 
     inet_addr_list_init(addr_list);
     inet_addr_list_init(mask_list);
@@ -96,14 +96,31 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
      * If we are listening on all interfaces (default), ask the system what
      * the interfaces are.
      */
-    if (strcasecmp(var_inet_interfaces, DEF_INET_INTERFACES) == 0) {
-       if (inet_addr_local(addr_list, mask_list) == 0)
+    if (strcmp(var_inet_interfaces, INET_INTERFACES_ALL) == 0) {
+       if (inet_addr_local(addr_list, mask_list,
+                           inet_proto_info()->ai_family_list) == 0)
            msg_fatal("could not find any active network interfaces");
-#if 0
-       if (addr_list->used == 1)
-           msg_warn("found only one active network interface: %s",
-                    inet_ntoa(addr_list->addrs[0]));
-#endif
+    }
+
+    /*
+     * Select all loopback interfaces from the system's available interface
+     * list.
+     */
+    else if (strcmp(var_inet_interfaces, INET_INTERFACES_LOCAL) == 0) {
+       inet_addr_list_init(&local_addrs);
+       inet_addr_list_init(&local_masks);
+       if (inet_addr_local(&local_addrs, &local_masks,
+                           inet_proto_info()->ai_family_list) == 0)
+           msg_fatal("could not find any active network interfaces");
+       for (sa = local_addrs.addrs, ma = local_masks.addrs;
+            sa < local_addrs.addrs + local_addrs.used; sa++, ma++) {
+           if (sock_addr_in_loopback(SOCK_ADDR_PTR(sa))) {
+               inet_addr_list_append(addr_list, SOCK_ADDR_PTR(sa));
+               inet_addr_list_append(mask_list, SOCK_ADDR_PTR(ma));
+           }
+       }
+       inet_addr_list_free(&local_addrs);
+       inet_addr_list_free(&local_masks);
     }
 
     /*
@@ -127,19 +144,29 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
         */
        inet_addr_list_uniq(addr_list);
 
+       /*
+        * Find out the netmask for each virtual interface, by looking it up
+        * among all the local interfaces.
+        */
        inet_addr_list_init(&local_addrs);
        inet_addr_list_init(&local_masks);
-       if (inet_addr_local(&local_addrs, &local_masks) == 0)
+       if (inet_addr_local(&local_addrs, &local_masks,
+                           inet_proto_info()->ai_family_list) == 0)
            msg_fatal("could not find any active network interfaces");
        for (nvirtual = 0; nvirtual < addr_list->used; nvirtual++) {
            for (nlocal = 0; /* see below */ ; nlocal++) {
-               if (nlocal >= local_addrs.used)
+               if (nlocal >= local_addrs.used) {
+                   SOCKADDR_TO_HOSTADDR(
+                                SOCK_ADDR_PTR(addr_list->addrs + nvirtual),
+                                SOCK_ADDR_LEN(addr_list->addrs + nvirtual),
+                                     &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
                    msg_fatal("parameter %s: no local interface found for %s",
-                             VAR_INET_INTERFACES,
-                             inet_ntoa(addr_list->addrs[nvirtual]));
-               if (addr_list->addrs[nvirtual].s_addr
-                   == local_addrs.addrs[nlocal].s_addr) {
-                   inet_addr_list_append(mask_list, &local_masks.addrs[nlocal]);
+                             VAR_INET_INTERFACES, hostaddr.buf);
+               }
+               if (SOCK_ADDR_EQ_ADDR(addr_list->addrs + nvirtual,
+                                     local_addrs.addrs + nlocal)) {
+                   inet_addr_list_append(mask_list,
+                                SOCK_ADDR_PTR(local_masks.addrs + nlocal));
                    break;
                }
            }
@@ -151,7 +178,7 @@ static void own_inet_addr_init(INET_ADDR_LIST *addr_list,
 
 /* own_inet_addr - is this my own internet address */
 
-int     own_inet_addr(struct in_addr * addr)
+int     own_inet_addr(struct sockaddr * addr)
 {
     int     i;
 
@@ -159,7 +186,7 @@ int     own_inet_addr(struct in_addr * addr)
        own_inet_addr_init(&addr_list, &mask_list);
 
     for (i = 0; i < addr_list.used; i++)
-       if (addr->s_addr == addr_list.addrs[i].s_addr)
+       if (SOCK_ADDR_EQ_ADDR(addr, addr_list.addrs + i))
            return (1);
     return (0);
 }
@@ -213,7 +240,7 @@ static void proxy_inet_addr_init(INET_ADDR_LIST *addr_list)
 
 /* proxy_inet_addr - is this my proxy internet address */
 
-int     proxy_inet_addr(struct in_addr * addr)
+int     proxy_inet_addr(struct sockaddr * addr)
 {
     int     i;
 
@@ -224,7 +251,7 @@ int     proxy_inet_addr(struct in_addr * addr)
        proxy_inet_addr_init(&proxy_list);
 
     for (i = 0; i < proxy_list.used; i++)
-       if (addr->s_addr == proxy_list.addrs[i].s_addr)
+       if (SOCK_ADDR_EQ_ADDR(addr, proxy_list.addrs + i))
            return (1);
     return (0);
 }
index 94fbac6a65a9de4c7bdc5de68c421f938af4507e..2f3d2f741afe82aec82b7e23b89d9e376b2aac89 100644 (file)
 /* .nf
 
  /*
-  * System library.
+  * Utility library.
   */
-#include <netinet/in.h>
+#include <inet_addr_list.h>
 
  /*
   * External interface.
   */
-extern int own_inet_addr(struct in_addr *);
+extern int own_inet_addr(struct sockaddr *);
 extern struct INET_ADDR_LIST *own_inet_addr_list(void);
 extern struct INET_ADDR_LIST *own_inet_mask_list(void);
-extern int proxy_inet_addr(struct in_addr *);
+extern int proxy_inet_addr(struct sockaddr *);
 extern struct INET_ADDR_LIST *proxy_inet_addr_list(void);
 
 /* LICENSE
index bad7abf126e8858b686b79f3e5ba69ec6a417bd1..830ad54c2bc7c7a72ebf15c08f89fea7477ab025 100644 (file)
@@ -14,8 +14,8 @@
 /*     resolve_local() determines if the named domain resolves to the
 /*     local mail system, either by case-insensitive exact match
 /*     against the domains, files or tables listed in $mydestination,
-/*     or by any of the network addresses listed in $inet_interfaces
-/*     or in $proxy_interfaces.
+/*     or by a match of an [address-literal] against of the network
+/*     addresses listed in $inet_interfaces or in $proxy_interfaces.
 /*
 /*     resolve_local_init() performs initialization. If this routine is
 /*     not called explicitly ahead of time, it will be called on the fly.
 /* System library. */
 
 #include <sys_defs.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
 
 /* Utility library. */
 
 #include <msg.h>
 #include <mymalloc.h>
 #include <string_list.h>
+#include <myaddrinfo.h>
+#include <valid_mailhost_addr.h>
 
 /* Global library. */
 
 #include <mail_params.h>
 #include <own_inet_addr.h>
 #include <resolve_local.h>
-#include <match_parent_style.h>
 
 /* Application-specific */
 
@@ -80,19 +74,26 @@ int     resolve_local(const char *addr)
 {
     char   *saved_addr = mystrdup(addr);
     char   *dest;
-    struct in_addr ipaddr;
+    const char *bare_dest;
+    struct addrinfo *res0 = 0;
     int     len;
 
-#define RETURN(x) { myfree(saved_addr); return(x); }
+#define RETURN(x) \
+    do { \
+       myfree(saved_addr); \
+       if (res0) \
+           freeaddrinfo(res0); \
+       return(x); \
+    } while (0)
 
     if (resolve_local_list == 0)
        resolve_local_init();
 
     /*
      * Strip one trailing dot but not dot-dot.
-     *
+     * 
      * XXX This should not be distributed all over the code. Problem is,
-     * addresses can enter the system via multiple paths: networks, local  
+     * addresses can enter the system via multiple paths: networks, local
      * forward/alias/include files, even as the result of address rewriting.
      */
     len = strlen(saved_addr);
@@ -113,14 +114,42 @@ int     resolve_local(const char *addr)
     /*
      * Compare the destination against the list of interface addresses that
      * we are supposed to listen on.
+     * 
+     * The destination may be an IPv6 address literal that was buried somewhere
+     * inside a deeply recursively nested address. This information comes
+     * from an untrusted source, and Wietse is not confident that everyone's
+     * getaddrinfo() etc. implementation is sufficiently robust. The syntax
+     * is complex enough with null field compression and with IPv4-in-IPv6
+     * addresses that errors are likely.
+     * 
+     * The solution below is ad-hoc. We neutralize the string as soon as we
+     * realize that its contents could be harmful. We neutralize the string
+     * here, instead of neutralizing it in every resolve_local() caller.
+     * That's because resolve_local knows how the address is going to be
+     * parsed and converted into binary form.
+     * 
+     * There are several more structural solutions to this.
+     * 
+     * - One solution is to disallow address literals. This is not as bad as it
+     * seems: I have never seen actual legitimate use of address literals.
+     * 
+     * - Another solution is to label each string with a trustworthiness label
+     * and to expect that all Postfix infrastructure will exercise additional
+     * caution when given a string with untrusted content. This is not likely
+     * to happen.
+     * 
+     * FIX 200501 IPv6 patch did not require "IPv6:" prefix in numerical
+     * addresses.
      */
     dest = saved_addr;
     if (*dest == '[' && dest[len - 1] == ']') {
        dest++;
        dest[len -= 2] = 0;
-       if ((ipaddr.s_addr = inet_addr(dest)) != INADDR_NONE
-           && (own_inet_addr(&ipaddr) || proxy_inet_addr(&ipaddr)))
-           RETURN(1);
+       if ((bare_dest = valid_mailhost_addr(dest, DO_GRIPE)) != 0
+           && hostaddr_to_sockaddr(bare_dest, (char *) 0, 0, &res0) == 0) {
+           if (own_inet_addr(res0->ai_addr) || proxy_inet_addr(res0->ai_addr))
+               RETURN(1);
+       }
     }
 
     /*
index aea0c1a4b5fc2e133d87109330aa942c94f989dc..ba4b78e7c640116e1ecca75e310a6cb272c44b7b 100644 (file)
@@ -225,7 +225,6 @@ void    smtp_printf(VSTREAM *stream, const char *fmt,...)
 
 int     smtp_fgetc(VSTREAM *stream)
 {
-    int     err;
     int     ch;
 
     /*
diff --git a/postfix/src/global/valid_mailhost_addr.c b/postfix/src/global/valid_mailhost_addr.c
new file mode 100644 (file)
index 0000000..79a7900
--- /dev/null
@@ -0,0 +1,152 @@
+/*++
+/* NAME
+/*     valid_mailhost_addr 3
+/* SUMMARY
+/*     mailhost address syntax validation
+/* SYNOPSIS
+/*     #include <valid_mailhost_addr.h>
+/*
+/*     const char *valid_mailhost_addr(name, gripe)
+/*     const char *name;
+/*     int     gripe;
+/*
+/*     int     valid_mailhost_literal(addr, gripe)
+/*     const char *addr;
+/*     int     gripe;
+/* DESCRIPTION
+/*     valid_mailhost_addr() requires that the input is a valid
+/*     RFC 2821 string representation of an IPv4 or IPv6 network
+/*     address.  A valid IPv4 address is in dotted quad decimal
+/*     form.  A valid IPv6 address includes the "IPV6:" prefix as
+/*     required by RFC 2821, and is in valid hexadecimal form or
+/*     in valid IPv4-in-IPv6 form.  The result value is the bare
+/*     address in the input argument (i.e. text after "IPV6:"
+/*     prefix, if any) in case of success, a null pointer in case
+/*     of failure.
+/*
+/*     valid_mailhost_literal() requires an address enclosed in
+/*     [].  The result is non-zero in case of success, zero in
+/*     case of failure.
+/*
+/*     These routines operate silently unless the gripe parameter
+/*     specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
+/*     provide suitable constants.
+/*
+/*     The IPV6_COL macro defines the "IPv6:" prefix.
+/* DIAGNOSTICS
+/*     Warnings are logged with msg_warn().
+/* SEE ALSO
+/*     valid_hostname(3)
+/*     RFC 952, RFC 1123, RFC 1035, RFC 2821
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <string.h>
+
+#ifdef STRCASECMP_IN_STRINGS_H
+#include <strings.h>
+#endif
+
+/* Utility library. */
+
+#include <msg.h>
+#include <myaddrinfo.h>
+
+/* Global library. */
+
+#include <valid_mailhost_addr.h>
+
+/* Application-specific. */
+
+#define IPV6_COL_LEN       (sizeof(IPV6_COL) - 1)
+#define HAS_IPV6_COL(str)  (strncasecmp((str), IPV6_COL, IPV6_COL_LEN) == 0)
+#define SKIP_IPV6_COL(str) (HAS_IPV6_COL(str) ? (str) + IPV6_COL_LEN : (str))
+
+/* valid_mailhost_addr - validate RFC 2821 numerical address form */
+
+const char *valid_mailhost_addr(const char *addr, int gripe)
+{
+    const char *bare_addr;
+
+    bare_addr = SKIP_IPV6_COL(addr);
+    return ((bare_addr != addr ? valid_ipv6_hostaddr : valid_ipv4_hostaddr)
+           (bare_addr, gripe) ? bare_addr : 0);
+}
+
+/* valid_mailhost_literal - validate [RFC 2821 numerical address] form */
+
+int     valid_mailhost_literal(const char *addr, int gripe)
+{
+    const char *myname = "valid_mailhost_literal";
+    MAI_HOSTADDR_STR hostaddr;
+    const char *last;
+    size_t address_bytes;
+
+    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 ((address_bytes = last - addr - 1) >= sizeof(hostaddr.buf)) {
+       if (gripe)
+           msg_warn("%s: too much text: %.100s", myname, addr);
+       return (0);
+    }
+    strncpy(hostaddr.buf, addr + 1, address_bytes);
+    hostaddr.buf[address_bytes] = 0;
+    return (valid_mailhost_addr(hostaddr.buf, gripe) != 0);
+}
+
+#ifdef TEST
+
+ /*
+  * Test program - reads hostnames from stdin, reports invalid hostnames to
+  * stderr.
+  */
+#include <stdlib.h>
+
+#include <vstring.h>
+#include <vstream.h>
+#include <vstring_vstream.h>
+#include <msg_vstream.h>
+
+int     main(int unused_argc, char **argv)
+{
+    VSTRING *buffer = vstring_alloc(1);
+
+    msg_vstream_init(argv[0], VSTREAM_ERR);
+    msg_verbose = 1;
+
+    while (vstring_fgets_nonl(buffer, VSTREAM_IN)) {
+       msg_info("testing: \"%s\"", vstring_str(buffer));
+       if (vstring_str(buffer)[0] == '[')
+           valid_mailhost_literal(vstring_str(buffer), DO_GRIPE);
+       else
+           valid_mailhost_addr(vstring_str(buffer), DO_GRIPE);
+    }
+    exit(0);
+}
+
+#endif
diff --git a/postfix/src/global/valid_mailhost_addr.h b/postfix/src/global/valid_mailhost_addr.h
new file mode 100644 (file)
index 0000000..95630ae
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef _VALID_MAILHOST_ADDR_H_INCLUDED_
+#define _VALID_MAILHOST_ADDR_H_INCLUDED_
+
+/*++
+/* NAME
+/*     valid_mailhost_addr 3h
+/* SUMMARY
+/*     mailhost address syntax validation
+/* SYNOPSIS
+/*     #include <valid_mailhost_addr.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * Utility library.
+  */
+#include <valid_hostname.h>
+
+ /*
+  * External interface
+  */
+#define IPV6_COL               "IPv6:" /* RFC 2821 */
+
+extern const char *valid_mailhost_addr(const char *, int);
+extern int valid_mailhost_literal(const char *, int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/global/wildcard_inet_addr.c b/postfix/src/global/wildcard_inet_addr.c
new file mode 100644 (file)
index 0000000..97f6c46
--- /dev/null
@@ -0,0 +1,68 @@
+/*++
+/* NAME
+/*     wildcard_inet_addr 3
+/* SUMMARY
+/*     expand wild-card address
+/* SYNOPSIS
+/*     #include <wildcard_inet_addr.h>
+/*
+/*     INET_ADDR_LIST *wildcard_inet_addr(void)
+/* DESCRIPTION
+/*     wildcard_inet_addr() determines all wild-card addresses
+/*     for all supported address families.
+/* DIAGNOSTICS
+/*     Fatal errors: out of memory.
+/* SEE ALSO
+/*     inet_addr_list(3) address list management
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*
+/*     Dean C. Strik
+/*     Department ICT
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB  Eindhoven, Netherlands
+/*     E-mail: <dean@ipnet6.org>
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <inet_addr_list.h>
+#include <inet_addr_host.h>
+
+/* Global library. */
+
+#include <wildcard_inet_addr.h>
+
+/* Application-specific. */
+
+static INET_ADDR_LIST wild_addr_list;
+
+static void wildcard_inet_addr_init(INET_ADDR_LIST *addr_list)
+{
+    inet_addr_list_init(addr_list);
+    if (inet_addr_host(addr_list, "") == 0)
+       msg_fatal("could not get list of wildcard addresses");
+}
+
+/* wildcard_inet_addr_list - return list of addresses */
+
+INET_ADDR_LIST *wildcard_inet_addr_list(void)
+{
+    if (wild_addr_list.used == 0)
+       wildcard_inet_addr_init(&wild_addr_list);
+
+    return (&wild_addr_list);
+}
diff --git a/postfix/src/global/wildcard_inet_addr.h b/postfix/src/global/wildcard_inet_addr.h
new file mode 100644 (file)
index 0000000..46b12e2
--- /dev/null
@@ -0,0 +1,33 @@
+#ifndef _WILDCARD_INET_ADDR_H_INCLUDED_
+#define _WILDCARD_INET_ADDR_H_INCLUDED_
+
+/*++
+/* NAME
+/*     wildcard_inet_addr 3h
+/* SUMMARY
+/*     grab the list of wildcard IP addresses.
+/* SYNOPSIS
+/*     #include <wildcard_inet_addr.h>
+/* DESCRIPTION
+/* .nf
+/*--*/
+
+ /*
+  * Utility library.
+  */
+#include <inet_addr_list.h>
+
+ /*
+  * External interface.
+  */
+extern struct INET_ADDR_LIST *wildcard_inet_addr_list(void);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     foo
+/* AUTHOR(S)
+/*     Jun-ichiro itojun Hagino
+/*--*/
+
+#endif
index 959dd1aefc7ee2a50f86d21fd9a57b02e79338ac..c711cafda3fda2165cdb3d06415e730220de110f 100644 (file)
@@ -143,7 +143,7 @@ static int read_buf(VSTREAM *fp, VSTRING *buf)
     return (len);
 }
 
-main(int unused_argc, char **unused_argv)
+int     main(int unused_argc, char **unused_argv)
 {
     VSTRING *unquoted = vstring_alloc(BUFLEN);
     VSTRING *quoted = vstring_alloc(100);
index 84c822c4505a7b3393058ef9f95ca25c5de3c2cf..416ce71ed8dc38cb1eef52cd0ac5798cc874d6ca 100644 (file)
@@ -20,7 +20,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -86,7 +86,10 @@ lmtp_addr.o: ../../include/vstring.h
 lmtp_addr.o: ../../include/vbuf.h
 lmtp_addr.o: ../../include/mymalloc.h
 lmtp_addr.o: ../../include/inet_addr_list.h
+lmtp_addr.o: ../../include/myaddrinfo.h
 lmtp_addr.o: ../../include/stringops.h
+lmtp_addr.o: ../../include/sock_addr.h
+lmtp_addr.o: ../../include/inet_proto.h
 lmtp_addr.o: ../../include/mail_params.h
 lmtp_addr.o: ../../include/own_inet_addr.h
 lmtp_addr.o: ../../include/dns.h
@@ -129,9 +132,13 @@ lmtp_connect.o: ../../include/timed_connect.h
 lmtp_connect.o: ../../include/stringops.h
 lmtp_connect.o: ../../include/host_port.h
 lmtp_connect.o: ../../include/sane_connect.h
+lmtp_connect.o: ../../include/inet_addr_list.h
+lmtp_connect.o: ../../include/myaddrinfo.h
+lmtp_connect.o: ../../include/sock_addr.h
 lmtp_connect.o: ../../include/mail_params.h
 lmtp_connect.o: ../../include/mail_proto.h
 lmtp_connect.o: ../../include/attr.h
+lmtp_connect.o: ../../include/own_inet_addr.h
 lmtp_connect.o: ../../include/dns.h
 lmtp_connect.o: lmtp.h
 lmtp_connect.o: ../../include/argv.h
index 6c6c3259e8b9823dbd146184648cb8313926d075..1710f787db0121bea076c9657e5f5881e8c50380 100644 (file)
 #include <string.h>
 #include <unistd.h>
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
@@ -78,6 +74,9 @@
 #include <mymalloc.h>
 #include <inet_addr_list.h>
 #include <stringops.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
 static void lmtp_print_addr(char *what, DNS_RR *addr_list)
 {
     DNS_RR *addr;
-    struct in_addr in_addr;
+    MAI_HOSTADDR_STR hostaddr;
 
     msg_info("begin %s address list", what);
     for (addr = addr_list; addr; addr = addr->next) {
-       if (addr->data_len > sizeof(addr)) {
-           msg_warn("skipping address length %d", addr->data_len);
+       if (dns_rr_to_pa(addr, &hostaddr) == 0) {
+           msg_warn("skipping record type %s: %m", dns_strtype(addr->type));
        } else {
-           memcpy((char *) &in_addr, addr->data, sizeof(in_addr));
            msg_info("pref %4d host %s/%s",
                     addr->pref, addr->name,
-                    inet_ntoa(in_addr));
+                    hostaddr.buf);
        }
     }
     msg_info("end %s address list", what);
@@ -119,11 +117,13 @@ static void lmtp_print_addr(char *what, DNS_RR *addr_list)
 static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
 {
     char   *myname = "lmtp_addr_one";
-    struct in_addr inaddr;
-    DNS_FIXED fixed;
     DNS_RR *addr = 0;
     DNS_RR *rr;
-    struct hostent *hp;
+    int     aierr;
+    struct addrinfo *res0;
+    struct addrinfo *res;
+    INET_PROTO_INFO *proto_info = inet_proto_info();
+    int     found;
 
     if (msg_verbose)
        msg_info("%s: host %s", myname, host);
@@ -131,42 +131,53 @@ static DNS_RR *lmtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
     /*
      * Interpret a numerical name as an address.
      */
-    if (ISDIGIT(host[0]) && (inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
-       memset((char *) &fixed, 0, sizeof(fixed));
-       return (dns_rr_append(addr_list,
-                             dns_rr_create(host, &fixed, pref,
-                                       (char *) &inaddr, sizeof(inaddr))));
+    if (hostaddr_to_sockaddr(host, (char *) 0, 0, &res0) == 0
+       && strchr((char *) proto_info->sa_family_list, res0->ai_family) != 0) {
+       if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
+           msg_fatal("host %s: conversion error for address family %d: %m",
+                   host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
+       addr_list = dns_rr_append(addr_list, addr);
+       freeaddrinfo(res0);
+       return (addr_list);
     }
 
     /*
-     * Use gethostbyname() when DNS is disabled.
+     * Use native name service when DNS is disabled.
      */
+#define RETRY_AI_ERROR(e) \
+       ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
+
     if (var_disable_dns) {
-       memset((char *) &fixed, 0, sizeof(fixed));
-       if ((hp = gethostbyname(host)) == 0) {
-           vstring_sprintf(why, "%s: host not found", host);
-           lmtp_errno = LMTP_FAIL;
-       } else if (hp->h_addrtype != AF_INET) {
-           vstring_sprintf(why, "%s: host not found", host);
-           msg_warn("%s: unknown address family %d for %s",
-                    myname, hp->h_addrtype, host);
-           lmtp_errno = LMTP_FAIL;
+       if ((aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0)) != 0) {
+           vstring_sprintf(why, "%s: %s", host, MAI_STRERROR(aierr));
+           lmtp_errno = (RETRY_AI_ERROR(aierr) ? LMTP_RETRY : LMTP_FAIL);
        } else {
-           while (hp->h_addr_list[0]) {
-               addr_list = dns_rr_append(addr_list,
-                                         dns_rr_create(host, &fixed, pref,
-                                                       hp->h_addr_list[0],
-                                                       sizeof(inaddr)));
-               hp->h_addr_list++;
+           for (found = 0, res = res0; res != 0; res = res->ai_next) {
+               if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+                   msg_info("skipping address family %d for host %s",
+                            res->ai_family, host);
+                   continue;
+               }
+               found++;
+               if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
+                   msg_fatal("host %s: conversion error for address family %d: %m",
+                   host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
+               addr_list = dns_rr_append(addr_list, addr);
+           }
+           freeaddrinfo(res0);
+           if (found == 0) {
+               vstring_sprintf(why, "%s: host not found", host);
+               lmtp_errno = LMTP_FAIL;
            }
+           return (addr_list);
        }
-       return (addr_list);
     }
 
     /*
      * Append the addresses for this host to the address list.
      */
-    switch (dns_lookup(host, T_A, RES_DEFNAMES, &addr, (VSTRING *) 0, why)) {
+    switch (dns_lookup_v(host, RES_DEFNAMES, &addr, (VSTRING *) 0, why,
+                        DNS_REQ_FLAG_ALL, proto_info->dns_atype_list)) {
     case DNS_OK:
        for (rr = addr; rr; rr = rr->next)
            rr->pref = pref;
index 36c19246cf1c7465c4ad62cef45c0ddab88e4ff7..e00a151149b79651c211f4d06566f79f77c0e646 100644 (file)
 #include <stringops.h>
 #include <host_port.h>
 #include <sane_connect.h>
+#include <inet_addr_list.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
 
 /* Global library. */
 
 #include <mail_params.h>
 #include <mail_proto.h>
+#include <own_inet_addr.h>
 
 /* DNS library. */
 
 #include <dns.h>
-
+       
 /* Application-specific. */
 
 #include "lmtp.h"
@@ -168,14 +172,18 @@ static LMTP_SESSION *lmtp_connect_addr(DNS_RR *addr, unsigned port,
                                      const char *destination, VSTRING *why)
 {
     char   *myname = "lmtp_connect_addr";
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;
+    struct sockaddr *sa = SOCK_ADDR_PTR(&ss);
+    SOCKADDR_SIZE salen = sizeof(ss);
+    MAI_HOSTADDR_STR hostaddr;
     int     sock;
 
     /*
      * Sanity checks.
      */
-    if (addr->data_len > sizeof(sin.sin_addr)) {
-       msg_warn("%s: skip address with length %d", myname, addr->data_len);
+    if (dns_rr_to_sa(addr, port, sa, &salen) != 0) {
+       msg_warn("%s: skip address type %s: %m",
+                myname, dns_strtype(addr->type));
        lmtp_errno = LMTP_RETRY;
        return (0);
     }
@@ -183,25 +191,19 @@ static LMTP_SESSION *lmtp_connect_addr(DNS_RR *addr, unsigned port,
     /*
      * Initialize.
      */
-    memset((char *) &sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-
-    if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
+    if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
        msg_fatal("%s: socket: %m", myname);
 
     /*
      * Connect to the LMTP server.
      */
-    sin.sin_port = port;
-    memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
-
+    SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
     if (msg_verbose)
        msg_info("%s: trying: %s[%s] port %d...",
-                myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
+                myname, addr->name, hostaddr.buf, ntohs(port));
 
-    return (lmtp_connect_sock(sock, (struct sockaddr *) & sin, sizeof(sin),
-                             addr->name, inet_ntoa(sin.sin_addr),
-                             destination, why));
+    return (lmtp_connect_sock(sock, sa, salen,
+                             addr->name, hostaddr.buf, destination, why));
 }
 
 /* lmtp_connect_sock - connect a socket over some transport */
@@ -313,7 +315,7 @@ static char *lmtp_parse_destination(const char *destination, char *def_service,
      * Parse the host/port information. We're working with a copy of the
      * destination argument so the parsing can be destructive.
      */
-    if ((err = host_port(buf, hostp, &service, def_service)) != 0)
+    if ((err = host_port(buf, hostp, (char *) 0, &service, def_service)) != 0)
        msg_fatal("%s in LMTP server description: %s", err, destination);
 
     /*
@@ -321,9 +323,11 @@ static char *lmtp_parse_destination(const char *destination, char *def_service,
      * aren't going to have lmtp defined as a service, use a default value
      * instead of just blowing up.
      */
-    if (alldig(service) && (port = atoi(service)) != 0)
+    if (alldig(service)) {
+       if ((port = atoi(service)) >= 65536)
+           msg_fatal("bad numeric port in destination: %s", destination);
        *portp = htons(port);
-    else if ((sp = getservbyname(service, protocol)) != 0)
+    else if ((sp = getservbyname(service, protocol)) != 0)
        *portp = sp->s_port;
     else
        *portp = htons(var_lmtp_tcp_port);
index a76c1dfdff6a5d705befd63bfc744ff63da6e457..36feee0d1a5d988c2b779a6a85c4a99dc15ae427 100644 (file)
@@ -22,7 +22,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -436,8 +436,8 @@ resolve.o: ../../include/mail_proto.h
 resolve.o: ../../include/vstream.h
 resolve.o: ../../include/iostuff.h
 resolve.o: ../../include/attr.h
-resolve.o: ../../include/rewrite_clnt.h
 resolve.o: ../../include/resolve_clnt.h
+resolve.o: ../../include/rewrite_clnt.h
 resolve.o: ../../include/tok822.h
 resolve.o: ../../include/mail_params.h
 resolve.o: ../../include/defer.h
index c444c99195ca0fd43e28309144ca3657048f7f20..1b4ba914543f09b6e80927b99031f1e59d0304c0 100644 (file)
@@ -25,7 +25,7 @@ BIN_DIR       = ../../libexec
 all:   $(PROG) $(LIB)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
@@ -106,6 +106,7 @@ master.o: ../../include/debug_process.h
 master.o: ../../include/mail_task.h
 master.o: ../../include/mail_conf.h
 master.o: ../../include/open_lock.h
+master.o: ../../include/inet_proto.h
 master.o: master.h
 master_avail.o: master_avail.c
 master_avail.o: ../../include/sys_defs.h
@@ -129,13 +130,15 @@ master_ent.o: ../../include/argv.h
 master_ent.o: ../../include/stringops.h
 master_ent.o: ../../include/readlline.h
 master_ent.o: ../../include/inet_addr_list.h
-master_ent.o: ../../include/inet_util.h
+master_ent.o: ../../include/myaddrinfo.h
+master_ent.o: ../../include/host_port.h
 master_ent.o: ../../include/inet_addr_host.h
 master_ent.o: ../../include/mail_proto.h
 master_ent.o: ../../include/iostuff.h
 master_ent.o: ../../include/attr.h
 master_ent.o: ../../include/mail_params.h
 master_ent.o: ../../include/own_inet_addr.h
+master_ent.o: ../../include/wildcard_inet_addr.h
 master_ent.o: master_proto.h
 master_ent.o: master.h
 master_flow.o: master_flow.c
@@ -154,8 +157,10 @@ master_listen.o: ../../include/stringops.h
 master_listen.o: ../../include/vstring.h
 master_listen.o: ../../include/vbuf.h
 master_listen.o: ../../include/inet_addr_list.h
+master_listen.o: ../../include/myaddrinfo.h
 master_listen.o: ../../include/set_eugid.h
 master_listen.o: ../../include/set_ugid.h
+master_listen.o: ../../include/sock_addr.h
 master_listen.o: ../../include/mail_params.h
 master_listen.o: master.h
 master_proto.o: master_proto.c
@@ -180,6 +185,8 @@ master_spawn.o: ../../include/msg.h
 master_spawn.o: ../../include/binhash.h
 master_spawn.o: ../../include/mymalloc.h
 master_spawn.o: ../../include/events.h
+master_spawn.o: ../../include/vstring.h
+master_spawn.o: ../../include/vbuf.h
 master_spawn.o: ../../include/argv.h
 master_spawn.o: master_proto.h
 master_spawn.o: master.h
index 70c3c2fb11399524a2260dd2120a64a639e6f110..9c1476243539ae5751594db13d20464421a45dbe 100644 (file)
@@ -78,9 +78,6 @@
 /* RESOURCE AND RATE CONTROLS
 /* .ad
 /* .fi
-/* .IP "\fBdaemon_timeout (18000s)\fR"
-/*     How much time a Postfix daemon process may take to handle a
-/*     request before it is terminated by a built-in watchdog timer.
 /* .IP "\fBdefault_process_limit (100)\fR"
 /*     The default maximal number of Postfix child processes that provide
 /*     a given service.
 /* .IP "\fBinet_interfaces (all)\fR"
 /*     The network interface addresses that this mail system receives mail
 /*     on.
+/* .IP "\fBinet_protocols (ipv4)\fR"
+/*     The Internet protocols Postfix will attempt to use when making
+/*     or accepting connections.
 /* .IP "\fBimport_environment (see 'postconf -d' output)\fR"
 /*     The list of environment parameters that a Postfix process will
 /*     import from a non-Postfix parent process.
 #include <mail_task.h>
 #include <mail_conf.h>
 #include <open_lock.h>
+#include <inet_proto.h>
 
 /* Application-specific. */
 
@@ -194,6 +195,13 @@ static void master_exit_event(int unused_event, char *unused_context)
     exit(0);
 }
 
+/* usage - show hint and terminate */
+
+static NORETURN usage(const char *me)
+{
+    msg_fatal("usage: %s [-c config_dir] [-e exit_time] [-D (debug)] [-t (test)] [-v]", me);
+}
+
 /* main - main program */
 
 int     main(int argc, char **argv)
@@ -319,11 +327,17 @@ int     main(int argc, char **argv)
            msg_verbose++;
            break;
        default:
-           msg_fatal("usage: %s [-c config_dir] [-e exit_time] [-D (debug)] [-t (test)] [-v]", argv[0]);
+           usage(argv[0]);
            /* NOTREACHED */
        }
     }
 
+    /*
+     * This program takes no other arguments.
+     */
+    if (argc > optind)
+       usage(argv[0]);
+
     /*
      * Final initializations. Unfortunately, we must read the global Postfix
      * configuration file after doing command-line processing, so that we get
@@ -332,6 +346,13 @@ int     main(int argc, char **argv)
      */
     master_vars_init();
 
+    /*
+     * In case of multi-protocol support. This needs to be done because
+     * master does not invoke mail_params_init() (it was written before that
+     * code existed).
+     */
+    (void) inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
+
     /*
      * Environment import filter, to enforce consistent behavior whether
      * Postfix is started by hand, or at system boot time.
index 8c22bb91c952709b43f338b1c8940d47f434784b..adb6349a7a5ce70d8efa3a47dbf855871bfe420e 100644 (file)
@@ -84,7 +84,7 @@
 #include <stringops.h>
 #include <readlline.h>
 #include <inet_addr_list.h>
-#include <inet_util.h>
+#include <host_port.h>
 #include <inet_addr_host.h>
 
 /* Global library. */
@@ -92,6 +92,7 @@
 #include <mail_proto.h>
 #include <mail_params.h>
 #include <own_inet_addr.h>
+#include <wildcard_inet_addr.h>
 
 /* Local stuff. */
 
@@ -234,6 +235,7 @@ MASTER_SERV *get_master_ent()
     int     n;
     char   *bufp;
     char   *atmp;
+    const char *parse_err;
     static char *saved_interfaces = 0;
 
     if (master_fp == 0)
@@ -297,7 +299,11 @@ MASTER_SERV *get_master_ent()
                     VAR_INET_INTERFACES);
        }
        serv->type = MASTER_SERV_TYPE_INET;
-       atmp = inet_parse(name, &host, &port);
+       atmp = mystrdup(name);
+       if ((parse_err = host_port(atmp, &host, "", &port, (char *) 0)) != 0)
+           msg_fatal("%s: line %d: %s in \"%s\"",
+                     VSTREAM_PATH(master_fp), master_line,
+                     parse_err, name);
        if (*host) {
            serv->flags |= MASTER_FLAG_INETHOST;/* host:port */
            MASTER_INET_ADDRLIST(serv) = (INET_ADDR_LIST *)
@@ -305,14 +311,14 @@ MASTER_SERV *get_master_ent()
            inet_addr_list_init(MASTER_INET_ADDRLIST(serv));
            if (inet_addr_host(MASTER_INET_ADDRLIST(serv), host) == 0)
                msg_fatal("%s: line %d: bad hostname or network address: %s",
-                         VSTREAM_PATH(master_fp), master_line, host);
+                         VSTREAM_PATH(master_fp), master_line, name);
            inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
            serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
-       } else if (strcasecmp(saved_interfaces, DEF_INET_INTERFACES) == 0) {
-           MASTER_INET_ADDRLIST(serv) = 0;     /* wild-card */
-           serv->listen_fd_count = 1;
        } else {
-           MASTER_INET_ADDRLIST(serv) = own_inet_addr_list();  /* virtual */
+           MASTER_INET_ADDRLIST(serv) =
+               strcasecmp(saved_interfaces, INET_INTERFACES_ALL) ?
+               own_inet_addr_list() :          /* virtual */
+               wildcard_inet_addr_list();      /* wild-card */
            inet_addr_list_uniq(MASTER_INET_ADDRLIST(serv));
            serv->listen_fd_count = MASTER_INET_ADDRLIST(serv)->used;
        }
index 9ff3056d1eb2394322f3cb363fd654fee5a77322..49d16d9e1dd6f39f558a2a742d09e818e80cdcbd 100644 (file)
@@ -55,6 +55,8 @@
 #include <set_eugid.h>
 #include <set_ugid.h>
 #include <iostuff.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
 
 /* Global library. */
 
@@ -71,6 +73,8 @@ void    master_listen_init(MASTER_SERV *serv)
     char   *myname = "master_listen_init";
     char   *end_point;
     int     n;
+    MAI_HOSTADDR_STR hostaddr;
+    struct sockaddr *sa;
 
     /*
      * Find out what transport we should use, then create one or more
@@ -105,24 +109,22 @@ void    master_listen_init(MASTER_SERV *serv)
        /*
         * INET-domain listener endpoints can be wildcarded (the default) or
         * bound to specific interface addresses.
+        * 
+        * With dual-stack IPv4/6 systems it does not matter, we have to specify
+        * the addresses anyway, either explicit or wild-card.
         */
     case MASTER_SERV_TYPE_INET:
-       if (MASTER_INET_ADDRLIST(serv) == 0) {  /* wild-card */
-           serv->listen_fd[0] =
-               inet_listen(MASTER_INET_PORT(serv),
-                           serv->max_proc > var_proc_limit ?
-                           serv->max_proc : var_proc_limit, NON_BLOCKING);
-           close_on_exec(serv->listen_fd[0], CLOSE_ON_EXEC);
-       } else {                                /* virtual or host:port */
-           for (n = 0; n < serv->listen_fd_count; n++) {
-               end_point = concatenate(inet_ntoa(MASTER_INET_ADDRLIST(serv)->addrs[n]),
-                                  ":", MASTER_INET_PORT(serv), (char *) 0);
-               serv->listen_fd[n]
-                   = inet_listen(end_point, serv->max_proc > var_proc_limit ?
-                            serv->max_proc : var_proc_limit, NON_BLOCKING);
-               close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC);
-               myfree(end_point);
-           }
+       for (n = 0; n < serv->listen_fd_count; n++) {
+           sa = SOCK_ADDR_PTR(MASTER_INET_ADDRLIST(serv)->addrs + n);
+           SOCKADDR_TO_HOSTADDR(sa, SOCK_ADDR_LEN(sa), &hostaddr,
+                                (MAI_SERVPORT_STR *) 0, 0);
+           end_point = concatenate(hostaddr.buf,
+                                   ":", MASTER_INET_PORT(serv), (char *) 0);
+           serv->listen_fd[n]
+               = inet_listen(end_point, serv->max_proc > var_proc_limit ?
+                             serv->max_proc : var_proc_limit, NON_BLOCKING);
+           close_on_exec(serv->listen_fd[n], CLOSE_ON_EXEC);
+           myfree(end_point);
        }
        break;
     default:
index d82ae49f9fa7a1122339f03d739b21bf4e3064b3..53b37220b98cb6b45042b06a54806f8bf727a93c 100644 (file)
@@ -45,6 +45,7 @@
  /*
   * Tunable parameters.
   */
+char   *var_inet_protocols;
 int     var_proc_limit;
 int     var_throttle_time;
 
@@ -53,6 +54,10 @@ int     var_throttle_time;
 void    master_vars_init(void)
 {
     char   *path;
+    static CONFIG_STR_TABLE str_table[] = {
+       VAR_INET_PROTOCOLS, DEF_INET_PROTOCOLS, &var_inet_protocols, 1, 0,
+       0,
+    };
     static CONFIG_INT_TABLE int_table[] = {
        VAR_PROC_LIMIT, DEF_PROC_LIMIT, &var_proc_limit, 1, 0,
        0,
@@ -61,11 +66,20 @@ void    master_vars_init(void)
        VAR_THROTTLE_TIME, DEF_THROTTLE_TIME, &var_throttle_time, 1, 0,
        0,
     };
+    static char *saved_inet_protocols;
 
+    if (var_inet_protocols && !saved_inet_protocols)
+       saved_inet_protocols = mystrdup(var_inet_protocols);
     mail_conf_read();
+    get_mail_conf_str_table(str_table);
     get_mail_conf_int_table(int_table);
     get_mail_conf_time_table(time_table);
     path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
     fset_master_ent(path);
     myfree(path);
+
+    if (saved_inet_protocols && strcmp(var_inet_protocols, saved_inet_protocols)) {
+       msg_warn("ignoring %s change", VAR_INET_PROTOCOLS);
+       msg_warn("to change %s, stop and start Postfix", VAR_INET_PROTOCOLS);
+    }
 }
index 4451a2d44e387dae3f66333c9a341188d13c1927..2a78eba16add858cfb374c85792f3795ed6a535b 100644 (file)
@@ -20,7 +20,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 8d832721e48d7c13cfba8cb0360a4c8b78472d41..57282f9acf6dfc57d143d805305c4e4d111e0fb2 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index dd7066f10f96fc8d40b6b3c39fe6be4b021b9df8..affdcd9e5991bcb2cb8a3cc9601dd9894248dab4 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index ff936365016951b4fb0a4c7cc1e917701de45286..217e98e4734d31824d036e0b989de37d13d4845a 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 update: ../../bin/$(PROG)
 
index bacd2dd16bdfcaebf299c960a8f1215778a0b307..2d9fd3464aefa44300609fa2e99e0dd012c4c6bd 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 2910a674ccec143421718cf10ab6678780a8bb3c..b7f93e86ec35cfec5cff825370aeee660f3a1abb 100644 (file)
@@ -26,7 +26,7 @@ $(PROG): $(OBJS) $(LIBS)
         ./$(PROG) -d) |egrep -v '^(myhostname|mydomain|mynetworks) ' >$@
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -83,6 +83,7 @@ postconf.o: ../../include/mymalloc.h
 postconf.o: ../../include/split_at.h
 postconf.o: ../../include/vstring_vstream.h
 postconf.o: ../../include/myflock.h
+postconf.o: ../../include/inet_proto.h
 postconf.o: ../../include/mynetworks.h
 postconf.o: ../../include/mail_conf.h
 postconf.o: ../../include/mail_dict.h
index 8da57e1e23f3afd740a2ca18d9746370098f24d8..9d59dfcc99282da1bcd8db7b842fa7bdf22fb989 100644 (file)
 #include <split_at.h>
 #include <vstring_vstream.h>
 #include <myflock.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -363,6 +364,7 @@ static const char *check_mydomainname(void)
 
 static const char *check_mynetworks(void)
 {
+    INET_PROTO_INFO *proto_info;
     const char *junk;
 
     if (var_inet_interfaces == 0) {
@@ -377,6 +379,13 @@ static const char *check_mynetworks(void)
            junk = DEF_MYNETWORKS_STYLE;
        var_mynetworks_style = mystrdup(junk);
     }
+    if (var_inet_protocols == 0) {
+       if ((mode & SHOW_DEFS)
+           || !(junk = mail_conf_lookup_eval(VAR_INET_PROTOCOLS)))
+           junk = DEF_INET_PROTOCOLS;
+       var_inet_protocols = mystrdup(junk);
+       proto_info = inet_proto_init(VAR_INET_PROTOCOLS, var_inet_protocols);
+    }
     return (mynetworks());
 }
 
index 48af4b9030a58081e462e175bcf2e4ab6f53e7fb..06f79c548a6299f567f79c5e67b172a33219b310 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 4249375d6afd10fe3ce49a674593ed07c31882c5..31615b51bb0e7e0e7bf62954045d66af00e6d220 100644 (file)
@@ -17,7 +17,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 3e63ead93b3ab082e43ef7748a12cb04aa51fd76..a5cc48b047fe17a1afb244847cc4cd403a04f228 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 04c283f6cd5e94d006617d0804e69ae65af52cba..071fe26aa8a09bc970b7077f3326775e4c9f867e 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index e914094f16c97cff828b7603b5b5f7d890aa3e27..586aa61097adb434882a1ceaaaa68716b8d0c903 100644 (file)
@@ -17,7 +17,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index a598181f2177ee6297ff6c900cfe11764a0396b2..3f0798af68d1ea9e3c998743810cdba7c9971813 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 update: ../../bin/$(PROG)
 
index 470f03c15a355ddb488d26da1b116504b74d1651..98ba568f74bfec485c16855aebcd9a62efb30439 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -78,3 +78,4 @@ postqueue.o: ../../include/flush_clnt.h
 postqueue.o: ../../include/smtp_stream.h
 postqueue.o: ../../include/vstring.h
 postqueue.o: ../../include/user_acl.h
+postqueue.o: ../../include/valid_mailhost_addr.h
index dc2464c77d740398c78363ab56c3fe0ae06e85a9..1d991ea4924bd1a6f4bd5026107c3307e7e0e016 100644 (file)
@@ -51,7 +51,9 @@
 /* .RE
 /* .IP "\fB-s \fIsite\fR"
 /*     Schedule immediate delivery of all mail that is queued for the named
-/*     \fIsite\fR. The site must be eligible for the "fast flush" service.
+/*     \fIsite\fR. A numerical site must be specified as a valid RFC 2821
+/*     address literal enclosed in [], just like in email addresses.
+/*     The site must be eligible for the "fast flush" service.
 /*     See \fBflush\fR(8) for more information about the "fast flush"
 /*     service.
 /*
 #include <flush_clnt.h>
 #include <smtp_stream.h>
 #include <user_acl.h>
+#include <valid_mailhost_addr.h>
 
 /* Application-specific. */
 
@@ -474,14 +477,10 @@ int     main(int argc, char **argv)
      */
     if (site_to_flush != 0) {
        bad_site = 0;
-       if (*site_to_flush == '['
-           && *(last = site_to_flush + strlen(site_to_flush) - 1) == ']') {
-           *last = 0;
-           bad_site = !valid_hostaddr(site_to_flush + 1, DONT_GRIPE);
-           *last = ']';
+       if (*site_to_flush == '[') {
+           bad_site = !valid_mailhost_literal(site_to_flush, DONT_GRIPE);
        } else {
-           bad_site = (!valid_hostname(site_to_flush, DONT_GRIPE)
-                       && !valid_hostaddr(site_to_flush, DONT_GRIPE));
+           bad_site = !valid_hostname(site_to_flush, DONT_GRIPE);
        }
        if (bad_site)
            msg_fatal_status(EX_USAGE,
index 98eb5f61a30aa84e4310e3c5c44b9d45d0771fcf..1930af83d0f614ccae34b4dc2274bdafdf7aa231 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 42c9148fd06f988ae33df2d84333807a74f7d3fc..96c3b65b03c54cd8ca425ae618e2a9a493c71403 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index e069952ae5fe79923642fb3b99771c1b9723bd5c..0a7e2caadcedeb1da41b3811021d713a453c1c4c 100644 (file)
@@ -22,7 +22,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 3f24a9351f293cca2d8ecf2a2adb6a3100994a48..e1b3250a2ed593b2414743a41ad2907805642c88 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -100,12 +100,19 @@ qmqpd_peer.o: qmqpd_peer.c
 qmqpd_peer.o: ../../include/sys_defs.h
 qmqpd_peer.o: ../../include/msg.h
 qmqpd_peer.o: ../../include/mymalloc.h
-qmqpd_peer.o: ../../include/valid_hostname.h
 qmqpd_peer.o: ../../include/stringops.h
 qmqpd_peer.o: ../../include/vstring.h
 qmqpd_peer.o: ../../include/vbuf.h
-qmqpd_peer.o: qmqpd.h
+qmqpd_peer.o: ../../include/myaddrinfo.h
+qmqpd_peer.o: ../../include/sock_addr.h
+qmqpd_peer.o: ../../include/inet_proto.h
+qmqpd_peer.o: ../../include/mail_proto.h
 qmqpd_peer.o: ../../include/vstream.h
+qmqpd_peer.o: ../../include/iostuff.h
+qmqpd_peer.o: ../../include/attr.h
+qmqpd_peer.o: ../../include/valid_mailhost_addr.h
+qmqpd_peer.o: ../../include/valid_hostname.h
+qmqpd_peer.o: qmqpd.h
 qmqpd_peer.o: ../../include/mail_stream.h
 qmqpd_state.o: qmqpd_state.c
 qmqpd_state.o: ../../include/sys_defs.h
index 0399e36a90081fcae961f071a9c647b21162a552..f86355f5ebafcce6ca7b24cf58425f6c45546e8c 100644 (file)
@@ -49,7 +49,7 @@
 /*     it is queued.
 /* .IP "\fBreceive_override_options (empty)\fR"
 /*     Enable or disable recipient validation, built-in content
-/*     filtering, or address rewriting.
+/*     filtering, or address mapping.
 /* RESOURCE AND RATE CONTROLS
 /* .ad
 /* .fi
@@ -323,7 +323,7 @@ static void qmqpd_write_attributes(QMQPD_STATE *state)
                    MAIL_ATTR_CLIENT_NAME, state->name);
     if (IS_AVAIL_CLIENT_ADDR(state->addr))
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
-                   MAIL_ATTR_CLIENT_ADDR, state->addr);
+                   MAIL_ATTR_CLIENT_ADDR, state->rfc_addr);
     if (IS_AVAIL_CLIENT_NAMADDR(state->namaddr))
        rec_fprintf(state->cleanup, REC_TYPE_ATTR, "%s=%s",
                    MAIL_ATTR_ORIGIN, state->namaddr);
@@ -402,7 +402,7 @@ static void qmqpd_write_content(QMQPD_STATE *state)
      */
     rec_fputs(state->cleanup, REC_TYPE_MESG, "");
     rec_fprintf(state->cleanup, REC_TYPE_NORM, "Received: from %s (%s [%s])",
-               state->name, state->name, state->addr);
+               state->name, state->name, state->rfc_addr);
     if (state->rcpt_count == 1 && state->recipient) {
        rec_fprintf(state->cleanup, REC_TYPE_NORM,
                    "\tby %s (%s) with %s id %s",
index f968eb72b23df6622ff1fc1dc3b2fb49b133f4d7..c782359b295d9f3604054b5d6b39ba0a9273a2b5 100644 (file)
@@ -36,6 +36,7 @@ typedef struct {
     char   *name;                      /* client name */
     char   *addr;                      /* client IP address */
     char   *namaddr;                   /* name[addr] */
+    char   *rfc_addr;                  /* RFC 2821 client IP address */
     char   *queue_id;                  /* queue file ID */
     VSTREAM *cleanup;                  /* cleanup server */
     MAIL_STREAM *dest;                 /* cleanup server */
index 84c878dcb0eae5eafa56368cd45156fdf2e9726f..d785d97ed4a1d99418289c7df73a05373819027b 100644 (file)
@@ -26,7 +26,7 @@
 /* .IP namaddr
 /*     String of the form: "name[addr]".
 /* .PP
-/*     qmqpd_peer_reset() releases memory allocate by qmqpd_peer_init().
+/*     qmqpd_peer_reset() releases memory allocated by qmqpd_peer_init().
 /* LICENSE
 /* .ad
 /* .fi
 #include <netdb.h>
 #include <string.h>
 
- /*
-  * Older systems don't have h_errno. Even modern systems don't have
-  * hstrerror().
-  */
-#ifdef NO_HERRNO
-
-static int h_errno = TRY_AGAIN;
-
-#define  HSTRERROR(err) "Host not found"
-
-#else
-
-#define  HSTRERROR(err) (\
-       err == TRY_AGAIN ? "Host not found, try again" : \
-       err == HOST_NOT_FOUND ? "Host not found" : \
-       err == NO_DATA ? "Host name has no address" : \
-       err == NO_RECOVERY ? "Name server failure" : \
-       strerror(errno) \
-    )
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
 #include <mymalloc.h>
-#include <valid_hostname.h>
 #include <stringops.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
+#include <mail_proto.h>
+#include <valid_mailhost_addr.h>
 
 /* Application-specific. */
 
@@ -88,16 +71,19 @@ static int h_errno = TRY_AGAIN;
 
 void    qmqpd_peer_init(QMQPD_STATE *state)
 {
-    struct sockaddr_in sin;
-    SOCKADDR_SIZE len = sizeof(sin);
-    struct hostent *hp;
-    int     i;
+    char   *myname = "qmqpd_peer_init";
+    struct sockaddr_storage ss;
+    struct sockaddr *sa;
+    SOCKADDR_SIZE sa_len;
+    INET_PROTO_INFO *proto_info = inet_proto_info();
+
+    sa = (struct sockaddr *) & ss;
+    sa_len = sizeof(ss);
 
     /*
      * Look up the peer address information.
      */
-    if (getpeername(vstream_fileno(state->client),
-                   (struct sockaddr *) & sin, &len) >= 0) {
+    if (getpeername(vstream_fileno(state->client), sa, &sa_len) >= 0) {
        errno = 0;
     }
 
@@ -105,54 +91,130 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
      * If peer went away, give up.
      */
     if (errno == ECONNRESET || errno == ECONNABORTED) {
-       state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
-       state->addr = mystrdup(CLIENT_ATTR_UNKNOWN);
+       state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+       state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+       state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
     }
 
     /*
-     * Look up and "verify" the client hostname.
+     * Convert the client address to printable address and hostname.
      */
-    else if (errno == 0 && sin.sin_family == AF_INET) {
-       state->addr = mystrdup(inet_ntoa(sin.sin_addr));
-       hp = gethostbyaddr((char *) &(sin.sin_addr),
-                          sizeof(sin.sin_addr), AF_INET);
-       if (hp == 0) {
-           state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
-       } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
-           state->name = mystrdup(CLIENT_ATTR_UNKNOWN);
-       } else {
-           state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
+    else if (errno == 0
+            && strchr((char *) proto_info->sa_family_list, sa->sa_family)) {
+       MAI_HOSTNAME_STR client_name;
+       MAI_HOSTADDR_STR client_addr;
+       int     aierr;
+       char   *colonp;
+
+       /*
+        * Convert the client address to printable form.
+        */
+       if ((aierr = sockaddr_to_hostaddr(sa, sa_len, &client_addr,
+                                         (MAI_SERVPORT_STR *) 0, 0)) != 0)
+           msg_fatal("%s: cannot convert client address to string: %s",
+                     myname, MAI_STRERROR(aierr));
+
+       /*
+        * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
+        * but only if IPv4 support is enabled (why would anyone want to turn
+        * it off)? With IPv4 support enabled we have no need for the IPv6
+        * form in logging, hostname verification and access checks.
+        */
+#ifdef HAS_IPV6
+       if (sa->sa_family == AF_INET6) {
+           if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
+               && IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
+               && (colonp = strrchr(client_addr.buf, ':')) != 0) {
+               struct addrinfo *res0;
+
+               if (msg_verbose > 1)
+                   msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
+                            myname, client_addr.buf, colonp + 1);
+
+               state->addr = mystrdup(colonp + 1);
+               state->rfc_addr = mystrdup(colonp + 1);
+               aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
+               if (aierr)
+                   msg_fatal("%s: cannot convert %s from string to binary: %s",
+                             myname, state->addr, MAI_STRERROR(aierr));
+               sa_len = res0->ai_addrlen;
+               memcpy((char *) sa, res0->ai_addr, sa_len);
+               freeaddrinfo(res0);
+           }
 
            /*
-            * Reject the hostname if it does not list the peer address.
+            * Following RFC 2821 section 4.1.3, an IPv6 address literal gets
+            * a prefix of 'IPv6:'. We do this consistently for all IPv6
+            * addresses that that appear in headers or envelopes. The fact
+            * that valid_mailhost_addr() enforces the form helps of course.
+            * We use the form without IPV6: prefix when doing access
+            * control, or when accessing the connection cache.
             */
+           else {
+               state->addr = mystrdup(client_addr.buf);
+               state->rfc_addr =
+                   concatenate(IPV6_COL, client_addr.buf, (char *) 0);
+           }
+       }
+
+       /*
+        * An IPv4 address is in dotted quad decimal form.
+        */
+       else
+#endif
+       {
+           state->addr = mystrdup(client_addr.buf);
+           state->rfc_addr = mystrdup(client_addr.buf);
+       }
+
+       /*
+        * Look up and sanity check the client hostname.
+        * 
+        * It is unsafe to allow numeric hostnames, especially because there
+        * exists pressure to turn off the name->addr double check. In that
+        * case an attacker could trivally bypass access restrictions.
+        * 
+        * sockaddr_to_hostname() already rejects malformed or numeric names.
+        */
 #define REJECT_PEER_NAME(state) { \
        myfree(state->name); \
-       state->name = mystrdup(CLIENT_ATTR_UNKNOWN); \
+       state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
     }
 
-           hp = gethostbyname(state->name);    /* clobbers hp->name!! */
-           if (hp == 0) {
+       if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
+                                         (MAI_SERVNAME_STR *) 0, 0)) != 0) {
+           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+       } else {
+           struct addrinfo *res0;
+           struct addrinfo *res;
+
+           state->name = mystrdup(client_name.buf);
+
+           /*
+            * Reject the hostname if it does not list the peer address.
+            */
+           aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0);
+           if (aierr) {
                msg_warn("%s: hostname %s verification failed: %s",
-                        state->addr, state->name, HSTRERROR(h_errno));
-               REJECT_PEER_NAME(state);
-           } else if (hp->h_length != sizeof(sin.sin_addr)) {
-               msg_warn("%s: hostname %s verification failed: bad address size %d",
-                        state->addr, state->name, hp->h_length);
+                        state->addr, state->name, MAI_STRERROR(aierr));
                REJECT_PEER_NAME(state);
            } else {
-               for (i = 0; /* void */ ; i++) {
-                   if (hp->h_addr_list[i] == 0) {
+               for (res = res0; /* void */ ; res = res->ai_next) {
+                   if (res == 0) {
                        msg_warn("%s: address not listed for hostname %s",
                                 state->addr, state->name);
                        REJECT_PEER_NAME(state);
                        break;
                    }
-                   if (memcmp(hp->h_addr_list[i],
-                              (char *) &sin.sin_addr,
-                              sizeof(sin.sin_addr)) == 0)
+                   if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+                       msg_info("skipping address family %d for host %s",
+                                res->ai_family, state->name);
+                       continue;
+                   }
+                   if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
                        break;                  /* keep peer name */
                }
+               freeaddrinfo(res0);
            }
        }
     }
@@ -164,6 +226,7 @@ void    qmqpd_peer_init(QMQPD_STATE *state)
     else {
        state->name = mystrdup("localhost");
        state->addr = mystrdup("127.0.0.1");    /* XXX bogus. */
+       state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
     }
 
     /*
@@ -180,4 +243,5 @@ void    qmqpd_peer_reset(QMQPD_STATE *state)
     myfree(state->name);
     myfree(state->addr);
     myfree(state->namaddr);
+    myfree(state->rfc_addr);
 }
index 1fc319818f7e5dca89c4d6b1474ac07343a42d80..4d54015b43f0b690a834cbd9d1d3d8403f409d41 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index c3ae7d2c38d1d4f6c1ee4a2bfa1baf55f3d94387..751db318a679d9d42ae961edeb74bc7716b5233d 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index c1aa4aed3d1e55e62d1ef0ba20c680445ae78403..8c47a6e59f193db633f4ce6921b0bb4c6938947f 100644 (file)
 /*     Non-default alias database. Specify \fIpathname\fR or
 /*     \fItype\fR:\fIpathname\fR. See \fBpostalias\fR(1) for
 /*     details.
+/* .IP "\fB-O \fIoption=value\fR (ignored)"
+/*     Backwards compatibility.
 /* .IP "\fB-o7\fR (ignored)"
 /* .IP "\fB-o8\fR (ignored)"
 /*     To send 8-bit or binary content, use an appropriate MIME encapsulation
@@ -941,7 +943,7 @@ int     main(int argc, char **argv)
            optind++;
            continue;
        }
-       if ((c = GETOPT(argc, argv, "A:B:C:F:GIL:N:R:UV:X:b:ce:f:h:imno:p:r:q:tvx")) <= 0)
+       if ((c = GETOPT(argc, argv, "A:B:C:F:GIL:N:O:R:UV:X:b:ce:f:h:imno:p:r:q:tvx")) <= 0)
            break;
        switch (c) {
        default:
index ae0e476cf936e620a2327166e0aea3307262bfed..66ed58fdc9fb762d418816b5c12d146e50946789 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index ad979599451ae2e88ffa2a53f83b23b5f66c3f1f..ffbc92ed3e023cf2997d99b0bf1f2bf59681bc69 100644 (file)
@@ -20,7 +20,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -92,11 +92,13 @@ smtp_addr.o: ../../include/vstring.h
 smtp_addr.o: ../../include/vbuf.h
 smtp_addr.o: ../../include/mymalloc.h
 smtp_addr.o: ../../include/inet_addr_list.h
+smtp_addr.o: ../../include/myaddrinfo.h
 smtp_addr.o: ../../include/stringops.h
-smtp_addr.o: ../../include/myrand.h
+smtp_addr.o: ../../include/inet_proto.h
 smtp_addr.o: ../../include/mail_params.h
 smtp_addr.o: ../../include/own_inet_addr.h
 smtp_addr.o: ../../include/dns.h
+smtp_addr.o: ../../include/sock_addr.h
 smtp_addr.o: smtp.h
 smtp_addr.o: ../../include/vstream.h
 smtp_addr.o: ../../include/argv.h
@@ -146,11 +148,13 @@ smtp_connect.o: ../../include/vstring.h
 smtp_connect.o: ../../include/split_at.h
 smtp_connect.o: ../../include/mymalloc.h
 smtp_connect.o: ../../include/inet_addr_list.h
+smtp_connect.o: ../../include/myaddrinfo.h
 smtp_connect.o: ../../include/iostuff.h
 smtp_connect.o: ../../include/timed_connect.h
 smtp_connect.o: ../../include/stringops.h
 smtp_connect.o: ../../include/host_port.h
 smtp_connect.o: ../../include/sane_connect.h
+smtp_connect.o: ../../include/sock_addr.h
 smtp_connect.o: ../../include/mail_params.h
 smtp_connect.o: ../../include/own_inet_addr.h
 smtp_connect.o: ../../include/deliver_pass.h
@@ -253,6 +257,8 @@ smtp_reuse.o: ../../include/maps.h
 smtp_reuse.o: ../../include/dict.h
 smtp_reuse.o: smtp_reuse.h
 smtp_reuse.o: ../../include/dns.h
+smtp_reuse.o: ../../include/sock_addr.h
+smtp_reuse.o: ../../include/myaddrinfo.h
 smtp_sasl_glue.o: smtp_sasl_glue.c
 smtp_sasl_glue.o: ../../include/sys_defs.h
 smtp_sasl_glue.o: ../../include/msg.h
@@ -371,6 +377,8 @@ smtp_unalias.o: ../../include/vstring.h
 smtp_unalias.o: ../../include/vbuf.h
 smtp_unalias.o: ../../include/msg.h
 smtp_unalias.o: ../../include/dns.h
+smtp_unalias.o: ../../include/sock_addr.h
+smtp_unalias.o: ../../include/myaddrinfo.h
 smtp_unalias.o: smtp.h
 smtp_unalias.o: ../../include/vstream.h
 smtp_unalias.o: ../../include/argv.h
index 997f80f32e37fb976ad53f9c80f80e49af42bbff..9a09fcfd4133e3ffa1cd6925a4ef6d3910499ea8 100644 (file)
 /*     Optional list of relay hosts for SMTP destinations that can't be
 /*     found or that are unreachable.
 /* .IP "\fBinet_interfaces (all)\fR"
-/*     The network interface addresses that this mail system receives mail
-/*     on.
+/*     The network interface addresses that this mail system receives
+/*     mail on.
+/* .IP "\fBinet_protocols (ipv4)\fR"
+/*     The Internet protocols Postfix will attempt to use when making
+/*     or accepting connections.
 /* .IP "\fBipc_timeout (3600s)\fR"
 /*     The time limit for sending or receiving information over an internal
 /*     communication channel.
 /*     on by way of a proxy or network address translation unit.
 /* .IP "\fBsmtp_bind_address (empty)\fR"
 /*     An optional numerical network address that the SMTP client should
-/*     bind to when making a connection.
+/*     bind to when making an IPv4 connection.
+/* .IP "\fBsmtp_bind_address6 (empty)\fR"
+/*     An optional numerical network address that the SMTP client should
+/*     bind to when making an IPv6 connection.
 /* .IP "\fBsmtp_helo_name ($myhostname)\fR"
 /*     The hostname to send in the SMTP EHLO or HELO command.
 /* .IP "\fBsmtp_host_lookup (dns)\fR"
@@ -385,6 +391,7 @@ char   *var_smtp_sasl_passwd;
 bool    var_smtp_sasl_enable;
 char   *var_smtp_sasl_mechs;
 char   *var_smtp_bind_addr;
+char   *var_smtp_bind_addr6;
 bool    var_smtp_rand_addr;
 int     var_smtp_pix_thresh;
 int     var_smtp_pix_delay;
@@ -498,11 +505,6 @@ static void post_init(char *unused_name, char **unused_argv)
        0,
     };
 
-    /*
-     * Turn on per-peer debugging.
-     */
-    debug_peer_init();
-
     /*
      * Select hostname lookup mechanisms.
      */
@@ -534,6 +536,11 @@ static void post_init(char *unused_name, char **unused_argv)
 static void pre_init(char *unused_name, char **unused_argv)
 {
 
+    /*
+     * Turn on per-peer debugging.
+     */
+    debug_peer_init();
+
     /*
      * SASL initialization.
      */
@@ -600,6 +607,7 @@ int     main(int argc, char **argv)
        VAR_SMTP_SASL_OPTS, DEF_SMTP_SASL_OPTS, &var_smtp_sasl_opts, 0, 0,
        VAR_SMTP_SASL_MECHS, DEF_SMTP_SASL_MECHS, &var_smtp_sasl_mechs, 0, 0,
        VAR_SMTP_BIND_ADDR, DEF_SMTP_BIND_ADDR, &var_smtp_bind_addr, 0, 0,
+       VAR_SMTP_BIND_ADDR6, DEF_SMTP_BIND_ADDR6, &var_smtp_bind_addr6, 0, 0,
        VAR_SMTP_HELO_NAME, DEF_SMTP_HELO_NAME, &var_smtp_helo_name, 1, 0,
        VAR_SMTP_HOST_LOOKUP, DEF_SMTP_HOST_LOOKUP, &var_smtp_host_lookup, 1, 0,
        VAR_SMTP_CACHE_DEST, DEF_SMTP_CACHE_DEST, &var_smtp_cache_dest, 0, 0,
index b7cf54ecf004ff9d031ae9485da225fc5c51febc..477fe710ecbf2e9516ed88c860e21c1b41b357cd 100644 (file)
 /*
 /*     All routines either return a DNS_RR pointer, or return a null
 /*     pointer and set the \fIsmtp_errno\fR global variable accordingly:
-/* .IP SMTP_RETRY
+/* .IP SMTP_ERR_RETRY
 /*     The request failed due to a soft error, and should be retried later.
-/* .IP SMTP_FAIL
+/* .IP SMTP_ERR_FAIL
 /*     The request attempt failed due to a hard error.
-/* .IP SMTP_LOOP
+/* .IP SMTP_ERR_LOOP
 /*     The local machine is the best mail exchanger.
 /* .PP
 /*     In addition, a textual description of the problem is made available
 #include <unistd.h>
 #include <errno.h>
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
- /*
-  * Older systems don't have h_errno. Even modern systems don't have
-  * hstrerror().
-  */
-#ifdef NO_HERRNO
-
-static int h_errno = TRY_AGAIN;
-
-#define  HSTRERROR(err) "Host not found"
-
-#else
-
-#define  HSTRERROR(err) (\
-        err == TRY_AGAIN ? "Host not found, try again" : \
-        err == HOST_NOT_FOUND ? "Host not found" : \
-        err == NO_DATA ? "Host name has no address" : \
-        err == NO_RECOVERY ? "Name server failure" : \
-        strerror(errno) \
-    )
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
@@ -111,7 +86,8 @@ static int h_errno = TRY_AGAIN;
 #include <mymalloc.h>
 #include <inet_addr_list.h>
 #include <stringops.h>
-#include <myrand.h>
+#include <myaddrinfo.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -132,17 +108,16 @@ static int h_errno = TRY_AGAIN;
 static void smtp_print_addr(char *what, DNS_RR *addr_list)
 {
     DNS_RR *addr;
-    struct in_addr in_addr;
+    MAI_HOSTADDR_STR hostaddr;
 
     msg_info("begin %s address list", what);
     for (addr = addr_list; addr; addr = addr->next) {
-       if (addr->data_len > sizeof(addr)) {
-           msg_warn("skipping address length %d", addr->data_len);
+       if (dns_rr_to_pa(addr, &hostaddr) == 0) {
+           msg_warn("skipping record type %s: %m", dns_strtype(addr->type));
        } else {
-           memcpy((char *) &in_addr, addr->data, sizeof(in_addr));
            msg_info("pref %4d host %s/%s",
                     addr->pref, addr->name,
-                    inet_ntoa(in_addr));
+                    hostaddr.buf);
        }
     }
     msg_info("end %s address list", what);
@@ -153,11 +128,13 @@ static void smtp_print_addr(char *what, DNS_RR *addr_list)
 static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRING *why)
 {
     char   *myname = "smtp_addr_one";
-    struct in_addr inaddr;
-    DNS_FIXED fixed;
     DNS_RR *addr = 0;
     DNS_RR *rr;
-    struct hostent *hp;
+    int     aierr;
+    struct addrinfo *res0;
+    struct addrinfo *res;
+    INET_PROTO_INFO *proto_info = inet_proto_info();
+    int     found;
 
     if (msg_verbose)
        msg_info("%s: host %s", myname, host);
@@ -165,18 +142,22 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
     /*
      * Interpret a numerical name as an address.
      */
-    if (ISDIGIT(host[0]) && (inaddr.s_addr = inet_addr(host)) != INADDR_NONE) {
-       memset((char *) &fixed, 0, sizeof(fixed));
-       return (dns_rr_append(addr_list,
-                             dns_rr_create(host, &fixed, pref,
-                                       (char *) &inaddr, sizeof(inaddr))));
+    if (hostaddr_to_sockaddr(host, (char *) 0, 0, &res0) == 0
+       && strchr((char *) proto_info->sa_family_list, res0->ai_family) != 0) {
+       if ((addr = dns_sa_to_rr(host, pref, res0->ai_addr)) == 0)
+           msg_fatal("host %s: conversion error for address family %d: %m",
+                   host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
+       addr_list = dns_rr_append(addr_list, addr);
+       freeaddrinfo(res0);
+       return (addr_list);
     }
 
     /*
      * Use DNS lookup, but keep the option open to use native name service.
      */
     if (smtp_host_lookup_mask & SMTP_HOST_FLAG_DNS) {
-       switch (dns_lookup(host, T_A, RES_DEFNAMES, &addr, (VSTRING *) 0, why)) {
+       switch (dns_lookup_v(host, RES_DEFNAMES, &addr, (VSTRING *) 0, why,
+                            DNS_REQ_FLAG_ALL, proto_info->dns_atype_list)) {
        case DNS_OK:
            for (rr = addr; rr; rr = rr->next)
                rr->pref = pref;
@@ -192,7 +173,7 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
        case DNS_NOTFOUND:
            if (smtp_errno != SMTP_ERR_RETRY)
                smtp_errno = SMTP_ERR_FAIL;
-           /* maybe gethostbyname() will succeed */
+           /* maybe native naming service will succeed */
            break;
        }
     }
@@ -200,29 +181,35 @@ static DNS_RR *smtp_addr_one(DNS_RR *addr_list, char *host, unsigned pref, VSTRI
     /*
      * Use the native name service which also looks in /etc/hosts.
      */
+#define RETRY_AI_ERROR(e) \
+        ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
+
     if (smtp_host_lookup_mask & SMTP_HOST_FLAG_NATIVE) {
-       memset((char *) &fixed, 0, sizeof(fixed));
-       if ((hp = gethostbyname(host)) == 0) {
-           vstring_sprintf(why, "%s: %s", host, HSTRERROR(h_errno));
+       if ((aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0)) != 0) {
+           vstring_sprintf(why, "%s: %s", host, MAI_STRERROR(aierr));
            if (smtp_errno != SMTP_ERR_RETRY)
                smtp_errno =
-                   (h_errno == TRY_AGAIN ? SMTP_ERR_RETRY : SMTP_ERR_FAIL);
-       } else if (hp->h_addrtype != AF_INET) {
-           vstring_sprintf(why, "%s: host not found", host);
-           msg_warn("%s: unknown address family %d for %s",
-                    myname, hp->h_addrtype, host);
-           if (smtp_errno != SMTP_ERR_RETRY)
-               smtp_errno = SMTP_ERR_FAIL;
+                   (RETRY_AI_ERROR(aierr) ? SMTP_ERR_RETRY : SMTP_ERR_FAIL);
        } else {
-           while (hp->h_addr_list[0]) {
-               addr_list = dns_rr_append(addr_list,
-                                         dns_rr_create(host, &fixed, pref,
-                                                       hp->h_addr_list[0],
-                                                       sizeof(inaddr)));
-               hp->h_addr_list++;
+           for (found = 0, res = res0; res != 0; res = res->ai_next) {
+               if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+                   msg_info("skipping address family %d for host %s",
+                            res->ai_family, host);
+                   continue;
+               }
+               found++;
+               if ((addr = dns_sa_to_rr(host, pref, res->ai_addr)) == 0)
+                   msg_fatal("host %s: conversion error for address family %d: %m",
+                   host, ((struct sockaddr *) (res0->ai_addr))->sa_family);
+               addr_list = dns_rr_append(addr_list, addr);
+           }
+           freeaddrinfo(res0);
+           if (found == 0) {
+               vstring_sprintf(why, "%s: host not found", host);
+               smtp_errno = SMTP_ERR_FAIL;
            }
+           return (addr_list);
        }
-       return (addr_list);
     }
 
     /*
@@ -266,8 +253,6 @@ static DNS_RR *smtp_find_self(DNS_RR *addr_list)
     DNS_RR *addr;
     int     i;
 
-#define INADDRP(x) ((struct in_addr *) (x))
-
     self = own_inet_addr_list();
     proxy = proxy_inet_addr_list();
 
@@ -277,7 +262,7 @@ static DNS_RR *smtp_find_self(DNS_RR *addr_list)
         * Find out if this mail system is listening on this address.
         */
        for (i = 0; i < self->used; i++)
-           if (INADDRP(addr->data)->s_addr == self->addrs[i].s_addr) {
+           if (DNS_RR_EQ_SA(addr, (struct sockaddr *) (self->addrs + i))) {
                if (msg_verbose)
                    msg_info("%s: found self at pref %d", myname, addr->pref);
                return (addr);
@@ -288,7 +273,7 @@ static DNS_RR *smtp_find_self(DNS_RR *addr_list)
         * address.
         */
        for (i = 0; i < proxy->used; i++)
-           if (INADDRP(addr->data)->s_addr == proxy->addrs[i].s_addr) {
+           if (DNS_RR_EQ_SA(addr, (struct sockaddr *) (proxy->addrs + i))) {
                if (msg_verbose)
                    msg_info("%s: found proxy at pref %d", myname, addr->pref);
                return (addr);
@@ -330,7 +315,17 @@ static DNS_RR *smtp_truncate_self(DNS_RR *addr_list, unsigned pref)
 
 static int smtp_compare_pref(DNS_RR *a, DNS_RR *b)
 {
-    return (a->pref - b->pref);
+    if (a->pref != b->pref)
+       return (a->pref - b->pref);
+#ifdef HAS_IPV6
+    if (a->type == b->type)                    /* 200412 */
+       return 0;
+    if (a->type == T_AAAA)
+       return (-1);
+    if (b->type == T_AAAA)
+       return (+1);
+#endif
+    return 0;
 }
 
 /* smtp_domain_addr - mail exchanger address lookup */
@@ -476,8 +471,13 @@ DNS_RR *smtp_host_addr(char *host, int misc_flags, VSTRING *why)
        smtp_errno = SMTP_ERR_LOOP;
        return (0);
     }
-    if (addr_list && addr_list->next && var_smtp_rand_addr)
-       addr_list = dns_rr_shuffle(addr_list);
+    if (addr_list && addr_list->next) {
+       if (var_smtp_rand_addr)
+           addr_list = dns_rr_shuffle(addr_list);
+       /* The following changes the order of equal-preference hosts. */
+       if (inet_proto_info()->ai_family_list[1] != 0)
+           addr_list = dns_rr_sort(addr_list, smtp_compare_pref);
+    }
     if (msg_verbose)
        smtp_print_addr(host, addr_list);
     return (addr_list);
index 564b8d42d81e338e5fd73031fb2880dad27c460f..e2661e487e4d851934190fbe22f64369580d2546 100644 (file)
@@ -53,6 +53,7 @@
 /* System library. */
 
 #include <sys_defs.h>
+#include <stdlib.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <fcntl.h>
 #include <ctype.h>
 
-#ifdef STRCASECMP_IN_STRINGS_H
-#include <strings.h>
-#endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
 #ifndef IPPORT_SMTP
 #define IPPORT_SMTP 25
 #endif
@@ -89,6 +82,8 @@
 #include <stringops.h>
 #include <host_port.h>
 #include <sane_connect.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
 
 /* Global library. */
 
@@ -116,22 +111,26 @@ static SMTP_SESSION *smtp_connect_addr(const char *dest, DNS_RR *addr,
                                               int sess_flags)
 {
     char   *myname = "smtp_connect_addr";
-    struct sockaddr_in sin;
+    struct sockaddr_storage ss;                /* remote */
+    struct sockaddr *sa = (struct sockaddr *) & ss;
+    SOCKADDR_SIZE salen = sizeof(ss);
+    MAI_HOSTADDR_STR hostaddr;
     int     sock;
-    INET_ADDR_LIST *addr_list;
     int     conn_stat;
     int     saved_errno;
     VSTREAM *stream;
     int     ch;
-    unsigned long inaddr;
+    char   *bind_addr;
+    char   *bind_var;
 
     smtp_errno = SMTP_ERR_NONE;                        /* Paranoia */
 
     /*
      * Sanity checks.
      */
-    if (addr->data_len > sizeof(sin.sin_addr)) {
-       msg_warn("%s: skip address with length %d", myname, addr->data_len);
+    if (dns_rr_to_sa(addr, port, sa, &salen) != 0) {
+       msg_warn("%s: skip address type %s: %m",
+                myname, dns_strtype(addr->type));
        smtp_errno = SMTP_ERR_RETRY;
        return (0);
     }
@@ -139,65 +138,90 @@ static SMTP_SESSION *smtp_connect_addr(const char *dest, DNS_RR *addr,
     /*
      * Initialize.
      */
-    memset((char *) &sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-
-    if ((sock = socket(sin.sin_family, SOCK_STREAM, 0)) < 0)
+    if ((sock = socket(sa->sa_family, SOCK_STREAM, 0)) < 0)
        msg_fatal("%s: socket: %m", myname);
 
     /*
      * Allow the sysadmin to specify the source address, for example, as "-o
      * smtp_bind_address=x.x.x.x" in the master.cf file.
      */
-    if (*var_smtp_bind_addr) {
-       sin.sin_addr.s_addr = inet_addr(var_smtp_bind_addr);
-       if (sin.sin_addr.s_addr == INADDR_NONE)
-           msg_fatal("%s: bad %s parameter: %s",
-                     myname, VAR_SMTP_BIND_ADDR, var_smtp_bind_addr);
-       if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
-           msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
-       if (msg_verbose)
-           msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
+#ifdef HAS_IPV6
+    if (sa->sa_family == AF_INET6) {
+       bind_addr = var_smtp_bind_addr6;
+       bind_var = VAR_SMTP_BIND_ADDR6;
+    } else
+#endif
+    if (sa->sa_family == AF_INET) {
+       bind_addr = var_smtp_bind_addr;
+       bind_var = VAR_SMTP_BIND_ADDR;
+    } else
+       bind_var = bind_addr = "";
+    if (*bind_addr) {
+       int     aierr;
+       struct addrinfo *res0;
+
+       if ((aierr = hostaddr_to_sockaddr(bind_addr, (char *) 0, 0, &res0)) != 0)
+           msg_fatal("%s: bad %s parameter: %s: %s",
+                     myname, bind_var, bind_addr, MAI_STRERROR(aierr));
+       if (bind(sock, res0->ai_addr, res0->ai_addrlen) < 0)
+           msg_warn("%s: bind %s: %m", myname, bind_addr);
+       else if (msg_verbose)
+           msg_info("%s: bind %s", myname, bind_addr);
+       freeaddrinfo(res0);
     }
 
     /*
      * When running as a virtual host, bind to the virtual interface so that
      * the mail appears to come from the "right" machine address.
+     * 
+     * XXX The IPv6 patch expands the null host (as client endpoint) and uses
+     * the result as the loopback address list.
      */
-    else if ((addr_list = own_inet_addr_list())->used == 1) {
-       memcpy((char *) &sin.sin_addr, addr_list->addrs, sizeof(sin.sin_addr));
-       inaddr = ntohl(sin.sin_addr.s_addr);
-       if (!IN_CLASSA(inaddr)
-           || !(((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)) {
-           if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
-               msg_warn("%s: bind %s: %m", myname, inet_ntoa(sin.sin_addr));
-           if (msg_verbose)
-               msg_info("%s: bind %s", myname, inet_ntoa(sin.sin_addr));
+    else {
+       int     count = 0;
+       struct sockaddr *own_addr = 0;
+       INET_ADDR_LIST *addr_list = own_inet_addr_list();
+       struct sockaddr_storage *s;
+
+       for (s = addr_list->addrs; s < addr_list->addrs + addr_list->used; s++) {
+           if (SOCK_ADDR_FAMILY(s) == sa->sa_family) {
+               if (count++ > 0)
+                   break;
+               own_addr = SOCK_ADDR_PTR(s);
+           }
+       }
+       if (count == 1 && !sock_addr_in_loopback(own_addr)) {
+           if (bind(sock, own_addr, SOCK_ADDR_LEN(own_addr)) < 0) {
+               SOCKADDR_TO_HOSTADDR(own_addr, SOCK_ADDR_LEN(own_addr),
+                                    &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+               msg_warn("%s: bind %s: %m", myname, hostaddr.buf);
+           } else if (msg_verbose) {
+               SOCKADDR_TO_HOSTADDR(own_addr, SOCK_ADDR_LEN(own_addr),
+                                    &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+               msg_info("%s: bind %s", myname, hostaddr.buf);
+           }
        }
     }
 
     /*
      * Connect to the SMTP server.
      */
-    sin.sin_port = port;
-    memcpy((char *) &sin.sin_addr, addr->data, sizeof(sin.sin_addr));
-
+    SOCKADDR_TO_HOSTADDR(sa, salen, &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
     if (msg_verbose)
        msg_info("%s: trying: %s[%s] port %d...",
-                myname, addr->name, inet_ntoa(sin.sin_addr), ntohs(port));
+                myname, addr->name, hostaddr.buf, ntohs(port));
     if (var_smtp_conn_tmout > 0) {
        non_blocking(sock, NON_BLOCKING);
-       conn_stat = timed_connect(sock, (struct sockaddr *) & sin,
-                                 sizeof(sin), var_smtp_conn_tmout);
+       conn_stat = timed_connect(sock, sa, salen, var_smtp_conn_tmout);
        saved_errno = errno;
        non_blocking(sock, BLOCKING);
        errno = saved_errno;
     } else {
-       conn_stat = sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin));
+       conn_stat = sane_connect(sock, sa, salen);
     }
     if (conn_stat < 0) {
        vstring_sprintf(why, "connect to %s[%s]: %m",
-                       addr->name, inet_ntoa(sin.sin_addr));
+                       addr->name, hostaddr.buf);
        smtp_errno = SMTP_ERR_RETRY;
        close(sock);
        return (0);
@@ -208,7 +232,7 @@ static SMTP_SESSION *smtp_connect_addr(const char *dest, DNS_RR *addr,
      */
     if (read_wait(sock, var_smtp_helo_tmout) < 0) {
        vstring_sprintf(why, "connect to %s[%s]: read timeout",
-                       addr->name, inet_ntoa(sin.sin_addr));
+                       addr->name, hostaddr.buf);
        smtp_errno = SMTP_ERR_RETRY;
        close(sock);
        return (0);
@@ -220,14 +244,14 @@ static SMTP_SESSION *smtp_connect_addr(const char *dest, DNS_RR *addr,
     stream = vstream_fdopen(sock, O_RDWR);
     if ((ch = VSTREAM_GETC(stream)) == VSTREAM_EOF) {
        vstring_sprintf(why, "connect to %s[%s]: server dropped connection without sending the initial SMTP greeting",
-                       addr->name, inet_ntoa(sin.sin_addr));
+                       addr->name, hostaddr.buf);
        smtp_errno = SMTP_ERR_RETRY;
        vstream_fclose(stream);
        return (0);
     }
     vstream_ungetc(stream, ch);
     return (smtp_session_alloc(stream, dest, addr->name,
-                              inet_ntoa(sin.sin_addr), port, sess_flags));
+                              hostaddr.buf, port, sess_flags));
 }
 
 /* smtp_parse_destination - parse destination */
@@ -249,13 +273,15 @@ static char *smtp_parse_destination(char *destination, char *def_service,
      * Parse the host/port information. We're working with a copy of the
      * destination argument so the parsing can be destructive.
      */
-    if ((err = host_port(buf, hostp, &service, def_service)) != 0)
+    if ((err = host_port(buf, hostp, (char *) 0, &service, def_service)) != 0)
        msg_fatal("%s in SMTP server description: %s", err, destination);
 
     /*
      * Convert service to port number, network byte order.
      */
-    if (alldig(service) && (port = atoi(service)) != 0) {
+    if (alldig(service)) {
+       if ((port = atoi(service)) >= 65536)
+           msg_fatal("bad network port in destination: %s", destination);
        *portp = htons(port);
     } else {
        if ((sp = getservbyname(service, protocol)) == 0)
@@ -315,19 +341,24 @@ static void smtp_cleanup_session(SMTP_STATE *state)
 
 static void smtp_scrub_addr_list(HTABLE *cached_addr, DNS_RR **addr_list)
 {
+    MAI_HOSTADDR_STR hostaddr;
     DNS_RR *addr;
     DNS_RR *next;
 
-#define INADDRP(x) ((struct in_addr *) (x))
-
+    /*
+     * XXX Extend the DNS_RR structure with fields for the printable address
+     * and/or binary sockaddr representations, so that we can avoid repeated
+     * binary->string transformations for the same address.
+     */
     for (addr = *addr_list; addr; addr = next) {
        next = addr->next;
-       if (addr->type == T_A) {
-           if (addr->data_len > sizeof(struct in_addr))
-               continue;
-           if (htable_locate(cached_addr, inet_ntoa(*INADDRP(addr->data))))
-               *addr_list = dns_rr_remove(*addr_list, addr);
+       if (dns_rr_to_pa(addr, &hostaddr) == 0) {
+           msg_warn("cannot convert type %s resource record to socket address",
+                    dns_strtype(addr->type));
+           continue;
        }
+       if (htable_locate(cached_addr, hostaddr.buf))
+           *addr_list = dns_rr_remove(*addr_list, addr);
     }
 }
 
@@ -336,9 +367,10 @@ static void smtp_scrub_addr_list(HTABLE *cached_addr, DNS_RR **addr_list)
 static void smtp_update_addr_list(DNS_RR **addr_list, const char *server_addr,
                                          int session_count)
 {
-    struct in_addr server_in_addr;
     DNS_RR *addr;
     DNS_RR *next;
+    int     aierr;
+    struct addrinfo *res0;
 
     if (*addr_list == 0)
        return;
@@ -359,18 +391,23 @@ static void smtp_update_addr_list(DNS_RR **addr_list, const char *server_addr,
      * 
      * XXX smtp_reuse_session() breaks if we remove two or more adjacent list
      * elements but do not truncate the list to zero length.
+     * 
+     * XXX Extend the SMTP_SESSION structure with sockaddr information so that
+     * we can avoid repeated string->binary transformations for the same
+     * address.
      */
-    server_in_addr.s_addr = inet_addr(server_addr);
-    for (addr = *addr_list; addr; addr = next) {
-       next = addr->next;
-       if (addr->type == T_A) {                /* NOT: switch */
-           if (addr->data_len > sizeof(server_in_addr))
-               continue;
-           if (INADDRP(addr->data)->s_addr == server_in_addr.s_addr) {
+    if ((aierr = hostaddr_to_sockaddr(server_addr, (char *) 0, 0, &res0)) != 0) {
+       msg_warn("hostaddr_to_sockaddr %s: %s",
+                server_addr, MAI_STRERROR(aierr));
+    } else {
+       for (addr = *addr_list; addr; addr = next) {
+           next = addr->next;
+           if (DNS_RR_EQ_SA(addr, (struct sockaddr *) res0->ai_addr)) {
                *addr_list = dns_rr_remove(*addr_list, addr);
                break;
            }
        }
+       freeaddrinfo(res0);
     }
 }
 
index f644ded9400b9218dc9fb90749825259e7e08d7e..f9fa6186b313a8cb7ae25e28b7cc823e334525b6 100644 (file)
@@ -225,11 +225,10 @@ SMTP_SESSION *smtp_reuse_domain(SMTP_STATE *state, int lookup_mx,
 
 SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, DNS_RR *addr, unsigned port)
 {
+    MAI_HOSTADDR_STR hostaddr;
     SMTP_SESSION *session;
     int     fd;
 
-#define INADDRP(x) ((struct in_addr *) (x))
-
     /*
      * Look up the session by its IP address. This means that we have no
      * destination-to-address binding properties.
@@ -237,11 +236,10 @@ SMTP_SESSION *smtp_reuse_addr(SMTP_STATE *state, DNS_RR *addr, unsigned port)
      * Note: if the label needs to be made more specific (with e.g., SASL login
      * information), just append the text with vstring_sprintf_append().
      */
-    if (addr->data_len > sizeof(struct in_addr))
+    if (dns_rr_to_pa(addr, &hostaddr) == 0)
        return (0);
     vstring_sprintf(state->endp_label, SMTP_SCACHE_LABEL(NO_MX_LOOKUP),
-                   state->service, inet_ntoa(*INADDRP(addr->data)),
-                   ntohs(port));
+                   state->service, hostaddr.buf, ntohs(port));
     if ((fd = scache_find_endp(smtp_scache, STR(state->endp_label),
                               state->endp_prop)) < 0)
        return (0);
index 9eab20e549c6f8d812e3b88c47b6a06594d713c2..7c391092b5af9d9e98e8b121a705d5ad5becfb3b 100644 (file)
@@ -312,7 +312,7 @@ SMTP_SESSION *smtp_session_activate(int fd, VSTRING *dest_prop,
      * Allright, bundle up what we have sofar.
      */
     session = smtp_session_alloc(vstream_fdopen(fd, O_RDWR),
-                                dest, host, addr, port, SMTP_SESS_FLAG_NONE);
+                              dest, host, addr, port, SMTP_SESS_FLAG_NONE);
     session->features = (features | SMTP_FEATURE_FROM_CACHE);
     session->reuse_count = reuse_count - 1;
     session->sndbufsize = sndbufsize;
index 20abf38801dc9d36556baa65ddfd6cd0a13da662..395fd695f0f88913f73903b0699efb72f32f4544 100644 (file)
@@ -85,8 +85,12 @@ const char *smtp_unalias_name(const char *name)
      */
     if ((result = htable_find(cache, name)) == 0) {
        fqdn = vstring_alloc(10);
-       if (dns_lookup_types(name, smtp_unalias_flags, (DNS_RR **) 0,
-                            fqdn, (VSTRING *) 0, T_MX, T_A, 0) != DNS_OK)
+       if (dns_lookup_l(name, smtp_unalias_flags, (DNS_RR **) 0, fqdn,
+                            (VSTRING *) 0, DNS_REQ_FLAG_ANY, T_MX, T_A,
+#ifdef HAS_IPV6
+                            T_AAAA,
+#endif
+                            0) != DNS_OK)
            vstring_strcpy(fqdn, name);
        htable_enter(cache, name, result = vstring_export(fqdn));
     }
index 4229c19e28fd076b5dd1c803fa6549dfda988995..f847ce1a430a8ae07753b7f5cf796e8f11a39e9b 100644 (file)
@@ -21,7 +21,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -154,6 +154,7 @@ smtpd.o: ../../include/anvil_clnt.h
 smtpd.o: ../../include/attr_clnt.h
 smtpd.o: ../../include/ehlo_mask.h
 smtpd.o: ../../include/maps.h
+smtpd.o: ../../include/valid_mailhost_addr.h
 smtpd.o: ../../include/mail_server.h
 smtpd.o: smtpd_token.h
 smtpd.o: smtpd.h
@@ -206,7 +207,10 @@ smtpd_check.o: ../../include/mac_expand.h
 smtpd_check.o: ../../include/mac_parse.h
 smtpd_check.o: ../../include/attr_clnt.h
 smtpd_check.o: ../../include/attr.h
+smtpd_check.o: ../../include/myaddrinfo.h
+smtpd_check.o: ../../include/inet_proto.h
 smtpd_check.o: ../../include/dns.h
+smtpd_check.o: ../../include/sock_addr.h
 smtpd_check.o: ../../include/string_list.h
 smtpd_check.o: ../../include/match_list.h
 smtpd_check.o: ../../include/match_ops.h
@@ -221,6 +225,7 @@ smtpd_check.o: ../../include/mail_error.h
 smtpd_check.o: ../../include/name_mask.h
 smtpd_check.o: ../../include/resolve_local.h
 smtpd_check.o: ../../include/own_inet_addr.h
+smtpd_check.o: ../../include/inet_addr_list.h
 smtpd_check.o: ../../include/mail_conf.h
 smtpd_check.o: ../../include/maps.h
 smtpd_check.o: ../../include/mail_addr_find.h
@@ -236,6 +241,7 @@ smtpd_check.o: ../../include/deliver_request.h
 smtpd_check.o: ../../include/recipient_list.h
 smtpd_check.o: ../../include/input_transp.h
 smtpd_check.o: ../../include/is_header.h
+smtpd_check.o: ../../include/valid_mailhost_addr.h
 smtpd_check.o: smtpd.h
 smtpd_check.o: ../../include/mail_stream.h
 smtpd_check.o: smtpd_sasl_glue.h
@@ -244,14 +250,18 @@ smtpd_peer.o: smtpd_peer.c
 smtpd_peer.o: ../../include/sys_defs.h
 smtpd_peer.o: ../../include/msg.h
 smtpd_peer.o: ../../include/mymalloc.h
-smtpd_peer.o: ../../include/valid_hostname.h
 smtpd_peer.o: ../../include/stringops.h
 smtpd_peer.o: ../../include/vstring.h
 smtpd_peer.o: ../../include/vbuf.h
+smtpd_peer.o: ../../include/myaddrinfo.h
+smtpd_peer.o: ../../include/sock_addr.h
+smtpd_peer.o: ../../include/inet_proto.h
 smtpd_peer.o: ../../include/mail_proto.h
 smtpd_peer.o: ../../include/vstream.h
 smtpd_peer.o: ../../include/iostuff.h
 smtpd_peer.o: ../../include/attr.h
+smtpd_peer.o: ../../include/valid_mailhost_addr.h
+smtpd_peer.o: ../../include/valid_hostname.h
 smtpd_peer.o: smtpd.h
 smtpd_peer.o: ../../include/argv.h
 smtpd_peer.o: ../../include/mail_stream.h
index 8b94bdc7782ad9e70e63f309aa7133eecc33fdf0..fb8aa610fc7b1bbe5b37ff99146ef94804be7d3f 100644 (file)
 /*     The list of domains that are delivered via the $local_transport
 /*     mail delivery transport.
 /* .IP "\fBinet_interfaces (all)\fR"
-/*     The network interface addresses that this mail system receives mail
-/*     on.
+/*     The network interface addresses that this mail system receives
+/*     mail on.
 /* .IP "\fBproxy_interfaces (empty)\fR"
 /*     The network interface addresses that this mail system receives mail
 /*     on by way of a proxy or network address translation unit.
+/* .IP "\fBinet_protocols (ipv4)\fR"
+/*     The Internet protocols Postfix will attempt to use when making
+/*     or accepting connections.
 /* .IP "\fBlocal_recipient_maps (proxy:unix:passwd.byname $alias_maps)\fR"
 /*     Lookup tables with all names or addresses of local recipients:
 /*     a recipient address is local when its domain matches $mydestination,
 #include <flush_clnt.h>
 #include <ehlo_mask.h>                 /* ehlo filter */
 #include <maps.h>                      /* ehlo filter */
+#include <valid_mailhost_addr.h>
 
 /* Single-threaded server skeleton. */
 
@@ -879,7 +883,7 @@ static void chat_reset(SMTPD_STATE *, int);
  /*
   * This filter is applied after printable().
   */
-#define NEUTER_CHARACTERS " <>()\\\";:@"
+#define NEUTER_CHARACTERS " <>()\\\";@"
 
  /*
   * Reasons for losing the client.
@@ -1806,7 +1810,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv)
        out_fprintf(out_stream, REC_TYPE_NORM,
                    "Received: from %s (%s [%s])",
                    state->helo_name ? state->helo_name : state->name,
-                   state->name, state->addr);
+                   state->name, state->rfc_addr);
        if (state->rcpt_count == 1 && state->recipient) {
            out_fprintf(out_stream, REC_TYPE_NORM,
                        state->cleanup ? "\tby %s (%s) with %s id %s" :
@@ -2119,9 +2123,15 @@ static int etrn_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        smtpd_chat_reply(state, "500 Syntax: ETRN domain");
        return (-1);
     }
-    if (!ISALNUM(argv[1].strval[0]))
-       argv[1].strval++;
-    if (!valid_hostname(argv[1].strval, DONT_GRIPE)) {
+    if (argv[1].strval[0] == '@' || argv[1].strval[0] == '#')
+        argv[1].strval++;
+
+    /*
+     * As an extension to RFC 1985 we also allow an RFC 2821 address literal
+     * enclosed in [].
+     */
+    if (!valid_hostname(argv[1].strval, DONT_GRIPE)
+       && !valid_mailhost_literal(argv[1].strval, DONT_GRIPE)) {
        state->error_mask |= MAIL_ERROR_PROTOCOL;
        smtpd_chat_reply(state, "501 Error: invalid parameter syntax");
        return (-1);
@@ -2188,6 +2198,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
 {
     SMTPD_TOKEN *argp;
     char   *attr_value;
+    const char *bare_value;
     char   *attr_name;
     int     update_namaddr = 0;
     int     peer_code;
@@ -2254,8 +2265,7 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
            if (peer_code != SMTPD_PEER_CODE_OK) {
                attr_value = CLIENT_NAME_UNKNOWN;
            } else {
-               if (!valid_hostname(attr_value, DONT_GRIPE)
-                   || valid_hostaddr(attr_value, DONT_GRIPE)) {
+               if (!valid_hostname(attr_value, DONT_GRIPE)) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
                    smtpd_chat_reply(state, "501 Bad %s syntax: %s",
                                     XCLIENT_NAME, attr_value);
@@ -2273,15 +2283,17 @@ static int xclient_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        else if (STREQ(attr_name, XCLIENT_ADDR)) {
            if (STREQ(attr_value, XCLIENT_UNAVAILABLE)) {
                attr_value = CLIENT_ADDR_UNKNOWN;
+               bare_value = attr_value;
            } else {
-               if (!valid_hostaddr(attr_value, DONT_GRIPE)) {
+               if ((bare_value = valid_mailhost_addr(attr_value, DONT_GRIPE)) == 0) {
                    state->error_mask |= MAIL_ERROR_PROTOCOL;
                    smtpd_chat_reply(state, "501 Bad %s syntax: %s",
                                     XCLIENT_ADDR, attr_value);
                    return (-1);
                }
            }
-           UPDATE_STR(state->addr, attr_value);
+           UPDATE_STR(state->addr, bare_value);
+           UPDATE_STR(state->rfc_addr, attr_value);
            update_namaddr = 1;
        }
 
@@ -2347,6 +2359,7 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
 {
     SMTPD_TOKEN *argp;
     char   *attr_value;
+    const char *bare_value;
     char   *attr_name;
     int     updated = 0;
     static NAME_CODE xforward_flags[] = {
@@ -2429,6 +2442,12 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
                attr_value = CLIENT_NAME_UNKNOWN;
            } else {
                neuter(attr_value, NEUTER_CHARACTERS, '?');
+               if (!valid_hostname(attr_value, DONT_GRIPE)) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                    XFORWARD_NAME, attr_value);
+                   return (-1);
+               }
            }
            UPDATE_STR(state->xforward.name, attr_value);
            break;
@@ -2441,10 +2460,18 @@ static int xforward_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *argv)
        case SMTPD_STATE_XFORWARD_ADDR:
            if (STREQ(attr_value, XFORWARD_UNAVAILABLE)) {
                attr_value = CLIENT_ADDR_UNKNOWN;
+               bare_value = attr_value;
            } else {
                neuter(attr_value, NEUTER_CHARACTERS, '?');
+               if ((bare_value = valid_mailhost_addr(attr_value, DONT_GRIPE)) == 0) {
+                   state->error_mask |= MAIL_ERROR_PROTOCOL;
+                   smtpd_chat_reply(state, "501 Bad %s syntax: %s",
+                                    XFORWARD_ADDR, attr_value);
+                   return (-1);
+               }
            }
-           UPDATE_STR(state->xforward.addr, attr_value);
+           UPDATE_STR(state->xforward.addr, bare_value);
+           UPDATE_STR(state->xforward.rfc_addr, attr_value);
            break;
 
            /*
@@ -2906,7 +2933,7 @@ static void post_jail_init(char *unused_name, char **unused_argv)
      * recipient checks, address mapping, header_body_checks?.
      */
     smtpd_input_transp_mask =
-       input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
+    input_transp_mask(VAR_INPUT_TRANSP, var_input_transp);
 
     /*
      * Sanity checks. The queue_minfree value should be at least as large as
index 442bbc1c77cebc976f1d5db75f803ed333555520..45b9c9c6fcbcca2233c164cbbef2b7c5b775c23c 100644 (file)
@@ -50,6 +50,7 @@ typedef struct {
     char   *name;                      /* name for access control */
     char   *addr;                      /* address for access control */
     char   *namaddr;                   /* name[address] */
+    char   *rfc_addr;                  /* address for RFC 2821 */
     char   *protocol;                  /* email protocol */
     char   *helo_name;                 /* helo/ehlo parameter */
     char   *ident;                     /* message identifier */
@@ -65,6 +66,7 @@ typedef struct SMTPD_STATE {
     char   *name;                      /* client hostname */
     char   *addr;                      /* client host address string */
     char   *namaddr;                   /* combined name and address */
+    char   *rfc_addr;                  /* address for RFC 2821 */
     int     peer_code;                 /* 2=ok, 4=soft, 5=hard */
     int     error_count;               /* reset after DOT */
     int     error_mask;                        /* client errors */
@@ -234,7 +236,7 @@ extern void smtpd_peer_reset(SMTPD_STATE *state);
        (((s)->xforward.flags & SMTPD_STATE_XFORWARD_CLIENT_MASK) ? \
            (s)->xforward.a : (s)->a)
 
-#define FORWARD_ADDR(s)                FORWARD_CLIENT_ATTR((s), addr)
+#define FORWARD_ADDR(s)                FORWARD_CLIENT_ATTR((s), rfc_addr)
 #define FORWARD_NAME(s)                FORWARD_CLIENT_ATTR((s), name)
 #define FORWARD_NAMADDR(s)     FORWARD_CLIENT_ATTR((s), namaddr)
 #define FORWARD_PROTO(s)       FORWARD_CLIENT_ATTR((s), protocol)
diff --git a/postfix/src/smtpd/smtpd_backup.in b/postfix/src/smtpd/smtpd_backup.in
new file mode 100644 (file)
index 0000000..84ba6ad
--- /dev/null
@@ -0,0 +1,20 @@
+#
+# Initialize.
+#
+#! ../bin/postmap smtpd_check_access
+#msg_verbose 1
+smtpd_delay_reject 0
+mynetworks 127.0.0.0/8,168.100.189.0/28
+#
+# MX backup
+#
+mydestination wzv.porcupine.org,localhost.porcupine.org
+inet_interfaces 168.100.189.7,127.0.0.1
+recipient_restrictions permit_mx_backup,reject
+rcpt wietse@wzv.porcupine.org
+rcpt wietse@fist.porcupine.org
+rcpt wietse@porcupine.org
+permit_mx_backup_networks 168.100.189.5
+rcpt wietse@fist.porcupine.org
+permit_mx_backup_networks 168.100.189.4
+rcpt wietse@fist.porcupine.org
diff --git a/postfix/src/smtpd/smtpd_backup.ref b/postfix/src/smtpd/smtpd_backup.ref
new file mode 100644 (file)
index 0000000..e783ac2
--- /dev/null
@@ -0,0 +1,34 @@
+>>> #
+>>> # Initialize.
+>>> #
+>>> #! ../bin/postmap smtpd_check_access
+>>> #msg_verbose 1
+>>> smtpd_delay_reject 0
+OK
+>>> mynetworks 127.0.0.0/8,168.100.189.0/28
+OK
+>>> #
+>>> # MX backup
+>>> #
+>>> mydestination wzv.porcupine.org,localhost.porcupine.org
+OK
+>>> inet_interfaces 168.100.189.7,127.0.0.1
+OK
+>>> recipient_restrictions permit_mx_backup,reject
+OK
+>>> rcpt wietse@wzv.porcupine.org
+OK
+>>> rcpt wietse@fist.porcupine.org
+OK
+>>> rcpt wietse@porcupine.org
+./smtpd_check: <queue id>: reject: RCPT from localhost[127.0.0.1]: 554 <wietse@porcupine.org>: Recipient address rejected: Access denied; to=<wietse@porcupine.org> proto=SMTP
+554 <wietse@porcupine.org>: Recipient address rejected: Access denied
+>>> permit_mx_backup_networks 168.100.189.5
+OK
+>>> rcpt wietse@fist.porcupine.org
+./smtpd_check: <queue id>: reject: RCPT from localhost[127.0.0.1]: 554 <wietse@fist.porcupine.org>: Recipient address rejected: Access denied; to=<wietse@fist.porcupine.org> proto=SMTP
+554 <wietse@fist.porcupine.org>: Recipient address rejected: Access denied
+>>> permit_mx_backup_networks 168.100.189.4
+OK
+>>> rcpt wietse@fist.porcupine.org
+OK
index dca4fa5aa3f6f51cdb0f06e39bea9d91fa174d47..47345514b87ebc774c1eef918e168968c4372183 100644 (file)
 #include <setjmp.h>
 #include <stdlib.h>
 #include <unistd.h>
+#include <errno.h>
 
 #ifdef STRCASECMP_IN_STRINGS_H
 #include <strings.h>
 #endif
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
 #include <ctable.h>
 #include <mac_expand.h>
 #include <attr_clnt.h>
+#include <myaddrinfo.h>
+#include <inet_proto.h>
 
 /* DNS library. */
 
 #include <string_list.h>
 #include <namadr_list.h>
 #include <domain_list.h>
+#include <string_list.h>
 #include <mail_params.h>
 #include <rewrite_clnt.h>
 #include <resolve_clnt.h>
 #include <input_transp.h>
 #include <is_header.h>
 #include <rewrite_clnt.h>
+#include <valid_mailhost_addr.h>
 
 /* Application-specific. */
 
@@ -370,6 +371,8 @@ static void PRINTFLIKE(3, 4) defer_if(SMTPD_DEFER *, int, const char *,...);
     defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2))
 #define DEFER_IF_REJECT3(state, class, fmt, a1, a2, a3) \
     defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3))
+#define DEFER_IF_REJECT4(state, class, fmt, a1, a2, a3, a4) \
+    defer_if(&(state)->defer_if_reject, (class), (fmt), (a1), (a2), (a3), (a4))
 #define DEFER_IF_PERMIT2(state, class, fmt, a1, a2) do { \
     if ((state)->warn_if_reject == 0) \
        defer_if(&(state)->defer_if_permit, (class), (fmt), (a1), (a2)); \
@@ -944,14 +947,14 @@ static int reject_invalid_hostaddr(SMTPD_STATE *state, char *addr,
        msg_info("%s: %s", myname, addr);
 
     if (addr[0] == '[' && (len = strlen(addr)) > 2 && addr[len - 1] == ']') {
-       test_addr = mystrndup(&addr[1], len - 2);
+       test_addr = mystrndup(addr + 1, len - 2);
     } else
        test_addr = addr;
 
     /*
      * Validate the address.
      */
-    if (!valid_hostaddr(test_addr, DONT_GRIPE))
+    if (!valid_mailhost_addr(test_addr, DONT_GRIPE))
        stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
                                  "%d <%s>: %s rejected: invalid ip address",
                                var_bad_name_code, reply_name, reply_class);
@@ -987,7 +990,8 @@ static int reject_invalid_hostname(SMTPD_STATE *state, char *name,
     /*
      * Validate the hostname.
      */
-    if (!valid_hostname(test_name, DONT_GRIPE))
+    if (!valid_hostname(test_name, DONT_GRIPE)
+       && !valid_hostaddr(test_name, DONT_GRIPE))      /* XXX back compat */
        stat = smtpd_check_reject(state, MAIL_ERROR_POLICY,
                                  "%d <%s>: %s rejected: Invalid name",
                                var_bad_name_code, reply_name, reply_class);
@@ -1056,8 +1060,9 @@ static int reject_unknown_hostname(SMTPD_STATE *state, char *name,
 #define RR_ADDR_TYPES  T_A
 #endif
 
-    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
-                                 (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0);
+    dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
+                             (VSTRING *) 0, DNS_REQ_FLAG_ANY,
+                             RR_ADDR_TYPES, T_MX, 0);
     if (dns_status == DNS_NOTFOUND)
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
                                   "%d <%s>: %s rejected: Host not found",
@@ -1081,8 +1086,9 @@ static int reject_unknown_mailhost(SMTPD_STATE *state, const char *name,
     if (msg_verbose)
        msg_info("%s: %s", myname, name);
 
-    dns_status = dns_lookup_types(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
-                                 (VSTRING *) 0, RR_ADDR_TYPES, T_MX, 0);
+    dns_status = dns_lookup_l(name, 0, (DNS_RR **) 0, (VSTRING *) 0,
+                             (VSTRING *) 0, DNS_REQ_FLAG_ANY,
+                             RR_ADDR_TYPES, T_MX, 0);
     if (dns_status == DNS_NOTFOUND)
        return (smtpd_check_reject(state, MAIL_ERROR_POLICY,
                                   "%d <%s>: %s rejected: Domain not found",
@@ -1238,7 +1244,7 @@ static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
                            const char *reply_name, const char *reply_class)
 {
     char   *myname = "all_auth_mx_addr";
-    struct in_addr addr;
+    MAI_HOSTADDR_STR hostaddr;
     DNS_RR *rr;
     DNS_RR *addr_list;
     int     dns_status;
@@ -1255,7 +1261,8 @@ static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
     /*
      * Verify that all host addresses are within permit_mx_backup_networks.
      */
-    dns_status = dns_lookup(host, T_A, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0);
+    dns_status = dns_lookup_v(host, 0, &addr_list, (VSTRING *) 0, (VSTRING *) 0,
+                             DNS_REQ_FLAG_ALL, inet_proto_info()->dns_atype_list);
     if (dns_status != DNS_OK) {
        DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
        "450 <%s>: %s rejected: Unable to look up host %s as mail exchanger",
@@ -1263,16 +1270,15 @@ static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
        return (NOPE);
     }
     for (rr = addr_list; rr != 0; rr = rr->next) {
-       if (rr->data_len > sizeof(addr)) {
-           msg_warn("%s: skipping address length %d for host %s",
-                    state->queue_id, rr->data_len, host);
+       if (dns_rr_to_pa(rr, &hostaddr) == 0) {
+           msg_warn("%s: skipping record type %s for host %s: %m",
+                    myname, dns_strtype(rr->type), host);
            continue;
        }
-       memcpy((char *) &addr, rr->data, sizeof(addr));
        if (msg_verbose)
-           msg_info("%s: checking: %s", myname, inet_ntoa(addr));
+           msg_info("%s: checking: %s", myname, hostaddr.buf);
 
-       if (!namadr_list_match(perm_mx_networks, host, inet_ntoa(addr))) {
+       if (!namadr_list_match(perm_mx_networks, host, hostaddr.buf)) {
 
            /*
             * Reject: at least one IP address is not listed in
@@ -1280,7 +1286,7 @@ static int all_auth_mx_addr(SMTPD_STATE *state, char *host,
             */
            if (msg_verbose)
                msg_info("%s: address %s for %s does not match %s",
-                      myname, inet_ntoa(addr), host, VAR_PERM_MX_NETWORKS);
+                        myname, hostaddr.buf, host, VAR_PERM_MX_NETWORKS);
            dns_rr_free(addr_list);
            return (NOPE);
        }
@@ -1295,9 +1301,11 @@ static int has_my_addr(SMTPD_STATE *state, const char *host,
                            const char *reply_name, const char *reply_class)
 {
     char   *myname = "has_my_addr";
-    struct in_addr addr;
-    char  **cpp;
-    struct hostent *hp;
+    struct addrinfo *res;
+    struct addrinfo *res0;
+    int     aierr;
+    MAI_HOSTADDR_STR hostaddr;
+    INET_PROTO_INFO *proto_info = inet_proto_info();
 
     if (msg_verbose)
        msg_info("%s: host %s", myname, host);
@@ -1308,30 +1316,36 @@ static int has_my_addr(SMTPD_STATE *state, const char *host,
 #define YUP    1
 #define NOPE   0
 
-    if ((hp = gethostbyname(host)) == 0) {
-       DEFER_IF_REJECT3(state, MAIL_ERROR_POLICY,
-         "450 <%s>: %s rejected: Unable to look up mail exchanger host %s",
-                        reply_name, reply_class, host);
-       return (NOPE);
-    }
-    if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
-       msg_warn("address type %d length %d for %s",
-                hp->h_addrtype, hp->h_length, host);
+    aierr = hostname_to_sockaddr(host, (char *) 0, 0, &res0);
+    if (aierr) {
+       DEFER_IF_REJECT4(state, MAIL_ERROR_POLICY,
+                        "450 <%s>: %s rejected: Unable to look up mail exchanger host %s: %s",
+                        reply_name, reply_class, host, MAI_STRERROR(aierr));
        return (NOPE);
     }
-    for (cpp = hp->h_addr_list; *cpp; cpp++) {
-       memcpy((char *) &addr, *cpp, sizeof(addr));
-       if (msg_verbose)
-           msg_info("%s: addr %s", myname, inet_ntoa(addr));
-       if (own_inet_addr(&addr))
-           return (YUP);
-       if (proxy_inet_addr(&addr))
-           return (YUP);
+#define HAS_MY_ADDR_RETURN(x) { freeaddrinfo(res0); return (x); }
+
+    for (res = res0; res != 0; res = res->ai_next) {
+       if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+           if (msg_verbose)
+               msg_info("skipping address family %d for host %s",
+                        res->ai_family, host);
+           continue;
+       }
+       if (msg_verbose) {
+           SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
+                                &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+           msg_info("%s: addr %s", myname, hostaddr.buf);
+       }
+       if (own_inet_addr(res->ai_addr))
+           HAS_MY_ADDR_RETURN(YUP);
+       if (proxy_inet_addr(res->ai_addr))
+           HAS_MY_ADDR_RETURN(YUP);
     }
     if (msg_verbose)
        msg_info("%s: host %s: no match", myname, host);
 
-    return (NOPE);
+    HAS_MY_ADDR_RETURN(NOPE);
 }
 
 /* i_am_mx - is this machine listed as MX relay */
@@ -1339,7 +1353,7 @@ static int has_my_addr(SMTPD_STATE *state, const char *host,
 static int i_am_mx(SMTPD_STATE *state, DNS_RR *mx_list,
                           const char *reply_name, const char *reply_class)
 {
-    const char *myname = "permit_mx_backup";
+    const char *myname = "i_am_mx";
     DNS_RR *mx;
 
     /*
@@ -1376,9 +1390,13 @@ static int i_am_mx(SMTPD_STATE *state, DNS_RR *mx_list,
 static int permit_mx_primary(SMTPD_STATE *state, DNS_RR *mx_list,
                            const char *reply_name, const char *reply_class)
 {
+    const char *myname = "permit_mx_primary";
     DNS_RR *mx;
     unsigned int best_pref;
 
+    if (msg_verbose)
+       msg_info("%s", myname);
+
     /*
      * Find the preference of the primary MX hosts.
      */
@@ -2070,6 +2088,7 @@ static int check_addr_access(SMTPD_STATE *state, const char *table,
     char   *addr;
     const char *value;
     DICT   *dict;
+    int     delim;
 
     if (msg_verbose)
        msg_info("%s: %s", myname, address);
@@ -2080,6 +2099,12 @@ static int check_addr_access(SMTPD_STATE *state, const char *table,
 #define CHK_ADDR_RETURN(x,y) { *found = y; return(x); }
 
     addr = STR(vstring_strcpy(error_text, address));
+#ifdef HAS_IPV6
+    if (strchr(addr, ':') != 0)
+       delim = ':';
+    else
+#endif
+       delim = '.';
 
     if ((dict = dict_handle(table)) == 0)
        msg_panic("%s: dictionary not found: %s", myname, table);
@@ -2093,7 +2118,7 @@ static int check_addr_access(SMTPD_STATE *state, const char *table,
                msg_fatal("%s: table lookup problem", table);
        }
        flags = PARTIAL;
-    } while (split_at_right(addr, '.'));
+    } while (split_at_right(addr, delim));
 
     CHK_ADDR_RETURN(SMTPD_CHECK_DUNNO, MISSED);
 }
@@ -2151,12 +2176,12 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
     DNS_RR *server_list;
     DNS_RR *server;
     int     found = 0;
-    struct in_addr addr;
-    struct hostent *hp;
-    char   *addr_string;
+    MAI_HOSTADDR_STR addr_string;
+    int     aierr;
+    struct addrinfo *res0;
+    struct addrinfo *res;
     int     status;
-    char  **cpp;
-    static DNS_FIXED fixed;
+    INET_PROTO_INFO *proto_info;
 
     /*
      * Sanity check.
@@ -2189,7 +2214,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
                            (VSTRING *) 0, (VSTRING *) 0);
     if (dns_status == DNS_NOTFOUND && h_errno == NO_DATA) {
        if (type == T_MX) {
-           server_list = dns_rr_create(domain, &fixed, 0,
+           server_list = dns_rr_create(domain, type, C_IN, 0, 0,
                                        domain, strlen(domain) + 1);
            dns_status = DNS_OK;
        } else if (type == T_NS) {
@@ -2216,6 +2241,7 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
     /*
      * Check the hostnames first, then the addresses.
      */
+    proto_info = inet_proto_info();
     for (server = server_list; server != 0; server = server->next) {
        if (msg_verbose)
            msg_info("%s: %s hostname check: %s",
@@ -2224,32 +2250,35 @@ static int check_server_access(SMTPD_STATE *state, const char *table,
                                      FULL, &found, reply_name, reply_class,
                                          def_acl)) != 0 || found)
            CHECK_SERVER_RETURN(status);
-       SET_H_ERRNO(0);
-       if ((hp = gethostbyname((char *) server->data)) == 0) {
+       if ((aierr = hostname_to_sockaddr((char *) server->data,
+                                         (char *) 0, 0, &res0)) != 0) {
            msg_warn("Unable to look up %s host %s for %s %s: %s",
                     dns_strtype(type), (char *) server->data,
-                    reply_class, reply_name, dns_strerror(h_errno));
+                    reply_class, reply_name, MAI_STRERROR(aierr));
            continue;
        }
-       if (hp->h_addrtype != AF_INET || hp->h_length != sizeof(addr)) {
-           if (msg_verbose)
-               msg_warn("address type %d length %d for %s",
-                      hp->h_addrtype, hp->h_length, (char *) server->data);
-           continue;                           /* XXX */
-       }
+       /* Now we must also free the addrinfo result. */
        if (msg_verbose)
            msg_info("%s: %s host address check: %s",
                     myname, dns_strtype(type), (char *) server->data);
-       for (cpp = hp->h_addr_list; *cpp; cpp++) {
-           memcpy((char *) &addr, *cpp, sizeof(addr));
-           addr_string = mystrdup(inet_ntoa(addr));
-           status = check_addr_access(state, table, addr_string, FULL,
+       for (res = res0; res != 0; res = res->ai_next) {
+           if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+               if (msg_verbose)
+                   msg_info("skipping address family %d for host %s",
+                            res->ai_family, server->data);
+               continue;
+           }
+           SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
+                                &addr_string, (MAI_SERVPORT_STR *) 0, 0);
+           status = check_addr_access(state, table, addr_string.buf, FULL,
                                       &found, reply_name, reply_class,
                                       def_acl);
-           myfree(addr_string);
-           if (status != 0 || found)
+           if (status != 0 || found) {
+               freeaddrinfo(res0);             /* 200412 */
                CHECK_SERVER_RETURN(status);
+           }
        }
+       freeaddrinfo(res0);                     /* 200412 */
     }
     CHECK_SERVER_RETURN(SMTPD_CHECK_DUNNO);
 }
@@ -2501,12 +2530,13 @@ static const char *smtpd_expand_lookup(const char *name, int unused_mode,
 
 static void *rbl_pagein(const char *query, void *unused_context)
 {
+    const char *myname = "rbl_pagein";
     DNS_RR *txt_list;
     VSTRING *why;
     int     dns_status;
     SMTPD_RBL_STATE *rbl;
     DNS_RR *addr_list;
-    struct in_addr addr;
+    MAI_HOSTADDR_STR hostaddr;
     DNS_RR *rr;
     DNS_RR *next;
     VSTRING *buf;
@@ -2516,6 +2546,8 @@ static void *rbl_pagein(const char *query, void *unused_context)
      * Do the query. If the DNS lookup produces no definitive reply, give the
      * requestor the benefit of the doubt. We can't block all email simply
      * because an RBL server is unavailable.
+     * 
+     * Don't do this for AAAA records. Yet.
      */
     why = vstring_alloc(10);
     dns_status = dns_lookup(query, T_A, 0, &addr_list, (VSTRING *) 0, why);
@@ -2552,8 +2584,11 @@ static void *rbl_pagein(const char *query, void *unused_context)
        rbl->txt = 0;
     rbl->a = argv_alloc(1);
     for (rr = addr_list; rr != 0; rr = rr->next) {
-       memcpy((char *) &addr.s_addr, addr_list->data, sizeof(addr.s_addr));
-       argv_add(rbl->a, inet_ntoa(addr), ARGV_END);
+       if (dns_rr_to_pa(rr, &hostaddr) == 0)
+           msg_warn("%s: skipping record type %s for query %s: %m",
+                    myname, dns_strtype(rr->type), query);
+       else
+           argv_add(rbl->a, hostaddr.buf, ARGV_END);
     }
     dns_rr_free(addr_list);
     return ((void *) rbl);
@@ -2690,12 +2725,10 @@ static int reject_rbl_addr(SMTPD_STATE *state, const char *rbl_domain,
        msg_info("%s: %s %s", myname, reply_class, addr);
 
     /*
-     * IPv4 only for now
+     * IPv4 / IPv6-mapped IPv4 (if supported) only for now
      */
-#ifdef INET6
-    if (inet_pton(AF_INET, addr, &a) != 1)
+    if (valid_ipv6_hostaddr(addr, DONT_GRIPE))
        return SMTPD_CHECK_DUNNO;
-#endif
 
     /*
      * Reverse the client IPV4 address, tack on the RBL domain name and query
@@ -3134,7 +3167,7 @@ static int generic_checks(SMTPD_STATE *state, ARGV *restrictions,
            msg_warn("restriction %s is deprecated. Use %s instead",
                     PERMIT_NAKED_IP_ADDR, PERMIT_MYNETWORKS);
            if (state->helo_name) {
-               if (state->helo_name[strspn(state->helo_name, "0123456789.")] == 0
+               if (state->helo_name[strspn(state->helo_name, "0123456789.:")] == 0
                && (status = reject_invalid_hostaddr(state, state->helo_name,
                                   state->helo_name, SMTPD_NAME_HELO)) == 0)
                    status = SMTPD_CHECK_OK;
@@ -4095,6 +4128,7 @@ char   *var_mail_checks = "";
 char   *var_rcpt_checks = "";
 char   *var_etrn_checks = "";
 char   *var_data_checks = "";
+char   *var_eod_checks = "";
 char   *var_relay_domains = "";
 char   *var_mynetworks = "";
 char   *var_notify_classes = "";
@@ -4106,6 +4140,7 @@ char   *var_maps_rbl_domains;
 char   *var_myorigin;
 char   *var_mydest;
 char   *var_inet_interfaces;
+char   *var_proxy_interfaces;
 char   *var_rcpt_delim;
 char   *var_rest_classes;
 char   *var_alias_maps;
@@ -4146,6 +4181,7 @@ static STRING_TABLE string_table[] = {
     VAR_MYORIGIN, DEF_MYORIGIN, &var_myorigin,
     VAR_MYDEST, DEF_MYDEST, &var_mydest,
     VAR_INET_INTERFACES, DEF_INET_INTERFACES, &var_inet_interfaces,
+    VAR_PROXY_INTERFACES, DEF_PROXY_INTERFACES, &var_proxy_interfaces,
     VAR_RCPT_DELIM, DEF_RCPT_DELIM, &var_rcpt_delim,
     VAR_REST_CLASSES, DEF_REST_CLASSES, &var_rest_classes,
     VAR_ALIAS_MAPS, DEF_ALIAS_MAPS, &var_alias_maps,
@@ -4467,6 +4503,7 @@ int     main(int argc, char **argv)
     char   *bp;
     char   *resp;
     char   *addr;
+    INET_PROTO_INFO *proto_info;
 
     /*
      * Initialization. Use dummies for client information.
@@ -4480,6 +4517,8 @@ int     main(int argc, char **argv)
     smtpd_state_init(&state, VSTREAM_IN, "smtpd");
     state.queue_id = "<queue id>";
 
+    proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
+
     /*
      * Main loop: update config parameters or test the client, helo, sender
      * and recipient restrictions.
@@ -4567,35 +4606,36 @@ int     main(int argc, char **argv)
                resp = 0;
                break;
            }
-           if (strcasecmp(args->argv[0], "local_recipient_maps") == 0) {
+           if (strcasecmp(args->argv[0], VAR_LOCAL_RCPT_MAPS) == 0) {
                UPDATE_STRING(var_local_rcpt_maps, args->argv[1]);
                UPDATE_MAPS(local_rcpt_maps, VAR_LOCAL_RCPT_MAPS,
                            var_local_rcpt_maps, DICT_FLAG_LOCK);
                resp = 0;
                break;
            }
-           if (strcasecmp(args->argv[0], "relay_recipient_maps") == 0) {
+           if (strcasecmp(args->argv[0], VAR_RELAY_RCPT_MAPS) == 0) {
                UPDATE_STRING(var_relay_rcpt_maps, args->argv[1]);
                UPDATE_MAPS(relay_rcpt_maps, VAR_RELAY_RCPT_MAPS,
                            var_relay_rcpt_maps, DICT_FLAG_LOCK);
                resp = 0;
                break;
            }
-           if (strcasecmp(args->argv[0], "canonical_maps") == 0) {
+           if (strcasecmp(args->argv[0], VAR_CANONICAL_MAPS) == 0) {
                UPDATE_STRING(var_canonical_maps, args->argv[1]);
                UPDATE_MAPS(canonical_maps, VAR_CANONICAL_MAPS,
                            var_canonical_maps, DICT_FLAG_LOCK);
                resp = 0;
                break;
            }
-           if (strcasecmp(args->argv[0], "rbl_reply_maps") == 0) {
+           if (strcasecmp(args->argv[0], VAR_RBL_REPLY_MAPS) == 0) {
                UPDATE_STRING(var_rbl_reply_maps, args->argv[1]);
                UPDATE_MAPS(rbl_reply_maps, VAR_RBL_REPLY_MAPS,
                            var_rbl_reply_maps, DICT_FLAG_LOCK);
                resp = 0;
                break;
            }
-           if (strcasecmp(args->argv[0], "mynetworks") == 0) {
+           if (strcasecmp(args->argv[0], VAR_MYNETWORKS) == 0) {
+               /* NOT: UPDATE_STRING */
                namadr_list_free(mynetworks);
                mynetworks =
                    namadr_list_init(match_parent_style(VAR_MYNETWORKS),
@@ -4603,7 +4643,8 @@ int     main(int argc, char **argv)
                resp = 0;
                break;
            }
-           if (strcasecmp(args->argv[0], "relay_domains") == 0) {
+           if (strcasecmp(args->argv[0], VAR_RELAY_DOMAINS) == 0) {
+               /* NOT: UPDATE_STRING */
                domain_list_free(relay_domains);
                relay_domains =
                    domain_list_init(match_parent_style(VAR_RELAY_DOMAINS),
@@ -4611,6 +4652,15 @@ int     main(int argc, char **argv)
                resp = 0;
                break;
            }
+           if (strcasecmp(args->argv[0], VAR_PERM_MX_NETWORKS) == 0) {
+               UPDATE_STRING(var_perm_mx_networks, args->argv[1]);
+               domain_list_free(perm_mx_networks);
+               perm_mx_networks =
+                   namadr_list_init(match_parent_style(VAR_PERM_MX_NETWORKS),
+                                    args->argv[1]);
+               resp = 0;
+               break;
+           }
            if (strcasecmp(args->argv[0], "restriction_class") == 0) {
                rest_class(args->argv[1]);
                resp = 0;
index 2b56051789791a0180f656176ea803d001ae6df7..496fb67a25ef2491902ae062e85fd16bb100f81f 100644 (file)
@@ -34,6 +34,10 @@ helo random.bad.domain
 helo friend.bad.domain
 helo_restrictions reject_invalid_hostname,reject_unknown_hostname
 helo 123.123.123.123
+helo [123.123.123.123]
+helo [::]
+helo [ipv6:::]
+helo [ipv6::::]
 helo_restrictions permit_naked_ip_address,reject_invalid_hostname,reject_unknown_hostname
 helo 123.123.123.123
 #
index 859e8b3811e088abad2a85ee5d90ae62991560c0..0b96f5f22010aee3c45f9033f9c596622e3ec7e8 100644 (file)
@@ -69,6 +69,16 @@ OK
 >>> helo 123.123.123.123
 ./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 450 <123.123.123.123>: Helo command rejected: Host not found; proto=SMTP helo=<123.123.123.123>
 450 <123.123.123.123>: Helo command rejected: Host not found
+>>> helo [123.123.123.123]
+OK
+>>> helo [::]
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 501 <[::]>: Helo command rejected: invalid ip address; proto=SMTP helo=<[::]>
+501 <[::]>: Helo command rejected: invalid ip address
+>>> helo [ipv6:::]
+OK
+>>> helo [ipv6::::]
+./smtpd_check: <queue id>: reject: HELO from foo[123.123.123.123]: 501 <[ipv6::::]>: Helo command rejected: invalid ip address; proto=SMTP helo=<[ipv6::::]>
+501 <[ipv6::::]>: Helo command rejected: invalid ip address
 >>> helo_restrictions permit_naked_ip_address,reject_invalid_hostname,reject_unknown_hostname
 OK
 >>> helo 123.123.123.123
index 28c127f2a5df9bcd223d24c007d03b88f6f71a91..41f627d1dac59b2b3481b82b9932702ad8ac1889 100644 (file)
 #include <netdb.h>
 #include <string.h>
 
- /*
-  * Older systems don't have h_errno. Even modern systems don't have
-  * hstrerror().
-  */
-#ifdef NO_HERRNO
-
-static int h_errno = TRY_AGAIN;
-
-#define  HSTRERROR(err) "Host not found"
-
-#else
-
-#define  HSTRERROR(err) (\
-       err == TRY_AGAIN ? "Host not found, try again" : \
-       err == HOST_NOT_FOUND ? "Host not found" : \
-       err == NO_DATA ? "Host name has no address" : \
-       err == NO_RECOVERY ? "Name server failure" : \
-       strerror(errno) \
-    )
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
 #include <mymalloc.h>
-#include <valid_hostname.h>
 #include <stringops.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
 #include <mail_proto.h>
+#include <valid_mailhost_addr.h>
 
 /* Application-specific. */
 
@@ -103,21 +85,19 @@ static int h_errno = TRY_AGAIN;
 
 void    smtpd_peer_init(SMTPD_STATE *state)
 {
-    struct sockaddr_in sin;
-    SOCKADDR_SIZE len = sizeof(sin);
-    struct hostent *hp;
-    int     i;
+    char   *myname = "smtpd_peer_init";
+    struct sockaddr_storage ss;
+    SOCKADDR_SIZE sa_len;
+    struct sockaddr *sa;
+    INET_PROTO_INFO *proto_info = inet_proto_info();
 
-    /*
-     * Avoid suprious complaints from Purify on Solaris.
-     */
-    memset((char *) &sin, 0, len);
+    sa = (struct sockaddr *) & ss;
+    sa_len = sizeof(ss);
 
     /*
      * Look up the peer address information.
      */
-    if (getpeername(vstream_fileno(state->client),
-                   (struct sockaddr *) & sin, &len) >= 0) {
+    if (getpeername(vstream_fileno(state->client), sa, &sa_len) >= 0) {
        errno = 0;
     }
 
@@ -127,64 +107,137 @@ void    smtpd_peer_init(SMTPD_STATE *state)
     if (errno == ECONNRESET || errno == ECONNABORTED) {
        state->name = mystrdup(CLIENT_NAME_UNKNOWN);
        state->addr = mystrdup(CLIENT_ADDR_UNKNOWN);
+       state->rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
        state->peer_code = SMTPD_PEER_CODE_PERM;
     }
 
     /*
-     * Look up and "verify" the client hostname.
+     * Convert the client address to printable address and hostname.
      */
-    else if (errno == 0 && sin.sin_family == AF_INET) {
-       state->addr = mystrdup(inet_ntoa(sin.sin_addr));
-       hp = gethostbyaddr((char *) &(sin.sin_addr),
-                          sizeof(sin.sin_addr), AF_INET);
-       if (hp == 0) {
-           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
-           state->peer_code = (h_errno == TRY_AGAIN ?
-                               SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
-       } else if (valid_hostaddr(hp->h_name, DONT_GRIPE)) {
-           msg_warn("numeric result %s in address->name lookup for %s",
-                    hp->h_name, state->addr);
-           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
-           state->peer_code = SMTPD_PEER_CODE_PERM;
-       } else if (!valid_hostname(hp->h_name, DONT_GRIPE)) {
-           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
-           state->peer_code = SMTPD_PEER_CODE_PERM;
-       } else {
-           state->name = mystrdup(hp->h_name); /* hp->name is clobbered!! */
-           state->peer_code = SMTPD_PEER_CODE_OK;
+    else if (errno == 0
+            && strchr((char *) proto_info->sa_family_list, sa->sa_family)) {
+       MAI_HOSTNAME_STR client_name;
+       MAI_HOSTADDR_STR client_addr;
+       int     aierr;
+       char   *colonp;
+
+       /*
+        * Convert the client address to printable form.
+        */
+       if ((aierr = sockaddr_to_hostaddr(sa, sa_len, &client_addr,
+                                         (MAI_SERVPORT_STR *) 0, 0)) != 0)
+           msg_fatal("%s: cannot convert client address to string: %s",
+                     myname, MAI_STRERROR(aierr));
+
+       /*
+        * We convert IPv4-in-IPv6 address to 'true' IPv4 address early on,
+        * but only if IPv4 support is enabled (why would anyone want to turn
+        * it off)? With IPv4 support enabled we have no need for the IPv6
+        * form in logging, hostname verification and access checks.
+        */
+#ifdef HAS_IPV6
+       if (sa->sa_family == AF_INET6) {
+           if (strchr((char *) proto_info->sa_family_list, AF_INET) != 0
+               && IN6_IS_ADDR_V4MAPPED(&SOCK_ADDR_IN6_ADDR(sa))
+               && (colonp = strrchr(client_addr.buf, ':')) != 0) {
+               struct addrinfo *res0;
+
+               if (msg_verbose > 1)
+                   msg_info("%s: rewriting V4-mapped address \"%s\" to \"%s\"",
+                            myname, client_addr.buf, colonp + 1);
+
+               state->addr = mystrdup(colonp + 1);
+               state->rfc_addr = mystrdup(colonp + 1);
+               aierr = hostaddr_to_sockaddr(state->addr, (char *) 0, 0, &res0);
+               if (aierr)
+                   msg_fatal("%s: cannot convert %s from string to binary: %s",
+                             myname, state->addr, MAI_STRERROR(aierr));
+               sa_len = res0->ai_addrlen;
+               memcpy((char *) sa, res0->ai_addr, sa_len);
+               freeaddrinfo(res0);             /* 200412 */
+           }
 
            /*
-            * Reject the hostname if it does not list the peer address.
+            * Following RFC 2821 section 4.1.3, an IPv6 address literal gets
+            * a prefix of 'IPv6:'. We do this consistently for all IPv6
+            * addresses that that appear in headers or envelopes. The fact
+            * that valid_mailhost_addr() enforces the form helps of course.
+            * We use the form without IPV6: prefix when doing access
+            * control, or when accessing the connection cache.
             */
+           else {
+               state->addr = mystrdup(client_addr.buf);
+               state->rfc_addr =
+                   concatenate(IPV6_COL, client_addr.buf, (char *) 0);
+           }
+       }
+
+       /*
+        * An IPv4 address is in dotted quad decimal form.
+        */
+       else
+#endif
+       {
+           state->addr = mystrdup(client_addr.buf);
+           state->rfc_addr = mystrdup(client_addr.buf);
+       }
+
+       /*
+        * Look up and sanity check the client hostname.
+        * 
+        * It is unsafe to allow numeric hostnames, especially because there
+        * exists pressure to turn off the name->addr double check. In that
+        * case an attacker could trivally bypass access restrictions.
+        * 
+        * sockaddr_to_hostname() already rejects malformed or numeric names.
+        */
+#define TEMP_AI_ERROR(e) \
+       ((e) == EAI_AGAIN || (e) == EAI_MEMORY || (e) == EAI_SYSTEM)
+
 #define REJECT_PEER_NAME(state, code) { \
        myfree(state->name); \
        state->name = mystrdup(CLIENT_NAME_UNKNOWN); \
        state->peer_code = code; \
     }
 
-           hp = gethostbyname(state->name);    /* clobbers hp->name!! */
-           if (hp == 0) {
+       if ((aierr = sockaddr_to_hostname(sa, sa_len, &client_name,
+                                         (MAI_SERVNAME_STR *) 0, 0)) != 0) {
+           state->name = mystrdup(CLIENT_NAME_UNKNOWN);
+           state->peer_code = (TEMP_AI_ERROR(aierr) ?
+                               SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM);
+       } else {
+           struct addrinfo *res0;
+           struct addrinfo *res;
+
+           state->name = mystrdup(client_name.buf);
+           state->peer_code = SMTPD_PEER_CODE_OK;
+
+           /*
+            * Reject the hostname if it does not list the peer address.
+            */
+           aierr = hostname_to_sockaddr(state->name, (char *) 0, 0, &res0);
+           if (aierr) {
                msg_warn("%s: hostname %s verification failed: %s",
-                        state->addr, state->name, HSTRERROR(h_errno));
-               REJECT_PEER_NAME(state, (h_errno == TRY_AGAIN ?
+                        state->addr, state->name, MAI_STRERROR(aierr));
+               REJECT_PEER_NAME(state, (TEMP_AI_ERROR(aierr) ?
                              SMTPD_PEER_CODE_TEMP : SMTPD_PEER_CODE_PERM));
-           } else if (hp->h_length != sizeof(sin.sin_addr)) {
-               msg_warn("%s: hostname %s verification failed: bad address size %d",
-                        state->addr, state->name, hp->h_length);
-               REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
            } else {
-               for (i = 0; /* void */ ; i++) {
-                   if (hp->h_addr_list[i] == 0) {
+               for (res = res0; /* void */ ; res = res->ai_next) {
+                   if (res == 0) {
                        msg_warn("%s: address not listed for hostname %s",
                                 state->addr, state->name);
                        REJECT_PEER_NAME(state, SMTPD_PEER_CODE_PERM);
                        break;
                    }
-                   if (memcmp(hp->h_addr_list[i],
-                              (char *) &sin.sin_addr,
-                              sizeof(sin.sin_addr)) == 0)
+                   if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+                       msg_info("skipping address family %d for host %s",
+                                res->ai_family, state->name);
+                       continue;
+                   }
+                   if (sock_addr_cmp_addr(res->ai_addr, sa) == 0)
                        break;                  /* keep peer name */
                }
+               freeaddrinfo(res0);
            }
        }
     }
@@ -196,6 +249,7 @@ void    smtpd_peer_init(SMTPD_STATE *state)
     else {
        state->name = mystrdup("localhost");
        state->addr = mystrdup("127.0.0.1");    /* XXX bogus. */
+       state->rfc_addr = mystrdup("127.0.0.1");/* XXX bogus. */
        state->peer_code = SMTPD_PEER_CODE_OK;
     }
 
@@ -213,4 +267,5 @@ void    smtpd_peer_reset(SMTPD_STATE *state)
     myfree(state->name);
     myfree(state->addr);
     myfree(state->namaddr);
+    myfree(state->rfc_addr);
 }
index d6a9638f71a294790ce9890681751468207c0eb3..614c96147ed2fbb6ae678df10fd56d29053c1fa5 100644 (file)
@@ -83,6 +83,7 @@ void    smtpd_xforward_preset(SMTPD_STATE *state)
     state->xforward.name = mystrdup(CLIENT_NAME_UNKNOWN);
     state->xforward.addr = mystrdup(CLIENT_ADDR_UNKNOWN);
     state->xforward.namaddr = mystrdup(CLIENT_NAMADDR_UNKNOWN);
+    state->xforward.rfc_addr = mystrdup(CLIENT_ADDR_UNKNOWN);
     /* Leave helo at zero. */
     state->xforward.protocol = mystrdup(CLIENT_PROTO_UNKNOWN);
     /* Leave ident at zero. */
@@ -99,6 +100,7 @@ void    smtpd_xforward_reset(SMTPD_STATE *state)
     FREE_AND_WIPE(state->xforward.name);
     FREE_AND_WIPE(state->xforward.addr);
     FREE_AND_WIPE(state->xforward.namaddr);
+    FREE_AND_WIPE(state->xforward.rfc_addr);
     FREE_AND_WIPE(state->xforward.protocol);
     FREE_AND_WIPE(state->xforward.helo_name);
     FREE_AND_WIPE(state->xforward.ident);
index f3738bcc633caae34f7d2a0e088fd2af237b7906..7091a797a48aea310314786ff53effd60a05c55c 100644 (file)
@@ -15,7 +15,7 @@ LIBS  = ../../lib/libglobal.a ../../lib/libutil.a
 all:   $(PROG)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 smtp-sink: smtp-sink.o $(LIBS)
        $(CC) $(CFLAGS) -o $@ smtp-sink.o $(LIBS) $(SYSLIBS)
@@ -85,6 +85,7 @@ qmqp-sink.o: ../../include/events.h
 qmqp-sink.o: ../../include/mymalloc.h
 qmqp-sink.o: ../../include/msg_vstream.h
 qmqp-sink.o: ../../include/netstring.h
+qmqp-sink.o: ../../include/inet_proto.h
 qmqp-sink.o: ../../include/qmqp_proto.h
 qmqp-source.o: qmqp-source.c
 qmqp-source.o: ../../include/sys_defs.h
@@ -99,9 +100,11 @@ qmqp-source.o: ../../include/connect.h
 qmqp-source.o: ../../include/iostuff.h
 qmqp-source.o: ../../include/mymalloc.h
 qmqp-source.o: ../../include/events.h
-qmqp-source.o: ../../include/find_inet.h
 qmqp-source.o: ../../include/netstring.h
 qmqp-source.o: ../../include/sane_connect.h
+qmqp-source.o: ../../include/host_port.h
+qmqp-source.o: ../../include/myaddrinfo.h
+qmqp-source.o: ../../include/inet_proto.h
 qmqp-source.o: ../../include/mail_date.h
 qmqp-source.o: ../../include/qmqp_proto.h
 smtp-sink.o: smtp-sink.c
@@ -119,6 +122,7 @@ smtp-sink.o: ../../include/mymalloc.h
 smtp-sink.o: ../../include/msg_vstream.h
 smtp-sink.o: ../../include/stringops.h
 smtp-sink.o: ../../include/sane_accept.h
+smtp-sink.o: ../../include/inet_proto.h
 smtp-sink.o: ../../include/smtp_stream.h
 smtp-source.o: smtp-source.c
 smtp-source.o: ../../include/sys_defs.h
@@ -134,7 +138,9 @@ smtp-source.o: ../../include/connect.h
 smtp-source.o: ../../include/iostuff.h
 smtp-source.o: ../../include/mymalloc.h
 smtp-source.o: ../../include/events.h
-smtp-source.o: ../../include/find_inet.h
 smtp-source.o: ../../include/sane_connect.h
+smtp-source.o: ../../include/host_port.h
+smtp-source.o: ../../include/myaddrinfo.h
+smtp-source.o: ../../include/inet_proto.h
 smtp-source.o: ../../include/smtp_stream.h
 smtp-source.o: ../../include/mail_date.h
index 2154980632c56ebdafb26c587aed9aae9e2dcb49..6517698b8acde977e1aca694b61bddb5a2b3cabe 100644 (file)
@@ -5,19 +5,26 @@
 /*     multi-threaded QMQP test server
 /* SYNOPSIS
 /* .fi
-/*     \fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
+/*     \fBqmqp-sink\fR [\fB-46cv\fR] [\fB-x \fItime\fR]
 /*     [\fBinet:\fR][\fIhost\fR]:\fIport\fR \fIbacklog\fR
 /*
-/*     \fBqmqp-sink\fR [\fB-cv\fR] [\fB-x \fItime\fR]
+/*     \fBqmqp-sink\fR [\fB-46cv\fR] [\fB-x \fItime\fR]
 /*     \fBunix:\fR\fIpathname\fR \fIbacklog\fR
 /* DESCRIPTION
 /*     \fBqmqp-sink\fR listens on the named host (or address) and port.
 /*     It receives messages from the network and throws them away.
 /*     The purpose is to measure QMQP client performance, not protocol
 /*     compliance.
-/*     Connections can be accepted on IPV4 endpoints or UNIX-domain sockets.
-/*     IPV4 is the default.
+/*     Connections can be accepted on IPv4 or IPv6 endpoints, or on
+/*     UNIX-domain sockets.
+/*     IPv4 and IPv6 are the default.
 /*     This program is the complement of the \fBqmqp-source\fR(1) program.
+/* .IP \fB-4\fR
+/*     Support IPv4 only. This option has no effect when
+/*     Postfix is built without IPv6 support.
+/* .IP \fB-6\fR
+/*     Support IPv6 only. This option is not available when
+/*     Postfix is built without IPv6 support.
 /* .IP \fB-c\fR
 /*     Display a running counter that is updated whenever a delivery
 /*     is completed.
@@ -65,6 +72,7 @@
 #include <iostuff.h>
 #include <msg_vstream.h>
 #include <netstring.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -235,6 +243,8 @@ int     main(int argc, char **argv)
     int     backlog;
     int     ch;
     int     ttl;
+    const char *protocols = INET_PROTO_NAME_ALL;
+    INET_PROTO_INFO *proto_info;
 
     /*
      * Initialize diagnostics.
@@ -244,8 +254,14 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "cvx:")) > 0) {
+    while ((ch = GETOPT(argc, argv, "46cvx:")) > 0) {
        switch (ch) {
+       case '4':
+           protocols = INET_PROTO_NAME_IPV4;
+           break;
+       case '6':
+           protocols = INET_PROTO_NAME_IPV6;
+           break;
        case 'c':
            count++;
            break;
@@ -269,6 +285,7 @@ int     main(int argc, char **argv)
     /*
      * Initialize.
      */
+    proto_info = inet_proto_init("protocols", protocols);
     buffer = vstring_alloc(1024);
     if (strncmp(argv[optind], "unix:", 5) == 0) {
        sock = unix_listen(argv[optind] + 5, backlog, BLOCKING);
index dc0556a19c690d79cb19f460e60690da07db4f14..367de51bd93259b6a180d3d3efbfeda1cac54b3f 100644 (file)
 /*     \fBqmqp-source\fR connects to the named host and TCP port (default 628)
 /*     and sends one or more messages to it, either sequentially
 /*     or in parallel. The program speaks the QMQP protocol.
-/*     Connections can be made to UNIX-domain and IPV4 servers.
-/*     IPV4 is the default.
+/*     Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
+/*     IPv4 and IPv6 are the default.
 /*
 /*     Options:
+/* .IP \fB-4\fR
+/*     Connect to the server with IPv4. This option has no effect when
+/*     Postfix is built without IPv6 support.
+/* .IP \fB-6\fR
+/*     Connect to the server with IPv6. This option is not available when
+/*     Postfix is built without IPv6 support.
 /* .IP \fB-c\fR
 /*     Display a running counter that is incremented each time
 /*     a delivery completes.
 #include <connect.h>
 #include <mymalloc.h>
 #include <events.h>
-#include <find_inet.h>
 #include <iostuff.h>
 #include <netstring.h>
 #include <sane_connect.h>
+#include <host_port.h>
+#include <myaddrinfo.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -120,7 +128,7 @@ static int var_timeout = 300;
 static const char *var_myhostname;
 static int session_count;
 static int message_count = 1;
-static struct sockaddr_in sin;
+static struct sockaddr_storage ss;
 
 #undef sun
 static struct sockaddr_un sun;
@@ -436,6 +444,12 @@ int     main(int argc, char **argv)
     int     ch;
     int     n;
     int     i;
+    char   *buf;
+    const char *parse_err;
+    struct addrinfo *res;
+    int     aierr;
+    const char *protocols = INET_PROTO_NAME_ALL;
+    INET_PROTO_INFO *proto_info;
 
     signal(SIGPIPE, SIG_IGN);
     msg_vstream_init(argv[0], VSTREAM_ERR);
@@ -443,8 +457,14 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "cC:f:l:m:r:R:s:t:vw:")) > 0) {
+    while ((ch = GETOPT(argc, argv, "46cC:f:l:m:r:R:s:t:vw:")) > 0) {
        switch (ch) {
+       case '4':
+           protocols = INET_PROTO_NAME_IPV4;
+           break;
+       case '6':
+           protocols = INET_PROTO_NAME_IPV6;
+           break;
        case 'c':
            count++;
            break;
@@ -498,6 +518,7 @@ int     main(int argc, char **argv)
     /*
      * Translate endpoint address to internal form.
      */
+    proto_info = inet_proto_init("protocols", protocols);
     if (strncmp(argv[optind], "unix:", 5) == 0) {
        path = argv[optind] + 5;
        path_len = strlen(path);
@@ -514,14 +535,19 @@ int     main(int argc, char **argv)
     } else {
        if (strncmp(argv[optind], "inet:", 5) == 0)
            argv[optind] += 5;
-       if ((port = split_at(host = argv[optind], ':')) == 0 || *port == 0)
-           port = "628";
-       memset((char *) &sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = find_inet_addr(host);
-       sin.sin_port = find_inet_port(port, "tcp");
-       sa = (struct sockaddr *) & sin;
-       sa_length = sizeof(sin);
+       buf = mystrdup(argv[optind]);
+       if ((parse_err = host_port(buf, &host, (char *) 0, &port, "628")) != 0)
+           msg_fatal("%s: %s", argv[optind], parse_err);
+       if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
+           msg_fatal("%s: %s", argv[optind], MAI_STRERROR(aierr));
+       myfree(buf);
+       sa = (struct sockaddr *) & ss;
+       memcpy((char *) sa, res->ai_addr, res->ai_addrlen);
+       sa_length = res->ai_addrlen;
+#ifdef HAS_SA_LEN
+       sa->sa_len = sa_length;
+#endif
+       freeaddrinfo(res);
     }
 
     /*
index ec958d3736e1bd686b5ebf2d46b5f1fb0761d7d5..c5e9c090570c84711ca73eb631665d22e37d89af 100644 (file)
 /*     The purpose is to measure client performance, not protocol
 /*     compliance.
 /*
-/*     Connections can be accepted on IPV4 endpoints or UNIX-domain sockets.
-/*     IPV4 is the default.
+/*     Connections can be accepted on IPv4 or IPv6 endpoints, or on
+/*     UNIX-domain sockets.
+/*     IPv4 and IPv6 are the default.
 /*     This program is the complement of the \fBsmtp-source\fR(1) program.
 /*
 /*     Arguments:
+/* .IP \fB-4\fR
+/*     Support IPv4 only. This option has no effect when
+/*     Postfix is built without IPv6 support.
+/* .IP \fB-6\fR
+/*     Support IPv6 only. This option is not available when
+/*     Postfix is built without IPv6 support.
 /* .IP \fB-a\fR
 /*     Do not announce SASL authentication support.
 /* .IP \fB-c\fR
 #include <msg_vstream.h>
 #include <stringops.h>
 #include <sane_accept.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -480,7 +488,7 @@ static int command_read(SINK_STATE *state)
        smtp_flush(state->stream);
        return (0);
     }
-    if (cmdp->flags & FLAG_DISCONNECT) 
+    if (cmdp->flags & FLAG_DISCONNECT)
        return (-1);
     if (cmdp->flags & FLAG_HARD_ERR) {
        smtp_printf(state->stream, "500 Error: command failed");
@@ -602,6 +610,8 @@ int     main(int argc, char **argv)
     int     sock;
     int     backlog;
     int     ch;
+    const char *protocols = INET_PROTO_NAME_ALL;
+    INET_PROTO_INFO *proto_info;
 
     /*
      * Initialize diagnostics.
@@ -611,8 +621,14 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "acCef:Fh:Ln:pPq:r:s:vw:8")) > 0) {
+    while ((ch = GETOPT(argc, argv, "46acCef:Fh:Ln:pPq:r:s:vw:8")) > 0) {
        switch (ch) {
+       case '4':
+           protocols = INET_PROTO_NAME_IPV4;
+           break;
+       case '6':
+           protocols = INET_PROTO_NAME_IPV6;
+           break;
        case 'a':
            disable_saslauth = 1;
            break;
@@ -687,6 +703,7 @@ int     main(int argc, char **argv)
     set_cmds_flags(enable_lmtp ? "lhlo" :
                   disable_esmtp ? "helo" :
                   "helo, ehlo", FLAG_ENABLE);
+    proto_info = inet_proto_init("protocols", protocols);
     if (strncmp(argv[optind], "unix:", 5) == 0) {
        sock = unix_listen(argv[optind] + 5, backlog, BLOCKING);
     } else {
index 4a6d7df40f53adb8eefde8a5aa145e4eaea9cc74..99f389e344983c949f9e53f9ef64aab65acdc849 100644 (file)
 /*     (default: port 25)
 /*     and sends one or more messages to it, either sequentially
 /*     or in parallel. The program speaks either SMTP (default) or
-/*     LMTP. Connections can be made to UNIX-domain and IPV4 servers.
-/*     IPV4 is the default.
+/*     LMTP.
+/*     Connections can be made to UNIX-domain and IPv4 or IPv6 servers.
+/*     IPv4 and IPv6 are the default.
 /*
 /*     Arguments:
+/* .IP \fB-4\fR
+/*     Connect to the server with IPv4. This option has no effect when
+/*     Postfix is built without IPv6 support.
+/* .IP \fB-6\fR
+/*     Connect to the server with IPv6. This option is not available when
+/*     Postfix is built without IPv6 support.
 /* .IP \fB-c\fR
 /*     Display a running counter that is incremented each time
 /*     an SMTP DATA command completes.
 #include <connect.h>
 #include <mymalloc.h>
 #include <events.h>
-#include <find_inet.h>
 #include <iostuff.h>
 #include <sane_connect.h>
+#include <host_port.h>
+#include <myaddrinfo.h>
+#include <inet_proto.h>
 
 /* Global library. */
 
@@ -155,7 +164,7 @@ static int var_timeout = 300;
 static const char *var_myhostname;
 static int session_count;
 static int message_count = 1;
-static struct sockaddr_in sin;
+static struct sockaddr_storage ss;
 
 #undef sun
 static struct sockaddr_un sun;
@@ -790,6 +799,12 @@ int     main(int argc, char **argv)
     int     sessions = 1;
     int     ch;
     int     i;
+    char   *buf;
+    const char *parse_err;
+    struct addrinfo *res;
+    int     aierr;
+    const char *protocols = INET_PROTO_NAME_ALL;
+    INET_PROTO_INFO *proto_info;
 
     signal(SIGPIPE, SIG_IGN);
     msg_vstream_init(argv[0], VSTREAM_ERR);
@@ -797,8 +812,14 @@ int     main(int argc, char **argv)
     /*
      * Parse JCL.
      */
-    while ((ch = GETOPT(argc, argv, "cC:df:l:Lm:Nor:R:s:S:t:vw:")) > 0) {
+    while ((ch = GETOPT(argc, argv, "46cC:df:l:Lm:Nor:R:s:S:t:vw:")) > 0) {
        switch (ch) {
+       case '4':
+           protocols = INET_PROTO_NAME_IPV4;
+           break;
+       case '6':
+           protocols = INET_PROTO_NAME_IPV6;
+           break;
        case 'c':
            count++;
            break;
@@ -879,6 +900,7 @@ int     main(int argc, char **argv)
     /*
      * Translate endpoint address to internal form.
      */
+    proto_info = inet_proto_init("protocols", protocols);
     if (strncmp(argv[optind], "unix:", 5) == 0) {
        path = argv[optind] + 5;
        path_len = strlen(path);
@@ -895,14 +917,19 @@ int     main(int argc, char **argv)
     } else {
        if (strncmp(argv[optind], "inet:", 5) == 0)
            argv[optind] += 5;
-       if ((port = split_at(host = argv[optind], ':')) == 0 || *port == 0)
-           port = "smtp";
-       memset((char *) &sin, 0, sizeof(sin));
-       sin.sin_family = AF_INET;
-       sin.sin_addr.s_addr = find_inet_addr(host);
-       sin.sin_port = find_inet_port(port, "tcp");
-       sa = (struct sockaddr *) & sin;
-       sa_length = sizeof(sin);
+       buf = mystrdup(argv[optind]);
+       if ((parse_err = host_port(buf, &host, (char *) 0, &port, "smtp")) != 0)
+           msg_fatal("%s: %s", argv[optind], parse_err);
+       if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
+           msg_fatal("%s: %s", argv[optind], MAI_STRERROR(aierr));
+       myfree(buf);
+       sa = (struct sockaddr *) & ss;
+       memcpy((char *) sa, res->ai_addr, res->ai_addrlen);
+       sa_length = res->ai_addrlen;
+#ifdef HAS_SA_LEN
+       sa->sa_len = sa_length;
+#endif
+       freeaddrinfo(res);
     }
 
     /*
index be7554fa8d04aabafb6d0da1033245da8dfb8882..06b0d8234e596e40458f018570194f7cfbc3763e 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index f511177954a640068fb3dda3c32e21c1eda795d9..bffe190b7b27b0363a234c8fa27f1a839bb143dc 100644 (file)
@@ -21,7 +21,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -144,8 +144,8 @@ trivial-rewrite.o: ../../include/iostuff.h
 trivial-rewrite.o: ../../include/attr.h
 trivial-rewrite.o: ../../include/resolve_local.h
 trivial-rewrite.o: ../../include/mail_conf.h
-trivial-rewrite.o: ../../include/rewrite_clnt.h
 trivial-rewrite.o: ../../include/resolve_clnt.h
+trivial-rewrite.o: ../../include/rewrite_clnt.h
 trivial-rewrite.o: ../../include/tok822.h
 trivial-rewrite.o: ../../include/mail_addr.h
 trivial-rewrite.o: ../../include/mail_server.h
index 3b345671dc32439b8319221908e038c393ea4272..8809405fb2ee3e9202f07dce05a5ad83657b4655 100644 (file)
@@ -356,12 +356,16 @@ static void resolve_addr(RES_CONTEXT *rp, char *addr,
      * XXX This may produce incorrect results if we cracked open a quoted
      * local-part with routing operators; see discussion above at the top of
      * the big loop.
+     * 
+     * XXX We explicitly disallow domain names in bare network address form. A
+     * network address destination should be formatted according to RFC 2821:
+     * it should be enclosed in [], and an IPv6 address should have an IPv6:
+     * prefix.
      */
     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)
-        || valid_hostaddr(rcpt_domain, DONT_GRIPE)))
+    if (*rcpt_domain == '[' ? !valid_mailhost_literal(rcpt_domain, DONT_GRIPE) :
+       !valid_hostname(rcpt_domain, DONT_GRIPE))
        *flags |= RESOLVE_FLAG_ERROR;
     tok822_free_tree(tree);
     tree = 0;
index a271eb5ab74dade28cc7d9e24d9e97f96500ace3..87d89da5bc87f165652aa11755aeffdc4b1da061 100644 (file)
@@ -10,7 +10,7 @@ SRCS  = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
        fifo_trigger.c file_limit.c find_inet.c fsspace.c fullname.c \
        get_domainname.c get_hostname.c hex_quote.c host_port.c htable.c \
        inet_addr_host.c inet_addr_list.c inet_addr_local.c inet_connect.c \
-       inet_listen.c inet_trigger.c inet_util.c line_wrap.c \
+       inet_listen.c inet_trigger.c line_wrap.c \
        lowercase.c lstat_as.c mac_expand.c mac_parse.c make_dirs.c \
        match_list.c match_ops.c msg.c msg_output.c msg_syslog.c \
        msg_vstream.c mvect.c myflock.c mymalloc.c myrand.c mystrtok.c \
@@ -29,7 +29,8 @@ SRCS  = alldig.c argv.c argv_split.c attr_print0.c attr_print64.c \
        write_buf.c write_wait.c auto_clnt.c attr_clnt.c attr_scan_plain.c \
        attr_print_plain.c sane_connect.c neuter.c name_code.c \
        uppercase.c unix_recv_fd.c stream_recv_fd.c unix_send_fd.c \
-       stream_send_fd.c dict_sdbm.c hex_code.c dummy_read.c dummy_write.c
+       stream_send_fd.c dict_sdbm.c hex_code.c dummy_read.c dummy_write.c \
+       myaddrinfo.c sock_addr.c inet_proto.c cidr_match.c mask_addr.c
 OBJS   = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
        attr_scan0.o attr_scan64.o base64_code.o basename.o binhash.o \
        chroot_uid.o clean_env.o close_on_exec.o concatenate.o ctable.o \
@@ -41,7 +42,7 @@ OBJS  = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
        fifo_trigger.o file_limit.o find_inet.o fsspace.o fullname.o \
        get_domainname.o get_hostname.o hex_quote.o host_port.o htable.o \
        inet_addr_host.o inet_addr_list.o inet_addr_local.o inet_connect.o \
-       inet_listen.o inet_trigger.o inet_util.o line_wrap.o \
+       inet_listen.o inet_trigger.o line_wrap.o \
        lowercase.o lstat_as.o mac_expand.o mac_parse.o make_dirs.o \
        match_list.o match_ops.o msg.o msg_output.o msg_syslog.o \
        msg_vstream.o mvect.o myflock.o mymalloc.o myrand.o mystrtok.o \
@@ -60,7 +61,8 @@ OBJS  = alldig.o argv.o argv_split.o attr_print0.o attr_print64.o \
        write_buf.o write_wait.o auto_clnt.o attr_clnt.o attr_scan_plain.o \
        attr_print_plain.o sane_connect.o $(STRCASE) neuter.o name_code.o \
        uppercase.o unix_recv_fd.o stream_recv_fd.o unix_send_fd.o \
-       stream_send_fd.o dict_sdbm.o hex_code.o dummy_read.o dummy_write.o
+       stream_send_fd.o dict_sdbm.o hex_code.o dummy_read.o dummy_write.o \
+       myaddrinfo.o sock_addr.o inet_proto.o cidr_match.o mask_addr.o
 HDRS   = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
        connect.h ctable.h dict.h dict_db.h dict_cdb.h dict_dbm.h dict_env.h \
        dict_cidr.h dict_ht.h dict_ni.h dict_nis.h \
@@ -68,7 +70,7 @@ HDRS  = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
        dict_static.h dict_tcp.h dict_unix.h dir_forest.h events.h \
        exec_command.h find_inet.h fsspace.h fullname.h get_domainname.h \
        get_hostname.h hex_quote.h host_port.h htable.h inet_addr_host.h \
-       inet_addr_list.h inet_addr_local.h inet_util.h iostuff.h \
+       inet_addr_list.h inet_addr_local.h iostuff.h \
        line_wrap.h listen.h lstat_as.h mac_expand.h mac_parse.h \
        make_dirs.h match_list.h match_ops.h msg.h msg_output.h \
        msg_syslog.h msg_vstream.h mvect.h myflock.h mymalloc.h myrand.h \
@@ -80,7 +82,8 @@ HDRS  = argv.h attr.h base64_code.h binhash.h chroot_uid.h clean_env.h \
        timed_wait.h trigger.h username.h valid_hostname.h vbuf.h \
        vbuf_print.h vstream.h vstring.h vstring_vstream.h watchdog.h \
        auto_clnt.h attr_clnt.h sane_connect.h name_code.h dict_sdbm.h \
-       hex_code.h
+       hex_code.h myaddrinfo.h sock_addr.h inet_proto.h cidr_match.h \
+       mask_addr.h
 TESTSRC        = fifo_open.c fifo_rdwr_bug.c fifo_rdonly_bug.c select_bug.c \
        stream_test.c dup2_pass_on_exec.c
 DEFS   = -I. -D$(SYSTYPE)
@@ -96,7 +99,8 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \
        inet_addr_list attr_print64 attr_scan64 base64_code attr_print0 \
        attr_scan0 host_port attr_scan_plain attr_print_plain htable \
-       unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code
+       unix_recv_fd unix_send_fd stream_recv_fd stream_send_fd hex_code \
+       myaddrinfo myaddrinfo4 inet_proto
 
 LIB_DIR        = ../../lib
 INC_DIR        = ../../include
@@ -106,7 +110,7 @@ INC_DIR     = ../../include
 all: $(LIB)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
@@ -370,6 +374,21 @@ hex_code: $(LIB)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
+myaddrinfo: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
+myaddrinfo4: $(LIB)
+       mv myaddrinfo.o junk
+       $(CC) $(CFLAGS) -DTEST -DEMULATE_IPV4_ADDRINFO -o $@ myaddrinfo.c $(LIB) $(SYSLIBS)
+       mv junk myaddrinfo.o
+
+inet_proto: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
        set -e; for i in [a-z][a-z0-9]*.c; do \
@@ -384,7 +403,8 @@ stream_test: stream_test.c $(LIB)
 tests: valid_hostname_test mac_expand_test dict_test unescape_test \
        hex_quote_test ctable_test inet_addr_list_test base64_code_test \
        attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \
-       dict_cidr_test attr_scan_plain_test htable_test hex_code_test
+       dict_cidr_test attr_scan_plain_test htable_test hex_code_test \
+       myaddrinfo_test
 
 valid_hostname_test: valid_hostname valid_hostname.in valid_hostname.ref
        ./valid_hostname <valid_hostname.in 2>valid_hostname.tmp
@@ -471,6 +491,21 @@ htable_test: htable /usr/share/dict/words
 hex_code_test: hex_code
        ./hex_code
 
+myaddrinfo_test: myaddrinfo myaddrinfo.ref myaddrinfo.ref2
+       ./myaddrinfo all belly.porcupine.org 168.100.189.2 >myaddrinfo.tmp 2>&1
+       diff myaddrinfo.ref myaddrinfo.tmp
+       rm -f myaddrinfo.tmp
+       ./myaddrinfo all null.porcupine.org 10.0.0.0 >myaddrinfo.tmp 2>&1
+       diff myaddrinfo.ref2 myaddrinfo.tmp
+       rm -f myaddrinfo.tmp
+
+myaddrinfo4_test: myaddrinfo4 myaddrinfo4.ref myaddrinfo4.ref2
+       ./myaddrinfo4 all belly.porcupine.org 168.100.189.2 >myaddrinfo4.tmp 2>&1
+       diff myaddrinfo4.ref myaddrinfo4.tmp
+       ./myaddrinfo4 all null.porcupine.org 10.0.0.0 >myaddrinfo4.tmp 2>&1
+       diff myaddrinfo4.ref2 myaddrinfo4.tmp
+       rm -f myaddrinfo4.tmp
+
 # do not edit below this line - it is generated by 'make depend'
 alldig.o: alldig.c
 alldig.o: sys_defs.h
@@ -593,6 +628,16 @@ chroot_uid.o: chroot_uid.c
 chroot_uid.o: sys_defs.h
 chroot_uid.o: msg.h
 chroot_uid.o: chroot_uid.h
+cidr_match.o: cidr_match.c
+cidr_match.o: sys_defs.h
+cidr_match.o: msg.h
+cidr_match.o: vstring.h
+cidr_match.o: vbuf.h
+cidr_match.o: stringops.h
+cidr_match.o: split_at.h
+cidr_match.o: myaddrinfo.h
+cidr_match.o: mask_addr.h
+cidr_match.o: cidr_match.h
 clean_env.o: clean_env.c
 clean_env.o: sys_defs.h
 clean_env.o: msg.h
@@ -663,8 +708,9 @@ dict_cidr.o: stringops.h
 dict_cidr.o: readlline.h
 dict_cidr.o: dict.h
 dict_cidr.o: argv.h
+dict_cidr.o: myaddrinfo.h
+dict_cidr.o: cidr_match.h
 dict_cidr.o: dict_cidr.h
-dict_cidr.o: split_at.h
 dict_db.o: dict_db.c
 dict_db.o: sys_defs.h
 dict_db.o: msg.h
@@ -949,12 +995,19 @@ htable.o: msg.h
 htable.o: htable.h
 inet_addr_host.o: inet_addr_host.c
 inet_addr_host.o: sys_defs.h
+inet_addr_host.o: mymalloc.h
 inet_addr_host.o: inet_addr_list.h
+inet_addr_host.o: myaddrinfo.h
 inet_addr_host.o: inet_addr_host.h
+inet_addr_host.o: sock_addr.h
+inet_addr_host.o: inet_proto.h
+inet_addr_host.o: msg.h
 inet_addr_list.o: inet_addr_list.c
 inet_addr_list.o: sys_defs.h
 inet_addr_list.o: msg.h
 inet_addr_list.o: mymalloc.h
+inet_addr_list.o: myaddrinfo.h
+inet_addr_list.o: sock_addr.h
 inet_addr_list.o: inet_addr_list.h
 inet_addr_local.o: inet_addr_local.c
 inet_addr_local.o: sys_defs.h
@@ -963,26 +1016,41 @@ inet_addr_local.o: mymalloc.h
 inet_addr_local.o: vstring.h
 inet_addr_local.o: vbuf.h
 inet_addr_local.o: inet_addr_list.h
+inet_addr_local.o: myaddrinfo.h
 inet_addr_local.o: inet_addr_local.h
+inet_addr_local.o: sock_addr.h
+inet_addr_local.o: mask_addr.h
+inet_addr_local.o: hex_code.h
 inet_connect.o: inet_connect.c
 inet_connect.o: sys_defs.h
 inet_connect.o: mymalloc.h
 inet_connect.o: msg.h
-inet_connect.o: find_inet.h
-inet_connect.o: inet_util.h
 inet_connect.o: iostuff.h
+inet_connect.o: host_port.h
 inet_connect.o: sane_connect.h
 inet_connect.o: connect.h
 inet_connect.o: timed_connect.h
+inet_connect.o: myaddrinfo.h
+inet_connect.o: sock_addr.h
+inet_connect.o: inet_proto.h
 inet_listen.o: inet_listen.c
 inet_listen.o: sys_defs.h
 inet_listen.o: mymalloc.h
 inet_listen.o: msg.h
-inet_listen.o: find_inet.h
-inet_listen.o: inet_util.h
+inet_listen.o: host_port.h
 inet_listen.o: iostuff.h
 inet_listen.o: listen.h
 inet_listen.o: sane_accept.h
+inet_listen.o: myaddrinfo.h
+inet_listen.o: sock_addr.h
+inet_listen.o: inet_proto.h
+inet_proto.o: inet_proto.c
+inet_proto.o: sys_defs.h
+inet_proto.o: mymalloc.h
+inet_proto.o: msg.h
+inet_proto.o: myaddrinfo.h
+inet_proto.o: name_mask.h
+inet_proto.o: inet_proto.h
 inet_trigger.o: inet_trigger.c
 inet_trigger.o: sys_defs.h
 inet_trigger.o: msg.h
@@ -991,11 +1059,6 @@ inet_trigger.o: iostuff.h
 inet_trigger.o: mymalloc.h
 inet_trigger.o: events.h
 inet_trigger.o: trigger.h
-inet_util.o: inet_util.c
-inet_util.o: sys_defs.h
-inet_util.o: mymalloc.h
-inet_util.o: split_at.h
-inet_util.o: inet_util.h
 line_wrap.o: line_wrap.c
 line_wrap.o: sys_defs.h
 line_wrap.o: line_wrap.h
@@ -1031,6 +1094,10 @@ make_dirs.o: stringops.h
 make_dirs.o: vstring.h
 make_dirs.o: vbuf.h
 make_dirs.o: make_dirs.h
+mask_addr.o: mask_addr.c
+mask_addr.o: sys_defs.h
+mask_addr.o: msg.h
+mask_addr.o: mask_addr.h
 match_list.o: match_list.c
 match_list.o: sys_defs.h
 match_list.o: msg.h
@@ -1056,6 +1123,8 @@ match_ops.o: argv.h
 match_ops.o: match_ops.h
 match_ops.o: stringops.h
 match_ops.o: vstring.h
+match_ops.o: cidr_match.h
+match_ops.o: myaddrinfo.h
 msg.o: msg.c
 msg.o: sys_defs.h
 msg.o: msg.h
@@ -1090,6 +1159,17 @@ mvect.o: mvect.c
 mvect.o: sys_defs.h
 mvect.o: mymalloc.h
 mvect.o: mvect.h
+myaddrinfo.o: myaddrinfo.c
+myaddrinfo.o: sys_defs.h
+myaddrinfo.o: mymalloc.h
+myaddrinfo.o: valid_hostname.h
+myaddrinfo.o: sock_addr.h
+myaddrinfo.o: stringops.h
+myaddrinfo.o: vstring.h
+myaddrinfo.o: vbuf.h
+myaddrinfo.o: msg.h
+myaddrinfo.o: inet_proto.h
+myaddrinfo.o: myaddrinfo.h
 myflock.o: myflock.c
 myflock.o: sys_defs.h
 myflock.o: msg.h
@@ -1259,6 +1339,10 @@ skipblanks.o: sys_defs.h
 skipblanks.o: stringops.h
 skipblanks.o: vstring.h
 skipblanks.o: vbuf.h
+sock_addr.o: sock_addr.c
+sock_addr.o: sys_defs.h
+sock_addr.o: msg.h
+sock_addr.o: sock_addr.h
 spawn_command.o: spawn_command.c
 spawn_command.o: sys_defs.h
 spawn_command.o: msg.h
@@ -1322,6 +1406,7 @@ stream_trigger.o: events.h
 stream_trigger.o: trigger.h
 sys_compat.o: sys_compat.c
 sys_compat.o: sys_defs.h
+sys_compat.o: iostuff.h
 timed_connect.o: timed_connect.c
 timed_connect.o: sys_defs.h
 timed_connect.o: msg.h
index d603dac1c8dcb8efd682d2d8c987f9909b84ca4c..f490c703464245658c0510ac344dd16eeef3e47d 100644 (file)
@@ -8,8 +8,8 @@
 /*     string array utilities
 /* SYNOPSIS
 /*     #include "argv.h"
- DESCRIPTION
- .nf
+/* DESCRIPTION
+/* .nf
 
  /*
   * External interface.
diff --git a/postfix/src/util/cidr_match.c b/postfix/src/util/cidr_match.c
new file mode 100644 (file)
index 0000000..b72b8db
--- /dev/null
@@ -0,0 +1,230 @@
+/*++
+/* NAME
+/*     cidr_match 3
+/* SUMMARY
+/*     CIDR-style pattern matching
+/* SYNOPSIS
+/*     #include <cidr_match.h>
+/*
+/*     VSTRING *cidr_match_parse(info, pattern, why)
+/*     CIDR_MATCH *info;
+/*     char    *pattern;
+/*     VSTRING *why;
+/*
+/*     int     cidr_match_execute(info, address)
+/*     CIDR_MATCH *info;
+/*     const char *address;
+/* DESCRIPTION
+/*     This module parses address or address/length patterns and
+/*     provides simple address matching. The implementation is
+/*     such that parsing and execution can be done without dynamic
+/*     memory allocation. The purpose is to minimize overhead when
+/*     called by functions that parse and execute on the fly, such
+/*     as match_hostaddr().
+/*
+/*     cidr_match_parse() parses an address or address/mask
+/*     expression and stores the result into the info argument.
+/*     The result is non-zero in case of problems: either the
+/*     value of the why argument, or a newly allocated VSTRING
+/*     (the caller should give the latter to vstring_free()).
+/*     The pattern argument is destroyed.
+/*
+/*     cidr_match_execute() matches the specified address against
+/*     a list of parsed expressions, and returns the matching
+/*     expression's data structure.
+/* SEE ALSO
+/*     dict_cidr(3) CIDR-style lookup table
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <vstring.h>
+#include <stringops.h>
+#include <split_at.h>
+#include <myaddrinfo.h>
+#include <mask_addr.h>
+#include <cidr_match.h>
+
+/* Application-specific. */
+
+ /*
+  * This is how we figure out the address family, address bit count and
+  * address byte count for a CIDR_MATCH entry.
+  */
+#ifdef HAS_IPV6
+#define CIDR_MATCH_ADDR_FAMILY(a) (strchr((a), ':') ? AF_INET6 : AF_INET)
+#define CIDR_MATCH_ADDR_BIT_COUNT(f) \
+    ((f) == AF_INET6 ? MAI_V6ADDR_BITS : \
+     (f) == AF_INET ? MAI_V4ADDR_BITS : \
+     (msg_panic("%s: bad address family %d", myname, (f)), 0))
+#define CIDR_MATCH_ADDR_BYTE_COUNT(f) \
+    ((f) == AF_INET6 ? MAI_V6ADDR_BYTES : \
+     (f) == AF_INET ? MAI_V4ADDR_BYTES : \
+     (msg_panic("%s: bad address family %d", myname, (f)), 0))
+#else
+#define CIDR_MATCH_ADDR_FAMILY(a) (AF_INET)
+#define CIDR_MATCH_ADDR_BIT_COUNT(f) \
+    ((f) == AF_INET ? MAI_V4ADDR_BITS : \
+     (msg_panic("%s: bad address family %d", myname, (f)), 0))
+#define CIDR_MATCH_ADDR_BYTE_COUNT(f) \
+    ((f) == AF_INET ? MAI_V4ADDR_BYTES : \
+     (msg_panic("%s: bad address family %d", myname, (f)), 0))
+#endif
+
+/* cidr_match_execute - match address against compiled CIDR pattern list */
+
+CIDR_MATCH *cidr_match_execute(CIDR_MATCH *list, const char *addr)
+{
+    unsigned char addr_bytes[CIDR_MATCH_ABYTES];
+    unsigned addr_family;
+    unsigned char *mp;
+    unsigned char *np;
+    unsigned char *ap;
+    CIDR_MATCH *entry;
+
+    addr_family = CIDR_MATCH_ADDR_FAMILY(addr);
+    if (inet_pton(addr_family, addr, addr_bytes) != 1)
+       return (0);
+
+    for (entry = list; entry; entry = entry->next) {
+       if (entry->addr_family == addr_family) {
+           /* Unoptimized case: netmask with some or all bits zero. */
+           if (entry->mask_shift < entry->addr_bit_count) {
+               for (np = entry->net_bytes, mp = entry->mask_bytes,
+                    ap = addr_bytes; /* void */ ; np++, mp++, ap++) {
+                   if (ap >= addr_bytes + entry->addr_byte_count)
+                       return (entry);
+                   if ((*ap & *mp) != *np)
+                       break;
+               }
+           }
+           /* Optimized case: all 1 netmask (i.e. no netmask specified). */
+           else {
+               for (np = entry->net_bytes,
+                    ap = addr_bytes; /* void */ ; np++, ap++) {
+                   if (ap >= addr_bytes + entry->addr_byte_count)
+                       return (entry);
+                   if (*ap != *np)
+                       break;
+               }
+           }
+       }
+    }
+    return (0);
+}
+
+/* cidr_match_parse - parse CIDR pattern */
+
+VSTRING *cidr_match_parse(CIDR_MATCH *ip, char *pattern, VSTRING *why)
+{
+    const char *myname = "cidr_match_parse";
+    char   *mask_search;
+    char   *mask;
+    MAI_HOSTADDR_STR hostaddr;
+    unsigned char *np;
+    unsigned char *mp;
+
+    /*
+     * Strip [] from [addr/len] or [addr]/len, destroying the pattern. CIDR
+     * maps don't need [] to eliminate syntax ambiguity, but matchlists need
+     * it. While stripping [], figure out where we should start looking for
+     * /mask information.
+     */
+    if (*pattern == '[') {
+       pattern++;
+       if ((mask_search = split_at(pattern, ']')) == 0) {
+           vstring_sprintf(why ? why : (why = vstring_alloc(20)),
+                           "missing ']' character after \"[%s\"", pattern);
+           return (why);
+       } else if (*mask_search != '/') {
+           if (*mask_search != 0) {
+               vstring_sprintf(why ? why : (why = vstring_alloc(20)),
+                               "garbage after \"[%s]\"", pattern);
+               return (why);
+           }
+           mask_search = pattern;
+       }
+    } else
+       mask_search = pattern;
+
+    /*
+     * Parse the pattern into network and mask, destroying the pattern.
+     */
+    if ((mask = split_at(mask_search, '/')) != 0) {
+       ip->addr_family = CIDR_MATCH_ADDR_FAMILY(pattern);
+       ip->addr_bit_count = CIDR_MATCH_ADDR_BIT_COUNT(ip->addr_family);
+       ip->addr_byte_count = CIDR_MATCH_ADDR_BYTE_COUNT(ip->addr_family);
+       if (!alldig(mask)
+           || (ip->mask_shift = atoi(mask)) > ip->addr_bit_count
+           || inet_pton(ip->addr_family, pattern, ip->net_bytes) != 1) {
+           vstring_sprintf(why ? why : (why = vstring_alloc(20)),
+                         "bad net/mask pattern: \"%s/%s\"", pattern, mask);
+           return (why);
+       }
+       if (ip->mask_shift > 0) {
+           /* Allow for bytes > 8. */
+           memset(ip->mask_bytes, (unsigned char) -1, ip->addr_byte_count);
+           mask_addr(ip->mask_bytes, ip->addr_byte_count, ip->mask_shift);
+       } else
+           memset(ip->mask_bytes, 0, ip->addr_byte_count);
+
+       /*
+        * Sanity check: all host address bits must be zero.
+        */
+       for (np = ip->net_bytes, mp = ip->mask_bytes;
+            np < ip->net_bytes + ip->addr_byte_count; np++, mp++) {
+           if (*np & ~(*mp)) {
+               mask_addr(ip->net_bytes, ip->addr_byte_count, ip->mask_shift);
+               if (inet_ntop(ip->addr_family, ip->net_bytes, hostaddr.buf,
+                             sizeof(hostaddr.buf)) == 0)
+                   msg_fatal("inet_ntop: %m");
+               vstring_sprintf(why ? why : (why = vstring_alloc(20)),
+                               "non-null host address bits in \"%s/%s\", "
+                               "perhaps you should use \"%s/%d\" instead",
+                               pattern, mask, hostaddr.buf, ip->mask_shift);
+               return (why);
+           }
+       }
+    }
+
+    /*
+     * No /mask specified. Treat a bare network address as /allbits.
+     */
+    else {
+       ip->addr_family = CIDR_MATCH_ADDR_FAMILY(pattern);
+       ip->addr_bit_count = CIDR_MATCH_ADDR_BIT_COUNT(ip->addr_family);
+       ip->addr_byte_count = CIDR_MATCH_ADDR_BYTE_COUNT(ip->addr_family);
+       if (inet_pton(ip->addr_family, pattern, ip->net_bytes) != 1) {
+           vstring_sprintf(why ? why : (why = vstring_alloc(20)),
+                           "bad address pattern: \"%s\"", pattern);
+           return (why);
+       }
+       ip->mask_shift = ip->addr_bit_count;
+       /* Allow for bytes > 8. */
+       memset(ip->mask_bytes, (unsigned char) -1, ip->addr_byte_count);
+    }
+
+    /*
+     * Wrap up the result.
+     */
+    ip->next = 0;
+
+    return (0);
+}
diff --git a/postfix/src/util/cidr_match.h b/postfix/src/util/cidr_match.h
new file mode 100644 (file)
index 0000000..153394f
--- /dev/null
@@ -0,0 +1,64 @@
+#ifndef _CIDR_MATCH_H_INCLUDED_
+#define _CIDR_MATCH_H_INCLUDED_
+
+/*++
+/* NAME
+/*     dict_cidr 3h
+/* SUMMARY
+/*     CIDR-style pattern matching
+/* SYNOPSIS
+/*     #include <cidr_match.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * System library.
+  */
+#include <limits.h>                    /* CHAR_BIT */
+
+ /*
+  * Utility library.
+  */
+#include <myaddrinfo.h>                        /* MAI_V6ADDR_BYTES etc. */
+#include <vstring.h>
+
+ /*
+  * External interface.
+  * 
+  * Address length is protocol dependent. Find out how large our address byte
+  * strings should be.
+  */
+#ifdef HAS_IPV6
+# define CIDR_MATCH_ABYTES     MAI_V6ADDR_BYTES
+#else
+# define CIDR_MATCH_ABYTES     MAI_V4ADDR_BYTES
+#endif
+
+ /*
+  * Each parsed CIDR pattern can be member of a linked list.
+  */
+typedef struct CIDR_MATCH {
+    unsigned char net_bytes[CIDR_MATCH_ABYTES];        /* network portion */
+    unsigned char mask_bytes[CIDR_MATCH_ABYTES];       /* network mask */
+    unsigned char addr_family;         /* AF_XXX */
+    unsigned char addr_byte_count;     /* typically, 4 or 16 */
+    unsigned char addr_bit_count;      /* optimization */
+    unsigned char mask_shift;          /* optimization */
+    struct CIDR_MATCH *next;           /* next entry */
+} CIDR_MATCH;
+
+extern VSTRING *cidr_match_parse(CIDR_MATCH *, char *, VSTRING *);
+extern CIDR_MATCH *cidr_match_execute(CIDR_MATCH *, const char *);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index 6ea4980c1752f1c75ad3c11578c8d96ee92c268e..e2c812e3fb7ad2d3cb8431d79f7b8b688237595e 100644 (file)
@@ -87,7 +87,7 @@ static int dict_default_delete(DICT *dict, const char *unused_key)
 
 /* dict_default_sequence - trap unimplemented operation */
 
-static int dict_default_sequence(DICT *dict, int function,
+static int dict_default_sequence(DICT *dict, int unused_function,
                         const char **unused_key, const char **unused_value)
 {
     msg_fatal("%s table %s: sequence operation is not supported",
index a5f931714b37d84e53b7498aa2be199a1a70c86c..28f075e7802189a96cbde84e42af8cacb6e72b03 100644 (file)
 #include <unistd.h>
 #include <string.h>
 #include <ctype.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
 /* Utility library. */
 
 #include <mymalloc.h>
 #include <stringops.h>
 #include <readlline.h>
 #include <dict.h>
+#include <myaddrinfo.h>
+#include <cidr_match.h>
 #include <dict_cidr.h>
-#include <split_at.h>
 
 /* Application-specific. */
 
  /*
   * Each rule in a CIDR table is parsed and stored in a linked list.
-  * Obviously all this is IPV4 specific and needs to be redone for IPV6.
   */
 typedef struct DICT_CIDR_ENTRY {
-    unsigned long net_bits;            /* network portion of address */
-    unsigned long mask_bits;           /* network mask */
+    CIDR_MATCH cidr_info;              /* must be first */
     char   *value;                     /* lookup result */
-    struct DICT_CIDR_ENTRY *next;      /* next entry */
 } DICT_CIDR_ENTRY;
 
 typedef struct {
@@ -73,26 +68,19 @@ typedef struct {
     DICT_CIDR_ENTRY *head;             /* first entry */
 } DICT_CIDR;
 
-#define BITS_PER_ADDR   32
-
 /* dict_cidr_lookup - CIDR table lookup */
 
 static const char *dict_cidr_lookup(DICT *dict, const char *key)
 {
     DICT_CIDR *dict_cidr = (DICT_CIDR *) dict;
     DICT_CIDR_ENTRY *entry;
-    unsigned long addr;
 
     if (msg_verbose)
-       msg_info("dict_cidr_lookup: %s: %s", dict_cidr->dict.name, key);
-
-    if ((addr = inet_addr(key)) == INADDR_NONE)
-       return (0);
-
-    for (entry = dict_cidr->head; entry; entry = entry->next)
-       if ((addr & entry->mask_bits) == entry->net_bits)
-           return (entry->value);
+       msg_info("dict_cidr_lookup: %s: %s", dict->name, key);
 
+    if ((entry = (DICT_CIDR_ENTRY *)
+        cidr_match_execute(&(dict_cidr->head->cidr_info), key)) != 0)
+       return (entry->value);
     return (0);
 }
 
@@ -105,7 +93,7 @@ static void dict_cidr_close(DICT *dict)
     DICT_CIDR_ENTRY *next;
 
     for (entry = dict_cidr->head; entry; entry = next) {
-       next = entry->next;
+       next = (DICT_CIDR_ENTRY *) entry->cidr_info.next;
        myfree(entry->value);
        myfree((char *) entry);
     }
@@ -114,24 +102,20 @@ static void dict_cidr_close(DICT *dict)
 
 /* dict_cidr_parse_rule - parse CIDR table rule into network, mask and value */
 
-static DICT_CIDR_ENTRY *dict_cidr_parse_rule(const char *mapname, int lineno,
-                                                    char *p)
+static DICT_CIDR_ENTRY *dict_cidr_parse_rule(char *p, VSTRING *why)
 {
     DICT_CIDR_ENTRY *rule;
-    char   *key;
+    char   *pattern;
     char   *value;
-    char   *mask;
-    int     mask_shift;
-    unsigned long net_bits;
-    unsigned long mask_bits;
-    struct in_addr net_addr;
+    CIDR_MATCH cidr_info;
+    MAI_HOSTADDR_STR hostaddr;
 
     /*
      * Split the rule into key and value. We already eliminated leading
      * whitespace, comments, empty lines or lines with whitespace only. This
      * means a null key can't happen but we will handle this anyway.
      */
-    key = p;
+    pattern = p;
     while (*p && !ISSPACE(*p))                 /* Skip over key */
        p++;
     if (*p)                                    /* Terminate key */
@@ -140,66 +124,35 @@ static DICT_CIDR_ENTRY *dict_cidr_parse_rule(const char *mapname, int lineno,
        p++;
     value = p;
     trimblanks(value, 0)[0] = 0;               /* Trim trailing blanks */
-    if (*key == 0) {
-       msg_warn("cidr map %s, line %d: no address pattern: skipping this rule",
-                mapname, lineno);
+    if (*pattern == 0) {
+       vstring_sprintf(why, "no address pattern");
        return (0);
     }
     if (*value == 0) {
-       msg_warn("cidr map %s, line %d: no lookup result: skipping this rule",
-                mapname, lineno);
+       vstring_sprintf(why, "no lookup result");
        return (0);
     }
 
     /*
-     * Parse the key into network and mask, and destroy the key. Treat a bare
-     * network address as /32.
-     * 
-     * We need explicit code for /0. The result of << is undefined when the
-     * shift is greater or equal to the number of bits in the shifted
-     * operand.
+     * Parse the pattern, destroying it in the process.
      */
-    if ((mask = split_at(key, '/')) != 0) {
-       if (!alldig(mask) || (mask_shift = atoi(mask)) > BITS_PER_ADDR
-           || (net_bits = inet_addr(key)) == INADDR_NONE) {
-           msg_warn("cidr map %s, line %d: bad net/mask pattern: \"%s/%s\": "
-                    "skipping this rule", mapname, lineno, key, mask);
-           return (0);
-       }
-       mask_bits = mask_shift > 0 ?
-           htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift)) : 0;
-       if (net_bits & ~mask_bits) {
-           net_addr.s_addr = (net_bits & mask_bits);
-           msg_warn("cidr map %s, line %d: net/mask pattern \"%s/%s\" with "
-                    "non-null host portion: skipping this rule",
-                    mapname, lineno, key, mask);
-           msg_warn("specify \"%s/%d\" if this is really what you want",
-                    inet_ntoa(net_addr), mask_shift);
-           return (0);
-       }
-    } else {
-       if ((net_bits = inet_addr(key)) == INADDR_NONE) {
-           msg_warn("cidr map %s, line %d: bad address pattern: \"%s\": "
-                    "skipping this rule", mapname, lineno, key);
-           return (0);
-       }
-       mask_shift = 32;
-       mask_bits = htonl(0xffffffff);
-    }
+    if (cidr_match_parse(&cidr_info, pattern, why) != 0)
+       return (0);
 
     /*
      * Bundle up the result.
      */
     rule = (DICT_CIDR_ENTRY *) mymalloc(sizeof(DICT_CIDR_ENTRY));
-    rule->net_bits = net_bits;
-    rule->mask_bits = mask_bits;
+    rule->cidr_info = cidr_info;
     rule->value = mystrdup(value);
-    rule->next = 0;
-
-    if (msg_verbose)
-       msg_info("dict_cidr_open: %s: %lu/%d %s",
-                mapname, rule->net_bits, mask_shift, rule->value);
 
+    if (msg_verbose) {
+       if (inet_ntop(cidr_info.addr_family, cidr_info.net_bytes,
+                     hostaddr.buf, sizeof(hostaddr.buf)) == 0)
+           msg_fatal("inet_ntop: %m");
+       msg_info("dict_cidr_open: add %s/%d %s",
+                hostaddr.buf, cidr_info.mask_shift, rule->value);
+    }
     return (rule);
 }
 
@@ -210,6 +163,7 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
     DICT_CIDR *dict_cidr;
     VSTREAM *map_fp;
     VSTRING *line_buffer = vstring_alloc(100);
+    VSTRING *why = vstring_alloc(100);
     DICT_CIDR_ENTRY *rule;
     DICT_CIDR_ENTRY *last_rule = 0;
     int     lineno = 0;
@@ -236,13 +190,16 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
        msg_fatal("open %s: %m", mapname);
 
     while (readlline(line_buffer, map_fp, &lineno)) {
-       rule = dict_cidr_parse_rule(mapname, lineno, vstring_str(line_buffer));
-       if (rule == 0)
+       rule = dict_cidr_parse_rule(vstring_str(line_buffer), why);
+       if (rule == 0) {
+           msg_warn("cidr map %s, line %d: %s: skipping this rule",
+                    mapname, lineno, vstring_str(why));
            continue;
+       }
        if (last_rule == 0)
            dict_cidr->head = rule;
        else
-           last_rule->next = rule;
+           last_rule->cidr_info.next = &(rule->cidr_info);
        last_rule = rule;
     }
 
@@ -252,6 +209,7 @@ DICT   *dict_cidr_open(const char *mapname, int open_flags, int dict_flags)
     if (vstream_fclose(map_fp))
        msg_fatal("cidr map %s: read error: %m", mapname);
     vstring_free(line_buffer);
+    vstring_free(why);
 
     return (DICT_DEBUG (&dict_cidr->dict));
 }
index bfcb0806e427ad31680b0d1c603dd956dbddac59..1798a60c9deb3209f2cc7241bd87858f9d3f73b8 100644 (file)
@@ -5,3 +5,7 @@ get 172.16.8.1
 get 172.16.17.1
 get 172.17.1.1
 get 172.17.1.2
+get 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+get 2001:240:5c7:0:2d0:b7ff:febe:ca9f
+get 1.1.1.1
+get 1:1:1:1:1:1:1:1
index a655ac4cf72ced3f48b6bab0020cfd2967f5b52a..518e17149c83ceb28acfab157766b5ea26074052 100644 (file)
@@ -7,3 +7,12 @@
 172.999.0.0/21         whatever
 172.16.1.999           whatever
 172.16.1.4
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7 match 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+2001:240:5c7::/64      match netblock 2001:240:5c7::/64
+1.0.0.0/0              match 0.0.0.0/0
+0.0.0.0/0              match 0.0.0.0/0
+1::/0                  match ::/0
+::/0                   match ::/0
+[1234                  foo
+[1234]junk             bar
+172.16.1.3/3x          whatever
index a1fe357b86b1bebae6e3c6d23cd76f3a7080d3f0..42d166e1a109a7f853c00b4b7ddd87171338e98e 100644 (file)
@@ -1,13 +1,21 @@
-./dict_open: warning: cidr map dict_cidr.map, line 5: net/mask pattern "172.16.1.3/21" with non-null host portion: skipping this rule
-./dict_open: warning: specify "172.16.0.0/21" if this is really what you want
+./dict_open: warning: cidr map dict_cidr.map, line 5: non-null host address bits in "172.16.1.3/21", perhaps you should use "172.16.0.0/21" instead: skipping this rule
 ./dict_open: warning: cidr map dict_cidr.map, line 6: bad net/mask pattern: "172.16.1.3/33": skipping this rule
 ./dict_open: warning: cidr map dict_cidr.map, line 7: bad net/mask pattern: "172.999.0.0/21": skipping this rule
 ./dict_open: warning: cidr map dict_cidr.map, line 8: bad address pattern: "172.16.1.999": skipping this rule
 ./dict_open: warning: cidr map dict_cidr.map, line 9: no lookup result: skipping this rule
+./dict_open: warning: cidr map dict_cidr.map, line 12: non-null host address bits in "1.0.0.0/0", perhaps you should use "0.0.0.0/0" instead: skipping this rule
+./dict_open: warning: cidr map dict_cidr.map, line 14: non-null host address bits in "1::/0", perhaps you should use "::/0" instead: skipping this rule
+./dict_open: warning: cidr map dict_cidr.map, line 16: missing ']' character after "[1234": skipping this rule
+./dict_open: warning: cidr map dict_cidr.map, line 17: garbage after "[1234]": skipping this rule
+./dict_open: warning: cidr map dict_cidr.map, line 18: bad net/mask pattern: "172.16.1.3/3x": skipping this rule
 172.16.0.0=554 match bad netblock 172.16.0.0/21
 172.16.0.1=554 match bad netblock 172.16.0.0/21
 172.16.7.255=554 match bad netblock 172.16.0.0/21
 172.16.8.1=554 match bad netblock 172.16.8.0/21
 172.16.17.1=554 match bad netblock 172.16.0.0/16
 172.17.1.1=554 match bad naked address
-172.17.1.2: not found
+172.17.1.2=match 0.0.0.0/0
+2001:240:5c7:0:2d0:b7ff:fe88:2ca7=match 2001:240:5c7:0:2d0:b7ff:fe88:2ca7
+2001:240:5c7:0:2d0:b7ff:febe:ca9f=match netblock 2001:240:5c7::/64
+1.1.1.1=match 0.0.0.0/0
+1:1:1:1:1:1:1:1=match ::/0
index ea0342dd8b165b1fd42e502e63f2c1701636b0c0..9ab82535e53bbe59c7abc8038090ec7bea9b7724 100644 (file)
@@ -100,7 +100,7 @@ ABCDEFGHIJKLMNOPQRSTUVWXYZ" SPACE_TAB;
 #include <vstream.h>
 #include <msg_vstream.h>
 
-main(int argc, char **argv)
+int     main(int argc, char **argv)
 {
     msg_vstream_init(argv[0], VSTREAM_ERR);
     if (argc != 2)
index df1bfc0793f59651f20c210772d9729a47b8f5b3..f3118b491d300161c1da2aa1dffe159af58c0787 100644 (file)
@@ -18,6 +18,7 @@
 /*     BSD TCP/IP network software.
 /*
 /*     find_inet_addr() translates a symbolic or numerical hostname.
+/*     This function is deprecated. Use hostname_to_hostaddr() instead.
 /*
 /*     find_inet_port() translates a symbolic or numerical port name.
 /* BUGS
index 662fdddc8aebd2007a94fd9a5731c0b6dae8cf1b..5c752b4990a31f5a24e22a99036477a4eb129b41 100644 (file)
@@ -126,7 +126,7 @@ static int read_buf(VSTREAM *fp, VSTRING *buf)
     return (len);
 }
 
-main(int unused_argc, char **unused_argv)
+int     main(int unused_argc, char **unused_argv)
 {
     VSTRING *raw = vstring_alloc(BUFLEN);
     VSTRING *hex = vstring_alloc(100);
index fd7593101f2c58e55a796e38d09ddd90bcdcc4da..bfcad8c09a37c0d9c3977a34222f3b4f1e5bf001 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <host_port.h>
 /*
-/*     const char *host_port(string, host, port, def_service)
+/*     const char *host_port(string, host, def_host, port, def_service)
 /*     char    *string;
 /*     char    **host;
+/*     char    *def_host;
 /*     char    **port;
 /*     char    *def_service;
 /* DESCRIPTION
 /*     name or address, and the service name or port number.
 /*     The input string is modified.
 /*
-/*     The following input formats are understood:
+/*     The following input formats are understood (null means
+/*     a null pointer argument):
 /*
-/*     [host]:port, [host]:, [host].
+/*     When def_service is not null, and def_host is null:
 /*
-/*     host:port, host:, host.
+/*             [host]:port, [host]:, [host]
+/*
+/*             host:port, host:, host
+/*
+/*     When def_host is not null, and def_service is null:
+/*
+/*             :port, port
+/*
+/*     Other combinations of def_service and def_host are
+/*     not supported and produce undefined results.
 /* DIAGNOSTICS
 /*     The result is a null pointer in case of success.
 /*     In case of problems the result is a string pointer with
 /*     the problem type.
+/* CLIENT EXAMPLE
+/* .ad
+/* .fi
+/*     Typical client usage allows the user to omit the service port,
+/*     in which case the client connects to a pre-determined default
+/*     port:
+/* .nf
+/* .na
+/*
+/*     buf = mystrdup(endpoint);
+/*     if ((parse_error = host_port(buf, &host, NULL, &port, defport)) != 0)
+/*         msg_fatal("%s in \"%s\"", parse_error, endpoint);
+/*     if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
+/*         msg_fatal("%s: %s", endpoint, MAI_STRERROR(aierr));
+/*     myfree(buf);
+/* SERVER EXAMPLE
+/* .ad
+/* .fi
+/*     Typical server usage allows the user to omit the host, meaning
+/*     listen on all available network addresses:
+/* .nf
+/* .na
+/*
+/*     buf = mystrdup(endpoint);
+/*     if ((parse_error = host_port(buf, &host, "", &port, NULL)) != 0)
+/*         msg_fatal("%s in \"%s\"", parse_error, endpoint);
+/*     if (*host == 0)
+/*         host = 0;
+/*     if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res)) != 0)
+/*         msg_fatal("%s: %s", endpoint, MAI_STRERROR(aierr));
+/*     myfree(buf);
 /* LICENSE
 /* .ad
 /* .fi
@@ -55,8 +97,8 @@
 
 /* host_port - parse string into host and port, destroy string */
 
-const char *host_port(char *buf, char **host, char **port,
-                             char *def_service)
+const char *host_port(char *buf, char **host, char *def_host,
+                             char **port, char *def_service)
 {
     char   *cp = buf;
 
@@ -69,43 +111,34 @@ const char *host_port(char *buf, char **host, char **port,
            return ("missing \"]\"");
        if (*cp && *cp++ != ':')
            return ("garbage after \"]\"");
-       if (*cp == 0)
-           *port = def_service;
-       else
-           *port = cp;
-
-       /*
-        * [host:port], [host:]. These conflict with IPV6 address literals.
-        */
-#if 1
-       if (strchr(*host, ':')) {
-           msg_warn("old-style address form: [%s]", *host);
-           msg_warn("support for [host:port] forms will go away");
-           msg_warn("specify [host]:port instead");
-           return (host_port(buf + 1, host, port, def_service));
-       }
-#endif
+       *port = *cp ? cp : def_service;
     }
 
     /*
-     * host:port, host:, host.
+     * host:port, host:, host, :port, port.
      */
     else {
-       *host = cp;
-       if ((cp = split_at_right(cp, ':')) == 0 || *cp == 0)
-           *port = def_service;
-       else
-           *port = cp;
+       if ((cp = split_at_right(buf, ':')) != 0) {
+           *host = *buf ? buf : def_host;
+           *port = *cp ? cp : def_service;
+       } else {
+           *host = def_host ? def_host : (*buf ? buf : 0);
+           *port = def_service ? def_service : (*buf ? buf : 0);
+       }
     }
+    if (*host == 0)
+       return ("missing host information");
+    if (*port == 0)
+       return ("missing service information");
 
     /*
      * Final sanity checks. We're still sloppy, allowing bare numerical
      * network addresses instead of requiring proper [ipaddress] forms.
      */
-    if (!valid_hostname(*host, DONT_GRIPE)
+    if (*host != def_host && !valid_hostname(*host, DONT_GRIPE)
        && !valid_hostaddr(*host, DONT_GRIPE))
        return ("valid hostname or network address required");
-    if (ISDIGIT(**port) && !alldig(*port))
+    if (*port != def_service && ISDIGIT(**port) && !alldig(*port))
        return ("garbage after numerical service");
     return (0);
 }
@@ -129,8 +162,10 @@ int     main(int unused_argc, char **unused_argv)
     while (vstring_fgets_nonl(in_buf, VSTREAM_IN)) {
        vstream_printf(">> %s\n", STR(in_buf));
        vstream_fflush(VSTREAM_OUT);
+       if (*STR(in_buf) == '#')
+           continue;
        vstring_strcpy(parse_buf, STR(in_buf));
-       if ((err = host_port(STR(parse_buf), &host, &port, "default-service")) != 0) {
+       if ((err = host_port(STR(parse_buf), &host, (char *) 0, &port, "default-service")) != 0) {
            msg_warn("%s in %s", err, STR(in_buf));
        } else {
            vstream_printf("host %s port %s\n", host, port);
index 629943a9cae1eedeb1b1eccfb13803b60c767e6f..b690a52280d2d063c78f20b94c329d6ebac5ac15 100644 (file)
@@ -13,7 +13,7 @@
 
  /* External interface. */
 
-extern const char *host_port(char *, char **, char **, char *);
+extern const char *host_port(char *, char **, char *, char **, char *);
 
 /* LICENSE
 /* .ad
index 34c8343837fba5391281df1cfe168586e9854ddf..324892fe0e9192c867e76d3b1cf9276c623b9900 100644 (file)
@@ -4,8 +4,8 @@ hhh
 [hhh]:ppp
 [hhh]:
 [hhh]
-[hhh:ppp]
-[hhh:]
+#[hhh:ppp]
+#[hhh:]
 hhh:1pp
 [hh.]
 hh.
index fbf672170b2cd4e9560453734c059831ce60a959..e1057c6223bc9a7b28f81b1225deebecc76478cd 100644 (file)
@@ -10,16 +10,8 @@ host hhh port ppp
 host hhh port default-service
 >> [hhh]
 host hhh port default-service
->> [hhh:ppp]
-unknown: warning: old-style address form: [hhh:ppp]
-unknown: warning: support for [host:port] forms will go away
-unknown: warning: specify [host]:port instead
-host hhh port ppp
->> [hhh:]
-unknown: warning: old-style address form: [hhh:]
-unknown: warning: support for [host:port] forms will go away
-unknown: warning: specify [host]:port instead
-host hhh port default-service
+>> #[hhh:ppp]
+>> #[hhh:]
 >> hhh:1pp
 unknown: warning: garbage after numerical service in hhh:1pp
 >> [hh.]
index b06689f1f3006ca4775598e3b97e79b0a8849642..3331ffee08a520fdbd7b480b67eaa25ee7538324 100644 (file)
@@ -12,7 +12,8 @@
 /* DESCRIPTION
 /*     inet_addr_host() determines all interface addresses of the
 /*     named host. The host may be specified as a symbolic name,
-/*     or as a numerical address. Address results are appended to
+/*     or as a numerical address. An empty host expands as the
+/*     wild-card address.  Address results are appended to
 /*     the specified address list. The result value is the number
 /*     of addresses appended to the list.
 /* DIAGNOSTICS
 #include <sys_defs.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
+#include <sys/socket.h>
 #include <netdb.h>
-
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
 
 /* Utility library. */
 
+#include <mymalloc.h>
 #include <inet_addr_list.h>
 #include <inet_addr_host.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <inet_proto.h>
+#include <msg.h>
 
 /* inet_addr_host - look up address list for host */
 
 int     inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
 {
-    struct hostent *hp;
-    struct in_addr addr;
+    const char *myname = "inet_addr_host";
+    int     sock;
+    struct addrinfo *res0;
+    struct addrinfo *res;
+    int     aierr;
+    int     hostnamelen;
+    const char *hname;
+    const char *serv;
     int     initial_count = addr_list->used;
-
-    if ((addr.s_addr = inet_addr(hostname)) != INADDR_NONE) {
-       inet_addr_list_append(addr_list, &addr);
+    INET_PROTO_INFO *proto_info;
+
+    /*
+     * The use of square brackets around an IPv6 addresses is required, even
+     * though we don't enforce it as it'd make the code unnecessarily
+     * complicated.
+     * 
+     * XXX AIX 5.1 getaddrinfo() does not allow "0" as service, regardless of
+     * whether or not a host is specified.
+     */
+    if (*hostname == 0) {
+       hname = 0;
+       serv = "1";
+    } else if (*hostname == '['
+              && hostname[(hostnamelen = strlen(hostname)) - 1] == ']') {
+       hname = mystrndup(hostname + 1, hostnamelen - 2);
+       serv = 0;
     } else {
-       if ((hp = gethostbyname(hostname)) != 0)
-           while (hp->h_addr_list[0])
-               inet_addr_list_append(addr_list,
-                                   (struct in_addr *) * hp->h_addr_list++);
+       hname = hostname;
+       serv = 0;
     }
+
+    proto_info = inet_proto_info();
+    if ((aierr = hostname_to_sockaddr(hname, serv, SOCK_STREAM, &res0)) == 0) {
+       for (res = res0; res; res = res->ai_next) {
+
+           /*
+            * Safety net.
+            */
+           if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+               msg_info("%s: skipping address family %d for host \"%s\"",
+                        myname, res->ai_family, hostname);
+               continue;
+           }
+
+           /*
+            * On Linux systems it is not unusual for user-land to be out of
+            * sync with kernel-land. When this is the case we try to be
+            * helpful and filter out address families that the library
+            * claims to understand but that are not supported by the kernel.
+            */
+           if ((sock = socket(res->ai_family, SOCK_STREAM, 0)) < 0) {
+               msg_warn("%s: skipping address family %d: %m",
+                        myname, res->ai_family);
+               continue;
+           }
+           if (close(sock))
+               msg_warn("%s: close socket: %m", myname);
+
+           inet_addr_list_append(addr_list, res->ai_addr);
+       }
+       freeaddrinfo(res0);
+    }
+    if (hname && hname != hostname)
+       myfree((char *) hname);
+
     return (addr_list->used - initial_count);
 }
 
@@ -73,27 +132,37 @@ int     inet_addr_host(INET_ADDR_LIST *addr_list, const char *hostname)
 #include <msg.h>
 #include <vstream.h>
 #include <msg_vstream.h>
+#include <sock_addr.h>
 
 int     main(int argc, char **argv)
 {
-    INET_ADDR_LIST addr_list;
-    int     i;
+    INET_ADDR_LIST list;
+    struct sockaddr_storage *sa;
+    MAI_HOSTADDR_STR hostaddr;
+    INET_PROTO_INFO *proto_info;
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
 
-    if (argc < 2)
-       msg_fatal("usage: %s hostname...", argv[0]);
+    if (argc < 3)
+       msg_fatal("usage: %s protocols hostname...", argv[0]);
+
+    proto_info = inet_proto_init(argv[0], *++argv);
+
+    inet_addr_list_init(&list);
 
     while (--argc && *++argv) {
-       inet_addr_list_init(&addr_list);
-       if (inet_addr_host(&addr_list, *argv) == 0)
+       if (inet_addr_host(&list, *argv) == 0)
            msg_fatal("not found: %s", *argv);
 
-       for (i = 0; i < addr_list.used; i++)
-           vstream_printf("%s\n", inet_ntoa(addr_list.addrs[i]));
+       for (sa = list.addrs; sa < list.addrs + list.used; sa++) {
+           SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
+                                &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+           vstream_printf("%s\n", hostaddr.buf);
+       }
        vstream_fflush(VSTREAM_OUT);
     }
-    inet_addr_list_free(&addr_list);
+    inet_addr_list_free(&list);
+    return (0);
 }
 
 #endif
index 49ae833d568698c92ccd8dd24e14ab7e6aa58f4d..f178e01341b4a3c5a5516627770e4a62baca2ad0 100644 (file)
@@ -11,7 +11,7 @@
 /*
 /*     void    inet_addr_list_append(list,addr)
 /*     INET_ADDR_LIST *list;
-/*     struct in_addr *addr;
+/*     struct sockaddr *addr;
 /*
 /*     void    inet_addr_list_uniq(list)
 /*     INET_ADDR_LIST *list;
 /* System library. */
 
 #include <sys_defs.h>
+#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 #include <stdlib.h>
+#include <netdb.h>
 
 /* Utility library. */
 
 #include <msg.h>
 #include <mymalloc.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
 #include <inet_addr_list.h>
 
 /* inet_addr_list_init - initialize internet address list */
@@ -66,37 +70,43 @@ void    inet_addr_list_init(INET_ADDR_LIST *list)
     list->used = 0;
     list->size = 0;
     init_size = 2;
-    list->addrs = (struct in_addr *) mymalloc(sizeof(*list->addrs) * init_size);
+    list->addrs = (struct sockaddr_storage *)
+       mymalloc(sizeof(*list->addrs) * init_size);
     list->size = init_size;
 }
 
 /* inet_addr_list_append - append address to internet address list */
 
-void    inet_addr_list_append(INET_ADDR_LIST *list, struct in_addr * addr)
+void    inet_addr_list_append(INET_ADDR_LIST *list,
+                                     struct sockaddr * addr)
 {
     char   *myname = "inet_addr_list_append";
+    MAI_HOSTADDR_STR hostaddr;
     int     new_size;
 
-    if (msg_verbose > 1)
-       msg_info("%s: %s", myname, inet_ntoa(*addr));
-
+    if (msg_verbose > 1) {
+       SOCKADDR_TO_HOSTADDR(addr, SOCK_ADDR_LEN(addr),
+                            &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+       msg_info("%s: %s", myname, hostaddr.buf);
+    }
     if (list->used >= list->size) {
        new_size = list->size * 2;
-       list->addrs = (struct in_addr *)
+       list->addrs = (struct sockaddr_storage *)
            myrealloc((char *) list->addrs, sizeof(*list->addrs) * new_size);
        list->size = new_size;
     }
-    list->addrs[list->used++] = *addr;
+    memcpy(list->addrs + list->used++, addr, SOCK_ADDR_LEN(addr));
 }
 
 /* inet_addr_list_comp - compare addresses */
 
 static int inet_addr_list_comp(const void *a, const void *b)
 {
-    const struct in_addr *a_addr = (const struct in_addr *) a;
-    const struct in_addr *b_addr = (const struct in_addr *) b;
 
-    return (a_addr->s_addr - b_addr->s_addr);
+    /*
+     * In case (struct *) != (void *).
+     */
+    return (sock_addr_cmp_addr(SOCK_ADDR_PTR(a), SOCK_ADDR_PTR(b)));
 }
 
 /* inet_addr_list_uniq - weed out duplicates */
@@ -135,6 +145,7 @@ void    inet_addr_list_free(INET_ADDR_LIST *list)
 }
 
 #ifdef TEST
+#include <inet_proto.h>
 
  /*
   * Duplicate elimination needs to be tested.
@@ -143,16 +154,22 @@ void    inet_addr_list_free(INET_ADDR_LIST *list)
 
 static void inet_addr_list_print(INET_ADDR_LIST *list)
 {
-    int     n;
+    MAI_HOSTADDR_STR hostaddr;
+    struct sockaddr_storage *sa;
 
-    for (n = 0; n < list->used; n++)
-       msg_info("%s", inet_ntoa(list->addrs[n]));
+    for (sa = list->addrs; sa < list->addrs + list->used; sa++) {
+       SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
+                            &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+       msg_info("%s", hostaddr.buf);
+    }
 }
 
 int     main(int argc, char **argv)
 {
     INET_ADDR_LIST list;
+    INET_PROTO_INFO *proto_info;
 
+    proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
     inet_addr_list_init(&list);
     while (--argc && *++argv)
        if (inet_addr_host(&list, *argv) == 0)
index 372b3ccb76adc7fc15915a772cad9335bcf5989b..8a109c155a38c2d0f3276b301e1c5f57c4eef823 100644 (file)
@@ -12,9 +12,9 @@
 /* .nf
 
  /*
-  * System library.
+  * Utility library.
   */
-#include <netinet/in.h>
+#include <myaddrinfo.h>                        /* generic name/addr API */
 
  /*
   * External interface.
 typedef struct INET_ADDR_LIST {
     int     used;                      /* nr of elements in use */
     int     size;                      /* actual list size */
-    struct in_addr *addrs;             /* payload */
+    struct sockaddr_storage *addrs;    /* payload */
 } INET_ADDR_LIST;
 
 extern void inet_addr_list_init(INET_ADDR_LIST *);
 extern void inet_addr_list_free(INET_ADDR_LIST *);
 extern void inet_addr_list_uniq(INET_ADDR_LIST *);
-extern void inet_addr_list_append(INET_ADDR_LIST *, struct in_addr *);
+extern void inet_addr_list_append(INET_ADDR_LIST *, struct sockaddr *);
 
 /* LICENSE
 /* .ad
index 0a3cb22a8a8960289c2ba0ed7d70269b306acb39..6ebe3eb815105e4c8855cb57f7bee4078668ac71 100644 (file)
@@ -6,9 +6,10 @@
 /* SYNOPSIS
 /*     #include <inet_addr_local.h>
 /*
-/*     int     inet_addr_local(addr_list, mask_list)
+/*     int     inet_addr_local(addr_list, mask_list, addr_family_list)
 /*     INET_ADDR_LIST *addr_list;
 /*     INET_ADDR_LIST *mask_list;
+/*     unsigned *addr_family;
 /* DESCRIPTION
 /*     inet_addr_local() determines all active IP interface addresses
 /*     of the local system. Any address found is appended to the
@@ -17,6 +18,8 @@
 /*
 /*     The mask_list is either a null pointer, or it is a list that
 /*     receives the netmasks of the interface addresses that were found.
+/*
+/*     The addr_family_list specifies one or more of AF_INET or AF_INET6.
 /* DIAGNOSTICS
 /*     Fatal errors: out of memory.
 /* SEE ALSO
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Dean C. Strik
+/*     Department ICT
+/*     Eindhoven University of Technology
+/*     P.O. Box 513
+/*     5600 MB  Eindhoven, Netherlands
+/*     E-mail: <dean@ipnet6.org>
 /*--*/
 
 /* System library. */
 #endif
 #include <errno.h>
 #include <string.h>
+#ifdef HAS_IPV6                                /* Linux only? */
+#include <netdb.h>
+#include <stdio.h>
+#endif
+#ifdef HAVE_GETIFADDRS
+#include <ifaddrs.h>
+#endif
 
 /* Utility library. */
 
 #include <vstring.h>
 #include <inet_addr_list.h>
 #include <inet_addr_local.h>
+#include <myaddrinfo.h>
+#include <sock_addr.h>
+#include <mask_addr.h>
+#include <hex_code.h>
 
  /*
-  * Support for variable-length addresses.
+  * Postfix needs its own interface address information to determine whether
+  * or not it is an MX host for some destination; without this information,
+  * mail would loop between MX hosts. Postfix also needs its interface
+  * addresses to figure out whether or not it is final destination for
+  * addresses of the form username@[ipaddress].
+  * 
+  * Postfix needs its own interface netmask information when no explicit
+  * mynetworks setting is given in main.cf, and "mynetworks_style = subnet".
+  * The mynetworks parameter controls, among others, what mail clients are
+  * allowed to relay mail through Postfix.
+  * 
+  * Different systems have different ways to find out this information. We will
+  * therefore use OS dependent methods. An overview:
+  * 
+  * - Use getifaddrs() when available.  This supports both IPv4/IPv6 addresses.
+  * The implementation however is not present in all major operating systems.
+  * 
+  * - Use SIOCGLIFCONF when available. This supports both IPv4/IPv6 addresses.
+  * With SIOCGLIFNETMASK we can obtain the netmask for either address family.
+  * Again, this is not present in all major operating systems.
+  * 
+  * - On Linux, get IPv4 interface information with SIOCGIFCONF, and read IPv6
+  * address/prefix information from a file in the /proc filesystem. Linux
+  * does not return IPv6 addresses with SIOCGIFCONF.
+  * 
+  * - On other systems we expect SIOCGIFCONF to return IPv6 addresses. Since
+  * SIOCGIFNETMASK does not work reliably for IPv6 addresses, we always set
+  * the prefix length to /128 (host), and expect the user to configure a more
+  * appropriate mynetworks setting if needed.
+  * 
+  * XXX: Each lookup method is implemented by its own function, so we duplicate
+  * some code. In this case, I think this is better than really drowning in
+  * the #ifdefs...
+  * 
+  * -- Dean Strik (dcs)
   */
-#ifdef _SIZEOF_ADDR_IFREQ
-#define NEXT_INTERFACE(ifr) ((struct ifreq *) \
-       ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)))
-#define IFREQ_SIZE(ifr)        _SIZEOF_ADDR_IFREQ(*ifr)
-#else
+
+/* ial_socket - make socket for ioctl() operations */
+
+static int ial_socket(int af)
+{
+    char   *myname = "inet_addr_local[socket]";
+    int     sock;
+
+    /*
+     * The host may not be actually configured with IPv6. When IPv6 support
+     * is not actually in the kernel, don't consider failure to create an
+     * IPv6 socket as fatal. This could be tuned better though. For other
+     * families, the error is fatal.
+     * 
+     * XXX Now that Postfix controls protocol support centrally with the
+     * inet_proto(3) module, this workaround should no longer be needed.
+     */
+    if ((sock = socket(af, SOCK_DGRAM, 0)) < 0) {
+#ifdef HAS_IPV6
+       if (af == AF_INET6) {
+           if (msg_verbose)
+               msg_warn("%s: socket: %m", myname);
+           return (-1);
+       }
+#endif
+       msg_fatal("%s: socket: %m", myname);
+    }
+    return (sock);
+}
+
+#ifdef HAVE_GETIFADDRS
+
+/*
+ * The getifaddrs(3) function, introduced by BSD/OS, provides a
+ * platform-independent way of requesting interface addresses,
+ * including IPv6 addresses. The implementation however is not
+ * present in all major operating systems.
+ */
+
+/* ial_getifaddrs - determine IP addresses using getifaddrs(3) */
+
+static int ial_getifaddrs(INET_ADDR_LIST *addr_list,
+                                 INET_ADDR_LIST *mask_list,
+                                 int af)
+{
+    char   *myname = "inet_addr_local[getifaddrs]";
+    struct ifaddrs *ifap, *ifa;
+    struct sockaddr *sa, *sam;
+
+    if (getifaddrs(&ifap) < 0)
+       msg_fatal("%s: getifaddrs: %m", myname);
+
+    /*
+     * Get the address of each IP network interface. According to BIND we
+     * must include interfaces that are down because the machine may still
+     * receive packets for that address (yes, via some other interface).
+     * Having no way to verify this claim on every machine, I will give them
+     * the benefit of the doubt.
+     * 
+     * FIX 200501: The IPv6 patch did not report NetBSD loopback interfaces;
+     * fixed by replacing IFF_RUNNING by IFF_UP.
+     * 
+     * FIX 200501: The IPV6 patch did not skip wild-card interface addresses
+     * (tested on FreeBSD).
+     */
+    for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+       if (!(ifa->ifa_flags & IFF_UP) || ifa->ifa_addr == 0)
+           continue;
+       sa = ifa->ifa_addr;
+       sam = ifa->ifa_netmask;
+       if (af != AF_UNSPEC && sa->sa_family != af)
+           continue;
+       switch (sa->sa_family) {
+       case AF_INET:
+           if (SOCK_ADDR_IN_ADDR(sa).s_addr == INADDR_ANY)
+               continue;
+           break;
+#ifdef HAS_IPV6
+       case AF_INET6:
+           if (IN6_IS_ADDR_UNSPECIFIED(&SOCK_ADDR_IN6_ADDR(sa)))
+               continue;
+           break;
+#endif
+       default:
+           continue;
+       }
+
+       inet_addr_list_append(addr_list, sa);
+       if (mask_list != 0) {
+
+           /*
+            * Unfortunately, sa_len/sa_family may be broken in the netmask
+            * sockaddr structure. We must fix this manually to have correct
+            * addresses.   --dcs
+            */
 #ifdef HAS_SA_LEN
-#define NEXT_INTERFACE(ifr) ((struct ifreq *) \
+           sam->sa_len = sa->sa_family == AF_INET6 ?
+               sizeof(struct sockaddr_in6) :
+               sizeof(struct sockaddr_in);
+#endif
+           sam->sa_family = sa->sa_family;
+           inet_addr_list_append(mask_list, sam);
+       }
+    }
+    freeifaddrs(ifap);
+    return (0);
+}
+
+#endif                                 /* HAVE_GETIFADDRS */
+
+#ifdef HAS_SIOCGLIF
+
+/*
+ * The SIOCLIF* ioctls are the successors of SIOCGIF* on the Solaris
+ * and HP/UX operating systems. The data is stored in sockaddr_storage
+ * structure. Both IPv4 and IPv6 addresses are returned though these
+ * calls.
+ */
+#define NEXT_INTERFACE(lifr)   (lifr + 1)
+#define LIFREQ_SIZE(lifr)      sizeof(lifr[0])
+
+/* ial_siocglif - determine IP addresses using ioctl(SIOCGLIF*) */
+
+static int ial_siocglif(INET_ADDR_LIST *addr_list,
+                               INET_ADDR_LIST *mask_list,
+                               int af)
+{
+    char   *myname = "inet_addr_local[siocglif]";
+    struct lifconf lifc;
+    struct lifreq *lifr;
+    struct lifreq *lifr_mask;
+    struct lifreq *the_end;
+    struct sockaddr *sa;
+    int     sock;
+    VSTRING *buf;
+
+    /*
+     * See also comments in ial_siocgif()
+     */
+    if (af != AF_INET && af != AF_INET6)
+       msg_fatal("%s: address family was %d, must be AF_INET (%d) or "
+                 "AF_INET6 (%d)", myname, af, AF_INET, AF_INET6);
+    sock = ial_socket(af);
+    if (sock < 0)
+       return (0);
+    buf = vstring_alloc(1024);
+    for (;;) {
+       memset(&lifc, 0, sizeof(lifc));
+       lifc.lifc_family = AF_UNSPEC;           /* XXX Why??? */
+       lifc.lifc_len = vstring_avail(buf);
+       lifc.lifc_buf = vstring_str(buf);
+       if (ioctl(sock, SIOCGLIFCONF, (char *) &lifc) < 0) {
+           if (errno != EINVAL)
+               msg_fatal("%s: ioctl SIOCGLIFCONF: %m", myname);
+       } else if (lifc.lifc_len < vstring_avail(buf) / 2)
+           break;
+       VSTRING_SPACE(buf, vstring_avail(buf) * 2);
+    }
+
+    the_end = (struct lifreq *) (lifc.lifc_buf + lifc.lifc_len);
+    for (lifr = lifc.lifc_req; lifr < the_end;) {
+       sa = (struct sockaddr *) & lifr->lifr_addr;
+       if (sa->sa_family != af) {
+           lifr = NEXT_INTERFACE(lifr);
+           continue;
+       }
+       if (af == AF_INET) {
+           if (SOCK_ADDR_IN_ADDR(sa).s_addr == INADDR_ANY) {
+               lifr = NEXT_INTERFACE(lifr);
+               continue;
+           }
+#ifdef HAS_IPV6
+       } else if (af == AF_INET6) {
+           if (IN6_IS_ADDR_UNSPECIFIED(&SOCK_ADDR_IN6_ADDR(sa))) {
+               lifr = NEXT_INTERFACE(lifr);
+               continue;
+           }
+       }
+#endif
+       inet_addr_list_append(addr_list, sa);
+       if (mask_list) {
+           lifr_mask = (struct lifreq *) mymalloc(sizeof(struct lifreq));
+           memcpy((char *) lifr_mask, (char *) lifr, sizeof(struct lifreq));
+           if (ioctl(sock, SIOCGLIFNETMASK, lifr_mask) < 0)
+               msg_fatal("%s: ioctl(SIOCGLIFNETMASK): %m", myname);
+           /* XXX: Check whether sa_len/family are honoured --dcs */
+           inet_addr_list_append(mask_list,
+                               (struct sockaddr *) & lifr_mask->lifr_addr);
+           myfree((char *) lifr_mask);
+       }
+       lifr = NEXT_INTERFACE(lifr);
+    }
+    vstring_free(buf);
+    (void) close(sock);
+    return (0);
+}
+
+#else                                  /* HAVE_SIOCGLIF */
+
+/*
+ * The classic SIOCGIF* ioctls. Modern BSD operating systems will
+ * also return IPv6 addresses through these structure. Note however
+ * that recent versions of these operating systems have getifaddrs.
+ */
+#if defined(_SIZEOF_ADDR_IFREQ)
+# define NEXT_INTERFACE(ifr)   ((struct ifreq *) \
+       ((char *) ifr + _SIZEOF_ADDR_IFREQ(*ifr)))
+# define IFREQ_SIZE(ifr)       _SIZEOF_ADDR_IFREQ(*ifr)
+#elif defined(HAS_SA_LEN)
+# define NEXT_INTERFACE(ifr)   ((struct ifreq *) \
        ((char *) ifr + sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len))
-#define IFREQ_SIZE(ifr)        (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
+# define IFREQ_SIZE(ifr)       (sizeof(ifr->ifr_name) + ifr->ifr_addr.sa_len)
 #else
-#define NEXT_INTERFACE(ifr) (ifr + 1)
-#define IFREQ_SIZE(ifr)        sizeof(ifr[0])
-#endif
+# define NEXT_INTERFACE(ifr)   (ifr + 1)
+# define IFREQ_SIZE(ifr)       sizeof(ifr[0])
 #endif
 
-/* inet_addr_local - find all IP addresses for this host */
+/* ial_siocgif - determine IP addresses using ioctl(SIOCGIF*) */
 
-int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
+static int ial_siocgif(INET_ADDR_LIST *addr_list,
+                              INET_ADDR_LIST *mask_list,
+                              int af)
 {
-    char   *myname = "inet_addr_local";
+    char   *myname = "inet_addr_local[siocgif]";
+    struct in_addr addr;
     struct ifconf ifc;
     struct ifreq *ifr;
+    struct ifreq *ifr_mask;
     struct ifreq *the_end;
     int     sock;
-    VSTRING *buf = vstring_alloc(1024);
-    int     initial_count = addr_list->used;
-    struct in_addr addr;
-    struct ifreq *ifr_mask;
-
-    if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
-       msg_fatal("%s: socket: %m", myname);
+    VSTRING *buf;
 
     /*
      * Get the network interface list. XXX The socket API appears to have no
@@ -106,6 +361,10 @@ int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
      * that the program can run out of memory due to a non-memory problem,
      * making it more difficult than necessary to diagnose the real problem.
      */
+    sock = ial_socket(af);
+    if (sock < 0)
+       return (0);
+    buf = vstring_alloc(1024);
     for (;;) {
        ifc.ifc_len = vstring_avail(buf);
        ifc.ifc_buf = vstring_str(buf);
@@ -117,53 +376,215 @@ int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list)
        VSTRING_SPACE(buf, vstring_avail(buf) * 2);
     }
 
-    /*
-     * Get the address of each IP network interface. According to BIND we
-     * must include interfaces that are down because the machine may still
-     * receive packets for that address (yes, via some other interface).
-     * Having no way to verify this claim on every machine, I will give them
-     * the benefit of the doubt.
-     */
     the_end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len);
     for (ifr = ifc.ifc_req; ifr < the_end;) {
-       if (ifr->ifr_addr.sa_family == AF_INET) {       /* IP interface */
+       if (ifr->ifr_addr.sa_family != af) {
+           ifr = NEXT_INTERFACE(ifr);
+           continue;
+       }
+       if (af == AF_INET) {
            addr = ((struct sockaddr_in *) & ifr->ifr_addr)->sin_addr;
-           if (addr.s_addr != INADDR_ANY) {    /* has IP address */
-               inet_addr_list_append(addr_list, &addr);
+           if (addr.s_addr != INADDR_ANY) {
+               inet_addr_list_append(addr_list, &ifr->ifr_addr);
                if (mask_list) {
                    ifr_mask = (struct ifreq *) mymalloc(IFREQ_SIZE(ifr));
                    memcpy((char *) ifr_mask, (char *) ifr, IFREQ_SIZE(ifr));
                    if (ioctl(sock, SIOCGIFNETMASK, ifr_mask) < 0)
                        msg_fatal("%s: ioctl SIOCGIFNETMASK: %m", myname);
-                   addr = ((struct sockaddr_in *) & ifr_mask->ifr_addr)->sin_addr;
-                   inet_addr_list_append(mask_list, &addr);
+
+                   /*
+                    * Note that this SIOCGIFNETMASK has truly screwed up the
+                    * contents of sa_len/sa_family. We must fix this
+                    * manually to have correct addresses.   --dcs
+                    */
+                   ifr_mask->ifr_addr.sa_family = af;
+#ifdef HAS_SA_LEN
+                   ifr_mask->ifr_addr.sa_len = sizeof(struct sockaddr_in);
+#endif
+                   inet_addr_list_append(mask_list, &ifr_mask->ifr_addr);
                    myfree((char *) ifr_mask);
                }
            }
        }
+#ifdef HAS_IPV6
+       else if (af == AF_INET6) {
+           struct sockaddr *sa;
+
+           sa = SOCK_ADDR_PTR(&ifr->ifr_addr);
+           if (!(IN6_IS_ADDR_UNSPECIFIED(&SOCK_ADDR_IN6_ADDR(sa)))) {
+               inet_addr_list_append(addr_list, sa);
+               if (mask_list) {
+                   /* XXX Assume /128 for everything */
+                   struct sockaddr_in6 mask6;
+
+                   mask6 = *SOCK_ADDR_IN6_PTR(sa);
+                   memset((char *) &mask6.sin6_addr, ~0,
+                          sizeof(mask6.sin6_addr));
+                   inet_addr_list_append(mask_list, SOCK_ADDR_PTR(&mask6));
+               }
+           }
+       }
+#endif
        ifr = NEXT_INTERFACE(ifr);
     }
     vstring_free(buf);
     (void) close(sock);
+    return (0);
+}
+
+#endif                                 /* HAVE_SIOCGLIF */
+
+#ifdef HAS_PROCNET_IFINET6
+
+/*
+ * Linux does not provide proper calls to retrieve IPv6 interface
+ * addresses. Instead, the addresses can be read from a file in the
+ * /proc tree. The most important issue with this approach however
+ * is that the /proc tree may not always be available, for example
+ * in a chrooted environment or in "hardened" (sic) installations.
+ */
+
+/* ial_procnet_ifinet6 - determine IPv6 addresses using /proc/net/if_inet6 */
+
+static int ial_procnet_ifinet6(INET_ADDR_LIST *addr_list,
+                                      INET_ADDR_LIST *mask_list)
+{
+    char   *myname = "inet_addr_local[procnet_ifinet6]";
+    FILE   *fp;
+    char    buf[BUFSIZ];
+    unsigned plen;
+    VSTRING *addrbuf;
+    struct sockaddr_in6 addr;
+    struct sockaddr_in6 mask;
+
+    /*
+     * Example: 00000000000000000000000000000001 01 80 10 80 lo
+     * 
+     * Fields: address, interface index, prefix length, scope value
+     * (net/ipv6.h), interface flags (linux/rtnetlink.h), device name.
+     * 
+     * FIX 200501 The IPv6 patch used fscanf(), which will hang on unexpected
+     * input. Use fgets() + sscanf() instead.
+     */
+    if ((fp = fopen(_PATH_PROCNET_IFINET6, "r")) != 0) {
+       addrbuf = vstring_alloc(MAI_V6ADDR_BYTES + 1);
+       memset((char *) &addr, 0, sizeof(addr));
+       addr.sin6_family = AF_INET6;
+#ifdef HAS_SA_LEN
+       addr.sin6_len = sizeof(addr);
+#endif
+       mask = addr;
+       while (fgets(buf, sizeof(buf), fp) != 0) {
+           /* 200501 hex_decode() is light-weight compared to getaddrinfo(). */
+           if (hex_decode(addrbuf, buf, MAI_V6ADDR_BYTES * 2) == 0
+               || sscanf(buf + MAI_V6ADDR_BYTES * 2, " %*x %x", &plen) != 1
+               || plen > MAI_V6ADDR_BITS) {
+               msg_warn("unexpected data in %s - skipping IPv6 configuration",
+                        _PATH_PROCNET_IFINET6);
+               break;
+           }
+           /* vstring_str(addrbuf) has worst-case alignment. */
+           addr.sin6_addr = *(struct in6_addr *) vstring_str(addrbuf);
+           inet_addr_list_append(addr_list, SOCK_ADDR_PTR(&addr));
+
+           memset((char *) &mask.sin6_addr, ~0, sizeof(mask.sin6_addr));
+           mask_addr((char *) &mask.sin6_addr, sizeof(mask.sin6_addr), plen);
+           inet_addr_list_append(mask_list, SOCK_ADDR_PTR(&mask));
+       }
+       vstring_free(addrbuf);
+       fclose(fp);                             /* FIX 200501 */
+    } else {
+       msg_warn("can't open %s (%m) - skipping IPv6 configuration",
+                _PATH_PROCNET_IFINET6);
+    }
+    return (0);
+}
+
+#endif                                 /* HAS_PROCNET_IFINET6 */
+
+/* inet_addr_local - find all IP addresses for this host */
+
+int     inet_addr_local(INET_ADDR_LIST *addr_list, INET_ADDR_LIST *mask_list,
+                               unsigned *addr_family_list)
+{
+    char   *myname = "inet_addr_local";
+    int     initial_count = addr_list->used;
+    unsigned family;
+    int     count;
+
+    while ((family = *addr_family_list++) != 0) {
+
+       /*
+        * IP Version 4
+        */
+       if (family == AF_INET) {
+           count = addr_list->used;
+#if defined(HAVE_GETIFADDRS)
+           ial_getifaddrs(addr_list, mask_list, AF_INET);
+#elif defined (HAS_SIOCGLIF)
+           ial_siocglif(addr_list, mask_list, AF_INET);
+#else
+           ial_siocgif(addr_list, mask_list, AF_INET);
+#endif
+           if (msg_verbose)
+               msg_info("%s: configured %d IPv4 addresses",
+                        myname, addr_list->used - count);
+       }
+
+       /*
+        * IP Version 6
+        */
+#ifdef HAS_IPV6
+       else if (family == AF_INET6) {
+           count = addr_list->used;
+#if defined(HAVE_GETIFADDRS)
+           ial_getifaddrs(addr_list, mask_list, AF_INET6);
+#elif defined(HAS_PROCNET_IFINET6)
+           ial_procnet_ifinet6(addr_list, mask_list);
+#elif defined(HAS_SIOCGLIF)
+           ial_siocglif(addr_list, mask_list, AF_INET6);
+#else
+           ial_siocgif(addr_list, mask_list, AF_INET6);
+#endif
+           if (msg_verbose)
+               msg_info("%s: configured %d IPv6 addresses", myname,
+                        addr_list->used - count);
+       }
+#endif
+
+       /*
+        * Something's not right.
+        */
+       else
+           msg_panic("%s: unknown address family %d", myname, family);
+    }
     return (addr_list->used - initial_count);
 }
 
 #ifdef TEST
 
+#include <string.h>
 #include <vstream.h>
 #include <msg_vstream.h>
+#include <inet_proto.h>
 
 int     main(int unused_argc, char **argv)
 {
     INET_ADDR_LIST addr_list;
     INET_ADDR_LIST mask_list;
+    MAI_HOSTADDR_STR hostaddr;
+    MAI_HOSTADDR_STR hostmask;
+    struct sockaddr *sa;
     int     i;
+    INET_PROTO_INFO *proto_info;
 
     msg_vstream_init(argv[0], VSTREAM_ERR);
+    msg_verbose = 1;
 
+    proto_info = inet_proto_init(argv[0], INET_PROTO_NAME_ALL);
     inet_addr_list_init(&addr_list);
     inet_addr_list_init(&mask_list);
-    inet_addr_local(&addr_list, &mask_list);
+    inet_addr_local(&addr_list, &mask_list, proto_info->ai_family_list);
 
     if (addr_list.used == 0)
        msg_fatal("cannot find any active network interfaces");
@@ -172,10 +593,15 @@ int     main(int unused_argc, char **argv)
        msg_warn("found only one active network interface");
 
     for (i = 0; i < addr_list.used; i++) {
-       vstream_printf("%s/", inet_ntoa(addr_list.addrs[i]));
-       vstream_printf("%s\n", inet_ntoa(mask_list.addrs[i]));
+       sa = SOCK_ADDR_PTR(addr_list.addrs + i);
+       SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
+                            &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+       sa = SOCK_ADDR_PTR(mask_list.addrs + i);
+       SOCKADDR_TO_HOSTADDR(SOCK_ADDR_PTR(sa), SOCK_ADDR_LEN(sa),
+                            &hostmask, (MAI_SERVPORT_STR *) 0, 0);
+       vstream_printf("%s/%s\n", hostaddr.buf, hostmask.buf);
+       vstream_fflush(VSTREAM_OUT);
     }
-    vstream_fflush(VSTREAM_OUT);
     inet_addr_list_free(&addr_list);
     inet_addr_list_free(&mask_list);
 }
index 969264fe2e6712185246df780ecac6bf386fe248..cb6b3f232ca2aeb2d61ee312191a7420bc5b9d03 100644 (file)
@@ -19,7 +19,7 @@
  /*
   * External interface.
   */
-extern int inet_addr_local(INET_ADDR_LIST *, INET_ADDR_LIST *);
+extern int inet_addr_local(INET_ADDR_LIST *, INET_ADDR_LIST *, unsigned *);
 
 /* LICENSE
 /* .ad
index 3c76734cdda4f9663c47f24ac0966725f11eaaf2..cc2cbf6f92a08cc7f2ca0c18749a622763f17929 100644 (file)
@@ -2,7 +2,7 @@
 /* NAME
 /*     inet_connect 3
 /* SUMMARY
-/*     connect to INET-domain listener
+/*     connect to TCP listener
 /* SYNOPSIS
 /*     #include <connect.h>
 /*
@@ -11,7 +11,7 @@
 /*     int     block_mode;
 /*     int     timeout;
 /* DESCRIPTION
-/*     inet_connect connects to a listener in the AF_INET domain at
+/*     inet_connect connects to a TCP listener at
 /*     the specified address, and returns the resulting file descriptor.
 /*
 /*     Arguments:
 /*     a value <= 0 to disable the time limit.
 /* DIAGNOSTICS
 /*     The result is -1 when the connection could not be made.
-/*     Th nature of the error is available via the global \fIerrno\fR
+/*     The nature of the error is available via the global \fIerrno\fR
 /*     variable.
 /*     Fatal errors: other system call failures.
-/* BUGS
-/*     This routine uses find_inet_addr() which ignores all but the
-/*     first address listed for the named host.
-/* SEE ALSO
-/*     find_inet(3), simple inet name service interface
 /* LICENSE
 /* .ad
 /* .fi
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
+#include <netdb.h>
 
 /* Utility library. */
 
 #include "mymalloc.h"
 #include "msg.h"
-#include "find_inet.h"
-#include "inet_util.h"
 #include "iostuff.h"
+#include "host_port.h"
 #include "sane_connect.h"
 #include "connect.h"
 #include "timed_connect.h"
+#include "myaddrinfo.h"
+#include "sock_addr.h"
+#include "inet_proto.h"
 
-/* inet_connect - connect to AF_INET-domain listener */
+static int inet_connect_one(struct addrinfo *, int, int);
+
+/* inet_connect - connect to TCP listener */
 
 int     inet_connect(const char *addr, int block_mode, int timeout)
 {
     char   *buf;
     char   *host;
     char   *port;
-    struct sockaddr_in sin;
+    const char *parse_err;
+    struct addrinfo *res;
+    struct addrinfo *res0;
+    int     aierr;
     int     sock;
+    MAI_HOSTADDR_STR hostaddr;
+    INET_PROTO_INFO *proto_info;
+    int     found;
 
     /*
      * Translate address information to internal form. No host defaults to
      * the local host.
      */
-    buf = inet_parse(addr, &host, &port);
-    if (*host == 0)
-       host = "localhost";
-    memset((char *) &sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_addr.s_addr = find_inet_addr(host);
-    sin.sin_port = find_inet_port(port, "tcp");
+    buf = mystrdup(addr);
+    if ((parse_err = host_port(buf, &host, "localhost", &port, (char *) 0)) != 0)
+       msg_fatal("%s: %s", addr, parse_err);
+    if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res0)) != 0)
+       msg_fatal("host/service %s/%s not found: %s",
+                 host, port, MAI_STRERROR(aierr));
     myfree(buf);
 
+    proto_info = inet_proto_info();
+    for (sock = -1, found = 0, res = res0; res != 0; res = res->ai_next) {
+
+       /*
+        * Safety net.
+        */
+       if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+           msg_info("skipping address family %d for host %s",
+                    res->ai_family, host);
+           continue;
+       }
+       found++;
+
+       /*
+        * In case of multiple addresses, show what address we're trying now.
+        */
+       if (msg_verbose) {
+           SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
+                                &hostaddr, (MAI_SERVPORT_STR *) 0, 0);
+           msg_info("trying... [%s]", hostaddr.buf);
+       }
+       if ((sock = inet_connect_one(res, block_mode, timeout)) < 0) {
+           if (msg_verbose)
+               msg_info("%m");
+       } else
+           break;
+    }
+    if (found == 0)
+       msg_fatal("host not found: %s", addr);
+    freeaddrinfo(res0);
+    return (sock);
+}
+
+/* inet_connect_one - try to connect to one address */
+
+static int inet_connect_one(struct addrinfo * res, int block_mode, int timeout)
+{
+    int     sock;
+
     /*
      * Create a client socket.
      */
-    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-       msg_fatal("socket: %m");
+    sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+    if (sock < 0)
+       return (-1);
 
     /*
      * Timed connect.
      */
     if (timeout > 0) {
        non_blocking(sock, NON_BLOCKING);
-       if (timed_connect(sock, (struct sockaddr *) & sin, sizeof(sin), timeout) < 0) {
+       if (timed_connect(sock, res->ai_addr, res->ai_addrlen, timeout) < 0) {
            close(sock);
            return (-1);
        }
@@ -115,7 +160,7 @@ int     inet_connect(const char *addr, int block_mode, int timeout)
      */
     else {
        non_blocking(sock, block_mode);
-       if (sane_connect(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0
+       if (sane_connect(sock, res->ai_addr, res->ai_addrlen) < 0
            && errno != EINPROGRESS) {
            close(sock);
            return (-1);
index 2a846b39b8ddaad234038f6a8b9d596789dbd573..257cf644bed8a36385d20990c6df17f868357fb2 100644 (file)
@@ -2,7 +2,7 @@
 /* NAME
 /*     inet_listen 3
 /* SUMMARY
-/*     start INET-domain listener
+/*     start TCP listener
 /* SYNOPSIS
 /*     #include <listen.h>
 /*
@@ -14,7 +14,7 @@
 /*     int     inet_accept(fd)
 /*     int     fd;
 /* DESCRIPTION
-/*     The \fBinet_listen\fR routine starts a listener in the INET domain
+/*     The \fBinet_listen\fR routine starts a TCP listener
 /*     on the specified address, with the specified backlog, and returns
 /*     the resulting file descriptor.
 /*
@@ -56,6 +56,7 @@
 #ifndef MAXHOSTNAMELEN
 #include <sys/param.h>
 #endif
+#include <errno.h>
 #include <string.h>
 #include <unistd.h>
 
 
 #include "mymalloc.h"
 #include "msg.h"
-#include "find_inet.h"
-#include "inet_util.h"
+#include "host_port.h"
 #include "iostuff.h"
 #include "listen.h"
 #include "sane_accept.h"
+#include "myaddrinfo.h"
+#include "sock_addr.h"
+#include "inet_proto.h"
 
-/* Application-specific stuff. */
-
-#ifndef INADDR_ANY
-#define INADDR_ANY     0xffffffff
-#endif
-
-/* inet_listen - create inet-domain listener */
+/* inet_listen - create TCP listener */
 
 int     inet_listen(const char *addr, int backlog, int block_mode)
 {
-    struct sockaddr_in sin;
+    struct addrinfo *res;
+    struct addrinfo *res0;
+    int     aierr;
     int     sock;
-    int     t = 1;
+    int     on = 1;
     char   *buf;
     char   *host;
     char   *port;
+    const char *parse_err;
+    MAI_HOSTADDR_STR hostaddr;
+    MAI_SERVPORT_STR portnum;
+    INET_PROTO_INFO *proto_info;
+    int     found;
 
     /*
      * Translate address information to internal form.
      */
-    buf = inet_parse(addr, &host, &port);
-    memset((char *) &sin, 0, sizeof(sin));
-    sin.sin_family = AF_INET;
-    sin.sin_port = find_inet_port(port, "tcp");
-    sin.sin_addr.s_addr = (*host ? find_inet_addr(host) : INADDR_ANY);
+    buf = mystrdup(addr);
+    if ((parse_err = host_port(buf, &host, "", &port, (char *) 0)) != 0)
+       msg_fatal("%s: %s", addr, parse_err);
+    if (*host == 0)
+       host = 0;
+    if ((aierr = hostname_to_sockaddr(host, port, SOCK_STREAM, &res0)) != 0)
+       msg_fatal("%s: %s", addr, MAI_STRERROR(aierr));
     myfree(buf);
+    /* No early returns or res0 leaks. */
 
-    /*
-     * Create a listener socket.
-     */
-    if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-       msg_fatal("socket: %m");
-    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *) &t, sizeof(t)) < 0)
-       msg_fatal("setsockopt: %m");
-    if (bind(sock, (struct sockaddr *) & sin, sizeof(sin)) < 0)
-       msg_fatal("bind %s port %d: %m", sin.sin_addr.s_addr == INADDR_ANY ?
-              "INADDR_ANY" : inet_ntoa(sin.sin_addr), ntohs(sin.sin_port));
+    proto_info = inet_proto_info();
+    for (found = 0, res = res0; res != 0; res = res->ai_next) {
+
+       /*
+        * Safety net.
+        */
+       if (strchr((char *) proto_info->sa_family_list, res->ai_family) == 0) {
+           msg_info("skipping address family %d for %s",
+                    res->ai_family, addr);
+           continue;
+       }
+       found++;
+
+       /*
+        * Show what address we're trying.
+        */
+       if (msg_verbose) {
+           SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
+                                &hostaddr, &portnum, 0);
+           msg_info("trying... [%s]:%s", hostaddr.buf, portnum.buf);
+       }
+
+       /*
+        * Create a listener socket.
+        */
+       if ((sock = socket(res->ai_family, res->ai_socktype, 0)) < 0)
+           msg_fatal("socket: %m");
+#ifdef HAS_IPV6
+# if defined(IPV6_V6ONLY) && !defined(BROKEN_AI_PASSIVE_NULL_HOST)
+       if (res->ai_family == AF_INET6
+           && setsockopt(sock, IPPROTO_IPV6, IPV6_V6ONLY,
+                         (char *) &on, sizeof(on)) < 0)
+           msg_fatal("setsockopt(IPV6_V6ONLY): %m");
+# endif
+#endif
+       if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
+                      (char *) &on, sizeof(on)) < 0)
+           msg_fatal("setsockopt(SO_REUSEADDR): %m");
+       if (bind(sock, res->ai_addr, res->ai_addrlen) < 0) {
+           SOCKADDR_TO_HOSTADDR(res->ai_addr, res->ai_addrlen,
+                                &hostaddr, &portnum, 0);
+           msg_fatal("bind %s port %s: %m", hostaddr.buf, portnum.buf);
+       }
+       break;
+    }
+    freeaddrinfo(res0);
+    if (found == 0)
+       msg_fatal("%s: host not found", addr);
     non_blocking(sock, block_mode);
     if (listen(sock, backlog) < 0)
        msg_fatal("listen: %m");
diff --git a/postfix/src/util/inet_proto.c b/postfix/src/util/inet_proto.c
new file mode 100644 (file)
index 0000000..4cd9bcb
--- /dev/null
@@ -0,0 +1,274 @@
+/*++
+/* NAME
+/*     inet_proto 3
+/* SUMMARY
+/*     convert protocol names to assorted constants
+/* SYNOPSIS
+/*     #include <inet_proto.h>
+/*
+/*     typedef struct {
+/* .in +4
+/*             unsigned ai_family; /* PF_UNSPEC, PF_INET, or PF_INET6 */
+/*             unsigned *ai_family_list; /* PF_INET and/or PF_INET6 */
+/*             unsigned *dns_atype_list;/* TAAAA and/or TA */
+/*             unsigned char *sa_family_list;/* AF_INET6 and/or AF_INET */
+/* .in -4
+/* } INET_PROTO_INFO;
+/*
+/*     INET_PROTO_INFO *inet_proto_init(context, protocols)
+/*
+/*     INET_PROTO_INFO *inet_proto_info()
+/* DESCRIPTION
+/*     inet_proto_init() converts a string with protocol names
+/*     into null-terminated lists of appropriate constants used
+/*     by Postfix library routines.  The idea is that one should
+/*     be able to configure an MTA for IPv4 only, without having
+/*     to recompile code (what a concept).
+/*
+/*     Unfortunately, some compilers won't link initialized data
+/*     without a function call into the same source module, so
+/*     we invoke inet_proto_info() in order to access the result
+/*     from inet_proto_init() from within library routines.
+/*     inet_proto_info() also conveniently initializes the data
+/*     to built-in defaults.
+/*
+/*     Arguments:
+/* .IP context
+/*     Typically, a configuration parameter name.
+/* .IP protocols
+/*     Null-terminated string with protocol names separated by
+/*     whitespace and/or commas:
+/* .RS
+/* .IP INET_PROTO_NAME_ALL
+/*     Enable all available IP protocols.
+/* .IP INET_PROTO_NAME_IPV4
+/*     Enable IP version 4 support.
+/* .IP INET_PROTO_NAME_IPV6
+/*     Enable IP version 6 support.
+/* .RS
+/* .PP
+/*     Results:
+/* .IP ai_family
+/*     Only one of PF_UNSPEC, PF_INET, or PF_INET6. This can be
+/*     used as input for the getaddrinfo() and getnameinfo()
+/*     routines.
+/* .IP ai_family_list
+/*     One or more of PF_INET or PF_INET6. This can be used as
+/*     input for the inet_addr_local() routine.
+/* .IP dns_atype_list
+/*     One or more of T_AAAA or TA. This can be used as input for
+/*     the dns_lookup_v() and dns_lookup_l() routines.
+/* .IP sa_family_list
+/*     One or more of AF_INET6 or AF_INET. This can be used as an
+/*     output filter for the results from the getaddrinfo() and
+/*     getnameinfo() routines.
+/* SEE ALSO
+/*     msg(3) diagnostics interface
+/* DIAGNOSTICS
+/*     This module will report if IPv6 is unavailable, and will
+/*     disable IPv6 support in Postfix. When IPv6 is the only
+/*     selected protocol, this is a fatal error.
+/*
+/*     Fatal errors: memory allocation problem.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#ifdef RESOLVE_H_NEEDS_STDIO_H
+#include <stdio.h>
+#endif
+#include <resolv.h>
+#include <stdarg.h>
+#include <unistd.h>
+
+/* Utility library. */
+
+#include <mymalloc.h>
+#include <msg.h>
+#include <myaddrinfo.h>
+#include <name_mask.h>
+#include <inet_proto.h>
+
+ /*
+  * Application-specific.
+  */
+
+ /*
+  * Run-time initialization, so we can work around LINUX where IPv6 falls
+  * flat on its face because it is not turned on in the kernel.
+  */
+INET_PROTO_INFO *inet_proto_table = 0;
+
+ /*
+  * Infrastructure: lookup table with the protocol names that we support.
+  */
+#define INET_PROTO_MASK_IPV4   (1<<0)
+#define INET_PROTO_MASK_IPV6   (1<<1)
+
+static NAME_MASK proto_table[] = {
+#ifdef HAS_IPV6
+    INET_PROTO_NAME_ALL, INET_PROTO_MASK_IPV4 | INET_PROTO_MASK_IPV6,
+    INET_PROTO_NAME_IPV6, INET_PROTO_MASK_IPV6,
+#else
+    INET_PROTO_NAME_ALL, INET_PROTO_MASK_IPV4,
+#endif
+    INET_PROTO_NAME_IPV4, INET_PROTO_MASK_IPV4,
+    0,
+};
+
+/* make_uchar_vector - create and initialize uchar vector */
+
+static unsigned char *make_uchar_vector(int len,...)
+{
+    const char *myname = "make_uchar_vector";
+    va_list ap;
+    int     count;
+    unsigned char *vp;
+
+    va_start(ap, len);
+    if (len <= 0)
+       msg_panic("%s: bad vector length: %d", myname, len);
+    vp = (unsigned char *) mymalloc(sizeof(*vp) * len);
+    for (count = 0; count < len; count++)
+       vp[count] = va_arg(ap, unsigned);
+    va_end(ap);
+    return (vp);
+}
+
+/* make_unsigned_vector - create and initialize integer vector */
+
+static unsigned *make_unsigned_vector(int len,...)
+{
+    const char *myname = "make_unsigned_vector";
+    va_list ap;
+    int     count;
+    unsigned *vp;
+
+    va_start(ap, len);
+    if (len <= 0)
+       msg_panic("%s: bad vector length: %d", myname, len);
+    vp = (unsigned *) mymalloc(sizeof(*vp) * len);
+    for (count = 0; count < len; count++)
+       vp[count] = va_arg(ap, unsigned);
+    va_end(ap);
+    return (vp);
+}
+
+/* inet_proto_free - destroy data */
+
+static void inet_proto_free(INET_PROTO_INFO *pf)
+{
+    myfree((char *) pf->ai_family_list);
+    myfree((char *) pf->dns_atype_list);
+    myfree((char *) pf->sa_family_list);
+    myfree((char *) pf);
+}
+
+/* inet_proto_init - convert protocol names to library inputs */
+
+INET_PROTO_INFO *inet_proto_init(const char *context, const char *protocols)
+{
+    const char *myname = "inet_proto";
+    INET_PROTO_INFO *pf;
+    int     inet_proto_mask;
+    int     sock;
+
+    /*
+     * Store addess family etc. info as null-terminated vectors. If that
+     * breaks because we must be able to store nulls, we'll deal with the
+     * additional complexity.
+     * 
+     * XXX Use compile-time initialized data templates instead of building the
+     * reply on the fly.
+     */
+    inet_proto_mask = name_mask(context, proto_table, protocols);
+    switch (inet_proto_mask) {
+#ifdef HAS_IPV6
+    case INET_PROTO_MASK_IPV6:
+       if ((sock = socket(PF_INET6, SOCK_STREAM, 0)) >= 0) {
+           close(sock);
+           pf = (INET_PROTO_INFO *) mymalloc(sizeof(*pf));
+           pf->ai_family = PF_INET6;
+           pf->ai_family_list = make_unsigned_vector(2, PF_INET6, 0);
+           pf->dns_atype_list = make_unsigned_vector(2, T_AAAA, 0);
+           pf->sa_family_list = make_uchar_vector(2, AF_INET6, 0);
+           break;
+       } else if (errno == EAFNOSUPPORT) {
+           msg_fatal("%s: IPv6 support is disabled: %m", context);
+       } else {
+           msg_fatal("socket: %m");
+       }
+    case (INET_PROTO_MASK_IPV6 | INET_PROTO_MASK_IPV4):
+       if ((sock = socket(PF_INET6, SOCK_STREAM, 0)) >= 0) {
+           close(sock);
+           pf = (INET_PROTO_INFO *) mymalloc(sizeof(*pf));
+           pf->ai_family = PF_UNSPEC;
+           pf->ai_family_list = make_unsigned_vector(3, PF_INET, PF_INET6, 0);
+           pf->dns_atype_list = make_unsigned_vector(3, T_A, T_AAAA, 0);
+           pf->sa_family_list = make_uchar_vector(3, AF_INET, AF_INET6, 0);
+           break;
+       } else if (errno == EAFNOSUPPORT) {
+           msg_warn("%s: IPv6 support is disabled: %m", context);
+           msg_warn("%s: configuring for IPv4 support only", context);
+           /* FALLTHROUGH */
+       } else {
+           msg_fatal("socket: %m");
+       }
+#endif
+    case INET_PROTO_MASK_IPV4:
+       pf = (INET_PROTO_INFO *) mymalloc(sizeof(*pf));
+       pf->ai_family = PF_INET;
+       pf->ai_family_list = make_unsigned_vector(2, PF_INET, 0);
+       pf->dns_atype_list = make_unsigned_vector(2, T_A, 0);
+       pf->sa_family_list = make_uchar_vector(2, AF_INET, 0);
+       break;
+    default:
+       msg_panic("%s: bad inet_proto_mask 0x%x", myname, inet_proto_mask);
+    }
+    if (inet_proto_table)
+       inet_proto_free(inet_proto_table);
+    return (inet_proto_table = pf);
+}
+
+#ifdef TEST
+
+ /*
+  * Small driver for unit tests.
+  */
+int     main(int argc, char **argv)
+{
+    char   *myname = argv[0];
+    INET_PROTO_INFO *pf;
+
+    if (argc < 2)
+       msg_fatal("usage: %s protocol(s)...", myname);
+
+    while (*++argv) {
+       msg_info("=== %s ===", *argv);
+       if (**argv)
+           inet_proto_init(myname, *argv);
+       pf = inet_proto_table;
+       msg_info("ai_family = %u", pf->ai_family);
+       msg_info("ai_family_list = %u %u...",
+                pf->ai_family_list[0], pf->ai_family_list[1]);
+       msg_info("dns_atype_list = %u %u...",
+                pf->dns_atype_list[0], pf->dns_atype_list[1]);
+       msg_info("sa_family_list = %u %u...",
+                pf->sa_family_list[0], pf->sa_family_list[1]);
+    }
+    return (0);
+}
+
+#endif
diff --git a/postfix/src/util/inet_proto.h b/postfix/src/util/inet_proto.h
new file mode 100644 (file)
index 0000000..1fcc9db
--- /dev/null
@@ -0,0 +1,51 @@
+#ifndef _INET_PROTO_INFO_H_INCLUDED_
+#define _INET_PROTO_INFO_H_INCLUDED_
+
+/*++
+/* NAME
+/*     inet_proto_info 3h
+/* SUMMARY
+/*     convert protocol names to assorted constants
+/* SYNOPSIS
+/*     #include <inet_proto_info.h>
+ DESCRIPTION
+ .nf
+
+ /*
+  * External interface.
+  */
+typedef struct {
+    unsigned int ai_family;            /* PF_UNSPEC, PF_INET, or PF_INET6 */
+    unsigned int *ai_family_list;      /* PF_INET and/or PF_INET6 */
+    unsigned int *dns_atype_list;      /* TAAAA and/or TA */
+    unsigned char *sa_family_list;     /* AF_INET6 and/or AF_INET */
+} INET_PROTO_INFO;
+
+ /*
+  * Some compilers won't link initialized data unless we call a function in
+  * the same source file. Therefore, inet_proto_info() is a function instead
+  * of a global variable.
+  */
+#define inet_proto_info() \
+    (inet_proto_table ? inet_proto_table : \
+       inet_proto_init("default protocol setting", DEF_INET_PROTOCOLS))
+
+extern INET_PROTO_INFO *inet_proto_init(const char *, const char *);
+extern INET_PROTO_INFO *inet_proto_table;
+
+#define INET_PROTO_NAME_IPV6   "ipv6"
+#define INET_PROTO_NAME_IPV4   "ipv4"
+#define INET_PROTO_NAME_ALL    "all"
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/util/inet_util.c b/postfix/src/util/inet_util.c
deleted file mode 100644 (file)
index 47a41a2..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-/*++
-/* NAME
-/*     inet_util 3
-/* SUMMARY
-/*     INET-domain utilities
-/* SYNOPSIS
-/*     #include <inet_util.h>
-/*
-/*     char    *inet_parse(addr, hostp, portp)
-/*     const char *addr;
-/*     char    **hostp;
-/*     char    **portp;
-/* DESCRIPTION
-/*     This module implements various support routines for
-/*     dealing with AF_INET connections, addresses etc.
-/*
-/*     inet_parse() takes an address of the form host:port and
-/*     breaks it up into its constituent parts. The resulting
-/*     host information is an empty string when the address
-/*     contains no host part or no host: part. inet_parse()
-/*     returns a pointer to memory that it has allocated for
-/*     string storage. The caller should pass the host to the
-/*     myfree() function when the storage is no longer needed.
-/* DIAGNOSTICS
-/*     Fatal errors: invalid address or host forms.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*     IBM T.J. Watson Research
-/*     P.O. Box 704
-/*     Yorktown Heights, NY 10598, USA
-/*--*/
-
-/* System libraries. */
-
-#include <sys_defs.h>
-
-/* Utility library. */
-
-#include "mymalloc.h"
-#include "split_at.h"
-#include "inet_util.h"
-
-/* inet_parse - parse host:port address spec */
-
-char   *inet_parse(const char *addr, char **hostp, char **portp)
-{
-    char   *buf;
-
-    buf = mystrdup(addr);
-    if ((*portp = split_at_right(buf, ':')) != 0) {
-       *hostp = buf;
-    } else {
-       *portp = buf;
-       *hostp = "";
-    }
-    return (buf);
-}
index c2856b803b86865b5db2bb4adc4cbe45a7f51361..b21f8b21fd3e92e2cce8920220ab58acecbf36dc 100644 (file)
@@ -162,7 +162,7 @@ int     mac_parse(const char *value, MAC_PARSE_FN action, char *context)
 
 /* mac_parse_print - print parse tree */
 
-static void mac_parse_print(int type, VSTRING *buf, char *unused_context)
+static int mac_parse_print(int type, VSTRING *buf, char *unused_context)
 {
     char   *type_name;
 
@@ -177,6 +177,7 @@ static void mac_parse_print(int type, VSTRING *buf, char *unused_context)
        msg_panic("unknown token type %d", type);
     }
     vstream_printf("%s \"%s\"\n", type_name, vstring_str(buf));
+    return (0);
 }
 
 int     main(int unused_argc, char **unused_argv)
index a0235acc495d0ff68e73f5484358420014f66453..cf50aae2575cb12897991471ed4f614308d319e2 100644 (file)
@@ -140,7 +140,7 @@ int     make_dirs(const char *path, int perms)
 #include <stdlib.h>
 #include <msg_vstream.h>
 
-main(int argc, char **argv)
+int     main(int argc, char **argv)
 {
     msg_vstream_init(argv[0], VSTREAM_ERR);
     if (argc < 2)
diff --git a/postfix/src/util/mask_addr.c b/postfix/src/util/mask_addr.c
new file mode 100644 (file)
index 0000000..38d5b6d
--- /dev/null
@@ -0,0 +1,68 @@
+/*++
+/* NAME
+/*     mask_addr 3
+/* SUMMARY
+/*     address bit banging
+/* SYNOPSIS
+/*     #include <mask_addr.h>
+/*
+/*     void    mask_addr(addr_bytes, addr_byte_count, network_bits)
+/*     unsigned char *addr_bytes;
+/*     unsigned addr_byte_count;
+/*     unsigned network_bits;
+/* DESCRIPTION
+/*     mask_addr() clears all the host bits in the specified
+/*     address.  The code can handle addresses of any length,
+/*     and bytes of any width.
+/*
+/*     Arguments:
+/* .IP addr_bytes
+/*     The network address in network byte order.
+/* .IP addr_byte_count
+/*     The network address length in bytes.
+/* .IP network_bits
+/*     The number of initial bits that will not be cleared.
+/* DIAGNOSTICS
+/*     Fatal errors: the number of network bits exceeds the address size.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <limits.h>                    /* CHAR_BIT */
+
+/* Utility library. */
+
+#include <msg.h>
+#include <mask_addr.h>
+
+/* mask_addr - mask off a variable-length address */
+
+void    mask_addr(unsigned char *addr_bytes,
+                         unsigned addr_byte_count,
+                         unsigned network_bits)
+{
+    unsigned char *p;
+
+    if (network_bits > addr_byte_count * CHAR_BIT)
+       msg_panic("mask_addr: address byte count %d too small for bit count %d", 
+               addr_byte_count, network_bits);
+
+    p = addr_bytes + network_bits / CHAR_BIT;
+    network_bits %= CHAR_BIT;
+
+    if (network_bits != 0)
+       *p++ &= ~0 << (CHAR_BIT - network_bits);
+
+    while (p < addr_bytes + addr_byte_count)
+       *p++ = 0;
+}
similarity index 55%
rename from postfix/src/util/inet_util.h
rename to postfix/src/util/mask_addr.h
index 7eea602792972473b0a78e3a1c16c1dc4a4344ce..0e70a41cd3a51f8443aa4decc2c66aae57cd81fb 100644 (file)
@@ -1,19 +1,20 @@
-#ifndef _INET_UTIL_H_INCLUDED_
-#define _INET_UTIL_H_INCLUDED_
+#ifndef _MASK_ADDR_H_INCLUDED_
+#define _MASK_ADDR_H_INCLUDED_
 
 /*++
 /* NAME
-/*     inet_util 3h
+/*     mask_addr 3h
 /* SUMMARY
-/*     INET-domain utilities
+/*     address bit banging
 /* SYNOPSIS
-/*     #include <inet_util.h>
+/*     #include <mask_addr.h>
 /* DESCRIPTION
 /* .nf
 
- /* External interface. */
-
-extern char *inet_parse(const char *, char **, char **);
+ /*
+  * External interface.
+  */
+extern void mask_addr(unsigned char *, unsigned, unsigned);
 
 /* LICENSE
 /* .ad
index ab4b13d0e080fa689aaf15797008e86a90f001c7..fb57b3e1d66b375301a7f1aec0a9b0c36b648c71 100644 (file)
@@ -95,6 +95,9 @@ struct MATCH_LIST {
     const char **match_args;           /* match arguments */
 };
 
+#define MATCH_DICTIONARY(pattern) \
+    ((pattern)[0] != '[' && strchr((pattern), ':') != 0)
+
 /* match_list_parse - parse buffer, destroy buffer */
 
 static ARGV *match_list_parse(ARGV *list, char *string)
@@ -125,7 +128,7 @@ static ARGV *match_list_parse(ARGV *list, char *string)
                    list = match_list_parse(list, vstring_str(buf));
            if (vstream_fclose(fp))
                msg_fatal("%s: read file %s: %m", myname, pattern);
-       } else if (strchr(pattern, ':') != 0) { /* type:table */
+       } else if (MATCH_DICTIONARY(pattern)) { /* type:table */
            if (buf == 0)
                buf = vstring_alloc(10);
 #define OPEN_FLAGS     O_RDONLY
@@ -137,7 +140,7 @@ static ARGV *match_list_parse(ARGV *list, char *string)
            map_type_name_flags = STR(buf) + (map_type_name - pattern);
            if (dict_handle(map_type_name_flags) == 0)
                dict_register(map_type_name_flags,
-                             dict_open(map_type_name, OPEN_FLAGS, DICT_FLAGS));
+                         dict_open(map_type_name, OPEN_FLAGS, DICT_FLAGS));
            argv_add(list, STR(buf), (char *) 0);
        } else {                                /* other pattern */
            argv_add(list, pattern, (char *) 0);
index 6334737b4a5f5d247a91188ca225fdb685130dff..19c1d3244d4420b584ea80ac42b51853704799dd 100644 (file)
 #include <strings.h>
 #endif
 
-#ifndef INADDR_NONE
-#define INADDR_NONE 0xffffffff
-#endif
-
 /* Utility library. */
 
 #include <msg.h>
 #include <dict.h>
 #include <match_ops.h>
 #include <stringops.h>
+#include <cidr_match.h>
+
+#define MATCH_DICTIONARY(pattern) \
+    ((pattern)[0] != '[' && strchr((pattern), ':') != 0)
 
 /* match_string - match a string literal */
 
@@ -95,7 +95,7 @@ int     match_string(int unused_flags, const char *string, const char *pattern)
     /*
      * Try dictionary lookup: exact match.
      */
-    if (strchr(pattern, ':') != 0) {
+    if (MATCH_DICTIONARY(pattern)) {
        key = lowercase(mystrdup(string));
        match = (dict_lookup(pattern, key) != 0);
        myfree(key);
@@ -136,7 +136,7 @@ int     match_hostname(int flags, const char *name, const char *pattern)
     /*
      * Try dictionary lookup: exact match and parent domains.
      */
-    if (strchr(pattern, ':') != 0) {
+    if (MATCH_DICTIONARY(pattern)) {
        temp = lowercase(mystrdup(name));
        match = 0;
        for (entry = temp; *entry != 0; entry = next) {
@@ -177,49 +177,28 @@ int     match_hostname(int flags, const char *name, const char *pattern)
     return (0);
 }
 
-/* match_parse_mask - parse net/mask pattern */
-
-static int match_parse_mask(const char *pattern, unsigned long *net_bits,
-                                   unsigned int *mask_shift)
-{
-    char   *saved_pattern;
-    char   *mask;
-
-#define BITS_PER_ADDR  32
-
-    saved_pattern = mystrdup(pattern);
-    if ((mask = split_at(saved_pattern, '/')) != 0) {
-       if (!alldig(mask) || (*mask_shift = atoi(mask)) > BITS_PER_ADDR
-           || (*net_bits = inet_addr(saved_pattern)) == INADDR_NONE) {
-           msg_fatal("bad net/mask pattern: %s", pattern);
-       }
-    }
-    myfree(saved_pattern);
-    return (mask != 0);
-}
-
 /* match_hostaddr - match host by address */
 
 int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
 {
     char   *myname = "match_hostaddr";
-    unsigned int mask_shift;
-    unsigned long mask_bits;
-    unsigned long net_bits;
-    unsigned long addr_bits;
-    struct in_addr net_addr;
+    char   *saved_patt;
+    CIDR_MATCH match_info;
+    VSTRING *err;
 
     if (msg_verbose)
        msg_info("%s: %s ~? %s", myname, addr, pattern);
 
-    if (addr[strspn(addr, "01234567890./:")] != 0)
+#define V4_ADDR_STRING_CHARS   "01234567890."
+#define V6_ADDR_STRING_CHARS   V4_ADDR_STRING_CHARS "abcdefABCDEF:"
+
+    if (addr[strspn(addr, V6_ADDR_STRING_CHARS)] != 0)
        return (0);
 
     /*
-     * Try dictionary lookup. This can be case insensitive. XXX Probably
-     * should also try again after stripping least significant octets.
+     * Try dictionary lookup. This can be case insensitive.
      */
-    if (strchr(pattern, ':') != 0) {
+    if (MATCH_DICTIONARY(pattern)) {
        if (dict_lookup(pattern, addr) != 0)
            return (1);
        if (dict_errno != 0)
@@ -230,28 +209,45 @@ int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
     /*
      * Try an exact match with the host address.
      */
-    if (strcasecmp(addr, pattern) == 0) {
-       return (1);
+    if (pattern[0] != '[') {
+       if (strcasecmp(addr, pattern) == 0)
+           return (1);
+    } else {
+       int     addr_len = strlen(addr);
+
+       if (strncasecmp(addr, pattern + 1, addr_len) == 0
+           && strcmp(pattern + 1 + addr_len, "]") == 0)
+           return (1);
     }
 
     /*
-     * In a net/mask pattern, the mask is specified as the number of bits of
-     * the network part.
+     * Light-weight tests before we get into expensive operations.
+     * 
+     * - Don't bother matching IPv4 against IPv6. Postfix transforms
+     * IPv4-in-IPv6 to native IPv4 form when IPv4 support is enabled in
+     * Postfix; if not, then Postfix has no business dealing with IPv4
+     * addresses anyway.
+     * 
+     * - Don't bother if the pattern is a bare IPv4 address. That form would
+     * have been matched with the strcasecmp() call above.
+     * 
+     * - Don't bother if the pattern isn't an address or address/mask.
      */
-    if (match_parse_mask(pattern, &net_bits, &mask_shift)) {
-       addr_bits = inet_addr(addr);
-       if (addr_bits == INADDR_NONE)
-           msg_fatal("%s: bad address argument: %s", myname, addr);
-       mask_bits = mask_shift > 0 ?
-           htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift)) : 0;
-       if ((addr_bits & mask_bits) == net_bits)
-           return (1);
-       if (net_bits & ~mask_bits) {
-           net_addr.s_addr = (net_bits & mask_bits);
-           msg_fatal("net/mask pattern %s has a non-null host portion; "
-                     "specify %s/%d if this is really what you want",
-                     pattern, inet_ntoa(net_addr), mask_shift);
-       }
-    }
-    return (0);
+    if (!strchr(addr, ':') != !strchr(pattern, ':')
+       || pattern[strspn(pattern, V4_ADDR_STRING_CHARS)] == 0
+       || pattern[strspn(pattern, V6_ADDR_STRING_CHARS "[]/")] != 0)
+       return (0);
+
+    /*
+     * No escape from expensive operations: either we have a net/mask
+     * pattern, or we have an address that can have multiple valid
+     * representations (e.g., 0:0:0:0:0:0:0:1 versus ::1, etc.). The only way
+     * to find out if the address matches the pattern is to transform
+     * everything into to binary form, and to do the comparison there.
+     */
+    saved_patt = mystrdup(pattern);
+    if ((err = cidr_match_parse(&match_info, saved_patt, (VSTRING *) 0)) != 0)
+       msg_fatal("%s", vstring_str(err));
+    myfree(saved_patt);
+    return (cidr_match_execute(&match_info, addr) != 0);
 }
index f5b2b87a2897c007b5151c4c9d6e5f455792d74c..7b6a6e7eb631275b75b91da45af68a8fe74b6f03 100644 (file)
@@ -206,7 +206,7 @@ int     msg_syslog_facility(const char *facility_name)
   * Usage: msg_syslog_test text...
   */
 
-main(int argc, char **argv)
+int     main(int argc, char **argv)
 {
     VSTRING *vp = vstring_alloc(256);
 
diff --git a/postfix/src/util/myaddrinfo.c b/postfix/src/util/myaddrinfo.c
new file mode 100644 (file)
index 0000000..2307979
--- /dev/null
@@ -0,0 +1,821 @@
+/*++
+/* NAME
+/*     myaddrinfo 3
+/* SUMMARY
+/*     addrinfo encapsulation and emulation
+/* SYNOPSIS
+/*     #include <myaddrinfo.h>
+/*
+/*     #define MAI_V4ADDR_BITS ...
+/*     #define MAI_V6ADDR_BITS ...
+/*     #define MAI_V4ADDR_BYTES ...
+/*     #define MAI_V6ADDR_BYTES ...
+/*
+/*     typedef struct { char buf[....]; } MAI_HOSTNAME_STR;
+/*     typedef struct { char buf[....]; } MAI_HOSTADDR_STR;
+/*     typedef struct { char buf[....]; } MAI_SERVNAME_STR;
+/*     typedef struct { char buf[....]; } MAI_SERVPORT_STR;
+/*
+/*     int     hostname_to_sockaddr(hostname, service, socktype, result)
+/*     const char *hostname;
+/*     const char *service;
+/*     int     socktype;
+/*     struct addrinfo **result;
+/*
+/*     int     hostaddr_to_sockaddr(hostaddr, service, socktype, result)
+/*     const char *hostaddr;
+/*     const char *service;
+/*     int     socktype;
+/*     struct addrinfo **result;
+/*
+/*     int     sockaddr_to_hostaddr(sa, salen, hostaddr, portnum, socktype)
+/*     const struct sockaddr *sa;
+/*     SOCKADDR_SIZE salen;
+/*     MAI_HOSTADDR_STR *hostaddr;
+/*     MAI_SERVPORT_STR *portnum;
+/*     int     socktype;
+/*
+/*     int     sockaddr_to_hostname(sa, salen, hostname, service, socktype)
+/*     const struct sockaddr *sa;
+/*     SOCKADDR_SIZE salen;
+/*     MAI_HOSTNAME_STR *hostname;
+/*     MAI_SERVNAME_STR *service;
+/*     int     socktype;
+/*
+/*     const char *MAI_STRERROR(error)
+/*     int     error;
+/* DESCRIPTION
+/*     This module provides a simplified user interface to the
+/*     getaddrinfo(3) and getnameinfo(3) routines (which provide
+/*     a unified interface to manipulate IPv4 and IPv6 socket
+/*     address structures).
+/*
+/*     On systems without getaddrinfo(3) and getnameinfo(3) support,
+/*     emulation for IPv4 only can be enabled by defining
+/*     EMULATE_IPV4_ADDRINFO.
+/*
+/*     hostname_to_sockaddr() looks up the binary addresses for
+/*     the specified symbolic hostname or numeric address.  The
+/*     result should be destroyed with freeaddrinfo(). A null host
+/*     pointer converts to the null host address.
+/*
+/*     hostaddr_to_sockaddr() converts a printable network address
+/*     into the corresponding binary form.  The result should be
+/*     destroyed with freeaddrinfo(). A null host pointer converts
+/*     to the null host address.
+/*
+/*     sockaddr_to_hostaddr() converts a binary network address
+/*     into printable form. The result buffers should be large
+/*     enough to hold the printable address or port including the
+/*     null terminator.
+/*
+/*     sockaddr_to_hostname() converts a binary network address
+/*     into a hostname or service.  The result buffer should be
+/*     large enough to hold the hostname or service including the
+/*     null terminator. This routine rejects malformed hostnames
+/*     or numeric hostnames and pretends that the lookup failed.
+/*
+/*     MAI_STRERROR() is an unsafe macro (it evaluates the argument
+/*     multiple times) that invokes strerror() or gai_strerror()
+/*     as appropriate.
+/*
+/*     This module exports the following constants that should be
+/*     user for storage allocation of name or address information:
+/* .IP MAI_V4ADDR_BITS
+/* .IP MAI_V6ADDR_BITS
+/* .IP MAI_V4ADDR_BYTES
+/* .IP MAI_V6ADDR_BYTES
+/*     The number of bits or bytes needed to store a binary
+/*     IPv4 or IPv6 network address.
+/* .PP
+/*     The types MAI_HOST{NAME,ADDR}_STR and MAI_SERV{NAME,PORT}_STR
+/*     implement buffers for the storage of the string representations
+/*     of symbolic or numerical hosts or services. Do not use
+/*     buffer types other than the ones that are expected here,
+/*     or things will blow up with buffer overflow problems.
+/*
+/*     Arguments:
+/* .IP hostname
+/*     On input to hostname_to_sockaddr(), a numeric or symbolic
+/*     hostname, or a null pointer (meaning the wild-card listen
+/*     address).  On output from sockaddr_to_hostname(), storage
+/*     for the result hostname, or a null pointer.
+/* .IP hostaddr
+/*     On input to hostaddr_to_sockaddr(), a numeric hostname,
+/*     or a null pointer (meaning the wild-card listen address).
+/*     On output from sockaddr_to_hostaddr(), storage for the
+/*     result hostaddress, or a null pointer.
+/* .IP service
+/*     On input to hostname/addr_to_sockaddr(), a numeric or
+/*     symbolic service name, or a null pointer in which case the
+/*     socktype argument is ignored.  On output from
+/*     sockaddr_to_hostname/addr(), storage for the result service
+/*     name, or a null pointer.
+/* .IP portnum
+/*     Storage for the result service port number, or a null pointer.
+/* .IP socktype
+/*     Socket type: SOCK_STREAM, SOCK_DGRAM, etc. This argument is
+/*     ignored when no service or port are specified.
+/* .IP sa
+/*     Protocol-independent socket address structure.
+/* .IP salen
+/*     Protocol-dependent socket address structure size in bytes.
+/* SEE ALSO
+/*     getaddrinfo(3), getnameinfo(3), freeaddrinfo(3), gai_strerror(3)
+/* DIAGNOSTICS
+/*     All routines either return 0 upon success, or an error code
+/*     that is compatible with gai_strerror().
+/*
+/*     On systems where addrinfo support is emulated by Postfix,
+/*     some out-of-memory errors are not reported to the caller,
+/*     but are handled by mymalloc().
+/* BUGS
+/*     The IPv4-only emulation code does not support requests that
+/*     specify a service but no socket type. It returns an error
+/*     indication, instead of enumerating all the possible answers.
+/*
+/*     The hostname/addr_to_sockaddr() routines should accept a
+/*     list of address families that the caller is interested in,
+/*     and they should return only information of those types.
+/*
+/*     Unfortunately, it is not possible to remove unwanted address
+/*     family results from hostname_to_sockaddr(), because we
+/*     don't know how the system library routine getaddrinfo()
+/*     allocates memory.  For example, getaddrinfo() could save
+/*     space by referencing the same string object from multiple
+/*     addrinfo structures; or it could allocate a string object
+/*     and the addrinfo structure as one memory block.
+/*
+/*     We could get around this by copying getaddrinfo() results
+/*     to our own private data structures, but that would only
+/*     make an already expensive API even more expensive.
+/*
+/*     A better workaround is to return a vector of addrinfo
+/*     pointers to the elements that contain only the elements
+/*     that the caller is interested in. The pointer to the
+/*     original getaddrinfo() result can be hidden at the end
+/*     after the null terminator, or before the first element.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* Utility library. */
+
+#include <mymalloc.h>
+#include <valid_hostname.h>
+#include <sock_addr.h>
+#include <stringops.h>
+#include <msg.h>
+#include <inet_proto.h>
+#include <myaddrinfo.h>
+
+/* Application-specific. */
+
+ /*
+  * Use an old trick to save some space: allocate space for two objects in
+  * one. In Postfix we often use this trick for structures that have an array
+  * of things at the end.
+  */
+struct ipv4addrinfo {
+    struct addrinfo info;
+    struct sockaddr_in sin;
+};
+
+ /*
+  * Make nulls more descriptive.
+  */
+#define NO_SERVICE     ((char *) 0)
+
+ /*
+  * When we're not interested in service ports, we must pick a socket type
+  * otherwise getaddrinfo() will give us duplicate results: one set for TCP,
+  * and another set for UDP. For consistency, we'll use the same default
+  * socket type for the results from emulation mode.
+  */
+#define MAI_SOCKTYPE   SOCK_STREAM     /* getaddrinfo() query */
+
+#ifdef EMULATE_IPV4_ADDRINFO
+
+/* clone_ipv4addrinfo - clone ipv4addrinfo structure */
+
+static struct ipv4addrinfo *clone_ipv4addrinfo(struct ipv4addrinfo * tp)
+{
+    struct ipv4addrinfo *ip;
+
+    ip = (struct ipv4addrinfo *) mymalloc(sizeof(*ip));
+    *ip = *tp;
+    ip->info.ai_addr = (struct sockaddr *) & (ip->sin);
+    return (ip);
+}
+
+/* init_ipv4addrinfo - initialize an ipv4addrinfo structure */
+
+static void init_ipv4addrinfo(struct ipv4addrinfo * ip, int socktype)
+{
+
+    /*
+     * Portability: null pointers aren't necessarily all-zero bits, so we
+     * make explicit assignments to all the pointers that we're aware of.
+     */
+    memset((char *) ip, 0, sizeof(*ip));
+    ip->info.ai_family = PF_INET;
+    ip->info.ai_socktype = socktype;
+    ip->info.ai_protocol = 0;                  /* XXX */
+    ip->info.ai_addrlen = sizeof(ip->sin);
+    ip->info.ai_canonname = 0;
+    ip->info.ai_addr = (struct sockaddr *) & (ip->sin);
+    ip->info.ai_next = 0;
+    ip->sin.sin_family = AF_INET;
+#ifdef HAS_SA_LEN
+    ip->sin.sin_len = sizeof(ip->sin);
+#endif
+}
+
+/* find_service - translate numeric or symbolic service name */
+
+static int find_service(const char *service, int socktype)
+{
+    struct servent *sp;
+    const char *proto;
+    unsigned port;
+
+    if (alldig(service)) {
+       port = atoi(service);
+       return (port < 65536 ? htons(port) : -1);
+    }
+    if (socktype == SOCK_STREAM) {
+       proto = "tcp";
+    } else if (socktype == SOCK_DGRAM) {
+       proto = "udp";
+    } else {
+       return (-1);
+    }
+    if ((sp = getservbyname(service, proto)) != 0) {
+       return (sp->s_port);
+    } else {
+       return (-1);
+    }
+}
+
+#endif
+
+/* hostname_to_sockaddr - hostname to binary address form */
+
+int     hostname_to_sockaddr(const char *hostname, const char *service,
+                                    int socktype, struct addrinfo ** res)
+{
+#ifdef EMULATE_IPV4_ADDRINFO
+
+    /*
+     * Emulated getaddrinfo(3) version.
+     */
+    static struct ipv4addrinfo template;
+    struct ipv4addrinfo *ip;
+    struct ipv4addrinfo *prev;
+    struct in_addr addr;
+    struct hostent *hp;
+    char  **name_list;
+    int     port;
+
+    /*
+     * Validate the service.
+     */
+    if (service) {
+       if ((port = find_service(service, socktype)) < 0)
+           return (EAI_SERVICE);
+    } else {
+       port = 0;
+       socktype = MAI_SOCKTYPE;
+    }
+
+    /*
+     * No host means INADDR_ANY.
+     */
+    if (hostname == 0) {
+       ip = (struct ipv4addrinfo *) mymalloc(sizeof(*ip));
+       init_ipv4addrinfo(ip, socktype);
+       ip->sin.sin_addr.s_addr = INADDR_ANY;
+       ip->sin.sin_port = port;
+       *res = &(ip->info);
+       return (0);
+    }
+
+    /*
+     * Numeric host.
+     */
+    if (inet_pton(AF_INET, hostname, (void *) &addr) == 1) {
+       ip = (struct ipv4addrinfo *) mymalloc(sizeof(*ip));
+       init_ipv4addrinfo(ip, socktype);
+       ip->sin.sin_addr = addr;
+       ip->sin.sin_port = port;
+       *res = &(ip->info);
+       return (0);
+    }
+
+    /*
+     * Look up the IPv4 address list.
+     */
+    if ((hp = gethostbyname(hostname)) == 0)
+       return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NODATA);
+    if (hp->h_addrtype != AF_INET
+       || hp->h_length != sizeof(template.sin.sin_addr))
+       return (EAI_NODATA);
+
+    /*
+     * Initialize the result template.
+     */
+    if (template.info.ai_addrlen == 0)
+       init_ipv4addrinfo(&template, socktype);
+
+    /*
+     * Copy the address information into an addrinfo structure.
+     */
+    prev = &template;
+    for (name_list = hp->h_addr_list; name_list[0]; name_list++) {
+       ip = clone_ipv4addrinfo(prev);
+       ip->sin.sin_addr = IN_ADDR(name_list[0]);
+       ip->sin.sin_port = port;
+       if (prev == &template)
+           *res = &(ip->info);
+       else
+           prev->info.ai_next = &(ip->info);
+       prev = ip;
+    }
+    return (0);
+#else
+
+    /*
+     * Native getaddrinfo(3) version.
+     * 
+     * XXX Wild-card listener issues.
+     * 
+     * With most IPv4 plus IPv6 systems, an IPv6 wild-card listener also listens
+     * on the IPv4 wild-card address. Connections from IPv4 clients appear as
+     * IPv4-in-IPv6 addresses; when Postfix support for IPv4 is turned on,
+     * Postfix automatically maps these embedded addresses to their original
+     * IPv4 form. So everything seems to be fine.
+     * 
+     * However, some applications prefer to use separate listener sockets for
+     * IPv4 and IPv6. The Postfix IPv6 patch provided such an example. And
+     * this is where things become tricky. On many systems the IPv6 and IPv4
+     * wild-card listeners cannot coexist. When one is already active, the
+     * other fails with EADDRINUSE. Solaris 9, however, will automagically
+     * "do the right thing" and allow both listeners to coexist.
+     * 
+     * Recent systems have the IPV6_V6ONLY feature (RFC 3493), which tells the
+     * system that we really mean IPv6 when we say IPv6. This allows us to
+     * set up separate wild-card listener sockets for IPv4 and IPv6. So
+     * everything seems to be fine again.
+     * 
+     * The following workaround disables the wild-card IPv4 listener when
+     * IPV6_V6ONLY is unavailable. This is necessary for some Linux versions,
+     * but is not needed for Solaris 9 (which allows IPv4 and IPv6 wild-card
+     * listeners to coexist). Solaris 10 beta already has IPV6_V6ONLY.
+     * 
+     * XXX This workaround obviously breaks if we want to support protocols in
+     * addition to IPv6 and IPv4, but it is needed only until IPv6
+     * implementations catch up with RFC 3493. A nicer fix is to filter the
+     * getaddrinfo() result, and to return a vector of addrinfo pointers to
+     * only those types of elements that the caller has expressed interested
+     * in.
+     * 
+     * XXX Vanilla AIX 5.1 getaddrinfo() does not support a null hostname with
+     * AI_PASSIVE. And since we don't know how getaddrinfo() manages its
+     * memory we can't bypass it for this special case, or freeaddrinfo()
+     * might blow up. Instead we turn off IPV6_V6ONLY in inet_listen(), and
+     * supply a protocol-dependent hard-coded string value to getaddrinfo()
+     * below, so that it will convert into the appropriate wild-card address.
+     */
+    struct addrinfo hints;
+
+    memset((char *) &hints, 0, sizeof(hints));
+    hints.ai_family = inet_proto_info()->ai_family;
+    hints.ai_socktype = service ? socktype : MAI_SOCKTYPE;
+    if (!hostname) {
+       hints.ai_flags = AI_PASSIVE;
+#if !defined(IPV6_V6ONLY) || defined(BROKEN_AI_PASSIVE_NULL_HOST)
+       switch (hints.ai_family) {
+       case PF_UNSPEC:
+           hints.ai_family = PF_INET6;
+#ifdef BROKEN_AI_PASSIVE_NULL_HOST
+       case PF_INET6:
+           hostname = "::";
+           break;
+       case PF_INET:
+           hostname = "0.0.0.0";
+           break;
+#endif
+       }
+#endif
+    }
+    return (getaddrinfo(hostname, service, &hints, res));
+#endif
+}
+
+/* hostaddr_to_sockaddr - printable address to binary address form */
+
+int     hostaddr_to_sockaddr(const char *hostaddr, const char *service,
+                                    int socktype, struct addrinfo ** res)
+{
+#ifdef EMULATE_IPV4_ADDRINFO
+
+    /*
+     * Emulated getaddrinfo(3) version.
+     */
+    struct ipv4addrinfo *ip;
+    struct in_addr addr;
+    int     port;
+
+    /*
+     * Validate the service.
+     */
+    if (service) {
+       if ((port = find_service(service, socktype)) < 0)
+           return (EAI_SERVICE);
+    } else {
+       port = 0;
+       socktype = MAI_SOCKTYPE;
+    }
+
+    /*
+     * No host means INADDR_ANY.
+     */
+    if (hostaddr == 0) {
+       ip = (struct ipv4addrinfo *) mymalloc(sizeof(*ip));
+       init_ipv4addrinfo(ip, socktype);
+       ip->sin.sin_addr.s_addr = INADDR_ANY;
+       ip->sin.sin_port = port;
+       *res = &(ip->info);
+       return (0);
+    }
+
+    /*
+     * Deal with bad address forms.
+     */
+    switch (inet_pton(AF_INET, hostaddr, (void *) &addr)) {
+    case 1:                                    /* Success */
+       break;
+    default:                                   /* Unparsable */
+       return (EAI_NONAME);
+    case -1:                                   /* See errno */
+       return (EAI_SYSTEM);
+    }
+
+    /*
+     * Initialize the result structure.
+     */
+    ip = (struct ipv4addrinfo *) mymalloc(sizeof(*ip));
+    init_ipv4addrinfo(ip, socktype);
+
+    /*
+     * And copy the result.
+     */
+    ip->sin.sin_addr = addr;
+    ip->sin.sin_port = port;
+    *res = &(ip->info);
+
+    return (0);
+#else
+
+    /*
+     * Native getaddrinfo(3) version. See comments in hostname_to_sockaddr().
+     * 
+     * XXX Vanilla AIX 5.1 getaddrinfo() returns multiple results when
+     * converting a printable ipv4 or ipv6 address to socket address with
+     * ai_family=PF_UNSPEC, ai_flags=AI_NUMERICHOST, ai_socktype=SOCK_STREAM,
+     * ai_protocol=0 or IPPROTO_TCP, and service=0. The workaround is to
+     * ignore all but the first result.
+     */
+    struct addrinfo hints;
+
+    memset(&hints, 0, sizeof(hints));
+    hints.ai_family = inet_proto_info()->ai_family;
+    hints.ai_socktype = service ? socktype : MAI_SOCKTYPE;
+    hints.ai_flags = AI_NUMERICHOST;
+    if (!hostaddr) {
+       hints.ai_flags |= AI_PASSIVE;
+#if !defined(IPV6_V6ONLY) || defined(BROKEN_AI_PASSIVE_NULL_HOST)
+       switch (hints.ai_family) {
+       case PF_UNSPEC:
+           hints.ai_family = PF_INET6;
+#ifdef BROKEN_AI_PASSIVE_NULL_HOST
+       case PF_INET6:
+           hostaddr = "::";
+           break;
+       case PF_INET:
+           hostaddr = "0.0.0.0";
+           break;
+#endif
+       }
+#endif
+    }
+    return (getaddrinfo(hostaddr, service, &hints, res));
+#endif
+}
+
+/* sockaddr_to_hostaddr - binary address to printable address form */
+
+int     sockaddr_to_hostaddr(const struct sockaddr * sa, SOCKADDR_SIZE salen,
+                                    MAI_HOSTADDR_STR *hostaddr,
+                                    MAI_SERVPORT_STR *portnum,
+                                    int unused_socktype)
+{
+#ifdef EMULATE_IPV4_ADDRINFO
+    char    portbuf[sizeof("65535")];
+    int     len;
+
+    /*
+     * Emulated getnameinfo(3) version. The buffer length includes the space
+     * for the null terminator.
+     */
+    if (sa->sa_family != AF_INET) {
+       errno = EAFNOSUPPORT;
+       return (EAI_SYSTEM);
+    }
+    if (hostaddr != 0) {
+       if (inet_ntop(AF_INET, (void *) &(SOCK_ADDR_IN_ADDR(sa)),
+                     hostaddr->buf, sizeof(hostaddr->buf)) == 0)
+           return (EAI_SYSTEM);
+    }
+    if (portnum != 0) {
+       sprintf(portbuf, "%d", ntohs(SOCK_ADDR_IN_PORT(sa)) & 0xffff);
+       if ((len = strlen(portbuf)) >= sizeof(portnum->buf)) {
+           errno = ENOSPC;
+           return (EAI_SYSTEM);
+       }
+       memcpy(portnum->buf, portbuf, len + 1);
+    }
+    return (0);
+#else
+
+    /*
+     * Native getnameinfo(3) version.
+     */
+    return (getnameinfo(sa, salen,
+                       hostaddr ? hostaddr->buf : (char *) 0,
+                       hostaddr ? sizeof(hostaddr->buf) : 0,
+                       portnum ? portnum->buf : (char *) 0,
+                       portnum ? sizeof(portnum->buf) : 0,
+                       NI_NUMERICHOST | NI_NUMERICSERV));
+#endif
+}
+
+/* sockaddr_to_hostname - binary address to printable hostname */
+
+int     sockaddr_to_hostname(const struct sockaddr * sa, SOCKADDR_SIZE salen,
+                                    MAI_HOSTNAME_STR *hostname,
+                                    MAI_SERVNAME_STR *service,
+                                    int socktype)
+{
+#ifdef EMULATE_IPV4_ADDRINFO
+
+    /*
+     * Emulated getnameinfo(3) version.
+     */
+    struct hostent *hp;
+    struct servent *sp;
+    size_t  len;
+
+    /*
+     * Sanity check.
+     */
+    if (sa->sa_family != AF_INET)
+       return (EAI_NODATA);
+
+    /*
+     * Look up the host name.
+     */
+    if (hostname != 0) {
+       if ((hp = gethostbyaddr((char *) &(SOCK_ADDR_IN_ADDR(sa)),
+                               sizeof(SOCK_ADDR_IN_ADDR(sa)),
+                               AF_INET)) == 0)
+           return (h_errno == TRY_AGAIN ? EAI_AGAIN : EAI_NONAME);
+
+       /*
+        * Save the result. The buffer length includes the space for the null
+        * terminator. Hostname sanity checks are at the end of this
+        * function.
+        */
+       if ((len = strlen(hp->h_name)) >= sizeof(hostname->buf)) {
+           errno = ENOSPC;
+           return (EAI_SYSTEM);
+       }
+       memcpy(hostname->buf, hp->h_name, len + 1);
+    }
+
+    /*
+     * Look up the service.
+     */
+    if (service != 0) {
+       if ((sp = getservbyport(ntohs(SOCK_ADDR_IN_PORT(sa)),
+                             socktype == SOCK_DGRAM ? "udp" : "tcp")) == 0)
+           return (EAI_NONAME);
+
+       /*
+        * Save the result. The buffer length includes the space for the null
+        * terminator.
+        */
+       if ((len = strlen(sp->s_name)) >= sizeof(service->buf)) {
+           errno = ENOSPC;
+           return (EAI_SYSTEM);
+       }
+       memcpy(service->buf, sp->s_name, len + 1);
+    }
+#else
+
+    /*
+     * Native getnameinfo(3) version.
+     */
+    int     err;
+
+    err = getnameinfo(sa, salen,
+                     hostname ? hostname->buf : (char *) 0,
+                     hostname ? sizeof(hostname->buf) : 0,
+                     service ? service->buf : (char *) 0,
+                     service ? sizeof(service->buf) : 0,
+                     socktype == SOCK_DGRAM ?
+                     NI_NAMEREQD | NI_DGRAM : NI_NAMEREQD);
+    if (err != 0)
+       return (err);
+#endif
+
+    /*
+     * Hostname sanity checks.
+     */
+    if (hostname != 0) {
+       if (valid_hostaddr(hostname->buf, DONT_GRIPE)) {
+           msg_warn("numeric hostname: %s", hostname->buf);
+           return (EAI_NONAME);
+       }
+       if (!valid_hostname(hostname->buf, DO_GRIPE))
+           return (EAI_NONAME);
+    }
+    return (0);
+}
+
+/* myaddrinfo_control - fine control */
+
+void    myaddrinfo_control(int name,...)
+{
+    const char *myname = "myaddrinfo_control";
+    va_list ap;
+
+    for (va_start(ap, name); name != 0; name = va_arg(ap, int)) {
+       switch (name) {
+       default:
+           msg_panic("%s: bad name %d", myname, name);
+       }
+    }
+}
+
+#ifdef EMULATE_IPV4_ADDRINFO
+
+/* freeaddrinfo - release storage */
+
+void    freeaddrinfo(struct addrinfo * ai)
+{
+    struct addrinfo *ap;
+    struct addrinfo *next;
+
+    /*
+     * Artefact of implementation: tolerate a null pointer argument.
+     */
+    for (ap = ai; ap != 0; ap = next) {
+       next = ap->ai_next;
+       if (ap->ai_canonname)
+           myfree(ap->ai_canonname);
+       /* ap->ai_addr is allocated within this memory block */
+       myfree((char *) ap);
+    }
+}
+
+static char *ai_errlist[] = {
+    "Success",
+    "Address family for hostname not supported",       /* EAI_ADDRFAMILY */
+    "Temporary failure in name resolution",    /* EAI_AGAIN     */
+    "Invalid value for ai_flags",      /* EAI_BADFLAGS   */
+    "Non-recoverable failure in name resolution",      /* EAI_FAIL      */
+    "ai_family not supported",         /* EAI_FAMILY     */
+    "Memory allocation failure",       /* EAI_MEMORY     */
+    "No address associated with hostname",     /* EAI_NODATA     */
+    "hostname nor servname provided, or not known",    /* EAI_NONAME     */
+    "service name not supported for ai_socktype",      /* EAI_SERVICE    */
+    "ai_socktype not supported",       /* EAI_SOCKTYPE   */
+    "System error returned in errno",  /* EAI_SYSTEM     */
+    "Invalid value for hints",         /* EAI_BADHINTS   */
+    "Resolved protocol is unknown",    /* EAI_PROTOCOL   */
+    "Unknown error",                   /* EAI_MAX        */
+};
+
+/* gai_strerror - error number to string */
+
+char   *gai_strerror(int ecode)
+{
+
+    /*
+     * Note: EAI_SYSTEM errors are not automatically handed over to
+     * strerror(). The application decides.
+     */
+    if (ecode < 0 || ecode > EAI_MAX)
+       ecode = EAI_MAX;
+    return (ai_errlist[ecode]);
+}
+
+#endif
+
+#ifdef TEST
+
+ /*
+  * A test program that takes some info from the command line and runs it
+  * forward and backward through the above conversion routines.
+  */
+#include <msg.h>
+#include <vstream.h>
+#include <msg_vstream.h>
+
+int     main(int argc, char **argv)
+{
+    struct addrinfo *info;
+    struct addrinfo *ip;
+    MAI_HOSTNAME_STR host;
+    MAI_HOSTADDR_STR addr;
+    int     err;
+
+    msg_vstream_init(argv[0], VSTREAM_ERR);
+
+    if (argc != 4)
+       msg_fatal("usage: %s protocols hostname hostaddress", argv[0]);
+
+    inet_proto_init(argv[0], argv[1]);
+
+    msg_info("=== hostname %s ===", argv[2]);
+
+    if ((err = hostname_to_sockaddr(argv[2], (char *) 0, 0, &info)) != 0) {
+       msg_info("hostname_to_sockaddr(%s): %s",
+         argv[2], err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
+    } else {
+       for (ip = info; ip != 0; ip = ip->ai_next) {
+           if ((err = sockaddr_to_hostaddr(ip->ai_addr, ip->ai_addrlen, &addr,
+                                        (MAI_SERVPORT_STR *) 0, 0)) != 0) {
+               msg_info("sockaddr_to_hostaddr: %s",
+                  err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
+               continue;
+           }
+           msg_info("%s -> family=%d sock=%d proto=%d %s", argv[2],
+                ip->ai_family, ip->ai_socktype, ip->ai_protocol, addr.buf);
+           if ((err = sockaddr_to_hostname(ip->ai_addr, ip->ai_addrlen, &host,
+                                        (MAI_SERVNAME_STR *) 0, 0)) != 0) {
+               msg_info("sockaddr_to_hostname: %s",
+                  err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
+               continue;
+           }
+           msg_info("%s -> %s", addr.buf, host.buf);
+       }
+       freeaddrinfo(info);
+    }
+
+    msg_info("=== host address %s ===", argv[3]);
+
+    if ((err = hostaddr_to_sockaddr(argv[3], (char *) 0, 0, &ip)) != 0) {
+       msg_info("hostaddr_to_sockaddr(%s): %s",
+         argv[3], err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
+    } else {
+       if ((err = sockaddr_to_hostaddr(ip->ai_addr, ip->ai_addrlen, &addr,
+                                       (MAI_SERVPORT_STR *) 0, 0)) != 0) {
+           msg_info("sockaddr_to_hostaddr: %s",
+                  err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
+       } else {
+           msg_info("%s -> family=%d sock=%d proto=%d %s", argv[3],
+                ip->ai_family, ip->ai_socktype, ip->ai_protocol, addr.buf);
+           if ((err = sockaddr_to_hostname(ip->ai_addr, ip->ai_addrlen, &host,
+                                        (MAI_SERVNAME_STR *) 0, 0)) != 0) {
+               msg_info("sockaddr_to_hostname: %s",
+                  err == EAI_SYSTEM ? strerror(errno) : gai_strerror(err));
+           } else
+               msg_info("%s -> %s", addr.buf, host.buf);
+           freeaddrinfo(ip);
+       }
+    }
+    exit(0);
+}
+
+#endif
diff --git a/postfix/src/util/myaddrinfo.h b/postfix/src/util/myaddrinfo.h
new file mode 100644 (file)
index 0000000..c567eb7
--- /dev/null
@@ -0,0 +1,211 @@
+#ifndef _MYADDRINFO_H_INCLUDED_
+#define _MYADDRINFO_H_INCLUDED_
+
+/*++
+/* NAME
+/*     myaddrinfo 3h
+/* SUMMARY
+/*     addrinfo encapsulation and emulation
+/* SYNOPSIS
+/*     #include <myaddrinfo.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * System library.
+  */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+#include <errno.h>                     /* MAI_STRERROR() */
+#include <limits.h>                    /* CHAR_BIT */
+
+ /*
+  * Backwards compatibility support for IPV4 systems without addrinfo API.
+  */
+#ifdef EMULATE_IPV4_ADDRINFO
+
+ /*
+  * Avoid clashes with global symbols, just in case some third-party library
+  * provides its own addrinfo() implementation. This also allows us to test
+  * the IPV4 emulation code on an IPV6 enabled system.
+  */
+#undef  freeaddrinfo
+#define freeaddrinfo   mai_freeaddrinfo
+#undef  gai_strerror
+#define gai_strerror   mai_strerror
+#undef  addrinfo
+#define addrinfo       mai_addrinfo
+#undef  sockaddr_storage
+#define sockaddr_storage mai_sockaddr_storage
+
+ /*
+  * Modern systems define this in <netdb.h>.
+  */
+struct addrinfo {
+    int     ai_flags;                  /* AI_PASSIVE|CANONNAME|NUMERICHOST */
+    int     ai_family;                 /* PF_xxx */
+    int     ai_socktype;               /* SOCK_xxx */
+    int     ai_protocol;               /* 0 or IPPROTO_xxx */
+    size_t  ai_addrlen;                        /* length of ai_addr */
+    char   *ai_canonname;              /* canonical name for nodename */
+    struct sockaddr *ai_addr;          /* binary address */
+    struct addrinfo *ai_next;          /* next structure in linked list */
+};
+
+ /*
+  * Modern systems define this in <sys/socket.h>.
+  */
+struct sockaddr_storage {
+    struct sockaddr_in dummy;          /* alignment!! */
+};
+
+ /*
+  * Result codes. See gai_strerror() for text. Undefine already imported
+  * definitions so that we can test the IPv4-only emulation on a modern
+  * system without getting a ton of compiler warnings.
+  */
+#undef  EAI_ADDRFAMILY
+#define EAI_ADDRFAMILY   1
+#undef  EAI_AGAIN
+#define EAI_AGAIN        2
+#undef  EAI_BADFLAGS
+#define EAI_BADFLAGS     3
+#undef  EAI_FAIL
+#define EAI_FAIL         4
+#undef  EAI_FAMILY
+#define EAI_FAMILY       5
+#undef  EAI_MEMORY
+#define EAI_MEMORY       6
+#undef  EAI_NODATA
+#define EAI_NODATA       7
+#undef  EAI_NONAME
+#define EAI_NONAME       8
+#undef  EAI_SERVICE
+#define EAI_SERVICE      9
+#undef  EAI_SOCKTYPE
+#define EAI_SOCKTYPE    10
+#undef  EAI_SYSTEM
+#define EAI_SYSTEM      11
+#undef  EAI_BADHINTS
+#define EAI_BADHINTS    12
+#undef  EAI_PROTOCOL
+#define EAI_PROTOCOL    13
+#undef  EAI_RESNULL
+#define EAI_RESNULL     14
+#undef  EAI_MAX
+#define EAI_MAX         15
+
+extern void freeaddrinfo(struct addrinfo *);
+extern char *gai_strerror(int);
+
+#endif
+
+ /*
+  * Bounds grow in leaps. These macros attempt to keep non-library code free
+  * from IPV6 #ifdef pollution. Avoid macro names that end in STRLEN because
+  * they suggest that space for the null terminator is not included.
+  */
+#ifdef HAS_IPV6
+# define MAI_HOSTADDR_STRSIZE  INET6_ADDRSTRLEN
+#else
+# ifndef INET_ADDRSTRLEN
+#  define INET_ADDRSTRLEN      16
+# endif
+# define MAI_HOSTADDR_STRSIZE  INET_ADDRSTRLEN
+#endif
+
+#define MAI_HOSTNAME_STRSIZE   1025
+#define MAI_SERVNAME_STRSIZE   32
+#define MAI_SERVPORT_STRSIZE   sizeof("65535")
+
+#define MAI_V4ADDR_BITS                32
+#define MAI_V6ADDR_BITS                128
+#define MAI_V4ADDR_BYTES       ((MAI_V4ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT)
+#define MAI_V6ADDR_BYTES       ((MAI_V6ADDR_BITS + (CHAR_BIT - 1))/CHAR_BIT)
+
+ /*
+  * Routines and data structures to hide some of the complexity of the
+  * addrinfo API. They still don't hide that we may get results for address
+  * families that we aren't interested in.
+  */
+typedef struct {
+    char    buf[MAI_HOSTNAME_STRSIZE];
+} MAI_HOSTNAME_STR;
+
+typedef struct {
+    char    buf[MAI_HOSTADDR_STRSIZE];
+} MAI_HOSTADDR_STR;
+
+typedef struct {
+    char    buf[MAI_SERVNAME_STRSIZE];
+} MAI_SERVNAME_STR;
+
+typedef struct {
+    char    buf[MAI_SERVPORT_STRSIZE];
+} MAI_SERVPORT_STR;
+
+extern int hostname_to_sockaddr(const char *, const char *, int,
+                                       struct addrinfo **);
+extern int hostaddr_to_sockaddr(const char *, const char *, int,
+                                       struct addrinfo **);
+extern int sockaddr_to_hostaddr(const struct sockaddr *, SOCKADDR_SIZE,
+                              MAI_HOSTADDR_STR *, MAI_SERVPORT_STR *, int);
+extern int sockaddr_to_hostname(const struct sockaddr *, SOCKADDR_SIZE,
+                              MAI_HOSTNAME_STR *, MAI_SERVNAME_STR *, int);
+extern void myaddrinfo_control(int,...);
+
+#define MAI_CTL_END    0               /* list terminator */
+
+#define MAI_STRERROR(e) ((e) == EAI_SYSTEM ? strerror(errno) : gai_strerror(e))
+
+ /*
+  * Macros for the case where we really don't want to be bothered with things
+  * that may fail.
+  */
+#define HOSTNAME_TO_SOCKADDR(host, serv, sock, res) \
+    do { \
+       int _aierr; \
+       _aierr = hostname_to_sockaddr((host), (serv), (sock), (res)); \
+       if (_aierr) \
+           msg_fatal("hostname_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
+    } while (0)
+
+#define HOSTADDR_TO_SOCKADDR(host, serv, sock, res) \
+    do { \
+       int _aierr; \
+       _aierr = hostaddr_to_sockaddr((host), (serv), (sock), (res)); \
+       if (_aierr) \
+           msg_fatal("hostaddr_to_sockaddr: %s", MAI_STRERROR(_aierr)); \
+    } while (0)
+
+#define SOCKADDR_TO_HOSTADDR(sa, salen, host, port, sock) \
+    do { \
+       int _aierr; \
+       _aierr = sockaddr_to_hostaddr((sa), (salen), (host), (port), (sock)); \
+       if (_aierr) \
+           msg_fatal("sockaddr_to_hostaddr: %s", MAI_STRERROR(_aierr)); \
+    } while (0)
+
+#define SOCKADDR_TO_HOSTNAME(sa, salen, host, service, sock) \
+    do { \
+       int _aierr; \
+       _aierr = sockaddr_to_hostname((sa), (salen), (host), (service), (sock)); \
+       if (_aierr) \
+           msg_fatal("sockaddr_to_hostname: %s", MAI_STRERROR(_aierr)); \
+    } while (0)
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
diff --git a/postfix/src/util/myaddrinfo.ref b/postfix/src/util/myaddrinfo.ref
new file mode 100644 (file)
index 0000000..49d6ed2
--- /dev/null
@@ -0,0 +1,8 @@
+./myaddrinfo: === hostname belly.porcupine.org ===
+./myaddrinfo: belly.porcupine.org -> family=28 sock=1 proto=6 2001:240:5c7:0:250:56ff:fe10:bd03
+./myaddrinfo: 2001:240:5c7:0:250:56ff:fe10:bd03 -> belly.porcupine.org
+./myaddrinfo: belly.porcupine.org -> family=2 sock=1 proto=6 168.100.189.6
+./myaddrinfo: 168.100.189.6 -> belly.porcupine.org
+./myaddrinfo: === host address 168.100.189.2 ===
+./myaddrinfo: 168.100.189.2 -> family=2 sock=1 proto=6 168.100.189.2
+./myaddrinfo: 168.100.189.2 -> spike.porcupine.org
diff --git a/postfix/src/util/myaddrinfo.ref2 b/postfix/src/util/myaddrinfo.ref2
new file mode 100644 (file)
index 0000000..da2ff91
--- /dev/null
@@ -0,0 +1,5 @@
+./myaddrinfo: === hostname null.porcupine.org ===
+./myaddrinfo: hostname_to_sockaddr(null.porcupine.org): No address associated with hostname
+./myaddrinfo: === host address 10.0.0.0 ===
+./myaddrinfo: 10.0.0.0 -> family=2 sock=1 proto=6 10.0.0.0
+./myaddrinfo: sockaddr_to_hostname: hostname nor servname provided, or not known
diff --git a/postfix/src/util/myaddrinfo4.ref b/postfix/src/util/myaddrinfo4.ref
new file mode 100644 (file)
index 0000000..37d07c2
--- /dev/null
@@ -0,0 +1,6 @@
+./myaddrinfo4: === hostname belly.porcupine.org ===
+./myaddrinfo4: belly.porcupine.org -> family=2 sock=1 proto=6 168.100.189.6
+./myaddrinfo4: 168.100.189.6 -> belly.porcupine.org
+./myaddrinfo4: === host address 168.100.189.2 ===
+./myaddrinfo4: 168.100.189.2 -> family=2 sock=1 proto=6 168.100.189.2
+./myaddrinfo4: 168.100.189.2 -> spike.porcupine.org
diff --git a/postfix/src/util/myaddrinfo4.ref2 b/postfix/src/util/myaddrinfo4.ref2
new file mode 100644 (file)
index 0000000..f73560b
--- /dev/null
@@ -0,0 +1,5 @@
+./myaddrinfo4: === hostname null.porcupine.org ===
+./myaddrinfo4: hostname2sockaddr(null.porcupine.org): No address associated with hostname
+./myaddrinfo4: === host address 10.0.0.0 ===
+./myaddrinfo4: 10.0.0.0 -> family=2 sock=1 proto=6 10.0.0.0
+./myaddrinfo4: sockaddr2hostname: hostname nor servname provided, or not known
index 5695c41c6ec9371c0d6ba53bc742567d1e79fd6a..2bd32ff54f99380b014811df3536e72e122f7817 100644 (file)
@@ -171,22 +171,6 @@ const char *str_name_mask_opt(const char *context, NAME_MASK *table,
     return (STR(buf));
 }
 
- /*
-  * ABI backwards compatibility.
-  */
-#undef name_mask
-#undef str_name_mask
-
-int     name_mask(const char *context, NAME_MASK *table, const char *names)
-{
-       return(name_mask_opt(context, table,names, NAME_MASK_DEFAULT));
-}
-
-const char *str_name_mask(const char *context, NAME_MASK *table, int mask)
-{
-    return(str_name_mask_opt(context, table, mask, NAME_MASK_DEFAULT));
-}
-
 #ifdef TEST
 
  /*
diff --git a/postfix/src/util/sock_addr.c b/postfix/src/util/sock_addr.c
new file mode 100644 (file)
index 0000000..6ccd041
--- /dev/null
@@ -0,0 +1,169 @@
+/*++
+/* NAME
+/*     sock_addr 3
+/* SUMMARY
+/*     sockaddr utilities
+/* SYNOPSIS
+/*     #include <sock_addr.h>
+/*
+/*     int     sock_addr_cmp_addr(sa, sb)
+/*     const struct sockaddr *sa;
+/*     const struct sockaddr *sb;
+/*
+/*     int     sock_addr_cmp_port(sa, sb)
+/*     const struct sockaddr *sa;
+/*     const struct sockaddr *sb;
+/*
+/*     int     SOCK_ADDR_EQ_ADDR(sa, sb)
+/*     const struct sockaddr *sa;
+/*     const struct sockaddr *sb;
+/*
+/*     int     SOCK_ADDR_EQ_PORT(sa, sb)
+/*     const struct sockaddr *sa;
+/*     const struct sockaddr *sb;
+/*
+/*     int     sock_addr_in_loopback(sa)
+/*     const struct sockaddr *sa;
+/* AUXILIARY MACROS
+/*     struct sockaddr *SOCK_ADDR_PTR(ptr)
+/*     unsigned char SOCK_ADDR_FAMILY(ptr)
+/*     unsigned char SOCK_ADDR_LEN(ptr)
+/*
+/*     struct sockaddr_in *SOCK_ADDR_IN_PTR(ptr)
+/*     unsigned char SOCK_ADDR_IN_FAMILY(ptr)
+/*     unsigned short SOCK_ADDR_IN_PORT(ptr)
+/*     struct in_addr SOCK_ADDR_IN_ADDR(ptr)
+/*     struct in_addr IN_ADDR(ptr)
+/*
+/*     struct sockaddr_in6 *SOCK_ADDR_IN6_PTR(ptr)
+/*     unsigned char SOCK_ADDR_IN6_FAMILY(ptr)
+/*     unsigned short SOCK_ADDR_IN6_PORT(ptr)
+/*     struct in6_addr SOCK_ADDR_IN6_ADDR(ptr)
+/*     struct in6_addr IN6_ADDR(ptr)
+/* DESCRIPTION
+/*     These utilities take protocol-independent address structures
+/*     and perform protocol-dependent operations on structure members.
+/*     Some of the macros described here are called unsafe,
+/*     because they evaluate one or more arguments multiple times.
+/*
+/*     sock_addr_cmp_addr() or sock_addr_cmp_port() compare the
+/*     address family and network address or port fields for
+/*     equality, and return indication of the difference between
+/*     their arguments:  < 0 if the first argument is "smaller",
+/*     0 for equality, and > 0 if the first argument is "larger".
+/*
+/*     The unsafe macros SOCK_ADDR_EQ_ADDR() or SOCK_ADDR_EQ_PORT()
+/*     compare compare the address family and network address or
+/*     port fields for equality, and return non-zero when their
+/*     arguments differ.
+/*
+/*     sock_addr_in_loopback() determines if the argument specifies
+/*     a loopback address.
+/*
+/*     The SOCK_ADDR_PTR() macro casts a generic pointer to (struct
+/*     sockaddr *).  The name is upper case for consistency not
+/*     safety.  SOCK_ADDR_FAMILY() and SOCK_ADDR_LEN() return the
+/*     address family and length of the real structure that hides
+/*     inside a generic sockaddr structure. On systems where struct
+/*     sockaddr has no sa_len member, SOCK_ADDR_LEN() cannot be
+/*     used as lvalue.
+/*
+/*     The macros SOCK_ADDR_IN{,6}_{PTR,FAMILY,PORT,ADDR}() cast
+/*     a generic pointer to a specific socket address structure
+/*     pointer, or access a specific socket address structure
+/*     member. These can be used as lvalues.
+/*
+/*     The unsafe INADDR() and IN6_ADDR() macros dereference a
+/*     generic pointer to a specific address structure.
+/* DIAGNOSTICS
+/*     Panic: unsupported address family.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+/* System library. */
+
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+/* Utility library. */
+
+#include <msg.h>
+#include <sock_addr.h>
+
+/* sock_addr_cmp_addr - compare addresses for equality */
+
+int     sock_addr_cmp_addr(const struct sockaddr * sa,
+                                  const struct sockaddr * sb)
+{
+    if (sa->sa_family != sb->sa_family)
+       return (sa->sa_family - sb->sa_family);
+
+    /*
+     * With IPv6 address structures, assume a non-hostile implementation that
+     * stores the address as a contiguous sequence of bits. Any holes in the
+     * sequence would invalidate the use of memcmp().
+     */
+    if (sa->sa_family == AF_INET) {
+       return (SOCK_ADDR_IN_ADDR(sa).s_addr - SOCK_ADDR_IN_ADDR(sb).s_addr);
+#ifdef HAS_IPV6
+    } else if (sa->sa_family == AF_INET6) {
+       return (memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)),
+                      (char *) &(SOCK_ADDR_IN6_ADDR(sb)),
+                      sizeof(SOCK_ADDR_IN6_ADDR(sa))));
+#endif
+    } else {
+       msg_panic("sock_addr_cmp_addr: unsupported address family %d",
+                 sa->sa_family);
+    }
+}
+
+/* sock_addr_cmp_port - compare ports for equality */
+
+int     sock_addr_cmp_port(const struct sockaddr * sa,
+                                  const struct sockaddr * sb)
+{
+    if (sa->sa_family != sb->sa_family)
+       return (sa->sa_family - sb->sa_family);
+
+    if (sa->sa_family == AF_INET) {
+       return (SOCK_ADDR_IN_PORT(sa) - SOCK_ADDR_IN_PORT(sb));
+#ifdef HAS_IPV6
+    } else if (sa->sa_family == AF_INET6) {
+       return (SOCK_ADDR_IN6_PORT(sa) - SOCK_ADDR_IN6_PORT(sb));
+#endif
+    } else {
+       msg_panic("sock_addr_cmp_port: unsupported address family %d",
+                 sa->sa_family);
+    }
+}
+
+/* sock_addr_in_loopback - determine if address is loopback */
+
+int sock_addr_in_loopback(const struct sockaddr * sa)
+{
+    unsigned long inaddr;
+
+    if (sa->sa_family == AF_INET) {
+       inaddr = ntohl(SOCK_ADDR_IN_ADDR(sa).s_addr);
+       return (IN_CLASSA(inaddr)
+               && ((inaddr & IN_CLASSA_NET) >> IN_CLASSA_NSHIFT)
+               == IN_LOOPBACKNET);
+#ifdef HAS_IPV6
+    } else if (sa->sa_family == AF_INET6) {
+       return (IN6_IS_ADDR_LOOPBACK(&SOCK_ADDR_IN6_ADDR(sa)));
+#endif
+    } else {
+       msg_panic("sock_addr_in_loopback: unsupported address family %d",
+                 sa->sa_family);
+    }
+}
diff --git a/postfix/src/util/sock_addr.h b/postfix/src/util/sock_addr.h
new file mode 100644 (file)
index 0000000..1fb54a8
--- /dev/null
@@ -0,0 +1,95 @@
+#ifndef _SOCK_ADDR_EQ_H_INCLUDED_
+#define _SOCK_ADDR_EQ_H_INCLUDED_
+
+/*++
+/* NAME
+/*     sock_addr 3h
+/* SUMMARY
+/*     socket address utilities
+/* SYNOPSIS
+/*     #include <sock_addr.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * System library.
+  */
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <string.h>
+
+ /*
+  * External interface.
+  */
+#define SOCK_ADDR_PTR(ptr)     ((struct sockaddr *)(ptr))
+#define SOCK_ADDR_FAMILY(ptr)  SOCK_ADDR_PTR(ptr)->sa_family
+#ifdef HAS_SA_LEN
+#define SOCK_ADDR_LEN(ptr)     SOCK_ADDR_PTR(ptr)->sa_len
+#endif
+
+#define SOCK_ADDR_IN_PTR(sa)   ((struct sockaddr_in *)(sa))
+#define SOCK_ADDR_IN_FAMILY(sa)        SOCK_ADDR_IN_PTR(sa)->sin_family
+#define SOCK_ADDR_IN_PORT(sa)  SOCK_ADDR_IN_PTR(sa)->sin_port
+#define SOCK_ADDR_IN_ADDR(sa)  SOCK_ADDR_IN_PTR(sa)->sin_addr
+#define IN_ADDR(ia)            (*((struct in_addr *) (ia)))
+
+extern int sock_addr_cmp_addr(const struct sockaddr *, const struct sockaddr *);
+extern int sock_addr_cmp_port(const struct sockaddr *, const struct sockaddr *);
+extern int sock_addr_in_loopback(const struct sockaddr *);
+
+#ifdef HAS_IPV6
+
+#ifndef HAS_SA_LEN
+#define SOCK_ADDR_LEN(sa) \
+    (SOCK_ADDR_PTR(sa)->sa_family == AF_INET6 ? \
+     sizeof(struct sockaddr_in6) : sizeof(struct sockaddr_in))
+#endif
+
+#define SOCK_ADDR_IN6_PTR(sa)  ((struct sockaddr_in6 *)(sa))
+#define SOCK_ADDR_IN6_FAMILY(sa) SOCK_ADDR_IN6_PTR(sa)->sin6_family
+#define SOCK_ADDR_IN6_PORT(sa) SOCK_ADDR_IN6_PTR(sa)->sin6_port
+#define SOCK_ADDR_IN6_ADDR(sa) SOCK_ADDR_IN6_PTR(sa)->sin6_addr
+#define IN6_ADDR(ia)           (*((struct in6_addr *) (ia)))
+
+#define SOCK_ADDR_EQ_ADDR(sa, sb) \
+    ((SOCK_ADDR_FAMILY(sa) == AF_INET && SOCK_ADDR_FAMILY(sb) == AF_INET \
+      && SOCK_ADDR_IN_ADDR(sa).s_addr == SOCK_ADDR_IN_ADDR(sb).s_addr) \
+     || (SOCK_ADDR_FAMILY(sa) == AF_INET6 && SOCK_ADDR_FAMILY(sb) == AF_INET6 \
+         && memcmp((char *) &(SOCK_ADDR_IN6_ADDR(sa)), \
+                   (char *) &(SOCK_ADDR_IN6_ADDR(sb)), \
+                   sizeof(SOCK_ADDR_IN6_ADDR(sa))) == 0))
+
+#define SOCK_ADDR_EQ_PORT(sa, sb) \
+    ((SOCK_ADDR_FAMILY(sa) == AF_INET && SOCK_ADDR_FAMILY(sb) == AF_INET \
+      && SOCK_ADDR_IN_PORT(sa) == SOCK_ADDR_IN_PORT(sb)) \
+     || (SOCK_ADDR_FAMILY(sa) == AF_INET6 && SOCK_ADDR_FAMILY(sb) == AF_INET6 \
+         && SOCK_ADDR_IN6_PORT(sa) == SOCK_ADDR_IN6_PORT(sb)))
+
+#else
+
+#ifndef HAS_SA_LEN
+#define SOCK_ADDR_LEN(sa)      sizeof(struct sockaddr_in)
+#endif
+
+#define SOCK_ADDR_EQ_ADDR(sa, sb) \
+    (SOCK_ADDR_FAMILY(sa) == AF_INET && SOCK_ADDR_FAMILY(sb) == AF_INET \
+     && SOCK_ADDR_IN_ADDR(sa).s_addr == SOCK_ADDR_IN_ADDR(sb).s_addr)
+
+#define SOCK_ADDR_EQ_PORT(sa, sb) \
+    (SOCK_ADDR_FAMILY(sa) == AF_INET && SOCK_ADDR_FAMILY(sb) == AF_INET \
+     && SOCK_ADDR_IN_PORT(sa) == SOCK_ADDR_IN_PORT(sb))
+
+#endif
+
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*     IBM T.J. Watson Research
+/*     P.O. Box 704
+/*     Yorktown Heights, NY 10598, USA
+/*--*/
+
+#endif
index 410783761caae39c4435d8e9b107fc4a99b9bfce..4d05de237d308736ef711be8955e42858f99471d 100644 (file)
@@ -104,7 +104,7 @@ int     main(int argc, char **argv)
        if (stream_send_fd(server_sock, client_fd) < 0)
            msg_fatal("send file descriptor: %m");
        if (close(client_fd) != 0)
-           msg_fatal("close(%d): %m");
+           msg_fatal("close(%d): %m", client_fd);
     }
     exit(0);
 }
index 9d33a3ab2421bdac70ab038722fc07f722537d56..982798f50a6fab544a5c4e679a00e660e2ca9834 100644 (file)
 /*     int     setsid()
 /*
 /*     void    dup2_pass_on_exec(int oldd, int newd)
+/*
+/*     char    *inet_ntop(af, src, dst, size)
+/*     int     af;
+/*     const void *src;
+/*     char    *dst;
+/*     size_t  size;
+/*
+/*     int     inet_pton(af, src, dst)
+/*     int     af;
+/*     const char *src;
+/*     void    *dst;
 /* DESCRIPTION
 /*     These routines are compiled for platforms that lack the functionality
 /*     or that have broken versions that we prefer to stay away from.
@@ -240,7 +251,9 @@ int     dup2_pass_on_exec(int oldd, int newd)
 
 #ifndef HAS_CLOSEFROM
 
+#include <unistd.h>
 #include <errno.h>
+#include <iostuff.h>
 
 /* closefrom() - closes all file descriptors from the given one up */
 
@@ -267,3 +280,81 @@ int     closefrom(int lowfd)
 }
 
 #endif
+
+#ifdef MISSING_INET_NTOP
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+/* inet_ntop - convert binary address to printable address */
+
+const char *inet_ntop(int af, const void *src, char *dst, size_t size)
+{
+    const unsigned char *addr;
+    char    buffer[sizeof("255.255.255.255")];
+    int     len;
+
+    if (af != AF_INET) {
+       errno = EAFNOSUPPORT;
+       return (0);
+    }
+    addr = (const unsigned char *) src;
+#if (CHAR_BIT > 8)
+    sprintf(buffer, "%d.%d.%d.%d", addr[0] & 0xff,
+           addr[1] & 0xff, addr[2] & 0xff, addr[3] & 0xff);
+#else
+    sprintf(buffer, "%d.%d.%d.%d", addr[0], addr[1], addr[2], addr[3]);
+#endif
+    if ((len = strlen(buffer)) >= size) {
+       errno = ENOSPC;
+       return (0);
+    } else {
+       memcpy(dst, buffer, len + 1);
+       return (dst);
+    }
+}
+
+#endif
+
+#ifdef MISSING_INET_PTON
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+#include <errno.h>
+
+#ifndef INADDR_NONE
+#define INADDR_NONE 0xffffffff
+#endif
+
+/* inet_pton - convert printable address to binary address */
+
+int     inet_pton(int af, const char *src, void *dst)
+{
+    struct in_addr addr;
+
+    /*
+     * inet_addr() accepts a wider range of input formats than inet_pton();
+     * the former accepts 1-, 2-, or 3-part dotted addresses, while the
+     * latter requires dotted quad form.
+     */
+    if (af != AF_INET) {
+       errno = EAFNOSUPPORT;
+       return (-1);
+    } else if ((addr.s_addr = inet_addr(src)) == INADDR_NONE
+              && strcmp(src, "255.255.255.255") != 0) {
+       return (0);
+    } else {
+       memcpy(dst, (char *) &addr, sizeof(addr));
+       return (1);
+    }
+}
+
+#endif
index ddee46102c93c1dfaab3c71b161f2fc3d509062c..76d90d61e6f9c6fd56c5b2db6ef95a7214108112 100644 (file)
 #define NATIVE_DAEMON_DIR "/usr/libexec/postfix"
 #endif
 
+#ifdef BSDI4
+/* #define HAS_IPV6 find out interface lookup method */
+#endif
+
 /* __FreeBSD_version version is major+minor */
 
 #if __FreeBSD_version >= 200000
 #define HAS_DEV_URANDOM                        /* XXX probably earlier */
 #endif
 
-#if __NetBSD_Version__ >= 105000000    /* XXX maybe earlier */
-#define HAS_ISSETUGID
+#if __NetBSD_Version__ >= 105000000
+#define HAS_ISSETUGID                  /* XXX maybe earlier */
 #endif
 
 #if __NetBSD_Version__ >= 106000000    /* XXX maybe earlier */
 
 #if __NetBSD_Version__ >= 200060000    /* 2.0F */
 #define HAS_CLOSEFROM
+#endif
+
+#if (defined(__NetBSD_Version__) && __NetBSD_Version__ >= 105000000) \
+    || (defined(__FreeBSD__) && __FreeBSD__ >= 4) \
+    || (defined(OpenBSD) && OpenBSD >= 200003) \
+    || defined(USAGI_LIBINET6)
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAVE_GETIFADDRS
+#endif
+
 #endif
 
  /*
 #define PRINTFLIKE(x,y)
 #define SCANFLIKE(x,y)
 #ifndef NO_NETINFO
-#define HAS_NETINFO
+# define HAS_NETINFO
+#endif
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAVE_GETIFADDRS
 #endif
 #define NATIVE_SENDMAIL_PATH "/usr/sbin/sendmail"
 #define NATIVE_MAILQ_PATH "/usr/bin/mailq"
@@ -237,6 +256,10 @@ extern int opterr;                 /* XXX use <getopt.h> */
 #define STATFS_IN_SYS_MOUNT_H
 #define HAS_POSIX_REGEXP
 #define BROKEN_WRITE_SELECT_ON_NON_BLOCKING_PIPE
+#ifndef NO_IPV6
+# define HAS_IPV6
+#endif
+
 #endif
 
  /*
@@ -309,6 +332,7 @@ extern int opterr;
 #define FIONREAD_IN_SYS_FILIO_H
 #define USE_STATVFS
 #define STATVFS_IN_SYS_STATVFS_H
+#define INT_MAX_IN_LIMITS_H
 #define STREAM_CONNECTIONS             /* avoid UNIX-domain sockets */
 #define LOCAL_LISTEN   stream_listen
 #define LOCAL_ACCEPT   stream_accept
@@ -318,6 +342,17 @@ extern int opterr;
 #define LOCAL_RECV_FD  stream_recv_fd
 #define HAS_VOLATILE_LOCKS
 #define BROKEN_READ_SELECT_ON_TCP_SOCKET
+#define CANT_WRITE_BEFORE_SENDING_FD
+#ifndef NO_POSIX_REGEXP
+# define HAS_POSIX_REGEXP
+#endif
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAS_SIOCGLIF
+#endif
+#ifndef NO_CLOSEFROM
+# define HAS_CLOSEFROM
+#endif
 
 /*
  * Allow build environment to override paths.
@@ -441,7 +476,10 @@ extern int opterr;
 #ifndef CMSG_LEN
 #define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
 #endif
-
+#ifndef NO_IPV6
+# define HAS_IPV6
+#endif
+#define BROKEN_AI_PASSIVE_NULL_HOST
 #endif
 
 #ifdef AIX4
@@ -590,6 +628,11 @@ extern int initgroups(const char *, int);
 #define SOCKADDR_SIZE  socklen_t
 #define SOCKOPT_SIZE   socklen_t
 #endif
+#ifndef NO_IPV6
+# define HAS_IPV6
+# define HAS_PROCNET_IFINET6
+# define _PATH_PROCNET_IFINET6 "/proc/net/if_inet6"
+#endif
 #include <linux/version.h>
 #if !defined(KERNEL_VERSION) || (LINUX_VERSION_CODE < KERNEL_VERSION(2,2,0)) \
        || (__GLIBC__ < 2)
@@ -1017,6 +1060,25 @@ extern int dup2_pass_on_exec(int oldd, int newd);
 
 #if !defined(USE_STATFS) && !defined(USE_STATVFS)
 #error "define USE_STATFS or USE_STATVFS"
+#endif
+
+ /*
+  * Defaults for systems that pre-date IPv6 support.
+  */
+#ifndef HAS_IPV6
+#define EMULATE_IPV4_ADDRINFO
+#define MISSING_INET_PTON
+#define MISSING_INET_NTOP
+extern const char *inet_ntop(int, const void *, char *, size_t);
+extern int inet_pton(int, const char *, void *);
+
+#endif
+
+ /*
+  * Defaults for all systems.
+  */
+#ifndef DEF_INET_PROTOCOLS
+#define DEF_INET_PROTOCOLS     "ipv4"
 #endif
 
  /*
index 23dd4b4d73f2eae815983e3394b7c400cb3317e6..25f65f721c05fd9ed636afc36237640117fe1bb7 100644 (file)
 /*     const char *addr;
 /*     int     gripe;
 /*
-/*     int     valid_hostliteral(addr, gripe)
+/*     int     valid_ipv4_hostaddr(addr, gripe)
+/*     const char *addr;
+/*     int     gripe;
+/*
+/*     int     valid_ipv6_hostaddr(addr, gripe)
 /*     const char *addr;
 /*     int     gripe;
 /* DESCRIPTION
-/*     valid_hostname() scrutinizes a hostname: the name should be no
-/*     longer than VALID_HOSTNAME_LEN characters, should contain only
-/*     letters, digits, dots and hyphens, no adjacent dots and hyphens,
-/*     no leading or trailing dots or hyphens, no labels longer than
-/*     VALID_LABEL_LEN characters, and no numeric top-level domain.
+/*     valid_hostname() scrutinizes a hostname: the name should
+/*     be no longer than VALID_HOSTNAME_LEN characters, should
+/*     contain only letters, digits, dots and hyphens, no adjacent
+/*     dots and hyphens, no leading or trailing dots or hyphens,
+/*     no labels longer than VALID_LABEL_LEN characters, and it
+/*     should not be all numeric.
 /*
 /*     valid_hostaddr() requires that the input is a valid string
-/*     representation of an internet network address.
+/*     representation of an IPv4 or IPv6 network address as
+/*     described next.
 /*
-/*     valid_hostliteral() requires an address enclosed in [].
+/*     valid_ipv4_hostaddr() and valid_ipv6_hostaddr() implement
+/*     protocol-specific address syntax checks. A valid IPv4
+/*     address is in dotted-quad decimal form. A valid IPv6 address
+/*      has 16-bit hexadecimal fields separated by ":", and does not
+/*      include the RFC 2821 style "IPv6:" prefix.
 /*
 /*     These routines operate silently unless the gripe parameter
 /*     specifies a non-zero value. The macros DO_GRIPE and DONT_GRIPE
 /*     provide suitable constants.
 /* DIAGNOSTICS
-/*     Both functions return zero if they disagree with the input.
+/*     All functions return zero if they disagree with the input.
 /* SEE ALSO
-/*     RFC 952, 1123, RFC 1035
+/*     RFC 952, RFC 1123, RFC 1035, RFC 2373.
 /* LICENSE
 /* .ad
 /* .fi
@@ -109,7 +119,14 @@ int     valid_hostname(const char *name, int gripe)
                    msg_warn("%s: misplaced hyphen: %.100s", myname, name);
                return (0);
            }
-       } else {
+       }
+#ifdef SLOPPY_VALID_HOSTNAME
+       else if (ch == ':' && valid_ipv6_hostaddr(name, DONT_GRIPE)) {
+           non_numeric = 0;
+           break;
+       }
+#endif
+       else {
            if (gripe)
                msg_warn("%s: invalid character %d(decimal): %.100s",
                         myname, ch, name);
@@ -120,7 +137,9 @@ int     valid_hostname(const char *name, int gripe)
     if (non_numeric == 0) {
        if (gripe)
            msg_warn("%s: numeric hostname: %.100s", myname, name);
-       /* NOT: return (0); this confuses users of the DNS client */
+#ifndef SLOPPY_VALID_HOSTNAME
+       return (0);
+#endif
     }
     if (cp - name > VALID_HOSTNAME_LEN) {
        if (gripe)
@@ -131,18 +150,11 @@ int     valid_hostname(const char *name, int gripe)
     return (1);
 }
 
-/* valid_hostaddr - test dotted quad string for correctness */
+/* valid_hostaddr - verify numerical address syntax */
 
 int     valid_hostaddr(const char *addr, int gripe)
 {
-    const char *cp;
-    char   *myname = "valid_hostaddr";
-    int     in_byte = 0;
-    int     byte_count = 0;
-    int     byte_val = 0;
-    int     ch;
-
-#define BYTES_NEEDED   4
+    const char *myname = "valid_hostaddr";
 
     /*
      * Trivial cases first.
@@ -154,20 +166,32 @@ int     valid_hostaddr(const char *addr, int gripe)
     }
 
     /*
-     * Preliminary IPV6 support.
+     * Protocol-dependent processing next.
      */
-    if (strchr(addr, ':')) {
-       if (*(cp = addr + strspn(addr, ":./0123456789abcdefABCDEF")) != 0) {
-           if (gripe)
-               msg_warn("%s: invalid character %d(decimal): %.100s",
-                        myname, *cp, addr);
-           return (0);
-       }
-       return (1);
-    }
+    if (strchr(addr, ':') != 0)
+       return (valid_ipv6_hostaddr(addr, gripe));
+    else
+       return (valid_ipv4_hostaddr(addr, gripe));
+}
+
+/* valid_ipv4_hostaddr - test dotted quad string for correctness */
+
+int     valid_ipv4_hostaddr(const char *addr, int gripe)
+{
+    const char *cp;
+    char   *myname = "valid_ipv4_hostaddr";
+    int     in_byte = 0;
+    int     byte_count = 0;
+    int     byte_val = 0;
+    int     ch;
+
+#define BYTES_NEEDED   4
 
     /*
      * Scary code to avoid sscanf() overflow nasties.
+     * 
+     * This routine is called by valid_ipv6_hostaddr(). It must not call that
+     * routine, to avoid deadly recursion.
      */
     for (cp = addr; (ch = *(unsigned const char *) cp) != 0; cp++) {
        if (ISDIGIT(ch)) {
@@ -189,7 +213,8 @@ int     valid_hostaddr(const char *addr, int gripe)
                    msg_warn("%s: misplaced dot: %.100s", myname, addr);
                return (0);
            }
-           if ((byte_count == 1 && byte_val == 0)) {
+           /* XXX Allow 0.0.0.0 but not 0.1.2.3 */
+           if (byte_count == 1 && byte_val == 0 && addr[strspn(addr, "0.")]) {
                if (gripe)
                    msg_warn("%s: bad initial octet value: %.100s", myname, addr);
                return (0);
@@ -211,37 +236,101 @@ int     valid_hostaddr(const char *addr, int gripe)
     return (1);
 }
 
-/* valid_hostliteral - validate address literal */
+/* valid_ipv6_hostaddr - validate IPv6 address syntax */
 
-int     valid_hostliteral(const char *addr, int gripe)
+int     valid_ipv6_hostaddr(const char *addr, int gripe)
 {
-    const char *myname = "valid_hostliteral";
-    char    buf[100];
-    const char *last;
+    const char *myname = "valid_ipv6_hostaddr";
+    int     null_field = 0;
+    int     field = 0;
+    unsigned char *cp = (unsigned char *) addr;
+    int     len = 0;
 
-    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);
+    /*
+     * FIX 200501 The IPv6 patch validated syntax with getaddrinfo(), but I
+     * am not confident that everyone's system library routines are robust
+     * enough, like buffer overflow free. Remember, the valid_hostmumble()
+     * routines are meant to protect Postfix against malformed information
+     * in data received from the network.
+     * 
+     * We require eight-field hex addresses of the form 0:1:2:3:4:5:6:7,
+     * 0:1:2:3:4:5:6a.6b.7c.7d, or some :: compressed version of the same.
+     * 
+     * Note: the character position is advanced inside the loop. I have added
+     * comments to show why we can't get stuck.
+     */
+    for (;;) {
+       switch (*cp) {
+       case 0:
+           /* Terminate the loop. */
+           if (field < 2) {
+               if (gripe)
+                   msg_warn("%s: too few `:' in IPv6 address: %.100s",
+                            myname, addr);
+               return (0);
+           } else if (len == 0 && null_field != field - 1) {
+               if (gripe)
+                   msg_warn("%s: bad null last field in IPv6 address: %.100s",
+                            myname, addr);
+               return (0);
+           } else
+               return (1);
+       case '.':
+           /* Terminate the loop. */
+           if (field < 2 || field > 6) {
+               if (gripe)
+                   msg_warn("%s: malformed IPv4-in-IPv6 address: %.100s",
+                            myname, addr);
+               return (0);
+           } else
+               /* NOT: valid_hostaddr(). Avoid recursion. */
+               return (valid_ipv4_hostaddr((char *) cp - len, gripe));
+       case ':':
+           /* Advance by exactly 1 character position or terminate. */
+           if (field == 0 && len == 0 && ISALNUM(cp[1])) {
+               if (gripe)
+                   msg_warn("%s: bad null first field in IPv6 address: %.100s",
+                            myname, addr);
+               return (0);
+           }
+           field++;
+           if (field > 7) {
+               if (gripe)
+                   msg_warn("%s: too many `:' in IPv6 address: %.100s",
+                            myname, addr);
+               return (0);
+           }
+           cp++;
+           len = 0;
+           if (*cp == ':') {
+               if (null_field > 0) {
+                   if (gripe)
+                       msg_warn("%s: too many `::' in IPv6 address: %.100s",
+                                myname, addr);
+                   return (0);
+               }
+               null_field = field;
+           } 
+           break;
+       default:
+           /* Advance by at least 1 character position or terminate. */
+           len = strspn(cp, "0123456789abcdefABCDEF");
+           if (len /* - strspn(cp, "0") */ > 4) {
+               if (gripe)
+                   msg_warn("%s: malformed IPv6 address: %.100s",
+                            myname, addr);
+               return (0);
+           }
+           if (len <= 0) {
+               if (gripe)
+                   msg_warn("%s: invalid character %d(decimal) in IPv6 address: %.100s",
+                            myname, *cp, addr);
+               return (0);
+           }
+           cp += len;
+           break;
+       }
     }
-    strncpy(buf, addr + 1, last - addr - 1);
-    buf[last - addr - 1] = 0;
-    return (valid_hostaddr(buf, gripe));
 }
 
 #ifdef TEST
@@ -268,7 +357,6 @@ int     main(int unused_argc, char **argv)
        msg_info("testing: \"%s\"", vstring_str(buffer));
        valid_hostname(vstring_str(buffer), DO_GRIPE);
        valid_hostaddr(vstring_str(buffer), DO_GRIPE);
-       valid_hostliteral(vstring_str(buffer), DO_GRIPE);
     }
     exit(0);
 }
index e66bbc53d7c87f98a7f35fe46e8cdcf6ae1d360d..8860153b595f09f0843e8917dfb06baf50885b61 100644 (file)
@@ -21,7 +21,8 @@
 
 extern int valid_hostname(const char *, int);
 extern int valid_hostaddr(const char *, int);
-extern int valid_hostliteral(const char *, int);
+extern int valid_ipv4_hostaddr(const char *, int);
+extern int valid_ipv6_hostaddr(const char *, int);
 
 /* LICENSE
 /* .ad
index 2eeb6257ab1750bc7b9b9b6c9b34100f11b85929..608c0d110e70d883679e5494c8bfec06a53dd1f4 100644 (file)
@@ -36,10 +36,20 @@ a.bb-.b
 a.b.-bb
 a.b.bb-
 a-a.b-b
-[1.2.3.4]
-[321.255.255.255]
-[1.2.3.4
-[1.2.3.4]foo
-[xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]
-[a:a:a:a:a:a:a:a]
-[g:a:a:a:a:a:a:a]
+:
+::
+:::
+a::
+::a
+::1.2.3.4
+a:a:a:a:a:1.2.3.4
+a:a:a:a:a:a:1.2.3.4
+a:a:a:a:a:a:a:1.2.3.4
+a:a:a:a:a:a:1.2.3.
+a:a:a:a:a:a:1.2.3
+a:a:a:a:a:a:a:a
+a:a:a:a:a:a:a:a:a
+g:a:a:a:a:a:a:a
+a::b
+:a::b
+a::b:
index 0c3cab0ce523fd1583f2fd409e92a2f553a76fca..08b23b8ce043fc0919f9d2e3c96682ef9c157bdb 100644 (file)
 ./valid_hostname: testing: "123456789012345678901234567890123456789012345678901234567890123"
 ./valid_hostname: warning: valid_hostname: numeric hostname: 123456789012345678901234567890123456789012345678901234567890123
-./valid_hostname: warning: valid_hostaddr: invalid octet value: 123456789012345678901234567890123456789012345678901234567890123
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: 123456789012345678901234567890123456789012345678901234567890123
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet value: 123456789012345678901234567890123456789012345678901234567890123
 ./valid_hostname: testing: "1234567890123456789012345678901234567890123456789012345678901234"
 ./valid_hostname: warning: valid_hostname: hostname label too long: 1234567890123456789012345678901234567890123456789012345678901234
-./valid_hostname: warning: valid_hostaddr: invalid octet value: 1234567890123456789012345678901234567890123456789012345678901234
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1234567890123456789012345678901234567890123456789012345678901234
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet value: 1234567890123456789012345678901234567890123456789012345678901234
 ./valid_hostname: testing: "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: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.123456789012345678901234567890123456789012345678901234567890123.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.1234567890123456789012345678901234567890123456789012345678901234.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.1234567890123456789012345678901234567890123456789012345678901234.b
 ./valid_hostname: testing: "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: 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_hostliteral: '[' expected at start: 321.255.255.255
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet value: 321.255.255.255
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: 0.0.0.0
 ./valid_hostname: testing: "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: 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_hostliteral: '[' expected at start: 0.255.255.255
+./valid_hostname: warning: valid_ipv4_hostaddr: bad initial octet value: 0.255.255.255
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: 1.2.3.321
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet value: 1.2.3.321
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: 1.2.3
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet count: 1.2.3
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: 1.2.3.4.5
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet count: 1.2.3.4.5
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: 1..2.3.4
+./valid_hostname: warning: valid_ipv4_hostaddr: misplaced dot: 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_hostaddr: misplaced dot: .1.2.3.4
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: .1.2.3.4
+./valid_hostname: warning: valid_ipv4_hostaddr: misplaced dot: .1.2.3.4
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: 1.2.3.4.5.
+./valid_hostname: warning: valid_ipv4_hostaddr: misplaced dot: 1.2.3.4.5.
 ./valid_hostname: testing: "1"
 ./valid_hostname: warning: valid_hostname: numeric hostname: 1
-./valid_hostname: warning: valid_hostaddr: invalid octet count: 1
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: 1
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet count: 1
 ./valid_hostname: testing: "."
 ./valid_hostname: warning: valid_hostname: misplaced delimiter: .
-./valid_hostname: warning: valid_hostaddr: misplaced dot: .
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: .
+./valid_hostname: warning: valid_ipv4_hostaddr: misplaced dot: .
 ./valid_hostname: testing: ""
 ./valid_hostname: warning: valid_hostname: empty hostname
 ./valid_hostname: warning: valid_hostaddr: empty address
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: 
 ./valid_hostname: testing: "321"
 ./valid_hostname: warning: valid_hostname: numeric hostname: 321
-./valid_hostname: warning: valid_hostaddr: invalid octet value: 321
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: 321
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet value: 321
 ./valid_hostname: testing: "f"
-./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): f
-./valid_hostname: warning: valid_hostliteral: '[' expected at start: f
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 102(decimal): f
 ./valid_hostname: testing: "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: warning: valid_ipv4_hostaddr: invalid character 102(decimal): f.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_hostliteral: '[' expected at start: 1f.2.3.4
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 102(decimal): 1f.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_hostliteral: '[' expected at start: f1.2.3.4
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 102(decimal): f1.2.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_hostliteral: '[' expected at start: 1.2f.3.4
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 102(decimal): 1.2f.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_hostliteral: '[' expected at start: 1.f2.3.4
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 102(decimal): 1.f2.3.4
 ./valid_hostname: testing: "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: warning: valid_ipv4_hostaddr: invalid character 102(decimal): 1.2.3.4f
 ./valid_hostname: testing: "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: warning: valid_ipv4_hostaddr: invalid character 102(decimal): 1.2.3.f4
 ./valid_hostname: testing: "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: warning: valid_ipv4_hostaddr: invalid character 102(decimal): 1.2.3.f
 ./valid_hostname: testing: "-.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_hostliteral: '[' expected at start: -.a.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 45(decimal): -.a.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.-.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.-.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.b.-
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.b.-
 ./valid_hostname: testing: "-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_hostliteral: '[' expected at start: -aa.b.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 45(decimal): -aa.b.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: aa-.b.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): aa-.b.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.-bb.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.-bb.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.bb-.b
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.bb-.b
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.b.-bb
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.b.-bb
 ./valid_hostname: testing: "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_hostliteral: '[' expected at start: a.b.bb-
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a.b.bb-
 ./valid_hostname: testing: "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
-./valid_hostname: testing: "[a:a:a:a:a:a:a:a]"
-./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [a:a:a:a:a:a:a:a]
-./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [a:a:a:a:a:a:a:a]
-./valid_hostname: testing: "[g:a:a:a:a:a:a:a]"
-./valid_hostname: warning: valid_hostname: invalid character 91(decimal): [g:a:a:a:a:a:a:a]
-./valid_hostname: warning: valid_hostaddr: invalid character 91(decimal): [g:a:a:a:a:a:a:a]
-./valid_hostname: warning: valid_hostaddr: invalid character 103(decimal): g:a:a:a:a:a:a:a
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid character 97(decimal): a-a.b-b
+./valid_hostname: testing: ":"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): :
+./valid_hostname: warning: valid_ipv6_hostaddr: too few `:' in IPv6 address: :
+./valid_hostname: testing: "::"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): ::
+./valid_hostname: testing: ":::"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): :::
+./valid_hostname: warning: valid_ipv6_hostaddr: too many `::' in IPv6 address: :::
+./valid_hostname: testing: "a::"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a::
+./valid_hostname: testing: "::a"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): ::a
+./valid_hostname: testing: "::1.2.3.4"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): ::1.2.3.4
+./valid_hostname: testing: "a:a:a:a:a:1.2.3.4"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:1.2.3.4
+./valid_hostname: testing: "a:a:a:a:a:a:1.2.3.4"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:a:1.2.3.4
+./valid_hostname: testing: "a:a:a:a:a:a:a:1.2.3.4"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:a:a:1.2.3.4
+./valid_hostname: warning: valid_ipv6_hostaddr: malformed IPv4-in-IPv6 address: a:a:a:a:a:a:a:1.2.3.4
+./valid_hostname: testing: "a:a:a:a:a:a:1.2.3."
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:a:1.2.3.
+./valid_hostname: warning: valid_ipv4_hostaddr: misplaced dot: 1.2.3.
+./valid_hostname: testing: "a:a:a:a:a:a:1.2.3"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:a:1.2.3
+./valid_hostname: warning: valid_ipv4_hostaddr: invalid octet count: 1.2.3
+./valid_hostname: testing: "a:a:a:a:a:a:a:a"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:a:a:a
+./valid_hostname: testing: "a:a:a:a:a:a:a:a:a"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a:a:a:a:a:a:a:a:a
+./valid_hostname: warning: valid_ipv6_hostaddr: too many `:' in IPv6 address: a:a:a:a:a:a:a:a:a
+./valid_hostname: testing: "g:a:a:a:a:a:a:a"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): g:a:a:a:a:a:a:a
+./valid_hostname: warning: valid_ipv6_hostaddr: invalid character 103(decimal) in IPv6 address: g:a:a:a:a:a:a:a
+./valid_hostname: testing: "a::b"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a::b
+./valid_hostname: testing: ":a::b"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): :a::b
+./valid_hostname: warning: valid_ipv6_hostaddr: bad null first field in IPv6 address: :a::b
+./valid_hostname: testing: "a::b:"
+./valid_hostname: warning: valid_hostname: invalid character 58(decimal): a::b:
+./valid_hostname: warning: valid_ipv6_hostaddr: bad null last field in IPv6 address: a::b:
index ff926dd813aed762e4f6e533f10f82b8adfdeabb..53d36601710d9cdb617ae51e66b68d3bbc40e6e9 100644 (file)
@@ -515,7 +515,7 @@ VSTRING *vstring_vsprintf_append(VSTRING *vp, const char *format, va_list ap)
   */
 #include <stdio.h>
 
-main(int argc, char **argv)
+int     main(int argc, char **argv)
 {
     VSTRING *vp = vstring_alloc(1);
 
index 2f644bf1dc7f994310a49c280dac302ffe942031..e19fd382255877ce43a2c64c466f4001c9a93526 100644 (file)
@@ -184,7 +184,7 @@ int     vstring_get_null_bound(VSTRING *vp, VSTREAM *fp, int bound)
 
 #define TEXT_VSTREAM    "vstring_vstream.c"
 
-main(void)
+int     main(void)
 {
     VSTRING *vp = vstring_alloc(1);
     VSTREAM *fp;
index f0d2bb3665a4b02df9c20aff060643422a256795..1c0c088cc7263ae9b410d540b8e3847111d69134 100644 (file)
@@ -233,7 +233,7 @@ void    watchdog_pat(void)
 
 #include <vstream.h>
 
-main(int unused_argc, char **unused_argv)
+int     main(int unused_argc, char **unused_argv)
 {
     WATCHDOG *wp;
 
index 1748ec7086c051581d73834209b8f0dc64bc9c51..53d86a81c235745a4b5d80c8dbfa140a793f21b5 100644 (file)
@@ -16,7 +16,7 @@ $(PROG): $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs && cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)
 
index 7573422aaea2b1d0094f54180251365208c1203e..6101d964de5fe7ec061383c4f5c782dc04ff949f 100644 (file)
 #include <dict_ht.h>
 #include <dict.h>
 #include <split_at.h>
+#include <stringops.h>
 
 /* Global library. */
 
@@ -305,6 +306,8 @@ static void verify_update_service(VSTREAM *client_stream)
                  ATTR_TYPE_NUM, MAIL_ATTR_ADDR_STATUS, &addr_status,
                  ATTR_TYPE_STR, MAIL_ATTR_WHY, text,
                  ATTR_TYPE_END) == 3) {
+       /* FIX 200501 IPv6 patch did not neuter ":" in address literals. */
+       translit(STR(addr), ":", "_");
        if ((status_name = verify_stat2name(addr_status)) == 0) {
            msg_warn("bad recipient status %d for recipient %s",
                     addr_status, STR(addr));
@@ -394,6 +397,8 @@ static void verify_query_service(VSTREAM *client_stream)
     (addr_status != DEL_RCPT_STAT_OK && updated + var_verify_neg_exp < now)
 #define PROBE_TTL      1000
 
+       /* FIX 200501 IPv6 patch did not neuter ":" in address literals. */
+       translit(STR(addr), ":", "_");
        if ((raw_data = dict_get(verify_map, STR(addr))) == 0   /* not found */
            || ((get_buf = vstring_alloc(10)),
                vstring_strcpy(get_buf, raw_data),      /* malformed */
index 3389ce566ae5fde70047506fc96b3e9b926bfcbd..60c562e72c5d0f89c2fba55ac7bf88be267974b1 100644 (file)
@@ -16,7 +16,7 @@ $(PROG):      $(OBJS) $(LIBS)
        $(CC) $(CFLAGS) -o $@ $(OBJS) $(LIBS) $(SYSLIBS)
 
 Makefile: Makefile.in
-       (set -e; echo "# DO NOT EDIT"; $(OPTS) $(SHELL) ../../makedefs; cat $?) >$@
+       (echo "# DO NOT EDIT"; tail +2 ../../conf/makedefs.out; cat $?) >$@
 
 test:  $(TESTPROG)