static void free_controlkeylist(controlkeylist_t *keylist, isc_mem_t *mctx) { while (!ISC_LIST_EMPTY(*keylist)) { controlkey_t *key = ISC_LIST_HEAD(*keylist); ISC_LIST_UNLINK(*keylist, key, link); free_controlkey(key, mctx); } }
isc_result_t printmessage(dig_query_t *query, dns_message_t *msg, isc_boolean_t headers) { char servtext[ISC_SOCKADDR_FORMATSIZE]; /* I've we've gotten this far, we've reached a server. */ query_error = 0; debug("printmessage()"); isc_sockaddr_format(&query->sockaddr, servtext, sizeof(servtext)); printf("Server:\t\t%s\n", query->userarg); printf("Address:\t%s\n", servtext); puts(""); if (!short_form) { isc_boolean_t headers = ISC_TRUE; puts("------------"); /* detailheader(query, msg);*/ detailsection(query, msg, headers, DNS_SECTION_QUESTION); detailsection(query, msg, headers, DNS_SECTION_ANSWER); detailsection(query, msg, headers, DNS_SECTION_AUTHORITY); detailsection(query, msg, headers, DNS_SECTION_ADDITIONAL); puts("------------"); } if (msg->rcode != 0) { char nametext[DNS_NAME_FORMATSIZE]; dns_name_format(query->lookup->name, nametext, sizeof(nametext)); printf("** server can't find %s: %s\n", nametext, rcode_totext(msg->rcode)); debug("returning with rcode == 0"); /* the lookup failed */ print_error |= 1; return (ISC_R_SUCCESS); } if ((msg->flags & DNS_MESSAGEFLAG_AA) == 0) puts("Non-authoritative answer:"); if (!ISC_LIST_EMPTY(msg->sections[DNS_SECTION_ANSWER])) printsection(query, msg, headers, DNS_SECTION_ANSWER); else printf("*** Can't find %s: No answer\n", query->lookup->textname); if (((msg->flags & DNS_MESSAGEFLAG_AA) == 0) && (query->lookup->rdtype != dns_rdatatype_a)) { puts("\nAuthoritative answers can be found from:"); printsection(query, msg, headers, DNS_SECTION_AUTHORITY); printsection(query, msg, headers, DNS_SECTION_ADDITIONAL); } return (ISC_R_SUCCESS); }
static void do_find(isc_boolean_t want_event) { isc_result_t result; isc_boolean_t done = ISC_FALSE; unsigned int options; options = DNS_ADBFIND_INET | DNS_ADBFIND_INET6; if (want_event) options |= DNS_ADBFIND_WANTEVENT | DNS_ADBFIND_EMPTYEVENT; dns_fixedname_init(&target); result = dns_adb_createfind(view->adb, task, adb_callback, NULL, dns_fixedname_name(&fixed), dns_rootname, 0, options, 0, dns_fixedname_name(&target), 0, &find); if (result == ISC_R_SUCCESS) { if (!ISC_LIST_EMPTY(find->list)) { /* * We have at least some of the addresses for the * name. */ INSIST((find->options & DNS_ADBFIND_WANTEVENT) == 0); print_addresses(find); done = ISC_TRUE; } else { /* * We don't know any of the addresses for this * name. */ if ((find->options & DNS_ADBFIND_WANTEVENT) == 0) { /* * And ADB isn't going to send us any events * either. This query loses. */ done = ISC_TRUE; } /* * If the DNS_ADBFIND_WANTEVENT flag was set, we'll * get an event when something happens. */ } } else if (result == DNS_R_ALIAS) { print_name(dns_fixedname_name(&target)); done = ISC_TRUE; } else { printf("dns_adb_createfind() returned %s\n", isc_result_totext(result)); done = ISC_TRUE; } if (done) { if (find != NULL) dns_adb_destroyfind(&find); isc_app_shutdown(); } }
void ns_controls_destroy(ns_controls_t **ctrlsp) { ns_controls_t *controls = *ctrlsp; REQUIRE(ISC_LIST_EMPTY(controls->listeners)); isccc_symtab_destroy(&controls->symtab); isc_mem_put(controls->server->mctx, controls, sizeof(*controls)); *ctrlsp = NULL; }
static void free_namelist (dns_message_t * msg, dns_namelist_t * namelist) { dns_name_t *name; dns_rdataset_t *set; while (!ISC_LIST_EMPTY (*namelist)) { name = ISC_LIST_HEAD (*namelist); ISC_LIST_UNLINK (*namelist, name, link); while (!ISC_LIST_EMPTY (name->list)) { set = ISC_LIST_HEAD (name->list); ISC_LIST_UNLINK (name->list, set, link); dns_message_puttemprdataset (msg, &set); } dns_message_puttempname (msg, &name); } }
void dns_diff_clear(dns_diff_t *diff) { dns_difftuple_t *t; REQUIRE(DNS_DIFF_VALID(diff)); while ((t = ISC_LIST_HEAD(diff->tuples)) != NULL) { ISC_LIST_UNLINK(diff->tuples, t, link); dns_difftuple_free(&t); } ENSURE(ISC_LIST_EMPTY(diff->tuples)); }
static void httpdmgr_destroy(isc_httpdmgr_t *httpdmgr) { isc_mem_t *mctx; isc_httpdurl_t *url; ENTER("httpdmgr_destroy"); LOCK(&httpdmgr->lock); if (!MSHUTTINGDOWN(httpdmgr)) { NOTICE("httpdmgr_destroy not shutting down yet"); UNLOCK(&httpdmgr->lock); return; } /* * If all clients are not shut down, don't do anything yet. */ if (!ISC_LIST_EMPTY(httpdmgr->running)) { NOTICE("httpdmgr_destroy clients still active"); UNLOCK(&httpdmgr->lock); return; } NOTICE("httpdmgr_destroy detaching socket, task, and timermgr"); isc_socket_detach(&httpdmgr->sock); isc_task_detach(&httpdmgr->task); httpdmgr->timermgr = NULL; /* * Clear out the list of all actions we know about. Just free the * memory. */ url = ISC_LIST_HEAD(httpdmgr->urls); while (url != NULL) { isc_mem_free(httpdmgr->mctx, url->url); ISC_LIST_UNLINK(httpdmgr->urls, url, link); isc_mem_put(httpdmgr->mctx, url, sizeof(isc_httpdurl_t)); url = ISC_LIST_HEAD(httpdmgr->urls); } UNLOCK(&httpdmgr->lock); isc_mutex_destroy(&httpdmgr->lock); if (httpdmgr->ondestroy != NULL) (httpdmgr->ondestroy)(httpdmgr->cb_arg); mctx = httpdmgr->mctx; isc_mem_putanddetach(&mctx, httpdmgr, sizeof(isc_httpdmgr_t)); EXIT("httpdmgr_destroy"); }
void cleanup_entropy(isc_entropy_t **ectx) { entropysource_t *source; while (!ISC_LIST_EMPTY(sources)) { source = ISC_LIST_HEAD(sources); ISC_LIST_UNLINK(sources, source, link); isc_entropy_destroysource(&source->source); isc_mem_put(source->mctx, source, sizeof(*source)); } isc_entropy_detach(ectx); }
static isc_result_t rdatasetiter_first(dns_rdatasetiter_t *iterator) { ecdb_rdatasetiter_t *ecdbiterator = (ecdb_rdatasetiter_t *)iterator; dns_ecdbnode_t *ecdbnode = (dns_ecdbnode_t *)iterator->node; REQUIRE(DNS_RDATASETITER_VALID(iterator)); if (ISC_LIST_EMPTY(ecdbnode->rdatasets)) return (ISC_R_NOMORE); ecdbiterator->current = ISC_LIST_HEAD(ecdbnode->rdatasets); return (ISC_R_SUCCESS); }
isc_boolean_t isc__taskmgr_ready(isc_taskmgr_t *manager0) { isc__taskmgr_t *manager = (isc__taskmgr_t *)manager0; #ifdef USE_SHARED_MANAGER if (manager == NULL) manager = taskmgr; #endif if (manager == NULL) return (ISC_FALSE); return (ISC_TF(!ISC_LIST_EMPTY(manager->ready_tasks))); }
void ns_lwresd_shutdown(void) { ns_lwreslistener_t *listener; RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); ns_lwreslistener_detach(&listener); } }
isc_result_t dns_fwdtable_add(dns_fwdtable_t *fwdtable, const dns_name_t *name, isc_sockaddrlist_t *addrs, dns_fwdpolicy_t fwdpolicy) { isc_result_t result; dns_forwarders_t *forwarders; dns_forwarder_t *fwd; isc_sockaddr_t *sa; REQUIRE(VALID_FWDTABLE(fwdtable)); forwarders = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarders_t)); if (forwarders == NULL) return (ISC_R_NOMEMORY); ISC_LIST_INIT(forwarders->fwdrs); for (sa = ISC_LIST_HEAD(*addrs); sa != NULL; sa = ISC_LIST_NEXT(sa, link)) { fwd = isc_mem_get(fwdtable->mctx, sizeof(dns_forwarder_t)); if (fwd == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } fwd->addr = *sa; fwd->dscp = -1; ISC_LINK_INIT(fwd, link); ISC_LIST_APPEND(forwarders->fwdrs, fwd, link); } forwarders->fwdpolicy = fwdpolicy; RWLOCK(&fwdtable->rwlock, isc_rwlocktype_write); result = dns_rbt_addname(fwdtable->table, name, forwarders); RWUNLOCK(&fwdtable->rwlock, isc_rwlocktype_write); if (result != ISC_R_SUCCESS) goto cleanup; return (ISC_R_SUCCESS); cleanup: while (!ISC_LIST_EMPTY(forwarders->fwdrs)) { fwd = ISC_LIST_HEAD(forwarders->fwdrs); ISC_LIST_UNLINK(forwarders->fwdrs, fwd, link); isc_mem_put(fwdtable->mctx, fwd, sizeof(dns_forwarder_t)); } isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t)); return (result); }
static void auto_detach(void *data, void *arg) { dns_forwarders_t *forwarders = data; dns_fwdtable_t *fwdtable = arg; isc_sockaddr_t *sa; UNUSED(arg); while (!ISC_LIST_EMPTY(forwarders->addrs)) { sa = ISC_LIST_HEAD(forwarders->addrs); ISC_LIST_UNLINK(forwarders->addrs, sa, link); isc_mem_put(fwdtable->mctx, sa, sizeof(isc_sockaddr_t)); } isc_mem_put(fwdtable->mctx, forwarders, sizeof(dns_forwarders_t)); }
static isc_result_t listener_startclients(ns_lwreslistener_t *listener) { ns_lwdclientmgr_t *cm; unsigned int i; isc_result_t result = ISC_R_SUCCESS; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_DEBUG(6), "listener_startclients: creating %d " "managers with %d clients each", listener->manager->ntasks, listener->manager->nclients); /* * Create the client managers. */ for (i = 0; i < listener->manager->ntasks; i++) { result = ns_lwdclientmgr_create(listener, listener->manager->nclients, ns_g_taskmgr); if (result != ISC_R_SUCCESS) break; } /* * Ensure that we have created at least one. */ if (ISC_LIST_EMPTY(listener->cmgrs)) return (result); /* * Walk the list of clients and start each one up. */ LOCK(&listener->lock); cm = ISC_LIST_HEAD(listener->cmgrs); while (cm != NULL) { result = ns_lwdclient_startrecv(cm); if (result != ISC_R_SUCCESS) isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "could not start lwres " "client handler: %s", isc_result_totext(result)); cm = ISC_LIST_NEXT(cm, link); } UNLOCK(&listener->lock); return (ISC_R_SUCCESS); }
static void free_listener(controllistener_t *listener) { INSIST(listener->exiting); INSIST(!listener->listening); INSIST(ISC_LIST_EMPTY(listener->connections)); if (listener->sock != NULL) isc_socket_detach(&listener->sock); free_controlkeylist(&listener->keys, listener->mctx); if (listener->acl != NULL) dns_acl_detach(&listener->acl); isc_mem_putanddetach(&listener->mctx, listener, sizeof(*listener)); }
static isc_result_t dispatch_query(struct query_trans *trans) { isc_result_t result; size_t namelen; isc_buffer_t b; char buf[4096]; /* XXX ad hoc constant, but should be enough */ char *cp; REQUIRE(trans != NULL); REQUIRE(trans->inuse == ISC_FALSE); REQUIRE(ISC_LIST_EMPTY(trans->answerlist)); REQUIRE(outstanding_queries < MAX_QUERIES); /* Construct qname */ cp = fgets(buf, sizeof(buf), fp); if (cp == NULL) return (ISC_R_NOMORE); /* zap NL if any */ if ((cp = strchr(buf, '\n')) != NULL) *cp = '\0'; namelen = strlen(buf); isc_buffer_init(&b, buf, namelen); isc_buffer_add(&b, namelen); dns_fixedname_init(&trans->fixedname); trans->qname = dns_fixedname_name(&trans->fixedname); result = dns_name_fromtext(trans->qname, &b, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) goto cleanup; /* Start resolution */ result = dns_client_startresolve(client, trans->qname, dns_rdataclass_in, trans->type, 0, query_task, process_answer, trans, &trans->xid); if (result != ISC_R_SUCCESS) goto cleanup; trans->inuse = ISC_TRUE; outstanding_queries++; return (ISC_R_SUCCESS); cleanup: dns_fixedname_invalidate(&trans->fixedname); return (result); }
static void lwdclientmgr_destroy(ns_lwdclientmgr_t *cm) { ns_lwdclient_t *client; ns_lwreslistener_t *listener; LOCK(&cm->lock); if (!SHUTTINGDOWN(cm)) { UNLOCK(&cm->lock); return; } /* * Run through the idle list and free the clients there. Idle * clients do not have a recv running nor do they have any finds * or similar running. */ client = ISC_LIST_HEAD(cm->idle); while (client != NULL) { ns_lwdclient_log(50, "destroying client %p, manager %p", client, cm); ISC_LIST_UNLINK(cm->idle, client, link); isc_mem_put(cm->mctx, client, sizeof(*client)); client = ISC_LIST_HEAD(cm->idle); } if (!ISC_LIST_EMPTY(cm->running)) { UNLOCK(&cm->lock); return; } UNLOCK(&cm->lock); lwres_context_destroy(&cm->lwctx); cm->view = NULL; isc_socket_detach(&cm->sock); isc_task_detach(&cm->task); DESTROYLOCK(&cm->lock); listener = cm->listener; ns_lwreslistener_unlinkcm(listener, cm); ns_lwdclient_log(50, "destroying manager %p", cm); isc_mem_put(cm->mctx, cm, sizeof(*cm)); ns_lwreslistener_detach(&listener); }
/* * Forget a view's list of policy zones. */ void dns_rpz_view_destroy(dns_view_t *view) { dns_rpz_zone_t *zone; REQUIRE(view != NULL); while (!ISC_LIST_EMPTY(view->rpz_zones)) { zone = ISC_LIST_HEAD(view->rpz_zones); ISC_LIST_UNLINK(view->rpz_zones, zone, link); if (dns_name_dynamic(&zone->origin)) dns_name_free(&zone->origin, view->mctx); if (dns_name_dynamic(&zone->nsdname)) dns_name_free(&zone->nsdname, view->mctx); if (dns_name_dynamic(&zone->cname)) dns_name_free(&zone->cname, view->mctx); isc_mem_put(view->mctx, zone, sizeof(*zone)); } }
static void detach(dns_db_t **dbp) { dns_ecdb_t *ecdb; isc_boolean_t need_destroy = ISC_FALSE; REQUIRE(dbp != NULL); ecdb = (dns_ecdb_t *)*dbp; REQUIRE(VALID_ECDB(ecdb)); LOCK(&ecdb->lock); ecdb->references--; if (ecdb->references == 0 && ISC_LIST_EMPTY(ecdb->nodes)) need_destroy = ISC_TRUE; UNLOCK(&ecdb->lock); if (need_destroy) destroy_ecdb(&ecdb); *dbp = NULL; }
static isc_result_t free_all_sessions(void) { pk11_token_t *token; isc_result_t ret = ISC_R_SUCCESS; isc_result_t oret; for (token = ISC_LIST_HEAD(tokens); token != NULL; token = ISC_LIST_NEXT(token, link)) { oret = free_session_list(&token->sessions); if (oret != ISC_R_SUCCESS) ret = oret; } if (!ISC_LIST_EMPTY(actives)) { ret = ISC_R_ADDRINUSE; oret = free_session_list(&actives); if (oret != ISC_R_SUCCESS) ret = oret; } return (ret); }
static isc_result_t ns_interfacemgr_scan0(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen, isc_boolean_t verbose) { isc_result_t result; isc_boolean_t purge = ISC_TRUE; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); mgr->generation++; /* Increment the generation count. */ result = do_scan(mgr, ext_listen, verbose); if ((result != ISC_R_SUCCESS) && (result != ISC_R_ADDRINUSE)) purge = ISC_FALSE; /* * Now go through the interface list and delete anything that * does not have the current generation number. This is * how we catch interfaces that go away or change their * addresses. */ if (purge) purge_old_interfaces(mgr); /* * Warn if we are not listening on any interface, unless * we're in lwresd-only mode, in which case that is to * be expected. */ if (ext_listen == NULL && ISC_LIST_EMPTY(mgr->interfaces) && ! ns_g_lwresdonly) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_WARNING, "not listening on any interfaces"); } return (result); }
static isc_result_t free_session_list(pk11_sessionlist_t *slist) { pk11_session_t *sp; CK_RV rv; isc_result_t ret; ret = ISC_R_SUCCESS; LOCK(&sessionlock); while (!ISC_LIST_EMPTY(*slist)) { sp = ISC_LIST_HEAD(*slist); UNLOCK(&sessionlock); if (sp->session != CK_INVALID_HANDLE) { rv = pkcs_C_CloseSession(sp->session); if (rv != CKR_OK) ret = DST_R_CRYPTOFAILURE; } LOCK(&sessionlock); ISC_LIST_UNLINK(*slist, sp, link); pk11_mem_put(sp, sizeof(*sp)); } UNLOCK(&sessionlock); return (ret); }
void isc_taskmgr_destroy(isc_taskmgr_t **managerp) { isc_taskmgr_t *manager; isc_task_t *task; unsigned int i; /* * Destroy '*managerp'. */ REQUIRE(managerp != NULL); manager = *managerp; REQUIRE(VALID_MANAGER(manager)); #ifndef ISC_PLATFORM_USETHREADS UNUSED(i); if (manager->refs > 1) { manager->refs--; *managerp = NULL; return; } #endif /* ISC_PLATFORM_USETHREADS */ XTHREADTRACE("isc_taskmgr_destroy"); /* * Only one non-worker thread may ever call this routine. * If a worker thread wants to initiate shutdown of the * task manager, it should ask some non-worker thread to call * isc_taskmgr_destroy(), e.g. by signalling a condition variable * that the startup thread is sleeping on. */ /* * Unlike elsewhere, we're going to hold this lock a long time. * We need to do so, because otherwise the list of tasks could * change while we were traversing it. * * This is also the only function where we will hold both the * task manager lock and a task lock at the same time. */ LOCK(&manager->lock); /* * Make sure we only get called once. */ INSIST(!manager->exiting); manager->exiting = ISC_TRUE; /* * Post shutdown event(s) to every task (if they haven't already been * posted). */ for (task = HEAD(manager->tasks); task != NULL; task = NEXT(task, link)) { LOCK(&task->lock); if (task_shutdown(task)) ENQUEUE(manager->ready_tasks, task, ready_link); UNLOCK(&task->lock); } #ifdef ISC_PLATFORM_USETHREADS /* * Wake up any sleeping workers. This ensures we get work done if * there's work left to do, and if there are already no tasks left * it will cause the workers to see manager->exiting. */ BROADCAST(&manager->work_available); UNLOCK(&manager->lock); /* * Wait for all the worker threads to exit. */ for (i = 0; i < manager->workers; i++) (void)isc_thread_join(manager->threads[i], NULL); #else /* ISC_PLATFORM_USETHREADS */ /* * Dispatch the shutdown events. */ UNLOCK(&manager->lock); while (isc__taskmgr_ready()) (void)isc__taskmgr_dispatch(); if (!ISC_LIST_EMPTY(manager->tasks)) isc_mem_printallactive(stderr); INSIST(ISC_LIST_EMPTY(manager->tasks)); #endif /* ISC_PLATFORM_USETHREADS */ manager_free(manager); *managerp = NULL; }
isc_result_t ns_lwresd_configure(isc_mem_t *mctx, const cfg_obj_t *config) { const cfg_obj_t *lwreslist = NULL; const cfg_obj_t *lwres = NULL; const cfg_obj_t *listenerslist = NULL; const cfg_listelt_t *element = NULL; ns_lwreslistener_t *listener; ns_lwreslistenerlist_t newlisteners; isc_result_t result; char socktext[ISC_SOCKADDR_FORMATSIZE]; isc_sockaddr_t *addrs = NULL; ns_lwresd_t *lwresd = NULL; isc_uint32_t count = 0; REQUIRE(mctx != NULL); REQUIRE(config != NULL); RUNTIME_CHECK(isc_once_do(&once, initialize_mutex) == ISC_R_SUCCESS); ISC_LIST_INIT(newlisteners); result = cfg_map_get(config, "lwres", &lwreslist); if (result != ISC_R_SUCCESS) return (ISC_R_SUCCESS); LOCK(&listeners_lock); /* * Run through the new lwres address list, noting sockets that * are already being listened on and moving them to the new list. * * Identifying duplicates addr/port combinations is left to either * the underlying config code, or to the bind attempt getting an * address-in-use error. */ for (element = cfg_list_first(lwreslist); element != NULL; element = cfg_list_next(element)) { in_port_t port; lwres = cfg_listelt_value(element); CHECK(ns_lwdmanager_create(mctx, lwres, &lwresd)); port = lwresd_g_listenport; if (port == 0) port = LWRES_UDP_PORT; listenerslist = NULL; (void)cfg_map_get(lwres, "listen-on", &listenerslist); if (listenerslist == NULL) { struct in_addr localhost; isc_sockaddr_t address; localhost.s_addr = htonl(INADDR_LOOPBACK); isc_sockaddr_fromin(&address, &localhost, port); CHECK(configure_listener(&address, lwresd, mctx, &newlisteners)); } else { isc_uint32_t i; CHECK(ns_config_getiplist(config, listenerslist, port, mctx, &addrs, &count)); for (i = 0; i < count; i++) CHECK(configure_listener(&addrs[i], lwresd, mctx, &newlisteners)); ns_config_putiplist(mctx, &addrs, count); } ns_lwdmanager_detach(&lwresd); } /* * Shutdown everything on the listeners list, and remove them from * the list. Then put all of the new listeners on it. */ while (!ISC_LIST_EMPTY(listeners)) { listener = ISC_LIST_HEAD(listeners); ISC_LIST_UNLINK(listeners, listener, link); isc_sockaddr_format(&listener->address, socktext, sizeof(socktext)); listener_shutdown(listener); ns_lwreslistener_detach(&listener); isc_log_write(ns_g_lctx, ISC_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_NOTICE, "lwres no longer listening on %s", socktext); } cleanup: ISC_LIST_APPENDLIST(listeners, newlisteners, link); if (addrs != NULL) ns_config_putiplist(mctx, &addrs, count); if (lwresd != NULL) ns_lwdmanager_detach(&lwresd); UNLOCK(&listeners_lock); return (result); }
void ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) { isc_result_t result; dns_name_t *question_name; dns_rdataset_t *question_rdataset; dns_zone_t *zone = NULL, *raw = NULL, *mayberaw; dns_db_t *db = NULL; dns_dbversion_t *ver = NULL; dns_rdataclass_t question_class; rrstream_t *soa_stream = NULL; rrstream_t *data_stream = NULL; rrstream_t *stream = NULL; dns_difftuple_t *current_soa_tuple = NULL; dns_name_t *soa_name; dns_rdataset_t *soa_rdataset; dns_rdata_t soa_rdata = DNS_RDATA_INIT; isc_boolean_t have_soa = ISC_FALSE; const char *mnemonic = NULL; isc_mem_t *mctx = client->mctx; dns_message_t *request = client->message; xfrout_ctx_t *xfr = NULL; isc_quota_t *quota = NULL; dns_transfer_format_t format = client->view->transfer_format; isc_netaddr_t na; dns_peer_t *peer = NULL; isc_buffer_t *tsigbuf = NULL; char *journalfile; char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")]; char keyname[DNS_NAME_FORMATSIZE]; isc_boolean_t is_poll = ISC_FALSE; isc_boolean_t is_dlz = ISC_FALSE; isc_boolean_t is_ixfr = ISC_FALSE; isc_uint32_t begin_serial = 0, current_serial; switch (reqtype) { case dns_rdatatype_axfr: mnemonic = "AXFR"; break; case dns_rdatatype_ixfr: mnemonic = "IXFR"; break; default: INSIST(0); break; } ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(6), "%s request", mnemonic); /* * Apply quota. */ result = isc_quota_attach(&ns_g_server->xfroutquota, "a); if (result != ISC_R_SUCCESS) { isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING, "%s request denied: %s", mnemonic, isc_result_totext(result)); goto failure; } /* * Interpret the question section. */ result = dns_message_firstname(request, DNS_SECTION_QUESTION); INSIST(result == ISC_R_SUCCESS); /* * The question section must contain exactly one question, and * it must be for AXFR/IXFR as appropriate. */ question_name = NULL; dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name); question_rdataset = ISC_LIST_HEAD(question_name->list); question_class = question_rdataset->rdclass; INSIST(question_rdataset->type == reqtype); if (ISC_LIST_NEXT(question_rdataset, link) != NULL) FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_message_nextname(request, DNS_SECTION_QUESTION); if (result != ISC_R_NOMORE) FAILC(DNS_R_FORMERR, "multiple questions"); result = dns_zt_find(client->view->zonetable, question_name, 0, NULL, &zone); if (result != ISC_R_SUCCESS) { /* * Normal zone table does not have a match. * Try the DLZ database */ // Temporary: only searching the first DLZ database if (! ISC_LIST_EMPTY(client->view->dlz_searched)) { result = dns_dlzallowzonexfr(client->view, question_name, &client->peeraddr, &db); pfilter_notify(result, client, "zonexfr"); if (result == ISC_R_NOPERM) { char _buf1[DNS_NAME_FORMATSIZE]; char _buf2[DNS_RDATACLASS_FORMATSIZE]; result = DNS_R_REFUSED; dns_name_format(question_name, _buf1, sizeof(_buf1)); dns_rdataclass_format(question_class, _buf2, sizeof(_buf2)); ns_client_log(client, DNS_LOGCATEGORY_SECURITY, NS_LOGMODULE_XFER_OUT, ISC_LOG_ERROR, "zone transfer '%s/%s' denied", _buf1, _buf2); goto failure; } if (result != ISC_R_SUCCESS) FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); is_dlz = ISC_TRUE; } else { /* * not DLZ and not in normal zone table, we are * not authoritative */ FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); } } else { /* zone table has a match */ switch(dns_zone_gettype(zone)) { /* Master and slave zones are OK for transfer. */ case dns_zone_master: case dns_zone_slave: case dns_zone_dlz: break; default: FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class); } CHECK(dns_zone_getdb(zone, &db)); dns_db_currentversion(db, &ver); } xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), "%s question section OK", mnemonic); /* * Check the authority section. Look for a SOA record with * the same name and class as the question. */ for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY); result == ISC_R_SUCCESS; result = dns_message_nextname(request, DNS_SECTION_AUTHORITY)) { soa_name = NULL; dns_message_currentname(request, DNS_SECTION_AUTHORITY, &soa_name); /* * Ignore data whose owner name is not the zone apex. */ if (! dns_name_equal(soa_name, question_name)) continue; for (soa_rdataset = ISC_LIST_HEAD(soa_name->list); soa_rdataset != NULL; soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link)) { /* * Ignore non-SOA data. */ if (soa_rdataset->type != dns_rdatatype_soa) continue; if (soa_rdataset->rdclass != question_class) continue; CHECK(dns_rdataset_first(soa_rdataset)); dns_rdataset_current(soa_rdataset, &soa_rdata); result = dns_rdataset_next(soa_rdataset); if (result == ISC_R_SUCCESS) FAILC(DNS_R_FORMERR, "IXFR authority section " "has multiple SOAs"); have_soa = ISC_TRUE; goto got_soa; } } got_soa: if (result != ISC_R_NOMORE) CHECK(result); xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6), "%s authority section OK", mnemonic); /* * If not a DLZ zone, decide whether to allow this transfer. */ if (!is_dlz) { ns_client_aclmsg("zone transfer", question_name, reqtype, client->view->rdclass, msg, sizeof(msg)); CHECK(ns_client_checkacl(client, NULL, msg, dns_zone_getxfracl(zone), ISC_TRUE, ISC_LOG_ERROR)); } /* * AXFR over UDP is not possible. */ if (reqtype == dns_rdatatype_axfr && (client->attributes & NS_CLIENTATTR_TCP) == 0) FAILC(DNS_R_FORMERR, "attempted AXFR over UDP"); /* * Look up the requesting server in the peer table. */ isc_netaddr_fromsockaddr(&na, &client->peeraddr); (void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer); /* * Decide on the transfer format (one-answer or many-answers). */ if (peer != NULL) (void)dns_peer_gettransferformat(peer, &format); /* * Get a dynamically allocated copy of the current SOA. */ if (is_dlz) dns_db_currentversion(db, &ver); CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS, ¤t_soa_tuple)); current_serial = dns_soa_getserial(¤t_soa_tuple->rdata); if (reqtype == dns_rdatatype_ixfr) { isc_boolean_t provide_ixfr; /* * Outgoing IXFR may have been disabled for this peer * or globally. */ provide_ixfr = client->view->provideixfr; if (peer != NULL) (void) dns_peer_getprovideixfr(peer, &provide_ixfr); if (provide_ixfr == ISC_FALSE) goto axfr_fallback; if (! have_soa) FAILC(DNS_R_FORMERR, "IXFR request missing SOA"); begin_serial = dns_soa_getserial(&soa_rdata); /* * RFC1995 says "If an IXFR query with the same or * newer version number than that of the server * is received, it is replied to with a single SOA * record of the server's current version, just as * in AXFR". The claim about AXFR is incorrect, * but other than that, we do as the RFC says. * * Sending a single SOA record is also how we refuse * IXFR over UDP (currently, we always do). */ if (DNS_SERIAL_GE(begin_serial, current_serial) || (client->attributes & NS_CLIENTATTR_TCP) == 0) { CHECK(soa_rrstream_create(mctx, db, ver, &stream)); is_poll = ISC_TRUE; goto have_stream; } journalfile = is_dlz ? NULL : dns_zone_getjournal(zone); if (journalfile != NULL) result = ixfr_rrstream_create(mctx, journalfile, begin_serial, current_serial, &data_stream); else result = ISC_R_NOTFOUND; if (result == ISC_R_NOTFOUND || result == ISC_R_RANGE) { xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(4), "IXFR version not in journal, " "falling back to AXFR"); mnemonic = "AXFR-style IXFR"; goto axfr_fallback; } CHECK(result); is_ixfr = ISC_TRUE; } else { axfr_fallback: CHECK(axfr_rrstream_create(mctx, db, ver, &data_stream)); } /* * Bracket the data stream with SOAs. */ CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream)); CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream, &stream)); soa_stream = NULL; data_stream = NULL; have_stream: CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf)); /* * Create the xfrout context object. This transfers the ownership * of "stream", "db", "ver", and "quota" to the xfrout context object. */ if (is_dlz) CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, question_class, zone, db, ver, quota, stream, dns_message_gettsigkey(request), tsigbuf, 3600, 3600, (format == dns_many_answers) ? ISC_TRUE : ISC_FALSE, &xfr)); else CHECK(xfrout_ctx_create(mctx, client, request->id, question_name, reqtype, question_class, zone, db, ver, quota, stream, dns_message_gettsigkey(request), tsigbuf, dns_zone_getmaxxfrout(zone), dns_zone_getidleout(zone), (format == dns_many_answers) ? ISC_TRUE : ISC_FALSE, &xfr)); xfr->mnemonic = mnemonic; stream = NULL; quota = NULL; CHECK(xfr->stream->methods->first(xfr->stream)); if (xfr->tsigkey != NULL) dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname)); else keyname[0] = '\0'; if (is_poll) xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s", (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname); else if (is_ixfr) xfrout_log1(client, question_name, question_class, ISC_LOG_INFO, "%s started%s%s (serial %u -> %u)", mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, begin_serial, current_serial); else xfrout_log1(client, question_name, question_class, ISC_LOG_INFO, "%s started%s%s (serial %u)", mnemonic, (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname, current_serial); if (zone != NULL) { dns_zone_getraw(zone, &raw); mayberaw = (raw != NULL) ? raw : zone; if ((client->attributes & NS_CLIENTATTR_WANTEXPIRE) != 0 && dns_zone_gettype(mayberaw) == dns_zone_slave) { isc_time_t expiretime; isc_uint32_t secs; dns_zone_getexpiretime(zone, &expiretime); secs = isc_time_seconds(&expiretime); if (secs >= client->now && result == ISC_R_SUCCESS) { client->attributes |= NS_CLIENTATTR_HAVEEXPIRE; client->expire = secs - client->now; } } if (raw != NULL) dns_zone_detach(&raw); } /* * Hand the context over to sendstream(). Set xfr to NULL; * sendstream() is responsible for either passing the * context on to a later event handler or destroying it. */ sendstream(xfr); xfr = NULL; result = ISC_R_SUCCESS; failure: if (result == DNS_R_REFUSED) inc_stats(zone, dns_nsstatscounter_xfrrej); if (quota != NULL) isc_quota_detach("a); if (current_soa_tuple != NULL) dns_difftuple_free(¤t_soa_tuple); if (stream != NULL) stream->methods->destroy(&stream); if (soa_stream != NULL) soa_stream->methods->destroy(&soa_stream); if (data_stream != NULL) data_stream->methods->destroy(&data_stream); if (ver != NULL) dns_db_closeversion(db, &ver, ISC_FALSE); if (db != NULL) dns_db_detach(&db); if (zone != NULL) dns_zone_detach(&zone); /* XXX kludge */ if (xfr != NULL) { xfrout_fail(xfr, result, "setting up zone transfer"); } else if (result != ISC_R_SUCCESS) { ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT, ISC_LOG_DEBUG(3), "zone transfer setup failed"); ns_client_error(client, result); } }
static isc_result_t ddns_update_ptr (struct data_string *ddns_fwd_name, struct data_string *ddns_rev_name, unsigned long ttl) { ns_updque updqueue; ns_updrec *updrec; isc_result_t result = ISC_R_UNEXPECTED; /* * The DHCP server submits a DNS query which deletes all of the PTR RRs * associated with the lease IP address, and adds a PTR RR whose data * is the client's (possibly disambiguated) host name. The server also * adds a DHCID RR specified in Section 4.3. * -- "Interaction between DHCP and DNS" */ ISC_LIST_INIT (updqueue); /* * Delete all PTR RRs. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_rev_name -> data, C_IN, T_PTR, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)0; updrec -> r_size = 0; updrec -> r_opcode = DELETE; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Add PTR RR. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_rev_name -> data, C_IN, T_PTR, ttl); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = ddns_fwd_name -> data; updrec -> r_size = ddns_fwd_name -> len; updrec -> r_opcode = ADD; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Attempt to perform the update. */ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); #if defined (DEBUG) print_dns_status ((int)result, &updqueue); #endif if (result == ISC_R_SUCCESS) { log_info ("added reverse map from %.*s to %.*s", (int)ddns_rev_name -> len, (const char *)ddns_rev_name -> data, (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data); } else { log_error ("unable to add reverse map from %.*s to %.*s: %s", (int)ddns_rev_name -> len, (const char *)ddns_rev_name -> data, (int)ddns_fwd_name -> len, (const char *)ddns_fwd_name -> data, isc_result_totext (result)); } /* Fall through. */ error: while (!ISC_LIST_EMPTY (updqueue)) { if((updqueue).head){ updrec = ISC_LIST_HEAD (updqueue); ISC_LIST_UNLINK (updqueue, updrec, r_link); minires_freeupdrec (updrec); } } return result; }
static isc_result_t ddns_remove_ptr (struct data_string *ddns_rev_name) { ns_updque updqueue; ns_updrec *updrec; isc_result_t result; /* * When a lease expires or a DHCP client issues a DHCPRELEASE request, * the DHCP server SHOULD delete the PTR RR that matches the DHCP * binding, if one was successfully added. The server's update query * SHOULD assert that the name in the PTR record matches the name of * the client whose lease has expired or been released. * -- "Interaction between DHCP and DNS" */ ISC_LIST_INIT (updqueue); /* * Delete the PTR RRset for the leased address. */ updrec = minires_mkupdrec (S_UPDATE, (const char *)ddns_rev_name -> data, C_IN, T_PTR, 0); if (!updrec) { result = ISC_R_NOMEMORY; goto error; } updrec -> r_data = (unsigned char *)0; updrec -> r_size = 0; updrec -> r_opcode = DELETE; ISC_LIST_APPEND (updqueue, updrec, r_link); /* * Attempt to perform the update. */ result = minires_nupdate (&resolver_state, ISC_LIST_HEAD (updqueue)); #if defined (DEBUG) print_dns_status ((int)result, &updqueue); #endif if (result == ISC_R_SUCCESS) { log_info ("removed reverse map on %.*s", (int)ddns_rev_name -> len, (const char *)ddns_rev_name -> data); } else { if (result != ISC_R_NXRRSET && result != ISC_R_NXDOMAIN) log_error ("can't remove reverse map on %.*s: %s", (int)ddns_rev_name -> len, (const char *)ddns_rev_name -> data, isc_result_totext (result)); } /* Not there is success. */ if (result == ISC_R_NXRRSET || result == ISC_R_NXDOMAIN) result = ISC_R_SUCCESS; /* Fall through. */ error: while (!ISC_LIST_EMPTY (updqueue)) { if((updqueue).head){ updrec = ISC_LIST_HEAD (updqueue); ISC_LIST_UNLINK (updqueue, updrec, r_link); minires_freeupdrec (updrec); } } return result; }
isc_boolean_t isc__taskmgr_ready(void) { if (taskmgr == NULL) return (ISC_FALSE); return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks))); }
static void resolve_ns(isc_task_t *task, isc_event_t *event) { struct probe_trans *trans = event->ev_arg; dns_clientresevent_t *rev = (dns_clientresevent_t *)event; dns_name_t *name; dns_rdataset_t *rdataset; isc_result_t result = ISC_R_SUCCESS; dns_rdata_t rdata = DNS_RDATA_INIT; struct probe_ns *pns; REQUIRE(task == probe_task); REQUIRE(trans->inuse == ISC_TRUE); INSIST(outstanding_probes > 0); for (name = ISC_LIST_HEAD(rev->answerlist); name != NULL; name = ISC_LIST_NEXT(name, link)) { for (rdataset = ISC_LIST_HEAD(name->list); rdataset != NULL; rdataset = ISC_LIST_NEXT(rdataset, link)) { (void)print_rdataset(rdataset, name); if (rdataset->type != dns_rdatatype_ns) continue; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_ns_t ns; dns_rdataset_current(rdataset, &rdata); /* * Extract the name from the NS record. */ result = dns_rdata_tostruct(&rdata, &ns, NULL); if (result != ISC_R_SUCCESS) continue; pns = isc_mem_get(mctx, sizeof(*pns)); if (pns == NULL) { fprintf(stderr, "resolve_ns: mem_get failed"); result = ISC_R_NOMEMORY; POST(result); /* * XXX: should we continue with the * available servers anyway? */ goto cleanup; } dns_fixedname_init(&pns->fixedname); pns->name = dns_fixedname_name(&pns->fixedname); ISC_LINK_INIT(pns, link); ISC_LIST_APPEND(trans->nslist, pns, link); ISC_LIST_INIT(pns->servers); dns_name_copy(&ns.name, pns->name, NULL); dns_rdata_reset(&rdata); dns_rdata_freestruct(&ns); } } } cleanup: dns_client_freeresanswer(client, &rev->answerlist); dns_client_destroyrestrans(&trans->resid); isc_event_free(&event); if (!ISC_LIST_EMPTY(trans->nslist)) { /* Go get addresses of NSes */ trans->current_ns = ISC_LIST_HEAD(trans->nslist); result = fetch_nsaddress(trans); } else result = ISC_R_FAILURE; if (result == ISC_R_SUCCESS) return; reset_probe(trans); }
static isc_result_t process_dhtkey(dns_message_t *msg, dns_name_t *signer, dns_name_t *name, dns_rdata_tkey_t *tkeyin, dns_tkeyctx_t *tctx, dns_rdata_tkey_t *tkeyout, dns_tsig_keyring_t *ring, dns_namelist_t *namelist) { isc_result_t result = ISC_R_SUCCESS; dns_name_t *keyname, ourname; dns_rdataset_t *keyset = NULL; dns_rdata_t keyrdata = DNS_RDATA_INIT, ourkeyrdata = DNS_RDATA_INIT; isc_boolean_t found_key = ISC_FALSE, found_incompatible = ISC_FALSE; dst_key_t *pubkey = NULL; isc_buffer_t ourkeybuf, *shared = NULL; isc_region_t r, r2, ourkeyr; unsigned char keydata[DST_KEY_MAXSIZE]; unsigned int sharedsize; isc_buffer_t secret; unsigned char *randomdata = NULL, secretdata[256]; dns_ttl_t ttl = 0; if (tctx->dhkey == NULL) { tkey_log("process_dhtkey: tkey-dhkey not defined"); tkeyout->error = dns_tsigerror_badalg; return (DNS_R_REFUSED); } if (!dns_name_equal(&tkeyin->algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey_log("process_dhtkey: algorithms other than " "hmac-md5 are not supported"); tkeyout->error = dns_tsigerror_badalg; return (ISC_R_SUCCESS); } /* * Look for a DH KEY record that will work with ours. */ for (result = dns_message_firstname(msg, DNS_SECTION_ADDITIONAL); result == ISC_R_SUCCESS && !found_key; result = dns_message_nextname(msg, DNS_SECTION_ADDITIONAL)) { keyname = NULL; dns_message_currentname(msg, DNS_SECTION_ADDITIONAL, &keyname); keyset = NULL; result = dns_message_findtype(keyname, dns_rdatatype_key, 0, &keyset); if (result != ISC_R_SUCCESS) continue; for (result = dns_rdataset_first(keyset); result == ISC_R_SUCCESS && !found_key; result = dns_rdataset_next(keyset)) { dns_rdataset_current(keyset, &keyrdata); pubkey = NULL; result = dns_dnssec_keyfromrdata(keyname, &keyrdata, msg->mctx, &pubkey); if (result != ISC_R_SUCCESS) { dns_rdata_reset(&keyrdata); continue; } if (dst_key_alg(pubkey) == DNS_KEYALG_DH) { if (dst_key_paramcompare(pubkey, tctx->dhkey)) { found_key = ISC_TRUE; ttl = keyset->ttl; break; } else found_incompatible = ISC_TRUE; } dst_key_free(&pubkey); dns_rdata_reset(&keyrdata); } } if (!found_key) { if (found_incompatible) { tkey_log("process_dhtkey: found an incompatible key"); tkeyout->error = dns_tsigerror_badkey; return (ISC_R_SUCCESS); } else { tkey_log("process_dhtkey: failed to find a key"); return (DNS_R_FORMERR); } } RETERR(add_rdata_to_list(msg, keyname, &keyrdata, ttl, namelist)); isc_buffer_init(&ourkeybuf, keydata, sizeof(keydata)); RETERR(dst_key_todns(tctx->dhkey, &ourkeybuf)); isc_buffer_usedregion(&ourkeybuf, &ourkeyr); dns_rdata_fromregion(&ourkeyrdata, dns_rdataclass_any, dns_rdatatype_key, &ourkeyr); dns_name_init(&ourname, NULL); dns_name_clone(dst_key_name(tctx->dhkey), &ourname); /* * XXXBEW The TTL should be obtained from the database, if it exists. */ RETERR(add_rdata_to_list(msg, &ourname, &ourkeyrdata, 0, namelist)); RETERR(dst_key_secretsize(tctx->dhkey, &sharedsize)); RETERR(isc_buffer_allocate(msg->mctx, &shared, sharedsize)); result = dst_key_computesecret(pubkey, tctx->dhkey, shared); if (result != ISC_R_SUCCESS) { tkey_log("process_dhtkey: failed to compute shared secret: %s", isc_result_totext(result)); goto failure; } dst_key_free(&pubkey); isc_buffer_init(&secret, secretdata, sizeof(secretdata)); randomdata = isc_mem_get(tkeyout->mctx, TKEY_RANDOM_AMOUNT); if (randomdata == NULL) goto failure; result = dst__entropy_getdata(randomdata, TKEY_RANDOM_AMOUNT, ISC_FALSE); if (result != ISC_R_SUCCESS) { tkey_log("process_dhtkey: failed to obtain entropy: %s", isc_result_totext(result)); goto failure; } r.base = randomdata; r.length = TKEY_RANDOM_AMOUNT; r2.base = tkeyin->key; r2.length = tkeyin->keylen; RETERR(compute_secret(shared, &r2, &r, &secret)); isc_buffer_free(&shared); RETERR(dns_tsigkey_create(name, &tkeyin->algorithm, isc_buffer_base(&secret), isc_buffer_usedlength(&secret), ISC_TRUE, signer, tkeyin->inception, tkeyin->expire, ring->mctx, ring, NULL)); /* This key is good for a long time */ tkeyout->inception = tkeyin->inception; tkeyout->expire = tkeyin->expire; tkeyout->key = randomdata; tkeyout->keylen = TKEY_RANDOM_AMOUNT; return (ISC_R_SUCCESS); failure: if (!ISC_LIST_EMPTY(*namelist)) free_namelist(msg, namelist); if (shared != NULL) isc_buffer_free(&shared); if (pubkey != NULL) dst_key_free(&pubkey); if (randomdata != NULL) isc_mem_put(tkeyout->mctx, randomdata, TKEY_RANDOM_AMOUNT); return (result); }