view.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2004-2015  Internet Systems Consortium, Inc. ("ISC")
00003  * Copyright (C) 1999-2003  Internet Software Consortium.
00004  *
00005  * Permission to use, copy, modify, and/or distribute this software for any
00006  * purpose with or without fee is hereby granted, provided that the above
00007  * copyright notice and this permission notice appear in all copies.
00008  *
00009  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00010  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00011  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00012  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00013  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00014  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00015  * PERFORMANCE OF THIS SOFTWARE.
00016  */
00017 
00018 /*! \file */
00019 
00020 #include <config.h>
00021 
00022 #include <isc/file.h>
00023 #include <isc/hash.h>
00024 #include <isc/lex.h>
00025 #include <isc/print.h>
00026 #include <isc/sha2.h>
00027 #include <isc/stats.h>
00028 #include <isc/string.h>         /* Required for HP/UX (and others?) */
00029 #include <isc/task.h>
00030 #include <isc/util.h>
00031 
00032 #include <dns/acache.h>
00033 #include <dns/acl.h>
00034 #include <dns/adb.h>
00035 #include <dns/badcache.h>
00036 #include <dns/cache.h>
00037 #include <dns/db.h>
00038 #include <dns/dispatch.h>
00039 #include <dns/dlz.h>
00040 #include <dns/dns64.h>
00041 #include <dns/dnssec.h>
00042 #include <dns/events.h>
00043 #include <dns/forward.h>
00044 #include <dns/keytable.h>
00045 #include <dns/keyvalues.h>
00046 #include <dns/master.h>
00047 #include <dns/masterdump.h>
00048 #include <dns/nta.h>
00049 #include <dns/order.h>
00050 #include <dns/peer.h>
00051 #include <dns/rrl.h>
00052 #include <dns/rbt.h>
00053 #include <dns/rdataset.h>
00054 #include <dns/request.h>
00055 #include <dns/resolver.h>
00056 #include <dns/result.h>
00057 #include <dns/rpz.h>
00058 #include <dns/stats.h>
00059 #include <dns/time.h>
00060 #include <dns/tsig.h>
00061 #include <dns/zone.h>
00062 #include <dns/zt.h>
00063 
00064 #define CHECK(op) \
00065         do { result = (op);                                      \
00066                if (result != ISC_R_SUCCESS) goto cleanup;        \
00067         } while (0)
00068 
00069 #define RESSHUTDOWN(v)  (((v)->attributes & DNS_VIEWATTR_RESSHUTDOWN) != 0)
00070 #define ADBSHUTDOWN(v)  (((v)->attributes & DNS_VIEWATTR_ADBSHUTDOWN) != 0)
00071 #define REQSHUTDOWN(v)  (((v)->attributes & DNS_VIEWATTR_REQSHUTDOWN) != 0)
00072 
00073 #define DNS_VIEW_DELONLYHASH 111
00074 #define DNS_VIEW_FAILCACHESIZE 1021
00075 
00076 static void resolver_shutdown(isc_task_t *task, isc_event_t *event);
00077 static void adb_shutdown(isc_task_t *task, isc_event_t *event);
00078 static void req_shutdown(isc_task_t *task, isc_event_t *event);
00079 
00080 isc_result_t
00081 dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
00082                 const char *name, dns_view_t **viewp)
00083 {
00084         dns_view_t *view;
00085         isc_result_t result;
00086         char buffer[1024];
00087 
00088         /*
00089          * Create a view.
00090          */
00091 
00092         REQUIRE(name != NULL);
00093         REQUIRE(viewp != NULL && *viewp == NULL);
00094 
00095         view = isc_mem_get(mctx, sizeof(*view));
00096         if (view == NULL)
00097                 return (ISC_R_NOMEMORY);
00098 
00099         view->nta_file = NULL;
00100         view->mctx = NULL;
00101         isc_mem_attach(mctx, &view->mctx);
00102         view->name = isc_mem_strdup(mctx, name);
00103         if (view->name == NULL) {
00104                 result = ISC_R_NOMEMORY;
00105                 goto cleanup_view;
00106         }
00107 
00108         result = isc_file_sanitize(NULL, view->name, "nta",
00109                                    buffer, sizeof(buffer));
00110         if (result != ISC_R_SUCCESS)
00111                 goto cleanup_name;
00112         view->nta_file = isc_mem_strdup(mctx, buffer);
00113         if (view->nta_file == NULL) {
00114                 result = ISC_R_NOMEMORY;
00115                 goto cleanup_name;
00116         }
00117 
00118         result = isc_mutex_init(&view->lock);
00119         if (result != ISC_R_SUCCESS)
00120                 goto cleanup_name;
00121 
00122         view->zonetable = NULL;
00123         if (isc_bind9) {
00124                 result = dns_zt_create(mctx, rdclass, &view->zonetable);
00125                 if (result != ISC_R_SUCCESS) {
00126                         UNEXPECTED_ERROR(__FILE__, __LINE__,
00127                                          "dns_zt_create() failed: %s",
00128                                          isc_result_totext(result));
00129                         result = ISC_R_UNEXPECTED;
00130                         goto cleanup_mutex;
00131                 }
00132         }
00133         view->secroots_priv = NULL;
00134         view->ntatable_priv = NULL;
00135         view->fwdtable = NULL;
00136         result = dns_fwdtable_create(mctx, &view->fwdtable);
00137         if (result != ISC_R_SUCCESS) {
00138                 UNEXPECTED_ERROR(__FILE__, __LINE__,
00139                                  "dns_fwdtable_create() failed: %s",
00140                                  isc_result_totext(result));
00141                 result = ISC_R_UNEXPECTED;
00142                 goto cleanup_zt;
00143         }
00144 
00145         view->acache = NULL;
00146         view->cache = NULL;
00147         view->cachedb = NULL;
00148         ISC_LIST_INIT(view->dlz_searched);
00149         ISC_LIST_INIT(view->dlz_unsearched);
00150         view->hints = NULL;
00151         view->resolver = NULL;
00152         view->adb = NULL;
00153         view->requestmgr = NULL;
00154         view->rdclass = rdclass;
00155         view->frozen = ISC_FALSE;
00156         view->task = NULL;
00157         result = isc_refcount_init(&view->references, 1);
00158         if (result != ISC_R_SUCCESS)
00159                 goto cleanup_fwdtable;
00160         view->weakrefs = 0;
00161         view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN|
00162                             DNS_VIEWATTR_REQSHUTDOWN);
00163         view->statickeys = NULL;
00164         view->dynamickeys = NULL;
00165         view->matchclients = NULL;
00166         view->matchdestinations = NULL;
00167         view->matchrecursiveonly = ISC_FALSE;
00168         result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys);
00169         if (result != ISC_R_SUCCESS)
00170                 goto cleanup_references;
00171         view->peers = NULL;
00172         view->order = NULL;
00173         view->delonly = NULL;
00174         view->rootdelonly = ISC_FALSE;
00175         view->rootexclude = NULL;
00176         view->adbstats = NULL;
00177         view->resstats = NULL;
00178         view->resquerystats = NULL;
00179         view->cacheshared = ISC_FALSE;
00180         ISC_LIST_INIT(view->dns64);
00181         view->dns64cnt = 0;
00182 
00183         /*
00184          * Initialize configuration data with default values.
00185          */
00186         view->recursion = ISC_TRUE;
00187         view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */
00188         view->additionalfromcache = ISC_TRUE;
00189         view->additionalfromauth = ISC_TRUE;
00190         view->enablednssec = ISC_TRUE;
00191         view->enablevalidation = ISC_TRUE;
00192         view->acceptexpired = ISC_FALSE;
00193         view->minimalresponses = ISC_FALSE;
00194         view->transfer_format = dns_one_answer;
00195         view->cacheacl = NULL;
00196         view->cacheonacl = NULL;
00197         view->queryacl = NULL;
00198         view->queryonacl = NULL;
00199         view->recursionacl = NULL;
00200         view->recursiononacl = NULL;
00201         view->sortlist = NULL;
00202         view->transferacl = NULL;
00203         view->notifyacl = NULL;
00204         view->updateacl = NULL;
00205         view->upfwdacl = NULL;
00206         view->denyansweracl = NULL;
00207         view->nocasecompress = NULL;
00208         view->answeracl_exclude = NULL;
00209         view->denyanswernames = NULL;
00210         view->answernames_exclude = NULL;
00211         view->rrl = NULL;
00212         view->provideixfr = ISC_TRUE;
00213         view->maxcachettl = 7 * 24 * 3600;
00214         view->maxncachettl = 3 * 3600;
00215         view->nta_lifetime = 0;
00216         view->nta_recheck = 0;
00217         view->prefetch_eligible = 0;
00218         view->prefetch_trigger = 0;
00219         view->dstport = 53;
00220         view->preferred_glue = 0;
00221         view->flush = ISC_FALSE;
00222         view->dlv = NULL;
00223         view->maxudp = 0;
00224         view->situdp = 0;
00225         view->maxbits = 0;
00226         view->v4_aaaa = dns_aaaa_ok;
00227         view->v6_aaaa = dns_aaaa_ok;
00228         view->aaaa_acl = NULL;
00229         view->rpzs = NULL;
00230         dns_fixedname_init(&view->dlv_fixed);
00231         view->managed_keys = NULL;
00232         view->redirect = NULL;
00233         view->redirectzone = NULL;
00234         dns_fixedname_init(&view->redirectfixed);
00235         view->requestnsid = ISC_FALSE;
00236         view->requestsit = ISC_TRUE;
00237         view->new_zone_file = NULL;
00238         view->new_zone_config = NULL;
00239         view->cfg_destroy = NULL;
00240         view->fail_ttl = 0;
00241         view->failcache = NULL;
00242         dns_badcache_init(view->mctx, DNS_VIEW_FAILCACHESIZE, &view->failcache);
00243 
00244         if (isc_bind9) {
00245                 result = dns_order_create(view->mctx, &view->order);
00246                 if (result != ISC_R_SUCCESS)
00247                         goto cleanup_dynkeys;
00248         }
00249 
00250         result = dns_peerlist_new(view->mctx, &view->peers);
00251         if (result != ISC_R_SUCCESS)
00252                 goto cleanup_order;
00253 
00254         result = dns_aclenv_init(view->mctx, &view->aclenv);
00255         if (result != ISC_R_SUCCESS)
00256                 goto cleanup_peerlist;
00257 
00258         ISC_LINK_INIT(view, link);
00259         ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL,
00260                        DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown,
00261                        view, NULL, NULL, NULL);
00262         ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL,
00263                        DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown,
00264                        view, NULL, NULL, NULL);
00265         ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL,
00266                        DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown,
00267                        view, NULL, NULL, NULL);
00268         view->viewlist = NULL;
00269         view->magic = DNS_VIEW_MAGIC;
00270 
00271         *viewp = view;
00272 
00273         return (ISC_R_SUCCESS);
00274 
00275  cleanup_peerlist:
00276         if (view->peers != NULL)
00277                 dns_peerlist_detach(&view->peers);
00278 
00279  cleanup_order:
00280         if (view->order != NULL)
00281                 dns_order_detach(&view->order);
00282 
00283  cleanup_dynkeys:
00284         if (view->dynamickeys != NULL)
00285                 dns_tsigkeyring_detach(&view->dynamickeys);
00286 
00287  cleanup_references:
00288         isc_refcount_destroy(&view->references);
00289 
00290  cleanup_fwdtable:
00291         if (view->fwdtable != NULL)
00292                 dns_fwdtable_destroy(&view->fwdtable);
00293 
00294  cleanup_zt:
00295         if (view->zonetable != NULL)
00296                 dns_zt_detach(&view->zonetable);
00297 
00298  cleanup_mutex:
00299         DESTROYLOCK(&view->lock);
00300 
00301         if (view->nta_file != NULL)
00302                 isc_mem_free(mctx, view->nta_file);
00303 
00304  cleanup_name:
00305         isc_mem_free(mctx, view->name);
00306 
00307  cleanup_view:
00308         isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
00309 
00310         return (result);
00311 }
00312 
00313 static inline void
00314 destroy(dns_view_t *view) {
00315         dns_dns64_t *dns64;
00316         dns_dlzdb_t *dlzdb;
00317 
00318         REQUIRE(!ISC_LINK_LINKED(view, link));
00319         REQUIRE(isc_refcount_current(&view->references) == 0);
00320         REQUIRE(view->weakrefs == 0);
00321         REQUIRE(RESSHUTDOWN(view));
00322         REQUIRE(ADBSHUTDOWN(view));
00323         REQUIRE(REQSHUTDOWN(view));
00324 
00325         if (view->order != NULL)
00326                 dns_order_detach(&view->order);
00327         if (view->peers != NULL)
00328                 dns_peerlist_detach(&view->peers);
00329 
00330         if (view->dynamickeys != NULL) {
00331                 isc_result_t result;
00332                 char template[20];
00333                 char keyfile[20];
00334                 FILE *fp = NULL;
00335                 int n;
00336 
00337                 n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
00338                              view->name);
00339                 if (n > 0 && (size_t)n < sizeof(keyfile)) {
00340                         result = isc_file_mktemplate(keyfile, template,
00341                                                      sizeof(template));
00342                         if (result == ISC_R_SUCCESS)
00343                                 (void)isc_file_openuniqueprivate(template, &fp);
00344                 }
00345                 if (fp == NULL)
00346                         dns_tsigkeyring_detach(&view->dynamickeys);
00347                 else {
00348                         result = dns_tsigkeyring_dumpanddetach(
00349                                                         &view->dynamickeys, fp);
00350                         if (result == ISC_R_SUCCESS) {
00351                                 if (fclose(fp) == 0)
00352                                         result = isc_file_rename(template,
00353                                                                  keyfile);
00354                                 if (result != ISC_R_SUCCESS)
00355                                         (void)remove(template);
00356                         } else {
00357                                 (void)fclose(fp);
00358                                 (void)remove(template);
00359                         }
00360                 }
00361         }
00362         if (view->statickeys != NULL)
00363                 dns_tsigkeyring_detach(&view->statickeys);
00364         if (view->adb != NULL)
00365                 dns_adb_detach(&view->adb);
00366         if (view->resolver != NULL)
00367                 dns_resolver_detach(&view->resolver);
00368         if (view->acache != NULL) {
00369                 if (view->cachedb != NULL)
00370                         dns_acache_putdb(view->acache, view->cachedb);
00371                 dns_acache_detach(&view->acache);
00372         }
00373         dns_rrl_view_destroy(view);
00374         if (view->rpzs != NULL)
00375                 dns_rpz_detach_rpzs(&view->rpzs);
00376         for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
00377              dlzdb != NULL;
00378              dlzdb = ISC_LIST_HEAD(view->dlz_searched)) {
00379                 ISC_LIST_UNLINK(view->dlz_searched, dlzdb, link);
00380                 dns_dlzdestroy(&dlzdb);
00381         }
00382         for (dlzdb = ISC_LIST_HEAD(view->dlz_unsearched);
00383              dlzdb != NULL;
00384              dlzdb = ISC_LIST_HEAD(view->dlz_unsearched)) {
00385                 ISC_LIST_UNLINK(view->dlz_unsearched, dlzdb, link);
00386                 dns_dlzdestroy(&dlzdb);
00387         }
00388         if (view->requestmgr != NULL)
00389                 dns_requestmgr_detach(&view->requestmgr);
00390         if (view->task != NULL)
00391                 isc_task_detach(&view->task);
00392         if (view->hints != NULL)
00393                 dns_db_detach(&view->hints);
00394         if (view->cachedb != NULL)
00395                 dns_db_detach(&view->cachedb);
00396         if (view->cache != NULL)
00397                 dns_cache_detach(&view->cache);
00398         if (view->nocasecompress != NULL)
00399                 dns_acl_detach(&view->nocasecompress);
00400         if (view->matchclients != NULL)
00401                 dns_acl_detach(&view->matchclients);
00402         if (view->matchdestinations != NULL)
00403                 dns_acl_detach(&view->matchdestinations);
00404         if (view->cacheacl != NULL)
00405                 dns_acl_detach(&view->cacheacl);
00406         if (view->cacheonacl != NULL)
00407                 dns_acl_detach(&view->cacheonacl);
00408         if (view->queryacl != NULL)
00409                 dns_acl_detach(&view->queryacl);
00410         if (view->queryonacl != NULL)
00411                 dns_acl_detach(&view->queryonacl);
00412         if (view->recursionacl != NULL)
00413                 dns_acl_detach(&view->recursionacl);
00414         if (view->recursiononacl != NULL)
00415                 dns_acl_detach(&view->recursiononacl);
00416         if (view->sortlist != NULL)
00417                 dns_acl_detach(&view->sortlist);
00418         if (view->transferacl != NULL)
00419                 dns_acl_detach(&view->transferacl);
00420         if (view->notifyacl != NULL)
00421                 dns_acl_detach(&view->notifyacl);
00422         if (view->updateacl != NULL)
00423                 dns_acl_detach(&view->updateacl);
00424         if (view->upfwdacl != NULL)
00425                 dns_acl_detach(&view->upfwdacl);
00426         if (view->denyansweracl != NULL)
00427                 dns_acl_detach(&view->denyansweracl);
00428         if (view->aaaa_acl != NULL)
00429                 dns_acl_detach(&view->aaaa_acl);
00430         if (view->answeracl_exclude != NULL)
00431                 dns_rbt_destroy(&view->answeracl_exclude);
00432         if (view->denyanswernames != NULL)
00433                 dns_rbt_destroy(&view->denyanswernames);
00434         if (view->answernames_exclude != NULL)
00435                 dns_rbt_destroy(&view->answernames_exclude);
00436         if (view->delonly != NULL) {
00437                 dns_name_t *name;
00438                 int i;
00439 
00440                 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
00441                         name = ISC_LIST_HEAD(view->delonly[i]);
00442                         while (name != NULL) {
00443                                 ISC_LIST_UNLINK(view->delonly[i], name, link);
00444                                 dns_name_free(name, view->mctx);
00445                                 isc_mem_put(view->mctx, name, sizeof(*name));
00446                                 name = ISC_LIST_HEAD(view->delonly[i]);
00447                         }
00448                 }
00449                 isc_mem_put(view->mctx, view->delonly, sizeof(dns_namelist_t) *
00450                             DNS_VIEW_DELONLYHASH);
00451                 view->delonly = NULL;
00452         }
00453         if (view->rootexclude != NULL) {
00454                 dns_name_t *name;
00455                 int i;
00456 
00457                 for (i = 0; i < DNS_VIEW_DELONLYHASH; i++) {
00458                         name = ISC_LIST_HEAD(view->rootexclude[i]);
00459                         while (name != NULL) {
00460                                 ISC_LIST_UNLINK(view->rootexclude[i],
00461                                                 name, link);
00462                                 dns_name_free(name, view->mctx);
00463                                 isc_mem_put(view->mctx, name, sizeof(*name));
00464                                 name = ISC_LIST_HEAD(view->rootexclude[i]);
00465                         }
00466                 }
00467                 isc_mem_put(view->mctx, view->rootexclude,
00468                             sizeof(dns_namelist_t) * DNS_VIEW_DELONLYHASH);
00469                 view->rootexclude = NULL;
00470         }
00471         if (view->adbstats != NULL)
00472                 isc_stats_detach(&view->adbstats);
00473         if (view->resstats != NULL)
00474                 isc_stats_detach(&view->resstats);
00475         if (view->resquerystats != NULL)
00476                 dns_stats_detach(&view->resquerystats);
00477         if (view->secroots_priv != NULL)
00478                 dns_keytable_detach(&view->secroots_priv);
00479         if (view->ntatable_priv != NULL)
00480                 dns_ntatable_detach(&view->ntatable_priv);
00481         for (dns64 = ISC_LIST_HEAD(view->dns64);
00482              dns64 != NULL;
00483              dns64 = ISC_LIST_HEAD(view->dns64)) {
00484                 dns_dns64_unlink(&view->dns64, dns64);
00485                 dns_dns64_destroy(&dns64);
00486         }
00487         if (view->managed_keys != NULL)
00488                 dns_zone_detach(&view->managed_keys);
00489         if (view->redirect != NULL)
00490                 dns_zone_detach(&view->redirect);
00491         dns_view_setnewzones(view, ISC_FALSE, NULL, NULL);
00492         dns_fwdtable_destroy(&view->fwdtable);
00493         dns_aclenv_destroy(&view->aclenv);
00494         dns_badcache_destroy(&view->failcache);
00495         DESTROYLOCK(&view->lock);
00496         isc_refcount_destroy(&view->references);
00497         isc_mem_free(view->mctx, view->nta_file);
00498         isc_mem_free(view->mctx, view->name);
00499         isc_mem_putanddetach(&view->mctx, view, sizeof(*view));
00500 }
00501 
00502 /*
00503  * Return true iff 'view' may be freed.
00504  * The caller must be holding the view lock.
00505  */
00506 static isc_boolean_t
00507 all_done(dns_view_t *view) {
00508 
00509         if (isc_refcount_current(&view->references) == 0 &&
00510             view->weakrefs == 0 &&
00511             RESSHUTDOWN(view) && ADBSHUTDOWN(view) && REQSHUTDOWN(view))
00512                 return (ISC_TRUE);
00513 
00514         return (ISC_FALSE);
00515 }
00516 
00517 void
00518 dns_view_attach(dns_view_t *source, dns_view_t **targetp) {
00519 
00520         REQUIRE(DNS_VIEW_VALID(source));
00521         REQUIRE(targetp != NULL && *targetp == NULL);
00522 
00523         isc_refcount_increment(&source->references, NULL);
00524 
00525         *targetp = source;
00526 }
00527 
00528 static void
00529 view_flushanddetach(dns_view_t **viewp, isc_boolean_t flush) {
00530         dns_view_t *view;
00531         unsigned int refs;
00532         isc_boolean_t done = ISC_FALSE;
00533 
00534         REQUIRE(viewp != NULL);
00535         view = *viewp;
00536         REQUIRE(DNS_VIEW_VALID(view));
00537 
00538         if (flush)
00539                 view->flush = ISC_TRUE;
00540         isc_refcount_decrement(&view->references, &refs);
00541         if (refs == 0) {
00542                 dns_zone_t *mkzone = NULL, *rdzone = NULL;
00543 
00544                 LOCK(&view->lock);
00545                 if (!RESSHUTDOWN(view))
00546                         dns_resolver_shutdown(view->resolver);
00547                 if (!ADBSHUTDOWN(view))
00548                         dns_adb_shutdown(view->adb);
00549                 if (!REQSHUTDOWN(view))
00550                         dns_requestmgr_shutdown(view->requestmgr);
00551                 if (view->acache != NULL)
00552                         dns_acache_shutdown(view->acache);
00553                 if (view->zonetable != NULL) {
00554                         if (view->flush)
00555                                 dns_zt_flushanddetach(&view->zonetable);
00556                         else
00557                                 dns_zt_detach(&view->zonetable);
00558                 }
00559                 if (view->managed_keys != NULL) {
00560                         mkzone = view->managed_keys;
00561                         view->managed_keys = NULL;
00562                         if (view->flush)
00563                                 dns_zone_flush(mkzone);
00564                 }
00565                 if (view->redirect != NULL) {
00566                         rdzone = view->redirect;
00567                         view->redirect = NULL;
00568                         if (view->flush)
00569                                 dns_zone_flush(rdzone);
00570                 }
00571                 done = all_done(view);
00572                 UNLOCK(&view->lock);
00573 
00574                 /* Need to detach zones outside view lock */
00575                 if (mkzone != NULL)
00576                         dns_zone_detach(&mkzone);
00577 
00578                 if (rdzone != NULL)
00579                         dns_zone_detach(&rdzone);
00580         }
00581 
00582         *viewp = NULL;
00583 
00584         if (done)
00585                 destroy(view);
00586 }
00587 
00588 void
00589 dns_view_flushanddetach(dns_view_t **viewp) {
00590         view_flushanddetach(viewp, ISC_TRUE);
00591 }
00592 
00593 void
00594 dns_view_detach(dns_view_t **viewp) {
00595         view_flushanddetach(viewp, ISC_FALSE);
00596 }
00597 
00598 static isc_result_t
00599 dialup(dns_zone_t *zone, void *dummy) {
00600         UNUSED(dummy);
00601         dns_zone_dialup(zone);
00602         return (ISC_R_SUCCESS);
00603 }
00604 
00605 void
00606 dns_view_dialup(dns_view_t *view) {
00607         REQUIRE(DNS_VIEW_VALID(view));
00608         REQUIRE(view->zonetable != NULL);
00609 
00610         (void)dns_zt_apply(view->zonetable, ISC_FALSE, dialup, NULL);
00611 }
00612 
00613 void
00614 dns_view_weakattach(dns_view_t *source, dns_view_t **targetp) {
00615 
00616         REQUIRE(DNS_VIEW_VALID(source));
00617         REQUIRE(targetp != NULL && *targetp == NULL);
00618 
00619         LOCK(&source->lock);
00620         source->weakrefs++;
00621         UNLOCK(&source->lock);
00622 
00623         *targetp = source;
00624 }
00625 
00626 void
00627 dns_view_weakdetach(dns_view_t **viewp) {
00628         dns_view_t *view;
00629         isc_boolean_t done = ISC_FALSE;
00630 
00631         REQUIRE(viewp != NULL);
00632         view = *viewp;
00633         REQUIRE(DNS_VIEW_VALID(view));
00634 
00635         LOCK(&view->lock);
00636 
00637         INSIST(view->weakrefs > 0);
00638         view->weakrefs--;
00639         done = all_done(view);
00640 
00641         UNLOCK(&view->lock);
00642 
00643         *viewp = NULL;
00644 
00645         if (done)
00646                 destroy(view);
00647 }
00648 
00649 static void
00650 resolver_shutdown(isc_task_t *task, isc_event_t *event) {
00651         dns_view_t *view = event->ev_arg;
00652         isc_boolean_t done;
00653 
00654         REQUIRE(event->ev_type == DNS_EVENT_VIEWRESSHUTDOWN);
00655         REQUIRE(DNS_VIEW_VALID(view));
00656         REQUIRE(view->task == task);
00657 
00658         UNUSED(task);
00659 
00660         isc_event_free(&event);
00661 
00662         LOCK(&view->lock);
00663 
00664         view->attributes |= DNS_VIEWATTR_RESSHUTDOWN;
00665         done = all_done(view);
00666 
00667         UNLOCK(&view->lock);
00668 
00669         if (done)
00670                 destroy(view);
00671 }
00672 
00673 static void
00674 adb_shutdown(isc_task_t *task, isc_event_t *event) {
00675         dns_view_t *view = event->ev_arg;
00676         isc_boolean_t done;
00677 
00678         REQUIRE(event->ev_type == DNS_EVENT_VIEWADBSHUTDOWN);
00679         REQUIRE(DNS_VIEW_VALID(view));
00680         REQUIRE(view->task == task);
00681 
00682         UNUSED(task);
00683 
00684         isc_event_free(&event);
00685 
00686         LOCK(&view->lock);
00687 
00688         view->attributes |= DNS_VIEWATTR_ADBSHUTDOWN;
00689         done = all_done(view);
00690 
00691         UNLOCK(&view->lock);
00692 
00693         if (done)
00694                 destroy(view);
00695 }
00696 
00697 static void
00698 req_shutdown(isc_task_t *task, isc_event_t *event) {
00699         dns_view_t *view = event->ev_arg;
00700         isc_boolean_t done;
00701 
00702         REQUIRE(event->ev_type == DNS_EVENT_VIEWREQSHUTDOWN);
00703         REQUIRE(DNS_VIEW_VALID(view));
00704         REQUIRE(view->task == task);
00705 
00706         UNUSED(task);
00707 
00708         isc_event_free(&event);
00709 
00710         LOCK(&view->lock);
00711 
00712         view->attributes |= DNS_VIEWATTR_REQSHUTDOWN;
00713         done = all_done(view);
00714 
00715         UNLOCK(&view->lock);
00716 
00717         if (done)
00718                 destroy(view);
00719 }
00720 
00721 isc_result_t
00722 dns_view_createzonetable(dns_view_t *view) {
00723 
00724         REQUIRE(DNS_VIEW_VALID(view));
00725         REQUIRE(!view->frozen);
00726         REQUIRE(view->zonetable == NULL);
00727 
00728         return (dns_zt_create(view->mctx, view->rdclass, &view->zonetable));
00729 }
00730 
00731 isc_result_t
00732 dns_view_createresolver(dns_view_t *view,
00733                         isc_taskmgr_t *taskmgr,
00734                         unsigned int ntasks, unsigned int ndisp,
00735                         isc_socketmgr_t *socketmgr,
00736                         isc_timermgr_t *timermgr,
00737                         unsigned int options,
00738                         dns_dispatchmgr_t *dispatchmgr,
00739                         dns_dispatch_t *dispatchv4,
00740                         dns_dispatch_t *dispatchv6)
00741 {
00742         isc_result_t result;
00743         isc_event_t *event;
00744         isc_mem_t *mctx = NULL;
00745 
00746         REQUIRE(DNS_VIEW_VALID(view));
00747         REQUIRE(!view->frozen);
00748         REQUIRE(view->resolver == NULL);
00749 
00750         result = isc_task_create(taskmgr, 0, &view->task);
00751         if (result != ISC_R_SUCCESS)
00752                 return (result);
00753         isc_task_setname(view->task, "view", view);
00754 
00755         result = dns_resolver_create(view, taskmgr, ntasks, ndisp, socketmgr,
00756                                      timermgr, options, dispatchmgr,
00757                                      dispatchv4, dispatchv6,
00758                                      &view->resolver);
00759         if (result != ISC_R_SUCCESS) {
00760                 isc_task_detach(&view->task);
00761                 return (result);
00762         }
00763         event = &view->resevent;
00764         dns_resolver_whenshutdown(view->resolver, view->task, &event);
00765         view->attributes &= ~DNS_VIEWATTR_RESSHUTDOWN;
00766 
00767         result = isc_mem_create(0, 0, &mctx);
00768         if (result != ISC_R_SUCCESS) {
00769                 dns_resolver_shutdown(view->resolver);
00770                 return (result);
00771         }
00772 
00773         result = dns_adb_create(mctx, view, timermgr, taskmgr, &view->adb);
00774         isc_mem_setname(mctx, "ADB", NULL);
00775         isc_mem_detach(&mctx);
00776         if (result != ISC_R_SUCCESS) {
00777                 dns_resolver_shutdown(view->resolver);
00778                 return (result);
00779         }
00780         event = &view->adbevent;
00781         dns_adb_whenshutdown(view->adb, view->task, &event);
00782         view->attributes &= ~DNS_VIEWATTR_ADBSHUTDOWN;
00783 
00784         result = dns_requestmgr_create(view->mctx, timermgr, socketmgr,
00785                                       dns_resolver_taskmgr(view->resolver),
00786                                       dns_resolver_dispatchmgr(view->resolver),
00787                                       dispatchv4, dispatchv6,
00788                                       &view->requestmgr);
00789         if (result != ISC_R_SUCCESS) {
00790                 dns_adb_shutdown(view->adb);
00791                 dns_resolver_shutdown(view->resolver);
00792                 return (result);
00793         }
00794         event = &view->reqevent;
00795         dns_requestmgr_whenshutdown(view->requestmgr, view->task, &event);
00796         view->attributes &= ~DNS_VIEWATTR_REQSHUTDOWN;
00797 
00798         return (ISC_R_SUCCESS);
00799 }
00800 
00801 void
00802 dns_view_setcache(dns_view_t *view, dns_cache_t *cache) {
00803         dns_view_setcache2(view, cache, ISC_FALSE);
00804 }
00805 
00806 void
00807 dns_view_setcache2(dns_view_t *view, dns_cache_t *cache, isc_boolean_t shared) {
00808         REQUIRE(DNS_VIEW_VALID(view));
00809         REQUIRE(!view->frozen);
00810 
00811         view->cacheshared = shared;
00812         if (view->cache != NULL) {
00813                 if (view->acache != NULL)
00814                         dns_acache_putdb(view->acache, view->cachedb);
00815                 dns_db_detach(&view->cachedb);
00816                 dns_cache_detach(&view->cache);
00817         }
00818         dns_cache_attach(cache, &view->cache);
00819         dns_cache_attachdb(cache, &view->cachedb);
00820         INSIST(DNS_DB_VALID(view->cachedb));
00821 
00822         if (view->acache != NULL)
00823                 dns_acache_setdb(view->acache, view->cachedb);
00824 }
00825 
00826 isc_boolean_t
00827 dns_view_iscacheshared(dns_view_t *view) {
00828         REQUIRE(DNS_VIEW_VALID(view));
00829 
00830         return (view->cacheshared);
00831 }
00832 
00833 void
00834 dns_view_sethints(dns_view_t *view, dns_db_t *hints) {
00835         REQUIRE(DNS_VIEW_VALID(view));
00836         REQUIRE(!view->frozen);
00837         REQUIRE(view->hints == NULL);
00838         REQUIRE(dns_db_iszone(hints));
00839 
00840         dns_db_attach(hints, &view->hints);
00841 }
00842 
00843 void
00844 dns_view_setkeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
00845         REQUIRE(DNS_VIEW_VALID(view));
00846         REQUIRE(ring != NULL);
00847         if (view->statickeys != NULL)
00848                 dns_tsigkeyring_detach(&view->statickeys);
00849         dns_tsigkeyring_attach(ring, &view->statickeys);
00850 }
00851 
00852 void
00853 dns_view_setdynamickeyring(dns_view_t *view, dns_tsig_keyring_t *ring) {
00854         REQUIRE(DNS_VIEW_VALID(view));
00855         REQUIRE(ring != NULL);
00856         if (view->dynamickeys != NULL)
00857                 dns_tsigkeyring_detach(&view->dynamickeys);
00858         dns_tsigkeyring_attach(ring, &view->dynamickeys);
00859 }
00860 
00861 void
00862 dns_view_getdynamickeyring(dns_view_t *view, dns_tsig_keyring_t **ringp) {
00863         REQUIRE(DNS_VIEW_VALID(view));
00864         REQUIRE(ringp != NULL && *ringp == NULL);
00865         if (view->dynamickeys != NULL)
00866                 dns_tsigkeyring_attach(view->dynamickeys, ringp);
00867 }
00868 
00869 void
00870 dns_view_restorekeyring(dns_view_t *view) {
00871         FILE *fp;
00872         char keyfile[20];
00873         int n;
00874 
00875         REQUIRE(DNS_VIEW_VALID(view));
00876 
00877         if (view->dynamickeys != NULL) {
00878                 n = snprintf(keyfile, sizeof(keyfile), "%s.tsigkeys",
00879                              view->name);
00880                 if (n > 0 && (size_t)n < sizeof(keyfile)) {
00881                         fp = fopen(keyfile, "r");
00882                         if (fp != NULL) {
00883                                 dns_keyring_restore(view->dynamickeys, fp);
00884                                 (void)fclose(fp);
00885                         }
00886                 }
00887         }
00888 }
00889 
00890 void
00891 dns_view_setdstport(dns_view_t *view, in_port_t dstport) {
00892         REQUIRE(DNS_VIEW_VALID(view));
00893         view->dstport = dstport;
00894 }
00895 
00896 void
00897 dns_view_freeze(dns_view_t *view) {
00898         REQUIRE(DNS_VIEW_VALID(view));
00899         REQUIRE(!view->frozen);
00900 
00901         if (view->resolver != NULL) {
00902                 INSIST(view->cachedb != NULL);
00903                 dns_resolver_freeze(view->resolver);
00904         }
00905         view->frozen = ISC_TRUE;
00906 }
00907 
00908 void
00909 dns_view_thaw(dns_view_t *view) {
00910         REQUIRE(DNS_VIEW_VALID(view));
00911         REQUIRE(view->frozen);
00912 
00913         view->frozen = ISC_FALSE;
00914 }
00915 
00916 isc_result_t
00917 dns_view_addzone(dns_view_t *view, dns_zone_t *zone) {
00918         isc_result_t result;
00919 
00920         REQUIRE(DNS_VIEW_VALID(view));
00921         REQUIRE(!view->frozen);
00922         REQUIRE(view->zonetable != NULL);
00923 
00924         result = dns_zt_mount(view->zonetable, zone);
00925 
00926         return (result);
00927 }
00928 
00929 isc_result_t
00930 dns_view_findzone(dns_view_t *view, dns_name_t *name, dns_zone_t **zonep) {
00931         isc_result_t result;
00932 
00933         REQUIRE(DNS_VIEW_VALID(view));
00934 
00935         LOCK(&view->lock);
00936         if (view->zonetable != NULL) {
00937                 result = dns_zt_find(view->zonetable, name, 0, NULL, zonep);
00938                 if (result == DNS_R_PARTIALMATCH) {
00939                         dns_zone_detach(zonep);
00940                         result = ISC_R_NOTFOUND;
00941                 }
00942         } else
00943                 result = ISC_R_NOTFOUND;
00944         UNLOCK(&view->lock);
00945 
00946         return (result);
00947 }
00948 
00949 isc_result_t
00950 dns_view_find(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
00951               isc_stdtime_t now, unsigned int options, isc_boolean_t use_hints,
00952               dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
00953               dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset) {
00954         return (dns_view_find2(view, name, type, now, options, use_hints,
00955                                ISC_FALSE, dbp, nodep, foundname, rdataset,
00956                                sigrdataset));
00957 }
00958 
00959 isc_result_t
00960 dns_view_find2(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
00961                isc_stdtime_t now, unsigned int options,
00962                isc_boolean_t use_hints, isc_boolean_t use_static_stub,
00963                dns_db_t **dbp, dns_dbnode_t **nodep, dns_name_t *foundname,
00964                dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
00965 {
00966         isc_result_t result;
00967         dns_db_t *db, *zdb;
00968         dns_dbnode_t *node, *znode;
00969         isc_boolean_t is_cache, is_staticstub_zone;
00970         dns_rdataset_t zrdataset, zsigrdataset;
00971         dns_zone_t *zone;
00972 
00973         /*
00974          * Find an rdataset whose owner name is 'name', and whose type is
00975          * 'type'.
00976          */
00977 
00978         REQUIRE(DNS_VIEW_VALID(view));
00979         REQUIRE(view->frozen);
00980         REQUIRE(type != dns_rdatatype_rrsig);
00981         REQUIRE(rdataset != NULL);  /* XXXBEW - remove this */
00982         REQUIRE(nodep == NULL || *nodep == NULL);
00983 
00984         /*
00985          * Initialize.
00986          */
00987         dns_rdataset_init(&zrdataset);
00988         dns_rdataset_init(&zsigrdataset);
00989         zdb = NULL;
00990         znode = NULL;
00991 
00992         /*
00993          * Find a database to answer the query.
00994          */
00995         db = NULL;
00996         node = NULL;
00997         is_staticstub_zone = ISC_FALSE;
00998         zone = NULL;
00999         LOCK(&view->lock);
01000         if (view->zonetable != NULL)
01001                 result = dns_zt_find(view->zonetable, name, 0, NULL, &zone);
01002         else
01003                 result = ISC_R_NOTFOUND;
01004         UNLOCK(&view->lock);
01005         if (zone != NULL && dns_zone_gettype(zone) == dns_zone_staticstub &&
01006             !use_static_stub)
01007                 result = ISC_R_NOTFOUND;
01008         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH) {
01009                 result = dns_zone_getdb(zone, &db);
01010                 if (result != ISC_R_SUCCESS && view->cachedb != NULL)
01011                         dns_db_attach(view->cachedb, &db);
01012                 else if (result != ISC_R_SUCCESS)
01013                         goto cleanup;
01014                 if (dns_zone_gettype(zone) == dns_zone_staticstub &&
01015                     dns_name_equal(name, dns_zone_getorigin(zone))) {
01016                         is_staticstub_zone = ISC_TRUE;
01017                 }
01018         } else if (result == ISC_R_NOTFOUND && view->cachedb != NULL)
01019                 dns_db_attach(view->cachedb, &db);
01020         else
01021                 goto cleanup;
01022 
01023         is_cache = dns_db_iscache(db);
01024 
01025  db_find:
01026         /*
01027          * Now look for an answer in the database.
01028          */
01029         result = dns_db_find(db, name, NULL, type, options,
01030                              now, &node, foundname, rdataset, sigrdataset);
01031 
01032         if (result == DNS_R_DELEGATION || result == ISC_R_NOTFOUND) {
01033                 if (dns_rdataset_isassociated(rdataset))
01034                         dns_rdataset_disassociate(rdataset);
01035                 if (sigrdataset != NULL &&
01036                     dns_rdataset_isassociated(sigrdataset))
01037                         dns_rdataset_disassociate(sigrdataset);
01038                 if (node != NULL)
01039                         dns_db_detachnode(db, &node);
01040                 if (!is_cache) {
01041                         dns_db_detach(&db);
01042                         if (view->cachedb != NULL && !is_staticstub_zone) {
01043                                 /*
01044                                  * Either the answer is in the cache, or we
01045                                  * don't know it.
01046                                  * Note that if the result comes from a
01047                                  * static-stub zone we stop the search here
01048                                  * (see the function description in view.h).
01049                                  */
01050                                 is_cache = ISC_TRUE;
01051                                 dns_db_attach(view->cachedb, &db);
01052                                 goto db_find;
01053                         }
01054                 } else {
01055                         /*
01056                          * We don't have the data in the cache.  If we've got
01057                          * glue from the zone, use it.
01058                          */
01059                         if (dns_rdataset_isassociated(&zrdataset)) {
01060                                 dns_rdataset_clone(&zrdataset, rdataset);
01061                                 if (sigrdataset != NULL &&
01062                                     dns_rdataset_isassociated(&zsigrdataset))
01063                                         dns_rdataset_clone(&zsigrdataset,
01064                                                            sigrdataset);
01065                                 result = DNS_R_GLUE;
01066                                 if (db != NULL)
01067                                         dns_db_detach(&db);
01068                                 dns_db_attach(zdb, &db);
01069                                 dns_db_attachnode(db, znode, &node);
01070                                 goto cleanup;
01071                         }
01072                 }
01073                 /*
01074                  * We don't know the answer.
01075                  */
01076                 result = ISC_R_NOTFOUND;
01077         } else if (result == DNS_R_GLUE) {
01078                 if (view->cachedb != NULL && !is_staticstub_zone) {
01079                         /*
01080                          * We found an answer, but the cache may be better.
01081                          * Remember what we've got and go look in the cache.
01082                          */
01083                         is_cache = ISC_TRUE;
01084                         dns_rdataset_clone(rdataset, &zrdataset);
01085                         dns_rdataset_disassociate(rdataset);
01086                         if (sigrdataset != NULL &&
01087                             dns_rdataset_isassociated(sigrdataset)) {
01088                                 dns_rdataset_clone(sigrdataset, &zsigrdataset);
01089                                 dns_rdataset_disassociate(sigrdataset);
01090                         }
01091                         dns_db_attach(db, &zdb);
01092                         dns_db_attachnode(zdb, node, &znode);
01093                         dns_db_detachnode(db, &node);
01094                         dns_db_detach(&db);
01095                         dns_db_attach(view->cachedb, &db);
01096                         goto db_find;
01097                 }
01098                 /*
01099                  * Otherwise, the glue is the best answer.
01100                  */
01101                 result = ISC_R_SUCCESS;
01102         }
01103 
01104         if (result == ISC_R_NOTFOUND && use_hints && view->hints != NULL) {
01105                 if (dns_rdataset_isassociated(rdataset))
01106                         dns_rdataset_disassociate(rdataset);
01107                 if (sigrdataset != NULL &&
01108                     dns_rdataset_isassociated(sigrdataset))
01109                         dns_rdataset_disassociate(sigrdataset);
01110                 if (db != NULL) {
01111                         if (node != NULL)
01112                                 dns_db_detachnode(db, &node);
01113                         dns_db_detach(&db);
01114                 }
01115                 result = dns_db_find(view->hints, name, NULL, type, options,
01116                                      now, &node, foundname,
01117                                      rdataset, sigrdataset);
01118                 if (result == ISC_R_SUCCESS || result == DNS_R_GLUE) {
01119                         /*
01120                          * We just used a hint.  Let the resolver know it
01121                          * should consider priming.
01122                          */
01123                         dns_resolver_prime(view->resolver);
01124                         dns_db_attach(view->hints, &db);
01125                         result = DNS_R_HINT;
01126                 } else if (result == DNS_R_NXRRSET) {
01127                         dns_db_attach(view->hints, &db);
01128                         result = DNS_R_HINTNXRRSET;
01129                 } else if (result == DNS_R_NXDOMAIN)
01130                         result = ISC_R_NOTFOUND;
01131 
01132                 /*
01133                  * Cleanup if non-standard hints are used.
01134                  */
01135                 if (db == NULL && node != NULL)
01136                         dns_db_detachnode(view->hints, &node);
01137         }
01138 
01139  cleanup:
01140         if (dns_rdataset_isassociated(&zrdataset)) {
01141                 dns_rdataset_disassociate(&zrdataset);
01142                 if (dns_rdataset_isassociated(&zsigrdataset))
01143                         dns_rdataset_disassociate(&zsigrdataset);
01144         }
01145 
01146         if (zdb != NULL) {
01147                 if (znode != NULL)
01148                         dns_db_detachnode(zdb, &znode);
01149                 dns_db_detach(&zdb);
01150         }
01151 
01152         if (db != NULL) {
01153                 if (node != NULL) {
01154                         if (nodep != NULL)
01155                                 *nodep = node;
01156                         else
01157                                 dns_db_detachnode(db, &node);
01158                 }
01159                 if (dbp != NULL)
01160                         *dbp = db;
01161                 else
01162                         dns_db_detach(&db);
01163         } else
01164                 INSIST(node == NULL);
01165 
01166         if (zone != NULL)
01167                 dns_zone_detach(&zone);
01168 
01169         return (result);
01170 }
01171 
01172 isc_result_t
01173 dns_view_simplefind(dns_view_t *view, dns_name_t *name, dns_rdatatype_t type,
01174                     isc_stdtime_t now, unsigned int options,
01175                     isc_boolean_t use_hints,
01176                     dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
01177 {
01178         isc_result_t result;
01179         dns_fixedname_t foundname;
01180 
01181         dns_fixedname_init(&foundname);
01182         result = dns_view_find(view, name, type, now, options, use_hints,
01183                                NULL, NULL, dns_fixedname_name(&foundname),
01184                                rdataset, sigrdataset);
01185         if (result == DNS_R_NXDOMAIN) {
01186                 /*
01187                  * The rdataset and sigrdataset of the relevant NSEC record
01188                  * may be returned, but the caller cannot use them because
01189                  * foundname is not returned by this simplified API.  We
01190                  * disassociate them here to prevent any misuse by the caller.
01191                  */
01192                 if (dns_rdataset_isassociated(rdataset))
01193                         dns_rdataset_disassociate(rdataset);
01194                 if (sigrdataset != NULL &&
01195                     dns_rdataset_isassociated(sigrdataset))
01196                         dns_rdataset_disassociate(sigrdataset);
01197         } else if (result != ISC_R_SUCCESS &&
01198                    result != DNS_R_GLUE &&
01199                    result != DNS_R_HINT &&
01200                    result != DNS_R_NCACHENXDOMAIN &&
01201                    result != DNS_R_NCACHENXRRSET &&
01202                    result != DNS_R_NXRRSET &&
01203                    result != DNS_R_HINTNXRRSET &&
01204                    result != ISC_R_NOTFOUND) {
01205                 if (dns_rdataset_isassociated(rdataset))
01206                         dns_rdataset_disassociate(rdataset);
01207                 if (sigrdataset != NULL &&
01208                     dns_rdataset_isassociated(sigrdataset))
01209                         dns_rdataset_disassociate(sigrdataset);
01210                 result = ISC_R_NOTFOUND;
01211         }
01212 
01213         return (result);
01214 }
01215 
01216 isc_result_t
01217 dns_view_findzonecut(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
01218                      isc_stdtime_t now, unsigned int options,
01219                      isc_boolean_t use_hints,
01220                      dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
01221 {
01222         return(dns_view_findzonecut2(view, name, fname, now, options,
01223                                      use_hints, ISC_TRUE,
01224                                      rdataset, sigrdataset));
01225 }
01226 
01227 isc_result_t
01228 dns_view_findzonecut2(dns_view_t *view, dns_name_t *name, dns_name_t *fname,
01229                       isc_stdtime_t now, unsigned int options,
01230                       isc_boolean_t use_hints,  isc_boolean_t use_cache,
01231                       dns_rdataset_t *rdataset, dns_rdataset_t *sigrdataset)
01232 {
01233         isc_result_t result;
01234         dns_db_t *db;
01235         isc_boolean_t is_cache, use_zone, try_hints;
01236         dns_zone_t *zone;
01237         dns_name_t *zfname;
01238         dns_rdataset_t zrdataset, zsigrdataset;
01239         dns_fixedname_t zfixedname;
01240         unsigned int ztoptions = 0;
01241 
01242         REQUIRE(DNS_VIEW_VALID(view));
01243         REQUIRE(view->frozen);
01244 
01245         db = NULL;
01246         use_zone = ISC_FALSE;
01247         try_hints = ISC_FALSE;
01248         zfname = NULL;
01249 
01250         /*
01251          * Initialize.
01252          */
01253         dns_fixedname_init(&zfixedname);
01254         dns_rdataset_init(&zrdataset);
01255         dns_rdataset_init(&zsigrdataset);
01256 
01257         /*
01258          * Find the right database.
01259          */
01260         zone = NULL;
01261         LOCK(&view->lock);
01262         if (view->zonetable != NULL) {
01263                 if ((options & DNS_DBFIND_NOEXACT) != 0)
01264                         ztoptions |= DNS_ZTFIND_NOEXACT;
01265                 result = dns_zt_find(view->zonetable, name, ztoptions,
01266                                      NULL, &zone);
01267         } else
01268                 result = ISC_R_NOTFOUND;
01269         UNLOCK(&view->lock);
01270         if (result == ISC_R_SUCCESS || result == DNS_R_PARTIALMATCH)
01271                 result = dns_zone_getdb(zone, &db);
01272         if (result == ISC_R_NOTFOUND) {
01273                 /*
01274                  * We're not directly authoritative for this query name, nor
01275                  * is it a subdomain of any zone for which we're
01276                  * authoritative.
01277                  */
01278                 if (use_cache && view->cachedb != NULL) {
01279                         /*
01280                          * We have a cache; try it.
01281                          */
01282                         dns_db_attach(view->cachedb, &db);
01283                 } else {
01284                         /*
01285                          * Maybe we have hints...
01286                          */
01287                         try_hints = ISC_TRUE;
01288                         goto finish;
01289                 }
01290         } else if (result != ISC_R_SUCCESS) {
01291                 /*
01292                  * Something is broken.
01293                  */
01294                 goto cleanup;
01295         }
01296         is_cache = dns_db_iscache(db);
01297 
01298  db_find:
01299         /*
01300          * Look for the zonecut.
01301          */
01302         if (!is_cache) {
01303                 result = dns_db_find(db, name, NULL, dns_rdatatype_ns, options,
01304                                      now, NULL, fname, rdataset, sigrdataset);
01305                 if (result == DNS_R_DELEGATION)
01306                         result = ISC_R_SUCCESS;
01307                 else if (result != ISC_R_SUCCESS)
01308                         goto cleanup;
01309                 if (use_cache && view->cachedb != NULL && db != view->hints) {
01310                         /*
01311                          * We found an answer, but the cache may be better.
01312                          */
01313                         zfname = dns_fixedname_name(&zfixedname);
01314                         result = dns_name_copy(fname, zfname, NULL);
01315                         if (result != ISC_R_SUCCESS)
01316                                 goto cleanup;
01317                         dns_rdataset_clone(rdataset, &zrdataset);
01318                         dns_rdataset_disassociate(rdataset);
01319                         if (sigrdataset != NULL &&
01320                             dns_rdataset_isassociated(sigrdataset)) {
01321                                 dns_rdataset_clone(sigrdataset, &zsigrdataset);
01322                                 dns_rdataset_disassociate(sigrdataset);
01323                         }
01324                         dns_db_detach(&db);
01325                         dns_db_attach(view->cachedb, &db);
01326                         is_cache = ISC_TRUE;
01327                         goto db_find;
01328                 }
01329         } else {
01330                 result = dns_db_findzonecut(db, name, options, now, NULL,
01331                                             fname, rdataset, sigrdataset);
01332                 if (result == ISC_R_SUCCESS) {
01333                         if (zfname != NULL &&
01334                             (!dns_name_issubdomain(fname, zfname) ||
01335                              (dns_zone_staticstub &&
01336                               dns_name_equal(fname, zfname)))) {
01337                                 /*
01338                                  * We found a zonecut in the cache, but our
01339                                  * zone delegation is better.
01340                                  */
01341                                 use_zone = ISC_TRUE;
01342                         }
01343                 } else if (result == ISC_R_NOTFOUND) {
01344                         if (zfname != NULL) {
01345                                 /*
01346                                  * We didn't find anything in the cache, but we
01347                                  * have a zone delegation, so use it.
01348                                  */
01349                                 use_zone = ISC_TRUE;
01350                         } else {
01351                                 /*
01352                                  * Maybe we have hints...
01353                                  */
01354                                 try_hints = ISC_TRUE;
01355                         }
01356                 } else {
01357                         /*
01358                          * Something bad happened.
01359                          */
01360                         goto cleanup;
01361                 }
01362         }
01363 
01364  finish:
01365         if (use_zone) {
01366                 if (dns_rdataset_isassociated(rdataset)) {
01367                         dns_rdataset_disassociate(rdataset);
01368                         if (sigrdataset != NULL &&
01369                             dns_rdataset_isassociated(sigrdataset))
01370                                 dns_rdataset_disassociate(sigrdataset);
01371                 }
01372                 result = dns_name_copy(zfname, fname, NULL);
01373                 if (result != ISC_R_SUCCESS)
01374                         goto cleanup;
01375                 dns_rdataset_clone(&zrdataset, rdataset);
01376                 if (sigrdataset != NULL &&
01377                     dns_rdataset_isassociated(&zrdataset))
01378                         dns_rdataset_clone(&zsigrdataset, sigrdataset);
01379         } else if (try_hints && use_hints && view->hints != NULL) {
01380                 /*
01381                  * We've found nothing so far, but we have hints.
01382                  */
01383                 result = dns_db_find(view->hints, dns_rootname, NULL,
01384                                      dns_rdatatype_ns, 0, now, NULL, fname,
01385                                      rdataset, NULL);
01386                 if (result != ISC_R_SUCCESS) {
01387                         /*
01388                          * We can't even find the hints for the root
01389                          * nameservers!
01390                          */
01391                         if (dns_rdataset_isassociated(rdataset))
01392                                 dns_rdataset_disassociate(rdataset);
01393                         result = ISC_R_NOTFOUND;
01394                 }
01395         }
01396 
01397  cleanup:
01398         if (dns_rdataset_isassociated(&zrdataset)) {
01399                 dns_rdataset_disassociate(&zrdataset);
01400                 if (dns_rdataset_isassociated(&zsigrdataset))
01401                         dns_rdataset_disassociate(&zsigrdataset);
01402         }
01403         if (db != NULL)
01404                 dns_db_detach(&db);
01405         if (zone != NULL)
01406                 dns_zone_detach(&zone);
01407 
01408         return (result);
01409 }
01410 
01411 isc_result_t
01412 dns_viewlist_find(dns_viewlist_t *list, const char *name,
01413                   dns_rdataclass_t rdclass, dns_view_t **viewp)
01414 {
01415         dns_view_t *view;
01416 
01417         REQUIRE(list != NULL);
01418 
01419         for (view = ISC_LIST_HEAD(*list);
01420              view != NULL;
01421              view = ISC_LIST_NEXT(view, link)) {
01422                 if (strcmp(view->name, name) == 0 && view->rdclass == rdclass)
01423                         break;
01424         }
01425         if (view == NULL)
01426                 return (ISC_R_NOTFOUND);
01427 
01428         dns_view_attach(view, viewp);
01429 
01430         return (ISC_R_SUCCESS);
01431 }
01432 
01433 isc_result_t
01434 dns_viewlist_findzone(dns_viewlist_t *list, dns_name_t *name,
01435                       isc_boolean_t allclasses, dns_rdataclass_t rdclass,
01436                       dns_zone_t **zonep)
01437 {
01438         dns_view_t *view;
01439         isc_result_t result;
01440         dns_zone_t *zone1 = NULL, *zone2 = NULL;
01441         dns_zone_t **zp = NULL;;
01442 
01443         REQUIRE(list != NULL);
01444         REQUIRE(zonep != NULL && *zonep == NULL);
01445 
01446         for (view = ISC_LIST_HEAD(*list);
01447              view != NULL;
01448              view = ISC_LIST_NEXT(view, link)) {
01449                 if (allclasses == ISC_FALSE && view->rdclass != rdclass)
01450                         continue;
01451 
01452                 /*
01453                  * If the zone is defined in more than one view,
01454                  * treat it as not found.
01455                  */
01456                 zp = (zone1 == NULL) ? &zone1 : &zone2;
01457                 LOCK(&view->lock);
01458                 if (view->zonetable != NULL)
01459                         result = dns_zt_find(view->zonetable, name, 0,
01460                                              NULL, zp);
01461                 else
01462                         result = ISC_R_NOTFOUND;
01463                 UNLOCK(&view->lock);
01464                 INSIST(result == ISC_R_SUCCESS ||
01465                        result == ISC_R_NOTFOUND ||
01466                        result == DNS_R_PARTIALMATCH);
01467 
01468                 /* Treat a partial match as no match */
01469                 if (result == DNS_R_PARTIALMATCH) {
01470                         dns_zone_detach(zp);
01471                         result = ISC_R_NOTFOUND;
01472                         POST(result);
01473                 }
01474 
01475                 if (zone2 != NULL) {
01476                         dns_zone_detach(&zone1);
01477                         dns_zone_detach(&zone2);
01478                         return (ISC_R_MULTIPLE);
01479                 }
01480         }
01481 
01482         if (zone1 != NULL) {
01483                 dns_zone_attach(zone1, zonep);
01484                 dns_zone_detach(&zone1);
01485                 return (ISC_R_SUCCESS);
01486         }
01487 
01488         return (ISC_R_NOTFOUND);
01489 }
01490 
01491 isc_result_t
01492 dns_view_load(dns_view_t *view, isc_boolean_t stop) {
01493 
01494         REQUIRE(DNS_VIEW_VALID(view));
01495         REQUIRE(view->zonetable != NULL);
01496 
01497         return (dns_zt_load(view->zonetable, stop));
01498 }
01499 
01500 isc_result_t
01501 dns_view_loadnew(dns_view_t *view, isc_boolean_t stop) {
01502 
01503         REQUIRE(DNS_VIEW_VALID(view));
01504         REQUIRE(view->zonetable != NULL);
01505 
01506         return (dns_zt_loadnew(view->zonetable, stop));
01507 }
01508 
01509 isc_result_t
01510 dns_view_asyncload(dns_view_t *view, dns_zt_allloaded_t callback, void *arg) {
01511         REQUIRE(DNS_VIEW_VALID(view));
01512         REQUIRE(view->zonetable != NULL);
01513 
01514         return (dns_zt_asyncload(view->zonetable, callback, arg));
01515 }
01516 
01517 isc_result_t
01518 dns_view_gettsig(dns_view_t *view, dns_name_t *keyname, dns_tsigkey_t **keyp)
01519 {
01520         isc_result_t result;
01521         REQUIRE(keyp != NULL && *keyp == NULL);
01522 
01523         result = dns_tsigkey_find(keyp, keyname, NULL,
01524                                   view->statickeys);
01525         if (result == ISC_R_NOTFOUND)
01526                 result = dns_tsigkey_find(keyp, keyname, NULL,
01527                                           view->dynamickeys);
01528         return (result);
01529 }
01530 
01531 isc_result_t
01532 dns_view_getpeertsig(dns_view_t *view, isc_netaddr_t *peeraddr,
01533                      dns_tsigkey_t **keyp)
01534 {
01535         isc_result_t result;
01536         dns_name_t *keyname = NULL;
01537         dns_peer_t *peer = NULL;
01538 
01539         result = dns_peerlist_peerbyaddr(view->peers, peeraddr, &peer);
01540         if (result != ISC_R_SUCCESS)
01541                 return (result);
01542 
01543         result = dns_peer_getkey(peer, &keyname);
01544         if (result != ISC_R_SUCCESS)
01545                 return (result);
01546 
01547         result = dns_view_gettsig(view, keyname, keyp);
01548         return ((result == ISC_R_NOTFOUND) ? ISC_R_FAILURE : result);
01549 }
01550 
01551 isc_result_t
01552 dns_view_checksig(dns_view_t *view, isc_buffer_t *source, dns_message_t *msg) {
01553         REQUIRE(DNS_VIEW_VALID(view));
01554         REQUIRE(source != NULL);
01555 
01556         return (dns_tsig_verify(source, msg, view->statickeys,
01557                                 view->dynamickeys));
01558 }
01559 
01560 isc_result_t
01561 dns_view_dumpdbtostream(dns_view_t *view, FILE *fp) {
01562         isc_result_t result;
01563 
01564         REQUIRE(DNS_VIEW_VALID(view));
01565 
01566         (void)fprintf(fp, ";\n; Cache dump of view '%s'\n;\n", view->name);
01567         result = dns_master_dumptostream(view->mctx, view->cachedb, NULL,
01568                                          &dns_master_style_cache, fp);
01569         if (result != ISC_R_SUCCESS)
01570                 return (result);
01571         dns_adb_dump(view->adb, fp);
01572         dns_resolver_printbadcache(view->resolver, fp);
01573         dns_badcache_print(view->failcache, "SERVFAIL cache", fp);
01574         return (ISC_R_SUCCESS);
01575 }
01576 
01577 isc_result_t
01578 dns_view_flushcache(dns_view_t *view) {
01579         return (dns_view_flushcache2(view, ISC_FALSE));
01580 }
01581 
01582 isc_result_t
01583 dns_view_flushcache2(dns_view_t *view, isc_boolean_t fixuponly) {
01584         isc_result_t result;
01585 
01586         REQUIRE(DNS_VIEW_VALID(view));
01587 
01588         if (view->cachedb == NULL)
01589                 return (ISC_R_SUCCESS);
01590         if (!fixuponly) {
01591                 result = dns_cache_flush(view->cache);
01592                 if (result != ISC_R_SUCCESS)
01593                         return (result);
01594         }
01595         if (view->acache != NULL)
01596                 dns_acache_putdb(view->acache, view->cachedb);
01597         dns_db_detach(&view->cachedb);
01598         dns_cache_attachdb(view->cache, &view->cachedb);
01599         if (view->acache != NULL)
01600                 dns_acache_setdb(view->acache, view->cachedb);
01601         if (view->resolver != NULL)
01602                 dns_resolver_flushbadcache(view->resolver, NULL);
01603         if (view->failcache != NULL)
01604                 dns_badcache_flush(view->failcache);
01605 
01606         dns_adb_flush(view->adb);
01607         return (ISC_R_SUCCESS);
01608 }
01609 
01610 isc_result_t
01611 dns_view_flushname(dns_view_t *view, dns_name_t *name) {
01612         return (dns_view_flushnode(view, name, ISC_FALSE));
01613 }
01614 
01615 isc_result_t
01616 dns_view_flushnode(dns_view_t *view, dns_name_t *name, isc_boolean_t tree) {
01617         isc_result_t result = ISC_R_SUCCESS;
01618 
01619         REQUIRE(DNS_VIEW_VALID(view));
01620 
01621         if (tree) {
01622                 if (view->adb != NULL)
01623                         dns_adb_flushnames(view->adb, name);
01624                 if (view->resolver != NULL)
01625                         dns_resolver_flushbadnames(view->resolver, name);
01626                 if (view->failcache != NULL)
01627                         dns_badcache_flushtree(view->failcache, name);
01628         } else {
01629                 if (view->adb != NULL)
01630                         dns_adb_flushname(view->adb, name);
01631                 if (view->resolver != NULL)
01632                         dns_resolver_flushbadcache(view->resolver, name);
01633                 if (view->failcache != NULL)
01634                         dns_badcache_flushname(view->failcache, name);
01635         }
01636 
01637         if (view->cache != NULL)
01638                 result = dns_cache_flushnode(view->cache, name, tree);
01639 
01640         return (result);
01641 }
01642 
01643 isc_result_t
01644 dns_view_adddelegationonly(dns_view_t *view, dns_name_t *name) {
01645         isc_result_t result;
01646         dns_name_t *new;
01647         isc_uint32_t hash;
01648 
01649         REQUIRE(DNS_VIEW_VALID(view));
01650 
01651         if (view->delonly == NULL) {
01652                 view->delonly = isc_mem_get(view->mctx,
01653                                             sizeof(dns_namelist_t) *
01654                                             DNS_VIEW_DELONLYHASH);
01655                 if (view->delonly == NULL)
01656                         return (ISC_R_NOMEMORY);
01657                 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
01658                         ISC_LIST_INIT(view->delonly[hash]);
01659         }
01660         hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
01661         new = ISC_LIST_HEAD(view->delonly[hash]);
01662         while (new != NULL && !dns_name_equal(new, name))
01663                 new = ISC_LIST_NEXT(new, link);
01664         if (new != NULL)
01665                 return (ISC_R_SUCCESS);
01666         new = isc_mem_get(view->mctx, sizeof(*new));
01667         if (new == NULL)
01668                 return (ISC_R_NOMEMORY);
01669         dns_name_init(new, NULL);
01670         result = dns_name_dup(name, view->mctx, new);
01671         if (result == ISC_R_SUCCESS)
01672                 ISC_LIST_APPEND(view->delonly[hash], new, link);
01673         else
01674                 isc_mem_put(view->mctx, new, sizeof(*new));
01675         return (result);
01676 }
01677 
01678 isc_result_t
01679 dns_view_excludedelegationonly(dns_view_t *view, dns_name_t *name) {
01680         isc_result_t result;
01681         dns_name_t *new;
01682         isc_uint32_t hash;
01683 
01684         REQUIRE(DNS_VIEW_VALID(view));
01685 
01686         if (view->rootexclude == NULL) {
01687                 view->rootexclude = isc_mem_get(view->mctx,
01688                                             sizeof(dns_namelist_t) *
01689                                             DNS_VIEW_DELONLYHASH);
01690                 if (view->rootexclude == NULL)
01691                         return (ISC_R_NOMEMORY);
01692                 for (hash = 0; hash < DNS_VIEW_DELONLYHASH; hash++)
01693                         ISC_LIST_INIT(view->rootexclude[hash]);
01694         }
01695         hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
01696         new = ISC_LIST_HEAD(view->rootexclude[hash]);
01697         while (new != NULL && !dns_name_equal(new, name))
01698                 new = ISC_LIST_NEXT(new, link);
01699         if (new != NULL)
01700                 return (ISC_R_SUCCESS);
01701         new = isc_mem_get(view->mctx, sizeof(*new));
01702         if (new == NULL)
01703                 return (ISC_R_NOMEMORY);
01704         dns_name_init(new, NULL);
01705         result = dns_name_dup(name, view->mctx, new);
01706         if (result == ISC_R_SUCCESS)
01707                 ISC_LIST_APPEND(view->rootexclude[hash], new, link);
01708         else
01709                 isc_mem_put(view->mctx, new, sizeof(*new));
01710         return (result);
01711 }
01712 
01713 isc_boolean_t
01714 dns_view_isdelegationonly(dns_view_t *view, dns_name_t *name) {
01715         dns_name_t *new;
01716         isc_uint32_t hash;
01717 
01718         REQUIRE(DNS_VIEW_VALID(view));
01719 
01720         if (!view->rootdelonly && view->delonly == NULL)
01721                 return (ISC_FALSE);
01722 
01723         hash = dns_name_hash(name, ISC_FALSE) % DNS_VIEW_DELONLYHASH;
01724         if (view->rootdelonly && dns_name_countlabels(name) <= 2) {
01725                 if (view->rootexclude == NULL)
01726                         return (ISC_TRUE);
01727                 new = ISC_LIST_HEAD(view->rootexclude[hash]);
01728                 while (new != NULL && !dns_name_equal(new, name))
01729                         new = ISC_LIST_NEXT(new, link);
01730                 if (new == NULL)
01731                         return (ISC_TRUE);
01732         }
01733 
01734         if (view->delonly == NULL)
01735                 return (ISC_FALSE);
01736 
01737         new = ISC_LIST_HEAD(view->delonly[hash]);
01738         while (new != NULL && !dns_name_equal(new, name))
01739                 new = ISC_LIST_NEXT(new, link);
01740         if (new == NULL)
01741                 return (ISC_FALSE);
01742         return (ISC_TRUE);
01743 }
01744 
01745 void
01746 dns_view_setrootdelonly(dns_view_t *view, isc_boolean_t value) {
01747         REQUIRE(DNS_VIEW_VALID(view));
01748         view->rootdelonly = value;
01749 }
01750 
01751 isc_boolean_t
01752 dns_view_getrootdelonly(dns_view_t *view) {
01753         REQUIRE(DNS_VIEW_VALID(view));
01754         return (view->rootdelonly);
01755 }
01756 
01757 isc_result_t
01758 dns_view_freezezones(dns_view_t *view, isc_boolean_t value) {
01759 
01760         REQUIRE(DNS_VIEW_VALID(view));
01761         REQUIRE(view->zonetable != NULL);
01762 
01763         return (dns_zt_freezezones(view->zonetable, value));
01764 }
01765 
01766 void
01767 dns_view_setadbstats(dns_view_t *view, isc_stats_t *stats) {
01768         REQUIRE(DNS_VIEW_VALID(view));
01769         REQUIRE(!view->frozen);
01770         REQUIRE(view->adbstats == NULL);
01771 
01772         isc_stats_attach(stats, &view->adbstats);
01773 }
01774 
01775 void
01776 dns_view_getadbstats(dns_view_t *view, isc_stats_t **statsp) {
01777         REQUIRE(DNS_VIEW_VALID(view));
01778         REQUIRE(statsp != NULL && *statsp == NULL);
01779 
01780         if (view->adbstats != NULL)
01781                 isc_stats_attach(view->adbstats, statsp);
01782 }
01783 
01784 void
01785 dns_view_setresstats(dns_view_t *view, isc_stats_t *stats) {
01786 
01787         REQUIRE(DNS_VIEW_VALID(view));
01788         REQUIRE(!view->frozen);
01789         REQUIRE(view->resstats == NULL);
01790 
01791         isc_stats_attach(stats, &view->resstats);
01792 }
01793 
01794 void
01795 dns_view_getresstats(dns_view_t *view, isc_stats_t **statsp) {
01796         REQUIRE(DNS_VIEW_VALID(view));
01797         REQUIRE(statsp != NULL && *statsp == NULL);
01798 
01799         if (view->resstats != NULL)
01800                 isc_stats_attach(view->resstats, statsp);
01801 }
01802 
01803 void
01804 dns_view_setresquerystats(dns_view_t *view, dns_stats_t *stats) {
01805         REQUIRE(DNS_VIEW_VALID(view));
01806         REQUIRE(!view->frozen);
01807         REQUIRE(view->resquerystats == NULL);
01808 
01809         dns_stats_attach(stats, &view->resquerystats);
01810 }
01811 
01812 void
01813 dns_view_getresquerystats(dns_view_t *view, dns_stats_t **statsp) {
01814         REQUIRE(DNS_VIEW_VALID(view));
01815         REQUIRE(statsp != NULL && *statsp == NULL);
01816 
01817         if (view->resquerystats != NULL)
01818                 dns_stats_attach(view->resquerystats, statsp);
01819 }
01820 
01821 isc_result_t
01822 dns_view_initntatable(dns_view_t *view,
01823                       isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr)
01824 {
01825         REQUIRE(DNS_VIEW_VALID(view));
01826         if (view->ntatable_priv != NULL)
01827                 dns_ntatable_detach(&view->ntatable_priv);
01828         return (dns_ntatable_create(view, taskmgr, timermgr,
01829                                     &view->ntatable_priv));
01830 }
01831 
01832 isc_result_t
01833 dns_view_getntatable(dns_view_t *view, dns_ntatable_t **ntp) {
01834         REQUIRE(DNS_VIEW_VALID(view));
01835         REQUIRE(ntp != NULL && *ntp == NULL);
01836         if (view->ntatable_priv == NULL)
01837                 return (ISC_R_NOTFOUND);
01838         dns_ntatable_attach(view->ntatable_priv, ntp);
01839         return (ISC_R_SUCCESS);
01840 }
01841 
01842 isc_result_t
01843 dns_view_initsecroots(dns_view_t *view, isc_mem_t *mctx) {
01844         REQUIRE(DNS_VIEW_VALID(view));
01845         if (view->secroots_priv != NULL)
01846                 dns_keytable_detach(&view->secroots_priv);
01847         return (dns_keytable_create(mctx, &view->secroots_priv));
01848 }
01849 
01850 isc_result_t
01851 dns_view_getsecroots(dns_view_t *view, dns_keytable_t **ktp) {
01852         REQUIRE(DNS_VIEW_VALID(view));
01853         REQUIRE(ktp != NULL && *ktp == NULL);
01854         if (view->secroots_priv == NULL)
01855                 return (ISC_R_NOTFOUND);
01856         dns_keytable_attach(view->secroots_priv, ktp);
01857         return (ISC_R_SUCCESS);
01858 }
01859 
01860 isc_boolean_t
01861 dns_view_ntacovers(dns_view_t *view, isc_stdtime_t now,
01862                    dns_name_t *name, dns_name_t *anchor)
01863 {
01864         REQUIRE(DNS_VIEW_VALID(view));
01865 
01866         if (view->ntatable_priv == NULL)
01867                 return (ISC_FALSE);
01868 
01869         return (dns_ntatable_covered(view->ntatable_priv, now, name, anchor));
01870 }
01871 
01872 isc_result_t
01873 dns_view_issecuredomain(dns_view_t *view, dns_name_t *name,
01874                         isc_stdtime_t now, isc_boolean_t checknta,
01875                         isc_boolean_t *secure_domain)
01876 {
01877         isc_result_t result;
01878         isc_boolean_t secure = ISC_FALSE;
01879         dns_fixedname_t fn;
01880         dns_name_t *anchor;
01881 
01882         REQUIRE(DNS_VIEW_VALID(view));
01883 
01884         if (view->secroots_priv == NULL)
01885                 return (ISC_R_NOTFOUND);
01886 
01887         dns_fixedname_init(&fn);
01888         anchor = dns_fixedname_name(&fn);
01889 
01890         result = dns_keytable_issecuredomain(view->secroots_priv, name,
01891                                              anchor, &secure);
01892         if (result != ISC_R_SUCCESS)
01893                 return (result);
01894 
01895         if (checknta && secure && view->ntatable_priv != NULL &&
01896             dns_ntatable_covered(view->ntatable_priv, now, name, anchor))
01897                 secure = ISC_FALSE;
01898 
01899         *secure_domain = secure;
01900         return (ISC_R_SUCCESS);
01901 }
01902 
01903 void
01904 dns_view_untrust(dns_view_t *view, dns_name_t *keyname,
01905                  dns_rdata_dnskey_t *dnskey, isc_mem_t *mctx)
01906 {
01907         isc_result_t result;
01908         unsigned char data[4096];
01909         dns_rdata_t rdata = DNS_RDATA_INIT;
01910         isc_buffer_t buffer;
01911         dst_key_t *key = NULL;
01912         dns_keytable_t *sr = NULL;
01913 
01914         /*
01915          * Clear the revoke bit, if set, so that the key will match what's
01916          * in secroots now.
01917          */
01918         dnskey->flags &= ~DNS_KEYFLAG_REVOKE;
01919 
01920         /* Convert dnskey to DST key. */
01921         isc_buffer_init(&buffer, data, sizeof(data));
01922         dns_rdata_fromstruct(&rdata, dnskey->common.rdclass,
01923                              dns_rdatatype_dnskey, dnskey, &buffer);
01924         result = dns_dnssec_keyfromrdata(keyname, &rdata, mctx, &key);
01925         if (result != ISC_R_SUCCESS)
01926                 return;
01927         result = dns_view_getsecroots(view, &sr);
01928         if (result == ISC_R_SUCCESS) {
01929                 dns_keytable_deletekeynode(sr, key);
01930                 dns_keytable_detach(&sr);
01931         }
01932         dst_key_free(&key);
01933 }
01934 
01935 void
01936 dns_view_setnewzones(dns_view_t *view, isc_boolean_t allow, void *cfgctx,
01937                      void (*cfg_destroy)(void **))
01938 {
01939         REQUIRE(DNS_VIEW_VALID(view));
01940         REQUIRE((cfgctx != NULL && cfg_destroy != NULL) || !allow);
01941 
01942         if (view->new_zone_file != NULL) {
01943                 isc_mem_free(view->mctx, view->new_zone_file);
01944                 view->new_zone_file = NULL;
01945         }
01946 
01947         if (view->new_zone_config != NULL) {
01948                 view->cfg_destroy(&view->new_zone_config);
01949                 view->cfg_destroy = NULL;
01950         }
01951 
01952         if (allow) {
01953                 isc_result_t result;
01954                 char buffer[1024];
01955 
01956                 result = isc_file_sanitize(NULL, view->name, "nzf",
01957                                            buffer, sizeof(buffer));
01958                 if (result == ISC_R_SUCCESS) {
01959                         view->new_zone_file = isc_mem_strdup(view->mctx,
01960                                                              buffer);
01961                         view->new_zone_config = cfgctx;
01962                         view->cfg_destroy = cfg_destroy;
01963                 }
01964         }
01965 }
01966 
01967 isc_result_t
01968 dns_view_searchdlz(dns_view_t *view, dns_name_t *name, unsigned int minlabels,
01969                    dns_clientinfomethods_t *methods,
01970                    dns_clientinfo_t *clientinfo,
01971                    dns_db_t **dbp)
01972 {
01973         dns_fixedname_t fname;
01974         dns_name_t *zonename;
01975         unsigned int namelabels;
01976         unsigned int i;
01977         isc_result_t result;
01978         dns_dlzfindzone_t findzone;
01979         dns_dlzdb_t *dlzdb;
01980         dns_db_t *db, *best = NULL;
01981 
01982         /*
01983          * Performs checks to make sure data is as we expect it to be.
01984          */
01985         REQUIRE(DNS_VIEW_VALID(view));
01986         REQUIRE(name != NULL);
01987         REQUIRE(dbp != NULL && *dbp == NULL);
01988 
01989         /* setup a "fixed" dns name */
01990         dns_fixedname_init(&fname);
01991         zonename = dns_fixedname_name(&fname);
01992 
01993         /* count the number of labels in the name */
01994         namelabels = dns_name_countlabels(name);
01995 
01996         for (dlzdb = ISC_LIST_HEAD(view->dlz_searched);
01997              dlzdb != NULL;
01998              dlzdb = ISC_LIST_NEXT(dlzdb, link))
01999         {
02000                 REQUIRE(DNS_DLZ_VALID(dlzdb));
02001 
02002                 /*
02003                  * loop through starting with the longest domain name and
02004                  * trying shorter names portions of the name until we find a
02005                  * match, have an error, or are below the 'minlabels'
02006                  * threshold.  minlabels is 0, if neither the standard
02007                  * database nor any previous DLZ database had a zone name
02008                  * match. Otherwise minlabels is the number of labels
02009                  * in that name.  We need to beat that for a "better"
02010                  * match for this DLZ database to be authoritative.
02011                  */
02012                 for (i = namelabels; i > minlabels && i > 1; i--) {
02013                         if (i == namelabels) {
02014                                 result = dns_name_copy(name, zonename, NULL);
02015                                 if (result != ISC_R_SUCCESS)
02016                                         return (result);
02017                         } else
02018                                 dns_name_split(name, i, NULL, zonename);
02019 
02020                         /* ask SDLZ driver if the zone is supported */
02021                         db = NULL;
02022                         findzone = dlzdb->implementation->methods->findzone;
02023                         result = (*findzone)(dlzdb->implementation->driverarg,
02024                                              dlzdb->dbdata, dlzdb->mctx,
02025                                              view->rdclass, zonename,
02026                                              methods, clientinfo, &db);
02027 
02028                         if (result != ISC_R_NOTFOUND) {
02029                                 if (best != NULL)
02030                                         dns_db_detach(&best);
02031                                 if (result == ISC_R_SUCCESS) {
02032                                         INSIST(db != NULL);
02033                                         dns_db_attach(db, &best);
02034                                         dns_db_detach(&db);
02035                                         minlabels = i;
02036                                 } else {
02037                                         if (db != NULL)
02038                                                 dns_db_detach(&db);
02039                                         break;
02040                                 }
02041                         } else if (db != NULL)
02042                                 dns_db_detach(&db);
02043                 }
02044         }
02045 
02046         if (best != NULL) {
02047                 dns_db_attach(best, dbp);
02048                 dns_db_detach(&best);
02049                 return (ISC_R_SUCCESS);
02050         }
02051 
02052         return (ISC_R_NOTFOUND);
02053 }
02054 
02055 isc_uint32_t
02056 dns_view_getfailttl(dns_view_t *view) {
02057         REQUIRE(DNS_VIEW_VALID(view));
02058         return (view->fail_ttl);
02059 }
02060 
02061 void
02062 dns_view_setfailttl(dns_view_t *view, isc_uint32_t fail_ttl) {
02063         REQUIRE(DNS_VIEW_VALID(view));
02064         view->fail_ttl = fail_ttl;
02065 }
02066 
02067 isc_result_t
02068 dns_view_saventa(dns_view_t *view) {
02069         isc_result_t result;
02070         isc_boolean_t removefile = ISC_FALSE;
02071         dns_ntatable_t *ntatable = NULL;
02072         FILE *fp = NULL;
02073 
02074         REQUIRE(DNS_VIEW_VALID(view));
02075 
02076         if (view->nta_lifetime == 0)
02077                 return (ISC_R_SUCCESS);
02078 
02079         /* Open NTA save file for overwrite. */
02080         CHECK(isc_stdio_open(view->nta_file, "w", &fp));
02081 
02082         result = dns_view_getntatable(view, &ntatable);
02083         if (result == ISC_R_NOTFOUND) {
02084                 removefile = ISC_TRUE;
02085                 result = ISC_R_SUCCESS;
02086                 goto cleanup;
02087         } else
02088                 CHECK(result);
02089 
02090         result = dns_ntatable_save(ntatable, fp);
02091         if (result == ISC_R_NOTFOUND) {
02092                 removefile = ISC_TRUE;
02093                 result = ISC_R_SUCCESS;
02094         }
02095 
02096  cleanup:
02097         if (ntatable != NULL)
02098                 dns_ntatable_detach(&ntatable);
02099 
02100         if (fp != NULL)
02101                 isc_stdio_close(fp);
02102 
02103         /* Don't leave half-baked NTA save files lying around. */
02104         if (result != ISC_R_SUCCESS || removefile)
02105                 (void) isc_file_remove(view->nta_file);
02106 
02107         return (result);
02108 }
02109 
02110 #define TSTR(t) ((t).value.as_textregion.base)
02111 #define TLEN(t) ((t).value.as_textregion.length)
02112 
02113 isc_result_t
02114 dns_view_loadnta(dns_view_t *view) {
02115         isc_result_t result;
02116         dns_ntatable_t *ntatable = NULL;
02117         isc_lex_t *lex = NULL;
02118         isc_token_t token;
02119         isc_stdtime_t now;
02120 
02121         REQUIRE(DNS_VIEW_VALID(view));
02122 
02123         if (view->nta_lifetime == 0)
02124                 return (ISC_R_SUCCESS);
02125 
02126         CHECK(isc_lex_create(view->mctx, 1025, &lex));
02127         CHECK(isc_lex_openfile(lex, view->nta_file));
02128         CHECK(dns_view_getntatable(view, &ntatable));
02129         isc_stdtime_get(&now);
02130 
02131         for (;;) {
02132                 int options = (ISC_LEXOPT_EOL | ISC_LEXOPT_EOF);
02133                 char *name, *type, *timestamp;
02134                 size_t len;
02135                 dns_fixedname_t fn;
02136                 dns_name_t *ntaname;
02137                 isc_buffer_t b;
02138                 isc_stdtime_t t;
02139                 isc_boolean_t forced;
02140 
02141                 CHECK(isc_lex_gettoken(lex, options, &token));
02142                 if (token.type == isc_tokentype_eof)
02143                         break;
02144                 else if (token.type != isc_tokentype_string)
02145                         CHECK(ISC_R_UNEXPECTEDTOKEN);
02146                 name = TSTR(token);
02147                 len = TLEN(token);
02148 
02149                 if (strcmp(name, ".") == 0)
02150                         ntaname = dns_rootname;
02151                 else {
02152                         dns_fixedname_init(&fn);
02153                         ntaname = dns_fixedname_name(&fn);
02154 
02155                         isc_buffer_init(&b, name, (unsigned int)len);
02156                         isc_buffer_add(&b, (unsigned int)len);
02157                         CHECK(dns_name_fromtext(ntaname, &b, dns_rootname,
02158                                                 0, NULL));
02159                 }
02160 
02161                 CHECK(isc_lex_gettoken(lex, options, &token));
02162                 if (token.type != isc_tokentype_string)
02163                         CHECK(ISC_R_UNEXPECTEDTOKEN);
02164                 type = TSTR(token);
02165 
02166                 if (strcmp(type, "regular") == 0)
02167                         forced = ISC_FALSE;
02168                 else if (strcmp(type, "forced") == 0)
02169                         forced = ISC_TRUE;
02170                 else
02171                         CHECK(ISC_R_UNEXPECTEDTOKEN);
02172 
02173                 CHECK(isc_lex_gettoken(lex, options, &token));
02174                 if (token.type != isc_tokentype_string)
02175                         CHECK(ISC_R_UNEXPECTEDTOKEN);
02176                 timestamp = TSTR(token);
02177                 CHECK(dns_time32_fromtext(timestamp, &t));
02178 
02179                 CHECK(isc_lex_gettoken(lex, options, &token));
02180                 if (token.type != isc_tokentype_eol &&
02181                     token.type != isc_tokentype_eof)
02182                         CHECK(ISC_R_UNEXPECTEDTOKEN);
02183 
02184                 if (now <= t) {
02185                         if (t > (now + 604800))
02186                                 t = now + 604800;
02187 
02188                         (void) dns_ntatable_add(ntatable, ntaname,
02189                                                 forced, 0, t);
02190                 }
02191         };
02192 
02193  cleanup:
02194         if (ntatable != NULL)
02195                 dns_ntatable_detach(&ntatable);
02196 
02197         if (lex != NULL) {
02198                 isc_lex_close(lex);
02199                 isc_lex_destroy(&lex);
02200         }
02201 
02202         return (result);
02203 }

Generated on Tue Apr 28 17:41:02 2015 by Doxygen 1.5.4 for BIND9 Internals 9.11.0pre-alpha