]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
1913. [func] Automatic empty zone creation for D.F.IP6.ARPA and
authorMark Andrews <marka@isc.org>
Thu, 18 Aug 2005 00:57:31 +0000 (00:57 +0000)
committerMark Andrews <marka@isc.org>
Thu, 18 Aug 2005 00:57:31 +0000 (00:57 +0000)
                        friends.  Note: RFC 1918 zones are not yet covered by
                        this but are likely to be in a future release.

                        New options: empty-server, empty-contact,
                        empty-zones-enable and disable-empty-zone.

12 files changed:
CHANGES
bin/named/builtin.c
bin/named/include/named/server.h
bin/named/named.conf.docbook
bin/named/query.c
bin/named/server.c
doc/arm/Bv9ARM-book.xml
lib/bind9/check.c
lib/dns/include/dns/zone.h
lib/dns/sdb.c
lib/dns/zone.c
lib/isccfg/namedconf.c

diff --git a/CHANGES b/CHANGES
index daaee612edf3913099f174a522592e81c641e339..ae205259e63e9b9ac872e98e4cc9f9331c419c71 100644 (file)
--- a/CHANGES
+++ b/CHANGES
@@ -1,3 +1,10 @@
+1913.  [func]          Automatic empty zone creation for D.F.IP6.ARPA and
+                       friends.  Note: RFC 1918 zones are not yet covered by
+                       this but are likely to be in a future release.
+
+                       New options: empty-server, empty-contact,
+                       empty-zones-enable and disable-empty-zone.
+
 1912.  [func]          ISC string copy API.
 
 1911.  [func]          Attempt to make the amount of work performed in a
index e258b4beab93aec46ee68e15ac1bcd3d1f13889b..a8ecde959aae17be05fdb916207900fdef333612 100644 (file)
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: builtin.c,v 1.7 2005/04/29 00:22:26 marka Exp $ */
+/* $Id: builtin.c,v 1.8 2005/08/18 00:57:26 marka Exp $ */
 
 /*! \file
  * \brief
- * The built-in "version", "hostname", "id" and "authors" databases.
+ * The built-in "version", "hostname", "id", "authors" and "empty" databases.
  */
 
 #include <config.h>
 #include <string.h>
 #include <stdio.h>
 
+#include <isc/mem.h>
 #include <isc/print.h>
 #include <isc/result.h>
 #include <isc/util.h>
 
-#include <dns/sdb.h>
 #include <dns/result.h>
+#include <dns/sdb.h>
 
 #include <named/builtin.h>
 #include <named/globals.h>
@@ -45,6 +46,7 @@ static isc_result_t do_version_lookup(dns_sdblookup_t *lookup);
 static isc_result_t do_hostname_lookup(dns_sdblookup_t *lookup);
 static isc_result_t do_authors_lookup(dns_sdblookup_t *lookup);
 static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
+static isc_result_t do_empty_lookup(dns_sdblookup_t *lookup);
 
 /*
  * We can't use function pointers as the db_data directly
@@ -54,12 +56,15 @@ static isc_result_t do_id_lookup(dns_sdblookup_t *lookup);
 
 struct builtin {
        isc_result_t (*do_lookup)(dns_sdblookup_t *lookup);
+       char *server;
+       char *contact;
 };
 
-static builtin_t version_builtin = { do_version_lookup };
-static builtin_t hostname_builtin = { do_hostname_lookup };
-static builtin_t authors_builtin = { do_authors_lookup };
-static builtin_t id_builtin = { do_id_lookup };
+static builtin_t version_builtin = { do_version_lookup,  NULL, NULL };
+static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
+static builtin_t authors_builtin = { do_authors_lookup, NULL, NULL };
+static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
+static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
 
 static dns_sdbimplementation_t *builtin_impl;
 
@@ -167,17 +172,38 @@ do_id_lookup(dns_sdblookup_t *lookup) {
                return (put_txt(lookup, ns_g_server->server_id));
 }
 
+static isc_result_t
+do_empty_lookup(dns_sdblookup_t *lookup) {
+
+       UNUSED(lookup);
+       return (ISC_R_SUCCESS);
+}
+
 static isc_result_t
 builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
        isc_result_t result;
+       const char *contact = "hostmaster";
+       const char *server = "@";
+       builtin_t *b = (builtin_t *) dbdata;
 
        UNUSED(zone);
        UNUSED(dbdata);
 
-       result = dns_sdb_putsoa(lookup, "@", "hostmaster", 0);
+       if (b == &empty_builtin) {
+               server = ".";
+               contact = ".";
+       } else {
+               if (b->server != NULL)
+                       server = b->server;
+               if (b->contact != NULL)
+                       contact = b->contact;
+       }
+       
+       result = dns_sdb_putsoa(lookup, server, contact, 0);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_FAILURE);
-       result = dns_sdb_putrr(lookup, "ns", 0, "@");
+
+       result = dns_sdb_putrr(lookup, "ns", 0, server);
        if (result != ISC_R_SUCCESS)
                return (ISC_R_FAILURE);
 
@@ -190,8 +216,11 @@ builtin_create(const char *zone, int argc, char **argv,
 {
        UNUSED(zone);
        UNUSED(driverdata);
-       if (argc != 1)
+
+       if ((argc != 1 && strcmp(argv[0], "empty") != 0) ||
+           argc != 3)
                return (DNS_R_SYNTAX);
+
        if (strcmp(argv[0], "version") == 0)
                *dbdata = &version_builtin;
        else if (strcmp(argv[0], "hostname") == 0)
@@ -200,17 +229,62 @@ builtin_create(const char *zone, int argc, char **argv,
                *dbdata = &authors_builtin;
        else if (strcmp(argv[0], "id") == 0)
                *dbdata = &id_builtin;
-       else
+       else if (strcmp(argv[0], "empty") == 0) { 
+               builtin_t *empty;
+               char *server;
+               char *contact;
+               /*
+                * We don't want built-in zones to fail.  Fallback to
+                * to the static configuration if memory allocation fails.
+                */
+               empty = isc_mem_get(ns_g_mctx, sizeof(*empty));
+               server = isc_mem_strdup(ns_g_mctx, argv[1]);
+               contact = isc_mem_strdup(ns_g_mctx, argv[2]);
+               if (empty == NULL || server == NULL || contact == NULL) {
+                       *dbdata = &empty_builtin;
+                       if (server != NULL)
+                               isc_mem_free(ns_g_mctx, server);
+                       if (contact != NULL)
+                               isc_mem_free(ns_g_mctx, contact);
+                       if (empty != NULL)
+                               isc_mem_put(ns_g_mctx, empty, sizeof (*empty));
+               } else {
+                       memcpy(empty, &empty_builtin, sizeof (empty_builtin));
+                       empty->server = server;
+                       empty->contact = contact;
+                       *dbdata = empty;
+               }
+       } else
                return (ISC_R_NOTIMPLEMENTED);
        return (ISC_R_SUCCESS);
 }
 
+static void
+builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
+       builtin_t *b = (builtin_t *) *dbdata;
+
+       UNUSED(zone);
+       UNUSED(driverdata);
+
+       /*
+        * Don't free the static versions.
+        */
+       if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
+           *dbdata == &authors_builtin || *dbdata == &id_builtin ||
+           *dbdata == &empty_builtin)
+               return;
+
+       isc_mem_free(ns_g_mctx, b->server);
+       isc_mem_free(ns_g_mctx, b->contact);
+       isc_mem_put(ns_g_mctx, b, sizeof (*b));
+}
+
 static dns_sdbmethods_t builtin_methods = {
        builtin_lookup,
        builtin_authority,
        NULL,           /* allnodes */
        builtin_create,
-       NULL            /* destroy */
+       builtin_destroy
 };
 
 isc_result_t
index fc1a0712e51e557844654f8d69317a441a94293f..1237de15fa68c11f2c01c8de683cda519801013d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.h,v 1.79 2005/08/15 01:21:05 marka Exp $ */
+/* $Id: server.h,v 1.80 2005/08/18 00:57:27 marka Exp $ */
 
 #ifndef NAMED_SERVER_H
 #define NAMED_SERVER_H 1
@@ -62,9 +62,6 @@ struct ns_server {
        isc_boolean_t           server_usehostname;
        char *                  server_id;      /*%< User-specified server id */
 
-       /*% Empty zone SOA ORIGIN and CONTACT */
-       char *                  empty_contact;
-       char *                  empty_server;
         /*%
         * Current ACL environment.  This defines the
         * current values of the localhost and localnets
index adbe9dce8d28de01ad7956d6c74c832dd4dcd856..d9d7952363e7f8f9e53cf600bc0f49387284ee29 100644 (file)
@@ -17,7 +17,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- $Id: named.conf.docbook,v 1.13 2005/06/27 00:15:41 marka Exp $ -->
+<!-- $Id: named.conf.docbook,v 1.14 2005/08/18 00:57:26 marka Exp $ -->
 <refentry>
   <refentryinfo>
     <date>Aug 13, 2004</date>
@@ -261,6 +261,11 @@ options {
        dnssec-lookaside <replaceable>string</replaceable> trust-anchor <replaceable>string</replaceable>;
        dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
 
+       empty-server <replaceable>string</replaceable>;
+       empty-contact <replaceable>string</replaceable>;
+       empty-zones-enable <replaceable>boolean</replaceable>;
+       disable-empty-zone <replaceable>string</replaceable>;
+
        dialup <replaceable>dialuptype</replaceable>;
        ixfr-from-differences <replaceable>ixfrdiff</replaceable>;
 
@@ -396,6 +401,12 @@ view <replaceable>string</replaceable> <replaceable>optional_class</replaceable>
        dnssec-lookaside <replaceable>string</replaceable> trust-anchor <replaceable>string</replaceable>;
 
        dnssec-must-be-secure <replaceable>string</replaceable> <replaceable>boolean</replaceable>;
+
+       empty-server <replaceable>string</replaceable>;
+       empty-contact <replaceable>string</replaceable>;
+       empty-zones-enable <replaceable>boolean</replaceable>;
+       disable-empty-zone <replaceable>string</replaceable>;
+
        dialup <replaceable>dialuptype</replaceable>;
        ixfr-from-differences <replaceable>ixfrdiff</replaceable>;
 
index 84169b53e5d07f28315c01c2ee9e0703db3e4e79..285f7133fad1c210947ef8a5869b0f9d3c166868 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: query.c,v 1.271 2005/08/11 04:45:38 marka Exp $ */
+/* $Id: query.c,v 1.272 2005/08/18 00:57:26 marka Exp $ */
 
 /*! \file */
 
@@ -31,6 +31,7 @@
 #include <dns/db.h>
 #include <dns/events.h>
 #include <dns/message.h>
+#include <dns/ncache.h>
 #include <dns/order.h>
 #include <dns/rdata.h>
 #include <dns/rdataclass.h>
@@ -2914,6 +2915,109 @@ answer_in_glue(ns_client_t *client, dns_rdatatype_t qtype) {
        }
 }
 
+#define NS_NAME_INIT(A,B) \
+        { \
+               DNS_NAME_MAGIC, \
+               A, sizeof(A), sizeof(B), \
+               DNS_NAMEATTR_READONLY | DNS_NAMEATTR_ABSOLUTE, \
+               B, NULL, { (void *)-1, (void *)-1}, \
+               {NULL, NULL} \
+       }
+
+static unsigned char inaddr10_offsets[] = { 0, 3, 11, 16 };
+static unsigned char inaddr172_offsets[] = { 0, 3, 7, 15, 20 };
+static unsigned char inaddr192_offsets[] = { 0, 4, 8, 16, 21 };
+
+static unsigned char inaddr10[] = "\00210\007IN-ADDR\004ARPA";
+
+static unsigned char inaddr16172[] = "\00216\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr17172[] = "\00217\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr18172[] = "\00218\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr19172[] = "\00219\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr20172[] = "\00220\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr21172[] = "\00221\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr22172[] = "\00222\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr23172[] = "\00223\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr24172[] = "\00224\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr25172[] = "\00225\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr26172[] = "\00226\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr27172[] = "\00227\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr28172[] = "\00228\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr29172[] = "\00229\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr30172[] = "\00230\003172\007IN-ADDR\004ARPA";
+static unsigned char inaddr31172[] = "\00231\003172\007IN-ADDR\004ARPA";
+
+static unsigned char inaddr168192[] = "\003168\003192\007IN-ADDR\004ARPA";
+
+static dns_name_t rfc1918names[] = {
+       NS_NAME_INIT(inaddr10, inaddr10_offsets),
+       NS_NAME_INIT(inaddr16172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr17172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr18172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr19172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr20172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr21172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr22172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr23172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr24172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr25172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr26172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr27172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr28172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr29172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr30172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr31172, inaddr172_offsets),
+       NS_NAME_INIT(inaddr168192, inaddr192_offsets)
+};
+
+
+static unsigned char prisoner_data[] = "\010prisoner\004iana\003org";
+static unsigned char hostmaster_data[] = "\012hostmaster\014root-servers\003org";
+
+static unsigned char prisoner_offsets[] = { 0, 9, 14, 18 };
+static unsigned char hostmaster_offsets[] = { 0, 11, 24, 28 };
+
+static dns_name_t prisoner = NS_NAME_INIT(prisoner_data, prisoner_offsets);
+static dns_name_t hostmaster = NS_NAME_INIT(hostmaster_data, hostmaster_offsets);
+
+static void
+warn_rfc1918(ns_client_t *client, dns_name_t *fname, dns_rdataset_t *rdataset) {
+       unsigned int i;
+       dns_rdata_t rdata = DNS_RDATA_INIT;
+       dns_rdata_soa_t soa;
+       dns_rdataset_t found;
+       isc_result_t result;
+       
+       for (i = 0; i < (sizeof(rfc1918names)/sizeof(*rfc1918names)); i++) {
+               if (dns_name_issubdomain(fname, &rfc1918names[i])) {
+                       dns_rdataset_init(&found);
+                       result = dns_ncache_getrdataset(rdataset,
+                                                       &rfc1918names[i],
+                                                       dns_rdatatype_soa,
+                                                       &found);
+                       if (result != ISC_R_SUCCESS)
+                               return;
+
+                       result = dns_rdataset_first(&found);
+                       RUNTIME_CHECK(result == ISC_R_SUCCESS);
+                       dns_rdataset_current(&found, &rdata);
+                       dns_rdata_tostruct(&rdata, &soa, NULL);
+                       if (dns_name_equal(&soa.origin, &prisoner) &&
+                           dns_name_equal(&soa.contact, &hostmaster)) {
+                               char buf[DNS_NAME_FORMATSIZE];
+                               dns_name_format(fname, buf, sizeof(buf));
+                               ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
+                                             NS_LOGMODULE_QUERY,
+                                             ISC_LOG_WARNING,
+                                             "RFC 1918 response from "
+                                             "Internet for %s", buf);
+                       }
+                       dns_rdataset_disassociate(&found);
+                       return;
+               }
+       }
+}
+
 /*
  * Do the bulk of query processing for the current query of 'client'.
  * If 'event' is non-NULL, we are returning from recursion and 'qtype'
@@ -3518,6 +3622,14 @@ query_find(ns_client_t *client, dns_fetchevent_t *event, dns_rdatatype_t qtype)
                 */
                if (result == DNS_R_NCACHENXDOMAIN)
                        client->message->rcode = dns_rcode_nxdomain;
+               /*
+                * Look for RFC 1918 leakage from Internet.
+                */
+               if (result == DNS_R_NCACHENXDOMAIN &&
+                   qtype == dns_rdatatype_ptr &&
+                   client->message->rdclass == dns_rdataclass_in &&
+                   dns_name_countlabels(fname) == 7)
+                       warn_rfc1918(client, fname, rdataset);
                /*
                 * We don't call query_addrrset() because we don't need any
                 * of its extra features (and things would probably break!).
index 96435cb42dcf925428a866adceb22e6556cd1421..0abab522b99be03ef4f4de0aeaf5f5ec44af1f64 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: server.c,v 1.447 2005/08/15 01:21:04 marka Exp $ */
+/* $Id: server.c,v 1.448 2005/08/18 00:57:27 marka Exp $ */
 
 /*! \file */
 
@@ -164,6 +164,58 @@ struct zonelistentry {
        ISC_LINK(struct zonelistentry)  link;
 };
 
+/*
+ * These zones should not leak onto the Internet.
+ */
+static const struct {
+       const char      *zone;
+       isc_boolean_t   rfc1918;
+} empty_zones[] = {
+#ifdef notyet
+       /* RFC 1918 */
+       { "10.IN-ADDR.ARPA", ISC_TRUE },
+       { "16.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "17.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "18.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "19.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "20.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "21.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "22.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "23.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "24.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "25.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "26.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "27.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "28.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "29.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "30.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "31.172.IN-ADDR.ARPA", ISC_TRUE },
+       { "168.192.IN-ADDR.ARPA", ISC_TRUE },
+#endif
+
+       /* RFC 3330 */
+       { "127.IN-ADDR.ARPA", ISC_FALSE },      /* LOOPBACK */
+       { "254.169.IN-ADDR.ARPA", ISC_FALSE },  /* LINK LOCAL */
+       { "2.0.192.IN-ADDR.ARPA", ISC_FALSE },  /* TEST NET */
+       { "255.255.255.255.IN-ADDR.ARPA", ISC_FALSE },  /* BROADCAST */
+
+       /* Local IPv6 Unicast Addresses */
+       { "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
+       { "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA", ISC_FALSE },
+       /* LOCALLY ASSIGNED LOCAL ADDRES S SCOPE */
+       { "D.F.IP6.ARPA", ISC_FALSE },
+       { "8.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
+       { "9.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
+       { "A.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
+       { "B.E.F.IP6.ARPA", ISC_FALSE },        /* LINK LOCAL */
+
+       { NULL, ISC_FALSE }
+};
+
+static const char *empty_dbtype[] = { "_builtin", "empty", NULL, NULL };
+static unsigned int empty_dbtypec = 
+               (sizeof(empty_dbtype) / sizeof(empty_dbtype[0]));
+
 static void
 fatal(const char *msg, isc_result_t result);
 
@@ -724,6 +776,36 @@ disable_algorithms(cfg_obj_t *disabled, dns_resolver_t *resolver) {
        return (result);
 }
 
+static isc_boolean_t
+on_disable_list(cfg_obj_t *disablelist, dns_name_t *zonename) {
+       cfg_listelt_t *element;
+       dns_fixedname_t fixed;
+       dns_name_t *name;
+       isc_result_t result;
+       cfg_obj_t *value;
+       const char *str;
+       isc_buffer_t b;
+
+       dns_fixedname_init(&fixed);
+       name = dns_fixedname_name(&fixed);
+       
+       for (element = cfg_list_first(disablelist);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               value = cfg_listelt_value(element);
+               str = cfg_obj_asstring(value);
+               isc_buffer_init(&b, str, strlen(str));
+               isc_buffer_add(&b, strlen(str));
+               result = dns_name_fromtext(name, &b, dns_rootname,
+                                          ISC_TRUE, NULL);
+               RUNTIME_CHECK(result == ISC_R_SUCCESS);
+               if (dns_name_equal(name, zonename))
+                       return (ISC_TRUE);
+       }
+       return (ISC_FALSE);
+}
+
 /*
  * Configure 'view' according to 'vconfig', taking defaults from 'config'
  * where values are missing in 'vconfig'.
@@ -765,7 +847,14 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        dns_order_t *order = NULL;
        isc_uint32_t udpsize;
        unsigned int check = 0;
+       dns_zone_t *zone = NULL;
        isc_uint32_t max_clients_per_query;
+       const char *sep = ": view ";
+       const char *viewname = view->name;
+       const char *forview = " for view ";
+       isc_boolean_t rfc1918;
+       isc_boolean_t empty_zones_enable;
+       cfg_obj_t *disablelist = NULL;
 
        REQUIRE(DNS_VIEW_VALID(view));
 
@@ -791,6 +880,12 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
                cfgmaps[i++] = config;
        cfgmaps[i] = NULL;
 
+       if (!strcmp(viewname, "_default")) {
+               sep = "";
+               viewname = "";
+               forview = "";
+       }
+
        /*
         * Set the view's port number for outgoing queries.
         */
@@ -1218,20 +1313,11 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        if (!view->recursion && view->recursionacl != NULL &&
            (view->recursionacl->length != 1 ||
             view->recursionacl->elements[0].type != dns_aclelementtype_any ||
-            view->recursionacl->elements[0].negative != ISC_TRUE)) {
-               const char *forview = " for view ";
-               const char *viewname = view->name;
-
-               if (!strcmp(view->name, "_bind") ||
-                   !strcmp(view->name, "_default")) {
-                       forview = "";
-                       viewname = "";
-               }
+            view->recursionacl->elements[0].negative != ISC_TRUE))
                isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
                              NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
                              "both \"recursion no;\" and \"allow-recursion\" "
                              "active%s%s", forview, viewname);
-       }
 
        CHECK(configure_view_acl(vconfig, config, "sortlist",
                                 actx, ns_g_mctx, &view->sortlist));
@@ -1373,9 +1459,153 @@ configure_view(dns_view_t *view, cfg_obj_t *config, cfg_obj_t *vconfig,
        } else
                dns_view_setrootdelonly(view, ISC_FALSE);
 
+       /*
+        * Setup automatic empty zones.  If recursion is off then
+        * they are disabled by default.
+        */
+       obj = NULL;
+       (void)ns_config_get(maps, "empty-zones-enable", &obj);
+       (void)ns_config_get(maps, "disable-empty-zone", &disablelist);
+       if (obj == NULL && disablelist == NULL &&
+           view->rdclass == dns_rdataclass_in) {
+               rfc1918 = ISC_FALSE;
+               empty_zones_enable = view->recursion;
+       } else if (view->rdclass == dns_rdataclass_in) {
+               rfc1918 = ISC_TRUE;
+               if (obj != NULL)
+                       empty_zones_enable = cfg_obj_asboolean(obj);
+               else
+                       empty_zones_enable = view->recursion;
+       } else {
+               rfc1918 = ISC_FALSE;
+               empty_zones_enable = ISC_FALSE;
+       }
+       if (empty_zones_enable) {
+               const char *empty;
+               int empty_zone = 0;
+               dns_fixedname_t fixed;
+               dns_name_t *name;
+               isc_buffer_t buffer;
+               char *str;
+               char server[DNS_NAME_FORMATSIZE + 1];
+               char contact[DNS_NAME_FORMATSIZE + 1];
+               isc_boolean_t logit;
+
+               dns_fixedname_init(&fixed);
+               name = dns_fixedname_name(&fixed);
+
+               obj = NULL;
+               result = ns_config_get(maps, "empty-server", &obj);
+               if (result == ISC_R_SUCCESS) {
+                       str = cfg_obj_asstring(obj);
+                       isc_buffer_init(&buffer, str, strlen(str));
+                       isc_buffer_add(&buffer, strlen(str));
+                       CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
+                                               ISC_FALSE, NULL));
+                       isc_buffer_init(&buffer, server, sizeof(server) - 1);
+                       CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
+                       server[isc_buffer_usedlength(&buffer)] = 0;
+                       empty_dbtype[2] = server;
+               } else
+                       empty_dbtype[2] = "@";
+
+               obj = NULL;
+               result = ns_config_get(maps, "empty-contact", &obj);
+               if (result == ISC_R_SUCCESS) {
+                       str = cfg_obj_asstring(obj);
+                       isc_buffer_init(&buffer, str, strlen(str));
+                       isc_buffer_add(&buffer, strlen(str));
+                       CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
+                                               ISC_FALSE, NULL));
+                       isc_buffer_init(&buffer, contact, sizeof(contact) - 1);
+                       CHECK(dns_name_totext(name, ISC_FALSE, &buffer));
+                       contact[isc_buffer_usedlength(&buffer)] = 0;
+                       empty_dbtype[3] = contact;
+               } else
+                       empty_dbtype[3] = ".";
+
+               logit = ISC_TRUE;
+               for (empty = empty_zones[empty_zone].zone;
+                    empty != NULL;
+                    empty = empty_zones[++empty_zone].zone)
+               {
+                       dns_forwarders_t *forwarders = NULL;
+
+                       isc_buffer_init(&buffer, empty, strlen(empty));
+                       isc_buffer_add(&buffer, strlen(empty));
+                       /*
+                        * Look for zone on drop list.
+                        */
+                       CHECK(dns_name_fromtext(name, &buffer, dns_rootname,
+                                               ISC_FALSE, NULL));
+                       if (disablelist != NULL &&
+                           on_disable_list(disablelist, name))
+                               continue;
+
+                       /*
+                        * This zone already exists.
+                        */
+                       (void)dns_view_findzone(view, name, &zone);
+                       if (zone != NULL) {
+                               dns_zone_detach(&zone);
+                               continue;
+                       }
+
+                       /*
+                        * If we would forward this name don't add a
+                        * empty zone for it.
+                        */
+                       result = dns_fwdtable_find(view->fwdtable, name,
+                                                  &forwarders);
+                       if (result == ISC_R_SUCCESS &&
+                           forwarders->fwdpolicy == dns_fwdpolicy_only)
+                               continue;
+                                               
+                       if (!rfc1918 && empty_zones[empty_zone].rfc1918) {
+                               if (logit) {
+                                       isc_log_write(ns_g_lctx,
+                                                     NS_LOGCATEGORY_GENERAL,
+                                                     NS_LOGMODULE_SERVER,
+                                                     ISC_LOG_WARNING,
+                                                     "Warning%s%s: "
+                                                     "'empty-zones-enable/"
+                                                     "disable-empty-zone' "
+                                                     "not set: disabling "
+                                                     "RFC 1918 empty zones",
+                                                     sep, viewname);
+                                       logit = ISC_FALSE;
+                               }
+                               continue;
+                       }
+
+                       CHECK(dns_zone_create(&zone, mctx));
+                       CHECK(dns_zone_setorigin(zone, name));
+                       dns_zone_setview(zone, view);
+                       CHECK(dns_zonemgr_managezone(ns_g_server->zonemgr, zone));
+                       dns_zone_setclass(zone, view->rdclass);
+                       dns_zone_settype(zone, dns_zone_master);
+                       CHECK(dns_zone_setdbtype(zone, empty_dbtypec,
+                                                empty_dbtype));
+                       if (view->queryacl != NULL)
+                               dns_zone_setqueryacl(zone, view->queryacl);
+                       dns_zone_setdialup(zone, dns_dialuptype_no);
+                       dns_zone_setnotifytype(zone, dns_notifytype_no);
+                       dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS,
+                                          ISC_TRUE);
+                       CHECK(dns_view_addzone(view, zone));
+                       isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
+                                     NS_LOGMODULE_SERVER, ISC_LOG_INFO,
+                                     "automatic empty zone%s%s: %s",
+                                     sep, viewname,  empty);
+                       dns_zone_detach(&zone);
+               }
+       }
+       
        result = ISC_R_SUCCESS;
 
  cleanup:
+       if (zone != NULL)
+               dns_zone_detach(&zone);
        if (dispatch4 != NULL)
                dns_dispatch_detach(&dispatch4);
        if (dispatch6 != NULL)
@@ -2813,7 +3043,7 @@ load_configuration(const char *filename, ns_server_t *server,
        } else if (result == ISC_R_SUCCESS) {
                CHECKM(setoptstring(server, &server->server_id, obj), "strdup");
        } else {
-               result = setoptstring(server, &server->server_id, NULL);
+               result = setstring(server, &server->server_id, NULL);
                RUNTIME_CHECK(result == ISC_R_SUCCESS);
        }
 
index 149dd062438cc8358330b6f68a0105d3d68dc51a..e7e263c8175a46b9aff68473320be420da30f8a7 100644 (file)
@@ -18,7 +18,7 @@
  - PERFORMANCE OF THIS SOFTWARE.
 -->
 
-<!-- File: $Id: Bv9ARM-book.xml,v 1.276 2005/07/19 06:12:16 marka Exp $ -->
+<!-- File: $Id: Bv9ARM-book.xml,v 1.277 2005/08/18 00:57:28 marka Exp $ -->
 <book xmlns:xi="http://www.w3.org/2001/XInclude">
   <title>BIND 9 Administrator Reference Manual</title>
 
@@ -4445,6 +4445,10 @@ category notify { null; };
     <optional> clients-per-query <replaceable>number</replaceable> ; </optional>
     <optional> max-clients-per-query <replaceable>number</replaceable> ; </optional>
     <optional> masterfile-format (<constant>text</constant>|<constant>raw</constant>) ; </optional>
+    <optional> empty-server <replaceable>name</replaceable> ; </optional>
+    <optional> empty-contact <replaceable>name</replaceable> ; </optional>
+    <optional> empty-zones-enable <replaceable>yes_or_no</replaceable> ; </optional>
+    <optional> disable-empty-zone <replaceable>zone_name</replaceable> ; </optional>
 };
 </programlisting>
 
@@ -7018,6 +7022,125 @@ query-source-v6 address * port *;
 
         </sect3>
 
+        <sect3 id="empty">
+          <title>Built-in Empty Zones</title>
+         <para>
+           Named has some built-in empty zones (SOA and NS records only).
+           These are for zones that should normally be answered locally
+           and which queries should not be sent to the Internet's root
+           servers.  The offical servers which cover these namespaces
+           return NXDOMAIN responses to these queries.  In particular
+           these cover the reverse namespace for addresses from RFC 1918 and
+           RFC 3330.  They also include the reverse namespace for IPv6 local
+           address (locally assigned), IPv6 link local addresses, the IPv6
+           loopback address and the IPv6 unknown addresss.
+         </para>
+         <para>
+           Named will attempt to determine if a built in zone already exists
+           or is active (covered by a forward-only forwarding declaration)
+           and will not not create a empty zone in that case.
+         </para>
+         <para>
+           The current list of empty zones is:
+           <itemizedlist>
+             <listitem>10.IN-ADDR.ARPA</listitem>
+             <listitem>127.IN-ADDR.ARPA</listitem>
+             <listitem>254.169.IN-ADDR.ARPA</listitem>
+             <listitem>16.172.IN-ADDR.ARPA</listitem>
+             <listitem>17.172.IN-ADDR.ARPA</listitem>
+             <listitem>18.172.IN-ADDR.ARPA</listitem>
+             <listitem>19.172.IN-ADDR.ARPA</listitem>
+             <listitem>20.172.IN-ADDR.ARPA</listitem>
+             <listitem>21.172.IN-ADDR.ARPA</listitem>
+             <listitem>22.172.IN-ADDR.ARPA</listitem>
+             <listitem>23.172.IN-ADDR.ARPA</listitem>
+             <listitem>24.172.IN-ADDR.ARPA</listitem>
+             <listitem>25.172.IN-ADDR.ARPA</listitem>
+             <listitem>26.172.IN-ADDR.ARPA</listitem>
+             <listitem>27.172.IN-ADDR.ARPA</listitem>
+             <listitem>28.172.IN-ADDR.ARPA</listitem>
+             <listitem>29.172.IN-ADDR.ARPA</listitem>
+             <listitem>30.172.IN-ADDR.ARPA</listitem>
+             <listitem>31.172.IN-ADDR.ARPA</listitem>
+             <listitem>168.192.IN-ADDR.ARPA</listitem>
+             <listitem>2.0.192.IN-ADDR.ARPA</listitem>
+             <listitem>0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</listitem>
+             <listitem>1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.IP6.ARPA</listitem>
+             <listitem>D.F.IP6.ARPA</listitem>
+             <listitem>8.E.F.IP6.ARPA</listitem>
+             <listitem>9.E.F.IP6.ARPA</listitem>
+             <listitem>A.E.F.IP6.ARPA</listitem>
+             <listitem>B.E.F.IP6.ARPA</listitem>
+           </itemizedlist>
+         </para>
+         <para>
+           Empty zones are settable at the view level and only apply to
+           views of class IN.  Disabled empty zones are only inherited
+           from options if there are no disabled empty zones specified
+           at the view level.  To override the options list of disabled
+           zones you can disable the root zone at the view level
+           (disable-empty-zone ".";).
+         </para>
+         <para>
+           If you are using the address ranges covered here you should
+           already have reverse zones covering the addresses you use.
+           In practice this appears to not be the case with many queries
+           being made to the infrustucture servers for names in these
+           spaces.  So many in fact that sacrificial servers were needed
+           to be deployed to channel the query load away from the
+           infrustucture servers.
+         </para>
+         <note>
+           The real parent servers for these zones should disable all
+           empty zone under the parent zone they serve.  For the real
+           root servers this is all built in empty zones.  This will
+           enable them to return referrals to deeper in the tree.
+         </note>
+          <variablelist>
+           <varlistentry>
+             <term><command>empty-server</command></term>
+             <listitem>
+               <para>
+                 Specify what server name will appear in the returned
+                 SOA record for empty zones.  If none is specified then
+                 the zone's name will be used.
+               </para>
+              </listitem>
+           </varlistentry>
+             
+           <varlistentry>
+             <term><command>empty-contact</command></term>
+             <listitem>
+               <para>
+                 Specify what contact name will appear in the returned
+                 SOA record for empty zones.  If none is specified then
+                 "." will be used.
+               </para>
+             </listitem>
+           </varlistentry>
+  
+           <varlistentry>
+             <term><command>empty-zones-enable</command></term>
+             <listitem>
+               <para>
+                 Enable / disable all empty zones.  By default they
+                 are enabled.
+               </para>
+             </listitem>
+           </varlistentry>
+  
+           <varlistentry>
+           <term><command>disable-empty-zone</command></term>
+             <listitem>
+               <para>
+                 Disable a indiviual empty zones.  By default none are
+                 disabled.  This option can be specified multiple times.
+               </para>
+             </listitem>
+           </varlistentry>
+          </variablelist>
+        </sect3>
+  
         <sect3 id="statsfile">
           <title>The Statistics File</title>
 
index f6cc674c46ab9ac0759d476e7fff88bd5eea28a1..e682f43db525cb80e99d8787cbc01d7a7a24925e 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: check.c,v 1.61 2005/07/28 05:42:20 marka Exp $ */
+/* $Id: check.c,v 1.62 2005/08/18 00:57:28 marka Exp $ */
 
 /*! \file */
 
@@ -413,6 +413,10 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
        cfg_obj_t *obj = NULL;
        cfg_listelt_t *element;
        isc_symtab_t *symtab = NULL;
+       dns_fixedname_t fixed;
+       const char *str;
+       dns_name_t *name;
+       isc_buffer_t b;
 
        static intervaltable intervals[] = {
        { "cleaning-interval", 60, 28 * 24 * 60 },      /* 28 days */
@@ -512,6 +516,9 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
                }
        }
 
+       dns_fixedname_init(&fixed);
+       name = dns_fixedname_name(&fixed);
+
        /*
         * Check the DLV zone name.
         */
@@ -526,16 +533,11 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
                     element != NULL;
                     element = cfg_list_next(element))
                {
-                       dns_fixedname_t fixedname;
-                       dns_name_t *name;
                        const char *dlv;
-                       isc_buffer_t b;
 
                        obj = cfg_listelt_value(element);
 
                        dlv = cfg_obj_asstring(cfg_tuple_get(obj, "domain"));
-                       dns_fixedname_init(&fixedname);
-                       name = dns_fixedname_name(&fixedname);
                        isc_buffer_init(&b, dlv, strlen(dlv));
                        isc_buffer_add(&b, strlen(dlv));
                        tresult = dns_name_fromtext(name, &b, dns_rootname,
@@ -568,7 +570,6 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
                        }
                        dlv = cfg_obj_asstring(cfg_tuple_get(obj,
                                               "trust-anchor"));
-                       dns_fixedname_init(&fixedname);
                        isc_buffer_init(&b, dlv, strlen(dlv));
                        isc_buffer_add(&b, strlen(dlv));
                        tresult = dns_name_fromtext(name, &b, dns_rootname,
@@ -608,6 +609,59 @@ check_options(cfg_obj_t *options, isc_log_t *logctx, isc_mem_t *mctx) {
                        isc_symtab_destroy(&symtab);
        }
 
+       /*
+        * Check empty zone configuration.
+        */
+       obj = NULL;
+       (void)cfg_map_get(options, "empty-server", &obj);
+       if (obj != NULL) {
+               str = cfg_obj_asstring(obj);
+               isc_buffer_init(&b, str, strlen(str));
+               isc_buffer_add(&b, strlen(str));
+               tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
+                                           dns_rootname, ISC_FALSE, NULL);
+               if (tresult != ISC_R_SUCCESS) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "empty-server: invalid name '%s'", str);
+                       result = ISC_R_FAILURE;
+               }
+       }
+
+       obj = NULL;
+       (void)cfg_map_get(options, "empty-contact", &obj);
+       if (obj != NULL) {
+               str = cfg_obj_asstring(obj);
+               isc_buffer_init(&b, str, strlen(str));
+               isc_buffer_add(&b, strlen(str));
+               tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
+                                           dns_rootname, ISC_FALSE, NULL);
+               if (tresult != ISC_R_SUCCESS) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "empty-contact: invalid name '%s'", str);
+                       result = ISC_R_FAILURE;
+               }
+       }
+
+       obj = NULL;
+       (void)cfg_map_get(options, "disable-empty-zone", &obj);
+       for (element = cfg_list_first(obj);
+            element != NULL;
+            element = cfg_list_next(element))
+       {
+               obj = cfg_listelt_value(element);
+               str = cfg_obj_asstring(obj);
+               isc_buffer_init(&b, str, strlen(str));
+               isc_buffer_add(&b, strlen(str));
+               tresult = dns_name_fromtext(dns_fixedname_name(&fixed), &b,
+                                           dns_rootname, ISC_FALSE, NULL);
+               if (tresult != ISC_R_SUCCESS) {
+                       cfg_obj_log(obj, logctx, ISC_LOG_ERROR,
+                                   "disable-empty-zone: invalid name '%s'",
+                                   str);
+                       result = ISC_R_FAILURE;
+               }
+       }
+
        return (result);
 }
 
index 7daa709d4f35ed5d2e8f796325ac3896d29614d8..a70a91337190d3e4b10d03c4fa35740cc834cf7d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.h,v 1.135 2005/06/20 01:03:55 marka Exp $ */
+/* $Id: zone.h,v 1.136 2005/08/18 00:57:30 marka Exp $ */
 
 #ifndef DNS_ZONE_H
 #define DNS_ZONE_H 1
@@ -59,6 +59,7 @@ typedef enum {
 #define DNS_ZONEOPT_CHECKMX      0x00004000U   /*%< check-mx */
 #define DNS_ZONEOPT_CHECKMXFAIL   0x00008000U  /*%< fatal check-mx failures */
 #define DNS_ZONEOPT_INTEGRITYCHECK 0x00010000U /*%< perform integrity checks */
+#define DNS_ZONEOPT_NOCHECKNS    0x00020000U   /*%< disable IN NS address checks */
 
 #ifndef NOMINUM_PUBLIC
 /*
index b8594f76a32b49ccff405283c11a9e9745b1bc2d..fc6b290f69164e4cd729009f6d82f3b40f144b88 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: sdb.c,v 1.51 2005/07/12 01:00:16 marka Exp $ */
+/* $Id: sdb.c,v 1.52 2005/08/18 00:57:29 marka Exp $ */
 
 /*! \file */
 
@@ -267,10 +267,11 @@ dns_sdb_unregister(dns_sdbimplementation_t **sdbimp) {
 static inline unsigned int
 initial_size(unsigned int len) {
        unsigned int size;
-       for (size = 64; size < (64 * 1024); size *= 2)
+
+       for (size = 1024; size < (64 * 1024); size *= 2)
                if (len < size)
                        return (size);
-       return (64 * 1024);
+       return (65535);
 }
 
 isc_result_t
@@ -381,6 +382,8 @@ dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
                if (result != ISC_R_SUCCESS)
                        goto failure;
 
+               if (size >= 65535)
+                       size = 65535;
                p = isc_mem_get(mctx, size);
                if (p == NULL) {
                        result = ISC_R_NOMEMORY;
@@ -396,6 +399,11 @@ dns_sdb_putrr(dns_sdblookup_t *lookup, const char *type, dns_ttl_t ttl,
                if (result != ISC_R_NOSPACE)
                        break;
 
+               /*
+                * Is the RR too big?
+                */
+               if (size >= 65535)
+                       break;
                isc_mem_put(mctx, p, size);
                p = NULL;
                size *= 2;
index 6b315114d0686044597d2002e6007a30b8a8616d..ee7082573721ace2c8b80eb076826dfdf2b2766d 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: zone.c,v 1.443 2005/07/29 00:32:53 marka Exp $ */
+/* $Id: zone.c,v 1.444 2005/08/18 00:57:29 marka Exp $ */
 
 /*! \file */
 
@@ -2004,6 +2004,9 @@ zone_check_ns(dns_zone_t *zone, dns_db_t *db, dns_name_t *name) {
        dns_name_t *foundname;
        int level;
        
+       if (DNS_ZONE_OPTION(zone, DNS_ZONEOPT_NOCHECKNS))
+               return (ISC_TRUE);
+
        if (zone->type == dns_zone_master)
                level = ISC_LOG_ERROR;
        else
index 309d6e79d1917a45895dcb7825b1e8e492229905..ec04f808dcd48d23811e756b067a768c2a344783 100644 (file)
@@ -15,7 +15,7 @@
  * PERFORMANCE OF THIS SOFTWARE.
  */
 
-/* $Id: namedconf.c,v 1.54 2005/07/18 05:59:01 marka Exp $ */
+/* $Id: namedconf.c,v 1.55 2005/08/18 00:57:31 marka Exp $ */
 
 /*! \file */
 
@@ -409,8 +409,8 @@ static cfg_type_t cfg_type_forwardtype = {
 static const char *zonetype_enums[] = {
        "master", "slave", "stub", "hint", "forward", "delegation-only", NULL };
 static cfg_type_t cfg_type_zonetype = {
-       "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum, &cfg_rep_string,
-       &zonetype_enums
+       "zonetype", cfg_parse_enum, cfg_print_ustring, cfg_doc_enum,
+       &cfg_rep_string, &zonetype_enums
 };
 
 static const char *loglevel_enums[] = {
@@ -747,6 +747,10 @@ view_clauses[] = {
        { "max-acache-size", &cfg_type_sizenodefault, 0 },
        { "clients-per-query", &cfg_type_uint32, 0 },
        { "max-clients-per-query", &cfg_type_uint32, 0 },
+       { "empty-server", &cfg_type_astring, 0 },
+       { "empty-contact", &cfg_type_astring, 0 },
+       { "empty-zones-enable", &cfg_type_boolean, 0 },
+       { "disable-empty-zone", &cfg_type_astring, CFG_CLAUSEFLAG_MULTI },
        { NULL, NULL, 0 }
 };