]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-3.8-20230409
authorWietse Venema <wietse@porcupine.org>
Sun, 9 Apr 2023 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <postfix-users@dukhovni.org>
Sun, 9 Apr 2023 22:21:32 +0000 (18:21 -0400)
18 files changed:
postfix/HISTORY
postfix/WISHLIST
postfix/proto/stop.double-history
postfix/proto/stop.spell-history
postfix/src/dns/dns_rr.c
postfix/src/global/mail_version.h
postfix/src/postconf/Makefile.in
postfix/src/postconf/postconf.h
postfix/src/postconf/postconf_dbms.c
postfix/src/postconf/postconf_edit.c
postfix/src/postconf/postconf_main.c
postfix/src/postconf/postconf_master.c
postfix/src/postconf/postconf_misc.c
postfix/src/postconf/test58.ref
postfix/src/postconf/test71.ref
postfix/src/postlogd/Makefile.in
postfix/src/util/Makefile.in
postfix/src/util/inet_prefix_top.c

index 81d5e00d0bff64b75f335d3b7c6f34b54603db7c..5fa9b3b9f20e87c8f0a9ce394122fcf8a8dd1544 100644 (file)
@@ -27025,14 +27025,22 @@ Apologies for any names omitted.
        double-free() attempt. Reported by Florian Piekert. File:
        dns/dns_rr.c.
 
-       Usability: Postfix does not support #comments after other
-       text, but people add them anyway, with unexpected results.
-       The postconf command now warns for trailing comments in
-       main.cf files. Similar warnings are planned for database
-       client configuration files. Files: util/mystrtok.c,
+       Usability: The postconf command now warns for trailing
+       comments in Postfix parameter values. Also refactored comment
+       warnings in match lists. Files: util/mystrtok.c,
        util/mystrtok.ref, util/match_list.c, global/namadr_list.ref,
        postconf/postconf_dbms.c, postconf/test71.ref.
 
-       TODO: #comment after text in DB client configuration files.
+       Cleanup: some postconf warnings did not include the full
+       main.cf or master.cf pathname, complicating the analysis
+       of multi-instance configurations. Also refactored ad-hoc
+       code that computed full main.cf or master.cf pathnames.
+       Files: postconf/postconf.h, postconf/postconf_dbms.c,
+       postconf/postconf_edit.c, postconf/postconf_main.c,
+       postconf/postconf_master.c, postconf/postconf_misc.c.
+
+       Cleanup: eliminated unused libdns dependencies. Files:
+       postlogd/Makefile.in.
 
-       TOIDO: test for dns_rr_copy() + dns_rr_free().
+       Cleanup: added inet_prefix_top() tests. File:
+       util/inet_prefix_top.c.
index a83418605bcee8514d4091a876c30b017ec55f3a..bc52ebc0118b329b7b022818a6a67aaff6cce97b 100644 (file)
@@ -21,6 +21,9 @@ Wish list:
        Multi-recipient support in sender/recipient_bcc_maps and
        always_bcc.
 
+       Test for dns_rr_copy() + dns_rr_free().
+
+
        mail_conf_xxx supprt for non-negative numbers (i.e. 
        numbers with a lower bound of zero).
 
index 9f05f29e3fdca4fe5a56eca572ed8446136a6657..c1026c8a06fb429bfb78ab3d60630a08b4e43095 100644 (file)
@@ -39,3 +39,4 @@ proto  proto SASL_README html proto SQLITE_README html
  util inet_prefix_top hc smtpd smtpd c smtpd smtpd_peer c 
  File smtp smtp h 
  manpage File postscreen postscreen c 
+ Files postconf postconf h postconf postconf_dbms c 
index 669c2e3f98ac49013e58d006dde16fdce7a6a1d0..096da091a198c0d9dab29d1a05c9c66f059f9e60 100644 (file)
@@ -53,3 +53,6 @@ Aleksandr
 Stankevic
 Gallagher
 Valgrind
+Florian
+Piekert
+refactored
index b84349267aac290be1be4a69929a6d347326f1da..3fde10e5882f1956f9439caf78fbb90ae71e7d0c 100644 (file)
@@ -209,11 +209,11 @@ DNS_RR *dns_rr_copy(DNS_RR *src)
      * Note: struct copy, because dns_rr_create() would not copy all fields.
      */
     dst = (DNS_RR *) mymalloc(sizeof(*dst));
-    memcpy((void *) dst, (void *) src, sizeof(*dst));
+    *dst = *src;
     dst->qname = mystrdup(src->qname);
     dst->rname = mystrdup(src->rname);
     if (dst->data)
-       dst->data = mymemdup(dst->data, dst->data_len);
+       dst->data = mymemdup(src->data, src->data_len);
     dst->next = 0;
     return (dst);
 }
index dbcfba979af336d9117180650d1136f69e204005..9dcb7bd06e0afe49ffccd61f1b60b3484be40d74 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      "20230406"
+#define MAIL_RELEASE_DATE      "20230409"
 #define MAIL_VERSION_NUMBER    "3.8"
 
 #ifdef SNAPSHOT
index 26e747c7bd4142dbd52e97cc52aa6861389ea7a5..f0cc4002a05b87bdf74997a1db74e6c1ae7f2ed4 100644 (file)
@@ -970,13 +970,19 @@ test71:   $(PROG) test71.ref
        rm -f main.cf master.cf
        touch main.cf master.cf
        echo "smtpd_client_restrictions = inline:{" >>main.cf
-       echo "  { aaa0 = #aaa1 } #aaa2" >>main.cf
+       echo "  {" >>main.cf
+       echo "  aaa0 = #aaa1" >>main.cf
+       echo "  } #aaa2" >>main.cf
        echo " }" >>main.cf
        echo "smtpd_helo_restrictions = pcre:{" >>main.cf
-       echo "  { /bbb0 #bbb1/ } #bbb2" >>main.cf
+       echo "  {" >>main.cf
+       echo "  /bbb0 #bbb1/" >>main.cf
+       echo "  } #bbb2" >>main.cf
        echo " }" >>main.cf
        echo "smtpd_sender_restrictions = regexp:{" >>main.cf
-       echo "  { /ccc0 #ccc1/ } #ccc2" >>main.cf
+       echo "  {" >>main.cf
+       echo "  /ccc0 #ccc1/" >>main.cf
+       echo "  } #ccc2" >>main.cf
        echo " }" >>main.cf
        touch -t 197101010000 main.cf
        $(HTABLE_FIX) $(SHLIB_ENV) $(VALGRIND) ./$(PROG) -nc . >test71.tmp 2>&1
index 7b23380a5793d97df4eb62a525d85266cf35911e..d11d66fd366175b74018a0f498b239dda75eb10d 100644 (file)
@@ -171,6 +171,8 @@ extern int pcf_cmd_mode;
   * postconf_misc.c.
   */
 extern void pcf_set_config_dir(void);
+extern const char *pcf_get_main_path(void);
+extern const char *pcf_get_master_path(void);
 
  /*
   * postconf_main.c
@@ -324,4 +326,6 @@ extern void pcf_show_tls(const char *);
 /*     Google, Inc.
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
+/*
+/*     Wietse Venema
 /*--*/
index 622e7a01dc9599482e87583ebf1f46d93530d5a4..b2777cb2e7688695e831fd38e46ebe74c2473e9b 100644 (file)
@@ -248,15 +248,15 @@ static void pcf_register_dbms_helper(char *str_value,
      * database or some other text.
      */
     while ((db_type = mystrtokq_cw(&str_value, CHARS_COMMA_SP, CHARS_BRACE,
-                  local_scope ? MASTER_CONF_FILE : MAIN_CONF_FILE)) != 0) {
+        local_scope ? pcf_get_master_path() : pcf_get_main_path())) != 0) {
        if (*db_type == CHARS_BRACE[0]) {
            if ((err = extpar(&db_type, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) {
                /* XXX Encapsulate this in pcf_warn() function. */
                if (local_scope)
-                   msg_warn("%s:%s: %s",
-                            MASTER_CONF_FILE, local_scope->name_space, err);
+                   msg_warn("%s:%s: %s", pcf_get_master_path(),
+                            local_scope->name_space, err);
                else
-                   msg_warn("%s: %s", MAIN_CONF_FILE, err);
+                   msg_warn("%s: %s", pcf_get_main_path(), err);
                myfree(err);
            }
            if (recurse)
@@ -310,11 +310,10 @@ static void pcf_register_dbms_helper(char *str_value,
                if ((err = extpar(&prefix, CHARS_BRACE, EXTPAR_FLAG_NONE)) != 0) {
                    /* XXX Encapsulate this in pcf_warn() function. */
                    if (local_scope)
-                       msg_warn("%s:%s: %s",
-                                MASTER_CONF_FILE, local_scope->name_space,
-                                err);
+                       msg_warn("%s:%s: %s", pcf_get_master_path(),
+                                local_scope->name_space, err);
                    else
-                       msg_warn("%s: %s", MAIN_CONF_FILE, err);
+                       msg_warn("%s: %s", pcf_get_main_path(), err);
                    myfree(err);
                }
                for (dp = pcf_dbms_info; dp->db_type != 0; dp++) {
index c60cb06f5da946556fb05d3b95832427a046b1bd..fc097d0417a891a5fcc21a91491ffc9e0d9facd5 100644 (file)
@@ -61,6 +61,8 @@
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
 /*--*/
 
 /* System library. */
@@ -147,7 +149,7 @@ static void pcf_gobble_cf_line(VSTRING *full_entry_buf, VSTRING *line_buf,
 
 void    pcf_edit_main(int mode, int argc, char **argv)
 {
-    char   *path;
+    const char *path;
     EDIT_FILE *ep;
     VSTREAM *src;
     VSTREAM *dst;
@@ -203,7 +205,7 @@ void    pcf_edit_main(int mode, int argc, char **argv)
      * don't leave behind thrash with random names.
      */
     pcf_set_config_dir();
-    path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0);
+    path = pcf_get_main_path();
     if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0)
        msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX);
     dst = ep->tmp_fp;
@@ -272,7 +274,6 @@ void    pcf_edit_main(int mode, int argc, char **argv)
     /*
      * Cleanup.
      */
-    myfree(path);
     vstring_free(buf);
     vstring_free(key);
     htable_free(table, myfree);
@@ -296,7 +297,7 @@ typedef struct {
 void    pcf_edit_master(int mode, int argc, char **argv)
 {
     const char *myname = "pcf_edit_master";
-    char   *path;
+    const char *path;
     EDIT_FILE *ep;
     VSTREAM *src;
     VSTREAM *dst;
@@ -401,7 +402,7 @@ void    pcf_edit_master(int mode, int argc, char **argv)
      * don't leave behind thrash with random names.
      */
     pcf_set_config_dir();
-    path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
+    path = pcf_get_master_path();
     if ((ep = edit_file_open(path, O_CREAT | O_WRONLY, 0644)) == 0)
        msg_fatal("open %s%s: %m", path, EDIT_FILE_SUFFIX);
     dst = ep->tmp_fp;
@@ -566,7 +567,6 @@ void    pcf_edit_master(int mode, int argc, char **argv)
     /*
      * Cleanup.
      */
-    myfree(path);
     vstring_free(line_buf);
     vstring_free(parse_buf);
     vstring_free(full_entry_buf);
index 8e6e226f3cdc3eaa084a1bc6a3ff639243c4f787..f19ba7ffbbbf0a1cf548c33cf6257c1587389e29 100644 (file)
@@ -68,6 +68,8 @@
 /*     Google, Inc.
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
+/*
+/*     Wietse Venema
 /*--*/
 
 /* System library. */
 
 void    pcf_read_parameters(void)
 {
-    char   *path;
+    const char *path;
 
     /*
      * A direct rip-off of mail_conf_read(). XXX Avoid code duplication by
      * better code decomposition.
      */
     pcf_set_config_dir();
-    path = concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0);
+    path = pcf_get_main_path();
     if (dict_load_file_xt(CONFIG_DICT, path) == 0)
        msg_fatal("open %s: %m", path);
-    myfree(path);
 }
 
 /* pcf_set_parameters - add or override name=value pairs */
index 687e03fdfe6ab61ed39d64636b8f13b46719c1f4..af58c1efa83ca05e12b347e972852e292081967c 100644 (file)
 /*     Google, Inc.
 /*     111 8th Avenue
 /*     New York, NY 10011, USA
+/*
+/*     Wietse Venema
 /*--*/
 
 /* System library. */
@@ -411,7 +413,7 @@ const char *pcf_parse_master_entry(PCF_MASTER_ENT *masterp, const char *buf)
 void    pcf_read_master(int fail_on_open_error)
 {
     const char *myname = "pcf_read_master";
-    char   *path;
+    const char *path;
     VSTRING *buf;
     VSTREAM *fp;
     const char *err;
@@ -430,7 +432,7 @@ void    pcf_read_master(int fail_on_open_error)
      */
     if (var_config_dir == 0)
        pcf_set_config_dir();
-    path = concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
+    path = pcf_get_master_path();
 
     /*
      * Initialize the in-memory master table.
@@ -463,7 +465,6 @@ void    pcf_read_master(int fail_on_open_error)
      * Null-terminate the master table and clean up.
      */
     pcf_master_table[entry_count].argv = 0;
-    myfree(path);
 }
 
 /* pcf_print_master_entry - print one master line */
index 0107651fbd76515737ca100a050d2b9df8c054ab..d8a5008a38be8e45358147975465cce9af15a968 100644 (file)
@@ -7,11 +7,20 @@
 /*     #include <postconf.h>
 /*
 /*     void    pcf_set_config_dir()
+/*
+/*     const char *pcf_get_main_path()
+/*
+/*     const char *pcf_get_master_path()
 /* DESCRIPTION
 /*     pcf_set_config_dir() forcibly overrides the var_config_dir
 /*     parameter setting with the value from the environment or
 /*     with the default pathname, and updates the mail parameter
 /*     dictionary.
+/*
+/*     pcf_get_main_path() and pcf_get_master_path() return a
+/*     pointer to a cached main.cf or master.cf full pathname,
+/*     based on the current var_config_dir setting. The functions
+/*     call pcf_set_config_dir() when no full pathname is cached.
 /* DIAGNOSTICS
 /*     Problems are reported to the standard error stream.
 /* LICENSE
@@ -23,6 +32,8 @@
 /*     IBM T.J. Watson Research
 /*     P.O. Box 704
 /*     Yorktown Heights, NY 10598, USA
+/*
+/*     Wietse Venema
 /*--*/
 
 /* System library. */
@@ -33,6 +44,7 @@
 
 #include <mymalloc.h>
 #include <safe.h>
+#include <stringops.h>
 
 /* Global library. */
 
 
 #include <postconf.h>
 
+ /*
+  * Pathname cache, based on current var_config_dir.
+  */
+static char *pcf_main_path = 0;
+static char *pcf_master_path = 0;
+
 /* pcf_set_config_dir - forcibly override var_config_dir */
 
 void    pcf_set_config_dir(void)
@@ -57,4 +75,34 @@ void    pcf_set_config_dir(void)
     } else {
        var_config_dir = mystrdup(DEF_CONFIG_DIR);
     }
+
+    /*
+     * Populate the full pathname cache.
+     */
+    if (pcf_main_path)
+       myfree(pcf_main_path);
+    pcf_main_path =
+       concatenate(var_config_dir, "/", MAIN_CONF_FILE, (char *) 0);
+    if (pcf_master_path)
+       myfree(pcf_master_path);
+    pcf_master_path =
+       concatenate(var_config_dir, "/", MASTER_CONF_FILE, (char *) 0);
+}
+
+/* pcf_get_main_path - generate and return full main.cf pathname */
+
+const char *pcf_get_main_path(void)
+{
+    if (pcf_main_path == 0)
+       pcf_set_config_dir();
+    return (pcf_main_path);
+}
+
+/* pcf_get_master_path - generate and return full master.cf pathname */
+
+const char *pcf_get_master_path(void)
+{
+    if (pcf_master_path == 0)
+       pcf_set_config_dir();
+    return (pcf_master_path);
 }
index ac24a4d31b3d5f2f6af99a7761c664c733d34ed4..7877dbec176894e8248f2669cf314e9f69a7df6c 100644 (file)
@@ -1,5 +1,5 @@
-./postconf: warning: main.cf: syntax error after '}' in "{ldap:xxx, memcache:yy}x"
-./postconf: warning: main.cf: missing '}' in "{xx"
+./postconf: warning: ./main.cf: syntax error after '}' in "{ldap:xxx, memcache:yy}x"
+./postconf: warning: ./main.cf: missing '}' in "{xx"
 config_directory = .
 mydestination = foo bar pipemap:{ldap:xxx, memcache:yy}x randmap:{xx
 xxx_domain = foo
index 1c4be0cae8a062bce64e88cdd8196a6ecd2a7c5f..3236bdc975917a7e7493c531e48da00598a0a441 100644 (file)
@@ -1,7 +1,7 @@
-./postconf: warning: main.cf: #comment after other text is not allowed: #aaa1 ...
-./postconf: warning: main.cf: #comment after other text is not allowed: #aaa2 ...
-./postconf: warning: main.cf: #comment after other text is not allowed: #ccc2 ...
-./postconf: warning: main.cf: #comment after other text is not allowed: #bbb2 ...
+./postconf: warning: ./main.cf: #comment after other text is not allowed: #aaa1 ...
+./postconf: warning: ./main.cf: #comment after other text is not allowed: #aaa2 ...
+./postconf: warning: ./main.cf: #comment after other text is not allowed: #ccc2 ...
+./postconf: warning: ./main.cf: #comment after other text is not allowed: #bbb2 ...
 config_directory = .
 smtpd_client_restrictions = inline:{ { aaa0 = #aaa1 } #aaa2 }
 smtpd_helo_restrictions = pcre:{ { /bbb0 #bbb1/ } #bbb2 }
index 21fad76dd8566c0c928bce5c552b40adf03b2807..d3d8e938b254c1f2aa3ba2170bc6472e656e643b 100644 (file)
@@ -8,8 +8,7 @@ CFLAGS  = $(DEBUG) $(OPT) $(DEFS)
 TESTPROG= 
 PROG   = postlogd
 INC_DIR = ../../include
-LIBS   = ../../lib/lib$(LIB_PREFIX)dns$(LIB_SUFFIX) \
-       ../../lib/lib$(LIB_PREFIX)master$(LIB_SUFFIX) \
+LIBS   = ../../lib/lib$(LIB_PREFIX)master$(LIB_SUFFIX) \
        ../../lib/lib$(LIB_PREFIX)global$(LIB_SUFFIX) \
        ../../lib/lib$(LIB_PREFIX)util$(LIB_SUFFIX)
 
index a3700f5681f0704fe15dc643dc35afa2d24aa370..f69dec58ee000e05bc6e88d09fbb7462d3d5dfbd 100644 (file)
@@ -145,7 +145,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \
        vstream timecmp dict_cache midna_domain casefold strcasecmp_utf8 \
        vbuf_print split_qnameval vstream msg_logger byte_mask \
        known_tcp_ports dict_stream find_inet binhash hash_fnv argv \
-       clean_env
+       clean_env inet_prefix_top
 PLUGIN_MAP_SO = $(LIB_PREFIX)pcre$(LIB_SUFFIX) $(LIB_PREFIX)lmdb$(LIB_SUFFIX) \
        $(LIB_PREFIX)cdb$(LIB_SUFFIX) $(LIB_PREFIX)sdbm$(LIB_SUFFIX)
 HTABLE_FIX = NORANDOMIZE=1
@@ -604,6 +604,11 @@ argv: $(LIB)
        $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
        mv junk $@.o
 
+inet_prefix_top: $(LIB)
+       mv $@.o junk
+       $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS)
+       mv junk $@.o
+
 tests: all 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 host_port_test dict_tests \
@@ -613,7 +618,7 @@ tests: all valid_hostname_test mac_expand_test dict_test unescape_test \
        strcasecmp_utf8_test vbuf_print_test miss_endif_cidr_test \
        miss_endif_regexp_test split_qnameval_test vstring_test \
        vstream_test byte_mask_tests mystrtok_test known_tcp_ports_test \
-       binhash_test argv_test
+       binhash_test argv_test inet_prefix_top_test
  
 dict_tests: all dict_test \
        dict_pcre_tests dict_cidr_test dict_thash_test dict_static_test \
@@ -1075,6 +1080,9 @@ find_inet_test: find_inet find_inet.ref
 argv_test: argv
        $(SHLIB_ENV) ${VALGRIND} ./argv
 
+inet_prefix_top_test: inet_prefix_top
+       $(SHLIB_ENV) ${VALGRIND} ./inet_prefix_top
+
 depend: $(MAKES)
        (sed '1,/^# do not edit/!d' Makefile.in; \
        set -e; for i in [a-z][a-z0-9]*.c; do \
index 56da5ddacf8dad8ad5c4d2a93eed5499d03f4b75..01720968890626ef6dde7b4b572906b1602b0d01 100644 (file)
@@ -100,3 +100,84 @@ char   *inet_prefix_top(int af, const void *src, int prefix_len)
        vstring_sprintf_append(buf, "/%d", prefix_len);
     return (vstring_export(buf));
 }
+
+#ifdef TEST
+
+#include <stdlib.h>
+#include <msg_vstream.h>
+
+ /*
+  * TODO: add test cases for fatal and panic errors, intercept msg_fatal()
+  * and msg_panic(), and verify the expected error messages.
+  */
+typedef struct TEST_CASE {
+    int     in_af;
+    const char *in_address;
+    int     in_prefix_len;
+    const char *exp_prefix;
+} TEST_CASE;
+
+static TEST_CASE test_cases[] = {
+    AF_INET, "255.255.255.255", 32, "255.255.255.255",
+    AF_INET, "255.255.255.255", 28, "255.255.255.240/28",
+    AF_INET, "255.255.255.255", 4, "240.0.0.0/4",
+    AF_INET, "255.255.255.255", 0, "0.0.0.0/0",
+    AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 128, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
+    AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 124, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff0/124",
+    AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 4, "f000::/4",
+    AF_INET6, "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff", 0, "::/0",
+};
+
+#define TEST_CASE_COUNT (sizeof(test_cases) / sizeof(test_cases[0]))
+
+int     main(int argc, char **argv)
+{
+    TEST_CASE *tp;
+    union {
+       struct in_addr in_addr;
+       struct in6_addr in6_addr;
+    }       u;
+    char   *act_prefix;
+    int     pass = 0;
+    int     fail = 0;
+
+    msg_vstream_init(argv[0], VSTREAM_ERR);
+
+    for (tp = test_cases; tp < test_cases + TEST_CASE_COUNT; tp++) {
+       msg_info("RUN  %s/%d -> %s", tp->in_address, tp->in_prefix_len,
+                tp->exp_prefix);
+       switch (inet_pton(tp->in_af, tp->in_address, &u)) {
+       case -1:
+           msg_warn("inet_pton(af = %d, src = \"%s\", &u) failed: %m",
+                    tp->in_af, tp->in_address);
+           fail += 1;
+           msg_info("FAIL %s/%d -> %s", tp->in_address, tp->in_prefix_len,
+                    tp->exp_prefix);
+           break;
+       default:
+           msg_warn("inet_pton(af = %d, src = \"%s\", &u) failed",
+                    tp->in_af, tp->in_address);
+           fail += 1;
+           msg_info("FAIL %s/%d -> %s", tp->in_address, tp->in_prefix_len,
+                    tp->exp_prefix);
+           break;
+       case 1:
+           act_prefix = inet_prefix_top(tp->in_af, &u, tp->in_prefix_len);
+           if (strcmp(act_prefix, tp->exp_prefix) != 0) {
+               msg_warn("got \"%s\", want \"%s\"", act_prefix, tp->exp_prefix);
+               fail += 1;
+               msg_info("FAIL %s/%d -> %s", tp->in_address, tp->in_prefix_len,
+                        tp->exp_prefix);
+           } else {
+               pass += 1;
+               msg_info("PASS %s/%d -> %s", tp->in_address, tp->in_prefix_len,
+                        tp->exp_prefix);
+           }
+           break;
+       }
+    }
+    msg_info("PASS=%d FAIL=%d", pass, fail);
+    return (fail > 0);
+}
+
+#endif                                 /* TEST */