]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.8-20230314
authorWietse Venema <wietse@porcupine.org>
Tue, 14 Mar 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sat, 18 Mar 2023 03:45:31 +0000 (23:45 -0400)
28 files changed:
postfix/.indent.pro
postfix/HISTORY
postfix/html/postconf.5.html
postfix/html/smtpd.8.html
postfix/man/man5/postconf.5
postfix/man/man8/smtpd.8
postfix/proto/postconf.proto
postfix/proto/stop.double-cc
postfix/proto/stop.double-history
postfix/proto/stop.spell-cc
postfix/proto/stop.spell-history
postfix/src/global/mail_params.h
postfix/src/global/mail_version.h
postfix/src/global/map_search.c
postfix/src/global/map_search.ref
postfix/src/global/maps.ref
postfix/src/smtpd/Makefile.in
postfix/src/smtpd/smtpd.c
postfix/src/smtpd/smtpd_check.c
postfix/src/smtpd/smtpd_peer.c
postfix/src/smtpd/smtpd_server.in
postfix/src/smtpd/smtpd_server.ref
postfix/src/util/Makefile.in
postfix/src/util/inet_addr_sizes.c [new file with mode: 0644]
postfix/src/util/inet_addr_sizes.h [new file with mode: 0644]
postfix/src/util/inet_prefix_top.c [new file with mode: 0644]
postfix/src/util/inet_prefix_top.h [moved from postfix/src/util/net_mask_top.h with 60% similarity]
postfix/src/util/net_mask_top.c [deleted file]

index 1f8431f0d3b8098a134d56ce47a5949101dad029..4ba45d081a72433fe3cfc24cf5b513dba2706927 100644 (file)
@@ -20,7 +20,6 @@
 -TBH_TABLE
 -TBINATTR
 -TBINATTR_INFO
--Tbind_props
 -TBINHASH
 -TBINHASH_INFO
 -TBIO
 -TBYTE_MASK
 -TCFG_PARSER
 -TCIDR_MATCH
--Tcipher_probe_t
 -TCLEANUP_REGION
--TCLEANUP_STAT_DETAIL
 -TCLEANUP_STATE
+-TCLEANUP_STAT_DETAIL
 -TCLIENT_LIST
 -TCLNT_STREAM
 -TCONFIG_BOOL_FN_TABLE
 -TCRYPTO_EX_DATA
 -TCTABLE
 -TCTABLE_ENTRY
--Td2i_X509_t
--Tdane_digest
--Tdane_mtype
 -TDB_COMMON_CTX
--TDELIVER_ATTR
 -TDELIVERED_HDR_INFO
+-TDELIVER_ATTR
 -TDELIVER_REQUEST
 -TDELTA_TIME
 -TDICT
 -TEVP_PKEY
 -TEXPAND_ATTR
 -TFILE
--Tfilter_ctx
 -TFORWARD_INFO
--Tgeneral_name_stack_t
 -THBC_ACTION_CALL_BACKS
 -THBC_CALL_BACKS
 -THBC_CHECKS
 -THOST
 -THTABLE
 -THTABLE_INFO
--Tiana_digest
 -TINET_ADDR_LIST
+-TINET_ADDR_SIZES
 -TINET_PROTO_INFO
 -TINSTANCE
 -TINST_SELECTION
 -TINT32_TYPE
--TINT_TABLE
 -TINTV
+-TINT_TABLE
 -TJMP_BUF_WRAPPER
 -TLDAP
--TLDAP_CONN
 -TLDAPMessage
 -TLDAPURLDesc
+-TLDAP_CONN
 -TLIB_DP
 -TLIB_FN
 -TLMTP_ATTR
 -TMAC_EXP_OP_INFO
 -TMAC_HEAD
 -TMAC_PARSE
--TMAI_HOSTADDR_STR
--TMAI_HOSTNAME_STR
 -TMAIL_ADDR_FORMATTER
 -TMAIL_ADDR_MAP_TEST
 -TMAIL_PRINT
 -TMAIL_SCAN
 -TMAIL_STREAM
 -TMAIL_VERSION
+-TMAI_HOSTADDR_STR
+-TMAI_HOSTNAME_STR
 -TMAI_SERVNAME_STR
 -TMAI_SERVPORT_STR
 -TMAPS
 -TMDB_val
 -TMILTER
 -TMILTER8
+-TMILTERS
 -TMILTER_MACROS
 -TMILTER_MSG_CONTEXT
--TMILTERS
 -TMIME_ENCODING
 -TMIME_INFO
 -TMIME_STACK
 -TNAME_MASK
 -TNBBIO
 -TNVTABLE_INFO
--Toff_t
 -TOPTIONS
 -TPCF_DBMS_INFO
 -TPCF_EVAL_CTX
 -TPCF_SERVICE_PATTERN
 -TPCF_STRING_NV
 -TPEER_NAME
--Tpem_load_state_t
 -TPGSQL_NAME
 -TPICKUP_INFO
 -TPIPE_ATTR
 -TPIPE_STATE
 -TPLMYSQL
 -TPLPGSQL
+-TPOSTMAP_KEY_STATE
 -TPOST_MAIL_FCLOSE_STATE
 -TPOST_MAIL_STATE
--TPOSTMAP_KEY_STATE
 -TPRIVATE_STR_TABLE
 -TPSC_CALL_BACK_ENTRY
 -TPSC_CLIENT_INFO
 -TRECIPIENT
 -TRECIPIENT_LIST
 -TREC_TYPE_NAME
--Tregex_t
--Tregmatch_t
--TRES_CONTEXT
 -TRESOLVE_REPLY
 -TRESPONSE
 -TREST_TABLE
+-TRES_CONTEXT
 -TRWR_CONTEXT
--Tsasl_conn_t
--Tsasl_secret_t
 -TSCACHE
 -TSCACHE_CLNT
 -TSCACHE_MULTI
 -TSENDER_LOGIN_MATCH
 -TSERVER_AC
 -TSESSION
--Tsfsistat
 -TSHARED_PATH
--Tsigset_t
 -TSINGLE_SERVER
 -TSINK_COMMAND
 -TSINK_STATE
--Tsize_t
 -TSLMDB
 -TSMFICTX
--TSM_STATE
--TSMTP_ADDR
--TSMTP_CLI_ATTR
--TSMTP_CMD
 -TSMTPD_CMD
 -TSMTPD_DEFER
 -TSMTPD_ENDPT_LOOKUP_INFO
 -TSMTPD_STATE
 -TSMTPD_TOKEN
 -TSMTPD_XFORWARD_ATTR
+-TSMTP_ADDR
+-TSMTP_CLI_ATTR
+-TSMTP_CMD
 -TSMTP_ITERATOR
 -TSMTP_RESP
 -TSMTP_SASL_AUTH_CACHE
 -TSMTP_TLS_POLICY
 -TSMTP_TLS_SESS
 -TSMTP_TLS_SITE_POLICY
--Tsockaddr
+-TSM_STATE
 -TSOCKADDR_SIZE
 -TSPAWN_ATTR
--Tssize_t
 -TSSL
--Tssl_cipher_stack_t
--Tssl_comp_stack_t
 -TSSL_CTX
 -TSSL_SESSION
 -TSTATE
 -TSTRING_TABLE
 -TSYS_EXITS_DETAIL
 -TTEST_CASE
--Ttime_t
--Ttlsa_filter
+-TTLSMGR_SCACHE
+-TTLSP_STATE
 -TTLS_APPL_STATE
 -TTLS_CERTS
 -TTLS_CLIENT_INIT_PROPS
 -TTLS_CLIENT_PARAMS
 -TTLS_CLIENT_START_PROPS
--TTLScontext_t
 -TTLS_DANE
--TTLSMGR_SCACHE
 -TTLS_PKEYS
 -TTLS_PRNG_SEED_INFO
 -TTLS_PRNG_SRC
--TTLSP_STATE
 -TTLS_ROLE
 -TTLS_SCACHE
 -TTLS_SCACHE_ENTRY
 -TTLS_TLSA
 -TTLS_USAGE
 -TTLS_VINFO
+-TTLScontext_t
 -TTOK822
 -TTRANSPORT_INFO
 -TTRIGGER_SERVER
--Tuint16_t
--Tuint32_t
--Tuint8_t
 -TUSER_ATTR
 -TVBUF
 -TVSTREAM
 -TWATCHDOG
 -TWATCH_FD
 -TX509
+-TX509V3_CTX
 -TX509_EXTENSION
 -TX509_NAME
--Tx509_stack_t
 -TX509_STORE_CTX
--TX509V3_CTX
 -TXSASL_CLIENT
 -TXSASL_CLIENT_CREATE_ARGS
 -TXSASL_CLIENT_IMPL
 -TXSASL_SERVER_CREATE_ARGS
 -TXSASL_SERVER_IMPL
 -TXSASL_SERVER_IMPL_INFO
+-Tbind_props
+-Tcipher_probe_t
+-Td2i_X509_t
+-Tdane_digest
+-Tdane_mtype
+-Tfilter_ctx
+-Tgeneral_name_stack_t
+-Tiana_digest
+-Toff_t
+-Tpem_load_state_t
+-Tregex_t
+-Tregmatch_t
+-Tsasl_conn_t
+-Tsasl_secret_t
+-Tsfsistat
+-Tsigset_t
+-Tsize_t
+-Tsockaddr
+-Tsockaddr_storage
+-Tssize_t
+-Tssl_cipher_stack_t
+-Tssl_comp_stack_t
+-Ttime_t
+-Ttlsa_filter
+-Tuint16_t
+-Tuint32_t
+-Tuint8_t
+-Tx509_stack_t
index 245645be378634c38cf1ce6f80dd371a0402fa6c..7aeaffb7028466538febb57e23e3c3c5e86610df 100644 (file)
@@ -26947,5 +26947,31 @@ Apologies for any names omitted.
        (default 32, no aggregation) and smtpd_client_ipv6_prefix_length
        (default 72, aggregation by /72 network blocks). The latter
        raises the bar for a memory exhaustion attack. Files:
-       util/net_mask_top.[hc], smtpd/smtpd.c, smtpd/smtpd_peer.c,
+       util/inet_prefix_top.[hc], smtpd/smtpd.c, smtpd/smtpd_peer.c,
        mantools/postlink, proto/postconf.proto.
+
+20230313
+
+       Factored out a function that may be generally useful, and
+       made a vstring_alloc() argument more precise to avoid memory
+       reallocation. Files: util/inet_prefix_top.c,
+       util/inet_addr_sizes.[hc].
+
+20230314
+
+       Bugfix (introduced: Postfix 3.5): check_ccert_access did
+       not parse inline map specifications. Report and fix by
+       Sean Gallagher. File: global/map_search.c.
+
+       Cleanup: don't do smtpd_client_*_rate and smtpd_client_*_count
+       address range computations when "/usr/sbin/sendmail -bs"
+       is not talking to a network client. File: smtpd/smtpd_peer.c.
+
+       Cleanup: renamed net_mask_top.* to inet_prefix_top.*.
+
+       Cleanup: updated unit tests. Files: smtpd/smtod_check.c,
+       smtpd/smtpd_server.in, smtpd/smtpd_server.ref.
+
+       Increased the smtpd_client_ipv6_prefix_length to 84 bits,
+       which should prevent anvil exhaustion attacks from a typical
+       /64 consumer network, without penalizing legitimate usage.
index 10816cb9aaea08350873d811cebb95b596f14b82..848b306854b23870e92f0eb282315f8f45dc73c4 100644 (file)
@@ -14646,8 +14646,8 @@ This feature is available in Postfix 2.2 and later.
 
 <p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv4 network blocks with the specified network prefix. Aggregation
-reduces the <a href="anvil.8.html">anvil(8)</a> resources needed to maintain counters. By
-default, aggregation is disabled for IPv4. </p>
+uses fewer <a href="anvil.8.html">anvil(8)</a> resources to maintain counters. By default,
+aggregation is disabled for IPv4. </p>
 
 <p> This feature is available in Postfix 3.8 and later. </p>
 
@@ -14655,13 +14655,12 @@ default, aggregation is disabled for IPv4. </p>
 </DD>
 
 <DT><b><a name="smtpd_client_ipv6_prefix_length">smtpd_client_ipv6_prefix_length</a>
-(default: 72)</b></DT><DD>
+(default: 84)</b></DT><DD>
 
 <p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv6 network blocks with the specified network prefix. Aggregation
-reduces the <a href="anvil.8.html">anvil(8)</a> resources needed to maintain counters. By
-default, aggregation is enabled for IPv6.
-</p>
+uses fewer the <a href="anvil.8.html">anvil(8)</a> resources to maintain counters. By default,
+aggregation is enabled for IPv6.  </p>
 
 <p> This feature is available in Postfix 3.8 and later. </p>
 
index ecf775cf891c895fa16e7b93763bae89c5846f1b..b7ec136c36b89906c35c2040f4a3adcb5755b84d 100644 (file)
@@ -968,7 +968,7 @@ SMTPD(8)                                                              SMTPD(8)
               Aggregate smtpd_client_*_count and  smtpd_client_*_rate  statis-
               tics by IPv4 network blocks with the specified network prefix.
 
-       <b><a href="postconf.5.html#smtpd_client_ipv6_prefix_length">smtpd_client_ipv6_prefix_length</a> (72)</b>
+       <b><a href="postconf.5.html#smtpd_client_ipv6_prefix_length">smtpd_client_ipv6_prefix_length</a> (84)</b>
               Aggregate  smtpd_client_*_count  and smtpd_client_*_rate statis-
               tics by IPv6 network blocks with the specified network prefix.
 
index 2d84788ba46cd60b88293430f63d9e60169c19ef..45b36382419c866c9bd99c30b6011cc45b36afb2 100644 (file)
@@ -9959,15 +9959,15 @@ This feature is available in Postfix 2.2 and later.
 .SH smtpd_client_ipv4_prefix_length (default: 32)
 Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv4 network blocks with the specified network prefix. Aggregation
-reduces the \fBanvil\fR(8) resources needed to maintain counters. By
-default, aggregation is disabled for IPv4.
+uses fewer \fBanvil\fR(8) resources to maintain counters. By default,
+aggregation is disabled for IPv4.
 .PP
 This feature is available in Postfix 3.8 and later.
-.SH smtpd_client_ipv6_prefix_length (default: 72)
+.SH smtpd_client_ipv6_prefix_length (default: 84)
 Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv6 network blocks with the specified network prefix. Aggregation
-reduces the \fBanvil\fR(8) resources needed to maintain counters. By
-default, aggregation is enabled for IPv6.
+uses fewer the \fBanvil\fR(8) resources to maintain counters. By default,
+aggregation is enabled for IPv6.
 .PP
 This feature is available in Postfix 3.8 and later.
 .SH smtpd_client_message_rate_limit (default: 0)
index 3062953e3c80e25661320e167e5c2a0bd458bd92..7519c53b4750824c25f22da307031ece214d6cf3 100644 (file)
@@ -846,7 +846,7 @@ Available in Postfix version 3.8 and later:
 .IP "\fBsmtpd_client_ipv4_prefix_length (32)\fR"
 Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv4 network blocks with the specified network prefix.
-.IP "\fBsmtpd_client_ipv6_prefix_length (72)\fR"
+.IP "\fBsmtpd_client_ipv6_prefix_length (84)\fR"
 Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv6 network blocks with the specified network prefix.
 .SH "TARPIT CONTROLS"
index d661dda65b21c5d3eaf5cc726fa6a3cf00da39fd..dffeab87f354b099dfc8d7161c6963b544d3f92a 100644 (file)
@@ -18603,17 +18603,16 @@ to MX or IP address lookup as if SRV record lookup was not enabled. <p>
 
 <p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv4 network blocks with the specified network prefix. Aggregation
-reduces the anvil(8) resources needed to maintain counters. By
-default, aggregation is disabled for IPv4. </p>
+uses fewer anvil(8) resources to maintain counters. By default,
+aggregation is disabled for IPv4. </p>
 
 <p> This feature is available in Postfix 3.8 and later. </p>
 
-%PARAM smtpd_client_ipv6_prefix_length 72
+%PARAM smtpd_client_ipv6_prefix_length 84
 
 <p> Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 by IPv6 network blocks with the specified network prefix. Aggregation
-reduces the anvil(8) resources needed to maintain counters. By
-default, aggregation is enabled for IPv6.
-</p>
+uses fewer the anvil(8) resources to maintain counters. By default,
+aggregation is enabled for IPv6.  </p>
 
 <p> This feature is available in Postfix 3.8 and later. </p>
index 09a32d8748d0572fb3f43a5059571c9a1590d2aa..8efd133ee306395bba269298ce58fde427741e02 100644 (file)
@@ -332,3 +332,4 @@ void  void cleanup_milter_receive state count
  struct DICT open const char int int dict_xx_open 
  Available in in Postfix version 2 3 3 7 
 length  length of 0 31 0 127 
+address  address string length 
index ff1eceaf41e39eddcd5f1c6df280e305c0c4c112..18511878d18004a5d24ac2ccf44f2277d8bd1240 100644 (file)
@@ -36,3 +36,4 @@ proto  proto SASL_README html proto SQLITE_README html
  postfix postfix c postlog postlog c 
  postfix postfix c postlog postlog c 
  util net_mask_top hc smtpd smtpd c smtpd smtpd_peer c 
+ util inet_prefix_top hc smtpd smtpd c smtpd smtpd_peer c 
index ec3df3008b8da23c48118e0ec0915ad488d0bde7..c642c7a32e0cacb2f2d14d55b22a61bd92bc0310 100644 (file)
@@ -1796,3 +1796,7 @@ nopref
 ADDRP
 iffalse
 iftrue
+Stringify
+bitcount
+bytecount
+ipproto
index 9cca6240f3d0fbdc4d48720ad6de9caa6a5c07c6..c248a4c8c3d00fb233eb1574d55881959c42f621 100644 (file)
@@ -49,3 +49,6 @@ css
 makemanidx
 soho
 soho
+Aleksandr
+Stankevic
+Gallagher
index d83c9eb506f80457cfb9339ecb0a7fb8b775604e..7c80add97414097d6e5a8645c75ed8eb27f4d488 100644 (file)
@@ -3204,7 +3204,7 @@ extern int var_smtpd_cauth_limit;
 extern int var_smtpd_cipv4_prefix;
 
 #define VAR_SMTPD_CIPV6_PREFIX         "smtpd_client_ipv6_prefix_length"
-#define DEF_SMTPD_CIPV6_PREFIX         72
+#define DEF_SMTPD_CIPV6_PREFIX         84
 #define MAX_SMTPD_CIPV6_PREFIX         128
 extern int var_smtpd_cipv6_prefix;
 
index e07da42337537bafa98a54024a000cf44aee0dd1..5c8aaba43f73362592fef32d9ac2b42e7a3bf779 100644 (file)
@@ -20,7 +20,7 @@
   * Patches change both the patchlevel and the release date. Snapshots have no
   * patchlevel; they change the release date only.
   */
-#define MAIL_RELEASE_DATE      "20230312"
+#define MAIL_RELEASE_DATE      "20230314"
 #define MAIL_VERSION_NUMBER    "3.8"
 
 #ifdef SNAPSHOT
index be4b42b33e9a3c70bc7c49efc19ff570335b3968..b10f7d516829f802527ecf4f46ec627702d34b83 100644 (file)
@@ -158,7 +158,8 @@ const MAP_SEARCH *map_search_create(const char *map_spec)
        if ((heap_err = extpar(&bp, CHARS_BRACE, EXTPAR_FLAG_STRIP)) != 0) {
            msg_warn("malformed map specification: '%s'", heap_err);
            MAP_SEARCH_CREATE_RETURN(0);
-       } else if ((map_type_name = mystrtok(&bp, CHARS_COMMA_SP)) == 0) {
+       } else if ((map_type_name = mystrtokq(&bp, CHARS_COMMA_SP,
+                                             CHARS_BRACE)) == 0) {
            msg_warn("empty map specification: '%s'", map_spec);
            MAP_SEARCH_CREATE_RETURN(0);
        }
@@ -308,6 +309,7 @@ int     main(int argc, char **argv)
        {"{type:name {search_order=one, two}}", 1, "type:name", "\01\02"},
        {"{type:name {search_order=one, two, bad}}", 0, 0, 0},
        {"{inline:{a=b} {search_order=one, two}}", 1, "inline:{a=b}", "\01\02"},
+       {"{inline:{a=b, c=d} {search_order=one, two}}", 1, "inline:{a=b, c=d}", "\01\02"},
        {0},
     };
     TEST_CASE *test_case;
index f072f253e50adf37d55dd203b697ffcfa22c839c..a296e4e4a7f5b1fc301868e4b6a3b9d906ed46cd 100644 (file)
@@ -19,3 +19,4 @@ unknown: test case 9: '{type:name {search_order=one, two}}'
 unknown: test case 10: '{type:name {search_order=one, two, bad}}'
 unknown: warning: unknown search type 'bad' in '{type:name {search_order=one, two, bad}}'
 unknown: test case 11: '{inline:{a=b} {search_order=one, two}}'
+unknown: test case 12: '{inline:{a=b, c=d} {search_order=one, two}}'
index 84033c7d848efdddc0fa85331899092c0233b744..2d3ad20ee6499edb5f82e25ae29c335c1ace23e1 100644 (file)
@@ -1,3 +1,4 @@
+unknown: dict_open_lookup: fail
 unknown: dict_open: fail:1maps
 unknown: dict_register: fail:1maps(0,lock) 1
 "": not found
index 422cbac5a7fac37a78c88ae03dfbc2861229ee95..7fdfe1286be7f1c581d93128357fd46df4da6f91 100644 (file)
@@ -481,6 +481,7 @@ smtpd_peer.o: ../../include/check_arg.h
 smtpd_peer.o: ../../include/dns.h
 smtpd_peer.o: ../../include/haproxy_srvr.h
 smtpd_peer.o: ../../include/htable.h
+smtpd_peer.o: ../../include/inet_prefix_top.h
 smtpd_peer.o: ../../include/inet_proto.h
 smtpd_peer.o: ../../include/iostuff.h
 smtpd_peer.o: ../../include/mail_params.h
@@ -492,7 +493,6 @@ smtpd_peer.o: ../../include/myaddrinfo.h
 smtpd_peer.o: ../../include/mymalloc.h
 smtpd_peer.o: ../../include/name_code.h
 smtpd_peer.o: ../../include/name_mask.h
-smtpd_peer.o: ../../include/net_mask_top.h
 smtpd_peer.o: ../../include/nvtable.h
 smtpd_peer.o: ../../include/sock_addr.h
 smtpd_peer.o: ../../include/split_at.h
index 7580629a0458bef1e7f9311ab8eaa3c0ac820d3f..2276e65f6d026ce9921e79fdfb3729a505abf2fe 100644 (file)
 /* .IP "\fBsmtpd_client_ipv4_prefix_length (32)\fR"
 /*     Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 /*     by IPv4 network blocks with the specified network prefix.
-/* .IP "\fBsmtpd_client_ipv6_prefix_length (72)\fR"
+/* .IP "\fBsmtpd_client_ipv6_prefix_length (84)\fR"
 /*     Aggregate smtpd_client_*_count and smtpd_client_*_rate statistics
 /*     by IPv6 network blocks with the specified network prefix.
 /* TARPIT CONTROLS
index b6a2aced680235f58384ce223dbb1560474665b5..b5ce4a94fc9834d86a12311e3b68b396e7fd7e8e 100644 (file)
@@ -5810,6 +5810,8 @@ bool    var_smtpd_peername_lookup;
 bool    var_smtpd_client_port_log;
 char   *var_smtpd_dns_re_filter;
 bool    var_smtpd_tls_ask_ccert;
+int     var_smtpd_cipv4_prefix;
+int     var_smtpd_cipv6_prefix;
 
 #define int_table test_int_table
 
@@ -5845,6 +5847,8 @@ static const INT_TABLE int_table[] = {
     VAR_SMTPD_PEERNAME_LOOKUP, DEF_SMTPD_PEERNAME_LOOKUP, &var_smtpd_peername_lookup,
     VAR_SMTPD_CLIENT_PORT_LOG, DEF_SMTPD_CLIENT_PORT_LOG, &var_smtpd_client_port_log,
     VAR_SMTPD_TLS_ACERT, DEF_SMTPD_TLS_ACERT, &var_smtpd_tls_ask_ccert,
+    VAR_SMTPD_CIPV4_PREFIX, DEF_SMTPD_CIPV4_PREFIX, &var_smtpd_cipv4_prefix,
+    VAR_SMTPD_CIPV6_PREFIX, DEF_SMTPD_CIPV6_PREFIX, &var_smtpd_cipv6_prefix,
     0,
 };
 
index f212035440b6042fd0e66cf812247c27082d7f36..838af9cb9f8697d5ec30dc074eb741667cb52cbe 100644 (file)
 #include <sock_addr.h>
 #include <inet_proto.h>
 #include <split_at.h>
-#include <net_mask_top.h>
+#include <inet_prefix_top.h>
 
 /* Global library. */
 
@@ -641,13 +641,16 @@ void    smtpd_peer_init(SMTPD_STATE *state)
 
     /*
      * Generate 'address' or 'net/mask' index for anvil event aggregation.
+     * Don't do this for non-socket input. See smtpd_peer_not_inet().
      */
-    af = SOCK_ADDR_FAMILY(&(state->sockaddr));
-    state->anvil_range = net_mask_top(af,
-                                     SOCK_ADDR_ADDRP(&(state->sockaddr)),
-                                     af == AF_INET ?
-                                     var_smtpd_cipv4_prefix :
-                                     var_smtpd_cipv6_prefix);
+    if (state->addr_family != AF_UNSPEC) {
+       af = SOCK_ADDR_FAMILY(&(state->sockaddr));
+       state->anvil_range = inet_prefix_top(af,
+                                       SOCK_ADDR_ADDRP(&(state->sockaddr)),
+                                            af == AF_INET ?
+                                            var_smtpd_cipv4_prefix :
+                                            var_smtpd_cipv6_prefix);
+    }
 }
 
 /* smtpd_peer_reset - destroy peer information */
index 691b8c6825a82234415d2c896ba2a791f0722108..f002fc16cad82aea2b8c0e4926a7c003311ca5cf 100644 (file)
@@ -27,15 +27,15 @@ rcpt foo@postfix.org
 helo_restrictions check_helo_ns_access,inline:{168.100.3.75=reject}
 helo www.porcupine.org
 helo example.tld
-helo foo@postfix.org
+helo foo@maildaemon.org
 sender_restrictions check_sender_ns_access,inline:{168.100.3.75=reject}
 mail foo@www.porcupine.org
 mail example.tld
-mail foo@postfix.org
+mail foo@maildaemon.org
 recipient_restrictions check_recipient_ns_access,inline:{168.100.3.75=reject}
 rcpt foo@www.porcupine.org
 rcpt foo@example.tld
-rcpt foo@postfix.org
+rcpt foo@maildaemon.org
 #
 # Check A access
 #
index b396a57b6f3e8c3b3dab910ca91f5d91025fd7a6..182d0d90cfec9308610bd1e74129632e0bc2dc17 100644 (file)
@@ -53,52 +53,52 @@ OK
 >>> helo example.tld
 ./smtpd_check: warning: Unable to look up NS host for example.tld: Host not found
 OK
->>> helo foo@postfix.org
-./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@postfix.org>: Helo command rejected: Access denied; from=<foo@postfix.org> proto=SMTP helo=<foo@postfix.org>
-554 5.7.1 <foo@postfix.org>: Helo command rejected: Access denied
+>>> helo foo@maildaemon.org
+./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@maildaemon.org>: Helo command rejected: Access denied; from=<foo@postfix.org> proto=SMTP helo=<foo@maildaemon.org>
+554 5.7.1 <foo@maildaemon.org>: Helo command rejected: Access denied
 >>> sender_restrictions check_sender_ns_access,inline:{168.100.3.75=reject}
 OK
 >>> mail foo@www.porcupine.org
-./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@www.porcupine.org>: Sender address rejected: Access denied; from=<foo@www.porcupine.org> proto=SMTP helo=<foo@postfix.org>
+./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@www.porcupine.org>: Sender address rejected: Access denied; from=<foo@www.porcupine.org> proto=SMTP helo=<foo@maildaemon.org>
 554 5.7.1 <foo@www.porcupine.org>: Sender address rejected: Access denied
 >>> mail example.tld
 ./smtpd_check: warning: Unable to look up NS host for example.tld: Host not found
 OK
->>> mail foo@postfix.org
-./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@postfix.org>: Sender address rejected: Access denied; from=<foo@postfix.org> proto=SMTP helo=<foo@postfix.org>
-554 5.7.1 <foo@postfix.org>: Sender address rejected: Access denied
+>>> mail foo@maildaemon.org
+./smtpd_check: <queue id>: reject: MAIL from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@maildaemon.org>: Sender address rejected: Access denied; from=<foo@maildaemon.org> proto=SMTP helo=<foo@maildaemon.org>
+554 5.7.1 <foo@maildaemon.org>: Sender address rejected: Access denied
 >>> recipient_restrictions check_recipient_ns_access,inline:{168.100.3.75=reject}
 OK
 >>> rcpt foo@www.porcupine.org
-./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@www.porcupine.org>: Recipient address rejected: Access denied; from=<foo@postfix.org> to=<foo@www.porcupine.org> proto=SMTP helo=<foo@postfix.org>
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@www.porcupine.org>: Recipient address rejected: Access denied; from=<foo@maildaemon.org> to=<foo@www.porcupine.org> proto=SMTP helo=<foo@maildaemon.org>
 554 5.7.1 <foo@www.porcupine.org>: Recipient address rejected: Access denied
 >>> rcpt foo@example.tld
 ./smtpd_check: warning: Unable to look up NS host for foo@example.tld: Host not found
 OK
->>> rcpt foo@postfix.org
-./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@postfix.org>: Recipient address rejected: Access denied; from=<foo@postfix.org> to=<foo@postfix.org> proto=SMTP helo=<foo@postfix.org>
-554 5.7.1 <foo@postfix.org>: Recipient address rejected: Access denied
+>>> rcpt foo@maildaemon.org
+./smtpd_check: <queue id>: reject: RCPT from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <foo@maildaemon.org>: Recipient address rejected: Access denied; from=<foo@maildaemon.org> to=<foo@maildaemon.org> proto=SMTP helo=<foo@maildaemon.org>
+554 5.7.1 <foo@maildaemon.org>: Recipient address rejected: Access denied
 >>> #
 >>> # Check A access
 >>> #
 >>> helo_restrictions check_helo_a_access,inline:{168.100.3.2=reject}
 OK
 >>> helo spike.porcupine.org
-./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <spike.porcupine.org>: Helo command rejected: Access denied; from=<foo@postfix.org> proto=SMTP helo=<spike.porcupine.org>
+./smtpd_check: <queue id>: reject: HELO from spike.porcupine.org[168.100.3.2]: 554 5.7.1 <spike.porcupine.org>: Helo command rejected: Access denied; from=<foo@maildaemon.org> proto=SMTP helo=<spike.porcupine.org>
 554 5.7.1 <spike.porcupine.org>: Helo command rejected: Access denied
 >>> helo www.porcupine.org
 OK
 >>> client_restrictions check_client_a_access,inline:{168.100.3.2=reject}
 OK
 >>> client spike.porcupine.org 1.2.3.4
-./smtpd_check: <queue id>: reject: CONNECT from spike.porcupine.org[1.2.3.4]: 554 5.7.1 <spike.porcupine.org[1.2.3.4]>: Client host rejected: Access denied; from=<foo@postfix.org> proto=SMTP helo=<www.porcupine.org>
+./smtpd_check: <queue id>: reject: CONNECT from spike.porcupine.org[1.2.3.4]: 554 5.7.1 <spike.porcupine.org[1.2.3.4]>: Client host rejected: Access denied; from=<foo@maildaemon.org> proto=SMTP helo=<www.porcupine.org>
 554 5.7.1 <spike.porcupine.org[1.2.3.4]>: Client host rejected: Access denied
 >>> client www.porcupine.org 1.2.3.4
 OK
 >>> reverse_client_restrictions check_reverse_client_a_access,inline:{168.100.3.2=reject}
 bad command
 >>> client spike.porcupine.org 1.2.3.4
-./smtpd_check: <queue id>: reject: CONNECT from spike.porcupine.org[1.2.3.4]: 554 5.7.1 <spike.porcupine.org[1.2.3.4]>: Client host rejected: Access denied; from=<foo@postfix.org> proto=SMTP helo=<www.porcupine.org>
+./smtpd_check: <queue id>: reject: CONNECT from spike.porcupine.org[1.2.3.4]: 554 5.7.1 <spike.porcupine.org[1.2.3.4]>: Client host rejected: Access denied; from=<foo@maildaemon.org> proto=SMTP helo=<www.porcupine.org>
 554 5.7.1 <spike.porcupine.org[1.2.3.4]>: Client host rejected: Access denied
 >>> client www.porcupine.org 1.2.3.4
 OK
index 4592f6a502e175fb6dcb8ea184aca09edee334f3..3e3ea9ab88033f06f9289564c0d1e32c35f742bf 100644 (file)
@@ -44,7 +44,8 @@ SRCS  = alldig.c allprint.c argv.c argv_split.c attr_clnt.c attr_print0.c \
        msg_logger.c logwriter.c unix_dgram_connect.c unix_dgram_listen.c \
        byte_mask.c known_tcp_ports.c argv_split_at.c dict_stream.c \
        sane_strtol.c hash_fnv.c ldseed.c mkmap_cdb.c mkmap_db.c mkmap_dbm.c \
-       mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c net_mask_top.c
+       mkmap_fail.c mkmap_lmdb.c mkmap_open.c mkmap_sdbm.c inet_prefix_top.c \
+       inet_addr_sizes.c
 OBJS   = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        attr_print64.o attr_print_plain.o attr_scan0.o attr_scan64.o \
        attr_scan_plain.o auto_clnt.o base64_code.o basename.o binhash.o \
@@ -90,7 +91,7 @@ OBJS  = alldig.o allprint.o argv.o argv_split.o attr_clnt.o attr_print0.o \
        msg_logger.o logwriter.o unix_dgram_connect.o unix_dgram_listen.o \
        byte_mask.o known_tcp_ports.o argv_split_at.o dict_stream.o \
        sane_strtol.o hash_fnv.o ldseed.o mkmap_db.o mkmap_dbm.o \
-       mkmap_fail.o mkmap_open.o net_mask_top.o
+       mkmap_fail.o mkmap_open.o inet_prefix_top.o inet_addr_sizes.o
 # MAP_OBJ is for maps that may be dynamically loaded with dynamicmaps.cf.
 # When hard-linking these, makedefs sets NON_PLUGIN_MAP_OBJ=$(MAP_OBJ),
 # otherwise it sets the PLUGIN_* macros.
@@ -122,7 +123,7 @@ HDRS        = argv.h attr.h attr_clnt.h auto_clnt.h base64_code.h binhash.h \
        valid_utf8_hostname.h midna_domain.h dict_union.h dict_inline.h \
        check_arg.h argv_attr.h msg_logger.h logwriter.h byte_mask.h \
        known_tcp_ports.h sane_strtol.h hash_fnv.h ldseed.h mkmap.h \
-       net_mask_top.h
+       inet_prefix_top.h inet_addr_sizes.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)
@@ -2024,6 +2025,11 @@ inet_addr_local.o: sock_addr.h
 inet_addr_local.o: sys_defs.h
 inet_addr_local.o: vbuf.h
 inet_addr_local.o: vstring.h
+inet_addr_sizes.o: inet_addr_sizes.c
+inet_addr_sizes.o: inet_addr_sizes.h
+inet_addr_sizes.o: msg.h
+inet_addr_sizes.o: myaddrinfo.h
+inet_addr_sizes.o: sys_defs.h
 inet_connect.o: connect.h
 inet_connect.o: host_port.h
 inet_connect.o: inet_connect.c
@@ -2048,6 +2054,15 @@ inet_listen.o: mymalloc.h
 inet_listen.o: sane_accept.h
 inet_listen.o: sock_addr.h
 inet_listen.o: sys_defs.h
+inet_prefix_top.o: check_arg.h
+inet_prefix_top.o: inet_addr_sizes.h
+inet_prefix_top.o: inet_prefix_top.c
+inet_prefix_top.o: inet_prefix_top.h
+inet_prefix_top.o: mask_addr.h
+inet_prefix_top.o: msg.h
+inet_prefix_top.o: sys_defs.h
+inet_prefix_top.o: vbuf.h
+inet_prefix_top.o: vstring.h
 inet_proto.o: check_arg.h
 inet_proto.o: inet_proto.c
 inet_proto.o: inet_proto.h
@@ -2416,15 +2431,6 @@ nbbio.o: mymalloc.h
 nbbio.o: nbbio.c
 nbbio.o: nbbio.h
 nbbio.o: sys_defs.h
-net_mask_top.o: check_arg.h
-net_mask_top.o: mask_addr.h
-net_mask_top.o: msg.h
-net_mask_top.o: myaddrinfo.h
-net_mask_top.o: net_mask_top.c
-net_mask_top.o: net_mask_top.h
-net_mask_top.o: sys_defs.h
-net_mask_top.o: vbuf.h
-net_mask_top.o: vstring.h
 netstring.o: check_arg.h
 netstring.o: compat_va_copy.h
 netstring.o: msg.h
diff --git a/postfix/src/util/inet_addr_sizes.c b/postfix/src/util/inet_addr_sizes.c
new file mode 100644 (file)
index 0000000..e788c22
--- /dev/null
@@ -0,0 +1,77 @@
+/*++
+/* NAME
+/*     inet_addr_sizes 3
+/* SUMMARY
+/*      get network address size metrics
+/* SYNOPSIS
+/*     #include <inet_addr_sizes.h>
+/*
+/*     typedef struct {
+/* .in +4
+/*         int     af;                  /* network address family (binary) */
+/*         char   *ipproto_str;         /* IP protocol version (string) */
+/*         int     addr_bitcount;       /* bits per address */
+/*         int     addr_bytecount;      /* bytes per address */
+/*         int     addr_strlen;         /* address string length */
+/*         int     addr_bitcount_strlen;/* addr_bitcount string length */
+/* .in -4
+/*     } INET_ADDR_SIZES;
+/*
+/*     const INET_ADDR_SIZES *inet_addr_sizes(int family)
+/* DESCRIPTION
+/*     inet_addr_sizes() returns address size metrics for the
+/*     specified network address family, AF_INET or AF_INET6.
+/* DIAGNOSTICS
+/*     inet_addr_sizes() returns a null pointer when the argument
+/*     specifies an unexpected address family.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*--*/
+
+ /*
+  * System library.
+  */
+#include <sys_defs.h>
+#include <string.h>
+
+ /*
+  * Utility library.
+  */
+#include <inet_addr_sizes.h>
+#include <msg.h>
+#include <myaddrinfo.h>
+
+ /*
+  * Stringify a numeric constant and use sizeof() to determine the resulting
+  * string length at compile time. Note that sizeof() includes a null
+  * terminator; the -1 corrects for that.
+  */
+#define _STRINGIFY(x) #x
+#define _STRLEN(x) (sizeof(_STRINGIFY(x)) - 1)
+
+static const INET_ADDR_SIZES table[] = {
+    {AF_INET, "IPv4", MAI_V4ADDR_BITS, MAI_V4ADDR_BYTES, INET_ADDRSTRLEN,
+    _STRLEN(MAI_V4ADDR_BITS)},
+#ifdef HAS_IPV6
+    {AF_INET6, "IPv6", MAI_V6ADDR_BITS, MAI_V6ADDR_BYTES, INET6_ADDRSTRLEN,
+    _STRLEN(MAI_V6ADDR_BITS)},
+#endif
+};
+
+/* inet_addr_sizes - get address size metrics for address family */
+
+const   INET_ADDR_SIZES *inet_addr_sizes(int af)
+{
+    const   INET_ADDR_SIZES *sp;
+
+    for (sp = table; /* see below */ ; sp++) {
+       if (sp >= table + sizeof(table) / sizeof(*table))
+           return (0);
+       if (sp->af == af)
+           return (sp);
+    }
+}
diff --git a/postfix/src/util/inet_addr_sizes.h b/postfix/src/util/inet_addr_sizes.h
new file mode 100644 (file)
index 0000000..c937c78
--- /dev/null
@@ -0,0 +1,36 @@
+#ifndef _INET_ADDR_SIZES_H_INCLUDED_
+#define _INET_ADDR_SIZES_H_INCLUDED_
+
+/*++
+/* NAME
+/*      inet_addr_sizes 3h
+/* SUMMARY
+/*      get network address size metrics
+/* SYNOPSIS
+/*      #include <inet_addr_sizes.h>
+/* DESCRIPTION
+/* .nf
+
+ /*
+  * External interface.
+  */
+typedef struct {
+    int     af;                                /* network address family (binary) */
+    char   *ipproto_str;               /* IP protocol version (string) */
+    int     addr_bitcount;             /* bits per address */
+    int     addr_bytecount;            /* bytes per address */
+    int     addr_strlen;               /* address string length */
+    int     addr_bitcount_strlen;      /* addr_bitcount string length */
+} INET_ADDR_SIZES;
+
+extern const INET_ADDR_SIZES *inet_addr_sizes(int);
+
+/* LICENSE
+/* .ad
+/* .fi
+/*      The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*      Wietse Venema
+/*--*/
+
+#endif
diff --git a/postfix/src/util/inet_prefix_top.c b/postfix/src/util/inet_prefix_top.c
new file mode 100644 (file)
index 0000000..56da5dd
--- /dev/null
@@ -0,0 +1,102 @@
+/*++
+/* NAME
+/*     inet_prefix_top 3
+/* SUMMARY
+/*     convert net/mask to printable string
+/* SYNOPSIS
+/*     #include <inet_prefix_top.h>
+/*
+/*     char    *inet_prefix_top(
+/*     int     family,
+/*     const void *src,
+/*     int     prefix_len)
+/* DESCRIPTION
+/*     inet_prefix_top() prints the network portion of the specified
+/*     IPv4 or IPv6 address, null bits for the host portion, and
+/*     the prefix length if it is shorter than the address.
+/*     The result should be passed to myfree(). The code can
+/*     handle addresses of any length, and bytes of any width.
+/*
+/*     Arguments:
+/* .IP af
+/*     The address family, as with inet_ntop().
+/* .IP src
+/*     Pointer to storage for an IPv4 or IPv6 address, as with
+/*     inet_ntop().
+/* .IP prefix_len
+/*     The number of most-significant bits in \fBsrc\fR that should
+/*     not be cleared.
+/* DIAGNOSTICS
+/*     Panic: unexpected protocol family, bad prefix length. Fatal
+/*     errors: address conversion error.
+/* LICENSE
+/* .ad
+/* .fi
+/*     The Secure Mailer license must be distributed with this software.
+/* AUTHOR(S)
+/*     Wietse Venema
+/*--*/
+
+ /*
+  * System library.
+  */
+#include <sys_defs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <string.h>
+
+ /*
+  * Utility library.
+  */
+#include <mask_addr.h>
+#include <msg.h>
+#include <inet_addr_sizes.h>
+#include <inet_prefix_top.h>
+#include <vstring.h>
+
+/* inet_prefix_top - printable net/mask pattern */
+
+char   *inet_prefix_top(int af, const void *src, int prefix_len)
+{
+    const char myname[] = "inet_prefix_top";
+    union {
+       struct in_addr in_addr;
+       struct in6_addr in6_addr;
+    }       u;
+    VSTRING *buf;
+    const INET_ADDR_SIZES *sp;
+
+    /*
+     * Sanity checks. XXX We use msg_fatal() because mail_conf_int() does not
+     * (yet) support non-negative integers.
+     */
+    if ((sp = inet_addr_sizes(af)) == 0)
+       msg_panic("%s: unexpected address family: %d", myname, af);
+    if (prefix_len > sp->addr_bitcount || prefix_len < 0)
+       msg_fatal("%s: bad %s address prefix length: %d",
+                 myname, sp->ipproto_str, prefix_len);
+
+    /*
+     * Strip a copy of the input address. When allocating the result memory,
+     * add 1 for the string terminator from inet_ntop(), or 1 for the '/'
+     * before the prefix. We should not rely on vstring(3)'s safety byte.
+     */
+    memcpy((void *) &u, src, sp->addr_bytecount);
+    if (prefix_len < sp->addr_bitcount) {
+       mask_addr((unsigned char *) &u, sp->addr_bytecount, prefix_len);
+       buf = vstring_alloc(sp->addr_strlen + sp->addr_bitcount_strlen + 1);
+    } else {
+       buf = vstring_alloc(sp->addr_strlen + 1);
+    }
+
+    /*
+     * Convert the result to string, and append the optional /prefix.
+     */
+    if (inet_ntop(af, &u, vstring_str(buf), vstring_avail(buf)) == 0)
+       msg_fatal("%s: inet_ntop: %m", myname);
+    vstring_set_payload_size(buf, strlen(vstring_str(buf)));
+    if (prefix_len < sp->addr_bitcount)
+       vstring_sprintf_append(buf, "/%d", prefix_len);
+    return (vstring_export(buf));
+}
similarity index 60%
rename from postfix/src/util/net_mask_top.h
rename to postfix/src/util/inet_prefix_top.h
index 8f043f5b77ea1a5f595bcfd03fd749b4913fd769..f604ee300ccff967499e8464c3d2bc8c0cde16a0 100644 (file)
@@ -1,20 +1,20 @@
-#ifndef _NET_MASK_TOP_H_INCLUDED_
-#define _NET_MASK_TOP_H_INCLUDED_
+#ifndef _INET_MASK_TOP_H_INCLUDED_
+#define _INET_MASK_TOP_H_INCLUDED_
 
 /*++
 /* NAME
-/*     net_mask_top 3h
+/*     inet_prefix_top 3h
 /* SUMMARY
 /*     convert net/mask to printable string
 /* SYNOPSIS
-/*     #include <net_mask_top.h>
+/*     #include <inet_prefix_top.h>
 /* DESCRIPTION
 /* .nf
 
  /*
   * External interface.
   */
-extern char *net_mask_top(int, const void *, int);
+extern char *inet_prefix_top(int, const void *, int);
 
 /* LICENSE
 /* .ad
diff --git a/postfix/src/util/net_mask_top.c b/postfix/src/util/net_mask_top.c
deleted file mode 100644 (file)
index 5483fca..0000000
+++ /dev/null
@@ -1,120 +0,0 @@
-/*++
-/* NAME
-/*     net_mask_top 3
-/* SUMMARY
-/*     convert net/mask to printable string
-/* SYNOPSIS
-/*     #include <mask_addr.h>
-/*
-/*     char    *net_mask_top(
-/*     int     family,
-/*     const void *src,
-/*     int     prefix_len)
-/* DESCRIPTION
-/*     net_mask_top() prints the network portion of the specified
-/*     IPv4 or IPv6 address, null bits for the host portion, and
-/*     the prefix length if it is shorter than the address.
-/*     The result should be passed to myfree(). The code can
-/*     handle addresses of any length, and bytes of any width.
-/*
-/*     Arguments:
-/* .IP af
-/*     The address family, as with inet_ntop().
-/* .IP src
-/*     Pointer to storage for an IPv4 or IPv6 address, as with
-/*     inet_ntop().
-/* .IP prefix_len
-/*     The number of most-significant bits in \fBsrc\fR that should
-/*     not be cleared.
-/* DIAGNOSTICS
-/*     Panic: unexpected protocol family, bad prefix length. Fatal
-/*     errors: address conversion error.
-/* LICENSE
-/* .ad
-/* .fi
-/*     The Secure Mailer license must be distributed with this software.
-/* AUTHOR(S)
-/*     Wietse Venema
-/*--*/
-
- /*
-  * System library.
-  */
-#include <sys_defs.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <string.h>
-
- /*
-  * Utility library.
-  */
-#include <mask_addr.h>
-#include <msg.h>
-#include <myaddrinfo.h>
-#include <net_mask_top.h>
-#include <vstring.h>
-
-/*
- * XXX Factor out if we also need this in other places.
- */
-struct addr_size {
-    int     af;                                /* address family (binary) */
-    char    ipproto_str[5];            /* IP protocol version (string) */
-    int     addr_bitcount;             /* bits per address */
-    int     addr_bytecount;            /* bytes per address */
-    int     addr_strlen;               /* string representation length */
-    int     slashdigs_strlen;          /* length of /0-31, /0-127 */
-};
-static struct addr_size addr_sizes[] = {
-    AF_INET, "IPv4", MAI_V4ADDR_BITS, MAI_V4ADDR_BYTES, INET_ADDRSTRLEN, 3,
-#ifdef HAS_IPV6
-    AF_INET6, "IPv6", MAI_V6ADDR_BITS, MAI_V6ADDR_BYTES, INET6_ADDRSTRLEN, 4,
-#endif
-};
-
-/* get_addr_size - get bit-banging numbers for address family */
-
-static struct addr_size *get_addr_size(int af)
-{
-    struct addr_size *ap;
-
-    for (ap = addr_sizes; /* see below */ ; ap++) {
-       if (ap >= addr_sizes + sizeof(addr_sizes) / sizeof(struct addr_size))
-           return (0);
-       if (ap->af == af)
-           return (ap);
-    }
-}
-
-/* net_mask_top - printable net/mask pattern */
-
-char   *net_mask_top(int af, const void *src, int prefix_len)
-{
-    const char myname[] = "net_mask_top";
-    union {
-       struct in_addr in_addr;
-       struct in6_addr in6_addr;
-    }       u;
-    VSTRING *buf;
-    struct addr_size *ap;
-
-    if ((ap = get_addr_size(af)) == 0)
-       msg_panic("%s: unexpected address family: %d", myname, af);
-    if (prefix_len > ap->addr_bitcount || prefix_len < 0)
-       msg_fatal("%s: bad %s address prefix length: %d",
-                 myname, ap->ipproto_str, prefix_len);
-    memcpy((void *) &u, src, ap->addr_bytecount);
-    if (prefix_len < ap->addr_bitcount) {
-       mask_addr((unsigned char *) &u, ap->addr_bytecount, prefix_len);
-       buf = vstring_alloc(ap->addr_strlen + ap->slashdigs_strlen);
-    } else {
-       buf = vstring_alloc(ap->addr_strlen);
-    }
-    if (inet_ntop(af, &u, vstring_str(buf), vstring_avail(buf)) == 0)
-       msg_fatal("%s: inet_ntop: %m", myname);
-    vstring_set_payload_size(buf, strlen(vstring_str(buf)));
-    if (prefix_len < ap->addr_bitcount)
-       vstring_sprintf_append(buf, "/%d", prefix_len);
-    return (vstring_export(buf));
-}