nta.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2014, 2015  Internet Systems Consortium, Inc. ("ISC")
00003  *
00004  * Permission to use, copy, modify, and/or distribute this software for any
00005  * purpose with or without fee is hereby granted, provided that the above
00006  * copyright notice and this permission notice appear in all copies.
00007  *
00008  * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
00009  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
00010  * AND FITNESS.  IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
00011  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
00012  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
00013  * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
00014  * PERFORMANCE OF THIS SOFTWARE.
00015  */
00016 
00017 /*! \file */
00018 
00019 #include <config.h>
00020 
00021 #include <isc/buffer.h>
00022 #include <isc/log.h>
00023 #include <isc/mem.h>
00024 #include <isc/print.h>
00025 #include <isc/rwlock.h>
00026 #include <isc/string.h>
00027 #include <isc/task.h>
00028 #include <isc/time.h>
00029 #include <isc/timer.h>
00030 #include <isc/util.h>
00031 
00032 #include <dns/db.h>
00033 #include <dns/log.h>
00034 #include <dns/nta.h>
00035 #include <dns/fixedname.h>
00036 #include <dns/name.h>
00037 #include <dns/rbt.h>
00038 #include <dns/rdataset.h>
00039 #include <dns/resolver.h>
00040 #include <dns/result.h>
00041 #include <dns/time.h>
00042 
00043 struct dns_nta {
00044         unsigned int            magic;
00045         isc_refcount_t          refcount;
00046         dns_ntatable_t          *ntatable;
00047         isc_boolean_t           forced;
00048         isc_timer_t             *timer;
00049         dns_fetch_t             *fetch;
00050         dns_rdataset_t          rdataset;
00051         dns_rdataset_t          sigrdataset;
00052         dns_fixedname_t         fn;
00053         dns_name_t              *name;
00054         isc_stdtime_t           expiry;
00055 };
00056 
00057 #define NTA_MAGIC               ISC_MAGIC('N', 'T', 'A', 'n')
00058 #define VALID_NTA(nn)           ISC_MAGIC_VALID(nn, NTA_MAGIC)
00059 
00060 /*
00061  * Obtain a reference to the nta object.  Released by
00062  * nta_detach.
00063  */
00064 static void
00065 nta_ref(dns_nta_t *nta) {
00066         isc_refcount_increment(&nta->refcount, NULL);
00067 }
00068 
00069 static void
00070 nta_detach(isc_mem_t *mctx, dns_nta_t **ntap) {
00071         unsigned int refs;
00072         dns_nta_t *nta = *ntap;
00073 
00074         REQUIRE(VALID_NTA(nta));
00075 
00076         *ntap = NULL;
00077         isc_refcount_decrement(&nta->refcount, &refs);
00078         if (refs == 0) {
00079                 nta->magic = 0;
00080                 if (nta->timer != NULL) {
00081                         (void) isc_timer_reset(nta->timer,
00082                                                isc_timertype_inactive,
00083                                                NULL, NULL, ISC_TRUE);
00084                         isc_timer_detach(&nta->timer);
00085                 }
00086                 isc_refcount_destroy(&nta->refcount);
00087                 if (dns_rdataset_isassociated(&nta->rdataset))
00088                         dns_rdataset_disassociate(&nta->rdataset);
00089                 if (dns_rdataset_isassociated(&nta->sigrdataset))
00090                         dns_rdataset_disassociate(&nta->sigrdataset);
00091                 if (nta->fetch != NULL) {
00092                         dns_resolver_cancelfetch(nta->fetch);
00093                         dns_resolver_destroyfetch(&nta->fetch);
00094                 }
00095                 isc_mem_put(mctx, nta, sizeof(dns_nta_t));
00096         }
00097 }
00098 
00099 static void
00100 free_nta(void *data, void *arg) {
00101         dns_nta_t *nta = (dns_nta_t *) data;
00102         isc_mem_t *mctx = (isc_mem_t *) arg;
00103 
00104         nta_detach(mctx, &nta);
00105 }
00106 
00107 isc_result_t
00108 dns_ntatable_create(dns_view_t *view,
00109                     isc_taskmgr_t *taskmgr, isc_timermgr_t *timermgr,
00110                     dns_ntatable_t **ntatablep)
00111 {
00112         dns_ntatable_t *ntatable;
00113         isc_result_t result;
00114 
00115         REQUIRE(ntatablep != NULL && *ntatablep == NULL);
00116 
00117         ntatable = isc_mem_get(view->mctx, sizeof(*ntatable));
00118         if (ntatable == NULL)
00119                 return (ISC_R_NOMEMORY);
00120 
00121         ntatable->task = NULL;
00122         result = isc_task_create(taskmgr, 0, &ntatable->task);
00123         if (result != ISC_R_SUCCESS)
00124                 goto cleanup_ntatable;
00125         isc_task_setname(ntatable->task, "ntatable", ntatable);
00126 
00127         ntatable->table = NULL;
00128         result = dns_rbt_create(view->mctx, free_nta, view->mctx,
00129                                 &ntatable->table);
00130         if (result != ISC_R_SUCCESS)
00131                 goto cleanup_task;
00132 
00133         result = isc_rwlock_init(&ntatable->rwlock, 0, 0);
00134         if (result != ISC_R_SUCCESS)
00135                 goto cleanup_rbt;
00136 
00137         ntatable->timermgr = timermgr;
00138         ntatable->taskmgr = taskmgr;
00139 
00140         ntatable->view = view;
00141         ntatable->references = 1;
00142 
00143         ntatable->magic = NTATABLE_MAGIC;
00144         *ntatablep = ntatable;
00145 
00146         return (ISC_R_SUCCESS);
00147 
00148    cleanup_rbt:
00149         dns_rbt_destroy(&ntatable->table);
00150 
00151    cleanup_task:
00152         isc_task_detach(&ntatable->task);
00153 
00154    cleanup_ntatable:
00155         isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
00156 
00157         return (result);
00158 }
00159 
00160 void
00161 dns_ntatable_attach(dns_ntatable_t *source, dns_ntatable_t **targetp) {
00162         REQUIRE(VALID_NTATABLE(source));
00163         REQUIRE(targetp != NULL && *targetp == NULL);
00164 
00165         RWLOCK(&source->rwlock, isc_rwlocktype_write);
00166 
00167         INSIST(source->references > 0);
00168         source->references++;
00169         INSIST(source->references != 0);
00170 
00171         RWUNLOCK(&source->rwlock, isc_rwlocktype_write);
00172 
00173         *targetp = source;
00174 }
00175 
00176 void
00177 dns_ntatable_detach(dns_ntatable_t **ntatablep) {
00178         isc_boolean_t destroy = ISC_FALSE;
00179         dns_ntatable_t *ntatable;
00180 
00181         REQUIRE(ntatablep != NULL && VALID_NTATABLE(*ntatablep));
00182 
00183         ntatable = *ntatablep;
00184         *ntatablep = NULL;
00185 
00186         RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
00187         INSIST(ntatable->references > 0);
00188         ntatable->references--;
00189         if (ntatable->references == 0)
00190                 destroy = ISC_TRUE;
00191         RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
00192 
00193         if (destroy) {
00194                 dns_rbt_destroy(&ntatable->table);
00195                 isc_rwlock_destroy(&ntatable->rwlock);
00196                 if (ntatable->task != NULL)
00197                         isc_task_detach(&ntatable->task);
00198                 ntatable->timermgr = NULL;
00199                 ntatable->taskmgr = NULL;
00200                 ntatable->magic = 0;
00201                 isc_mem_put(ntatable->view->mctx, ntatable, sizeof(*ntatable));
00202         }
00203 }
00204 
00205 static void
00206 fetch_done(isc_task_t *task, isc_event_t *event) {
00207         dns_fetchevent_t *devent = (dns_fetchevent_t *)event;
00208         dns_nta_t *nta = devent->ev_arg;
00209         isc_result_t eresult = devent->result;
00210         dns_ntatable_t *ntatable = nta->ntatable;
00211         dns_view_t *view = ntatable->view;
00212         isc_stdtime_t now;
00213 
00214         UNUSED(task);
00215 
00216         if (dns_rdataset_isassociated(&nta->rdataset))
00217                 dns_rdataset_disassociate(&nta->rdataset);
00218         if (dns_rdataset_isassociated(&nta->sigrdataset))
00219                 dns_rdataset_disassociate(&nta->sigrdataset);
00220         if (nta->fetch == devent->fetch)
00221                 nta->fetch = NULL;
00222         dns_resolver_destroyfetch(&devent->fetch);
00223 
00224         if (devent->node != NULL)
00225                 dns_db_detachnode(devent->db, &devent->node);
00226         if (devent->db != NULL)
00227                 dns_db_detach(&devent->db);
00228 
00229         isc_event_free(&event);
00230         isc_stdtime_get(&now);
00231 
00232         switch (eresult) {
00233         case ISC_R_SUCCESS:
00234         case DNS_R_NCACHENXDOMAIN:
00235         case DNS_R_NXDOMAIN:
00236         case DNS_R_NCACHENXRRSET:
00237         case DNS_R_NXRRSET:
00238                 nta->expiry = now;
00239                 break;
00240         default:
00241                 break;
00242         }
00243 
00244         /*
00245          * If we're expiring before the next recheck, we might
00246          * as well stop the timer now.
00247          */
00248         if (nta->timer != NULL && nta->expiry - now < ntatable->recheck)
00249                 (void) isc_timer_reset(nta->timer, isc_timertype_inactive,
00250                                        NULL, NULL, ISC_TRUE);
00251         nta_detach(view->mctx, &nta);
00252 }
00253 
00254 static void
00255 checkbogus(isc_task_t *task, isc_event_t *event) {
00256         dns_nta_t *nta = event->ev_arg;
00257         dns_ntatable_t *ntatable = nta->ntatable;
00258         dns_view_t *view = ntatable->view;
00259         isc_result_t result;
00260 
00261         if (nta->fetch != NULL) {
00262                 dns_resolver_cancelfetch(nta->fetch);
00263                 nta->fetch = NULL;
00264         }
00265         if (dns_rdataset_isassociated(&nta->rdataset))
00266                 dns_rdataset_disassociate(&nta->rdataset);
00267         if (dns_rdataset_isassociated(&nta->sigrdataset))
00268                 dns_rdataset_disassociate(&nta->sigrdataset);
00269 
00270         isc_event_free(&event);
00271 
00272         nta_ref(nta);
00273         result = dns_resolver_createfetch(view->resolver, nta->name,
00274                                           dns_rdatatype_nsec,
00275                                           NULL, NULL, NULL,
00276                                           DNS_FETCHOPT_NONTA,
00277                                           task, fetch_done, nta,
00278                                           &nta->rdataset,
00279                                           &nta->sigrdataset,
00280                                           &nta->fetch);
00281         if (result != ISC_R_SUCCESS)
00282                 nta_detach(view->mctx, &nta);
00283 }
00284 
00285 static isc_result_t
00286 settimer(dns_ntatable_t *ntatable, dns_nta_t *nta, isc_uint32_t lifetime) {
00287         isc_result_t result;
00288         isc_interval_t interval;
00289         dns_view_t *view;
00290 
00291         REQUIRE(VALID_NTATABLE(ntatable));
00292         REQUIRE(VALID_NTA(nta));
00293 
00294         if (ntatable->timermgr == NULL)
00295                 return (ISC_R_SUCCESS);
00296 
00297         view = ntatable->view;
00298         if (view->nta_recheck == 0 || lifetime <= view->nta_recheck)
00299                 return (ISC_R_SUCCESS);
00300 
00301         isc_interval_set(&interval, view->nta_recheck, 0);
00302         result = isc_timer_create(ntatable->timermgr, isc_timertype_ticker,
00303                                   NULL, &interval, ntatable->task,
00304                                   checkbogus, nta, &nta->timer);
00305         return (result);
00306 }
00307 
00308 static isc_result_t
00309 nta_create(dns_ntatable_t *ntatable, dns_name_t *name, dns_nta_t **target) {
00310         isc_result_t result;
00311         dns_nta_t *nta = NULL;
00312         dns_view_t *view;
00313 
00314         REQUIRE(VALID_NTATABLE(ntatable));
00315         REQUIRE(target != NULL && *target == NULL);
00316 
00317         view = ntatable->view;
00318 
00319         nta = isc_mem_get(view->mctx, sizeof(dns_nta_t));
00320         if (nta == NULL)
00321                 return (ISC_R_NOMEMORY);
00322 
00323         nta->ntatable = ntatable;
00324         nta->expiry = 0;
00325         nta->timer = NULL;
00326         nta->fetch = NULL;
00327         dns_rdataset_init(&nta->rdataset);
00328         dns_rdataset_init(&nta->sigrdataset);
00329 
00330         result = isc_refcount_init(&nta->refcount, 1);
00331         if (result != ISC_R_SUCCESS) {
00332                 isc_mem_put(view->mctx, nta, sizeof(dns_nta_t));
00333                 return (result);
00334         }
00335 
00336         dns_fixedname_init(&nta->fn);
00337         nta->name = dns_fixedname_name(&nta->fn);
00338         dns_name_copy(name, nta->name, NULL);
00339 
00340         nta->magic = NTA_MAGIC;
00341 
00342         *target = nta;
00343         return (ISC_R_SUCCESS);
00344 }
00345 
00346 isc_result_t
00347 dns_ntatable_add(dns_ntatable_t *ntatable, dns_name_t *name,
00348                  isc_boolean_t force, isc_stdtime_t now,
00349                  isc_uint32_t lifetime)
00350 {
00351         isc_result_t result;
00352         dns_nta_t *nta = NULL;
00353         dns_rbtnode_t *node;
00354         dns_view_t *view;
00355 
00356         REQUIRE(VALID_NTATABLE(ntatable));
00357 
00358         view = ntatable->view;
00359 
00360         result = nta_create(ntatable, name, &nta);
00361         if (result != ISC_R_SUCCESS)
00362                 return (result);
00363 
00364         nta->expiry = now + lifetime;
00365         nta->forced = force;
00366 
00367         RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
00368 
00369         node = NULL;
00370         result = dns_rbt_addnode(ntatable->table, name, &node);
00371         if (result == ISC_R_SUCCESS) {
00372                 if (!force)
00373                         (void)settimer(ntatable, nta, lifetime);
00374                 node->data = nta;
00375                 nta = NULL;
00376         } else if (result == ISC_R_EXISTS) {
00377                 dns_nta_t *n = node->data;
00378                 if (n == NULL) {
00379                         if (!force)
00380                                 (void)settimer(ntatable, nta, lifetime);
00381                         node->data = nta;
00382                         nta = NULL;
00383                 } else {
00384                         n->expiry = nta->expiry;
00385                         nta_detach(view->mctx, &nta);
00386                 }
00387                 result = ISC_R_SUCCESS;
00388         }
00389 
00390         RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
00391 
00392         if (nta != NULL)
00393                 nta_detach(view->mctx, &nta);
00394 
00395         return (result);
00396 }
00397 
00398 /*
00399  * Caller must hold a write lock on rwlock.
00400  */
00401 static isc_result_t
00402 delete(dns_ntatable_t *ntatable, dns_name_t *name) {
00403         isc_result_t result;
00404         dns_rbtnode_t *node = NULL;
00405 
00406         REQUIRE(VALID_NTATABLE(ntatable));
00407         REQUIRE(name != NULL);
00408 
00409         result = dns_rbt_findnode(ntatable->table, name, NULL, &node, NULL,
00410                                   DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00411         if (result == ISC_R_SUCCESS) {
00412                 if (node->data != NULL)
00413                         result = dns_rbt_deletenode(ntatable->table,
00414                                                     node, ISC_FALSE);
00415                 else
00416                         result = ISC_R_NOTFOUND;
00417         } else if (result == DNS_R_PARTIALMATCH)
00418                 result = ISC_R_NOTFOUND;
00419 
00420         return (result);
00421 }
00422 
00423 isc_result_t
00424 dns_ntatable_delete(dns_ntatable_t *ntatable, dns_name_t *name) {
00425         isc_result_t result;
00426 
00427         RWLOCK(&ntatable->rwlock, isc_rwlocktype_write);
00428         result = delete(ntatable, name);
00429         RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_write);
00430 
00431         return (result);
00432 }
00433 
00434 isc_boolean_t
00435 dns_ntatable_covered(dns_ntatable_t *ntatable, isc_stdtime_t now,
00436                      dns_name_t *name, dns_name_t *anchor)
00437 {
00438         isc_result_t result;
00439         dns_fixedname_t fn;
00440         dns_rbtnode_t *node;
00441         dns_name_t *foundname;
00442         dns_nta_t *nta = NULL;
00443         isc_boolean_t answer = ISC_FALSE;
00444         isc_rwlocktype_t locktype = isc_rwlocktype_read;
00445 
00446         REQUIRE(ntatable == NULL || VALID_NTATABLE(ntatable));
00447         REQUIRE(dns_name_isabsolute(name));
00448 
00449         if (ntatable == NULL)
00450                 return (ISC_FALSE);
00451 
00452         dns_fixedname_init(&fn);
00453         foundname = dns_fixedname_name(&fn);
00454 
00455  relock:
00456         RWLOCK(&ntatable->rwlock, locktype);
00457  again:
00458         node = NULL;
00459         result = dns_rbt_findnode(ntatable->table, name, foundname, &node, NULL,
00460                                   DNS_RBTFIND_NOOPTIONS, NULL, NULL);
00461         if (result == DNS_R_PARTIALMATCH) {
00462                 if (dns_name_issubdomain(foundname, anchor))
00463                         result = ISC_R_SUCCESS;
00464         }
00465         if (result == ISC_R_SUCCESS) {
00466                 nta = (dns_nta_t *) node->data;
00467                 answer = ISC_TF(nta->expiry >= now);
00468         }
00469 
00470         /* Deal with expired NTA */
00471         if (result == ISC_R_SUCCESS && !answer) {
00472                 char nb[DNS_NAME_FORMATSIZE];
00473 
00474                 if (locktype == isc_rwlocktype_read) {
00475                         RWUNLOCK(&ntatable->rwlock, locktype);
00476                         locktype = isc_rwlocktype_write;
00477                         goto relock;
00478                 }
00479 
00480                 dns_name_format(foundname, nb, sizeof(nb));
00481                 isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
00482                               DNS_LOGMODULE_NTA, ISC_LOG_INFO,
00483                               "deleting expired NTA at %s", nb);
00484 
00485                 if (nta->timer != NULL) {
00486                         (void) isc_timer_reset(nta->timer,
00487                                                isc_timertype_inactive,
00488                                                NULL, NULL, ISC_TRUE);
00489                         isc_timer_detach(&nta->timer);
00490                 }
00491 
00492                 result = delete(ntatable, foundname);
00493                 if (result != ISC_R_SUCCESS) {
00494                         isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
00495                                       DNS_LOGMODULE_NTA, ISC_LOG_INFO,
00496                                       "deleting NTA failed: %s",
00497                                       isc_result_totext(result));
00498                 }
00499                 goto again;
00500         }
00501         RWUNLOCK(&ntatable->rwlock, locktype);
00502 
00503         return (answer);
00504 }
00505 
00506 static isc_result_t
00507 putstr(isc_buffer_t **b, const char *str) {
00508         isc_result_t result;
00509 
00510         result = isc_buffer_reserve(b, strlen(str));
00511         if (result != ISC_R_SUCCESS)
00512                 return (result);
00513 
00514         isc_buffer_putstr(*b, str);
00515         return (ISC_R_SUCCESS);
00516 }
00517 
00518 isc_result_t
00519 dns_ntatable_totext(dns_ntatable_t *ntatable, isc_buffer_t **buf) {
00520         isc_result_t result;
00521         dns_rbtnode_t *node;
00522         dns_rbtnodechain_t chain;
00523         isc_boolean_t first = ISC_TRUE;
00524         isc_stdtime_t now;
00525 
00526         REQUIRE(VALID_NTATABLE(ntatable));
00527 
00528         isc_stdtime_get(&now);
00529 
00530         RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
00531         dns_rbtnodechain_init(&chain, ntatable->view->mctx);
00532         result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL);
00533         if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00534                 if (result == ISC_R_NOTFOUND)
00535                         result = ISC_R_SUCCESS;
00536                 goto cleanup;
00537         }
00538         for (;;) {
00539                 dns_rbtnodechain_current(&chain, NULL, NULL, &node);
00540                 if (node->data != NULL) {
00541                         dns_nta_t *n = (dns_nta_t *) node->data;
00542                         char nbuf[DNS_NAME_FORMATSIZE];
00543                         char tbuf[ISC_FORMATHTTPTIMESTAMP_SIZE];
00544                         char obuf[DNS_NAME_FORMATSIZE +
00545                                   ISC_FORMATHTTPTIMESTAMP_SIZE +
00546                                   sizeof("expired:  \n")];
00547                         dns_fixedname_t fn;
00548                         dns_name_t *name;
00549                         isc_time_t t;
00550 
00551                         dns_fixedname_init(&fn);
00552                         name = dns_fixedname_name(&fn);
00553                         dns_rbt_fullnamefromnode(node, name);
00554                         dns_name_format(name, nbuf, sizeof(nbuf));
00555                         isc_time_set(&t, n->expiry, 0);
00556                         isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
00557 
00558                         snprintf(obuf, sizeof(obuf), "%s%s: %s %s",
00559                                  first ? "" : "\n", nbuf,
00560                                  n->expiry < now ? "expired" : "expiry",
00561                                  tbuf);
00562                         first = ISC_FALSE;
00563                         result = putstr(buf, obuf);
00564                         if (result != ISC_R_SUCCESS)
00565                                 goto cleanup;
00566                 }
00567                 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00568                 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00569                         if (result == ISC_R_NOMORE)
00570                                 result = ISC_R_SUCCESS;
00571                         break;
00572                 }
00573         }
00574 
00575    cleanup:
00576         dns_rbtnodechain_invalidate(&chain);
00577         RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
00578         return (result);
00579 }
00580 
00581 #if 0
00582 isc_result_t
00583 dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
00584         isc_result_t result;
00585         dns_rbtnode_t *node;
00586         dns_rbtnodechain_t chain;
00587         isc_stdtime_t now;
00588 
00589         REQUIRE(VALID_NTATABLE(ntatable));
00590 
00591         isc_stdtime_get(&now);
00592 
00593         RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
00594         dns_rbtnodechain_init(&chain, ntatable->view->mctx);
00595         result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL);
00596         if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
00597                 goto cleanup;
00598         for (;;) {
00599                 dns_rbtnodechain_current(&chain, NULL, NULL, &node);
00600                 if (node->data != NULL) {
00601                         dns_nta_t *n = (dns_nta_t *) node->data;
00602                         char nbuf[DNS_NAME_FORMATSIZE], tbuf[80];
00603                         dns_fixedname_t fn;
00604                         dns_name_t *name;
00605                         isc_time_t t;
00606 
00607                         dns_fixedname_init(&fn);
00608                         name = dns_fixedname_name(&fn);
00609                         dns_rbt_fullnamefromnode(node, name);
00610                         dns_name_format(name, nbuf, sizeof(nbuf));
00611                         isc_time_set(&t, n->expiry, 0);
00612                         isc_time_formattimestamp(&t, tbuf, sizeof(tbuf));
00613                         fprintf(fp, "%s: %s %s\n", nbuf,
00614                                 n->expiry < now ? "expired" : "expiry",
00615                                 tbuf);
00616                 }
00617                 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00618                 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00619                         if (result == ISC_R_NOMORE)
00620                                 result = ISC_R_SUCCESS;
00621                         break;
00622                 }
00623         }
00624 
00625    cleanup:
00626         dns_rbtnodechain_invalidate(&chain);
00627         RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
00628         return (result);
00629 }
00630 #endif
00631 
00632 isc_result_t
00633 dns_ntatable_dump(dns_ntatable_t *ntatable, FILE *fp) {
00634         isc_result_t result;
00635         isc_buffer_t *text = NULL;
00636         int len = 4096;
00637 
00638         result = isc_buffer_allocate(ntatable->view->mctx, &text, len);
00639         if (result != ISC_R_SUCCESS)
00640                 return (result);
00641 
00642         result = dns_ntatable_totext(ntatable, &text);
00643 
00644         if (isc_buffer_usedlength(text) != 0) {
00645                 (void) putstr(&text, "\n");
00646         } else if (result == ISC_R_SUCCESS) {
00647                 (void) putstr(&text, "none");
00648         } else {
00649                 (void) putstr(&text, "could not dump NTA table: ");
00650                 (void) putstr(&text, isc_result_totext(result));
00651         }
00652 
00653         fprintf(fp, "%.*s", (int) isc_buffer_usedlength(text),
00654                 (char *) isc_buffer_base(text));
00655         isc_buffer_free(&text);
00656         return (result);
00657 }
00658 
00659 isc_result_t
00660 dns_ntatable_save(dns_ntatable_t *ntatable, FILE *fp) {
00661         isc_result_t result;
00662         dns_rbtnode_t *node;
00663         dns_rbtnodechain_t chain;
00664         isc_stdtime_t now;
00665         isc_boolean_t written = ISC_FALSE;
00666 
00667         REQUIRE(VALID_NTATABLE(ntatable));
00668 
00669         isc_stdtime_get(&now);
00670 
00671         RWLOCK(&ntatable->rwlock, isc_rwlocktype_read);
00672         dns_rbtnodechain_init(&chain, ntatable->view->mctx);
00673         result = dns_rbtnodechain_first(&chain, ntatable->table, NULL, NULL);
00674         if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN)
00675                 goto cleanup;
00676 
00677         for (;;) {
00678                 dns_rbtnodechain_current(&chain, NULL, NULL, &node);
00679                 if (node->data != NULL) {
00680                         dns_nta_t *n = (dns_nta_t *) node->data;
00681                         if (now <= n->expiry) {
00682                                 isc_buffer_t b;
00683                                 char nbuf[DNS_NAME_FORMATSIZE + 1], tbuf[80];
00684                                 dns_fixedname_t fn;
00685                                 dns_name_t *name;
00686 
00687                                 dns_fixedname_init(&fn);
00688                                 name = dns_fixedname_name(&fn);
00689                                 dns_rbt_fullnamefromnode(node, name);
00690 
00691                                 isc_buffer_init(&b, nbuf, sizeof(nbuf));
00692                                 result = dns_name_totext(name, ISC_FALSE, &b);
00693                                 if (result != ISC_R_SUCCESS)
00694                                         goto skip;
00695 
00696                                 /* Zero terminate. */
00697                                 isc_buffer_putuint8(&b, 0);
00698 
00699                                 isc_buffer_init(&b, tbuf, sizeof(tbuf));
00700                                 dns_time32_totext(n->expiry, &b);
00701 
00702                                 /* Zero terminate. */
00703                                 isc_buffer_putuint8(&b, 0);
00704 
00705                                 fprintf(fp, "%s %s %s\n", nbuf,
00706                                         n->forced ? "forced" : "regular",
00707                                         tbuf);
00708                                 written = ISC_TRUE;
00709                         }
00710                 }
00711         skip:
00712                 result = dns_rbtnodechain_next(&chain, NULL, NULL);
00713                 if (result != ISC_R_SUCCESS && result != DNS_R_NEWORIGIN) {
00714                         if (result == ISC_R_NOMORE)
00715                                 result = ISC_R_SUCCESS;
00716                         break;
00717                 }
00718         }
00719 
00720    cleanup:
00721         dns_rbtnodechain_invalidate(&chain);
00722         RWUNLOCK(&ntatable->rwlock, isc_rwlocktype_read);
00723 
00724         if (result != ISC_R_SUCCESS)
00725                 return (result);
00726         else
00727                 return (written ? ISC_R_SUCCESS : ISC_R_NOTFOUND);
00728 }

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