isc_result_t fwd_print_list_buff(isc_mem_t *mctx, dns_forwarders_t *fwdrs, isc_buffer_t **out_buf) { isc_result_t result; size_t list_len; isc_buffer_t *dummy_fwdr_buf = NULL; /* fully dynamic allocation */ isc_buffer_t tmp_buf; /* hack: only the base buffer is allocated */ cfg_parser_t *parser = NULL; cfg_obj_t *forwarders_cfg = NULL; const cfg_obj_t *faddresses; const cfg_listelt_t *fwdr_cfg; /* config representation */ /* internal representation */ #if LIBDNS_VERSION_MAJOR < 140 isc_sockaddr_t *fwdr_int; #else /* LIBDNS_VERSION_MAJOR >= 140 */ dns_forwarder_t *fwdr_int; #endif isc_buffer_initnull(&tmp_buf); tmp_buf.mctx = mctx; CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); /* Create dummy string with list of IP addresses of the same length * as the original list of forwarders. Parse this string to obtain * nested cfg structures which will be filled with data for actual * forwarders. * * This is nasty hack but it is easiest way to create list of cfg_objs * I found. */ list_len = fwd_list_len(fwdrs); CHECK(fwd_list_gen_dummy_config_string(mctx, list_len, &dummy_fwdr_buf)); CHECK(cfg_parse_buffer(parser, dummy_fwdr_buf, cfg_type_forwarders, &forwarders_cfg)); /* Walk through internal representation and cfg representation and copy * data from the internal one to cfg data structures.*/ faddresses = cfg_tuple_get(forwarders_cfg, "addresses"); for (fwdr_int = ISC_LIST_HEAD( #if LIBDNS_VERSION_MAJOR < 140 fwdrs->addrs #else /* LIBDNS_VERSION_MAJOR >= 140 */ fwdrs->fwdrs #endif ), fwdr_cfg = cfg_list_first(faddresses); INSIST((fwdr_int == NULL) == (fwdr_cfg == NULL)), fwdr_int != NULL; fwdr_int = ISC_LIST_NEXT(fwdr_int, link), fwdr_cfg = cfg_list_next(fwdr_cfg)) { #if LIBDNS_VERSION_MAJOR < 140 fwdr_cfg->obj->value.sockaddr = *fwdr_int; #else /* LIBDNS_VERSION_MAJOR >= 140 */ fwdr_cfg->obj->value.sockaddrdscp.sockaddr = fwdr_int->addr; fwdr_cfg->obj->value.sockaddrdscp.dscp = fwdr_int->dscp; #endif } cfg_print(faddresses, buffer_append_str, &tmp_buf); /* create and copy string from tmp to output buffer */ CHECK(isc_buffer_allocate(mctx, out_buf, tmp_buf.used)); isc_buffer_putmem(*out_buf, isc_buffer_base(&tmp_buf), isc_buffer_usedlength(&tmp_buf)); cleanup: if (forwarders_cfg != NULL) cfg_obj_destroy(parser, &forwarders_cfg); if (parser != NULL) cfg_parser_destroy(&parser); if (dummy_fwdr_buf != NULL) { if (tmp_buf.base != NULL) isc_mem_put(mctx, tmp_buf.base, tmp_buf.length); isc_buffer_free(&dummy_fwdr_buf); } return result; }
/* * Convert a resolv.conf file into a config structure. */ isc_result_t ns_lwresd_parseeresolvconf(isc_mem_t *mctx, cfg_parser_t *pctx, cfg_obj_t **configp) { char text[4096]; char str[16]; isc_buffer_t b; lwres_context_t *lwctx = NULL; lwres_conf_t *lwc = NULL; isc_sockaddr_t sa; isc_netaddr_t na; int i; isc_result_t result; lwres_result_t lwresult; lwctx = NULL; lwresult = lwres_context_create(&lwctx, mctx, ns__lwresd_memalloc, ns__lwresd_memfree, LWRES_CONTEXT_SERVERMODE); if (lwresult != LWRES_R_SUCCESS) { result = ISC_R_NOMEMORY; goto cleanup; } lwresult = lwres_conf_parse(lwctx, lwresd_g_resolvconffile); if (lwresult != LWRES_R_SUCCESS) { result = DNS_R_SYNTAX; goto cleanup; } lwc = lwres_conf_get(lwctx); INSIST(lwc != NULL); isc_buffer_init(&b, text, sizeof(text)); CHECK(buffer_putstr(&b, "options {\n")); /* * Build the list of forwarders. */ if (lwc->nsnext > 0) { CHECK(buffer_putstr(&b, "\tforwarders {\n")); for (i = 0; i < lwc->nsnext; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr( &sa, &lwc->nameservers[i], ns_g_port)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t")); CHECK(isc_netaddr_totext(&na, &b)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } /* * Build the sortlist */ if (lwc->sortlistnxt > 0) { CHECK(buffer_putstr(&b, "\tsortlist {\n")); CHECK(buffer_putstr(&b, "\t\t{\n")); CHECK(buffer_putstr(&b, "\t\t\tany;\n")); CHECK(buffer_putstr(&b, "\t\t\t{\n")); for (i = 0; i < lwc->sortlistnxt; i++) { lwres_addr_t *lwaddr = &lwc->sortlist[i].addr; lwres_addr_t *lwmask = &lwc->sortlist[i].mask; unsigned int mask; CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwmask, 0)); isc_netaddr_fromsockaddr(&na, &sa); result = isc_netaddr_masktoprefixlen(&na, &mask); if (result != ISC_R_SUCCESS) { char addrtext[ISC_NETADDR_FORMATSIZE]; isc_netaddr_format(&na, addrtext, sizeof(addrtext)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_LWRESD, ISC_LOG_ERROR, "processing sortlist: '%s' is " "not a valid netmask", addrtext); goto cleanup; } CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, lwaddr, 0)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t\t\t")); CHECK(isc_netaddr_totext(&na, &b)); snprintf(str, sizeof(str), "%u", mask); CHECK(buffer_putstr(&b, "/")); CHECK(buffer_putstr(&b, str)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t\t\t};\n")); CHECK(buffer_putstr(&b, "\t\t};\n")); CHECK(buffer_putstr(&b, "\t};\n")); } CHECK(buffer_putstr(&b, "};\n\n")); CHECK(buffer_putstr(&b, "lwres {\n")); /* * Build the search path */ if (lwc->searchnxt > 0) { if (lwc->searchnxt > 0) { CHECK(buffer_putstr(&b, "\tsearch {\n")); for (i = 0; i < lwc->searchnxt; i++) { CHECK(buffer_putstr(&b, "\t\t\"")); CHECK(buffer_putstr(&b, lwc->search[i])); CHECK(buffer_putstr(&b, "\";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } } /* * Build the ndots line */ if (lwc->ndots != 1) { CHECK(buffer_putstr(&b, "\tndots ")); snprintf(str, sizeof(str), "%u", lwc->ndots); CHECK(buffer_putstr(&b, str)); CHECK(buffer_putstr(&b, ";\n")); } /* * Build the listen-on line */ if (lwc->lwnext > 0) { CHECK(buffer_putstr(&b, "\tlisten-on {\n")); for (i = 0; i < lwc->lwnext; i++) { CHECK(lwaddr_sockaddr_fromlwresaddr(&sa, &lwc->lwservers[i], 0)); isc_netaddr_fromsockaddr(&na, &sa); CHECK(buffer_putstr(&b, "\t\t")); CHECK(isc_netaddr_totext(&na, &b)); CHECK(buffer_putstr(&b, ";\n")); } CHECK(buffer_putstr(&b, "\t};\n")); } CHECK(buffer_putstr(&b, "};\n")); #if 0 printf("%.*s\n", (int)isc_buffer_usedlength(&b), (char *)isc_buffer_base(&b)); #endif lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); return (cfg_parse_buffer(pctx, &b, &cfg_type_namedconf, configp)); cleanup: if (lwctx != NULL) { lwres_conf_clear(lwctx); lwres_context_destroy(&lwctx); } return (result); }
static isc_result_t setup_dnsseckeys(dns_client_t *client) { isc_result_t result; cfg_parser_t *parser = NULL; const cfg_obj_t *keys = NULL; const cfg_obj_t *managed_keys = NULL; cfg_obj_t *bindkeys = NULL; const char *filename = anchorfile; if (!root_validation && !dlv_validation) return (ISC_R_SUCCESS); if (filename == NULL) { #ifndef WIN32 filename = NS_SYSCONFDIR "/bind.keys"; #else static char buf[MAX_PATH]; strlcpy(buf, isc_ntpaths_get(SYS_CONF_DIR), sizeof(buf)); strlcat(buf, "\\bind.keys", sizeof(buf)); filename = buf; #endif } if (trust_anchor == NULL) { trust_anchor = isc_mem_strdup(mctx, "."); if (trust_anchor == NULL) fatal("out of memory"); } if (trust_anchor != NULL) CHECK(convert_name(&afn, &anchor_name, trust_anchor)); if (dlv_anchor != NULL) CHECK(convert_name(&dfn, &dlv_name, dlv_anchor)); CHECK(cfg_parser_create(mctx, dns_lctx, &parser)); if (access(filename, R_OK) != 0) { if (anchorfile != NULL) fatal("Unable to read key file '%s'", anchorfile); } else { result = cfg_parse_file(parser, filename, &cfg_type_bindkeys, &bindkeys); if (result != ISC_R_SUCCESS) if (anchorfile != NULL) fatal("Unable to load keys from '%s'", anchorfile); } if (bindkeys == NULL) { isc_buffer_t b; isc_buffer_init(&b, anchortext, sizeof(anchortext) - 1); isc_buffer_add(&b, sizeof(anchortext) - 1); result = cfg_parse_buffer(parser, &b, &cfg_type_bindkeys, &bindkeys); if (result != ISC_R_SUCCESS) fatal("Unable to parse built-in keys"); } INSIST(bindkeys != NULL); cfg_map_get(bindkeys, "trusted-keys", &keys); cfg_map_get(bindkeys, "managed-keys", &managed_keys); if (keys != NULL) CHECK(load_keys(keys, client)); if (managed_keys != NULL) CHECK(load_keys(managed_keys, client)); result = ISC_R_SUCCESS; if (trusted_keys == 0) fatal("No trusted keys were loaded"); if (dlv_validation) dns_client_setdlv(client, dns_rdataclass_in, dlv_anchor); cleanup: if (result != ISC_R_SUCCESS) delv_log(ISC_LOG_ERROR, "setup_dnsseckeys: %s", isc_result_totext(result)); return (result); }