void setup_entropy(isc_mem_t *mctx, const char *randomfile, isc_entropy_t **ectx) { isc_result_t result; isc_entropysource_t *source = NULL; entropysource_t *elt; int usekeyboard = ISC_ENTROPY_KEYBOARDMAYBE; REQUIRE(ectx != NULL); if (*ectx == NULL) { result = isc_entropy_create(mctx, ectx); if (result != ISC_R_SUCCESS) fatal("could not create entropy object"); ISC_LIST_INIT(sources); } if (randomfile != NULL && strcmp(randomfile, "keyboard") == 0) { usekeyboard = ISC_ENTROPY_KEYBOARDYES; randomfile = NULL; } result = isc_entropy_usebestsource(*ectx, &source, randomfile, usekeyboard); if (result != ISC_R_SUCCESS) fatal("could not initialize entropy source: %s", isc_result_totext(result)); if (source != NULL) { elt = isc_mem_get(mctx, sizeof(*elt)); if (elt == NULL) fatal("out of memory"); elt->source = source; elt->mctx = mctx; ISC_LINK_INIT(elt, link); ISC_LIST_APPEND(sources, elt, link); } }
static inline isc_result_t tostruct_in_nsap_ptr(ARGS_TOSTRUCT) { isc_region_t region; dns_rdata_in_nsap_ptr_t *nsap_ptr = target; dns_name_t name; REQUIRE(rdata->type == dns_rdatatype_nsap_ptr); REQUIRE(rdata->rdclass == dns_rdataclass_in); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); nsap_ptr->common.rdclass = rdata->rdclass; nsap_ptr->common.rdtype = rdata->type; ISC_LINK_INIT(&nsap_ptr->common, link); dns_name_init(&name, NULL); dns_rdata_toregion(rdata, ®ion); dns_name_fromregion(&name, ®ion); dns_name_init(&nsap_ptr->owner, NULL); RETERR(name_duporclone(&name, mctx, &nsap_ptr->owner)); nsap_ptr->mctx = mctx; return (ISC_R_SUCCESS); }
static inline isc_result_t tostruct_x25(ARGS_TOSTRUCT) { dns_rdata_x25_t *x25 = target; isc_region_t r; REQUIRE(rdata->type == dns_rdatatype_x25); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); x25->common.rdclass = rdata->rdclass; x25->common.rdtype = rdata->type; ISC_LINK_INIT(&x25->common, link); dns_rdata_toregion(rdata, &r); x25->x25_len = uint8_fromregion(&r); isc_region_consume(&r, 1); x25->x25 = mem_maybedup(mctx, r.base, x25->x25_len); if (x25->x25 == NULL) return (ISC_R_NOMEMORY); x25->mctx = mctx; return (ISC_R_SUCCESS); }
static inline isc_result_t tostruct_in_aaaa (ARGS_TOSTRUCT) { dns_rdata_in_aaaa_t *aaaa = target; isc_region_t r; REQUIRE (rdata->type == 28); REQUIRE (rdata->rdclass == 1); REQUIRE (target != NULL); REQUIRE (rdata->length == 16); UNUSED (mctx); aaaa->common.rdclass = rdata->rdclass; aaaa->common.rdtype = rdata->type; ISC_LINK_INIT (&aaaa->common, link); dns_rdata_toregion (rdata, &r); INSIST (r.length == 16); memcpy (aaaa->in6_addr.s6_addr, r.base, 16); return (ISC_R_SUCCESS); }
static inline isc_result_t tostruct_in_dhcid(ARGS_TOSTRUCT) { dns_rdata_in_dhcid_t *dhcid = target; isc_region_t region; REQUIRE(rdata->type == 49); REQUIRE(rdata->rdclass == 1); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); dhcid->common.rdclass = rdata->rdclass; dhcid->common.rdtype = rdata->type; ISC_LINK_INIT(&dhcid->common, link); dns_rdata_toregion(rdata, ®ion); dhcid->dhcid = mem_maybedup(mctx, region.base, region.length); if (dhcid->dhcid == NULL) return (ISC_R_NOMEMORY); dhcid->mctx = mctx; return (ISC_R_SUCCESS); }
static inline isc_result_t tostruct_in_nsap(ARGS_TOSTRUCT) { dns_rdata_in_nsap_t *nsap = target; isc_region_t r; REQUIRE(rdata->type == 22); REQUIRE(rdata->rdclass == 1); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); nsap->common.rdclass = rdata->rdclass; nsap->common.rdtype = rdata->type; ISC_LINK_INIT(&nsap->common, link); dns_rdata_toregion(rdata, &r); nsap->nsap_len = r.length; nsap->nsap = mem_maybedup(mctx, r.base, r.length); if (nsap->nsap == NULL) return (ISC_R_NOMEMORY); nsap->mctx = mctx; return (ISC_R_SUCCESS); }
static isc_result_t controlkeylist_fromcfg(const cfg_obj_t *keylist, isc_mem_t *mctx, controlkeylist_t *keyids) { const cfg_listelt_t *element; char *newstr = NULL; const char *str; const cfg_obj_t *obj; controlkey_t *key; for (element = cfg_list_first(keylist); element != NULL; element = cfg_list_next(element)) { obj = cfg_listelt_value(element); str = cfg_obj_asstring(obj); newstr = isc_mem_strdup(mctx, str); if (newstr == NULL) goto cleanup; key = isc_mem_get(mctx, sizeof(*key)); if (key == NULL) goto cleanup; key->keyname = newstr; key->secret.base = NULL; key->secret.length = 0; ISC_LINK_INIT(key, link); ISC_LIST_APPEND(*keyids, key, link); newstr = NULL; } return (ISC_R_SUCCESS); cleanup: if (newstr != NULL) isc_mem_free(mctx, newstr); free_controlkeylist(keyids, mctx); return (ISC_R_NOMEMORY); }
isc_result_t dns_db_register(const char *name, dns_dbcreatefunc_t create, void *driverarg, isc_mem_t *mctx, dns_dbimplementation_t **dbimp) { dns_dbimplementation_t *imp; REQUIRE(name != NULL); REQUIRE(dbimp != NULL && *dbimp == NULL); RUNTIME_CHECK(isc_once_do(&once, initialize) == ISC_R_SUCCESS); RWLOCK(&implock, isc_rwlocktype_write); imp = impfind(name); if (imp != NULL) { RWUNLOCK(&implock, isc_rwlocktype_write); return (ISC_R_EXISTS); } imp = isc_mem_get(mctx, sizeof(dns_dbimplementation_t)); if (imp == NULL) { RWUNLOCK(&implock, isc_rwlocktype_write); return (ISC_R_NOMEMORY); } imp->name = name; imp->create = create; imp->mctx = NULL; imp->driverarg = driverarg; isc_mem_attach(mctx, &imp->mctx); ISC_LINK_INIT(imp, link); ISC_LIST_APPEND(implementations, imp, link); RWUNLOCK(&implock, isc_rwlocktype_write); *dbimp = imp; return (ISC_R_SUCCESS); }
static inline isc_result_t tostruct_md (ARGS_TOSTRUCT) { dns_rdata_md_t *md = target; isc_region_t r; dns_name_t name; REQUIRE (rdata->type == 3); REQUIRE (target != NULL); REQUIRE (rdata->length != 0); md->common.rdclass = rdata->rdclass; md->common.rdtype = rdata->type; ISC_LINK_INIT (&md->common, link); dns_name_init (&name, NULL); dns_rdata_toregion (rdata, &r); dns_name_fromregion (&name, &r); dns_name_init (&md->md, NULL); RETERR (name_duporclone (&name, mctx, &md->md)); md->mctx = mctx; return (ISC_R_SUCCESS); }
static inline isc_result_t tostruct_isdn(ARGS_TOSTRUCT) { dns_rdata_isdn_t *isdn = target; isc_region_t r; REQUIRE(rdata->type == 20); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); isdn->common.rdclass = rdata->rdclass; isdn->common.rdtype = rdata->type; ISC_LINK_INIT(&isdn->common, link); dns_rdata_toregion(rdata, &r); isdn->isdn_len = uint8_fromregion(&r); isc_region_consume(&r, 1); isdn->isdn = mem_maybedup(mctx, r.base, isdn->isdn_len); if (isdn->isdn == NULL) return (ISC_R_NOMEMORY); isc_region_consume(&r, isdn->isdn_len); isdn->subaddress_len = uint8_fromregion(&r); isc_region_consume(&r, 1); isdn->subaddress = mem_maybedup(mctx, r.base, isdn->subaddress_len); if (isdn->subaddress == NULL) goto cleanup; isdn->mctx = mctx; return (ISC_R_SUCCESS); cleanup: if (mctx != NULL && isdn->isdn != NULL) isc_mem_free(mctx, isdn->isdn); return (ISC_R_NOMEMORY); }
static inline isc_result_t tostruct_lp(ARGS_TOSTRUCT) { isc_region_t region; dns_rdata_lp_t *lp = target; dns_name_t name; REQUIRE(rdata->type == dns_rdatatype_lp); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); lp->common.rdclass = rdata->rdclass; lp->common.rdtype = rdata->type; ISC_LINK_INIT(&lp->common, link); dns_name_init(&name, NULL); dns_rdata_toregion(rdata, ®ion); lp->pref = uint16_fromregion(®ion); isc_region_consume(®ion, 2); dns_name_fromregion(&name, ®ion); dns_name_init(&lp->lp, NULL); RETERR(name_duporclone(&name, mctx, &lp->lp)); lp->mctx = mctx; return (ISC_R_SUCCESS); }
static isc_result_t listener_create(isc_mem_t *mctx, ns_lwresd_t *lwresd, ns_lwreslistener_t **listenerp) { ns_lwreslistener_t *listener; isc_result_t result; REQUIRE(listenerp != NULL && *listenerp == NULL); listener = isc_mem_get(mctx, sizeof(ns_lwreslistener_t)); if (listener == NULL) return (ISC_R_NOMEMORY); result = isc_mutex_init(&listener->lock); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, listener, sizeof(ns_lwreslistener_t)); return (result); } listener->magic = LWRESLISTENER_MAGIC; listener->refs = 1; listener->sock = NULL; listener->manager = NULL; ns_lwdmanager_attach(lwresd, &listener->manager); listener->mctx = NULL; isc_mem_attach(mctx, &listener->mctx); ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->cmgrs); *listenerp = listener; return (ISC_R_SUCCESS); }
int main(int argc, char *argv[]) { int i, ch, error; struct addrinfo hints, *res; isc_result_t result; isc_sockaddr_t sa; isc_sockaddrlist_t servers; isc_taskmgr_t *taskmgr = NULL; isc_socketmgr_t *socketmgr = NULL; isc_timermgr_t *timermgr = NULL; while ((ch = getopt(argc, argv, "c:dhv")) != -1) { switch (ch) { case 'c': cacheserver = optarg; break; case 'd': debug_mode = ISC_TRUE; break; case 'h': usage(); break; case 'v': verbose_level++; break; default: usage(); break; } } argc -= optind; argv += optind; /* Common set up */ isc_lib_register(); result = dns_lib_init(); if (result != ISC_R_SUCCESS) { fprintf(stderr, "dns_lib_init failed: %d\n", result); exit(1); } result = ctxs_init(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); if (result != ISC_R_SUCCESS) { fprintf(stderr, "ctx create failed: %d\n", result); exit(1); } isc_app_ctxstart(actx); result = dns_client_createx(mctx, actx, taskmgr, socketmgr, timermgr, 0, &client); if (result != ISC_R_SUCCESS) { fprintf(stderr, "dns_client_createx failed: %d\n", result); exit(1); } /* Set local cache server */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; error = getaddrinfo(cacheserver, "53", &hints, &res); if (error != 0) { fprintf(stderr, "failed to convert server name (%s): %s\n", cacheserver, gai_strerror(error)); exit(1); } if (res->ai_addrlen > sizeof(sa.type)) { fprintf(stderr, "assumption failure: addrlen is too long: %ld\n", (long)res->ai_addrlen); exit(1); } memcpy(&sa.type.sa, res->ai_addr, res->ai_addrlen); sa.length = res->ai_addrlen; freeaddrinfo(res); ISC_LINK_INIT(&sa, link); ISC_LIST_INIT(servers); ISC_LIST_APPEND(servers, &sa, link); result = dns_client_setservers(client, dns_rdataclass_in, NULL, &servers); if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to set server: %d\n", result); exit(1); } /* Create the main task */ probe_task = NULL; result = isc_task_create(taskmgr, 0, &probe_task); if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to create task: %d\n", result); exit(1); } /* Open input file */ if (argc == 0) fp = stdin; else { fp = fopen(argv[0], "r"); if (fp == NULL) { fprintf(stderr, "failed to open input file: %s\n", argv[0]); exit(1); } } /* Set up and start probe */ for (i = 0; i < MAX_PROBES; i++) { probes[i].inuse = ISC_FALSE; probes[i].domain = NULL; dns_fixedname_init(&probes[i].fixedname); probes[i].qname = NULL; probes[i].qlabel = qlabels; probes[i].qname_found = ISC_FALSE; probes[i].resid = NULL; ISC_LIST_INIT(probes[i].nslist); probes[i].reqid = NULL; probes[i].qmessage = NULL; result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &probes[i].qmessage); if (result == ISC_R_SUCCESS) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &probes[i].rmessage); } if (result != ISC_R_SUCCESS) { fprintf(stderr, "initialization failure\n"); exit(1); } } for (i = 0; i < MAX_PROBES; i++) { result = probe_domain(&probes[i]); if (result == ISC_R_NOMORE) break; else if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to issue an initial probe\n"); exit(1); } } /* Start event loop */ isc_app_ctxrun(actx); /* Dump results */ printf("Per domain results (out of %lu domains):\n", number_of_domains); printf(" valid: %lu\n" " ignore: %lu\n" " nxdomain: %lu\n" " othererr: %lu\n" " multiplesoa: %lu\n" " multiplecname: %lu\n" " brokenanswer: %lu\n" " lame: %lu\n" " unknown: %lu\n" " multiple errors: %lu\n", domain_stat.valid, domain_stat.ignore, domain_stat.nxdomain, domain_stat.othererr, domain_stat.multiplesoa, domain_stat.multiplecname, domain_stat.brokenanswer, domain_stat.lame, domain_stat.unknown, multiple_error_domains); printf("Per server results (out of %lu servers):\n", number_of_servers); printf(" valid: %lu\n" " ignore: %lu\n" " nxdomain: %lu\n" " othererr: %lu\n" " multiplesoa: %lu\n" " multiplecname: %lu\n" " brokenanswer: %lu\n" " lame: %lu\n" " unknown: %lu\n", server_stat.valid, server_stat.ignore, server_stat.nxdomain, server_stat.othererr, server_stat.multiplesoa, server_stat.multiplecname, server_stat.brokenanswer, server_stat.lame, server_stat.unknown); /* Cleanup */ for (i = 0; i < MAX_PROBES; i++) { dns_message_destroy(&probes[i].qmessage); dns_message_destroy(&probes[i].rmessage); } isc_task_detach(&probe_task); dns_client_destroy(&client); dns_lib_shutdown(); isc_app_ctxfinish(actx); ctxs_destroy(&mctx, &actx, &taskmgr, &socketmgr, &timermgr); exit(0); }
static isc_result_t ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr, const char *name, ns_interface_t **ifpret) { ns_interface_t *ifp; isc_result_t result; int disp; REQUIRE(NS_INTERFACEMGR_VALID(mgr)); ifp = isc_mem_get(mgr->mctx, sizeof(*ifp)); if (ifp == NULL) return (ISC_R_NOMEMORY); ifp->mgr = NULL; ifp->generation = mgr->generation; ifp->addr = *addr; ifp->flags = 0; strncpy(ifp->name, name, sizeof(ifp->name)); ifp->name[sizeof(ifp->name)-1] = '\0'; ifp->clientmgr = NULL; result = isc_mutex_init(&ifp->lock); if (result != ISC_R_SUCCESS) goto lock_create_failure; result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr, ns_g_timermgr, &ifp->clientmgr); if (result != ISC_R_SUCCESS) { isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR, "ns_clientmgr_create() failed: %s", isc_result_totext(result)); goto clientmgr_create_failure; } for (disp = 0; disp < MAX_UDP_DISPATCH; disp++) ifp->udpdispatch[disp] = NULL; ifp->tcpsocket = NULL; /* * Create a single TCP client object. It will replace itself * with a new one as soon as it gets a connection, so the actual * connections will be handled in parallel even though there is * only one client initially. */ ifp->ntcptarget = 1; ifp->ntcpcurrent = 0; ifp->nudpdispatch = 0; ISC_LINK_INIT(ifp, link); ns_interfacemgr_attach(mgr, &ifp->mgr); ISC_LIST_APPEND(mgr->interfaces, ifp, link); ifp->references = 1; ifp->magic = IFACE_MAGIC; *ifpret = ifp; return (ISC_R_SUCCESS); clientmgr_create_failure: DESTROYLOCK(&ifp->lock); lock_create_failure: ifp->magic = 0; isc_mem_put(mgr->mctx, ifp, sizeof(*ifp)); return (ISC_R_UNEXPECTED); }
ISC_TIMERFUNC_SCOPE isc_result_t isc__timer_create(isc_timermgr_t *manager0, isc_timertype_t type, isc_time_t *expires, isc_interval_t *interval, isc_task_t *task, isc_taskaction_t action, const void *arg, isc_timer_t **timerp) { isc__timermgr_t *manager = (isc__timermgr_t *)manager0; isc__timer_t *timer; isc_result_t result; isc_time_t now; /* * Create a new 'type' timer managed by 'manager'. The timers * parameters are specified by 'expires' and 'interval'. Events * will be posted to 'task' and when dispatched 'action' will be * called with 'arg' as the arg value. The new timer is returned * in 'timerp'. */ REQUIRE(VALID_MANAGER(manager)); REQUIRE(task != NULL); REQUIRE(action != NULL); if (expires == NULL) expires = isc_time_epoch; if (interval == NULL) interval = isc_interval_zero; REQUIRE(type == isc_timertype_inactive || !(isc_time_isepoch(expires) && isc_interval_iszero(interval))); REQUIRE(timerp != NULL && *timerp == NULL); REQUIRE(type != isc_timertype_limited || !(isc_time_isepoch(expires) || isc_interval_iszero(interval))); /* * Get current time. */ if (type != isc_timertype_inactive) { TIME_NOW(&now); } else { /* * We don't have to do this, but it keeps the compiler from * complaining about "now" possibly being used without being * set, even though it will never actually happen. */ isc_time_settoepoch(&now); } timer = isc_mem_get(manager->mctx, sizeof(*timer)); if (timer == NULL) return (ISC_R_NOMEMORY); timer->manager = manager; timer->references = 1; if (type == isc_timertype_once && !isc_interval_iszero(interval)) { result = isc_time_add(&now, interval, &timer->idle); if (result != ISC_R_SUCCESS) { isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } } else isc_time_settoepoch(&timer->idle); timer->type = type; timer->expires = *expires; timer->interval = *interval; timer->task = NULL; isc_task_attach(task, &timer->task); timer->action = action; /* * Removing the const attribute from "arg" is the best of two * evils here. If the timer->arg member is made const, then * it affects a great many recipients of the timer event * which did not pass in an "arg" that was truly const. * Changing isc_timer_create() to not have "arg" prototyped as const, * though, can cause compilers warnings for calls that *do* * have a truly const arg. The caller will have to carefully * keep track of whether arg started as a true const. */ DE_CONST(arg, timer->arg); timer->index = 0; result = isc_mutex_init(&timer->lock); if (result != ISC_R_SUCCESS) { isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } ISC_LINK_INIT(timer, link); timer->common.impmagic = TIMER_MAGIC; timer->common.magic = ISCAPI_TIMER_MAGIC; timer->common.methods = (isc_timermethods_t *)&timermethods; LOCK(&manager->lock); /* * Note we don't have to lock the timer like we normally would because * there are no external references to it yet. */ if (type != isc_timertype_inactive) result = schedule(timer, &now, ISC_TRUE); else result = ISC_R_SUCCESS; if (result == ISC_R_SUCCESS) APPEND(manager->timers, timer, link); UNLOCK(&manager->lock); if (result != ISC_R_SUCCESS) { timer->common.impmagic = 0; timer->common.magic = 0; DESTROYLOCK(&timer->lock); isc_task_detach(&timer->task); isc_mem_put(manager->mctx, timer, sizeof(*timer)); return (result); } *timerp = (isc_timer_t *)timer; return (ISC_R_SUCCESS); }
static isc_result_t get_rndckey(isc_mem_t *mctx, controlkeylist_t *keyids) { isc_result_t result; cfg_parser_t *pctx = NULL; cfg_obj_t *config = NULL; const cfg_obj_t *key = NULL; const cfg_obj_t *algobj = NULL; const cfg_obj_t *secretobj = NULL; const char *algstr = NULL; const char *secretstr = NULL; controlkey_t *keyid = NULL; char secret[1024]; unsigned int algtype; isc_buffer_t b; isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_INFO, "configuring command channel from '%s'", ns_g_keyfile); if (! isc_file_exists(ns_g_keyfile)) return (ISC_R_FILENOTFOUND); CHECK(cfg_parser_create(mctx, ns_g_lctx, &pctx)); CHECK(cfg_parse_file(pctx, ns_g_keyfile, &cfg_type_rndckey, &config)); CHECK(cfg_map_get(config, "key", &key)); keyid = isc_mem_get(mctx, sizeof(*keyid)); if (keyid == NULL) CHECK(ISC_R_NOMEMORY); keyid->keyname = isc_mem_strdup(mctx, cfg_obj_asstring(cfg_map_getname(key))); keyid->secret.base = NULL; keyid->secret.length = 0; keyid->algorithm = DST_ALG_UNKNOWN; ISC_LINK_INIT(keyid, link); if (keyid->keyname == NULL) CHECK(ISC_R_NOMEMORY); CHECK(bind9_check_key(key, ns_g_lctx)); (void)cfg_map_get(key, "algorithm", &algobj); (void)cfg_map_get(key, "secret", &secretobj); INSIST(algobj != NULL && secretobj != NULL); algstr = cfg_obj_asstring(algobj); secretstr = cfg_obj_asstring(secretobj); if (ns_config_getkeyalgorithm2(algstr, NULL, &algtype, NULL) != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "unsupported algorithm '%s' in " "key '%s' for use with command " "channel", algstr, keyid->keyname); goto cleanup; } keyid->algorithm = algtype; isc_buffer_init(&b, secret, sizeof(secret)); result = isc_base64_decodestring(secretstr, &b); if (result != ISC_R_SUCCESS) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "secret for key '%s' on command channel: %s", keyid->keyname, isc_result_totext(result)); goto cleanup; } keyid->secret.length = isc_buffer_usedlength(&b); keyid->secret.base = isc_mem_get(mctx, keyid->secret.length); if (keyid->secret.base == NULL) { cfg_obj_log(key, ns_g_lctx, ISC_LOG_WARNING, "couldn't register key '%s': " "out of memory", keyid->keyname); CHECK(ISC_R_NOMEMORY); } memmove(keyid->secret.base, isc_buffer_base(&b), keyid->secret.length); ISC_LIST_APPEND(*keyids, keyid, link); keyid = NULL; result = ISC_R_SUCCESS; cleanup: if (keyid != NULL) free_controlkey(keyid, mctx); if (config != NULL) cfg_obj_destroy(pctx, &config); if (pctx != NULL) cfg_parser_destroy(&pctx); return (result); }
isc_result_t isc_entropy_createfilesource(isc_entropy_t *ent, const char *fname) { isc_result_t ret; isc_entropysource_t *source; HCRYPTPROV hcryptprov; BOOL err; REQUIRE(VALID_ENTROPY(ent)); REQUIRE(fname != NULL); LOCK(&ent->lock); source = NULL; /* * The first time we just try to acquire the context */ err = CryptAcquireContext(&hcryptprov, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT); if (!err){ (void)GetLastError(); ret = ISC_R_IOERROR; goto errout; } source = isc_mem_get(ent->mctx, sizeof(isc_entropysource_t)); if (source == NULL) { ret = ISC_R_NOMEMORY; goto closecontext; } /* * From here down, no failures can occur. */ source->magic = SOURCE_MAGIC; source->type = ENTROPY_SOURCETYPE_FILE; source->ent = ent; source->total = 0; source->bad = ISC_FALSE; memset(source->name, 0, sizeof(source->name)); ISC_LINK_INIT(source, link); source->sources.file.handle = hcryptprov; /* * Hook it into the entropy system. */ ISC_LIST_APPEND(ent->sources, source, link); ent->nsources++; UNLOCK(&ent->lock); return (ISC_R_SUCCESS); closecontext: CryptReleaseContext(hcryptprov, 0); errout: if (source != NULL) isc_mem_put(ent->mctx, source, sizeof(isc_entropysource_t)); UNLOCK(&ent->lock); return (ret); }
static inline isc_result_t tostruct_sig(ARGS_TOSTRUCT) { isc_region_t sr; dns_rdata_sig_t *sig = target; dns_name_t signer; REQUIRE(rdata->type == dns_rdatatype_sig); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); sig->common.rdclass = rdata->rdclass; sig->common.rdtype = rdata->type; ISC_LINK_INIT(&sig->common, link); dns_rdata_toregion(rdata, &sr); /* * Type covered. */ sig->covered = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* * Algorithm. */ sig->algorithm = uint8_fromregion(&sr); isc_region_consume(&sr, 1); /* * Labels. */ sig->labels = uint8_fromregion(&sr); isc_region_consume(&sr, 1); /* * Original TTL. */ sig->originalttl = uint32_fromregion(&sr); isc_region_consume(&sr, 4); /* * Expire time. */ sig->timeexpire = uint32_fromregion(&sr); isc_region_consume(&sr, 4); /* * Time signed. */ sig->timesigned = uint32_fromregion(&sr); isc_region_consume(&sr, 4); /* * Key ID. */ sig->keyid = uint16_fromregion(&sr); isc_region_consume(&sr, 2); dns_name_init(&signer, NULL); dns_name_fromregion(&signer, &sr); dns_name_init(&sig->signer, NULL); RETERR(name_duporclone(&signer, mctx, &sig->signer)); isc_region_consume(&sr, name_length(&sig->signer)); /* * Signature. */ sig->siglen = sr.length; sig->signature = mem_maybedup(mctx, sr.base, sig->siglen); if (sig->signature == NULL) goto cleanup; sig->mctx = mctx; return (ISC_R_SUCCESS); cleanup: if (mctx != NULL) dns_name_free(&sig->signer, mctx); return (ISC_R_NOMEMORY); }
isc_result_t dns_tsig_sign(dns_message_t *msg) { dns_tsigkey_t *key; dns_rdata_any_tsig_t tsig, querytsig; unsigned char data[128]; isc_buffer_t databuf, sigbuf; isc_buffer_t *dynbuf; dns_name_t *owner; dns_rdata_t *rdata = NULL; dns_rdatalist_t *datalist; dns_rdataset_t *dataset; isc_region_t r; isc_stdtime_t now; isc_mem_t *mctx; dst_context_t *ctx = NULL; isc_result_t ret; unsigned char badtimedata[BADTIMELEN]; unsigned int sigsize = 0; isc_boolean_t response = is_response(msg); REQUIRE(msg != NULL); REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); /* * If this is a response, there should be a query tsig. */ if (response && msg->querytsig == NULL) return (DNS_R_EXPECTEDTSIG); dynbuf = NULL; mctx = msg->mctx; key = dns_message_gettsigkey(msg); tsig.mctx = mctx; tsig.common.rdclass = dns_rdataclass_any; tsig.common.rdtype = dns_rdatatype_tsig; ISC_LINK_INIT(&tsig.common, link); dns_name_init(&tsig.algorithm, NULL); dns_name_clone(key->algorithm, &tsig.algorithm); isc_stdtime_get(&now); tsig.timesigned = now + msg->timeadjust; tsig.fudge = DNS_TSIG_FUDGE; tsig.originalid = msg->id; isc_buffer_init(&databuf, data, sizeof(data)); if (response) tsig.error = msg->querytsigstatus; else tsig.error = dns_rcode_noerror; if (tsig.error != dns_tsigerror_badtime) { tsig.otherlen = 0; tsig.other = NULL; } else { isc_buffer_t otherbuf; tsig.otherlen = BADTIMELEN; tsig.other = badtimedata; isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen); isc_buffer_putuint48(&otherbuf, tsig.timesigned); } if (key->key != NULL && tsig.error != dns_tsigerror_badsig) { unsigned char header[DNS_MESSAGE_HEADERLEN]; isc_buffer_t headerbuf; isc_uint16_t digestbits; ret = dst_context_create3(key->key, mctx, DNS_LOGCATEGORY_DNSSEC, ISC_TRUE, &ctx); if (ret != ISC_R_SUCCESS) return (ret); /* * If this is a response, digest the query signature. */ if (response) { dns_rdata_t querytsigrdata = DNS_RDATA_INIT; ret = dns_rdataset_first(msg->querytsig); if (ret != ISC_R_SUCCESS) goto cleanup_context; dns_rdataset_current(msg->querytsig, &querytsigrdata); ret = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_putuint16(&databuf, querytsig.siglen); if (isc_buffer_availablelength(&databuf) < querytsig.siglen) { ret = ISC_R_NOSPACE; goto cleanup_context; } isc_buffer_putmem(&databuf, querytsig.signature, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } #if defined(__clang__) && \ ( __clang_major__ < 3 || \ (__clang_major__ == 3 && __clang_minor__ < 2) || \ (__clang_major__ == 4 && __clang_minor__ < 2)) /* false positive: http://llvm.org/bugs/show_bug.cgi?id=14461 */ else memset(&querytsig, 0, sizeof(querytsig)); #endif /* * Digest the header. */ isc_buffer_init(&headerbuf, header, sizeof(header)); dns_message_renderheader(msg, &headerbuf); isc_buffer_usedregion(&headerbuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest the remainder of the message. */ isc_buffer_usedregion(msg->buffer, &r); isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; if (msg->tcp_continuation == 0) { /* * Digest the name, class, ttl, alg. */ dns_name_toregion(&key->name, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_clear(&databuf); isc_buffer_putuint16(&databuf, dns_rdataclass_any); isc_buffer_putuint32(&databuf, 0); /* ttl */ isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; dns_name_toregion(&tsig.algorithm, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } /* Digest the timesigned and fudge */ isc_buffer_clear(&databuf); if (tsig.error == dns_tsigerror_badtime) { INSIST(response); tsig.timesigned = querytsig.timesigned; } isc_buffer_putuint48(&databuf, tsig.timesigned); isc_buffer_putuint16(&databuf, tsig.fudge); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; if (msg->tcp_continuation == 0) { /* * Digest the error and other data length. */ isc_buffer_clear(&databuf); isc_buffer_putuint16(&databuf, tsig.error); isc_buffer_putuint16(&databuf, tsig.otherlen); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest other data. */ if (tsig.otherlen > 0) { r.length = tsig.otherlen; r.base = tsig.other; ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } } ret = dst_key_sigsize(key->key, &sigsize); if (ret != ISC_R_SUCCESS) goto cleanup_context; tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize); if (tsig.signature == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_context; } isc_buffer_init(&sigbuf, tsig.signature, sigsize); ret = dst_context_sign(ctx, &sigbuf); if (ret != ISC_R_SUCCESS) goto cleanup_signature; dst_context_destroy(&ctx); digestbits = dst_key_getbits(key->key); if (digestbits != 0) { unsigned int bytes = (digestbits + 1) / 8; if (response && bytes < querytsig.siglen) bytes = querytsig.siglen; if (bytes > isc_buffer_usedlength(&sigbuf)) bytes = isc_buffer_usedlength(&sigbuf); tsig.siglen = bytes; } else tsig.siglen = isc_buffer_usedlength(&sigbuf); } else { tsig.siglen = 0; tsig.signature = NULL; } ret = dns_message_gettemprdata(msg, &rdata); if (ret != ISC_R_SUCCESS) goto cleanup_signature; ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512); if (ret != ISC_R_SUCCESS) goto cleanup_rdata; ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &tsig, dynbuf); if (ret != ISC_R_SUCCESS) goto cleanup_dynbuf; dns_message_takebuffer(msg, &dynbuf); if (tsig.signature != NULL) { isc_mem_put(mctx, tsig.signature, sigsize); tsig.signature = NULL; } owner = NULL; ret = dns_message_gettempname(msg, &owner); if (ret != ISC_R_SUCCESS) goto cleanup_rdata; dns_name_init(owner, NULL); ret = dns_name_dup(&key->name, msg->mctx, owner); if (ret != ISC_R_SUCCESS) goto cleanup_owner; datalist = NULL; ret = dns_message_gettemprdatalist(msg, &datalist); if (ret != ISC_R_SUCCESS) goto cleanup_owner; dataset = NULL; ret = dns_message_gettemprdataset(msg, &dataset); if (ret != ISC_R_SUCCESS) goto cleanup_rdatalist; datalist->rdclass = dns_rdataclass_any; datalist->type = dns_rdatatype_tsig; datalist->covers = 0; datalist->ttl = 0; ISC_LIST_INIT(datalist->rdata); ISC_LIST_APPEND(datalist->rdata, rdata, link); RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS); msg->tsig = dataset; msg->tsigname = owner; /* Windows does not like the tsig name being compressed. */ msg->tsigname->attributes |= DNS_NAMEATTR_NOCOMPRESS; return (ISC_R_SUCCESS); cleanup_rdatalist: dns_message_puttemprdatalist(msg, &datalist); cleanup_owner: dns_message_puttempname(msg, &owner); goto cleanup_rdata; cleanup_dynbuf: isc_buffer_free(&dynbuf); cleanup_rdata: dns_message_puttemprdata(msg, &rdata); cleanup_signature: if (tsig.signature != NULL) isc_mem_put(mctx, tsig.signature, sigsize); cleanup_context: if (ctx != NULL) dst_context_destroy(&ctx); return (ret); }
isc_result_t dns_tsig_sign(dns_message_t *msg) { dns_tsigkey_t *key; dns_rdata_any_tsig_t tsig, querytsig; unsigned char data[128]; isc_buffer_t databuf, sigbuf; isc_buffer_t *dynbuf; dns_name_t *owner; dns_rdata_t *rdata; dns_rdatalist_t *datalist; dns_rdataset_t *dataset; isc_region_t r; isc_stdtime_t now; isc_mem_t *mctx; dst_context_t *ctx = NULL; isc_result_t ret; unsigned char badtimedata[BADTIMELEN]; unsigned int sigsize = 0; REQUIRE(msg != NULL); REQUIRE(VALID_TSIG_KEY(dns_message_gettsigkey(msg))); /* * If this is a response, there should be a query tsig. */ if (is_response(msg) && msg->querytsig == NULL) return (DNS_R_EXPECTEDTSIG); dynbuf = NULL; mctx = msg->mctx; key = dns_message_gettsigkey(msg); tsig.mctx = mctx; tsig.common.rdclass = dns_rdataclass_any; tsig.common.rdtype = dns_rdatatype_tsig; ISC_LINK_INIT(&tsig.common, link); dns_name_init(&tsig.algorithm, NULL); dns_name_clone(key->algorithm, &tsig.algorithm); isc_stdtime_get(&now); tsig.timesigned = now + msg->timeadjust; tsig.fudge = DNS_TSIG_FUDGE; tsig.originalid = msg->id; isc_buffer_init(&databuf, data, sizeof(data)); if (is_response(msg)) tsig.error = msg->querytsigstatus; else tsig.error = dns_rcode_noerror; if (tsig.error != dns_tsigerror_badtime) { tsig.otherlen = 0; tsig.other = NULL; } else { isc_buffer_t otherbuf; tsig.otherlen = BADTIMELEN; tsig.other = badtimedata; isc_buffer_init(&otherbuf, tsig.other, tsig.otherlen); buffer_putuint48(&otherbuf, tsig.timesigned); } if (key->key != NULL && tsig.error != dns_tsigerror_badsig) { unsigned char header[DNS_MESSAGE_HEADERLEN]; isc_buffer_t headerbuf; ret = dst_context_create(key->key, mctx, &ctx); if (ret != ISC_R_SUCCESS) return (ret); /* * If this is a response, digest the query signature. */ if (is_response(msg)) { dns_rdata_t querytsigrdata = DNS_RDATA_INIT; ret = dns_rdataset_first(msg->querytsig); if (ret != ISC_R_SUCCESS) goto cleanup_context; dns_rdataset_current(msg->querytsig, &querytsigrdata); ret = dns_rdata_tostruct(&querytsigrdata, &querytsig, NULL); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_putuint16(&databuf, querytsig.siglen); if (isc_buffer_availablelength(&databuf) < querytsig.siglen) { ret = ISC_R_NOSPACE; goto cleanup_context; } isc_buffer_putmem(&databuf, querytsig.signature, querytsig.siglen); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } /* * Digest the header. */ isc_buffer_init(&headerbuf, header, sizeof(header)); dns_message_renderheader(msg, &headerbuf); isc_buffer_usedregion(&headerbuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest the remainder of the message. */ isc_buffer_usedregion(msg->buffer, &r); isc_region_consume(&r, DNS_MESSAGE_HEADERLEN); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; if (msg->tcp_continuation == 0) { /* * Digest the name, class, ttl, alg. */ dns_name_toregion(&key->name, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; isc_buffer_clear(&databuf); isc_buffer_putuint16(&databuf, dns_rdataclass_any); isc_buffer_putuint32(&databuf, 0); /* ttl */ isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; dns_name_toregion(&tsig.algorithm, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } /* Digest the timesigned and fudge */ isc_buffer_clear(&databuf); if (tsig.error == dns_tsigerror_badtime) tsig.timesigned = querytsig.timesigned; buffer_putuint48(&databuf, tsig.timesigned); isc_buffer_putuint16(&databuf, tsig.fudge); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; if (msg->tcp_continuation == 0) { /* * Digest the error and other data length. */ isc_buffer_clear(&databuf); isc_buffer_putuint16(&databuf, tsig.error); isc_buffer_putuint16(&databuf, tsig.otherlen); isc_buffer_usedregion(&databuf, &r); ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; /* * Digest the error and other data. */ if (tsig.otherlen > 0) { r.length = tsig.otherlen; r.base = tsig.other; ret = dst_context_adddata(ctx, &r); if (ret != ISC_R_SUCCESS) goto cleanup_context; } } ret = dst_key_sigsize(key->key, &sigsize); if (ret != ISC_R_SUCCESS) goto cleanup_context; tsig.signature = (unsigned char *) isc_mem_get(mctx, sigsize); if (tsig.signature == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_context; } isc_buffer_init(&sigbuf, tsig.signature, sigsize); ret = dst_context_sign(ctx, &sigbuf); if (ret != ISC_R_SUCCESS) goto cleanup_signature; dst_context_destroy(&ctx); tsig.siglen = isc_buffer_usedlength(&sigbuf); } else { tsig.siglen = 0; tsig.signature = NULL; } rdata = NULL; ret = dns_message_gettemprdata(msg, &rdata); if (ret != ISC_R_SUCCESS) goto cleanup_signature; ret = isc_buffer_allocate(msg->mctx, &dynbuf, 512); if (ret != ISC_R_SUCCESS) goto cleanup_signature; ret = dns_rdata_fromstruct(rdata, dns_rdataclass_any, dns_rdatatype_tsig, &tsig, dynbuf); if (ret != ISC_R_SUCCESS) goto cleanup_dynbuf; dns_message_takebuffer(msg, &dynbuf); if (tsig.signature != NULL) { isc_mem_put(mctx, tsig.signature, sigsize); tsig.signature = NULL; } owner = NULL; ret = dns_message_gettempname(msg, &owner); if (ret != ISC_R_SUCCESS) goto cleanup_dynbuf; dns_name_init(owner, NULL); ret = dns_name_dup(&key->name, msg->mctx, owner); if (ret != ISC_R_SUCCESS) goto cleanup_owner; datalist = NULL; ret = dns_message_gettemprdatalist(msg, &datalist); if (ret != ISC_R_SUCCESS) goto cleanup_owner; datalist->rdclass = dns_rdataclass_any; datalist->type = dns_rdatatype_tsig; datalist->covers = 0; datalist->ttl = 0; ISC_LIST_INIT(datalist->rdata); ISC_LIST_APPEND(datalist->rdata, rdata, link); dataset = NULL; ret = dns_message_gettemprdataset(msg, &dataset); if (ret != ISC_R_SUCCESS) goto cleanup_owner; dns_rdataset_init(dataset); RUNTIME_CHECK(dns_rdatalist_tordataset(datalist, dataset) == ISC_R_SUCCESS); msg->tsig = dataset; msg->tsigname = owner; return (ISC_R_SUCCESS); cleanup_owner: if (owner != NULL) dns_message_puttempname(msg, &owner); cleanup_dynbuf: if (dynbuf != NULL) isc_buffer_free(&dynbuf); cleanup_signature: if (tsig.signature != NULL) isc_mem_put(mctx, tsig.signature, sigsize); cleanup_context: if (ctx != NULL) dst_context_destroy(&ctx); return (ret); }
int main(int argc, char *argv[]) { int ch, i, gai_error; struct addrinfo hints, *res; isc_textregion_t tr; dns_client_t *client = NULL; isc_result_t result; isc_sockaddr_t sa; dns_message_t *qmessage, *rmessage; dns_rdatatype_t type = dns_rdatatype_a; isc_buffer_t *outputbuf; while ((ch = getopt(argc, argv, "t:")) != -1) { switch (ch) { case 't': tr.base = optarg; tr.length = strlen(optarg); result = dns_rdatatype_fromtext(&type, &tr); if (result != ISC_R_SUCCESS) { fprintf(stderr, "invalid RRtype: %s\n", optarg); exit(1); } break; default: usage(); } } argc -= optind; argv += optind; if (argc < 2) usage(); isc_lib_register(); result = dns_lib_init(); if (result != ISC_R_SUCCESS) { fprintf(stderr, "dns_lib_init failed: %d\n", result); exit(1); } result = dns_client_create(&client, 0); if (result != ISC_R_SUCCESS) { fprintf(stderr, "dns_client_create failed: %d\n", result); exit(1); } /* Prepare message structures */ mctx = NULL; qmessage = NULL; rmessage = NULL; result = isc_mem_create(0, 0, &mctx); if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to create a memory context\n"); exit(1); } result = dns_message_create(mctx, DNS_MESSAGE_INTENTRENDER, &qmessage); if (result == ISC_R_SUCCESS) { result = dns_message_create(mctx, DNS_MESSAGE_INTENTPARSE, &rmessage); } if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to create messages\n"); exit(1); } /* Initialize the nameserver address */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_DGRAM; hints.ai_protocol = IPPROTO_UDP; hints.ai_flags = AI_NUMERICHOST; gai_error = getaddrinfo(argv[0], "53", &hints, &res); if (gai_error != 0) { fprintf(stderr, "getaddrinfo failed: %s\n", gai_strerror(gai_error)); exit(1); } INSIST(res->ai_addrlen <= sizeof(sa.type)); memcpy(&sa.type, res->ai_addr, res->ai_addrlen); freeaddrinfo(res); sa.length = res->ai_addrlen; ISC_LINK_INIT(&sa, link); /* Construct qname */ result = make_querymessage(qmessage, argv[1], type); if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to create a query\n"); exit(1); } /* Send request and wait for a response */ result = dns_client_request(client, qmessage, rmessage, &sa, 0, 0, NULL, 60, 0, 3); if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to get a response: %s\n", dns_result_totext(result)); } /* Dump the response */ outputbuf = NULL; result = isc_buffer_allocate(mctx, &outputbuf, 65535); if (result != ISC_R_SUCCESS) { fprintf(stderr, "failed to allocate a result buffer\n"); exit(1); } for (i = 0; i < DNS_SECTION_MAX; i++) { print_section(rmessage, i, outputbuf); isc_buffer_clear(outputbuf); } isc_buffer_free(&outputbuf); /* Cleanup */ dns_message_destroy(&qmessage); dns_message_destroy(&rmessage); isc_mem_destroy(&mctx); dns_client_destroy(&client); dns_lib_shutdown(); exit(0); }
static inline isc_result_t tostruct_tkey(ARGS_TOSTRUCT) { dns_rdata_tkey_t *tkey = target; dns_name_t alg; isc_region_t sr; REQUIRE(rdata->type == 249); REQUIRE(target != NULL); REQUIRE(rdata->length != 0); tkey->common.rdclass = rdata->rdclass; tkey->common.rdtype = rdata->type; ISC_LINK_INIT(&tkey->common, link); dns_rdata_toregion(rdata, &sr); /* * Algorithm Name. */ dns_name_init(&alg, NULL); dns_name_fromregion(&alg, &sr); dns_name_init(&tkey->algorithm, NULL); RETERR(name_duporclone(&alg, mctx, &tkey->algorithm)); isc_region_consume(&sr, name_length(&tkey->algorithm)); /* * Inception. */ tkey->inception = uint32_fromregion(&sr); isc_region_consume(&sr, 4); /* * Expire. */ tkey->expire = uint32_fromregion(&sr); isc_region_consume(&sr, 4); /* * Mode. */ tkey->mode = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* * Error. */ tkey->error = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* * Key size. */ tkey->keylen = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* * Key. */ tkey->key = mem_maybedup(mctx, sr.base, tkey->keylen); if (tkey->key == NULL) goto cleanup; isc_region_consume(&sr, tkey->keylen); /* * Other size. */ tkey->otherlen = uint16_fromregion(&sr); isc_region_consume(&sr, 2); /* * Other. */ tkey->other = mem_maybedup(mctx, sr.base, tkey->otherlen); if (tkey->other == NULL) goto cleanup; tkey->mctx = mctx; return (ISC_R_SUCCESS); cleanup: if (mctx != NULL) dns_name_free(&tkey->algorithm, mctx); if (mctx != NULL && tkey->key != NULL) isc_mem_free(mctx, tkey->key); return (ISC_R_NOMEMORY); }
/*% * create an instance of the driver. Remember, only 1 copy of the driver's * code is ever loaded, the driver has to remember which context it's * operating in. This is done via use of the dbdata argument which is * passed into all query functions. */ static isc_result_t postgres_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { isc_result_t result; dbinstance_t *dbi = NULL; unsigned int j; #ifdef ISC_PLATFORM_USETHREADS /* if multi-threaded, we need a few extra variables. */ int dbcount; db_list_t *dblist = NULL; int i; char *endp; #endif /* ISC_PLATFORM_USETHREADS */ UNUSED(driverarg); UNUSED(dlzname); /* seed random # generator */ srand( (unsigned)time( NULL ) ); #ifdef ISC_PLATFORM_USETHREADS /* if debugging, let user know we are multithreaded. */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "Postgres driver running multithreaded"); #else /* ISC_PLATFORM_USETHREADS */ /* if debugging, let user know we are single threaded. */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1), "Postgres driver running single threaded"); #endif /* ISC_PLATFORM_USETHREADS */ /* verify we have at least 5 arg's passed to the driver */ if (argc < 5) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver requires at least " "4 command line args."); return (ISC_R_FAILURE); } /* no more than 8 arg's should be passed to the driver */ if (argc > 8) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver cannot accept more than " "7 command line args."); return (ISC_R_FAILURE); } /* multithreaded build can have multiple DB connections */ #ifdef ISC_PLATFORM_USETHREADS /* check how many db connections we should create */ dbcount = strtol(argv[1], &endp, 10); if (*endp != '\0' || dbcount < 0) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver database connection count " "must be positive."); return (ISC_R_FAILURE); } /* allocate memory for database connection list */ dblist = isc_mem_get(ns_g_mctx, sizeof(db_list_t)); if (dblist == NULL) return (ISC_R_NOMEMORY); /* initialize DB connection list */ ISC_LIST_INIT(*dblist); /* * create the appropriate number of database instances (DBI) * append each new DBI to the end of the list */ for (i=0; i < dbcount; i++) { #endif /* ISC_PLATFORM_USETHREADS */ /* how many queries were passed in from config file? */ switch(argc) { case 5: result = build_sqldbinstance(ns_g_mctx, NULL, NULL, NULL, argv[3], argv[4], NULL, &dbi); break; case 6: result = build_sqldbinstance(ns_g_mctx, NULL, NULL, argv[5], argv[3], argv[4], NULL, &dbi); break; case 7: result = build_sqldbinstance(ns_g_mctx, argv[6], NULL, argv[5], argv[3], argv[4], NULL, &dbi); break; case 8: result = build_sqldbinstance(ns_g_mctx, argv[6], argv[7], argv[5], argv[3], argv[4], NULL, &dbi); break; default: /* not really needed, should shut up compiler. */ result = ISC_R_FAILURE; } if (result == ISC_R_SUCCESS) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2), "Postgres driver created database " "instance object."); } else { /* unsuccessful?, log err msg and cleanup. */ isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver could not create " "database instance object."); goto cleanup; } #ifdef ISC_PLATFORM_USETHREADS /* when multithreaded, build a list of DBI's */ ISC_LINK_INIT(dbi, link); ISC_LIST_APPEND(*dblist, dbi, link); #endif /* create and set db connection */ dbi->dbconn = PQconnectdb(argv[2]); /* * if db connection cannot be created, log err msg and * cleanup. */ if (dbi->dbconn == NULL) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver could not allocate " "memory for database connection"); goto cleanup; } /* if we cannot connect the first time, try 3 more times. */ for (j = 0; PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK && j < 3; j++) PQreset((PGconn *) dbi->dbconn); #ifdef ISC_PLATFORM_USETHREADS /* * if multi threaded, let user know which connection * failed. user could be attempting to create 10 db * connections and for some reason the db backend only * allows 9 */ if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver failed to create " "database connection number %u " "after 4 attempts", i + 1); goto cleanup; } /* set DBI = null for next loop through. */ dbi = NULL; } /* end for loop */ /* set dbdata to the list we created. */ *dbdata = dblist; #else /* ISC_PLATFORM_USETHREADS */ /* if single threaded, just let user know we couldn't connect. */ if (PQstatus((PGconn *) dbi->dbconn) != CONNECTION_OK) { isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE, DNS_LOGMODULE_DLZ, ISC_LOG_ERROR, "Postgres driver failed to create database " "connection after 4 attempts"); goto cleanup; } /* * single threaded build can only use 1 db connection, return * it via dbdata */ *dbdata = dbi; #endif /* ISC_PLATFORM_USETHREADS */ /* hey, we got through all of that ok, return success. */ return(ISC_R_SUCCESS); cleanup: #ifdef ISC_PLATFORM_USETHREADS /* * if multithreaded, we could fail because only 1 connection * couldn't be made. We should cleanup the other successful * connections properly. */ postgres_destroy_dblist(dblist); #else /* ISC_PLATFORM_USETHREADS */ if (dbi != NULL) destroy_sqldbinstance(dbi); #endif /* ISC_PLATFORM_USETHREADS */ return(ISC_R_FAILURE); }
static isc_result_t load(const char *filename, const char *origintext, isc_boolean_t cache) { dns_fixedname_t forigin; dns_name_t *origin; isc_result_t result; isc_buffer_t source; size_t len; dbinfo *dbi; unsigned int i; dbi = isc_mem_get(mctx, sizeof(*dbi)); if (dbi == NULL) return (ISC_R_NOMEMORY); dbi->db = NULL; dbi->version = NULL; dbi->wversion = NULL; for (i = 0; i < MAXVERSIONS; i++) dbi->rversions[i] = NULL; dbi->hold_count = 0; for (i = 0; i < MAXHOLD; i++) dbi->hold_nodes[i] = NULL; dbi->dbiterator = NULL; dbi->iversion = NULL; dbi->pause_every = pause_every; dbi->ascending = ascending; ISC_LINK_INIT(dbi, link); len = strlen(origintext); isc_buffer_constinit(&source, origintext, len); isc_buffer_add(&source, len); dns_fixedname_init(&forigin); origin = dns_fixedname_name(&forigin); result = dns_name_fromtext(origin, &source, dns_rootname, 0, NULL); if (result != ISC_R_SUCCESS) return (result); result = dns_db_create(mctx, dbtype, origin, cache ? dns_dbtype_cache : dns_dbtype_zone, dns_rdataclass_in, 0, NULL, &dbi->db); if (result != ISC_R_SUCCESS) { isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } printf("loading %s (%s)\n", filename, origintext); result = dns_db_load(dbi->db, filename); if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE) { dns_db_detach(&dbi->db); isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } printf("loaded\n"); if (cache) { INSIST(cache_dbi == NULL); dns_dbtable_adddefault(dbtable, dbi->db); cache_dbi = dbi; } else { if (dns_dbtable_add(dbtable, dbi->db) != ISC_R_SUCCESS) { dns_db_detach(&dbi->db); isc_mem_put(mctx, dbi, sizeof(*dbi)); return (result); } } ISC_LIST_APPEND(dbs, dbi, link); return (ISC_R_SUCCESS); }
static void resolve_nsaddress(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; dns_rdata_t rdata = DNS_RDATA_INIT; struct probe_ns *pns = trans->current_ns; isc_result_t result; REQUIRE(task == probe_task); REQUIRE(trans->inuse == ISC_TRUE); REQUIRE(pns != NULL); 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_a) continue; for (result = dns_rdataset_first(rdataset); result == ISC_R_SUCCESS; result = dns_rdataset_next(rdataset)) { dns_rdata_in_a_t rdata_a; struct server *server; dns_rdataset_current(rdataset, &rdata); result = dns_rdata_tostruct(&rdata, &rdata_a, NULL); if (result != ISC_R_SUCCESS) continue; server = isc_mem_get(mctx, sizeof(*server)); if (server == NULL) { fprintf(stderr, "resolve_nsaddress: " "mem_get failed"); result = ISC_R_NOMEMORY; POST(result); goto cleanup; } isc_sockaddr_fromin(&server->address, &rdata_a.in_addr, 53); ISC_LINK_INIT(server, link); server->result_a = none; server->result_aaaa = none; ISC_LIST_APPEND(pns->servers, server, link); } } } cleanup: dns_client_freeresanswer(client, &rev->answerlist); dns_client_destroyrestrans(&trans->resid); isc_event_free(&event); next_ns: trans->current_ns = ISC_LIST_NEXT(pns, link); if (trans->current_ns == NULL) { trans->current_ns = ISC_LIST_HEAD(trans->nslist); dns_fixedname_invalidate(&trans->fixedname); trans->qname = NULL; result = set_nextqname(trans); if (result == ISC_R_SUCCESS) result = probe_name(trans, dns_rdatatype_a); } else { result = fetch_nsaddress(trans); if (result != ISC_R_SUCCESS) goto next_ns; /* XXX: this is unlikely to succeed */ } if (result != ISC_R_SUCCESS) reset_probe(trans); }
static void add_listener(ns_controls_t *cp, controllistener_t **listenerp, const cfg_obj_t *control, const cfg_obj_t *config, isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx, const char *socktext, isc_sockettype_t type) { isc_mem_t *mctx = cp->server->mctx; controllistener_t *listener; const cfg_obj_t *allow; const cfg_obj_t *global_keylist = NULL; const cfg_obj_t *control_keylist = NULL; dns_acl_t *new_acl = NULL; isc_result_t result = ISC_R_SUCCESS; listener = isc_mem_get(mctx, sizeof(*listener)); if (listener == NULL) result = ISC_R_NOMEMORY; if (result == ISC_R_SUCCESS) { listener->mctx = NULL; isc_mem_attach(mctx, &listener->mctx); listener->controls = cp; listener->task = cp->server->task; listener->address = *addr; listener->sock = NULL; listener->listening = ISC_FALSE; listener->exiting = ISC_FALSE; listener->acl = NULL; listener->type = type; listener->perm = 0; listener->owner = 0; listener->group = 0; ISC_LINK_INIT(listener, link); ISC_LIST_INIT(listener->keys); ISC_LIST_INIT(listener->connections); /* * Make the acl. */ if (control != NULL && type == isc_sockettype_tcp) { allow = cfg_tuple_get(control, "allow"); result = cfg_acl_fromconfig(allow, config, ns_g_lctx, aclconfctx, mctx, 0, &new_acl); } else { result = dns_acl_any(mctx, &new_acl); } } if (result == ISC_R_SUCCESS) { dns_acl_attach(new_acl, &listener->acl); dns_acl_detach(&new_acl); if (config != NULL) get_key_info(config, control, &global_keylist, &control_keylist); if (control_keylist != NULL) { result = controlkeylist_fromcfg(control_keylist, listener->mctx, &listener->keys); if (result == ISC_R_SUCCESS) register_keys(control, global_keylist, &listener->keys, listener->mctx, socktext); } else result = get_rndckey(mctx, &listener->keys); if (result != ISC_R_SUCCESS && control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't install keys for " "command channel %s: %s", socktext, isc_result_totext(result)); } if (result == ISC_R_SUCCESS) { int pf = isc_sockaddr_pf(&listener->address); if ((pf == AF_INET && isc_net_probeipv4() != ISC_R_SUCCESS) || #ifdef ISC_PLATFORM_HAVESYSUNH (pf == AF_UNIX && isc_net_probeunix() != ISC_R_SUCCESS) || #endif (pf == AF_INET6 && isc_net_probeipv6() != ISC_R_SUCCESS)) result = ISC_R_FAMILYNOSUPPORT; } if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) isc_socket_cleanunix(&listener->address, ISC_FALSE); if (result == ISC_R_SUCCESS) result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(&listener->address), type, &listener->sock); if (result == ISC_R_SUCCESS) isc_socket_setname(listener->sock, "control", NULL); #ifndef ISC_ALLOW_MAPPED if (result == ISC_R_SUCCESS) isc_socket_ipv6only(listener->sock, ISC_TRUE); #endif if (result == ISC_R_SUCCESS) result = isc_socket_bind(listener->sock, &listener->address, ISC_SOCKET_REUSEADDRESS); if (result == ISC_R_SUCCESS && type == isc_sockettype_unix) { listener->perm = cfg_obj_asuint32(cfg_tuple_get(control, "perm")); listener->owner = cfg_obj_asuint32(cfg_tuple_get(control, "owner")); listener->group = cfg_obj_asuint32(cfg_tuple_get(control, "group")); result = isc_socket_permunix(&listener->address, listener->perm, listener->owner, listener->group); } if (result == ISC_R_SUCCESS) result = control_listen(listener); if (result == ISC_R_SUCCESS) result = control_accept(listener); if (result == ISC_R_SUCCESS) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "command channel listening on %s", socktext); *listenerp = listener; } else { if (listener != NULL) { listener->exiting = ISC_TRUE; free_listener(listener); } if (control != NULL) cfg_obj_log(control, ns_g_lctx, ISC_LOG_WARNING, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); else isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_CONTROL, ISC_LOG_NOTICE, "couldn't add command channel %s: %s", socktext, isc_result_totext(result)); *listenerp = NULL; } /* XXXDCL return error results? fail hard? */ }
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); }
isc_result_t dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm, dst_key_t *dstkey, isc_boolean_t generated, dns_name_t *creator, isc_stdtime_t inception, isc_stdtime_t expire, isc_mem_t *mctx, dns_tsig_keyring_t *ring, dns_tsigkey_t **key) { dns_tsigkey_t *tkey; isc_result_t ret; unsigned int refs = 0; REQUIRE(key == NULL || *key == NULL); REQUIRE(name != NULL); REQUIRE(algorithm != NULL); REQUIRE(mctx != NULL); REQUIRE(key != NULL || ring != NULL); tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t)); if (tkey == NULL) return (ISC_R_NOMEMORY); dns_name_init(&tkey->name, NULL); ret = dns_name_dup(name, mctx, &tkey->name); if (ret != ISC_R_SUCCESS) goto cleanup_key; (void)dns_name_downcase(&tkey->name, &tkey->name, NULL); if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) { tkey->algorithm = DNS_TSIG_HMACMD5_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA1_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA224_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA224) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA256_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA256) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA384_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA384) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) { tkey->algorithm = DNS_TSIG_HMACSHA512_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA512) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) { tkey->algorithm = DNS_TSIG_GSSAPI_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { ret = DNS_R_BADALG; goto cleanup_name; } } else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME; if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) { ret = DNS_R_BADALG; goto cleanup_name; } } else { if (dstkey != NULL) { ret = DNS_R_BADALG; goto cleanup_name; } tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t)); if (tkey->algorithm == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_name; } dns_name_init(tkey->algorithm, NULL); ret = dns_name_dup(algorithm, mctx, tkey->algorithm); if (ret != ISC_R_SUCCESS) goto cleanup_algorithm; (void)dns_name_downcase(tkey->algorithm, tkey->algorithm, NULL); } if (creator != NULL) { tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t)); if (tkey->creator == NULL) { ret = ISC_R_NOMEMORY; goto cleanup_algorithm; } dns_name_init(tkey->creator, NULL); ret = dns_name_dup(creator, mctx, tkey->creator); if (ret != ISC_R_SUCCESS) { isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); goto cleanup_algorithm; } } else tkey->creator = NULL; tkey->key = NULL; if (dstkey != NULL) dst_key_attach(dstkey, &tkey->key); tkey->ring = ring; if (key != NULL) refs = 1; if (ring != NULL) refs++; ret = isc_refcount_init(&tkey->refs, refs); if (ret != ISC_R_SUCCESS) goto cleanup_creator; tkey->generated = generated; tkey->inception = inception; tkey->expire = expire; tkey->mctx = NULL; isc_mem_attach(mctx, &tkey->mctx); ISC_LINK_INIT(tkey, link); tkey->magic = TSIG_MAGIC; if (ring != NULL) { ret = keyring_add(ring, name, tkey); if (ret != ISC_R_SUCCESS) goto cleanup_refs; } /* * Ignore this if it's a GSS key, since the key size is meaningless. */ if (dstkey != NULL && dst_key_size(dstkey) < 64 && !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) && !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) { char namestr[DNS_NAME_FORMATSIZE]; dns_name_format(name, namestr, sizeof(namestr)); isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC, DNS_LOGMODULE_TSIG, ISC_LOG_INFO, "the key '%s' is too short to be secure", namestr); } if (key != NULL) *key = tkey; return (ISC_R_SUCCESS); cleanup_refs: tkey->magic = 0; while (refs-- > 0) isc_refcount_decrement(&tkey->refs, NULL); isc_refcount_destroy(&tkey->refs); cleanup_creator: if (tkey->key != NULL) dst_key_free(&tkey->key); if (tkey->creator != NULL) { dns_name_free(tkey->creator, mctx); isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t)); } cleanup_algorithm: if (algname_is_allocated(tkey->algorithm)) { if (dns_name_dynamic(tkey->algorithm)) dns_name_free(tkey->algorithm, mctx); isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t)); } cleanup_name: dns_name_free(&tkey->name, mctx); cleanup_key: isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t)); return (ret); }
static void isc_httpd_accept(isc_task_t *task, isc_event_t *ev) { isc_result_t result; isc_httpdmgr_t *httpdmgr = ev->ev_arg; isc_httpd_t *httpd; isc_region_t r; isc_socket_newconnev_t *nev = (isc_socket_newconnev_t *)ev; isc_sockaddr_t peeraddr; ENTER("accept"); LOCK(&httpdmgr->lock); if (MSHUTTINGDOWN(httpdmgr)) { NOTICE("accept shutting down, goto out"); goto out; } if (nev->result == ISC_R_CANCELED) { NOTICE("accept canceled, goto out"); goto out; } if (nev->result != ISC_R_SUCCESS) { /* XXXMLG log failure */ NOTICE("accept returned failure, goto requeue"); goto requeue; } (void)isc_socket_getpeername(nev->newsocket, &peeraddr); if (httpdmgr->client_ok != NULL && !(httpdmgr->client_ok)(&peeraddr, httpdmgr->cb_arg)) { isc_socket_detach(&nev->newsocket); goto requeue; } httpd = isc_mem_get(httpdmgr->mctx, sizeof(isc_httpd_t)); if (httpd == NULL) { /* XXXMLG log failure */ NOTICE("accept failed to allocate memory, goto requeue"); isc_socket_detach(&nev->newsocket); goto requeue; } httpd->mgr = httpdmgr; ISC_LINK_INIT(httpd, link); ISC_LIST_APPEND(httpdmgr->running, httpd, link); ISC_HTTPD_SETRECV(httpd); httpd->sock = nev->newsocket; isc_socket_setname(httpd->sock, "httpd", NULL); httpd->flags = 0; /* * Initialize the buffer for our headers. */ httpd->headerdata = isc_mem_get(httpdmgr->mctx, HTTP_SENDGROW); if (httpd->headerdata == NULL) { isc_mem_put(httpdmgr->mctx, httpd, sizeof(isc_httpd_t)); isc_socket_detach(&nev->newsocket); goto requeue; } httpd->headerlen = HTTP_SENDGROW; isc_buffer_init(&httpd->headerbuffer, httpd->headerdata, httpd->headerlen); ISC_LIST_INIT(httpd->bufflist); isc_buffer_initnull(&httpd->bodybuffer); reset_client(httpd); r.base = (unsigned char *)httpd->recvbuf; r.length = HTTP_RECVLEN - 1; result = isc_socket_recv(httpd->sock, &r, 1, task, isc_httpd_recvdone, httpd); /* FIXME!!! */ POST(result); NOTICE("accept queued recv on socket"); requeue: result = isc_socket_accept(httpdmgr->sock, task, isc_httpd_accept, httpdmgr); if (result != ISC_R_SUCCESS) { /* XXXMLG what to do? Log failure... */ NOTICE("accept could not reaccept due to failure"); } out: UNLOCK(&httpdmgr->lock); httpdmgr_destroy(httpdmgr); isc_event_free(&ev); EXIT("accept"); }
isc_result_t dns_view_create(isc_mem_t *mctx, dns_rdataclass_t rdclass, const char *name, dns_view_t **viewp) { dns_view_t *view; isc_result_t result; /* * Create a view. */ REQUIRE(name != NULL); REQUIRE(viewp != NULL && *viewp == NULL); view = isc_mem_get(mctx, sizeof(*view)); if (view == NULL) return (ISC_R_NOMEMORY); view->mctx = NULL; isc_mem_attach(mctx, &view->mctx); view->name = isc_mem_strdup(mctx, name); if (view->name == NULL) { result = ISC_R_NOMEMORY; goto cleanup_view; } result = isc_mutex_init(&view->lock); if (result != ISC_R_SUCCESS) goto cleanup_name; view->zonetable = NULL; if (isc_bind9) { result = dns_zt_create(mctx, rdclass, &view->zonetable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "dns_zt_create() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto cleanup_mutex; } } view->secroots_priv = NULL; view->fwdtable = NULL; result = dns_fwdtable_create(mctx, &view->fwdtable); if (result != ISC_R_SUCCESS) { UNEXPECTED_ERROR(__FILE__, __LINE__, "dns_fwdtable_create() failed: %s", isc_result_totext(result)); result = ISC_R_UNEXPECTED; goto cleanup_zt; } view->acache = NULL; view->cache = NULL; view->cachedb = NULL; ISC_LIST_INIT(view->dlz_searched); ISC_LIST_INIT(view->dlz_unsearched); view->hints = NULL; view->resolver = NULL; view->adb = NULL; view->requestmgr = NULL; view->rdclass = rdclass; view->frozen = ISC_FALSE; view->task = NULL; result = isc_refcount_init(&view->references, 1); if (result != ISC_R_SUCCESS) goto cleanup_fwdtable; view->weakrefs = 0; view->attributes = (DNS_VIEWATTR_RESSHUTDOWN|DNS_VIEWATTR_ADBSHUTDOWN| DNS_VIEWATTR_REQSHUTDOWN); view->statickeys = NULL; view->dynamickeys = NULL; view->matchclients = NULL; view->matchdestinations = NULL; view->matchrecursiveonly = ISC_FALSE; result = dns_tsigkeyring_create(view->mctx, &view->dynamickeys); if (result != ISC_R_SUCCESS) goto cleanup_references; view->peers = NULL; view->order = NULL; view->delonly = NULL; view->rootdelonly = ISC_FALSE; view->rootexclude = NULL; view->adbstats = NULL; view->resstats = NULL; view->resquerystats = NULL; view->cacheshared = ISC_FALSE; ISC_LIST_INIT(view->dns64); view->dns64cnt = 0; /* * Initialize configuration data with default values. */ view->recursion = ISC_TRUE; view->auth_nxdomain = ISC_FALSE; /* Was true in BIND 8 */ view->additionalfromcache = ISC_TRUE; view->additionalfromauth = ISC_TRUE; view->enablednssec = ISC_TRUE; view->enablevalidation = ISC_TRUE; view->acceptexpired = ISC_FALSE; view->minimalresponses = ISC_FALSE; view->transfer_format = dns_one_answer; view->cacheacl = NULL; view->cacheonacl = NULL; view->queryacl = NULL; view->queryonacl = NULL; view->recursionacl = NULL; view->recursiononacl = NULL; view->sortlist = NULL; view->transferacl = NULL; view->notifyacl = NULL; view->updateacl = NULL; view->upfwdacl = NULL; view->denyansweracl = NULL; view->nocasecompress = NULL; view->answeracl_exclude = NULL; view->denyanswernames = NULL; view->answernames_exclude = NULL; view->rrl = NULL; view->provideixfr = ISC_TRUE; view->maxcachettl = 7 * 24 * 3600; view->maxncachettl = 3 * 3600; view->dstport = 53; view->preferred_glue = 0; view->flush = ISC_FALSE; view->dlv = NULL; view->maxudp = 0; view->situdp = 0; view->maxbits = 0; view->v4_aaaa = dns_aaaa_ok; view->v6_aaaa = dns_aaaa_ok; view->aaaa_acl = NULL; view->rpzs = NULL; dns_fixedname_init(&view->dlv_fixed); view->managed_keys = NULL; view->redirect = NULL; view->requestnsid = ISC_FALSE; view->requestsit = ISC_TRUE; view->new_zone_file = NULL; view->new_zone_config = NULL; view->cfg_destroy = NULL; if (isc_bind9) { result = dns_order_create(view->mctx, &view->order); if (result != ISC_R_SUCCESS) goto cleanup_dynkeys; } result = dns_peerlist_new(view->mctx, &view->peers); if (result != ISC_R_SUCCESS) goto cleanup_order; result = dns_aclenv_init(view->mctx, &view->aclenv); if (result != ISC_R_SUCCESS) goto cleanup_peerlist; ISC_LINK_INIT(view, link); ISC_EVENT_INIT(&view->resevent, sizeof(view->resevent), 0, NULL, DNS_EVENT_VIEWRESSHUTDOWN, resolver_shutdown, view, NULL, NULL, NULL); ISC_EVENT_INIT(&view->adbevent, sizeof(view->adbevent), 0, NULL, DNS_EVENT_VIEWADBSHUTDOWN, adb_shutdown, view, NULL, NULL, NULL); ISC_EVENT_INIT(&view->reqevent, sizeof(view->reqevent), 0, NULL, DNS_EVENT_VIEWREQSHUTDOWN, req_shutdown, view, NULL, NULL, NULL); view->viewlist = NULL; view->magic = DNS_VIEW_MAGIC; *viewp = view; return (ISC_R_SUCCESS); cleanup_peerlist: if (view->peers != NULL) dns_peerlist_detach(&view->peers); cleanup_order: if (view->order != NULL) dns_order_detach(&view->order); cleanup_dynkeys: if (view->dynamickeys != NULL) dns_tsigkeyring_detach(&view->dynamickeys); cleanup_references: isc_refcount_destroy(&view->references); cleanup_fwdtable: if (view->fwdtable != NULL) dns_fwdtable_destroy(&view->fwdtable); cleanup_zt: if (view->zonetable != NULL) dns_zt_detach(&view->zonetable); cleanup_mutex: DESTROYLOCK(&view->lock); cleanup_name: isc_mem_free(mctx, view->name); cleanup_view: isc_mem_putanddetach(&view->mctx, view, sizeof(*view)); return (result); }