changeset 108:1c7677042b78

move to autoconf/automake/docbook
author carl
date Sun, 18 Dec 2005 12:05:05 -0800
parents eeaaecda4acc
children 9978e29c4d71
files Makefile.am package src/Makefile.am xml/dnsbl.in
diffstat 4 files changed, 681 insertions(+), 286 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.am	Sun Dec 18 09:50:25 2005 -0800
+++ b/Makefile.am	Sun Dec 18 12:05:05 2005 -0800
@@ -1,21 +1,20 @@
 SUBDIRS = src man html info
 hackdir = $(sysconfdir)
-hack_SCRIPTS = syslog2iptables
-sysconf_DATA = syslog2iptables.conf
-CLEANFILES = syslog2iptables xml/syslog2iptables xml/Makefile
-EXTRA_DIST = syslog2iptables.rc syslog2iptables.conf syslog2iptables.spec $(wildcard xml/h*) $(wildcard xml/M*) $(wildcard xml/s*)
+hack_SCRIPTS = dnsbl
+dconfdir = $(sysconfdir)/dnsbl
+dconf_DATA = dnsbl.conf hosts-ignore.conf html-tags.conf tld.conf
+CLEANFILES = dnsbl xml/dnsbl xml/Makefile
+EXTRA_DIST = dnsbl.rc $(dconf_DATA) dnsbl.spec $(wildcard xml/h*) $(wildcard xml/M*) $(wildcard xml/s*)
 
-syslog2iptables: $(srcdir)/syslog2iptables.rc
-	   rm -f syslog2iptables
-	   echo "#!" $(BASH) >syslog2iptables
-	   cat $(srcdir)/syslog2iptables.rc     | \
+dnsbl: $(srcdir)/dnsbl.rc
+	   rm -f dnsbl
+	   echo "#!" $(BASH) >dnsbl
+	   cat $(srcdir)/dnsbl.rc     | \
 	       sed -e "s,SBINDIR,$(sbindir),g"  | \
-	       sed -e "s,SYSCONFDIR,$(sysconfdir),g" >>syslog2iptables
+	       sed -e "s,SYSCONFDIR,$(sysconfdir),g" >>dnsbl
 
-chkconfig: syslog2iptables
-	   mv -f $(sysconfdir)/syslog2iptables /etc/rc.d/init.d
-	   /sbin/chkconfig --del syslog2iptables
-	   /sbin/chkconfig --add syslog2iptables
-	   /sbin/chkconfig --level 2345 syslog2iptables on
-	   /etc/rc.d/init.d/syslog2iptables start
+chkconfig: dnsbl
+	   mv -f $(sysconfdir)/dnsbl /etc/rc.d/init.d
+	   /sbin/chkconfig --del dnsbl
+	   /sbin/chkconfig --add dnsbl
 
--- a/package	Sun Dec 18 09:50:25 2005 -0800
+++ b/package	Sun Dec 18 12:05:05 2005 -0800
@@ -29,6 +29,10 @@
                     /etc/rc.d/init.d/$NAME stop
                 fi
                 make chkconfig
+                if [ -f /etc/rc.d/init.d/$NAME ]; then
+                    chkconfig $NAME on
+                    /etc/rc.d/init.d/$NAME start
+                fi
             cd ..
         cd ..
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/Makefile.am	Sun Dec 18 12:05:05 2005 -0800
@@ -0,0 +1,12 @@
+sbin_PROGRAMS = dnsbl
+dnsbl_SOURCES = dnsbl.cpp dnsbl.h context.cpp context.h tokenizer.cpp tokenizer.h scanner.cpp scanner.h includes.h
+
+# set the include path found by configure
+INCLUDES= $(all_includes)
+
+# the library search path.
+dnsbl_LDFLAGS = $(all_libraries) -pthread
+
+# default compile flags
+dnsbl_CXXFLAGS = -pthread
+
--- a/xml/dnsbl.in	Sun Dec 18 09:50:25 2005 -0800
+++ b/xml/dnsbl.in	Sun Dec 18 12:05:05 2005 -0800
@@ -1,40 +1,152 @@
-<html>
+<reference>
+    <title>@PACKAGE@ Sendmail milter - Version @VERSION@</title>
+    <partintro>
+        <title>Packages</title>
+        <para>The various source and binary packages are available at <ulink
+        url="http://www.five-ten-sg.com/@PACKAGE@/packages">http://www.five-ten-sg.com/@PACKAGE@/packages</ulink>
+        The most recent documentation is available at <ulink
+        url="http://www.five-ten-sg.com/@PACKAGE@/">http://www.five-ten-sg.com/@PACKAGE@/</ulink>
+        </para>
+
+    </partintro>
+
+    <refentry id="@PACKAGE@.1">
+        <refentryinfo>
+            <date>2005-12-18</date>
+        </refentryinfo>
 
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
-<title>DNSBL Sendmail milter - Version 5.10</title>
-</head>
+        <refmeta>
+            <refentrytitle>@PACKAGE@</refentrytitle>
+            <manvolnum>1</manvolnum>
+            <refmiscinfo>@PACKAGE@ @VERSION@</refmiscinfo>
+        </refmeta>
+
+        <refnamediv id='name.1'>
+            <refname>@PACKAGE@</refname>
+            <refpurpose>a sendmail milter with per-user dnsbl filtering</refpurpose>
+        </refnamediv>
+
+        <refsynopsisdiv id='synopsis.1'>
+            <title>Synopsis</title>
+            <cmdsynopsis>
+                <command>@PACKAGE@</command>
+                <arg><option>-c</option></arg>
+                <arg><option>-s</option></arg>
+                <arg><option>-d <replaceable class="parameter">n</replaceable></option></arg>
+                <arg><option>-e <replaceable class="parameter">from|to</replaceable></option></arg>
+                <arg><option>-r <replaceable class="parameter">local-domain-socket</replaceable></option></arg>
+                <arg><option>-p <replaceable class="parameter">sendmail-socket</replaceable></option></arg>
+                <arg><option>-t <replaceable class="parameter">timeout</replaceable></option></arg>
+            </cmdsynopsis>
+        </refsynopsisdiv>
 
-<center>Introduction</center>
-<p>This milter is released under the GPL license version 2 included in
-the LICENSE file in the distribution, and also available at
-<a href="http://www.gnu.org/licenses/gpl.html">http://www.gnu.org/licenses/gpl.html</a>
+        <refsect1 id='options.1'>
+            <title>Options</title>
+            <variablelist>
+                <varlistentry>
+                    <term>-c</term>
+                    <listitem>
+                        <para>
+                            Load the configuration file, print a cannonical form
+                            of the configuration on stdout, and exit.
+                       </para>
+                   </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>-s</term>
+                    <listitem>
+                        <para>
+                            Stress test the configuration loading code by repeating
+                            the load/free cycle in an infinite loop.
+                       </para>
+                   </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>-d <replaceable class="parameter">n</replaceable></term>
+                    <listitem>
+                        <para>
+                            Set the debug level to <replaceable class="parameter">n</replaceable>.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>-e <replaceable class="parameter">from|to</replaceable></term>
+                    <listitem>
+                        <para>
+                            Print the results of looking up the from and to addresses in the
+                            current configuration. The | character is used to separate the from and to
+                            addresses in the argument to the -e switch.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>-r <replaceable class="parameter">local-domain-socket</replaceable></term>
+                    <listitem>
+                        <para>
+                            Set the local socket used for the connection to our own dns resolver processes.
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>-p <replaceable class="parameter">sendmail-socket</replaceable></term>
+                    <listitem>
+                        <para>
+                            Set the socket used for the milter connection to sendmail. This is either
+                            "inet:port@ip-address" or "local:local-domain-socket-file-name".
+                        </para>
+                    </listitem>
+                </varlistentry>
+                <varlistentry>
+                    <term>-t <replaceable class="parameter">timeout</replaceable></term>
+                    <listitem>
+                        <para>
+                            Set the timeout in seconds used for communication with sendmail.
+                        </para>
+                    </listitem>
+                </varlistentry>
+            </variablelist>
+        </refsect1>
 
-<p>Consider the case of a mail server that is acting as secondary MX for
-a collection of clients, each of which has a collection of mail domains.
+        <refsect1>
+            <title>Usage</title>
+            <para><command>@PACKAGE@</command> -c</para>
+            <para><command>@PACKAGE@</command> -s</para>
+            <para><command>@PACKAGE@</command> -d 2</para>
+            <para><command>@PACKAGE@</command> -e'someone@aol.com|localname@mydomain.tld'</para>
+            <para><command>@PACKAGE@</command> -d 10 -r /var/run/dnsbl/dnsbl.resolver.sock -p local:/var/run/dnsbl/dnsbl.sock</para>
+        </refsect1>
+
+        <refsect1 id='introduction.1'>
+            <title>Introduction</title>
+            <para>
+                Consider the case of a mail server that is acting as secondary MX for a
+                collection of clients, each of which has a collection of mail domains.
 Each client may use their own collection of DNSBLs on their primary mail
 server.  We present here a mechanism whereby the backup mail server can
 use the correct set of DNSBLs for each recipient for each message.  As a
 side-effect, it gives us the ability to customize the set of DNSBLs on a
 per-recipient basis, so that fred@example.com could use SPEWS and the
 SBL, where all other users @example.com use only the SBL.
-
-<p>This milter can also verify the envelope from/recipient pairs with
-the primary MX server.  This allows the backup mail servers to properly
+            </para>
+            <para>
+                This milter can also verify the envelope from/recipient pairs with the
+                primary MX server.  This allows the backup mail servers to properly
 reject mail sent to invalid addresses.  Otherwise, the backup mail
 servers will accept that mail, and then generate a bounce message when
 the message is forwarded to the primary server (and rejected there with
 no such user).
-
-<p>This milter will also decode (uuencode, base64, mime, html entity,
-url encodings) and scan for HTTP and HTTPS URLs and bare hostnames in
-the body of the mail.  If any of those host names have A or NS records
-on the SBL (or a single configurable DNSBL), the mail will be rejected
+            </para>
+            <para>
+                This milter will also decode (uuencode, base64, mime, html entity, url
+                encodings) and scan for HTTP and HTTPS URLs and bare hostnames in the
+                body of the mail.  If any of those host names have A or NS records on
+                the SBL (or a single configurable DNSBL), the mail will be rejected
 unless previously whitelisted.  This milter also counts the number of
 invalid HTML tags, and can reject mail if that count exceeds your
 specified limit.
-
-<p>The DNSBL milter reads a text configuration file (dnsbl.conf) on
+            </para>
+            <para>
+                The DNSBL milter reads a text configuration file (dnsbl.conf) on
 startup, and whenever the config file (or any of the referenced include
 files) is changed.  The entire configuration file is case insensitive.
 If the configuration cannot be loaded due to a syntax error, the milter
@@ -43,17 +155,22 @@
 root from dnsbl@$hostname.  You probably want to added dnsbl@$hostname
 to your /etc/mail/virtusertable since otherwise sendmail will reject
 that message.
+            </para>
+        </refsect1>
 
-<hr> <center>DCC Issues</center>
-<p>If you are also using the <a
-href="http://www.rhyolite.com/anti-spam/dcc/">DCC</a> milter, there are
-a few considerations.  You may need to whitelist senders from the DCC
-bulk detector, or from the DNS based lists.  Those are two very
+        <refsect1 id='todo.1'>
+            <title>DCC Issues</title>
+            <para>
+                If you are also using the <ulink
+                url="http://www.rhyolite.com/anti-spam/dcc/">DCC</ulink> milter, there
+                are a few considerations.  You may need to whitelist senders from the
+                DCC bulk detector, or from the DNS based lists.  Those are two very
 different reasons for whitelisting.  The former is done thru the DCC
 whiteclnt config file, the later is done thru the DNSBL milter config
 file.
-
-<p>You may want to blacklist some specific senders or sending domains.
+            </para>
+            <para>
+                You may want to blacklist some specific senders or sending domains.
 This could be done thru either the DCC (on a global basis, or for a
 specific single recipient).  We prefer to do such blacklisting via the
 DNSBL milter config, since it can be done for a collection of recipient
@@ -61,48 +178,58 @@
 entire message in the DCC log files.  The DNSBL milter approach has the
 feature that the mail is rejected earlier (at RCPT TO time), and the
 sending machine just gets a generic "550 5.7.1 no such user" message.
-
-<p>The DCC whiteclnt file can be included in the DNSBL milter config by
-the dcc_to and dcc_from statements.  This will import the (env_to,
-env_from, and substitute mail_host) entries from the DCC config into the
-DNSBL config.  This allows using the DCC config as the single point for
+            </para>
+            <para>
+                The DCC whiteclnt file can be included in the DNSBL milter config by the
+                dcc_to and dcc_from statements.  This will import the (env_to, env_from,
+                and substitute mail_host) entries from the DCC config into the DNSBL
+                config.  This allows using the DCC config as the single point for
 white/blacklisting.
-
-<p>Consider the case where you have multiple clients, each with their
-own mail servers, and each running their own DCC milters.  Each client
-is using the DCC facilities for envelope from/to white/blacklisting.
+            </para>
+            <para>
+                Consider the case where you have multiple clients, each with their own
+                mail servers, and each running their own DCC milters.  Each client is
+                using the DCC facilities for envelope from/to white/blacklisting.
 Presumably you can use rsync or scp to fetch copies of your clients DCC
 whiteclnt files on a regular basis.  Your mail server, acting as a
 backup MX for your clients, can use the DNSBL milter, and include those
 client DCC config files.  The envelope from/to white/blacklisting will
 be appropriately tagged and used only for the domains controlled by each
 of those clients.
-
-<hr> <center>Definitions</center>
-
-<p>CONTEXT - a collection of parameters that defines the filtering
-context to be used for a collection of envelope recipient addresses.
-The context includes such things as the list of DNSBLs to be used, and
-the various content filtering parameters.
-
-<p>DNSBL - a named DNS based blocking list is defined by a dns suffix
-(e.g. sbl-xbl.spamhaus.org) and a message string that is used to
-generate the "550 5.7.1" smtp error return code.  The names of these
-DNSBLs will be used to define the DNSBL-LISTs.
+            </para>
+        </refsect1>
 
-<p>DNSBL-LIST - a named list of DNSBLs that will be used for specific
+        <refsect1 id='todo.1'>
+            <title>Definitions</title>
+            <para>
+                CONTEXT - a collection of parameters that defines the filtering context
+                to be used for a collection of envelope recipient addresses.  The
+                context includes such things as the list of DNSBLs to be used, and the
+                various content filtering parameters.
+            </para>
+            <para>
+                DNSBL - a named DNS based blocking list is defined by a dns suffix (e.g.
+                sbl-xbl.spamhaus.org) and a message string that is used to generate the
+                "550 5.7.1" smtp error return code.  The names of these DNSBLs will be
+                used to define the DNSBL-LISTs.
+            </para>
+            <para>
+                DNSBL-LIST - a named list of DNSBLs that will be used for specific
 recipients or recipient domains.
-
-<hr> <center>Filtering Procedure</center>
+            </para>
+        </refsect1>
 
-<p>If the client has authenticated with sendmail, the mail is accepted,
-the filtering contexts are not used, the dns lists are not checked, and
-the body content is not scanned.  Otherwise, we follow these steps for
-each recipient.
-
-<ol>
-
-<li>The envelope to email address is used to find an initial filtering
+        <refsect1 id='todo.1'>
+            <title>Filtering Procedure</title>
+            <para>
+                If the client has authenticated with sendmail, the mail is accepted, the
+                filtering contexts are not used, the dns lists are not checked, and the
+                body content is not scanned.  Otherwise, we follow these steps for each
+                recipient.
+            </para>
+            <orderedlist>
+                <listitem>
+                    The envelope to email address is used to find an initial filtering
 context.  We first look for a context that specified the full email
 address in the env_to statement.  If that is not found, we look for a
 context that specified the entire domain name of the envelope recipient
@@ -110,200 +237,453 @@
 that specified the user@ part of the envelope recipient in the env_to
 statement.  If that is not found, we use the first top level context
 defined in the config file.
-
-<br><br><li>The initial filtering context may redirect to a child
-context based on the values in the initial context's env_from statement.
-We look for [1) the full envelope from email address, 2) the domain name
+                </listitem>
+                <listitem>
+                    The initial filtering context may redirect to a child context based on
+                    the values in the initial context's env_from statement.  We look for [1)
+                    the full envelope from email address, 2) the domain name part of the
+                    envelope from address, 3) the user@ part of the envelope from address]
+                    in that context's env_from statement, with values that point to a child
+                    context.  If such an entry is found, we switch to that child filtering
+                    context.
+                </listitem>
+                <listitem>
+                    We lookup [1) the full envelope from email address, 2) the domain name
 part of the envelope from address, 3) the user@ part of the envelope
-from address] in that context's env_from statement, with values that
-point to a child context.  If such an entry is found, we switch to that
-child filtering context.
-
-<br><br><li>We lookup [1) the full envelope from email address, 2) the
-domain name part of the envelope from address, 3) the user@ part of the
-envelope from address] in the filtering context env_from statement.
-That results in one of (white, black, unknown, inherit).
-
-<br><br><li>If the answer is black, mail to this recipient is rejected
-with "no such user", and the dns lists are not checked.
-
-<br><br><li>If the answer is white, mail to this recipient is accepted
-and the dns lists are not checked.
-
-<br><br><li>If the answer is unknown, we don't reject yet, but the dns
-lists will be checked, and the content may be scanned.
-
-<br><br><li>If the answer is inherit, we repeat the envelope from search
-in the parent context.
-
-<br><br><li>The dns lists specified in the filtering context are checked
-and the mail is rejected if any list has an A record for the standard
-dns based lookup scheme (reversed octets of the client followed by the
-dns suffix).
-
-<br><br><li>If the mail has not been accepted or rejected yet, we look
-for a verification context, which is the closest ancestor of the
-filtering context that both specifies a verification host, and which
-covers the envelope to address.  If we find such a verification context,
-and the verification host is not our own hostname, we open an smtp
-conversation with that verification host.  The current envelope from and
-recipient to values are passed to that verification host.  If we receive
-a 5xy response those commands, we reject the current recipient with "no
-such user".
-
-<br><br><li>If the mail has not been accepted or rejected yet, and the
-filtering context enables content filtering, and this is the first such
-recipient in this smtp transaction, we set the content filtering
-parameters from this context, and enable content filtering for the body
-of this message.
-
-</ol>
-
-<p>If content filtering is enabled for this body, the mail text is
-decoded (uuencode, base64, mime, html entity, url encodings), scanned
-for HTTP and HTTPS URLs, and the first &lt;configurable&gt; host names
-are checked for their presence on the single &lt;configurable&gt; DNSBL.
+                    from address] in the filtering context env_from statement.  That results
+                    in one of (white, black, unknown, inherit).
+                </listitem>
+                <listitem>
+                    If the answer is black, mail to this recipient is rejected with "no such
+                    user", and the dns lists are not checked.
+                </listitem>
+                <listitem>
+                    If the answer is white, mail to this recipient is accepted and the dns
+                    lists are not checked.
+                </listitem>
+                <listitem>
+                    If the answer is unknown, we don't reject yet, but the dns lists will be
+                    checked, and the content may be scanned.
+                <listitem>
+                    If the answer is inherit, we repeat the envelope from search in the
+                    parent context.
+                </listitem>
+                <listitem>
+                    The dns lists specified in the filtering context are checked and the
+                    mail is rejected if any list has an A record for the standard dns based
+                    lookup scheme (reversed octets of the client followed by the dns
+                    suffix).
+                </listitem>
+                <listitem>
+                    If the mail has not been accepted or rejected yet, we look for a
+                    verification context, which is the closest ancestor of the filtering
+                    context that both specifies a verification host, and which covers the
+                    envelope to address.  If we find such a verification context, and the
+                    verification host is not our own hostname, we open an smtp conversation
+                    with that verification host.  The current envelope from and recipient to
+                    values are passed to that verification host.  If we receive a 5xy
+                    response those commands, we reject the current recipient with "no such
+                    user".
+                </listitem>
+                <listitem>
+                    If the mail has not been accepted or rejected yet, and the filtering
+                    context enables content filtering, and this is the first such recipient
+                    in this smtp transaction, we set the content filtering parameters from
+                    this context, and enable content filtering for the body of this message.
+                </listitem>
+            </orderedlist>
+            <para>
+                If content filtering is enabled for this body, the mail text is decoded
+                (uuencode, base64, mime, html entity, url encodings), scanned for HTTP
+                and HTTPS URLs, and the first &lt;configurable&gt; host names are
+                checked for their presence on the single &lt;configurable&gt; DNSBL.
 The only known list that is suitable for this purpose is the SBL.  If
 any of those host names are on that DNSBL (or have nameservers that are
 on that list), and it is not on the &lt;configurable&gt; ignore list,
 the mail is rejected.  We also scan for excessive bad html tags, and if
 a &lt;configurable&gt; limit is exceeded, the mail is rejected.
+            </para>
+        </refsect1>
 
-<hr> <center>Sendmail access vs. DNSBL</center>
-<p>With the standard sendmail.mc dnsbl FEATURE, the dnsbl checks may be
+        <refsect1>
+            <title>Sendmail access vs. DNSBL</title>
+            <para>
+                With the standard sendmail.mc dnsbl FEATURE, the dnsbl checks may be
 suppressed by entries in the /etc/mail/access database.  For example,
 suppose you control a /18 of address space, and have allocated some /24s
 to some clients.  You have access entries like
-
-<pre>
+                <screen>
 192.168.4   OK
 192.168.17  OK
-</pre>
-
-<p>to allow those clients to smarthost thru your mail server.  Now if
-one of those clients happens get infected with a virus that turns a
-machine into an open proxy, and their 192.168.4.45 lands on the SBL-XBL,
-you will still wind up allowing that infected machine to smarthost thru
-your mail servers.
-
-<p>With this DNSBL milter, the sendmail access database cannot override
-the dnsbl checks, so that machine won't be able to send mail to or thru
-your smarthost mail server (unless the virus/proxy can use smtp-auth).
-
-<p>Using the standard sendmail features, you would add access entries to
+                </screen>
+            </para>
+            <para>
+                to allow those clients to smarthost thru your mail server.  Now if one
+                of those clients happens get infected with a virus that turns a machine
+                into an open proxy, and their 192.168.4.45 lands on the SBL-XBL, you
+                will still wind up allowing that infected machine to smarthost thru your
+                mail servers.
+            </para>
+            <para>
+                With this DNSBL milter, the sendmail access database cannot override the
+                dnsbl checks, so that machine won't be able to send mail to or thru your
+                smarthost mail server (unless the virus/proxy can use smtp-auth).
+            </para>
+            <para>
+                Using the standard sendmail features, you would add access entries to
 allow hosts on your local network to relay thru your mail server.  Those
 OK entries in the sendmail access database will override all the dnsbl
 checks.  With this DNSBL milter, you will need to have the local users
-authenticate with smtp-auth to get the same effect.  You might find <a
-href="http://www.ists.dartmouth.edu/classroom/sendmail-ssl-how-to.php">
-these directions</a> helpful for setting up smtp-auth if you are on RH
-Linux.
-
-<hr> <center>Installation and configuration</center>
-<p>Usage:  Note that this has ONLY been tested on Linux, specifically
-RedHat Linux.  In particular, this milter makes no attempt to understand
-IPv6.  Your mileage will vary.  You will need at a minimum a C++
-compiler with a minimally thread safe STL implementation.  The
-distribution includes a test.cpp program.  If it fails this milter won't
-work.  If it passes, this milter might work.
+                authenticate with smtp-auth to get the same effect.  You might find
+                <ulink
+                url="http://www.ists.dartmouth.edu/classroom/sendmail-ssl-how-to.php">
+                these directions</ulink> helpful for setting up smtp-auth if you are on
+                RH Linux.
+            </para>
+        </refsect1>
 
-Fetch <a href="http://www.five-ten-sg.com/util/dnsbl.tar.gz">dnsbl.tar.gz</a>
-and
-
-<pre>
-tar xfvz dnsbl.tar.gz
-bash install.bash
-</pre>
-
-Read and understand the contents of that install.bash script before you
-run it.  It may not be suitable for your system.  Modify your
-sendmail.mc by removing all the "FEATURE(dnsbl" lines, add the following
-line in your sendmail.mc and rebuild the .cf file
-
-<pre>
+        <refsect1>
+            <title>Installation and configuration</title>
+            <para>
+                This is a standard GNU autoconf/automake installation, so the normal
+                <screen>
+                    ./configure
+                    make
+                    su
+                    make install
+                </screen>
+                works. "make chkconfig" will setup the init.d runlevel scripts.
+            </para>
+            <para>
+                Note that this has ONLY been tested on Linux, specifically RedHat Linux.
+                In particular, this milter makes no attempt to understand IPv6.  Your
+                mileage will vary.  You will need at a minimum a C++ compiler with a
+                minimally thread safe STL implementation.  The distribution includes a
+                test.cpp program.  If it fails this milter won't work.  If it passes,
+                this milter might work.
+            </para>
+            <para>
+                Modify your sendmail.mc by removing all the "FEATURE(dnsbl" lines, add
+                the following line in your sendmail.mc and rebuild the .cf file
+            </para>
+            <para>
+                <screen>
 INPUT_MAIL_FILTER(`dnsbl', `S=local:/var/run/dnsbl/dnsbl.sock, F=T, T=C:30s;S:5m;R:5m;E:5m')
-</pre>
-
-Read the sample <a
-href="http://www.five-ten-sg.com/dnsbl/dnsbl.conf">/etc/dnsbl/dnsbl.conf</a>
-file and modify it to fit your configuration.  You can test your
-configuration files, and see a readable internal dump of them on stdout
-with
-
-<pre>
-cd /etc/dnsbl
-/usr/sbin/dnsbl -c
-</pre>
+                </screen>
+            </para>
+            <para>
+                Modify the default <citerefentry>
+                <refentrytitle>@PACKAGE@.conf</refentrytitle> <manvolnum>5</manvolnum>
+                </citerefentry> configuration.
+            </para>
 
-You can check a specific envelope from/to pair with
 
-<pre>
-cd /etc/dnsbl
-from="$1" # or your from address
-to="$2"   # or your to address
-/usr/sbin/dnsbl -e "$from"'|'"$to"
-</pre>
-
-<hr> <center>Performance issues</center>
-
-<p>Consider a high volume high performance machine running sendmail.
-Each sendmail process can do its own dns resolution.  Typically, such
-dns resolver libraries are not thread safe, and so must be protected by
-some sort of mutex in a threaded environment.  When we add a milter to
+        <refsect1 id='todo.1'>
+            <title>Performance Issues</title>
+            <para>
+                Consider a high volume high performance machine running sendmail.  Each
+                sendmail process can do its own dns resolution.  Typically, such dns
+                resolver libraries are not thread safe, and so must be protected by some
+                sort of mutex in a threaded environment.  When we add a milter to
 sendmail, we now have a collection of sendmail processes, and a
 collection of milter threads.
-
-<p>We will be doing a lot of dns lookups per mail message, and at least
+            </para>
+            <para>
+                We will be doing a lot of dns lookups per mail message, and at least
 some of those will take many tens of seconds.  If all this dns work is
 serialized inside the milter, we have an upper limit of about 25K mail
 messages per day.  That is clearly not sufficient for many sites.
-
-<p>Since we want to do parallel dns resolution across those milter
-threads, we add another collection of dns resolver processes.  Each
-sendmail process is talking to a milter thread over a socket, and each
-milter thread is talking to a dns resolver process over another socket.
-
-<p>Suppose we are processing 20 messages per second, and each message
+            </para>
+            <para>
+                Since we want to do parallel dns resolution across those milter threads,
+                we add another collection of dns resolver processes.  Each sendmail
+                process is talking to a milter thread over a socket, and each milter
+                thread is talking to a dns resolver process over another socket.
+            </para>
+            <para>
+                Suppose we are processing 20 messages per second, and each message
 requires 20 seconds of dns work.  Then we will have 400 sendmail
 processes, 400 milter threads, and 400 dns resolver processes.  Of
 course that steady state is very unlikely to happen.
+            </para>
+        </refsect1>
 
-<hr> <center>Rejected Ideas</center>
 
-<p>The following ideas have been considered and rejected.
-
-<p>Add max_recipients for each mail domain to the configuration.
+        <refsect1 id='todo.1'>
+            <title>Rejected Ideas</title>
+            <para>
+                The following ideas have been considered and rejected.
+            </para>
+            <para>
+                Add max_recipients for each mail domain to the configuration.
 Recipients in excess of that limit will be rejected, and all the
 recipients in that domain will be removed if there are some other
 whitelisted recipients.  Current spammers *very* rarely send more than
-ten recipients in a single smtp transaction, so this won't stop
-any significant amount of spam.
-
-<p>Add poison addresses to the configuration.  If any recipient is
+                ten recipients in a single smtp transaction, so this won't stop any
+                significant amount of spam.
+            </para>
+            <para>
+                Add poison addresses to the configuration.  If any recipient is
 poison, all recipients are rejected even if they would be whitelisted,
 and the data is rejected if sent.  I have a collection of spam trap
 addresses that would be suitable for such use.  Based on my log files,
 any mail to those spam trap addresses is rejected based on either dnsbl
 lookups or the DCC.  So this won't result in blocking any additional
 spam.
-
-<p>Add an option to only allow one recipient if the return path is
+            </para>
+            <para>
+                Add an option to only allow one recipient if the return path is
 empty.  Based on my log files, there is no mail that violates this
 check.
+            </para>
+            <para>
+                Reject the mail if the envelope from domain name contains any MX
+                records pointing to 127.0.0.0/8.  I don't see any significant amount of
+                spam sent with such domain names.
+            </para>
+        </refsect1>
 
-<p>Reject the mail if the envelope from domain name contains any MX
-records pointing to 127.0.0.0/8. I don't see any significant amount of spam
-sent with such domain names.
+        <refsect1 id='todo.1'>
+            <title>TODO</title>
+            <para>
+                The following ideas are under consideration.
+            </para>
+            <para>
+                Add a per-context option to reject mail if the number of digits in
+                the reverse dns client name exceeds some threshold.
+            </para>
+        </refsect1>
+
+        <refsect1>
+            <title>Configuration</title>
+            <para>
+                The configuration file is documented in <citerefentry>
+                <refentrytitle>@PACKAGE@.conf</refentrytitle> <manvolnum>5</manvolnum>
+                </citerefentry>.  Any change to the config file, or any file included
+                from that config file, will cause it to be reloaded within three
+                minutes.
+            </para>
+        </refsect1>
+
+        <refsect1>
+            <title>Copyright</title>
+            <para>
+                Copyright (C) 2005 by 510 Software Group &lt;carl@five-ten-sg.com&gt;
+            </para>
+            <para>
+                This program is free software; you can redistribute it and/or modify it
+                under the terms of the GNU General Public License as published by the
+                Free Software Foundation; either version 2, or (at your option) any
+                later version.
+            </para>
+            <para>
+                You should have received a copy of the GNU General Public License along
+                with this program; see the file COPYING.  If not, please write to the
+                Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+            </para>
+        </refsect1>
+
+        <refsect1>
+            <para>
+                $Id$
+            </para>
+        </refsect1>
+    </refentry>
+
+
+    <refentry id="@PACKAGE@.conf.5">
+        <refentryinfo>
+            <date>2005-12-18</date>
+        </refentryinfo>
 
-<hr> <center>Future work</center>
+        <refmeta>
+            <refentrytitle>@PACKAGE@.conf</refentrytitle>
+            <manvolnum>5</manvolnum>
+            <refmiscinfo>@PACKAGE@ @VERSION@</refmiscinfo>
+        </refmeta>
+
+        <refnamediv id='name.5'>
+            <refname>@PACKAGE@.conf</refname>
+            <refpurpose>configuration file for @PACKAGE@</refpurpose>
+        </refnamediv>
+
+        <refsynopsisdiv id='synopsis.5'>
+            <title>Synopsis</title>
+            <cmdsynopsis>
+                <command>@PACKAGE@.conf</command>
+            </cmdsynopsis>
+        </refsynopsisdiv>
+
+        <refsect1 id='description.5'>
+            <title>Description</title>
+            <para>The <command>@PACKAGE@.conf</command> configuration file is
+            specified by this partial bnf description.</para>
+
+            <literallayout class="monospaced"><![CDATA[
+CONFIG     = {CONTEXT ";"}+
+CONTEXT    = "context" NAME "{" {STATEMENT}+ "}"
+STATEMENT  = (DNSBL | DNSBLLIST | CONTENT | ENV-TO | VERIFY | CONTEXT | ENV-FROM) ";"
 
-<p>The following ideas are under consideration.
+DNSBL      = "dnsbl" NAME DNSPREFIX ERROR-MSG
+
+DNSBLLIST  = "dnsbl_list" {NAME}+
+
+CONTENT    = "content" ("on" | "off") "{" {CONTENT-ST}+ "}"
+CONTENT-ST = (FILTER | IGNORE | TLD | HTML-TAGS | HTML-LIMIT | HOST-LIMIT) ";"
+FILTER     = "filter" DNSPREFIX ERROR-MSG
+IGNORE     = "ignore"     "{" {HOSTNAME [";"]}+ "}"
+TLD        = "tld"        "{" {TLD      [";"]}+ "}"
+HTML-TAGS  = "html_tags"  "{" {HTMLTAG  [";"]}+ "}"
+ERROR-MSG  = string containing exactly two %s replacement tokens for the client ip address
+
+HTML-LIMIT = "html_limit" ("on" INTEGER ERROR-MSG | "off")
+
+HOST-LIMIT = "host_limit" ("on" INTEGER ERROR-MSG | "off" | "soft" INTEGER)
+
+ENV-TO     = "env_to"     "{" {(TO-ADDR | DCC-TO)}+ "}"
+TO-ADDR    = ADDRESS [";"]
+DCC-TO     = "dcc_to" ("ok" | "many") "{" DCCINCLUDEFILE "}" ";"
+
+VERIFY     = "verify" HOSTNAME ";"
+
+ENV_FROM   = "env_from" [DEFAULT] "{" {(FROM-ADDR | DCC-FROM)}+ "}"
+FROM-ADDR  = ADDRESS VALUE [";"]
+DCC-FROM   = "dcc_from" "{" DCCINCLUDEFILE "}" ";"
+DEFAULT    = ("white" | "black" | "unknown" | "inherit" | "")
+ADDRESS    = (USER@ | DOMAIN | USER@DOMAIN)
+VALUE      = ("white" | "black" | "unknown" | CHILD-CONTEXT-NAME)]]></literallayout>
+        </refsect1>
 
-<p>Add a per-context option to reject mail if the number of digits in
-the reverse dns client name exceeds some threshold.
+        <refsect1 id='sample.5'>
+            <title>Sample</title>
+            <literallayout class="monospaced"><![CDATA[
+context sample {
+    dnsbl   local   blackholes.five-ten-sg.com  "Mail from %s rejected - local; see http://www.five-ten-sg.com/blackhole.php?%s";
+    dnsbl   sbl     sbl-xbl.spamhaus.org        "Mail from %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s";
+    dnsbl   xbl     xbl.spamhaus.org            "Mail from %s rejected - xbl; see http://www.spamhaus.org/query/bl?ip=%s";
+    dnsbl   dul     dul.dnsbl.sorbs.net         "Mail from %s rejected - dul; see http://www.sorbs.net/lookup.shtml?%s";
+    dnsbl_list  local sbl dul;
+
+    content on {
+        filter    sbl-xbl.spamhaus.org        "Mail containing %s rejected - sbl; see http://www.spamhaus.org/query/bl?ip=%s";
+        ignore    { include "hosts-ignore.conf"; };
+        tld       { include "tld.conf"; };
+        html_tags { include "html-tags.conf"; };
+        html_limit on 20 "Mail containing excessive bad html tags rejected";
+        html_limit off;
+        host_limit on 20 "Mail containing excessive host names rejected";
+        host_limit soft 20;
+    };
+
+    env_to {
+        # child contexts are not allowed to specify recipient addresses outside these domains
+        # leave this outer global context env_to empty to allow arbitrary recipients in child contexts
+        mydomain.com;
+        customer1.com;
+        customer1a.com;
+        customer1b.com;
+        customer2.com;
+        customer2a.com;
+        customer2b.com;
+    };
+
+    context whitelist {
+        content off {};
+        env_to {
+            # dcc_to ok { include "/var/dcc/whitecommon"; };    # copy the dcc OK values (env_to) into this context
+        };
+        env_from white {};      # white forces all unmatched from addresses (everyone in this case) to be whitelisted
+                                # so all mail TO these env_to addresses is accepted
+    };
+
+    context abuse {
+        dnsbl_list xbl;
+        content off {};
+        env_to {
+            abuse@;             # no content filtering on abuse reports
+            postmaster@;        # ""
+        };
+        env_from unknown {};    # ignore all parent white/black listing
+    };
+
+    context minimal {
+        dnsbl_list sbl dul;
+        content on {};
+        env_to {
+            sales@mydomain.com;
+        };
+    };
 
-<pre>
+    context blacklist {
+        env_to {
+            dcc_to many { include "/var/dcc/whitecommon"; };    # copy the dcc MANY values (env_to) into this context
+            old-employee@mydomain.com;
+        };
+        env_from black {};      # black forces all unmatched from addresses (everyone in this case) to be blacklisted
+                                # so all mail TO these env_to addresses is rejected
+    };
+
+    context vp {    # special context for the vp
+        env_to {
+            vp@mydomain.com;
+        };
+        env_from inherit {
+            nai.com                 black;      # the vp does not like nai
+            yahoo.com               unknown;    # override parent context blacklisting
+            mother@spammyisp.com    white;      # suppress dnsbl checking
+        };
+    };
+
+    context customer1 {
+        dnsbl_list sbl dul;
+        env_to {
+            customer1.com;
+            customer1a.com;
+            customer1b.com;
+        };
+
+        verify mail.customer1.com;
+
+        context customer1a {
+            env_to {
+                customer1a.com;
+            }
+            env_from black {                        # blacklist everything
+                first@acceptable.com    unknown;    # except these specific envelope senders
+                second@another.com      unknown;
+                yahoo.com               inherit;    # delegate to the parent
+            };
+        };
+
+        env_from {  # default value of the default is inherit
+            yahoo.com           black;      # no mail from yahoo
+            first@yahoo.com     unknown;    # except this one
+        };
+    };
+
+    context customer2 {
+        dnsbl_list sbl;
+        env_to {
+            customer2.com;
+            customer2a.com;
+            customer2b.com;
+        };
+    };
+
+    env_from unknown {
+        dcc_from { include "/var/dcc/whitecommon"; };   # copy the dcc OK/MANY values (env_from, substitute mail_host) into this context
+        abuse@              abuse;      # replies to abuse reports use the abuse context
+        yahoo.com           black;      # don't take mail from yahoo
+        spammer@example.com black;
+    };
+};]]></literallayout>
+        </refsect1>
+
+        <refsect1>
+            <para>
 $Id$
-</pre>
-</body>
-</html>
+            </para>
+        </refsect1>
+
+    </refentry>
+</reference>