void irs_context_destroy(irs_context_t **contextp) { irs_context_t *context; REQUIRE(contextp != NULL); context = *contextp; REQUIRE(IRS_CONTEXT_VALID(context)); isc_task_detach(&context->task); irs_dnsconf_destroy(&context->dnsconf); irs_resconf_destroy(&context->resconf); dns_client_destroy(&context->dnsclient); ctxs_destroy(NULL, &context->actx, &context->taskmgr, &context->socketmgr, &context->timermgr); context->magic = 0; isc_mem_putanddetach(&context->mctx, context, sizeof(*context)); *contextp = NULL; #ifndef ISC_PLATFORM_USETHREADS irs_g_context = NULL; #else (void)isc_thread_key_setspecific(irs_context_key, NULL); #endif }
/*% parses a file and fills in the data structure. */ isc_result_t irs_resconf_load(isc_mem_t *mctx, const char *filename, irs_resconf_t **confp) { FILE *fp = NULL; char word[256]; isc_result_t rval, ret = ISC_R_SUCCESS; irs_resconf_t *conf; int i, stopchar; REQUIRE(mctx != NULL); REQUIRE(filename != NULL); REQUIRE(strlen(filename) > 0U); REQUIRE(confp != NULL && *confp == NULL); conf = isc_mem_get(mctx, sizeof(*conf)); if (conf == NULL) return (ISC_R_NOMEMORY); conf->mctx = mctx; ISC_LIST_INIT(conf->nameservers); conf->numns = 0; conf->domainname = NULL; conf->searchnxt = 0; conf->resdebug = 0; conf->ndots = 1; for (i = 0; i < RESCONFMAXSEARCH; i++) conf->search[i] = NULL; errno = 0; if ((fp = fopen(filename, "r")) != NULL) { do { stopchar = getword(fp, word, sizeof(word)); if (stopchar == EOF) { rval = ISC_R_SUCCESS; POST(rval); break; } if (strlen(word) == 0U) rval = ISC_R_SUCCESS; else if (strcmp(word, "nameserver") == 0) rval = resconf_parsenameserver(conf, fp); else if (strcmp(word, "domain") == 0) rval = resconf_parsedomain(conf, fp); else if (strcmp(word, "search") == 0) rval = resconf_parsesearch(conf, fp); else if (strcmp(word, "sortlist") == 0) rval = resconf_parsesortlist(conf, fp); else if (strcmp(word, "options") == 0) rval = resconf_parseoption(conf, fp); else { /* unrecognised word. Ignore entire line */ rval = ISC_R_SUCCESS; stopchar = eatline(fp); if (stopchar == EOF) { break; } } if (ret == ISC_R_SUCCESS && rval != ISC_R_SUCCESS) ret = rval; } while (1); fclose(fp); } else { switch (errno) { case ENOENT: break; default: isc_mem_put(mctx, conf, sizeof(*conf)); return (ISC_R_INVALIDFILE); } } /* If we don't find a nameserver fall back to localhost */ if (conf->numns == 0) { INSIST(ISC_LIST_EMPTY(conf->nameservers)); /* XXX: should we catch errors? */ (void)add_server(conf->mctx, "127.0.0.1", &conf->nameservers); (void)add_server(conf->mctx, "::1", &conf->nameservers); } /* * Construct unified search list from domain or configured * search list */ ISC_LIST_INIT(conf->searchlist); if (conf->domainname != NULL) { ret = add_search(conf, conf->domainname); } else if (conf->searchnxt > 0) { for (i = 0; i < conf->searchnxt; i++) { ret = add_search(conf, conf->search[i]); if (ret != ISC_R_SUCCESS) break; } } conf->magic = IRS_RESCONF_MAGIC; if (ret != ISC_R_SUCCESS) irs_resconf_destroy(&conf); else { if (fp == NULL) ret = ISC_R_FILENOTFOUND; *confp = conf; } return (ret); }
isc_result_t irs_context_create(irs_context_t **contextp) { isc_result_t result; irs_context_t *context; isc_appctx_t *actx = NULL; isc_mem_t *mctx = NULL; isc_taskmgr_t *taskmgr = NULL; isc_socketmgr_t *socketmgr = NULL; isc_timermgr_t *timermgr = NULL; dns_client_t *client = NULL; isc_sockaddrlist_t *nameservers; irs_dnsconf_dnskeylist_t *trustedkeys; irs_dnsconf_dnskey_t *trustedkey; isc_lib_register(); result = dns_lib_init(); if (result != ISC_R_SUCCESS) return (result); result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); if (result != ISC_R_SUCCESS) return (result); result = isc_app_ctxstart(actx); if (result != ISC_R_SUCCESS) { ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); return (result); } context = isc_mem_get(mctx, sizeof(*context)); if (context == NULL) { ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); return (ISC_R_NOMEMORY); } context->mctx = mctx; context->actx = actx; context->taskmgr = taskmgr; context->socketmgr = socketmgr; context->timermgr = timermgr; context->resconf = NULL; context->dnsconf = NULL; context->task = NULL; result = isc_task_create(taskmgr, 0, &context->task); if (result != ISC_R_SUCCESS) goto fail; /* Create a DNS client object */ result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, 0, &client); if (result != ISC_R_SUCCESS) goto fail; context->dnsclient = client; /* Read resolver configuration file */ result = irs_resconf_load(mctx, RESOLV_CONF, &context->resconf); if (result != ISC_R_SUCCESS) goto fail; /* Set nameservers */ nameservers = irs_resconf_getnameservers(context->resconf); result = dns_client_setservers(client, dns_rdataclass_in, NULL, nameservers); if (result != ISC_R_SUCCESS) goto fail; /* Read advanced DNS configuration (if any) */ result = irs_dnsconf_load(mctx, DNS_CONF, &context->dnsconf); if (result != ISC_R_SUCCESS) goto fail; trustedkeys = irs_dnsconf_gettrustedkeys(context->dnsconf); for (trustedkey = ISC_LIST_HEAD(*trustedkeys); trustedkey != NULL; trustedkey = ISC_LIST_NEXT(trustedkey, link)) { result = dns_client_addtrustedkey(client, dns_rdataclass_in, trustedkey->keyname, trustedkey->keydatabuf); if (result != ISC_R_SUCCESS) goto fail; } context->magic = IRS_CONTEXT_MAGIC; *contextp = context; return (ISC_R_SUCCESS); fail: if (context->task != NULL) isc_task_detach(&context->task); if (context->resconf != NULL) irs_resconf_destroy(&context->resconf); if (context->dnsconf != NULL) irs_dnsconf_destroy(&context->dnsconf); if (client != NULL) dns_client_destroy(&client); ctxs_destroy(NULL, &actx, &taskmgr, &socketmgr, &timermgr); isc_mem_putanddetach(&mctx, context, sizeof(*context)); return (result); }
static isc_result_t findserver(dns_client_t *client) { isc_result_t result; irs_resconf_t *resconf = NULL; isc_sockaddrlist_t *nameservers; isc_sockaddr_t *sa, *next; isc_uint32_t destport; result = parse_uint(&destport, port, 0xffff, "port"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); result = irs_resconf_load(mctx, "/etc/resolv.conf", &resconf); if (result != ISC_R_SUCCESS && result != ISC_R_FILENOTFOUND) { delv_log(ISC_LOG_ERROR, "irs_resconf_load: %s", isc_result_totext(result)); goto cleanup; } /* Get nameservers from resolv.conf */ nameservers = irs_resconf_getnameservers(resconf); for (sa = ISC_LIST_HEAD(*nameservers); sa != NULL; sa = next) { next = ISC_LIST_NEXT(sa, link); /* Set destination port */ if (sa->type.sa.sa_family == AF_INET && use_ipv4) { sa->type.sin.sin_port = htons(destport); continue; } if (sa->type.sa.sa_family == AF_INET6 && use_ipv6) { sa->type.sin6.sin6_port = htons(destport); continue; } /* Incompatible protocol family */ ISC_LIST_UNLINK(*nameservers, sa, link); isc_mem_put(mctx, sa, sizeof(*sa)); } /* None found, use localhost */ if (ISC_LIST_EMPTY(*nameservers)) { if (use_ipv4) { struct in_addr localhost; localhost.s_addr = htonl(INADDR_LOOPBACK); sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_sockaddr_fromin(sa, &localhost, destport); ISC_LINK_INIT(sa, link); ISC_LIST_APPEND(*nameservers, sa, link); } if (use_ipv6) { sa = isc_mem_get(mctx, sizeof(*sa)); if (sa == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } isc_sockaddr_fromin6(sa, &in6addr_loopback, destport); ISC_LINK_INIT(sa, link); ISC_LIST_APPEND(*nameservers, sa, link); } } result = dns_client_setservers(client, dns_rdataclass_in, NULL, nameservers); if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "dns_client_setservers: %s", isc_result_totext(result)); cleanup: if (resconf != NULL) irs_resconf_destroy(&resconf); return (result); }