]> git.ipfire.org Git - thirdparty/bind9.git/commitdiff
Implement ipv4only.arpa forward and reverse zones as per RFC 8880.
authorMark Andrews <marka@isc.org>
Thu, 5 Jul 2018 05:29:30 +0000 (15:29 +1000)
committerMark Andrews <marka@isc.org>
Fri, 11 Dec 2020 03:16:40 +0000 (14:16 +1100)
bin/named/builtin.c
bin/named/named.conf.rst
bin/named/server.c
doc/man/named.conf.5in
doc/misc/options
doc/misc/options.active
doc/misc/options.grammar.rst
lib/isccfg/namedconf.c

index 2817ffd3ad60cf685ce0004bcfa1b3be1ec3c1c4..bc6e9b2f1e3bc74f861b1315bd1599dda752d318 100644 (file)
 typedef struct builtin builtin_t;
 
 static isc_result_t
-do_version_lookup(dns_sdblookup_t *lookup);
+do_authors_lookup(dns_sdblookup_t *lookup);
 static isc_result_t
-do_hostname_lookup(dns_sdblookup_t *lookup);
+do_dns64_lookup(dns_sdblookup_t *lookup);
 static isc_result_t
-do_authors_lookup(dns_sdblookup_t *lookup);
+do_empty_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_hostname_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);
+do_ipv4only_lookup(dns_sdblookup_t *lookup);
 static isc_result_t
-do_dns64_lookup(dns_sdblookup_t *lookup);
+do_ipv4reverse_lookup(dns_sdblookup_t *lookup);
+static isc_result_t
+do_version_lookup(dns_sdblookup_t *lookup);
 
 /*
  * We can't use function pointers as the db_data directly
@@ -57,12 +61,14 @@ struct builtin {
        char *contact;
 };
 
-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 builtin_t dns64_builtin = { do_dns64_lookup, NULL, NULL };
+static builtin_t empty_builtin = { do_empty_lookup, NULL, NULL };
+static builtin_t hostname_builtin = { do_hostname_lookup, NULL, NULL };
+static builtin_t id_builtin = { do_id_lookup, NULL, NULL };
+static builtin_t ipv4only_builtin = { do_ipv4only_lookup, NULL, NULL };
+static builtin_t ipv4reverse_builtin = { do_ipv4reverse_lookup, NULL, NULL };
+static builtin_t version_builtin = { do_version_lookup, NULL, NULL };
 
 static dns_sdbimplementation_t *builtin_impl;
 static dns_sdbimplementation_t *dns64_impl;
@@ -89,7 +95,8 @@ static const unsigned char hex16[256] = {
        1, 1,   1,   1,   1,   1,   1,   1,   1,   1,   1, 1, 1, 1, 1, 1  /*F0*/
 };
 
-const unsigned char decimal[] = "0123456789";
+static const unsigned char decimal[] = "0123456789";
+static const unsigned char ipv4only[] = "\010ipv4only\004arpa";
 
 static size_t
 dns64_rdata(unsigned char *v, size_t start, unsigned char *rdata) {
@@ -429,6 +436,30 @@ do_empty_lookup(dns_sdblookup_t *lookup) {
        return (ISC_R_SUCCESS);
 }
 
+static isc_result_t
+do_ipv4only_lookup(dns_sdblookup_t *lookup) {
+       isc_result_t result;
+       unsigned char data[2][4] = { { 192, 0, 0, 170 }, { 192, 0, 0, 171 } };
+
+       for (int i = 0; i < 2; i++) {
+               result = dns_sdb_putrdata(lookup, dns_rdatatype_a, 3600,
+                                         data[i], 4);
+               if (result != ISC_R_SUCCESS) {
+                       return (result);
+               }
+       }
+       return (ISC_R_SUCCESS);
+}
+
+static isc_result_t
+do_ipv4reverse_lookup(dns_sdblookup_t *lookup) {
+       isc_result_t result;
+
+       result = dns_sdb_putrdata(lookup, dns_rdatatype_ptr, 0, ipv4only,
+                                 sizeof(ipv4only));
+       return (result);
+}
+
 static isc_result_t
 builtin_authority(const char *zone, void *dbdata, dns_sdblookup_t *lookup) {
        isc_result_t result;
@@ -472,7 +503,10 @@ builtin_create(const char *zone, int argc, char **argv, void *driverdata,
        UNUSED(zone);
        UNUSED(driverdata);
 
-       if (strcmp(argv[0], "empty") == 0 || strcmp(argv[0], "dns64") == 0) {
+       if (strcmp(argv[0], "dns64") == 0 || strcmp(argv[0], "empty") == 0 ||
+           strcmp(argv[0], "ipv4only") == 0 ||
+           strcmp(argv[0], "ipv4reverse") == 0)
+       {
                if (argc != 3) {
                        return (DNS_R_SYNTAX);
                }
@@ -480,19 +514,27 @@ builtin_create(const char *zone, int argc, char **argv, void *driverdata,
                return (DNS_R_SYNTAX);
        }
 
-       if (strcmp(argv[0], "version") == 0) {
-               *dbdata = &version_builtin;
+       if (strcmp(argv[0], "authors") == 0) {
+               *dbdata = &authors_builtin;
        } else if (strcmp(argv[0], "hostname") == 0) {
                *dbdata = &hostname_builtin;
-       } else if (strcmp(argv[0], "authors") == 0) {
-               *dbdata = &authors_builtin;
        } else if (strcmp(argv[0], "id") == 0) {
                *dbdata = &id_builtin;
-       } else if (strcmp(argv[0], "empty") == 0 ||
-                  strcmp(argv[0], "dns64") == 0) {
+       } else if (strcmp(argv[0], "version") == 0) {
+               *dbdata = &version_builtin;
+       } else if (strcmp(argv[0], "dns64") == 0 ||
+                  strcmp(argv[0], "empty") == 0 ||
+                  strcmp(argv[0], "ipv4only") == 0 ||
+                  strcmp(argv[0], "ipv4reverse") == 0)
+       {
                builtin_t *empty;
                char *server;
                char *contact;
+
+               if (argc != 3) {
+                       return (DNS_R_SYNTAX);
+               }
+
                /*
                 * We don't want built-in zones to fail.  Fallback to
                 * the static configuration if memory allocation fails.
@@ -501,10 +543,14 @@ builtin_create(const char *zone, int argc, char **argv, void *driverdata,
                server = isc_mem_strdup(named_g_mctx, argv[1]);
                contact = isc_mem_strdup(named_g_mctx, argv[2]);
                if (empty == NULL || server == NULL || contact == NULL) {
-                       if (strcmp(argv[0], "empty") == 0) {
+                       if (strcmp(argv[0], "dns64") == 0) {
+                               *dbdata = &dns64_builtin;
+                       } else if (strcmp(argv[0], "empty") == 0) {
                                *dbdata = &empty_builtin;
+                       } else if (strcmp(argv[0], "ipv4only") == 0) {
+                               *dbdata = &ipv4only_builtin;
                        } else {
-                               *dbdata = &dns64_builtin;
+                               *dbdata = &ipv4reverse_builtin;
                        }
                        if (server != NULL) {
                                isc_mem_free(named_g_mctx, server);
@@ -517,11 +563,17 @@ builtin_create(const char *zone, int argc, char **argv, void *driverdata,
                                            sizeof(*empty));
                        }
                } else {
-                       if (strcmp(argv[0], "empty") == 0) {
+                       if (strcmp(argv[0], "dns64") == 0) {
+                               memmove(empty, &dns64_builtin,
+                                       sizeof(empty_builtin));
+                       } else if (strcmp(argv[0], "empty") == 0) {
                                memmove(empty, &empty_builtin,
                                        sizeof(empty_builtin));
+                       } else if (strcmp(argv[0], "ipv4only") == 0) {
+                               memmove(empty, &ipv4only_builtin,
+                                       sizeof(empty_builtin));
                        } else {
-                               memmove(empty, &dns64_builtin,
+                               memmove(empty, &ipv4reverse_builtin,
                                        sizeof(empty_builtin));
                        }
                        empty->server = server;
@@ -544,9 +596,10 @@ builtin_destroy(const char *zone, void *driverdata, void **dbdata) {
        /*
         * Don't free the static versions.
         */
-       if (*dbdata == &version_builtin || *dbdata == &hostname_builtin ||
-           *dbdata == &authors_builtin || *dbdata == &id_builtin ||
-           *dbdata == &empty_builtin || *dbdata == &dns64_builtin)
+       if (*dbdata == &authors_builtin || *dbdata == &dns64_builtin ||
+           *dbdata == &empty_builtin || *dbdata == &hostname_builtin ||
+           *dbdata == &id_builtin || *dbdata == &ipv4only_builtin ||
+           *dbdata == &ipv4reverse_builtin || *dbdata == &version_builtin)
        {
                return;
        }
index 1933eefa9c7813d2cb464ca69676fac37ebb2df1..bf4ba2d0593c037f947cc782c2590035f9129459 100644 (file)
@@ -264,6 +264,9 @@ OPTIONS
        hostname ( quoted_string | none );
        inline-signing boolean;
        interface-interval duration;
+       ipv4only-contact string;
+       ipv4only-enable boolean;
+       ipv4only-server string;
        ixfr-from-differences ( primary | master | secondary | slave |
            boolean );
        keep-response-order { address_match_element; ... };
@@ -640,6 +643,9 @@ VIEW
            | ipv6_address ) [ port integer ] [ dscp integer ]; ... };
        glue-cache boolean;// deprecated
        inline-signing boolean;
+       ipv4only-contact string;
+       ipv4only-enable boolean;
+       ipv4only-server string;
        ixfr-from-differences ( primary | master | secondary | slave |
            boolean );
        key string {
index 733d2b7f8f5c35ecb18ee4a0952d8106a5a3b1cf..5ce695b5eec69cdfb1afda1703e6fb6f22623ef0 100644 (file)
 #define SIZE_AS_PERCENT ((size_t)-2)
 #endif /* ifndef SIZE_AS_PERCENT */
 
+#ifndef ARRAYSIZE
+#define ARRAYSIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
 #ifdef TUNE_LARGE
 #define RESOLVER_NTASKS_PERCPU 32
 #define UDPBUFFERS            32768
@@ -3386,7 +3390,7 @@ cleanup:
 }
 
 static isc_result_t
-create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
+create_empty_zone(dns_zone_t *pzone, dns_name_t *name, dns_view_t *view,
                  const cfg_obj_t *zonelist, const char **empty_dbtype,
                  int empty_dbtypec, dns_zonestat_level_t statlevel) {
        char namebuf[DNS_NAME_FORMATSIZE];
@@ -3406,7 +3410,7 @@ create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
        dns_name_t *contact;
        dns_name_t *ns;
        dns_name_t *zname;
-       dns_zone_t *myzone = NULL;
+       dns_zone_t *zone = NULL;
        int rbt_dbtypec = 1;
        isc_result_t result;
        dns_namereln_t namereln;
@@ -3469,7 +3473,7 @@ create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
        /*
         * Is the existing zone the ok to use?
         */
-       if (zone != NULL) {
+       if (pzone != NULL) {
                unsigned int typec;
                const char **dbargv;
 
@@ -3481,29 +3485,29 @@ create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
                        dbargv = empty_dbtype;
                }
 
-               result = check_dbtype(zone, typec, dbargv, view->mctx);
+               result = check_dbtype(pzone, typec, dbargv, view->mctx);
                if (result != ISC_R_SUCCESS) {
-                       zone = NULL;
+                       pzone = NULL;
                }
 
-               if (zone != NULL && dns_zone_gettype(zone) != dns_zone_master) {
-                       zone = NULL;
+               if (pzone != NULL && dns_zone_gettype(pzone) != dns_zone_master)
+               {
+                       pzone = NULL;
                }
-               if (zone != NULL && dns_zone_getfile(zone) != NULL) {
-                       zone = NULL;
+               if (pzone != NULL && dns_zone_getfile(pzone) != NULL) {
+                       pzone = NULL;
                }
-               if (zone != NULL) {
-                       dns_zone_getraw(zone, &myzone);
-                       if (myzone != NULL) {
-                               dns_zone_detach(&myzone);
-                               zone = NULL;
+               if (pzone != NULL) {
+                       dns_zone_getraw(pzone, &zone);
+                       if (zone != NULL) {
+                               dns_zone_detach(&zone);
+                               pzone = NULL;
                        }
                }
        }
 
-       if (zone == NULL) {
-               CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &myzone));
-               zone = myzone;
+       if (pzone == NULL) {
+               CHECK(dns_zonemgr_createzone(named_g_server->zonemgr, &zone));
                CHECK(dns_zone_setorigin(zone, name));
                CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
                if (db == NULL) {
@@ -3512,6 +3516,8 @@ create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
                dns_zone_setclass(zone, view->rdclass);
                dns_zone_settype(zone, dns_zone_master);
                dns_zone_setstats(zone, named_g_server->zonestats);
+       } else {
+               dns_zone_attach(pzone, &zone);
        }
 
        dns_zone_setoption(zone, ~DNS_ZONEOPT_NOCHECKNS, false);
@@ -3555,8 +3561,8 @@ create_empty_zone(dns_zone_t *zone, dns_name_t *name, dns_view_t *view,
                      "automatic empty zone%s%s: %s", sep, viewname, namebuf);
 
 cleanup:
-       if (myzone != NULL) {
-               dns_zone_detach(&myzone);
+       if (zone != NULL) {
+               dns_zone_detach(&zone);
        }
        if (version != NULL) {
                dns_db_closeversion(db, &version, false);
@@ -3570,6 +3576,84 @@ cleanup:
        return (result);
 }
 
+static isc_result_t
+create_ipv4only_zone(dns_zone_t *pzone, dns_view_t *view,
+                    const dns_name_t *name, const char *type, isc_mem_t *mctx,
+                    const char *server, const char *contact) {
+       char namebuf[DNS_NAME_FORMATSIZE];
+       const char *dbtype[4] = { "_builtin", NULL, "@", "." };
+       const char *sep = ": view ";
+       const char *viewname = view->name;
+       dns_zone_t *zone = NULL;
+       int dbtypec = 4;
+       isc_result_t result;
+
+       REQUIRE(type != NULL);
+
+       if (!strcmp(viewname, "_default")) {
+               sep = "";
+               viewname = "";
+       }
+
+       dbtype[1] = type;
+       if (server != NULL) {
+               dbtype[2] = server;
+       }
+       if (contact != NULL) {
+               dbtype[3] = contact;
+       }
+
+       if (pzone != NULL) {
+               result = check_dbtype(pzone, dbtypec, dbtype, view->mctx);
+               if (result != ISC_R_SUCCESS) {
+                       pzone = NULL;
+               }
+       }
+
+       if (pzone == NULL) {
+               /*
+                * Create the actual zone.
+                */
+               CHECK(dns_zone_create(&zone, mctx));
+               CHECK(dns_zone_setorigin(zone, name));
+               CHECK(dns_zonemgr_managezone(named_g_server->zonemgr, zone));
+               dns_zone_setclass(zone, view->rdclass);
+               dns_zone_settype(zone, dns_zone_master);
+               dns_zone_setstats(zone, named_g_server->zonestats);
+               dns_zone_setdbtype(zone, dbtypec, dbtype);
+               dns_zone_setdialup(zone, dns_dialuptype_no);
+               dns_zone_setnotifytype(zone, dns_notifytype_no);
+               dns_zone_setautomatic(zone, true);
+               dns_zone_setoption(zone, DNS_ZONEOPT_NOCHECKNS, true);
+       } else {
+               dns_zone_attach(pzone, &zone);
+       }
+       if (view->queryacl != NULL) {
+               dns_zone_setqueryacl(zone, view->queryacl);
+       } else {
+               dns_zone_clearqueryacl(zone);
+       }
+       if (view->queryonacl != NULL) {
+               dns_zone_setqueryonacl(zone, view->queryonacl);
+       } else {
+               dns_zone_clearqueryonacl(zone);
+       }
+       dns_zone_setview(zone, view);
+       CHECK(dns_view_addzone(view, zone));
+
+       dns_name_format(name, namebuf, sizeof(namebuf));
+       isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
+                     NAMED_LOGMODULE_SERVER, ISC_LOG_INFO,
+                     "automatic ipv4only zone%s%s: %s", sep, viewname,
+                     namebuf);
+
+cleanup:
+       if (zone != NULL) {
+               dns_zone_detach(&zone);
+       }
+       return (result);
+}
+
 #ifdef HAVE_DNSTAP
 static isc_result_t
 configure_dnstap(const cfg_obj_t **maps, dns_view_t *view) {
@@ -5629,6 +5713,92 @@ configure_view(dns_view_t *view, dns_viewlist_t *viewlist, cfg_obj_t *config,
                }
        }
 
+       obj = NULL;
+       if (view->rdclass == dns_rdataclass_in) {
+               (void)named_config_get(maps, "ipv4only-enable", &obj);
+       }
+       if (view->rdclass == dns_rdataclass_in && (obj != NULL)
+                   ? cfg_obj_asboolean(obj)
+                   : !ISC_LIST_EMPTY(view->dns64))
+       {
+               const char *server, *contact;
+               dns_fixedname_t fixed;
+               dns_name_t *name;
+               struct {
+                       const char *name;
+                       const char *type;
+               } zones[] = {
+                       { "ipv4only.arpa", "ipv4only" },
+                       { "170.0.0.192.in-addr.arpa", "ipv4reverse" },
+                       { "171.0.0.192.in-addr.arpa", "ipv4reverse" },
+               };
+               size_t ipv4only_zone;
+
+               obj = NULL;
+               result = named_config_get(maps, "ipv4only-server", &obj);
+               if (result == ISC_R_SUCCESS) {
+                       server = cfg_obj_asstring(obj);
+               } else {
+                       server = NULL;
+               }
+
+               obj = NULL;
+               result = named_config_get(maps, "ipv4only-contact", &obj);
+               if (result == ISC_R_SUCCESS) {
+                       contact = cfg_obj_asstring(obj);
+               } else {
+                       contact = NULL;
+               }
+
+               name = dns_fixedname_initname(&fixed);
+               for (ipv4only_zone = 0; ipv4only_zone < ARRAYSIZE(zones);
+                    ipv4only_zone++) {
+                       dns_forwarders_t *dnsforwarders = NULL;
+
+                       CHECK(dns_name_fromstring(
+                               name, zones[ipv4only_zone].name, 0, NULL));
+
+                       (void)dns_view_findzone(view, name, &zone);
+                       if (zone != NULL) {
+                               dns_zone_detach(&zone);
+                               continue;
+                       }
+
+                       /*
+                        * If we would forward this name don't add it.
+                        */
+                       result = dns_fwdtable_find(view->fwdtable, name, NULL,
+                                                  &dnsforwarders);
+                       if (result == ISC_R_SUCCESS &&
+                           dnsforwarders->fwdpolicy == dns_fwdpolicy_only) {
+                               continue;
+                       }
+
+                       /*
+                        * See if we can re-use a existing zone.
+                        */
+                       result = dns_viewlist_find(&named_g_server->viewlist,
+                                                  view->name, view->rdclass,
+                                                  &pview);
+                       if (result != ISC_R_NOTFOUND && result != ISC_R_SUCCESS)
+                       {
+                               goto cleanup;
+                       }
+
+                       if (pview != NULL) {
+                               (void)dns_view_findzone(pview, name, &zone);
+                               dns_view_detach(&pview);
+                       }
+
+                       CHECK(create_ipv4only_zone(zone, view, name,
+                                                  zones[ipv4only_zone].type,
+                                                  mctx, server, contact));
+                       if (zone != NULL) {
+                               dns_zone_detach(&zone);
+                       }
+               }
+       }
+
        obj = NULL;
        result = named_config_get(maps, "rate-limit", &obj);
        if (result == ISC_R_SUCCESS) {
index abf620fa11e96455eeb24beaa0e889dcdd594850..015763ad193142c14e5135bc8289966726efded5 100644 (file)
@@ -327,6 +327,9 @@ options {
       hostname ( quoted_string | none );
       inline\-signing boolean;
       interface\-interval duration;
+      ipv4only\-contact string;
+      ipv4only\-enable boolean;
+      ipv4only\-server string;
       ixfr\-from\-differences ( primary | master | secondary | slave |
           boolean );
       keep\-response\-order { address_match_element; ... };
@@ -735,6 +738,9 @@ view string [ class ] {
           | ipv6_address ) [ port integer ] [ dscp integer ]; ... };
       glue\-cache boolean;// deprecated
       inline\-signing boolean;
+      ipv4only\-contact string;
+      ipv4only\-enable boolean;
+      ipv4only\-server string;
       ixfr\-from\-differences ( primary | master | secondary | slave |
           boolean );
       key string {
index 27ee95a3d3779de92ab7eb07cb8814140ca335cb..eac0be785a9597520b33e4ddabcade19ba5fa7ed 100644 (file)
@@ -215,6 +215,9 @@ options {
         hostname ( <quoted_string> | none );
         inline-signing <boolean>;
         interface-interval <duration>;
+        ipv4only-contact <string>;
+        ipv4only-enable <boolean>;
+        ipv4only-server <string>;
         ixfr-from-differences ( primary | master | secondary | slave |
             <boolean> );
         keep-response-order { <address_match_element>; ... };
@@ -589,6 +592,9 @@ view <string> [ <class> ] {
             | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
         glue-cache <boolean>; // deprecated
         inline-signing <boolean>;
+        ipv4only-contact <string>;
+        ipv4only-enable <boolean>;
+        ipv4only-server <string>;
         ixfr-from-differences ( primary | master | secondary | slave |
             <boolean> );
         key <string> {
index 9fbffdb84075b52c297cfcfd935929045884989e..b418af3c39ecd171349f943ba2969218527c1774 100644 (file)
@@ -192,6 +192,9 @@ options {
         hostname ( <quoted_string> | none );
         inline-signing <boolean>;
         interface-interval <duration>;
+        ipv4only-contact <string>;
+        ipv4only-enable <boolean>;
+        ipv4only-server <string>;
         ixfr-from-differences ( primary | master | secondary | slave |
             <boolean> );
         keep-response-order { <address_match_element>; ... };
@@ -529,6 +532,9 @@ view <string> [ <class> ] {
             | <ipv6_address> ) [ port <integer> ] [ dscp <integer> ]; ... };
         glue-cache <boolean>; // deprecated
         inline-signing <boolean>;
+        ipv4only-contact <string>;
+        ipv4only-enable <boolean>;
+        ipv4only-server <string>;
         ixfr-from-differences ( primary | master | secondary | slave |
             <boolean> );
         key <string> {
index ace29b5704fdf39760dddb1d7b7243c54e020c41..9dba4f965ad53adb8dc66913e5e2179f838a4c52 100644 (file)
        hostname ( <quoted_string> | none );
        inline-signing <boolean>;
        interface-interval <duration>;
+       ipv4only-contact <string>;
+       ipv4only-enable <boolean>;
+       ipv4only-server <string>;
        ixfr-from-differences ( primary | master | secondary | slave |
            <boolean> );
        keep-response-order { <address_match_element>; ... };
index f139aa3dda17ae422a707e262d8d768d765f0c73..ceb9a022291433f4faa731cb613735155fce371e 100644 (file)
@@ -2022,6 +2022,9 @@ static cfg_clausedef_t view_clauses[] = {
        { "filter-aaaa-on-v4", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
        { "filter-aaaa-on-v6", &cfg_type_boolean, CFG_CLAUSEFLAG_OBSOLETE },
        { "glue-cache", &cfg_type_boolean, CFG_CLAUSEFLAG_DEPRECATED },
+       { "ipv4only-enable", &cfg_type_boolean, 0 },
+       { "ipv4only-contact", &cfg_type_astring, 0 },
+       { "ipv4only-server", &cfg_type_astring, 0 },
        { "ixfr-from-differences", &cfg_type_ixfrdifftype, 0 },
        { "lame-ttl", &cfg_type_duration, 0 },
 #ifdef HAVE_LMDB