1 /* $NetBSD: rootns.c,v 1.9 2015/07/08 17:28:59 christos Exp $ */
4 * Copyright (C) 2004, 2005, 2007, 2008, 2010, 2012-2015 Internet Systems Consortium, Inc. ("ISC")
5 * Copyright (C) 1999-2002 Internet Software Consortium.
7 * Permission to use, copy, modify, and/or distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
11 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
16 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
20 /* Id: rootns.c,v 1.40.476.1 2012/02/07 00:44:14 each Exp */
26 #include <isc/buffer.h>
27 #include <isc/string.h> /* Required for HP/UX (and others?) */
30 #include <dns/callbacks.h>
32 #include <dns/dbiterator.h>
33 #include <dns/fixedname.h>
35 #include <dns/master.h>
36 #include <dns/rdata.h>
37 #include <dns/rdata.h>
38 #include <dns/rdataset.h>
39 #include <dns/rdatasetiter.h>
40 #include <dns/rdatastruct.h>
41 #include <dns/rdatatype.h>
42 #include <dns/result.h>
43 #include <dns/rootns.h>
46 static char root_ns
[] =
48 "; Internet Root Nameservers\n"
51 ". 518400 IN NS A.ROOT-SERVERS.NET.\n"
52 ". 518400 IN NS B.ROOT-SERVERS.NET.\n"
53 ". 518400 IN NS C.ROOT-SERVERS.NET.\n"
54 ". 518400 IN NS D.ROOT-SERVERS.NET.\n"
55 ". 518400 IN NS E.ROOT-SERVERS.NET.\n"
56 ". 518400 IN NS F.ROOT-SERVERS.NET.\n"
57 ". 518400 IN NS G.ROOT-SERVERS.NET.\n"
58 ". 518400 IN NS H.ROOT-SERVERS.NET.\n"
59 ". 518400 IN NS I.ROOT-SERVERS.NET.\n"
60 ". 518400 IN NS J.ROOT-SERVERS.NET.\n"
61 ". 518400 IN NS K.ROOT-SERVERS.NET.\n"
62 ". 518400 IN NS L.ROOT-SERVERS.NET.\n"
63 ". 518400 IN NS M.ROOT-SERVERS.NET.\n"
64 "A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4\n"
65 "A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n"
66 "B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201\n"
67 "C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n"
68 "C.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2::c\n"
69 "D.ROOT-SERVERS.NET. 3600000 IN A 199.7.91.13\n"
70 "D.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2d::d\n"
71 "E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n"
72 "F.ROOT-SERVERS.NET. 3600000 IN A 192.5.5.241\n"
73 "F.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2F::F\n"
74 "G.ROOT-SERVERS.NET. 3600000 IN A 192.112.36.4\n"
75 "H.ROOT-SERVERS.NET. 3600000 IN A 128.63.2.53\n"
76 "H.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:1::803F:235\n"
77 "I.ROOT-SERVERS.NET. 3600000 IN A 192.36.148.17\n"
78 "I.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7fe::53\n"
79 "J.ROOT-SERVERS.NET. 3600000 IN A 192.58.128.30\n"
80 "J.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:C27::2:30\n"
81 "K.ROOT-SERVERS.NET. 3600000 IN A 193.0.14.129\n"
82 "K.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7FD::1\n"
83 "L.ROOT-SERVERS.NET. 3600000 IN A 199.7.83.42\n"
84 "L.ROOT-SERVERS.NET. 604800 IN AAAA 2001:500:3::42\n"
85 "M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n"
86 "M.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:DC3::35\n";
89 in_rootns(dns_rdataset_t
*rootns
, dns_name_t
*name
) {
91 dns_rdata_t rdata
= DNS_RDATA_INIT
;
94 if (!dns_rdataset_isassociated(rootns
))
95 return (ISC_R_NOTFOUND
);
97 result
= dns_rdataset_first(rootns
);
98 while (result
== ISC_R_SUCCESS
) {
99 dns_rdataset_current(rootns
, &rdata
);
100 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
101 if (result
!= ISC_R_SUCCESS
)
103 if (dns_name_compare(name
, &ns
.name
) == 0)
104 return (ISC_R_SUCCESS
);
105 result
= dns_rdataset_next(rootns
);
106 dns_rdata_reset(&rdata
);
108 if (result
== ISC_R_NOMORE
)
109 result
= ISC_R_NOTFOUND
;
114 check_node(dns_rdataset_t
*rootns
, dns_name_t
*name
,
115 dns_rdatasetiter_t
*rdsiter
) {
117 dns_rdataset_t rdataset
;
119 dns_rdataset_init(&rdataset
);
120 result
= dns_rdatasetiter_first(rdsiter
);
121 while (result
== ISC_R_SUCCESS
) {
122 dns_rdatasetiter_current(rdsiter
, &rdataset
);
123 switch (rdataset
.type
) {
124 case dns_rdatatype_a
:
125 case dns_rdatatype_aaaa
:
126 result
= in_rootns(rootns
, name
);
127 if (result
!= ISC_R_SUCCESS
)
130 case dns_rdatatype_ns
:
131 if (dns_name_compare(name
, dns_rootname
) == 0)
135 result
= ISC_R_FAILURE
;
138 dns_rdataset_disassociate(&rdataset
);
139 result
= dns_rdatasetiter_next(rdsiter
);
141 if (result
== ISC_R_NOMORE
)
142 result
= ISC_R_SUCCESS
;
144 if (dns_rdataset_isassociated(&rdataset
))
145 dns_rdataset_disassociate(&rdataset
);
150 check_hints(dns_db_t
*db
) {
152 dns_rdataset_t rootns
;
153 dns_dbiterator_t
*dbiter
= NULL
;
154 dns_dbnode_t
*node
= NULL
;
156 dns_fixedname_t fixname
;
158 dns_rdatasetiter_t
*rdsiter
= NULL
;
160 isc_stdtime_get(&now
);
162 dns_fixedname_init(&fixname
);
163 name
= dns_fixedname_name(&fixname
);
165 dns_rdataset_init(&rootns
);
166 (void)dns_db_find(db
, dns_rootname
, NULL
, dns_rdatatype_ns
, 0,
167 now
, NULL
, name
, &rootns
, NULL
);
168 result
= dns_db_createiterator(db
, 0, &dbiter
);
169 if (result
!= ISC_R_SUCCESS
)
171 result
= dns_dbiterator_first(dbiter
);
172 while (result
== ISC_R_SUCCESS
) {
173 result
= dns_dbiterator_current(dbiter
, &node
, name
);
174 if (result
!= ISC_R_SUCCESS
)
176 result
= dns_db_allrdatasets(db
, node
, NULL
, now
, &rdsiter
);
177 if (result
!= ISC_R_SUCCESS
)
179 result
= check_node(&rootns
, name
, rdsiter
);
180 if (result
!= ISC_R_SUCCESS
)
182 dns_rdatasetiter_destroy(&rdsiter
);
183 dns_db_detachnode(db
, &node
);
184 result
= dns_dbiterator_next(dbiter
);
186 if (result
== ISC_R_NOMORE
)
187 result
= ISC_R_SUCCESS
;
190 if (dns_rdataset_isassociated(&rootns
))
191 dns_rdataset_disassociate(&rootns
);
193 dns_rdatasetiter_destroy(&rdsiter
);
195 dns_db_detachnode(db
, &node
);
197 dns_dbiterator_destroy(&dbiter
);
202 dns_rootns_create(isc_mem_t
*mctx
, dns_rdataclass_t rdclass
,
203 const char *filename
, dns_db_t
**target
)
205 isc_result_t result
, eresult
;
208 dns_rdatacallbacks_t callbacks
;
211 REQUIRE(target
!= NULL
&& *target
== NULL
);
213 result
= dns_db_create(mctx
, "rbt", dns_rootname
, dns_dbtype_zone
,
214 rdclass
, 0, NULL
, &db
);
215 if (result
!= ISC_R_SUCCESS
)
218 len
= strlen(root_ns
);
219 isc_buffer_init(&source
, root_ns
, len
);
220 isc_buffer_add(&source
, len
);
222 dns_rdatacallbacks_init(&callbacks
);
223 result
= dns_db_beginload(db
, &callbacks
);
224 if (result
!= ISC_R_SUCCESS
)
226 if (filename
!= NULL
) {
228 * Load the hints from the specified filename.
230 result
= dns_master_loadfile(filename
, &db
->origin
,
231 &db
->origin
, db
->rdclass
,
233 &callbacks
, db
->mctx
);
234 } else if (rdclass
== dns_rdataclass_in
) {
236 * Default to using the Internet root servers.
238 result
= dns_master_loadbuffer(&source
, &db
->origin
,
239 &db
->origin
, db
->rdclass
,
241 &callbacks
, db
->mctx
);
243 result
= ISC_R_NOTFOUND
;
244 eresult
= dns_db_endload(db
, &callbacks
);
245 if (result
== ISC_R_SUCCESS
|| result
== DNS_R_SEENINCLUDE
)
247 if (result
!= ISC_R_SUCCESS
&& result
!= DNS_R_SEENINCLUDE
)
249 if (check_hints(db
) != ISC_R_SUCCESS
)
250 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
251 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
252 "extra data in root hints '%s'",
253 (filename
!= NULL
) ? filename
: "<BUILT-IN>");
255 return (ISC_R_SUCCESS
);
258 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
, DNS_LOGMODULE_HINTS
,
259 ISC_LOG_ERROR
, "could not configure root hints from "
260 "'%s': %s", (filename
!= NULL
) ? filename
: "<BUILT-IN>",
261 isc_result_totext(result
));
270 report(dns_view_t
*view
, dns_name_t
*name
, isc_boolean_t missing
,
273 const char *viewname
= "", *sep
= "";
274 char namebuf
[DNS_NAME_FORMATSIZE
];
275 char typebuf
[DNS_RDATATYPE_FORMATSIZE
];
276 char databuf
[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
280 if (strcmp(view
->name
, "_bind") != 0 &&
281 strcmp(view
->name
, "_default") != 0) {
282 viewname
= view
->name
;
286 dns_name_format(name
, namebuf
, sizeof(namebuf
));
287 dns_rdatatype_format(rdata
->type
, typebuf
, sizeof(typebuf
));
288 isc_buffer_init(&buffer
, databuf
, sizeof(databuf
) - 1);
289 result
= dns_rdata_totext(rdata
, NULL
, &buffer
);
290 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
291 databuf
[isc_buffer_usedlength(&buffer
)] = '\0';
294 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
295 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
296 "checkhints%s%s: %s/%s (%s) missing from hints",
297 sep
, viewname
, namebuf
, typebuf
, databuf
);
299 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
300 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
301 "checkhints%s%s: %s/%s (%s) extra record "
302 "in hints", sep
, viewname
, namebuf
, typebuf
,
307 inrrset(dns_rdataset_t
*rrset
, dns_rdata_t
*rdata
) {
309 dns_rdata_t current
= DNS_RDATA_INIT
;
311 result
= dns_rdataset_first(rrset
);
312 while (result
== ISC_R_SUCCESS
) {
313 dns_rdataset_current(rrset
, ¤t
);
314 if (dns_rdata_compare(rdata
, ¤t
) == 0)
316 dns_rdata_reset(¤t
);
317 result
= dns_rdataset_next(rrset
);
323 * Check that the address RRsets match.
325 * Note we don't complain about missing glue records.
329 check_address_records(dns_view_t
*view
, dns_db_t
*hints
, dns_db_t
*db
,
330 dns_name_t
*name
, isc_stdtime_t now
)
332 isc_result_t hresult
, rresult
, result
;
333 dns_rdataset_t hintrrset
, rootrrset
;
334 dns_rdata_t rdata
= DNS_RDATA_INIT
;
335 dns_name_t
*foundname
;
336 dns_fixedname_t fixed
;
338 dns_rdataset_init(&hintrrset
);
339 dns_rdataset_init(&rootrrset
);
340 dns_fixedname_init(&fixed
);
341 foundname
= dns_fixedname_name(&fixed
);
343 hresult
= dns_db_find(hints
, name
, NULL
, dns_rdatatype_a
, 0,
344 now
, NULL
, foundname
, &hintrrset
, NULL
);
345 rresult
= dns_db_find(db
, name
, NULL
, dns_rdatatype_a
,
346 DNS_DBFIND_GLUEOK
, now
, NULL
, foundname
,
348 if (hresult
== ISC_R_SUCCESS
&&
349 (rresult
== ISC_R_SUCCESS
|| rresult
== DNS_R_GLUE
)) {
350 result
= dns_rdataset_first(&rootrrset
);
351 while (result
== ISC_R_SUCCESS
) {
352 dns_rdata_reset(&rdata
);
353 dns_rdataset_current(&rootrrset
, &rdata
);
354 if (!inrrset(&hintrrset
, &rdata
))
355 report(view
, name
, ISC_TRUE
, &rdata
);
356 result
= dns_rdataset_next(&rootrrset
);
358 result
= dns_rdataset_first(&hintrrset
);
359 while (result
== ISC_R_SUCCESS
) {
360 dns_rdata_reset(&rdata
);
361 dns_rdataset_current(&hintrrset
, &rdata
);
362 if (!inrrset(&rootrrset
, &rdata
))
363 report(view
, name
, ISC_FALSE
, &rdata
);
364 result
= dns_rdataset_next(&hintrrset
);
367 if (hresult
== ISC_R_NOTFOUND
&&
368 (rresult
== ISC_R_SUCCESS
|| rresult
== DNS_R_GLUE
)) {
369 result
= dns_rdataset_first(&rootrrset
);
370 while (result
== ISC_R_SUCCESS
) {
371 dns_rdata_reset(&rdata
);
372 dns_rdataset_current(&rootrrset
, &rdata
);
373 report(view
, name
, ISC_TRUE
, &rdata
);
374 result
= dns_rdataset_next(&rootrrset
);
377 if (dns_rdataset_isassociated(&rootrrset
))
378 dns_rdataset_disassociate(&rootrrset
);
379 if (dns_rdataset_isassociated(&hintrrset
))
380 dns_rdataset_disassociate(&hintrrset
);
383 * Check AAAA records.
385 hresult
= dns_db_find(hints
, name
, NULL
, dns_rdatatype_aaaa
, 0,
386 now
, NULL
, foundname
, &hintrrset
, NULL
);
387 rresult
= dns_db_find(db
, name
, NULL
, dns_rdatatype_aaaa
,
388 DNS_DBFIND_GLUEOK
, now
, NULL
, foundname
,
390 if (hresult
== ISC_R_SUCCESS
&&
391 (rresult
== ISC_R_SUCCESS
|| rresult
== DNS_R_GLUE
)) {
392 result
= dns_rdataset_first(&rootrrset
);
393 while (result
== ISC_R_SUCCESS
) {
394 dns_rdata_reset(&rdata
);
395 dns_rdataset_current(&rootrrset
, &rdata
);
396 if (!inrrset(&hintrrset
, &rdata
))
397 report(view
, name
, ISC_TRUE
, &rdata
);
398 dns_rdata_reset(&rdata
);
399 result
= dns_rdataset_next(&rootrrset
);
401 result
= dns_rdataset_first(&hintrrset
);
402 while (result
== ISC_R_SUCCESS
) {
403 dns_rdata_reset(&rdata
);
404 dns_rdataset_current(&hintrrset
, &rdata
);
405 if (!inrrset(&rootrrset
, &rdata
))
406 report(view
, name
, ISC_FALSE
, &rdata
);
407 dns_rdata_reset(&rdata
);
408 result
= dns_rdataset_next(&hintrrset
);
411 if (hresult
== ISC_R_NOTFOUND
&&
412 (rresult
== ISC_R_SUCCESS
|| rresult
== DNS_R_GLUE
)) {
413 result
= dns_rdataset_first(&rootrrset
);
414 while (result
== ISC_R_SUCCESS
) {
415 dns_rdata_reset(&rdata
);
416 dns_rdataset_current(&rootrrset
, &rdata
);
417 report(view
, name
, ISC_TRUE
, &rdata
);
418 dns_rdata_reset(&rdata
);
419 result
= dns_rdataset_next(&rootrrset
);
422 if (dns_rdataset_isassociated(&rootrrset
))
423 dns_rdataset_disassociate(&rootrrset
);
424 if (dns_rdataset_isassociated(&hintrrset
))
425 dns_rdataset_disassociate(&hintrrset
);
429 dns_root_checkhints(dns_view_t
*view
, dns_db_t
*hints
, dns_db_t
*db
) {
431 dns_rdata_t rdata
= DNS_RDATA_INIT
;
433 dns_rdataset_t hintns
, rootns
;
434 const char *viewname
= "", *sep
= "";
437 dns_fixedname_t fixed
;
439 REQUIRE(hints
!= NULL
);
441 REQUIRE(view
!= NULL
);
443 isc_stdtime_get(&now
);
445 if (strcmp(view
->name
, "_bind") != 0 &&
446 strcmp(view
->name
, "_default") != 0) {
447 viewname
= view
->name
;
451 dns_rdataset_init(&hintns
);
452 dns_rdataset_init(&rootns
);
453 dns_fixedname_init(&fixed
);
454 name
= dns_fixedname_name(&fixed
);
456 result
= dns_db_find(hints
, dns_rootname
, NULL
, dns_rdatatype_ns
, 0,
457 now
, NULL
, name
, &hintns
, NULL
);
458 if (result
!= ISC_R_SUCCESS
) {
459 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
460 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
461 "checkhints%s%s: unable to get root NS rrset "
462 "from hints: %s", sep
, viewname
,
463 dns_result_totext(result
));
467 result
= dns_db_find(db
, dns_rootname
, NULL
, dns_rdatatype_ns
, 0,
468 now
, NULL
, name
, &rootns
, NULL
);
469 if (result
!= ISC_R_SUCCESS
) {
470 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
471 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
472 "checkhints%s%s: unable to get root NS rrset "
473 "from cache: %s", sep
, viewname
,
474 dns_result_totext(result
));
479 * Look for missing root NS names.
481 result
= dns_rdataset_first(&rootns
);
482 while (result
== ISC_R_SUCCESS
) {
483 dns_rdataset_current(&rootns
, &rdata
);
484 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
485 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
486 result
= in_rootns(&hintns
, &ns
.name
);
487 if (result
!= ISC_R_SUCCESS
) {
488 char namebuf
[DNS_NAME_FORMATSIZE
];
489 /* missing from hints */
490 dns_name_format(&ns
.name
, namebuf
, sizeof(namebuf
));
491 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
492 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
493 "checkhints%s%s: unable to find root "
494 "NS '%s' in hints", sep
, viewname
,
497 check_address_records(view
, hints
, db
, &ns
.name
, now
);
498 dns_rdata_reset(&rdata
);
499 result
= dns_rdataset_next(&rootns
);
501 if (result
!= ISC_R_NOMORE
) {
506 * Look for extra root NS names.
508 result
= dns_rdataset_first(&hintns
);
509 while (result
== ISC_R_SUCCESS
) {
510 dns_rdataset_current(&hintns
, &rdata
);
511 result
= dns_rdata_tostruct(&rdata
, &ns
, NULL
);
512 RUNTIME_CHECK(result
== ISC_R_SUCCESS
);
513 result
= in_rootns(&rootns
, &ns
.name
);
514 if (result
!= ISC_R_SUCCESS
) {
515 char namebuf
[DNS_NAME_FORMATSIZE
];
516 /* extra entry in hints */
517 dns_name_format(&ns
.name
, namebuf
, sizeof(namebuf
));
518 isc_log_write(dns_lctx
, DNS_LOGCATEGORY_GENERAL
,
519 DNS_LOGMODULE_HINTS
, ISC_LOG_WARNING
,
520 "checkhints%s%s: extra NS '%s' in hints",
521 sep
, viewname
, namebuf
);
523 dns_rdata_reset(&rdata
);
524 result
= dns_rdataset_next(&hintns
);
526 if (result
!= ISC_R_NOMORE
) {
531 if (dns_rdataset_isassociated(&rootns
))
532 dns_rdataset_disassociate(&rootns
);
533 if (dns_rdataset_isassociated(&hintns
))
534 dns_rdataset_disassociate(&hintns
);