]> git.ipfire.org Git - thirdparty/postfix.git/commitdiff
postfix-2.0.8 v2.0.8
authorWietse Venema <wietse@porcupine.org>
Tue, 15 Apr 2003 05:00:00 +0000 (00:00 -0500)
committerViktor Dukhovni <viktor@dukhovni.org>
Tue, 5 Feb 2013 15:51:45 +0000 (15:51 +0000)
16 files changed:
postfix/HISTORY
postfix/INSTALL
postfix/RELEASE_NOTES
postfix/conf/sample-misc.cf
postfix/html/basic.html
postfix/html/virtual.5.html
postfix/man/man5/virtual.5
postfix/postfix-install
postfix/proto/virtual
postfix/src/global/mail_stream.c
postfix/src/global/mail_stream.h
postfix/src/global/mail_version.h
postfix/src/nqmgr/qmgr_message.c
postfix/src/qmgr/qmgr_message.c
postfix/src/smtpstone/smtp-source.c
postfix/src/util/match_ops.c

index 283e48572b99d2d12420f8d6d3906f84282655e5..638882f1a9f65d790d89edd0bcea05f760200168 100644 (file)
@@ -7700,8 +7700,30 @@ Apologies for any names omitted.
        for non-existent addresses. This required re-architecting
        the recipient table lookup code. File:  smtpd/smtpd_check.c.
 
+20030410
+
+       Safety: log a fatal error when a net/mask pattern has a
+       non-zero host part, so that mail delivery is deferred.
+       File: util/match_ops.c.
+
+20030411
+
+       Bugfix: extraneous warning about out-of-order original
+       recipient records by Patrik Rak. Files: *qmgr/qmgr_message.c.
+
+10030415
+
+       Workaround: log a warning and reset incoming queue file
+       time stamps when the file system clock is ahead of the
+       local clock, instead of ignoring new mail until the next
+       queue scan. The file system clock drift detection executes
+       only once per process instance, to minimize the performance
+       impact. File: global/mail_stream.c.
+
 Open problems:
 
+        Low: smtp-source may block when sending large test messages.
+
        Low: after successful delivery, per-queue window += 1/window,
        after failure, queue window -= 1 (Victor).
 
index b2361a4883442b0b89e909375aa9b68ada009d25..4544120cd655bb35e92367e898bcf255df50645e 100644 (file)
@@ -144,15 +144,19 @@ configuration directory other than /etc/postfix, use:
 
 Be sure to get the quotes right. These details matter a lot.
 
-Other parameters whose defaults can be specified in this way are:
-
-    Macro name          default value for
-    -------------------------------------
-    DEF_COMMAND_DIR     command_directory
-    DEF_DAEMON_DIR      daemon_directory
-    DEF_SENDMAIL_PATH   sendmail_path
-    DEF_MAILQ_PATH      mailq_path
-    DEF_NEWALIAS_PATH   newaliases_path
+Parameters whose defaults can be specified in this way are:
+
+    Macro name          default value for  typical default
+    -----------------------------------------------------------
+    DEF_COMMAND_DIR     command_directory /usr/sbin
+    DEF_CONFIG_DIR      config_directory  /etc/postfix
+    DEF_DAEMON_DIR      daemon_directory  /usr/libexec/postfix
+    DEF_MAILQ_PATH      mailq_path        /usr/bin/mailq
+    DEF_MANPAGE_DIR     manpage_directory /usr/local/man
+    DEF_NEWALIAS_PATH   newaliases_path   /usr/bin/newaliases
+    DEF_README_DIR      readme_directory  no (do not install)
+    DEF_SAMPLE_DIR      sample_directory  /etc/postfix
+    DEF_SENDMAIL_PATH   sendmail_path     /usr/sbin/sendmail
 
 In order to build Postfix for very large applications, where you
 expect to run more than 1000 delivery processes, you may need to
index 4977c0adadd276bd2170e1a60eac364865f14fcb..731f1a7117a300cf48645f94a0e487a431c874e2 100644 (file)
@@ -24,6 +24,23 @@ snapshot release).  Patches change the patchlevel and the release
 date. Snapshots change only the release date, unless they include
 the same bugfixes as a patch release.
 
+Incompatible changes with Postfix version 2.0.8 (released 20030415)
+===================================================================
+
+Too many people mess up their net/mask patterns, causing open
+mail relay problems. Postfix processes now abort when given a
+net/mask pattern with a non-zero host portion (for example,
+168.100.189.2/28), and suggest to specify the proper net/mask
+pattern instead (for example, 168.100.189.0/28).
+
+Major changes with Postfix version 2.0.8 (released 20030415)
+============================================================
+
+Workaround for file system clock drift that caused Postfix to ignore
+new mail (this could happen with file systems mounted from a server).
+Postfix now logs a warning and proceeds with only slightly reduced
+performance, instead of ignoring new mail.
+
 Incompatible changes with Postfix version 2.0.6 (released 20030305)
 ===================================================================
 
index f4911fc275431fcc4c1288fd8a8f2eed7ad8537f..54d6fea92f8a9aad9e9fcb333926e51b2951725d 100644 (file)
@@ -4,6 +4,13 @@
 # This file contains example settings for miscellaneous Postfix
 # configuration parameters.
 
+# The allow_min_user parameter specifies whether a recipient address
+# can have a '-' as the first character. By default, this is not
+# allowed, to avoid accidents with software that passes email addresses
+# via the command line.
+#
+allow_min_user = no
+
 # The always_bcc parameter specifies an optional address that
 # receives a copy of each message that enters the Postfix system,
 # not including bounces that are generated locally.
index abaf634544ace53dd07c43917eccdd7f33ef493a..0e4262009b4beaadf85ba73c03a1f4861a999db8 100644 (file)
@@ -355,9 +355,10 @@ top-level domain).
 <a name="mynetworks"> <h2> My own networks </h2> </a>
 
 The <b>mynetworks</b> parameter lists all networks that this machine
-somehow trusts. This information can be used by the <a href="uce.html">
-anti-UCE</a> features to recognize trusted SMTP clients that are
-allowed to relay mail through Postfix.
+somehow trusts. This information can be used by the <a
+href="uce.html#smtpd_recipient_restrictions"> anti-UCE</a> features
+to recognize trusted SMTP clients that are allowed to relay mail
+through Postfix.
 
 <p>
 
index 2f855eac83e729eaff9a306fbba52a9c92c86cd4..30011e06589a0acfa43d09334f8d28a05dfea5ec 100644 (file)
@@ -138,9 +138,9 @@ VIRTUAL(5)                                             VIRTUAL(5)
            <i>user2@virtual-alias.domain</i>   <i>address2,</i> <i>address3</i>
 
        The <i>virtual-alias.domain</i> <i>anything</i> entry is required for  a
-       virtual alias domain. Without this entry, mail is rejected
-       with "relay access denied", or bounces  with  "mail  loops
-       back to myself".
+       virtual alias domain. <b>Without</b> <b>this</b> <b>entry,</b> <b>mail</b> <b>is</b> <b>rejected</b>
+       <b>with</b> <b>"relay</b> <b>access</b> <b>denied",</b> <b>or</b> <b>bounces</b>  <b>with</b>  <b>"mail</b>  <b>loops</b>
+       <b>back</b> <b>to</b> <b>myself".</b>
 
        Do  not  specify virtual alias domain names in the <b>main.cf</b>
        <b>mydestination</b> or <b>relay</b><i>_</i><b>domains</b> configuration parameters.
index 98a64d047f833c5f59742f37aa37d1c18ac10a1e..bec609898de381e6a922c8cd4282cb6d7828fa27 100644 (file)
@@ -141,9 +141,9 @@ See the output from \fBpostconf -m\fR for available database types.
 .fi
 .sp
 The \fIvirtual-alias.domain anything\fR entry is required for a
-virtual alias domain. Without this entry, mail is rejected
+virtual alias domain. \fBWithout this entry, mail is rejected
 with "relay access denied", or bounces with
-"mail loops back to myself".
+"mail loops back to myself".\fR
 
 Do not specify virtual alias domain names in the \fBmain.cf
 mydestination\fR or \fBrelay_domains\fR configuration parameters.
index 6bb2044b29ab0e20be709b0d43a70def50b4a586..0bb3b3523a61590be54ba6f58f4a4a0f4b761d1e 100644 (file)
 #      The built-in default directory name is the current directory.
 #      This parameter setting is not recorded in the installed main.cf file.
 # .IP config_directory
-#      The destination directory for Postfix configuration files.
+#      The final destination directory for Postfix configuration files.
 #      The built-in default directory name is /etc/postfix.
-#      This parameter setting is not recorded in the installed main.cf file.
+#      This parameter setting is not recorded in the installed main.cf file
+#      and can be changed only by recompiling Postfix.
 # .IP daemon_directory
-#      The destination directory for Postfix daemon programs. This directory
-#      should not be in the command search path of any users.
+#      The final destination directory for Postfix daemon programs. This
+#      directory should not be in the command search path of any users.
 #      The built-in default directory name is /usr/libexec/postfix.
 #      This parameter setting is recorded in the installed main.cf file.
 # .IP command_directory
-#      The destination directory for Postfix administrative commands. This
-#      directory should be in the command search path of adminstrative users.
-#      The built-in default directory name is system dependent.
+#      The final destination directory for Postfix administrative commands.
+#      This directory should be in the command search path of adminstrative
+#      users. The built-in default directory name is system dependent.
 #      This parameter setting is recorded in the installed main.cf file.
 # .IP queue_directory
-#      The destination directory for Postfix queues.
+#      The final destination directory for Postfix queues.
 #      The built-in default directory name is /var/spool/postfix.
 #      This parameter setting is recorded in the installed main.cf file.
 # .IP sendmail_path
-#      The full destination pathname for the Postfix sendmail command.
+#      The final destination pathname for the Postfix sendmail command.
 #      This is the Sendmail-compatible mail posting interface.
 #      The built-in default pathname is system dependent.
 #      This parameter setting is recorded in the installed main.cf file.
 # .IP newaliases_path
-#      The full destination pathname for the Postfix newaliases command.
+#      The final destination pathname for the Postfix newaliases command.
 #      This is the Sendmail-compatible command to build alias databases
 #      for the Postfix local delivery agent.
 #      The built-in default pathname is system dependent.
 #      This parameter setting is recorded in the installed main.cf file.
 # .IP mailq_path
-#      The full destination pathname for the Postfix mailq command.
+#      The final destination pathname for the Postfix mailq command.
 #      This is the Sendmail-compatible command to list the mail queue.
 #      The built-in default pathname is system dependent.
 #      This parameter setting is recorded in the installed main.cf file.
@@ -286,30 +287,30 @@ distribution to other machines."
 tempdir_prompt="a directory for scratch files while installing
 Postfix.  You must have write permission in this directory."
 
-config_directory_prompt="the destination directory for installed
-Postfix configuration files."
+config_directory_prompt="the final destination directory for
+installed Postfix configuration files."
 
-daemon_directory_prompt="the destination directory for installed
-Postfix daemon programs.  This directory should not be in the
-command search path of any users."
+daemon_directory_prompt="the final destination directory for
+installed Postfix daemon programs.  This directory should not be
+in the command search path of any users."
 
-command_directory_prompt="the destination directory for installed
-Postfix administrative commands.  This directory should be in the
-command search path of adminstrative users."
+command_directory_prompt="the final destination directory for
+installed Postfix administrative commands.  This directory should
+be in the command search path of adminstrative users."
 
-queue_directory_prompt="the destination directory for Postfix
+queue_directory_prompt="the final destination directory for Postfix
 queues."
 
-sendmail_path_prompt="the full destination pathname for the installed
-Postfix sendmail command. This is the Sendmail-compatible mail
-posting interface."
+sendmail_path_prompt="the final destination pathname for the
+installed Postfix sendmail command. This is the Sendmail-compatible
+mail posting interface."
 
-newaliases_path_prompt="the full destination pathname for the
+newaliases_path_prompt="the final destination pathname for the
 installed Postfix newaliases command.  This is the Sendmail-compatible
 command to build alias databases for the Postfix local delivery
 agent."
 
-mailq_path_prompt="the full destination pathname for the installed
+mailq_path_prompt="the final destination pathname for the installed
 Postfix mailq command.  This is the Sendmail-compatible mail queue
 listing command."
 
index 5c559a15a87ed7e6f5d106f4693bfd3673267588..f0d904aa0f81ce5d2b2c093281fbd3ad79ffe904 100644 (file)
 # .fi
 # .sp
 #      The \fIvirtual-alias.domain anything\fR entry is required for a
-#      virtual alias domain. Without this entry, mail is rejected
+#      virtual alias domain. \fBWithout this entry, mail is rejected
 #      with "relay access denied", or bounces with 
-#      "mail loops back to myself".
+#      "mail loops back to myself".\fR
 #
 #      Do not specify virtual alias domain names in the \fBmain.cf
 #      mydestination\fR or \fBrelay_domains\fR configuration parameters.
index 6e4812e03ed361938a80c7795d134401512d814f..094cb00b05c1ba3c37b84836b83ba425af4038d7 100644 (file)
@@ -83,6 +83,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <errno.h>
+#include <utime.h>
 
 /* Utility library. */
 
@@ -110,9 +111,10 @@ static VSTRING *id_buf;
 
 /* mail_stream_cleanup - clean up after success or failure */
 
-void    mail_stream_cleanup(MAIL_STREAM * info)
+void    mail_stream_cleanup(MAIL_STREAM *info)
 {
     FREE_AND_WIPE(info->close, info->stream);
+    FREE_AND_WIPE(myfree, info->queue);
     FREE_AND_WIPE(myfree, info->id);
     FREE_AND_WIPE(myfree, info->class);
     FREE_AND_WIPE(myfree, info->service);
@@ -121,10 +123,17 @@ void    mail_stream_cleanup(MAIL_STREAM * info)
 
 /* mail_stream_finish_file - finish file mail stream */
 
-static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
+static int mail_stream_finish_file(MAIL_STREAM *info, VSTRING *unused_why)
 {
     int     status = 0;
     static char wakeup[] = {TRIGGER_REQ_WAKEUP};
+    struct stat st;
+    time_t  now;
+    struct utimbuf tbuf;
+    char   *path_to_reset = 0;
+    static int incoming_fs_clock_ok = 0;
+    static int incoming_clock_warned = 0;
+    int     check_incoming_fs_clock;
 
     /*
      * Make sure the message makes it to file. Set the execute bit when no
@@ -137,15 +146,50 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
      * as are files with unknown record type codes. Every Postfix queue file
      * must end with an explicit END record. Postfix queue files without END
      * record are discarded.
+     * 
+     * Attempt to detect file system clocks that are ahead of local time, but
+     * don't check the file system clock all the time. The effect of file
+     * system clock drift can be difficult to understand (Postfix ignores new
+     * mail until the next queue run).
+     * 
+     * This clock drift detection code may not work with file systems that work
+     * on a local copy of the file and that update the server only after the
+     * file is closed.
      */
+    check_incoming_fs_clock =
+       (!incoming_fs_clock_ok && !strcmp(info->queue, MAIL_QUEUE_INCOMING));
+
     if (vstream_fflush(info->stream)
        || fchmod(vstream_fileno(info->stream), 0700 | info->mode)
 #ifdef HAS_FSYNC
        || fsync(vstream_fileno(info->stream))
 #endif
+       || (check_incoming_fs_clock
+           && fstat(vstream_fileno(info->stream), &st) < 0)
        )
        status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
 
+#ifdef TEST
+    st.st_mtime += 10;
+#endif
+
+    /*
+     * Work around file system clocks that are ahead of local time.
+     */
+    if (status == CLEANUP_STAT_OK && check_incoming_fs_clock) {
+       if (st.st_mtime <= time(&now)) {
+           incoming_fs_clock_ok = 1;
+       } else {
+           path_to_reset = mystrdup(VSTREAM_PATH(info->stream));
+           if (incoming_clock_warned == 0) {
+               msg_warn("file system clock is %d seconds ahead of local clock",
+                        (int) (st.st_mtime - now));
+               msg_warn("resetting file time stamps - this hurts performance");
+               incoming_clock_warned = 1;
+           }
+       }
+    }
+
     /*
      * Close the queue file and mark it as closed. Be prepared for
      * vstream_fclose() to fail even after vstream_fflush() and fsync()
@@ -158,6 +202,16 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
        status = (errno == EFBIG ? CLEANUP_STAT_SIZE : CLEANUP_STAT_WRITE);
     info->stream = 0;
 
+    /*
+     * Work around file system clocks that are ahead of local time.
+     */
+    if (path_to_reset != 0) {
+       tbuf.actime = tbuf.modtime = now;
+       if (utime(path_to_reset, &tbuf) < 0 && errno != ENOENT)
+           msg_fatal("%s: update file time stamps: %m", info->id);
+       myfree(path_to_reset);
+    }
+
     /*
      * When all is well, notify the next service that a new message has been
      * queued.
@@ -174,7 +228,7 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why)
 
 /* mail_stream_finish_ipc - finish IPC mail stream */
 
-static int mail_stream_finish_ipc(MAIL_STREAM * info, VSTRING *why)
+static int mail_stream_finish_ipc(MAIL_STREAM *info, VSTRING *why)
 {
     int     status = CLEANUP_STAT_WRITE;
 
@@ -199,7 +253,7 @@ static int mail_stream_finish_ipc(MAIL_STREAM * info, VSTRING *why)
 
 /* mail_stream_finish - finish action */
 
-int     mail_stream_finish(MAIL_STREAM * info, VSTRING *why)
+int     mail_stream_finish(MAIL_STREAM *info, VSTRING *why)
 {
     return (info->finish(info, why));
 }
@@ -220,6 +274,7 @@ MAIL_STREAM *mail_stream_file(const char *queue, const char *class,
     info->stream = stream;
     info->finish = mail_stream_finish_file;
     info->close = vstream_fclose;
+    info->queue = mystrdup(queue);
     info->id = mystrdup(basename(VSTREAM_PATH(stream)));
     info->class = mystrdup(class);
     info->service = mystrdup(service);
@@ -247,6 +302,7 @@ MAIL_STREAM *mail_stream_service(const char *class, const char *name)
        info->stream = stream;
        info->finish = mail_stream_finish_ipc;
        info->close = vstream_fclose;
+       info->queue = 0;
        info->id = mystrdup(vstring_str(id_buf));
        info->class = 0;
        info->service = 0;
@@ -297,6 +353,7 @@ MAIL_STREAM *mail_stream_command(const char *command)
        info->stream = stream;
        info->finish = mail_stream_finish_ipc;
        info->close = vstream_pclose;
+       info->queue = 0;
        info->id = mystrdup(vstring_str(id_buf));
        info->class = 0;
        info->service = 0;
index c9fbfd97a78a2ba46f0f821e8d990711a72f6cde..a1e64f13ec7df2b0eb8480f189c67f5cdfba0e98 100644 (file)
@@ -27,6 +27,7 @@ typedef int (*MAIL_STREAM_CLOSE_FN) (VSTREAM *);
 
 struct MAIL_STREAM {
     VSTREAM *stream;                   /* file or pipe or socket */
+    char   *queue;                     /* (initial) queue name */
     char   *id;                                /* queue id */
     MAIL_STREAM_FINISH_FN finish;      /* finish code */
     MAIL_STREAM_CLOSE_FN close;                /* close stream */
index d3ee7e8c207e4d3708c0821758688f0b689de316..f6422cad23ccee6fe2b5d2b6fc1eb1d9690ee02f 100644 (file)
   * Patches change the patchlevel and the release date. Snapshots change the
   * release date only, unless they include the same bugfix as a patch release.
   */
-#define MAIL_RELEASE_DATE      "20030319"
+#define MAIL_RELEASE_DATE      "20030415"
 
 #define VAR_MAIL_VERSION       "mail_version"
-#define DEF_MAIL_VERSION       "2.0.7"
+#define DEF_MAIL_VERSION       "2.0.8"
 extern char *var_mail_version;
 
  /*
index 943d3b75732a1e9fd77ff77b401118675cf7b6f0..0da7e08cdfae2f0d9fca4d560497c0b73e55c806 100644 (file)
@@ -397,6 +397,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                message->rcpt_unread--;
            }
        } else if (rec_type == REC_TYPE_RCPT) {
+           /* See also below for code setting orig_rcpt. */
            if (message->rcpt_list.len < recipient_limit) {
                message->rcpt_unread--;
                qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
@@ -467,7 +468,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
            orig_rcpt = 0;
        }
        if (rec_type == REC_TYPE_ORCP)
-           orig_rcpt = mystrdup(start);
+           /* See also above for code clearing orig_rcpt. */
+           if (message->rcpt_offset == 0)
+               orig_rcpt = mystrdup(start);
     } while (rec_type > 0 && rec_type != REC_TYPE_END);
 
     /*
index 233477cd850bc1d7a4edfc3079f8143b67f3b5e6..9afac7ff9c2e2e5f42f2d1da192e197404a7386e 100644 (file)
@@ -273,6 +273,7 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
                       "queue %s", message->queue_name);
            }
        } else if (rec_type == REC_TYPE_RCPT) {
+           /* See also below for code setting orig_rcpt. */
 #define FUDGE(x)       ((x) * (var_qmgr_fudge / 100.0))
            if (message->rcpt_list.len < FUDGE(var_qmgr_rcpt_limit)) {
                qmgr_rcpt_list_add(&message->rcpt_list, curr_offset,
@@ -347,7 +348,9 @@ static int qmgr_message_read(QMGR_MESSAGE *message)
            orig_rcpt = 0;
        }
        if (rec_type == REC_TYPE_ORCP)
-           orig_rcpt = mystrdup(start);
+           /* See also above for code clearing orig_rcpt. */
+           if (message->rcpt_offset == 0)
+               orig_rcpt = mystrdup(start);
     } while (rec_type > 0 && rec_type != REC_TYPE_END);
 
     /*
index b5aeaddc739f13351214fa5ab82477e0f6926ac2..9eafa9a187b20985caff93e55f80fc848966f747 100644 (file)
@@ -651,6 +651,7 @@ static void data_done(int unused_event, char *context)
            mydate = mail_date(time((time_t *) 0));
            mypid = getpid();
        }
+#if SMTP_PRINTF_NO_LONGER_FLUSHES
        smtp_printf(session->stream, "From: <%s>", sender);
        smtp_printf(session->stream, "To: <%s>", recipient);
        smtp_printf(session->stream, "Date: %s", mydate);
@@ -658,6 +659,16 @@ static void data_done(int unused_event, char *context)
                    mypid, vstream_fileno(session->stream), message_count, var_myhostname);
        if (subject)
            smtp_printf(session->stream, "Subject: %s", subject);
+#else
+       vstream_fprintf(session->stream, "From: <%s>\r\n", sender);
+       vstream_fprintf(session->stream, "To: <%s>\r\n", recipient);
+       vstream_fprintf(session->stream, "Date: %s\r\n", mydate);
+       vstream_fprintf(session->stream, "Message-Id: <%04x.%04x.%04x@%s>\r\n",
+                     mypid, vstream_fileno(session->stream), message_count,
+                       var_myhostname);
+       if (subject)
+           vstream_fprintf(session->stream, "Subject: %s\r\n", subject);
+#endif
        smtp_fputs("", 0, session->stream);
     }
 
@@ -672,6 +683,11 @@ static void data_done(int unused_event, char *context)
        smtp_fputs("La de da de da 3.", 17, session->stream);
        smtp_fputs("La de da de da 4.", 17, session->stream);
     } else {
+
+       /*
+        * XXX This may cause the process to block with message content
+        * larger than VSTREAM_BUFIZ bytes.
+        */
        smtp_fputs(message_data, message_length, session->stream);
     }
 
index 1bde84abdfa463aabd0115b48c78d0448a9c4037..d1586f7be6a423c446110c4bc650b6dc4e7aa0cd 100644 (file)
@@ -207,6 +207,7 @@ int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
     unsigned long mask_bits;
     unsigned long net_bits;
     unsigned long addr_bits;
+    struct in_addr net_addr;
 
     if (msg_verbose)
        msg_info("%s: %s ~? %s", myname, addr, pattern);
@@ -242,7 +243,14 @@ int     match_hostaddr(int unused_flags, const char *addr, const char *pattern)
        if (addr_bits == INADDR_NONE)
            msg_fatal("%s: bad address argument: %s", myname, addr);
        mask_bits = htonl((0xffffffff) << (BITS_PER_ADDR - mask_shift));
-       return ((addr_bits & mask_bits) == (net_bits & mask_bits));
+       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);
 }