00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <config.h>
00023
00024 #include <isc/buffer.h>
00025 #include <isc/string.h>
00026 #include <isc/util.h>
00027
00028 #include <dns/callbacks.h>
00029 #include <dns/db.h>
00030 #include <dns/dbiterator.h>
00031 #include <dns/fixedname.h>
00032 #include <dns/log.h>
00033 #include <dns/master.h>
00034 #include <dns/rdata.h>
00035 #include <dns/rdata.h>
00036 #include <dns/rdataset.h>
00037 #include <dns/rdatasetiter.h>
00038 #include <dns/rdatastruct.h>
00039 #include <dns/rdatatype.h>
00040 #include <dns/result.h>
00041 #include <dns/rootns.h>
00042 #include <dns/view.h>
00043
00044 static char root_ns[] =
00045 ";\n"
00046 "; Internet Root Nameservers\n"
00047 ";\n"
00048 "$TTL 518400\n"
00049 ". 518400 IN NS A.ROOT-SERVERS.NET.\n"
00050 ". 518400 IN NS B.ROOT-SERVERS.NET.\n"
00051 ". 518400 IN NS C.ROOT-SERVERS.NET.\n"
00052 ". 518400 IN NS D.ROOT-SERVERS.NET.\n"
00053 ". 518400 IN NS E.ROOT-SERVERS.NET.\n"
00054 ". 518400 IN NS F.ROOT-SERVERS.NET.\n"
00055 ". 518400 IN NS G.ROOT-SERVERS.NET.\n"
00056 ". 518400 IN NS H.ROOT-SERVERS.NET.\n"
00057 ". 518400 IN NS I.ROOT-SERVERS.NET.\n"
00058 ". 518400 IN NS J.ROOT-SERVERS.NET.\n"
00059 ". 518400 IN NS K.ROOT-SERVERS.NET.\n"
00060 ". 518400 IN NS L.ROOT-SERVERS.NET.\n"
00061 ". 518400 IN NS M.ROOT-SERVERS.NET.\n"
00062 "A.ROOT-SERVERS.NET. 3600000 IN A 198.41.0.4\n"
00063 "A.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:BA3E::2:30\n"
00064 "B.ROOT-SERVERS.NET. 3600000 IN A 192.228.79.201\n"
00065 "C.ROOT-SERVERS.NET. 3600000 IN A 192.33.4.12\n"
00066 "C.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2::c\n"
00067 "D.ROOT-SERVERS.NET. 3600000 IN A 199.7.91.13\n"
00068 "D.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2d::d\n"
00069 "E.ROOT-SERVERS.NET. 3600000 IN A 192.203.230.10\n"
00070 "F.ROOT-SERVERS.NET. 3600000 IN A 192.5.5.241\n"
00071 "F.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:2F::F\n"
00072 "G.ROOT-SERVERS.NET. 3600000 IN A 192.112.36.4\n"
00073 "H.ROOT-SERVERS.NET. 3600000 IN A 128.63.2.53\n"
00074 "H.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:500:1::803F:235\n"
00075 "I.ROOT-SERVERS.NET. 3600000 IN A 192.36.148.17\n"
00076 "I.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7fe::53\n"
00077 "J.ROOT-SERVERS.NET. 3600000 IN A 192.58.128.30\n"
00078 "J.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:503:C27::2:30\n"
00079 "K.ROOT-SERVERS.NET. 3600000 IN A 193.0.14.129\n"
00080 "K.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:7FD::1\n"
00081 "L.ROOT-SERVERS.NET. 3600000 IN A 199.7.83.42\n"
00082 "L.ROOT-SERVERS.NET. 604800 IN AAAA 2001:500:3::42\n"
00083 "M.ROOT-SERVERS.NET. 3600000 IN A 202.12.27.33\n"
00084 "M.ROOT-SERVERS.NET. 3600000 IN AAAA 2001:DC3::35\n";
00085
00086 static isc_result_t
00087 in_rootns(dns_rdataset_t *rootns, dns_name_t *name) {
00088 isc_result_t result;
00089 dns_rdata_t rdata = DNS_RDATA_INIT;
00090 dns_rdata_ns_t ns;
00091
00092 if (!dns_rdataset_isassociated(rootns))
00093 return (ISC_R_NOTFOUND);
00094
00095 result = dns_rdataset_first(rootns);
00096 while (result == ISC_R_SUCCESS) {
00097 dns_rdataset_current(rootns, &rdata);
00098 result = dns_rdata_tostruct(&rdata, &ns, NULL);
00099 if (result != ISC_R_SUCCESS)
00100 return (result);
00101 if (dns_name_compare(name, &ns.name) == 0)
00102 return (ISC_R_SUCCESS);
00103 result = dns_rdataset_next(rootns);
00104 dns_rdata_reset(&rdata);
00105 }
00106 if (result == ISC_R_NOMORE)
00107 result = ISC_R_NOTFOUND;
00108 return (result);
00109 }
00110
00111 static isc_result_t
00112 check_node(dns_rdataset_t *rootns, dns_name_t *name,
00113 dns_rdatasetiter_t *rdsiter) {
00114 isc_result_t result;
00115 dns_rdataset_t rdataset;
00116
00117 dns_rdataset_init(&rdataset);
00118 result = dns_rdatasetiter_first(rdsiter);
00119 while (result == ISC_R_SUCCESS) {
00120 dns_rdatasetiter_current(rdsiter, &rdataset);
00121 switch (rdataset.type) {
00122 case dns_rdatatype_a:
00123 case dns_rdatatype_aaaa:
00124 result = in_rootns(rootns, name);
00125 if (result != ISC_R_SUCCESS)
00126 goto cleanup;
00127 break;
00128 case dns_rdatatype_ns:
00129 if (dns_name_compare(name, dns_rootname) == 0)
00130 break;
00131
00132 default:
00133 result = ISC_R_FAILURE;
00134 goto cleanup;
00135 }
00136 dns_rdataset_disassociate(&rdataset);
00137 result = dns_rdatasetiter_next(rdsiter);
00138 }
00139 if (result == ISC_R_NOMORE)
00140 result = ISC_R_SUCCESS;
00141 cleanup:
00142 if (dns_rdataset_isassociated(&rdataset))
00143 dns_rdataset_disassociate(&rdataset);
00144 return (result);
00145 }
00146
00147 static isc_result_t
00148 check_hints(dns_db_t *db) {
00149 isc_result_t result;
00150 dns_rdataset_t rootns;
00151 dns_dbiterator_t *dbiter = NULL;
00152 dns_dbnode_t *node = NULL;
00153 isc_stdtime_t now;
00154 dns_fixedname_t fixname;
00155 dns_name_t *name;
00156 dns_rdatasetiter_t *rdsiter = NULL;
00157
00158 isc_stdtime_get(&now);
00159
00160 dns_fixedname_init(&fixname);
00161 name = dns_fixedname_name(&fixname);
00162
00163 dns_rdataset_init(&rootns);
00164 (void)dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
00165 now, NULL, name, &rootns, NULL);
00166 result = dns_db_createiterator(db, 0, &dbiter);
00167 if (result != ISC_R_SUCCESS)
00168 goto cleanup;
00169 result = dns_dbiterator_first(dbiter);
00170 while (result == ISC_R_SUCCESS) {
00171 result = dns_dbiterator_current(dbiter, &node, name);
00172 if (result != ISC_R_SUCCESS)
00173 goto cleanup;
00174 result = dns_db_allrdatasets(db, node, NULL, now, &rdsiter);
00175 if (result != ISC_R_SUCCESS)
00176 goto cleanup;
00177 result = check_node(&rootns, name, rdsiter);
00178 if (result != ISC_R_SUCCESS)
00179 goto cleanup;
00180 dns_rdatasetiter_destroy(&rdsiter);
00181 dns_db_detachnode(db, &node);
00182 result = dns_dbiterator_next(dbiter);
00183 }
00184 if (result == ISC_R_NOMORE)
00185 result = ISC_R_SUCCESS;
00186
00187 cleanup:
00188 if (dns_rdataset_isassociated(&rootns))
00189 dns_rdataset_disassociate(&rootns);
00190 if (rdsiter != NULL)
00191 dns_rdatasetiter_destroy(&rdsiter);
00192 if (node != NULL)
00193 dns_db_detachnode(db, &node);
00194 if (dbiter != NULL)
00195 dns_dbiterator_destroy(&dbiter);
00196 return (result);
00197 }
00198
00199 isc_result_t
00200 dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
00201 const char *filename, dns_db_t **target)
00202 {
00203 isc_result_t result, eresult;
00204 isc_buffer_t source;
00205 unsigned int len;
00206 dns_rdatacallbacks_t callbacks;
00207 dns_db_t *db = NULL;
00208
00209 REQUIRE(target != NULL && *target == NULL);
00210
00211 result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
00212 rdclass, 0, NULL, &db);
00213 if (result != ISC_R_SUCCESS)
00214 goto failure;
00215
00216 len = strlen(root_ns);
00217 isc_buffer_init(&source, root_ns, len);
00218 isc_buffer_add(&source, len);
00219
00220 dns_rdatacallbacks_init(&callbacks);
00221 result = dns_db_beginload(db, &callbacks);
00222 if (result != ISC_R_SUCCESS)
00223 goto failure;
00224 if (filename != NULL) {
00225
00226
00227
00228 result = dns_master_loadfile(filename, &db->origin,
00229 &db->origin, db->rdclass,
00230 DNS_MASTER_HINT,
00231 &callbacks, db->mctx);
00232 } else if (rdclass == dns_rdataclass_in) {
00233
00234
00235
00236 result = dns_master_loadbuffer(&source, &db->origin,
00237 &db->origin, db->rdclass,
00238 DNS_MASTER_HINT,
00239 &callbacks, db->mctx);
00240 } else
00241 result = ISC_R_NOTFOUND;
00242 eresult = dns_db_endload(db, &callbacks);
00243 if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)
00244 result = eresult;
00245 if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
00246 goto failure;
00247 if (check_hints(db) != ISC_R_SUCCESS)
00248 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00249 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00250 "extra data in root hints '%s'",
00251 (filename != NULL) ? filename : "<BUILT-IN>");
00252 *target = db;
00253 return (ISC_R_SUCCESS);
00254
00255 failure:
00256 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL, DNS_LOGMODULE_HINTS,
00257 ISC_LOG_ERROR, "could not configure root hints from "
00258 "'%s': %s", (filename != NULL) ? filename : "<BUILT-IN>",
00259 isc_result_totext(result));
00260
00261 if (db != NULL)
00262 dns_db_detach(&db);
00263
00264 return (result);
00265 }
00266
00267 static void
00268 report(dns_view_t *view, dns_name_t *name, isc_boolean_t missing,
00269 dns_rdata_t *rdata)
00270 {
00271 const char *viewname = "", *sep = "";
00272 char namebuf[DNS_NAME_FORMATSIZE];
00273 char typebuf[DNS_RDATATYPE_FORMATSIZE];
00274 char databuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:123.123.123.123")];
00275 isc_buffer_t buffer;
00276 isc_result_t result;
00277
00278 if (strcmp(view->name, "_bind") != 0 &&
00279 strcmp(view->name, "_default") != 0) {
00280 viewname = view->name;
00281 sep = ": view ";
00282 }
00283
00284 dns_name_format(name, namebuf, sizeof(namebuf));
00285 dns_rdatatype_format(rdata->type, typebuf, sizeof(typebuf));
00286 isc_buffer_init(&buffer, databuf, sizeof(databuf) - 1);
00287 result = dns_rdata_totext(rdata, NULL, &buffer);
00288 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00289 databuf[isc_buffer_usedlength(&buffer)] = '\0';
00290
00291 if (missing)
00292 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00293 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00294 "checkhints%s%s: %s/%s (%s) missing from hints",
00295 sep, viewname, namebuf, typebuf, databuf);
00296 else
00297 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00298 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00299 "checkhints%s%s: %s/%s (%s) extra record "
00300 "in hints", sep, viewname, namebuf, typebuf,
00301 databuf);
00302 }
00303
00304 static isc_boolean_t
00305 inrrset(dns_rdataset_t *rrset, dns_rdata_t *rdata) {
00306 isc_result_t result;
00307 dns_rdata_t current = DNS_RDATA_INIT;
00308
00309 result = dns_rdataset_first(rrset);
00310 while (result == ISC_R_SUCCESS) {
00311 dns_rdataset_current(rrset, ¤t);
00312 if (dns_rdata_compare(rdata, ¤t) == 0)
00313 return (ISC_TRUE);
00314 dns_rdata_reset(¤t);
00315 result = dns_rdataset_next(rrset);
00316 }
00317 return (ISC_FALSE);
00318 }
00319
00320
00321
00322
00323
00324
00325
00326 static void
00327 check_address_records(dns_view_t *view, dns_db_t *hints, dns_db_t *db,
00328 dns_name_t *name, isc_stdtime_t now)
00329 {
00330 isc_result_t hresult, rresult, result;
00331 dns_rdataset_t hintrrset, rootrrset;
00332 dns_rdata_t rdata = DNS_RDATA_INIT;
00333 dns_name_t *foundname;
00334 dns_fixedname_t fixed;
00335
00336 dns_rdataset_init(&hintrrset);
00337 dns_rdataset_init(&rootrrset);
00338 dns_fixedname_init(&fixed);
00339 foundname = dns_fixedname_name(&fixed);
00340
00341 hresult = dns_db_find(hints, name, NULL, dns_rdatatype_a, 0,
00342 now, NULL, foundname, &hintrrset, NULL);
00343 rresult = dns_db_find(db, name, NULL, dns_rdatatype_a,
00344 DNS_DBFIND_GLUEOK, now, NULL, foundname,
00345 &rootrrset, NULL);
00346 if (hresult == ISC_R_SUCCESS &&
00347 (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
00348 result = dns_rdataset_first(&rootrrset);
00349 while (result == ISC_R_SUCCESS) {
00350 dns_rdata_reset(&rdata);
00351 dns_rdataset_current(&rootrrset, &rdata);
00352 if (!inrrset(&hintrrset, &rdata))
00353 report(view, name, ISC_TRUE, &rdata);
00354 result = dns_rdataset_next(&rootrrset);
00355 }
00356 result = dns_rdataset_first(&hintrrset);
00357 while (result == ISC_R_SUCCESS) {
00358 dns_rdata_reset(&rdata);
00359 dns_rdataset_current(&hintrrset, &rdata);
00360 if (!inrrset(&rootrrset, &rdata))
00361 report(view, name, ISC_FALSE, &rdata);
00362 result = dns_rdataset_next(&hintrrset);
00363 }
00364 }
00365 if (hresult == ISC_R_NOTFOUND &&
00366 (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
00367 result = dns_rdataset_first(&rootrrset);
00368 while (result == ISC_R_SUCCESS) {
00369 dns_rdata_reset(&rdata);
00370 dns_rdataset_current(&rootrrset, &rdata);
00371 report(view, name, ISC_TRUE, &rdata);
00372 result = dns_rdataset_next(&rootrrset);
00373 }
00374 }
00375 if (dns_rdataset_isassociated(&rootrrset))
00376 dns_rdataset_disassociate(&rootrrset);
00377 if (dns_rdataset_isassociated(&hintrrset))
00378 dns_rdataset_disassociate(&hintrrset);
00379
00380
00381
00382
00383 hresult = dns_db_find(hints, name, NULL, dns_rdatatype_aaaa, 0,
00384 now, NULL, foundname, &hintrrset, NULL);
00385 rresult = dns_db_find(db, name, NULL, dns_rdatatype_aaaa,
00386 DNS_DBFIND_GLUEOK, now, NULL, foundname,
00387 &rootrrset, NULL);
00388 if (hresult == ISC_R_SUCCESS &&
00389 (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
00390 result = dns_rdataset_first(&rootrrset);
00391 while (result == ISC_R_SUCCESS) {
00392 dns_rdata_reset(&rdata);
00393 dns_rdataset_current(&rootrrset, &rdata);
00394 if (!inrrset(&hintrrset, &rdata))
00395 report(view, name, ISC_TRUE, &rdata);
00396 dns_rdata_reset(&rdata);
00397 result = dns_rdataset_next(&rootrrset);
00398 }
00399 result = dns_rdataset_first(&hintrrset);
00400 while (result == ISC_R_SUCCESS) {
00401 dns_rdata_reset(&rdata);
00402 dns_rdataset_current(&hintrrset, &rdata);
00403 if (!inrrset(&rootrrset, &rdata))
00404 report(view, name, ISC_FALSE, &rdata);
00405 dns_rdata_reset(&rdata);
00406 result = dns_rdataset_next(&hintrrset);
00407 }
00408 }
00409 if (hresult == ISC_R_NOTFOUND &&
00410 (rresult == ISC_R_SUCCESS || rresult == DNS_R_GLUE)) {
00411 result = dns_rdataset_first(&rootrrset);
00412 while (result == ISC_R_SUCCESS) {
00413 dns_rdata_reset(&rdata);
00414 dns_rdataset_current(&rootrrset, &rdata);
00415 report(view, name, ISC_TRUE, &rdata);
00416 dns_rdata_reset(&rdata);
00417 result = dns_rdataset_next(&rootrrset);
00418 }
00419 }
00420 if (dns_rdataset_isassociated(&rootrrset))
00421 dns_rdataset_disassociate(&rootrrset);
00422 if (dns_rdataset_isassociated(&hintrrset))
00423 dns_rdataset_disassociate(&hintrrset);
00424 }
00425
00426 void
00427 dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
00428 isc_result_t result;
00429 dns_rdata_t rdata = DNS_RDATA_INIT;
00430 dns_rdata_ns_t ns;
00431 dns_rdataset_t hintns, rootns;
00432 const char *viewname = "", *sep = "";
00433 isc_stdtime_t now;
00434 dns_name_t *name;
00435 dns_fixedname_t fixed;
00436
00437 REQUIRE(hints != NULL);
00438 REQUIRE(db != NULL);
00439 REQUIRE(view != NULL);
00440
00441 isc_stdtime_get(&now);
00442
00443 if (strcmp(view->name, "_bind") != 0 &&
00444 strcmp(view->name, "_default") != 0) {
00445 viewname = view->name;
00446 sep = ": view ";
00447 }
00448
00449 dns_rdataset_init(&hintns);
00450 dns_rdataset_init(&rootns);
00451 dns_fixedname_init(&fixed);
00452 name = dns_fixedname_name(&fixed);
00453
00454 result = dns_db_find(hints, dns_rootname, NULL, dns_rdatatype_ns, 0,
00455 now, NULL, name, &hintns, NULL);
00456 if (result != ISC_R_SUCCESS) {
00457 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00458 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00459 "checkhints%s%s: unable to get root NS rrset "
00460 "from hints: %s", sep, viewname,
00461 dns_result_totext(result));
00462 goto cleanup;
00463 }
00464
00465 result = dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
00466 now, NULL, name, &rootns, NULL);
00467 if (result != ISC_R_SUCCESS) {
00468 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00469 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00470 "checkhints%s%s: unable to get root NS rrset "
00471 "from cache: %s", sep, viewname,
00472 dns_result_totext(result));
00473 goto cleanup;
00474 }
00475
00476
00477
00478
00479 result = dns_rdataset_first(&rootns);
00480 while (result == ISC_R_SUCCESS) {
00481 dns_rdataset_current(&rootns, &rdata);
00482 result = dns_rdata_tostruct(&rdata, &ns, NULL);
00483 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00484 result = in_rootns(&hintns, &ns.name);
00485 if (result != ISC_R_SUCCESS) {
00486 char namebuf[DNS_NAME_FORMATSIZE];
00487
00488 dns_name_format(&ns.name, namebuf, sizeof(namebuf));
00489 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00490 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00491 "checkhints%s%s: unable to find root "
00492 "NS '%s' in hints", sep, viewname,
00493 namebuf);
00494 } else
00495 check_address_records(view, hints, db, &ns.name, now);
00496 dns_rdata_reset(&rdata);
00497 result = dns_rdataset_next(&rootns);
00498 }
00499 if (result != ISC_R_NOMORE) {
00500 goto cleanup;
00501 }
00502
00503
00504
00505
00506 result = dns_rdataset_first(&hintns);
00507 while (result == ISC_R_SUCCESS) {
00508 dns_rdataset_current(&hintns, &rdata);
00509 result = dns_rdata_tostruct(&rdata, &ns, NULL);
00510 RUNTIME_CHECK(result == ISC_R_SUCCESS);
00511 result = in_rootns(&rootns, &ns.name);
00512 if (result != ISC_R_SUCCESS) {
00513 char namebuf[DNS_NAME_FORMATSIZE];
00514
00515 dns_name_format(&ns.name, namebuf, sizeof(namebuf));
00516 isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
00517 DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
00518 "checkhints%s%s: extra NS '%s' in hints",
00519 sep, viewname, namebuf);
00520 }
00521 dns_rdata_reset(&rdata);
00522 result = dns_rdataset_next(&hintns);
00523 }
00524 if (result != ISC_R_NOMORE) {
00525 goto cleanup;
00526 }
00527
00528 cleanup:
00529 if (dns_rdataset_isassociated(&rootns))
00530 dns_rdataset_disassociate(&rootns);
00531 if (dns_rdataset_isassociated(&hintns))
00532 dns_rdataset_disassociate(&hintns);
00533 }