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
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;
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) {
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;
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);
}
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.
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);
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;
/*
* 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;
}
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; ... };
| 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 {
#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
}
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];
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;
/*
* Is the existing zone the ok to use?
*/
- if (zone != NULL) {
+ if (pzone != NULL) {
unsigned int typec;
const char **dbargv;
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) {
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);
"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);
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) {
}
}
+ 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) {
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; ... };
| 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 {
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>; ... };
| <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> {
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>; ... };
| <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> {
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>; ... };
{ "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