1999-09-24 01:43:02 +00:00
|
|
|
/*
|
2010-04-07 23:51:06 +00:00
|
|
|
* Copyright (C) Internet Systems Consortium, Inc. ("ISC")
|
1999-09-24 01:43:02 +00:00
|
|
|
*
|
|
|
|
* SPDX-License-Identifier: MPL-2.0
|
2021-06-03 08:37:05 +02:00
|
|
|
*
|
1999-09-24 01:43:02 +00:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, you can obtain one at https://mozilla.org/MPL/2.0/.
|
2018-02-23 09:53:12 +01:00
|
|
|
*
|
1999-09-24 01:43:02 +00:00
|
|
|
* See the COPYRIGHT file distributed with this work for additional
|
2005-02-07 00:53:29 +00:00
|
|
|
* information regarding copyright ownership.
|
1999-09-24 01:43:02 +00:00
|
|
|
*/
|
|
|
|
|
2005-04-27 04:57:32 +00:00
|
|
|
/*! \file */
|
2000-06-22 22:00:42 +00:00
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
#include <stdbool.h>
|
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <isc/buffer.h>
|
2024-08-14 13:25:50 +02:00
|
|
|
#include <isc/log.h>
|
2021-10-04 17:14:53 +02:00
|
|
|
#include <isc/result.h>
|
2022-04-11 15:53:34 +01:00
|
|
|
#include <isc/string.h>
|
2000-04-28 01:12:23 +00:00
|
|
|
#include <isc/util.h>
|
1999-09-24 01:43:02 +00:00
|
|
|
|
2000-05-08 14:38:29 +00:00
|
|
|
#include <dns/callbacks.h>
|
1999-09-24 01:43:02 +00:00
|
|
|
#include <dns/db.h>
|
2001-08-27 03:36:00 +00:00
|
|
|
#include <dns/dbiterator.h>
|
|
|
|
#include <dns/fixedname.h>
|
1999-09-24 01:43:02 +00:00
|
|
|
#include <dns/master.h>
|
2001-08-27 03:36:00 +00:00
|
|
|
#include <dns/rdata.h>
|
|
|
|
#include <dns/rdataset.h>
|
2005-02-07 00:53:29 +00:00
|
|
|
#include <dns/rdatasetiter.h>
|
2001-08-27 03:36:00 +00:00
|
|
|
#include <dns/rdatastruct.h>
|
2005-02-07 00:53:29 +00:00
|
|
|
#include <dns/rdatatype.h>
|
2000-01-22 01:59:02 +00:00
|
|
|
#include <dns/rootns.h>
|
2005-02-07 00:53:29 +00:00
|
|
|
#include <dns/view.h>
|
1999-09-24 01:43:02 +00:00
|
|
|
|
2023-10-18 10:45:41 +11:00
|
|
|
/*
|
|
|
|
* Also update 'upcoming' when updating 'root_ns'.
|
|
|
|
*/
|
1999-10-04 22:39:48 +00:00
|
|
|
static char root_ns[] =
|
1999-10-05 17:40:12 +00:00
|
|
|
";\n"
|
|
|
|
"; Internet Root Nameservers\n"
|
|
|
|
";\n"
|
|
|
|
"$TTL 518400\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
". 518400 IN NS A.ROOT-SERVERS.NET.\n"
|
1999-10-05 17:40:12 +00:00
|
|
|
". 518400 IN NS B.ROOT-SERVERS.NET.\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
". 518400 IN NS C.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS D.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS E.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS F.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS G.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS H.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS I.ROOT-SERVERS.NET.\n"
|
1999-10-05 17:40:12 +00:00
|
|
|
". 518400 IN NS J.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS K.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS L.ROOT-SERVERS.NET.\n"
|
|
|
|
". 518400 IN NS M.ROOT-SERVERS.NET.\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
"A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4\n"
|
2008-02-05 03:21:20 +00:00
|
|
|
"A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n"
|
2023-10-12 10:19:38 +11:00
|
|
|
"B.ROOT-SERVERS.NET. 3600000 IN A 170.247.170.2\n"
|
|
|
|
"B.ROOT-SERVERS.NET. 3600000 IN AAAA 2801:1b8:10::b\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
"C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n"
|
2014-03-29 10:30:40 +11:00
|
|
|
"C.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2::c\n"
|
2012-12-14 12:47:51 +11:00
|
|
|
"D.ROOT-SERVERS.NET. 3600000 IN A 199.7.91.13\n"
|
2013-04-27 16:42:59 -07:00
|
|
|
"D.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2d::d\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
"E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n"
|
2016-08-29 10:15:12 +10:00
|
|
|
"E.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:a8::e\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
"F.ROOT-SERVERS.NET. 3600000 IN A 192.5.5.241\n"
|
2008-02-05 03:21:20 +00:00
|
|
|
"F.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2F::F\n"
|
2000-01-22 02:35:10 +00:00
|
|
|
"G.ROOT-SERVERS.NET. 3600000 IN A 192.112.36.4\n"
|
2016-10-21 22:44:06 +11:00
|
|
|
"G.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:12::d0d\n"
|
2015-11-17 13:16:44 +11:00
|
|
|
"H.ROOT-SERVERS.NET. 3600000 IN A 198.97.190.53\n"
|
|
|
|
"H.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:1::53\n"
|
2000-01-22 02:28:04 +00:00
|
|
|
"I.ROOT-SERVERS.NET. 3600000 IN A 192.36.148.17\n"
|
2010-06-18 05:36:24 +00:00
|
|
|
"I.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7fe::53\n"
|
2002-11-05 22:21:28 +00:00
|
|
|
"J.ROOT-SERVERS.NET. 3600000 IN A 192.58.128.30\n"
|
2008-02-05 03:21:20 +00:00
|
|
|
"J.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:C27::2:30\n"
|
1999-10-05 17:40:12 +00:00
|
|
|
"K.ROOT-SERVERS.NET. 3600000 IN A 193.0.14.129\n"
|
2008-02-05 03:21:20 +00:00
|
|
|
"K.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7FD::1\n"
|
2007-10-30 23:44:01 +00:00
|
|
|
"L.ROOT-SERVERS.NET. 3600000 IN A 199.7.83.42\n"
|
2016-03-11 20:36:48 +11:00
|
|
|
"L.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:9f::42\n"
|
2008-02-05 03:21:20 +00:00
|
|
|
"M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n"
|
|
|
|
"M.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:DC3::35\n";
|
1999-09-24 01:43:02 +00:00
|
|
|
|
2023-10-18 10:45:41 +11:00
|
|
|
static unsigned char b_data[] = "\001b\014root-servers\003net";
|
|
|
|
|
|
|
|
static struct upcoming {
|
|
|
|
const dns_name_t name;
|
|
|
|
dns_rdatatype_t type;
|
|
|
|
isc_stdtime_t time;
|
|
|
|
} upcoming[] = { {
|
2025-02-21 12:09:46 +01:00
|
|
|
.name = DNS_NAME_INITABSOLUTE(b_data),
|
2023-10-18 10:45:41 +11:00
|
|
|
.type = dns_rdatatype_a,
|
|
|
|
.time = 1701086400 /* November 27 2023, 12:00 UTC */
|
|
|
|
},
|
|
|
|
{
|
2025-02-21 12:09:46 +01:00
|
|
|
.name = DNS_NAME_INITABSOLUTE(b_data),
|
2023-10-18 10:45:41 +11:00
|
|
|
.type = dns_rdatatype_aaaa,
|
|
|
|
.time = 1701086400 /* November 27 2023, 12:00 UTC */
|
|
|
|
} };
|
|
|
|
|
2001-08-27 03:36:00 +00:00
|
|
|
static isc_result_t
|
|
|
|
in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_ns_t ns;
|
2008-02-05 23:47:08 +00:00
|
|
|
|
2001-09-30 03:02:47 +00:00
|
|
|
if (!dns_rdataset_isassociated(rootns)) {
|
|
|
|
return ISC_R_NOTFOUND;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-09-30 03:02:47 +00:00
|
|
|
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(rootns) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2001-08-27 03:36:00 +00:00
|
|
|
dns_rdataset_current(rootns, &rdata);
|
|
|
|
result = dns_rdata_tostruct(&rdata, &ns, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
return result;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
if (dns_name_compare(name, &ns.name) == 0) {
|
|
|
|
return ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
|
|
|
}
|
2025-03-21 23:32:27 -07:00
|
|
|
return ISC_R_NOTFOUND;
|
2001-08-27 03:36:00 +00:00
|
|
|
}
|
|
|
|
|
2008-02-05 23:47:08 +00:00
|
|
|
static isc_result_t
|
2001-08-27 03:36:00 +00:00
|
|
|
check_node(dns_rdataset_t *rootns, dns_name_t *name,
|
|
|
|
dns_rdatasetiter_t *rdsiter) {
|
2025-03-26 22:49:03 -07:00
|
|
|
DNS_RDATASETITER_FOREACH(rdsiter) {
|
|
|
|
dns_rdataset_t rdataset = DNS_RDATASET_INIT;
|
2001-08-27 03:36:00 +00:00
|
|
|
dns_rdatasetiter_current(rdsiter, &rdataset);
|
2025-03-26 22:49:03 -07:00
|
|
|
dns_rdatatype_t type = rdataset.type;
|
|
|
|
dns_rdataset_disassociate(&rdataset);
|
|
|
|
|
|
|
|
switch (type) {
|
2001-08-27 03:36:00 +00:00
|
|
|
case dns_rdatatype_a:
|
|
|
|
case dns_rdatatype_aaaa:
|
2025-03-26 22:49:03 -07:00
|
|
|
return in_rootns(rootns, name);
|
2001-08-27 03:36:00 +00:00
|
|
|
case dns_rdatatype_ns:
|
|
|
|
if (dns_name_compare(name, dns_rootname) == 0) {
|
2025-03-26 22:49:03 -07:00
|
|
|
return ISC_R_SUCCESS;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2021-10-11 12:09:16 +02:00
|
|
|
FALLTHROUGH;
|
2001-08-27 03:36:00 +00:00
|
|
|
default:
|
2025-03-26 22:49:03 -07:00
|
|
|
return ISC_R_FAILURE;
|
2001-08-27 03:36:00 +00:00
|
|
|
}
|
|
|
|
}
|
2025-03-26 22:49:03 -07:00
|
|
|
|
|
|
|
return ISC_R_SUCCESS;
|
2001-08-27 03:36:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static isc_result_t
|
|
|
|
check_hints(dns_db_t *db) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdataset_t rootns;
|
|
|
|
dns_dbiterator_t *dbiter = NULL;
|
|
|
|
dns_dbnode_t *node = NULL;
|
2023-03-30 21:13:41 +02:00
|
|
|
isc_stdtime_t now = isc_stdtime_now();
|
2001-08-27 03:36:00 +00:00
|
|
|
dns_fixedname_t fixname;
|
|
|
|
dns_name_t *name;
|
|
|
|
dns_rdatasetiter_t *rdsiter = NULL;
|
|
|
|
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixname);
|
2001-08-27 03:36:00 +00:00
|
|
|
|
|
|
|
dns_rdataset_init(&rootns);
|
2001-09-30 03:02:47 +00:00
|
|
|
(void)dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0, now,
|
|
|
|
NULL, name, &rootns, NULL);
|
2008-09-24 02:46:23 +00:00
|
|
|
result = dns_db_createiterator(db, 0, &dbiter);
|
2001-08-27 03:36:00 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2025-03-26 22:49:03 -07:00
|
|
|
DNS_DBITERATOR_FOREACH(dbiter) {
|
2001-08-27 03:36:00 +00:00
|
|
|
result = dns_dbiterator_current(dbiter, &node, name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2022-11-16 10:47:40 +11:00
|
|
|
result = dns_db_allrdatasets(db, node, NULL, 0, now, &rdsiter);
|
2001-08-27 03:36:00 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
result = check_node(&rootns, name, rdsiter);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
goto cleanup;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
dns_rdatasetiter_destroy(&rdsiter);
|
Decouple database and node lifetimes by adding node-specific vtables
All databases in the codebase follow the same structure: a database is
an associative container from DNS names to nodes, and each node is an
associative container from RR types to RR data.
Each database implementation (qpzone, qpcache, sdlz, builtin, dyndb) has
its own corresponding node type (qpznode, qpcnode, etc). However, some
code needs to work with nodes generically regardless of their specific
type - for example, to acquire locks, manage references, or
register/unregister slabs from the heap.
Currently, these generic node operations are implemented as methods in
the database vtable, which creates problematic coupling between database
and node lifetimes. If a node outlives its parent database, the node
destructor will destroy all RR data, and each RR data destructor will
try to unregister from heaps by calling a virtual function from the
database vtable. Since the database was already freed, this causes a
crash.
This commit breaks the coupling by standardizing the layout of all
database nodes, adding a dedicated vtable for node operations, and
moving node-specific methods from the database vtable to the node
vtable.
2025-06-05 11:51:29 +02:00
|
|
|
dns_db_detachnode(&node);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (dns_rdataset_isassociated(&rootns)) {
|
|
|
|
dns_rdataset_disassociate(&rootns);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
if (rdsiter != NULL) {
|
|
|
|
dns_rdatasetiter_destroy(&rdsiter);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
if (node != NULL) {
|
Decouple database and node lifetimes by adding node-specific vtables
All databases in the codebase follow the same structure: a database is
an associative container from DNS names to nodes, and each node is an
associative container from RR types to RR data.
Each database implementation (qpzone, qpcache, sdlz, builtin, dyndb) has
its own corresponding node type (qpznode, qpcnode, etc). However, some
code needs to work with nodes generically regardless of their specific
type - for example, to acquire locks, manage references, or
register/unregister slabs from the heap.
Currently, these generic node operations are implemented as methods in
the database vtable, which creates problematic coupling between database
and node lifetimes. If a node outlives its parent database, the node
destructor will destroy all RR data, and each RR data destructor will
try to unregister from heaps by calling a virtual function from the
database vtable. Since the database was already freed, this causes a
crash.
This commit breaks the coupling by standardizing the layout of all
database nodes, adding a dedicated vtable for node operations, and
moving node-specific methods from the database vtable to the node
vtable.
2025-06-05 11:51:29 +02:00
|
|
|
dns_db_detachnode(&node);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
if (dbiter != NULL) {
|
|
|
|
dns_dbiterator_destroy(&dbiter);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
1999-09-24 01:43:02 +00:00
|
|
|
isc_result_t
|
2000-01-27 01:55:46 +00:00
|
|
|
dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
|
|
|
|
const char *filename, dns_db_t **target) {
|
1999-12-23 00:09:04 +00:00
|
|
|
isc_result_t result, eresult;
|
1999-09-24 01:43:02 +00:00
|
|
|
isc_buffer_t source;
|
2013-12-04 12:47:23 +11:00
|
|
|
unsigned int len;
|
1999-09-24 01:43:02 +00:00
|
|
|
dns_rdatacallbacks_t callbacks;
|
2000-01-18 23:38:42 +00:00
|
|
|
dns_db_t *db = NULL;
|
2000-08-01 01:33:37 +00:00
|
|
|
|
2000-01-18 23:38:42 +00:00
|
|
|
REQUIRE(target != NULL && *target == NULL);
|
1999-09-24 01:43:02 +00:00
|
|
|
|
2024-03-05 16:17:33 -08:00
|
|
|
result = dns_db_create(mctx, ZONEDB_DEFAULT, dns_rootname,
|
|
|
|
dns_dbtype_zone, rdclass, 0, NULL, &db);
|
1999-09-24 01:43:02 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2015-01-08 19:19:12 +11:00
|
|
|
goto failure;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-24 01:43:02 +00:00
|
|
|
|
|
|
|
len = strlen(root_ns);
|
103. [func] libisc buffer API changes for <isc/buffer.h>:
Added:
isc_buffer_base(b) (pointer)
isc_buffer_current(b) (pointer)
isc_buffer_active(b) (pointer)
isc_buffer_used(b) (pointer)
isc_buffer_length(b) (int)
isc_buffer_usedlength(b) (int)
isc_buffer_consumedlength(b) (int)
isc_buffer_remaininglength(b) (int)
isc_buffer_activelength(b) (int)
isc_buffer_availablelength(b) (int)
Removed:
ISC_BUFFER_USEDCOUNT(b)
ISC_BUFFER_AVAILABLECOUNT(b)
isc_buffer_type(b)
Changed names:
isc_buffer_used(b, r) ->
isc_buffer_usedregion(b, r)
isc_buffer_available(b, r) ->
isc_buffer_available_region(b, r)
isc_buffer_consumed(b, r) ->
isc_buffer_consumedregion(b, r)
isc_buffer_active(b, r) ->
isc_buffer_activeregion(b, r)
isc_buffer_remaining(b, r) ->
isc_buffer_remainingregion(b, r)
Buffer types were removed, so the ISC_BUFFERTYPE_*
macros are no more, and the type argument to
isc_buffer_init and isc_buffer_allocate were removed.
isc_buffer_putstr is now void (instead of isc_result_t)
and requires that the caller ensure that there
is enough available buffer space for the string.
2000-04-27 00:03:12 +00:00
|
|
|
isc_buffer_init(&source, root_ns, len);
|
1999-09-24 01:43:02 +00:00
|
|
|
isc_buffer_add(&source, len);
|
|
|
|
|
2012-06-20 14:13:12 -05:00
|
|
|
dns_rdatacallbacks_init(&callbacks);
|
|
|
|
result = dns_db_beginload(db, &callbacks);
|
1999-09-24 01:43:02 +00:00
|
|
|
if (result != ISC_R_SUCCESS) {
|
2015-01-08 19:19:12 +11:00
|
|
|
goto failure;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-27 01:55:46 +00:00
|
|
|
if (filename != NULL) {
|
|
|
|
/*
|
|
|
|
* Load the hints from the specified filename.
|
|
|
|
*/
|
|
|
|
result = dns_master_loadfile(filename, &db->origin, &db->origin,
|
2018-04-03 13:09:55 +02:00
|
|
|
db->rdclass, DNS_MASTER_HINT, 0,
|
|
|
|
&callbacks, NULL, NULL, db->mctx,
|
|
|
|
dns_masterformat_text, 0);
|
2000-01-27 01:55:46 +00:00
|
|
|
} else if (rdclass == dns_rdataclass_in) {
|
|
|
|
/*
|
|
|
|
* Default to using the Internet root servers.
|
|
|
|
*/
|
|
|
|
result = dns_master_loadbuffer(
|
2008-02-05 23:47:08 +00:00
|
|
|
&source, &db->origin, &db->origin, db->rdclass,
|
2000-06-07 03:30:02 +00:00
|
|
|
DNS_MASTER_HINT, &callbacks, db->mctx);
|
2000-01-27 01:55:46 +00:00
|
|
|
} else {
|
2000-04-06 22:03:35 +00:00
|
|
|
result = ISC_R_NOTFOUND;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2012-06-20 14:13:12 -05:00
|
|
|
eresult = dns_db_endload(db, &callbacks);
|
2000-10-17 07:22:39 +00:00
|
|
|
if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE) {
|
1999-09-24 01:43:02 +00:00
|
|
|
result = eresult;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-10-17 07:22:39 +00:00
|
|
|
if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) {
|
2015-01-08 19:19:12 +11:00
|
|
|
goto failure;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2001-08-27 03:36:00 +00:00
|
|
|
if (check_hints(db) != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
|
|
|
|
ISC_LOG_WARNING, "extra data in root hints '%s'",
|
2001-08-27 03:36:00 +00:00
|
|
|
(filename != NULL) ? filename : "<BUILT-IN>");
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2000-01-18 23:38:42 +00:00
|
|
|
*target = db;
|
2000-04-06 22:03:35 +00:00
|
|
|
return ISC_R_SUCCESS;
|
1999-09-24 01:43:02 +00:00
|
|
|
|
2015-01-08 19:19:12 +11:00
|
|
|
failure:
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
|
2015-01-08 19:19:12 +11:00
|
|
|
ISC_LOG_ERROR,
|
|
|
|
"could not configure root hints from "
|
|
|
|
"'%s': %s",
|
|
|
|
(filename != NULL) ? filename : "<BUILT-IN>",
|
|
|
|
isc_result_totext(result));
|
|
|
|
|
|
|
|
if (db != NULL) {
|
|
|
|
dns_db_detach(&db);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
1999-09-24 01:43:02 +00:00
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
|
|
|
|
static void
|
2018-04-17 08:29:14 -07:00
|
|
|
report(dns_view_t *view, dns_name_t *name, bool missing, dns_rdata_t *rdata) {
|
2005-02-07 00:53:29 +00:00
|
|
|
const char *viewname = "", *sep = "";
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
char typebuf[DNS_RDATATYPE_FORMATSIZE];
|
|
|
|
char databuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
|
|
|
|
isc_buffer_t buffer;
|
|
|
|
isc_result_t result;
|
|
|
|
|
2008-02-05 23:47:08 +00:00
|
|
|
if (strcmp(view->name, "_bind") != 0 &&
|
2022-11-02 19:33:14 +01:00
|
|
|
strcmp(view->name, "_default") != 0)
|
|
|
|
{
|
2008-02-05 23:47:08 +00:00
|
|
|
viewname = view->name;
|
|
|
|
sep = ": view ";
|
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
|
|
|
|
dns_name_format(name, namebuf, sizeof(namebuf));
|
|
|
|
dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
|
|
|
|
isc_buffer_init(&buffer, databuf, sizeof(databuf) - 1);
|
|
|
|
result = dns_rdata_totext(rdata, NULL, &buffer);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
databuf[isc_buffer_usedlength(&buffer)] = '\0';
|
|
|
|
|
|
|
|
if (missing) {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
|
|
|
|
ISC_LOG_WARNING,
|
2005-02-07 00:53:29 +00:00
|
|
|
"checkhints%s%s: %s/%s (%s) missing from hints",
|
|
|
|
sep, viewname, namebuf, typebuf, databuf);
|
|
|
|
} else {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
|
|
|
|
ISC_LOG_WARNING,
|
2005-02-07 00:53:29 +00:00
|
|
|
"checkhints%s%s: %s/%s (%s) extra record "
|
|
|
|
"in hints",
|
|
|
|
sep, viewname, namebuf, typebuf, databuf);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
|
|
|
|
2018-04-17 08:29:14 -07:00
|
|
|
static bool
|
2005-02-07 00:53:29 +00:00
|
|
|
inrrset(dns_rdataset_t *rrset, dns_rdata_t *rdata) {
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(rrset) {
|
|
|
|
dns_rdata_t current = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(rrset, ¤t);
|
|
|
|
if (dns_rdata_compare(rdata, ¤t) == 0) {
|
2018-04-17 08:29:14 -07:00
|
|
|
return true;
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
2018-04-17 08:29:14 -07:00
|
|
|
return false;
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
|
|
|
|
2023-10-18 10:45:41 +11:00
|
|
|
static bool
|
|
|
|
changing(const dns_name_t *name, dns_rdatatype_t type, isc_stdtime_t now) {
|
|
|
|
for (size_t i = 0; i < ARRAY_SIZE(upcoming); i++) {
|
|
|
|
if (upcoming[i].time > now && upcoming[i].type == type &&
|
|
|
|
dns_name_equal(&upcoming[i].name, name))
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2005-02-07 00:53:29 +00:00
|
|
|
/*
|
|
|
|
* Check that the address RRsets match.
|
|
|
|
*
|
|
|
|
* Note we don't complain about missing glue records.
|
|
|
|
*/
|
|
|
|
|
|
|
|
static void
|
|
|
|
check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
|
|
|
|
dns_name_t *name, isc_stdtime_t now) {
|
2025-03-21 23:32:27 -07:00
|
|
|
isc_result_t hresult, rresult;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_t hintrrset, rootrrset;
|
|
|
|
dns_name_t *foundname;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
|
|
|
|
dns_rdataset_init(&hintrrset);
|
|
|
|
dns_rdataset_init(&rootrrset);
|
2018-03-28 14:38:09 +02:00
|
|
|
foundname = dns_fixedname_initname(&fixed);
|
2005-02-07 00:53:29 +00:00
|
|
|
|
|
|
|
hresult = dns_db_find(hints, name, NULL, dns_rdatatype_a, 0, now, NULL,
|
|
|
|
foundname, &hintrrset, NULL);
|
|
|
|
rresult = dns_db_find(db, name, NULL, dns_rdatatype_a,
|
|
|
|
DNS_DBFIND_GLUEOK, now, NULL, foundname,
|
|
|
|
&rootrrset, NULL);
|
|
|
|
if (hresult == ISC_R_SUCCESS &&
|
|
|
|
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE))
|
|
|
|
{
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&rootrrset) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&rootrrset, &rdata);
|
2023-10-18 10:45:41 +11:00
|
|
|
if (!inrrset(&hintrrset, &rdata) &&
|
|
|
|
!changing(name, dns_rdatatype_a, now))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
report(view, name, true, &rdata);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&hintrrset) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&hintrrset, &rdata);
|
2023-10-18 10:45:41 +11:00
|
|
|
if (!inrrset(&rootrrset, &rdata) &&
|
|
|
|
!changing(name, dns_rdatatype_a, now))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
report(view, name, false, &rdata);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
2008-02-05 23:47:08 +00:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
if (hresult == ISC_R_NOTFOUND &&
|
|
|
|
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE))
|
|
|
|
{
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&rootrrset) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&rootrrset, &rdata);
|
2018-04-17 08:29:14 -07:00
|
|
|
report(view, name, true, &rdata);
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dns_rdataset_isassociated(&rootrrset)) {
|
|
|
|
dns_rdataset_disassociate(&rootrrset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
if (dns_rdataset_isassociated(&hintrrset)) {
|
|
|
|
dns_rdataset_disassociate(&hintrrset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Check AAAA records.
|
|
|
|
*/
|
|
|
|
hresult = dns_db_find(hints, name, NULL, dns_rdatatype_aaaa, 0, now,
|
|
|
|
NULL, foundname, &hintrrset, NULL);
|
|
|
|
rresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
|
|
|
|
DNS_DBFIND_GLUEOK, now, NULL, foundname,
|
|
|
|
&rootrrset, NULL);
|
|
|
|
if (hresult == ISC_R_SUCCESS &&
|
|
|
|
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE))
|
|
|
|
{
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&rootrrset) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&rootrrset, &rdata);
|
2023-10-18 10:45:41 +11:00
|
|
|
if (!inrrset(&hintrrset, &rdata) &&
|
|
|
|
!changing(name, dns_rdatatype_aaaa, now))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
report(view, name, true, &rdata);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&hintrrset) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&hintrrset, &rdata);
|
2023-10-18 10:45:41 +11:00
|
|
|
if (!inrrset(&rootrrset, &rdata) &&
|
|
|
|
!changing(name, dns_rdatatype_aaaa, now))
|
|
|
|
{
|
2018-04-17 08:29:14 -07:00
|
|
|
report(view, name, false, &rdata);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
2008-02-05 23:47:08 +00:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
if (hresult == ISC_R_NOTFOUND &&
|
|
|
|
(rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE))
|
|
|
|
{
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&rootrrset) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&rootrrset, &rdata);
|
2018-04-17 08:29:14 -07:00
|
|
|
report(view, name, true, &rdata);
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
if (dns_rdataset_isassociated(&rootrrset)) {
|
|
|
|
dns_rdataset_disassociate(&rootrrset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
if (dns_rdataset_isassociated(&hintrrset)) {
|
|
|
|
dns_rdataset_disassociate(&hintrrset);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
|
|
|
|
isc_result_t result;
|
|
|
|
dns_rdata_ns_t ns;
|
|
|
|
dns_rdataset_t hintns, rootns;
|
|
|
|
const char *viewname = "", *sep = "";
|
2023-03-30 21:13:41 +02:00
|
|
|
isc_stdtime_t now = isc_stdtime_now();
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_name_t *name;
|
|
|
|
dns_fixedname_t fixed;
|
|
|
|
|
|
|
|
REQUIRE(hints != NULL);
|
|
|
|
REQUIRE(db != NULL);
|
|
|
|
REQUIRE(view != NULL);
|
|
|
|
|
2008-02-05 23:47:08 +00:00
|
|
|
if (strcmp(view->name, "_bind") != 0 &&
|
2022-11-02 19:33:14 +01:00
|
|
|
strcmp(view->name, "_default") != 0)
|
|
|
|
{
|
2008-02-05 23:47:08 +00:00
|
|
|
viewname = view->name;
|
|
|
|
sep = ": view ";
|
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
|
|
|
|
dns_rdataset_init(&hintns);
|
|
|
|
dns_rdataset_init(&rootns);
|
2018-03-28 14:38:09 +02:00
|
|
|
name = dns_fixedname_initname(&fixed);
|
2005-02-07 00:53:29 +00:00
|
|
|
|
|
|
|
result = dns_db_find(hints, dns_rootname, NULL, dns_rdatatype_ns, 0,
|
|
|
|
now, NULL, name, &hintns, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
|
|
|
|
ISC_LOG_WARNING,
|
2005-02-07 00:53:29 +00:00
|
|
|
"checkhints%s%s: unable to get root NS rrset "
|
|
|
|
"from hints: %s",
|
2021-10-04 17:14:53 +02:00
|
|
|
sep, viewname, isc_result_totext(result));
|
2005-02-07 00:53:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
|
|
|
|
|
|
|
result = dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0, now,
|
|
|
|
NULL, name, &rootns, NULL);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
|
|
|
|
ISC_LOG_WARNING,
|
2005-02-07 00:53:29 +00:00
|
|
|
"checkhints%s%s: unable to get root NS rrset "
|
|
|
|
"from cache: %s",
|
2021-10-04 17:14:53 +02:00
|
|
|
sep, viewname, isc_result_totext(result));
|
2005-02-07 00:53:29 +00:00
|
|
|
goto cleanup;
|
|
|
|
}
|
2008-02-05 23:47:08 +00:00
|
|
|
|
2005-02-07 00:53:29 +00:00
|
|
|
/*
|
|
|
|
* Look for missing root NS names.
|
|
|
|
*/
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&rootns) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&rootns, &rdata);
|
|
|
|
result = dns_rdata_tostruct(&rdata, &ns, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
result = in_rootns(&hintns, &ns.name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
/* missing from hints */
|
|
|
|
dns_name_format(&ns.name, namebuf, sizeof(namebuf));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL,
|
2005-02-07 00:53:29 +00:00
|
|
|
DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
|
|
|
|
"checkhints%s%s: unable to find root "
|
|
|
|
"NS '%s' in hints",
|
|
|
|
sep, viewname, namebuf);
|
2008-02-05 23:47:08 +00:00
|
|
|
} else {
|
2005-02-07 00:53:29 +00:00
|
|
|
check_address_records(view, hints, db, &ns.name, now);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Look for extra root NS names.
|
|
|
|
*/
|
2025-03-21 23:32:27 -07:00
|
|
|
DNS_RDATASET_FOREACH(&hintns) {
|
|
|
|
dns_rdata_t rdata = DNS_RDATA_INIT;
|
2005-02-07 00:53:29 +00:00
|
|
|
dns_rdataset_current(&hintns, &rdata);
|
|
|
|
result = dns_rdata_tostruct(&rdata, &ns, NULL);
|
|
|
|
RUNTIME_CHECK(result == ISC_R_SUCCESS);
|
|
|
|
result = in_rootns(&rootns, &ns.name);
|
|
|
|
if (result != ISC_R_SUCCESS) {
|
|
|
|
char namebuf[DNS_NAME_FORMATSIZE];
|
|
|
|
/* extra entry in hints */
|
|
|
|
dns_name_format(&ns.name, namebuf, sizeof(namebuf));
|
2024-08-13 18:20:26 +02:00
|
|
|
isc_log_write(DNS_LOGCATEGORY_GENERAL,
|
2005-02-07 00:53:29 +00:00
|
|
|
DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
|
|
|
|
"checkhints%s%s: extra NS '%s' in hints",
|
|
|
|
sep, viewname, namebuf);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
cleanup:
|
|
|
|
if (dns_rdataset_isassociated(&rootns)) {
|
|
|
|
dns_rdataset_disassociate(&rootns);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
if (dns_rdataset_isassociated(&hintns)) {
|
|
|
|
dns_rdataset_disassociate(&hintns);
|
2020-02-13 21:48:23 +01:00
|
|
|
}
|
2005-02-07 00:53:29 +00:00
|
|
|
}
|