isc_boolean_t dns_compress_getsensitive(dns_compress_t *cctx) { REQUIRE(VALID_CCTX(cctx)); return (ISC_TF((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0)); }
isc_boolean_t isc_file_isabsolute(const char *filename) { REQUIRE(filename != NULL); return (ISC_TF(filename[0] == '/')); }
static void parse_args(isc_boolean_t is_batchfile, isc_boolean_t config_only, int argc, char **argv) { isc_result_t result; isc_textregion_t tr; isc_boolean_t firstarg = ISC_TRUE; dig_lookup_t *lookup = NULL; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; isc_boolean_t open_type_class = ISC_TRUE; char batchline[MXNAME]; int bargc; char *bargv[64]; int rc; char **rv; #ifndef NOPOSIX char *homedir; char rcfile[256]; #endif char *input; int i; isc_boolean_t need_clone = ISC_TRUE; /* * The semantics for parsing the args is a bit complex; if * we don't have a host yet, make the arg apply globally, * otherwise make it apply to the latest host. This is * a bit different than the previous versions, but should * form a consistent user interface. * * First, create a "default lookup" which won't actually be used * anywhere, except for cloning into new lookups */ debug("parse_args()"); if (!is_batchfile) { debug("making new lookup"); default_lookup = make_empty_lookup(); default_lookup->adflag = ISC_TRUE; default_lookup->edns = 0; #ifndef NOPOSIX /* * Treat ${HOME}/.digrc as a special batchfile */ INSIST(batchfp == NULL); homedir = getenv("HOME"); if (homedir != NULL) { unsigned int n; n = snprintf(rcfile, sizeof(rcfile), "%s/.digrc", homedir); if (n < sizeof(rcfile)) batchfp = fopen(rcfile, "r"); } if (batchfp != NULL) { while (fgets(batchline, sizeof(batchline), batchfp) != 0) { debug("config line %s", batchline); bargc = 1; input = batchline; bargv[bargc] = next_token(&input, " \t\r\n"); while ((bargv[bargc] != NULL) && (bargc < 62)) { bargc++; bargv[bargc] = next_token(&input, " \t\r\n"); } bargv[0] = argv[0]; argv0 = argv[0]; for(i = 0; i < bargc; i++) debug(".digrc argv %d: %s", i, bargv[i]); parse_args(ISC_TRUE, ISC_TRUE, bargc, (char **)bargv); } fclose(batchfp); } #endif } if (is_batchfile && !config_only) { /* Processing '-f batchfile'. */ lookup = clone_lookup(default_lookup, ISC_TRUE); need_clone = ISC_FALSE; } else lookup = default_lookup; rc = argc; rv = argv; for (rc--, rv++; rc > 0; rc--, rv++) { debug("main parsing %s", rv[0]); if (strncmp(rv[0], "%", 1) == 0) break; if (strncmp(rv[0], "@", 1) == 0) { addresscount = getaddresses(lookup, &rv[0][1], NULL); } else if (rv[0][0] == '+') { plus_option(&rv[0][1], is_batchfile, lookup); } else if (rv[0][0] == '-') { if (rc <= 1) { if (dash_option(&rv[0][1], NULL, &lookup, &open_type_class, &need_clone, config_only, argc, argv, &firstarg)) { rc--; rv++; } } else { if (dash_option(&rv[0][1], rv[1], &lookup, &open_type_class, &need_clone, config_only, argc, argv, &firstarg)) { rc--; rv++; } } } else { /* * Anything which isn't an option */ if (open_type_class) { if (strncasecmp(rv[0], "ixfr=", 5) == 0) { rdtype = dns_rdatatype_ixfr; result = ISC_R_SUCCESS; } else { tr.base = rv[0]; tr.length = strlen(rv[0]); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS && rdtype == dns_rdatatype_ixfr) { fprintf(stderr, ";; Warning, " "ixfr requires a " "serial number\n"); continue; } } if (result == ISC_R_SUCCESS) { if (lookup->rdtypeset) { fprintf(stderr, ";; Warning, " "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { isc_uint32_t serial; lookup->rdtype = dns_rdatatype_ixfr; lookup->rdtypeset = ISC_TRUE; result = parse_uint(&serial, &rv[0][5], MAXSERIAL, "serial number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse " "serial number"); lookup->ixfr_serial = serial; lookup->section_question = plusquest; lookup->comments = pluscomm; lookup->tcp_mode = ISC_TRUE; } else { lookup->rdtype = rdtype; lookup->rdtypeset = ISC_TRUE; if (rdtype == dns_rdatatype_axfr) { lookup->section_question = plusquest; lookup->comments = pluscomm; } lookup->ixfr_serial = ISC_FALSE; } continue; } result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { if (lookup->rdclassset) { fprintf(stderr, ";; Warning, " "extra class option\n"); } lookup->rdclass = rdclass; lookup->rdclassset = ISC_TRUE; continue; } } if (!config_only) { if (need_clone) lookup = clone_lookup(default_lookup, ISC_TRUE); need_clone = ISC_TRUE; strncpy(lookup->textname, rv[0], sizeof(lookup->textname)); lookup->textname[sizeof(lookup->textname)-1]=0; lookup->trace_root = ISC_TF(lookup->trace || lookup->ns_search_only); lookup->new_search = ISC_TRUE; if (firstarg) { printgreeting(argc, argv, lookup); firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, lookup, link); debug("looking up %s", lookup->textname); } /* XXX Error message */ } } /* * If we have a batchfile, seed the lookup list with the * first entry, then trust the callback in dighost_shutdown * to get the rest */ if ((batchname != NULL) && !(is_batchfile)) { if (strcmp(batchname, "-") == 0) batchfp = stdin; else batchfp = fopen(batchname, "r"); if (batchfp == NULL) { perror(batchname); if (exitcode < 8) exitcode = 8; fatal("couldn't open specified batch file"); } /* XXX Remove code dup from shutdown code */ next_line: if (fgets(batchline, sizeof(batchline), batchfp) != 0) { bargc = 1; debug("batch line %s", batchline); if (batchline[0] == '\r' || batchline[0] == '\n' || batchline[0] == '#' || batchline[0] == ';') goto next_line; input = batchline; bargv[bargc] = next_token(&input, " \t\r\n"); while ((bargv[bargc] != NULL) && (bargc < 14)) { bargc++; bargv[bargc] = next_token(&input, " \t\r\n"); } bargv[0] = argv[0]; argv0 = argv[0]; for(i = 0; i < bargc; i++) debug("batch argv %d: %s", i, bargv[i]); parse_args(ISC_TRUE, ISC_FALSE, bargc, (char **)bargv); return; } return; } /* * If no lookup specified, search for root */ if ((lookup_list.head == NULL) && !config_only) { if (need_clone) lookup = clone_lookup(default_lookup, ISC_TRUE); need_clone = ISC_TRUE; lookup->trace_root = ISC_TF(lookup->trace || lookup->ns_search_only); lookup->new_search = ISC_TRUE; strcpy(lookup->textname, "."); lookup->rdtype = dns_rdatatype_ns; lookup->rdtypeset = ISC_TRUE; if (firstarg) { printgreeting(argc, argv, lookup); firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, lookup, link); } if (!need_clone) destroy_lookup(lookup); }
isc_result_t cfg_acl_fromconfig2(const cfg_obj_t *caml, const cfg_obj_t *cctx, isc_log_t *lctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx, unsigned int nest_level, isc_uint16_t family, dns_acl_t **target) { isc_result_t result; dns_acl_t *dacl = NULL, *inneracl = NULL; dns_aclelement_t *de; const cfg_listelt_t *elt; dns_iptable_t *iptab; int new_nest_level = 0; if (nest_level != 0) new_nest_level = nest_level - 1; REQUIRE(target != NULL); REQUIRE(*target == NULL || DNS_ACL_VALID(*target)); if (*target != NULL) { /* * If target already points to an ACL, then we're being * called recursively to configure a nested ACL. The * nested ACL's contents should just be absorbed into its * parent ACL. */ dns_acl_attach(*target, &dacl); dns_acl_detach(target); } else { /* * Need to allocate a new ACL structure. Count the items * in the ACL definition that will require space in the * elements table. (Note that if nest_level is nonzero, * *everything* goes in the elements table.) */ isc_uint32_t nelem; if (nest_level == 0) { result = count_acl_elements(caml, cctx, lctx, ctx, mctx, &nelem, NULL); if (result != ISC_R_SUCCESS) return (result); } else nelem = cfg_list_length(caml, ISC_FALSE); result = dns_acl_create(mctx, nelem, &dacl); if (result != ISC_R_SUCCESS) return (result); } de = dacl->elements; for (elt = cfg_list_first(caml); elt != NULL; elt = cfg_list_next(elt)) { const cfg_obj_t *ce = cfg_listelt_value(elt); isc_boolean_t neg = ISC_FALSE; INSIST(dacl->length <= dacl->alloc); if (cfg_obj_istuple(ce)) { /* Might be a negated element */ const cfg_obj_t *negated = cfg_tuple_get(ce, "negated"); if (! cfg_obj_isvoid(negated)) { neg = ISC_TRUE; dacl->has_negatives = ISC_TRUE; ce = negated; } } /* * If nest_level is nonzero, then every element is * to be stored as a separate, nested ACL rather than * merged into the main iptable. */ iptab = dacl->iptable; if (nest_level != 0) { result = dns_acl_create(mctx, cfg_list_length(ce, ISC_FALSE), &de->nestedacl); if (result != ISC_R_SUCCESS) goto cleanup; iptab = de->nestedacl->iptable; } if (cfg_obj_isnetprefix(ce)) { /* Network prefix */ isc_netaddr_t addr; unsigned int bitlen; cfg_obj_asnetprefix(ce, &addr, &bitlen); if (family != 0 && family != addr.family) { char buf[ISC_NETADDR_FORMATSIZE + 1]; isc_netaddr_format(&addr, buf, sizeof(buf)); cfg_obj_log(ce, lctx, ISC_LOG_WARNING, "'%s': incorrect address family; " "ignoring", buf); if (nest_level != 0) dns_acl_detach(&de->nestedacl); continue; } result = isc_netaddr_prefixok(&addr, bitlen); if (result != ISC_R_SUCCESS) { char buf[ISC_NETADDR_FORMATSIZE + 1]; isc_netaddr_format(&addr, buf, sizeof(buf)); cfg_obj_log(ce, lctx, ISC_LOG_WARNING, "'%s/%u': address/prefix length " "mismatch", buf, bitlen); } /* * If nesting ACLs (nest_level != 0), we negate * the nestedacl element, not the iptable entry. */ result = dns_iptable_addprefix(iptab, &addr, bitlen, ISC_TF(nest_level != 0 || !neg)); if (result != ISC_R_SUCCESS) goto cleanup; if (nest_level > 0) { INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_nestedacl; de->negative = neg; } else continue; } else if (cfg_obj_islist(ce)) { /* * If we're nesting ACLs, put the nested * ACL onto the elements list; otherwise * merge it into *this* ACL. We nest ACLs * in two cases: 1) sortlist, 2) if the * nested ACL contains negated members. */ if (inneracl != NULL) dns_acl_detach(&inneracl); result = cfg_acl_fromconfig(ce, cctx, lctx, ctx, mctx, new_nest_level, &inneracl); if (result != ISC_R_SUCCESS) goto cleanup; nested_acl: if (nest_level > 0 || inneracl->has_negatives) { INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_nestedacl; de->negative = neg; if (de->nestedacl != NULL) dns_acl_detach(&de->nestedacl); dns_acl_attach(inneracl, &de->nestedacl); dns_acl_detach(&inneracl); /* Fall through. */ } else { INSIST(dacl->length + inneracl->length <= dacl->alloc); dns_acl_merge(dacl, inneracl, ISC_TF(!neg)); de += inneracl->length; /* elements added */ dns_acl_detach(&inneracl); INSIST(dacl->length <= dacl->alloc); continue; } } else if (cfg_obj_istype(ce, &cfg_type_keyref)) { /* Key name. */ INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_keyname; de->negative = neg; dns_name_init(&de->keyname, NULL); result = convert_keyname(ce, lctx, mctx, &de->keyname); if (result != ISC_R_SUCCESS) goto cleanup; #ifdef HAVE_GEOIP } else if (cfg_obj_istuple(ce) && cfg_obj_isvoid(cfg_tuple_get(ce, "negated"))) { INSIST(dacl->length < dacl->alloc); result = parse_geoip_element(ce, lctx, ctx, de); if (result != ISC_R_SUCCESS) goto cleanup; de->type = dns_aclelementtype_geoip; de->negative = neg; #endif /* HAVE_GEOIP */ } else if (cfg_obj_isstring(ce)) { /* ACL name. */ const char *name = cfg_obj_asstring(ce); if (strcasecmp(name, "any") == 0) { /* Iptable entry with zero bit length. */ result = dns_iptable_addprefix(iptab, NULL, 0, ISC_TF(nest_level != 0 || !neg)); if (result != ISC_R_SUCCESS) goto cleanup; if (nest_level != 0) { INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_nestedacl; de->negative = neg; } else continue; } else if (strcasecmp(name, "none") == 0) { /* none == !any */ /* * We don't unconditional set * dacl->has_negatives and * de->negative to true so we can handle * "!none;". */ result = dns_iptable_addprefix(iptab, NULL, 0, ISC_TF(nest_level != 0 || neg)); if (result != ISC_R_SUCCESS) goto cleanup; if (!neg) dacl->has_negatives = !neg; if (nest_level != 0) { INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_nestedacl; de->negative = !neg; } else continue; } else if (strcasecmp(name, "localhost") == 0) { INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_localhost; de->negative = neg; } else if (strcasecmp(name, "localnets") == 0) { INSIST(dacl->length < dacl->alloc); de->type = dns_aclelementtype_localnets; de->negative = neg; } else { if (inneracl != NULL) dns_acl_detach(&inneracl); /* * This call should just find the cached * of the named acl. */ result = convert_named_acl(ce, cctx, lctx, ctx, mctx, new_nest_level, &inneracl); if (result != ISC_R_SUCCESS) goto cleanup; goto nested_acl; } } else { cfg_obj_log(ce, lctx, ISC_LOG_WARNING, "address match list contains " "unsupported element type"); result = ISC_R_FAILURE; goto cleanup; } /* * This should only be reached for localhost, localnets * and keyname elements, and nested ACLs if nest_level is * nonzero (i.e., in sortlists). */ if (de->nestedacl != NULL && de->type != dns_aclelementtype_nestedacl) dns_acl_detach(&de->nestedacl); dacl->node_count++; de->node_num = dacl->node_count; dacl->length++; de++; INSIST(dacl->length <= dacl->alloc); } dns_acl_attach(dacl, target); result = ISC_R_SUCCESS; cleanup: if (inneracl != NULL) dns_acl_detach(&inneracl); dns_acl_detach(&dacl); return (result); }
static void setup(void) { isc_result_t result; isc_resourcevalue_t old_openfiles; #ifdef HAVE_LIBSCF char *instance = NULL; #endif /* * Get the user and group information before changing the root * directory, so the administrator does not need to keep a copy * of the user and group databases in the chroot'ed environment. */ ns_os_inituserinfo(ns_g_username); /* * Initialize time conversion information */ ns_os_tzset(); ns_os_opendevnull(); #ifdef HAVE_LIBSCF /* Check if named is under smf control, before chroot. */ result = ns_smf_get_instance(&instance, 0, ns_g_mctx); /* We don't care about instance, just check if we got one. */ if (result == ISC_R_SUCCESS) ns_smf_got_instance = 1; else ns_smf_got_instance = 0; if (instance != NULL) isc_mem_free(ns_g_mctx, instance); #endif /* HAVE_LIBSCF */ #ifdef PATH_RANDOMDEV /* * Initialize system's random device as fallback entropy source * if running chroot'ed. */ if (ns_g_chrootdir != NULL) { result = isc_entropy_create(ns_g_mctx, &ns_g_fallbackentropy); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_entropy_create() failed: %s", isc_result_totext(result)); result = isc_entropy_createfilesource(ns_g_fallbackentropy, PATH_RANDOMDEV); if (result != ISC_R_SUCCESS) { ns_main_earlywarning("could not open pre-chroot " "entropy source %s: %s", PATH_RANDOMDEV, isc_result_totext(result)); isc_entropy_detach(&ns_g_fallbackentropy); } } #endif #ifdef ISC_PLATFORM_USETHREADS /* * Check for the number of cpu's before ns_os_chroot(). */ ns_g_cpus_detected = isc_os_ncpus(); #endif ns_os_chroot(ns_g_chrootdir); /* * For operating systems which have a capability mechanism, now * is the time to switch to minimal privs and change our user id. * On traditional UNIX systems, this call will be a no-op, and we * will change the user ID after reading the config file the first * time. (We need to read the config file to know which possibly * privileged ports to bind() to.) */ ns_os_minprivs(); result = ns_log_init(ISC_TF(ns_g_username != NULL)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("ns_log_init() failed: %s", isc_result_totext(result)); /* * Now is the time to daemonize (if we're not running in the * foreground). We waited until now because we wanted to get * a valid logging context setup. We cannot daemonize any later, * because calling create_managers() will create threads, which * would be lost after fork(). */ if (!ns_g_foreground) ns_os_daemonize(); /* * We call isc_app_start() here as some versions of FreeBSD's fork() * destroys all the signal handling it sets up. */ result = isc_app_start(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_app_start() failed: %s", isc_result_totext(result)); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "starting BIND %s%s", ns_g_version, saved_command_line); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "built with %s", ns_g_configargs); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "BIND 9 is maintained by Internet Systems Consortium,"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "Inc. (ISC), a non-profit 501(c)(3) public-benefit "); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "corporation. Support and training for BIND 9 are "); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "available at https://www.isc.org/support"); isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "----------------------------------------------------"); dump_symboltable(); /* * Get the initial resource limits. */ (void)isc_resource_getlimit(isc_resource_stacksize, &ns_g_initstacksize); (void)isc_resource_getlimit(isc_resource_datasize, &ns_g_initdatasize); (void)isc_resource_getlimit(isc_resource_coresize, &ns_g_initcoresize); (void)isc_resource_getlimit(isc_resource_openfiles, &ns_g_initopenfiles); /* * System resources cannot effectively be tuned on some systems. * Raise the limit in such cases for safety. */ old_openfiles = ns_g_initopenfiles; ns_os_adjustnofile(); (void)isc_resource_getlimit(isc_resource_openfiles, &ns_g_initopenfiles); if (old_openfiles != ns_g_initopenfiles) { isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL, NS_LOGMODULE_MAIN, ISC_LOG_NOTICE, "adjusted limit on open files from " "%" ISC_PRINT_QUADFORMAT "u to " "%" ISC_PRINT_QUADFORMAT "u", old_openfiles, ns_g_initopenfiles); } /* * If the named configuration filename is relative, prepend the current * directory's name before possibly changing to another directory. */ if (! isc_file_isabsolute(ns_g_conffile)) { result = isc_file_absolutepath(ns_g_conffile, absolute_conffile, sizeof(absolute_conffile)); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("could not construct absolute path " "of configuration file: %s", isc_result_totext(result)); ns_g_conffile = absolute_conffile; } /* * Record the server's startup time. */ result = isc_time_now(&ns_g_boottime); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("isc_time_now() failed: %s", isc_result_totext(result)); result = create_managers(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("create_managers() failed: %s", isc_result_totext(result)); ns_builtin_init(); /* * Add calls to register sdb drivers here. */ /* xxdb_init(); */ #ifdef ISC_DLZ_DLOPEN /* * Register the DLZ "dlopen" driver. */ result = dlz_dlopen_init(ns_g_mctx); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("dlz_dlopen_init() failed: %s", isc_result_totext(result)); #endif #if CONTRIB_DLZ /* * Register any other contributed DLZ drivers. */ result = dlz_drivers_init(); if (result != ISC_R_SUCCESS) ns_main_earlyfatal("dlz_drivers_init() failed: %s", isc_result_totext(result)); #endif ns_server_create(ns_g_mctx, &ns_g_server); }
/* * Called at startup for each dlopen zone in named.conf */ static isc_result_t dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { dlopen_data_t *cd; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_FAILURE; isc_boolean_t triedload = ISC_FALSE; UNUSED(driverarg); if (argc < 2) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen driver for '%s' needs a path to " "the shared library", dlzname); return (ISC_R_FAILURE); } isc_mem_create(0, 0, &mctx); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { isc_mem_destroy(&mctx); return (ISC_R_NOMEMORY); } memset(cd, 0, sizeof(*cd)); cd->mctx = mctx; cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); if (cd->dl_path == NULL) { result = ISC_R_NOMEMORY; goto failed; } cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); if (cd->dlzname == NULL) { result = ISC_R_NOMEMORY; goto failed; } triedload = ISC_TRUE; /* Initialize the lock */ result = isc_mutex_init(&cd->lock); if (result != ISC_R_SUCCESS) goto failed; /* Open the library */ cd->dl_handle = LoadLibraryA(cd->dl_path); if (cd->dl_handle == NULL) { unsigned int error = GetLastError(); dlopen_log(ISC_LOG_ERROR, "dlz_dlopen failed to open library '%s' - %u", cd->dl_path, error); result = ISC_R_FAILURE; goto cleanup_lock; } /* Find the symbols */ cd->dlz_version = (dlz_dlopen_version_t *) dl_load_symbol(cd, "dlz_version", ISC_TRUE); cd->dlz_create = (dlz_dlopen_create_t *) dl_load_symbol(cd, "dlz_create", ISC_TRUE); cd->dlz_lookup = (dlz_dlopen_lookup_t *) dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); if (cd->dlz_create == NULL || cd->dlz_version == NULL || cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) { /* We're missing a required symbol */ result = ISC_R_FAILURE; goto cleanup_lock; } cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) dl_load_symbol(cd, "dlz_allnodes", ISC_TF(cd->dlz_allowzonexfr != NULL)); cd->dlz_authority = (dlz_dlopen_authority_t *) dl_load_symbol(cd, "dlz_authority", ISC_FALSE); cd->dlz_newversion = (dlz_dlopen_newversion_t *) dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) dl_load_symbol(cd, "dlz_closeversion", ISC_TF(cd->dlz_newversion != NULL)); cd->dlz_configure = (dlz_dlopen_configure_t *) dl_load_symbol(cd, "dlz_configure", ISC_FALSE); cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); if (cd->version < (DLZ_DLOPEN_VERSION - DLZ_DLOPEN_AGE) || cd->version > DLZ_DLOPEN_VERSION) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: %s: incorrect driver API version %d, " "requires %d", cd->dl_path, cd->version, DLZ_DLOPEN_VERSION); result = ISC_R_FAILURE; goto cleanup_lock; } /* * Call the library's create function. Note that this is an * extended version of dlz create, with the addition of * named function pointers for helper functions that the * driver will need. This avoids the need for the backend to * link the BIND9 libraries */ MAYBE_LOCK(cd); result = cd->dlz_create(dlzname, argc-1, argv+1, &cd->dbdata, "log", dlopen_log, "putrr", dns_sdlz_putrr, "putnamedrr", dns_sdlz_putnamedrr, "writeable_zone", dns_dlz_writeablezone, NULL); MAYBE_UNLOCK(cd); if (result != ISC_R_SUCCESS) goto cleanup_lock; *dbdata = cd; return (ISC_R_SUCCESS); cleanup_lock: DESTROYLOCK(&cd->lock); failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); if (cd->dl_path) isc_mem_free(mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(mctx, cd->dlzname); if (triedload) (void) isc_mutex_destroy(&cd->lock); if (cd->dl_handle) FreeLibrary(cd->dl_handle); isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); return (result); }
/** * Convert and copy value to setting structure. * * @retval ISC_R_SUCCESS New value was converted and copied. * @retval ISC_R_IGNORE New and old values are same, no change was made. * @retval ISC_R_NOMEMORY * @retval ISC_R_UNEXPECTEDEND * @retval ISC_R_UNEXPECTEDTOKEN * @retval others Other errors from isc_parse_uint32(). */ static isc_result_t ATTR_NONNULLS ATTR_CHECKRESULT set_value(isc_mem_t *mctx, const settings_set_t *set, setting_t *setting, const char *value) { isc_result_t result; isc_uint32_t numeric_value; isc_uint32_t len; REQUIRE(setting != NULL); REQUIRE(value != NULL); REQUIRE(set != NULL); /* catch attempts to modify built-in defaults */ REQUIRE(set->lock != NULL); LOCK(set->lock); /* Check and convert new values. */ switch (setting->type) { case ST_STRING: if (setting->filled && strcmp(setting->value.value_char, value) == 0) CLEANUP_WITH(ISC_R_IGNORE); break; case ST_UNSIGNED_INTEGER: if (*value == '\0') CLEANUP_WITH(ISC_R_UNEXPECTEDEND); result = isc_parse_uint32(&numeric_value, value, 10); if (result != ISC_R_SUCCESS) { log_error_r("setting '%s' has to be unsigned integer " "(base 10)", setting->name); goto cleanup; } if (setting->filled && setting->value.value_uint == numeric_value) CLEANUP_WITH(ISC_R_IGNORE); break; case ST_BOOLEAN: if (strcasecmp(value, "yes") == 0 || strcasecmp(value, "true") == 0) numeric_value = 1; else if (strcasecmp(value, "no") == 0 || strcasecmp(value, "false") == 0) numeric_value = 0; else { log_error("unknown boolean expression " "(setting '%s': value '%s')", setting->name, value); CLEANUP_WITH(ISC_R_UNEXPECTEDTOKEN); } if (setting->filled && setting->value.value_boolean == ISC_TF(numeric_value)) CLEANUP_WITH(ISC_R_IGNORE); break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, "invalid setting_type_t value %u", setting->type); break; } switch (setting->type) { case ST_STRING: len = strlen(value) + 1; if (setting->is_dynamic) isc_mem_free(mctx, setting->value.value_char); CHECKED_MEM_ALLOCATE(mctx, setting->value.value_char, len); setting->is_dynamic = ISC_TRUE; CHECK(isc_string_copy(setting->value.value_char, len, value)); break; case ST_UNSIGNED_INTEGER: setting->value.value_uint = numeric_value; break; case ST_BOOLEAN: setting->value.value_boolean = ISC_TF(numeric_value); break; default: UNEXPECTED_ERROR(__FILE__, __LINE__, "invalid setting_type_t value %u", setting->type); break; } setting->filled = 1; result = ISC_R_SUCCESS; cleanup: UNLOCK(set->lock); return result; }
static inline isc_result_t fromtext_in_apl(ARGS_FROMTEXT) { isc_token_t token; unsigned char addr[16]; unsigned long afi; isc_uint8_t prefix; isc_uint8_t len; isc_boolean_t neg; char *cp, *ap, *slash; int n; REQUIRE(type == 42); REQUIRE(rdclass == 1); UNUSED(type); UNUSED(rdclass); UNUSED(origin); UNUSED(options); UNUSED(callbacks); do { RETERR(isc_lex_getmastertoken(lexer, &token, isc_tokentype_string, ISC_TRUE)); if (token.type != isc_tokentype_string) break; cp = DNS_AS_STR(token); neg = ISC_TF(*cp == '!'); if (neg) cp++; afi = strtoul(cp, &ap, 10); if (*ap++ != ':' || cp == ap) RETTOK(DNS_R_SYNTAX); if (afi > 0xffffU) RETTOK(ISC_R_RANGE); slash = strchr(ap, '/'); if (slash == NULL || slash == ap) RETTOK(DNS_R_SYNTAX); RETTOK(isc_parse_uint8(&prefix, slash + 1, 10)); switch (afi) { case 1: *slash = '\0'; n = inet_pton(AF_INET, ap, addr); *slash = '/'; if (n != 1) RETTOK(DNS_R_BADDOTTEDQUAD); if (prefix > 32) RETTOK(ISC_R_RANGE); for (len = 4; len > 0; len--) if (addr[len - 1] != 0) break; break; case 2: *slash = '\0'; n = inet_pton(AF_INET6, ap, addr); *slash = '/'; if (n != 1) RETTOK(DNS_R_BADAAAA); if (prefix > 128) RETTOK(ISC_R_RANGE); for (len = 16; len > 0; len--) if (addr[len - 1] != 0) break; break; default: RETTOK(ISC_R_NOTIMPLEMENTED); } RETERR(uint16_tobuffer(afi, target)); RETERR(uint8_tobuffer(prefix, target)); RETERR(uint8_tobuffer(len | ((neg) ? 0x80 : 0), target)); RETERR(mem_tobuffer(target, addr, len)); } while (1); /* * Let upper layer handle eol/eof. */ isc_lex_ungettoken(lexer, &token); return (ISC_R_SUCCESS); }
static inline isc_result_t totext_soa(ARGS_TOTEXT) { isc_region_t dregion; dns_name_t mname; dns_name_t rname; dns_name_t prefix; isc_boolean_t sub; int i; isc_boolean_t multiline; isc_boolean_t comment; REQUIRE(rdata->type == 6); REQUIRE(rdata->length != 0); multiline = ISC_TF((tctx->flags & DNS_STYLEFLAG_MULTILINE) != 0); if (multiline) comment = ISC_TF((tctx->flags & DNS_STYLEFLAG_COMMENT) != 0); else comment = ISC_FALSE; dns_name_init(&mname, NULL); dns_name_init(&rname, NULL); dns_name_init(&prefix, NULL); dns_rdata_toregion(rdata, &dregion); dns_name_fromregion(&mname, &dregion); isc_region_consume(&dregion, name_length(&mname)); dns_name_fromregion(&rname, &dregion); isc_region_consume(&dregion, name_length(&rname)); sub = name_prefix(&mname, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); RETERR(str_totext(" ", target)); sub = name_prefix(&rname, tctx->origin, &prefix); RETERR(dns_name_totext(&prefix, sub, target)); if (multiline) RETERR(str_totext(" (" , target)); RETERR(str_totext(tctx->linebreak, target)); for (i = 0; i < 5; i++) { char buf[sizeof("0123456789 ; ")]; unsigned long num; num = uint32_fromregion(&dregion); isc_region_consume(&dregion, 4); sprintf(buf, comment ? "%-10lu ; " : "%lu", num); RETERR(str_totext(buf, target)); if (comment) { RETERR(str_totext(soa_fieldnames[i], target)); /* Print times in week/day/hour/minute/second form */ if (i >= 1) { RETERR(str_totext(" (", target)); RETERR(dns_ttl_totext(num, ISC_TRUE, target)); RETERR(str_totext(")", target)); } RETERR(str_totext(tctx->linebreak, target)); } else if (i < 4) { RETERR(str_totext(tctx->linebreak, target)); } } if (multiline) RETERR(str_totext(")", target)); return (ISC_R_SUCCESS); }
static inline isc_boolean_t isusertype(dns_rdatatype_t type) { return (ISC_TF(type != dns_rdatatype_ns && type != dns_rdatatype_soa && type != dns_rdatatype_rrsig)); }
static inline isc_result_t totext_in_apl(ARGS_TOTEXT) { isc_region_t sr; isc_region_t ir; isc_uint16_t afi; isc_uint8_t prefix; isc_uint8_t len; isc_boolean_t neg; unsigned char buf[16]; char txt[sizeof(" !64000")]; const char *sep = ""; int n; REQUIRE(rdata->type == 42); REQUIRE(rdata->rdclass == 1); UNUSED(tctx); dns_rdata_toregion(rdata, &sr); ir.base = buf; ir.length = sizeof(buf); while (sr.length > 0) { INSIST(sr.length >= 4); afi = uint16_fromregion(&sr); isc_region_consume(&sr, 2); prefix = *sr.base; isc_region_consume(&sr, 1); len = (*sr.base & 0x7f); neg = ISC_TF((*sr.base & 0x80) != 0); isc_region_consume(&sr, 1); INSIST(len <= sr.length); n = snprintf(txt, sizeof(txt), "%s%s%u:", sep, neg ? "!": "", afi); INSIST(n < (int)sizeof(txt)); RETERR(str_totext(txt, target)); switch (afi) { case 1: INSIST(len <= 4); INSIST(prefix <= 32); memset(buf, 0, sizeof(buf)); memcpy(buf, sr.base, len); RETERR(inet_totext(AF_INET, &ir, target)); break; case 2: INSIST(len <= 16); INSIST(prefix <= 128); memset(buf, 0, sizeof(buf)); memcpy(buf, sr.base, len); RETERR(inet_totext(AF_INET6, &ir, target)); break; default: return (ISC_R_NOTIMPLEMENTED); } n = snprintf(txt, sizeof(txt), "/%u", prefix); INSIST(n < (int)sizeof(txt)); RETERR(str_totext(txt, target)); isc_region_consume(&sr, len); sep = " "; } return (ISC_R_SUCCESS); }
/* * Called at startup for each dlopen zone in named.conf */ static isc_result_t dlopen_dlz_create(const char *dlzname, unsigned int argc, char *argv[], void *driverarg, void **dbdata) { dlopen_data_t *cd; isc_mem_t *mctx = NULL; isc_result_t result = ISC_R_FAILURE; int dlopen_flags = 0; UNUSED(driverarg); if (argc < 2) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen driver for '%s' needs a path to " "the shared library", dlzname); return (ISC_R_FAILURE); } isc_mem_create(0, 0, &mctx); cd = isc_mem_get(mctx, sizeof(*cd)); if (cd == NULL) { isc_mem_destroy(&mctx); return (ISC_R_NOMEMORY); } memset(cd, 0, sizeof(*cd)); cd->mctx = mctx; cd->dl_path = isc_mem_strdup(cd->mctx, argv[1]); if (cd->dl_path == NULL) { goto failed; } cd->dlzname = isc_mem_strdup(cd->mctx, dlzname); if (cd->dlzname == NULL) { goto failed; } /* Initialize the lock */ isc_mutex_init(&cd->lock); /* Open the library */ dlopen_flags = RTLD_NOW|RTLD_GLOBAL; #ifdef RTLD_DEEPBIND /* * If RTLD_DEEPBIND is available then use it. This can avoid * issues with a module using a different version of a system * library than one that bind9 uses. For example, bind9 may link * to MIT kerberos, but the module may use Heimdal. If we don't * use RTLD_DEEPBIND then we could end up with Heimdal functions * calling MIT functions, which leads to bizarre results (usually * a segfault). */ dlopen_flags |= RTLD_DEEPBIND; #endif cd->dl_handle = dlopen(cd->dl_path, dlopen_flags); if (cd->dl_handle == NULL) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen failed to open library '%s' - %s", cd->dl_path, dlerror()); goto failed; } /* Find the symbols */ cd->dlz_version = (dlz_dlopen_version_t *) dl_load_symbol(cd, "dlz_version", ISC_TRUE); cd->dlz_create = (dlz_dlopen_create_t *) dl_load_symbol(cd, "dlz_create", ISC_TRUE); cd->dlz_lookup = (dlz_dlopen_lookup_t *) dl_load_symbol(cd, "dlz_lookup", ISC_TRUE); cd->dlz_findzonedb = (dlz_dlopen_findzonedb_t *) dl_load_symbol(cd, "dlz_findzonedb", ISC_TRUE); if (cd->dlz_create == NULL || cd->dlz_lookup == NULL || cd->dlz_findzonedb == NULL) { /* We're missing a required symbol */ goto failed; } cd->dlz_allowzonexfr = (dlz_dlopen_allowzonexfr_t *) dl_load_symbol(cd, "dlz_allowzonexfr", ISC_FALSE); cd->dlz_allnodes = (dlz_dlopen_allnodes_t *) dl_load_symbol(cd, "dlz_allnodes", ISC_TF(cd->dlz_allowzonexfr != NULL)); cd->dlz_authority = (dlz_dlopen_authority_t *) dl_load_symbol(cd, "dlz_authority", ISC_FALSE); cd->dlz_newversion = (dlz_dlopen_newversion_t *) dl_load_symbol(cd, "dlz_newversion", ISC_FALSE); cd->dlz_closeversion = (dlz_dlopen_closeversion_t *) dl_load_symbol(cd, "dlz_closeversion", ISC_TF(cd->dlz_newversion != NULL)); cd->dlz_configure = (dlz_dlopen_configure_t *) dl_load_symbol(cd, "dlz_configure", ISC_FALSE); cd->dlz_ssumatch = (dlz_dlopen_ssumatch_t *) dl_load_symbol(cd, "dlz_ssumatch", ISC_FALSE); cd->dlz_addrdataset = (dlz_dlopen_addrdataset_t *) dl_load_symbol(cd, "dlz_addrdataset", ISC_FALSE); cd->dlz_subrdataset = (dlz_dlopen_subrdataset_t *) dl_load_symbol(cd, "dlz_subrdataset", ISC_FALSE); cd->dlz_delrdataset = (dlz_dlopen_delrdataset_t *) dl_load_symbol(cd, "dlz_delrdataset", ISC_FALSE); cd->dlz_destroy = (dlz_dlopen_destroy_t *) dl_load_symbol(cd, "dlz_destroy", ISC_FALSE); /* Check the version of the API is the same */ cd->version = cd->dlz_version(&cd->flags); if (cd->version != DLZ_DLOPEN_VERSION) { dlopen_log(ISC_LOG_ERROR, "dlz_dlopen: incorrect version %d " "should be %d in '%s'", cd->version, DLZ_DLOPEN_VERSION, cd->dl_path); goto failed; } /* * Call the library's create function. Note that this is an * extended version of dlz create, with the addition of * named function pointers for helper functions that the * driver will need. This avoids the need for the backend to * link the BIND9 libraries */ MAYBE_LOCK(cd); result = cd->dlz_create(dlzname, argc-1, argv+1, &cd->dbdata, "log", dlopen_log, "putrr", dns_sdlz_putrr, "putnamedrr", dns_sdlz_putnamedrr, "writeable_zone", dns_dlz_writeablezone, NULL); MAYBE_UNLOCK(cd); if (result != ISC_R_SUCCESS) goto failed; *dbdata = cd; return (ISC_R_SUCCESS); failed: dlopen_log(ISC_LOG_ERROR, "dlz_dlopen of '%s' failed", dlzname); if (cd->dl_path) isc_mem_free(mctx, cd->dl_path); if (cd->dlzname) isc_mem_free(mctx, cd->dlzname); if (dlopen_flags) (void) isc_mutex_destroy(&cd->lock); #ifdef HAVE_DLCLOSE if (cd->dl_handle) dlclose(cd->dl_handle); #endif isc_mem_put(mctx, cd, sizeof(*cd)); isc_mem_destroy(&mctx); 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 plus_option(char *option, isc_boolean_t is_batchfile, dig_lookup_t *lookup) { isc_result_t result; char option_store[256]; char *cmd, *value, *ptr; isc_uint32_t num; isc_boolean_t state = ISC_TRUE; #ifdef DIG_SIGCHASE size_t n; #endif strncpy(option_store, option, sizeof(option_store)); option_store[sizeof(option_store)-1]=0; ptr = option_store; cmd = next_token(&ptr,"="); if (cmd == NULL) { printf(";; Invalid option %s\n", option_store); return; } value = ptr; if (strncasecmp(cmd, "no", 2)==0) { cmd += 2; state = ISC_FALSE; } #define FULLCHECK(A) \ do { \ size_t _l = strlen(cmd); \ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ goto invalid_option; \ } while (0) #define FULLCHECK2(A, B) \ do { \ size_t _l = strlen(cmd); \ if ((_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) && \ (_l >= sizeof(B) || strncasecmp(cmd, B, _l) != 0)) \ goto invalid_option; \ } while (0) switch (cmd[0]) { case 'a': switch (cmd[1]) { case 'a': /* aaonly / aaflag */ FULLCHECK2("aaonly", "aaflag"); lookup->aaonly = state; break; case 'd': switch (cmd[2]) { case 'd': /* additional */ FULLCHECK("additional"); lookup->section_additional = state; break; case 'f': /* adflag */ case '\0': /* +ad is a synonym for +adflag */ FULLCHECK("adflag"); lookup->adflag = state; break; default: goto invalid_option; } break; case 'l': /* all */ FULLCHECK("all"); lookup->section_question = state; lookup->section_authority = state; lookup->section_answer = state; lookup->section_additional = state; lookup->comments = state; rrcomments = state; lookup->stats = state; printcmd = state; break; case 'n': /* answer */ FULLCHECK("answer"); lookup->section_answer = state; break; case 'u': /* authority */ FULLCHECK("authority"); lookup->section_authority = state; break; default: goto invalid_option; } break; case 'b': switch (cmd[1]) { case 'e':/* besteffort */ FULLCHECK("besteffort"); lookup->besteffort = state; break; case 'u':/* bufsize */ FULLCHECK("bufsize"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&num, value, COMMSIZE, "buffer size"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse buffer size"); lookup->udpsize = num; break; default: goto invalid_option; } break; case 'c': switch (cmd[1]) { case 'd':/* cdflag */ switch (cmd[2]) { case 'f': /* cdflag */ case '\0': /* +cd is a synonym for +cdflag */ FULLCHECK("cdflag"); lookup->cdflag = state; break; default: goto invalid_option; } break; case 'l': /* cl */ FULLCHECK("cl"); noclass = ISC_TF(!state); break; case 'm': /* cmd */ FULLCHECK("cmd"); printcmd = state; break; case 'o': /* comments */ FULLCHECK("comments"); lookup->comments = state; if (lookup == default_lookup) pluscomm = state; break; default: goto invalid_option; } break; case 'd': switch (cmd[1]) { case 'e': /* defname */ FULLCHECK("defname"); if (!lookup->trace) { usesearch = state; } break; case 'n': /* dnssec */ FULLCHECK("dnssec"); if (state && lookup->edns == -1) lookup->edns = 0; lookup->dnssec = state; break; case 'o': /* domain */ FULLCHECK("domain"); if (value == NULL) goto need_value; if (!state) goto invalid_option; strncpy(domainopt, value, sizeof(domainopt)); domainopt[sizeof(domainopt)-1] = '\0'; break; default: goto invalid_option; } break; case 'e': FULLCHECK("edns"); if (!state) { lookup->edns = -1; break; } if (value == NULL) { lookup->edns = 0; break; } result = parse_uint(&num, value, 255, "edns"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse edns"); lookup->edns = num; break; case 'f': /* fail */ FULLCHECK("fail"); lookup->servfail_stops = state; break; case 'i': switch (cmd[1]) { case 'd': /* identify */ FULLCHECK("identify"); lookup->identify = state; break; case 'g': /* ignore */ default: /* Inherits default for compatibility */ FULLCHECK("ignore"); lookup->ignore = ISC_TRUE; } break; case 'k': FULLCHECK("keepopen"); keep_open = state; break; case 'm': /* multiline */ FULLCHECK("multiline"); multiline = state; break; case 'n': switch (cmd[1]) { case 'd': /* ndots */ FULLCHECK("ndots"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&num, value, MAXNDOTS, "ndots"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse ndots"); ndots = num; break; case 's': switch (cmd[2]) { case 'i': /* nsid */ FULLCHECK("nsid"); if (state && lookup->edns == -1) lookup->edns = 0; lookup->nsid = state; break; case 's': /* nssearch */ FULLCHECK("nssearch"); lookup->ns_search_only = state; if (state) { lookup->trace_root = ISC_TRUE; lookup->recurse = ISC_TRUE; lookup->identify = ISC_TRUE; lookup->stats = ISC_FALSE; lookup->comments = ISC_FALSE; rrcomments = ISC_FALSE; lookup->section_additional = ISC_FALSE; lookup->section_authority = ISC_FALSE; lookup->section_question = ISC_FALSE; lookup->rdtype = dns_rdatatype_ns; lookup->rdtypeset = ISC_TRUE; short_form = ISC_TRUE; } break; default: goto invalid_option; } break; default: goto invalid_option; } break; case 'o': FULLCHECK("onesoa"); onesoa = state; break; case 'q': switch (cmd[1]) { case 'r': /* qr */ FULLCHECK("qr"); qr = state; break; case 'u': /* question */ FULLCHECK("question"); lookup->section_question = state; if (lookup == default_lookup) plusquest = state; break; default: goto invalid_option; } break; case 'r': switch (cmd[1]) { case 'e': switch (cmd[2]) { case 'c': /* recurse */ FULLCHECK("recurse"); lookup->recurse = state; break; case 't': /* retry / retries */ FULLCHECK2("retry", "retries"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&lookup->retries, value, MAXTRIES - 1, "retries"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse retries"); lookup->retries++; break; default: goto invalid_option; } break; case 'r': /* rrcomments */ FULLCHECK("rrcomments"); rrcomments = state; break; default: goto invalid_option; } break; case 's': switch (cmd[1]) { case 'e': /* search */ FULLCHECK("search"); if (!lookup->trace) { usesearch = state; } break; case 'h': if (cmd[2] != 'o') goto invalid_option; switch (cmd[3]) { case 'r': /* short */ FULLCHECK("short"); short_form = state; if (state) { printcmd = ISC_FALSE; lookup->section_additional = ISC_FALSE; lookup->section_answer = ISC_TRUE; lookup->section_authority = ISC_FALSE; lookup->section_question = ISC_FALSE; lookup->comments = ISC_FALSE; rrcomments = ISC_FALSE; lookup->stats = ISC_FALSE; } break; case 'w': /* showsearch */ FULLCHECK("showsearch"); if (!lookup->trace) { showsearch = state; usesearch = state; } break; default: goto invalid_option; } break; #ifdef DIG_SIGCHASE case 'i': /* sigchase */ FULLCHECK("sigchase"); lookup->sigchase = state; if (lookup->sigchase) lookup->dnssec = ISC_TRUE; break; #endif case 'p': /* split */ FULLCHECK("split"); if (value != NULL && !state) goto invalid_option; if (!state) { splitwidth = 0; break; } else if (value == NULL) break; result = parse_uint(&splitwidth, value, 1023, "split"); if (splitwidth % 4 != 0) { splitwidth = ((splitwidth + 3) / 4) * 4; fprintf(stderr, ";; Warning, split must be " "a multiple of 4; adjusting " "to %d\n", splitwidth); } /* * There is an adjustment done in the * totext_<rrtype>() functions which causes * splitwidth to shrink. This is okay when we're * using the default width but incorrect in this * case, so we correct for it */ if (splitwidth) splitwidth += 3; if (result != ISC_R_SUCCESS) fatal("Couldn't parse retries"); break; case 't': /* stats */ FULLCHECK("stats"); lookup->stats = state; break; default: goto invalid_option; } break; case 't': switch (cmd[1]) { case 'c': /* tcp */ FULLCHECK("tcp"); if (!is_batchfile) lookup->tcp_mode = state; break; case 'i': /* timeout */ FULLCHECK("timeout"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&timeout, value, MAXTIMEOUT, "timeout"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse timeout"); if (timeout == 0) timeout = 1; break; #if DIG_SIGCHASE_TD case 'o': /* topdown */ FULLCHECK("topdown"); lookup->do_topdown = state; break; #endif case 'r': switch (cmd[2]) { case 'a': /* trace */ FULLCHECK("trace"); lookup->trace = state; lookup->trace_root = state; if (state) { lookup->recurse = ISC_FALSE; lookup->identify = ISC_TRUE; lookup->comments = ISC_FALSE; rrcomments = ISC_FALSE; lookup->stats = ISC_FALSE; lookup->section_additional = ISC_FALSE; lookup->section_authority = ISC_TRUE; lookup->section_question = ISC_FALSE; lookup->dnssec = ISC_TRUE; usesearch = ISC_FALSE; } break; case 'i': /* tries */ FULLCHECK("tries"); if (value == NULL) goto need_value; if (!state) goto invalid_option; result = parse_uint(&lookup->retries, value, MAXTRIES, "tries"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse tries"); if (lookup->retries == 0) lookup->retries = 1; break; #ifdef DIG_SIGCHASE case 'u': /* trusted-key */ FULLCHECK("trusted-key"); if (value == NULL) goto need_value; if (!state) goto invalid_option; n = strlcpy(trustedkey, ptr, sizeof(trustedkey)); if (n >= sizeof(trustedkey)) fatal("trusted key too large"); break; #endif default: goto invalid_option; } break; case 't': /* ttlid */ FULLCHECK("ttlid"); nottl = ISC_TF(!state); break; default: goto invalid_option; } break; case 'v': FULLCHECK("vc"); if (!is_batchfile) lookup->tcp_mode = state; break; default: invalid_option: need_value: fprintf(stderr, "Invalid option: +%s\n", option); usage(); } return; }
isc_result_t isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) { struct rlimit rl; ISC_PLATFORM_RLIMITTYPE rlim_value; int unixresult; int unixresource; isc_result_t result; result = resource2rlim(resource, &unixresource); if (result != ISC_R_SUCCESS) return (result); if (value == ISC_RESOURCE_UNLIMITED) rlim_value = RLIM_INFINITY; else { /* * isc_resourcevalue_t was chosen as an unsigned 64 bit * integer so that it could contain the maximum range of * reasonable values. Unfortunately, this exceeds the typical * range on Unix systems. Ensure the range of * ISC_PLATFORM_RLIMITTYPE is not overflowed. */ isc_resourcevalue_t rlim_max; isc_boolean_t rlim_t_is_signed = ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0); if (rlim_t_is_signed) rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 << (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1)); else rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1; if (value > rlim_max) value = rlim_max; rlim_value = value; } /* * The BIND 8 documentation reports: * * Note: on some operating systems the server cannot set an * unlimited value and cannot determine the maximum number of * open files the kernel can support. On such systems, choosing * unlimited will cause the server to use the larger of the * rlim_max for RLIMIT_NOFILE and the value returned by * sysconf(_SC_OPEN_MAX). If the actual kernel limit is larger * than this value, use limit files to specify the limit * explicitly. * * The CHANGES for 8.1.2-T3A also mention: * * 352. [bug] Because of problems with setting an infinite * rlim_max for RLIMIT_NOFILE on some systems, previous versions * of the server implemented "limit files unlimited" by setting * the limit to the value returned by sysconf(_SC_OPEN_MAX). The * server will now use RLIM_INFINITY on systems which allow it. * * At some point the BIND 8 server stopped using SC_OPEN_MAX for this * purpose at all, but it isn't clear to me when or why, as my access * to the CVS archive is limited at the time of this writing. What * BIND 8 *does* do is to set RLIMIT_NOFILE to either RLIMIT_INFINITY * on a half dozen operating systems or to FD_SETSIZE on the rest, * the latter of which is probably fewer than the real limit. (Note * that libisc's socket module will have problems with any fd over * FD_SETSIZE. This should be fixed in the socket module, not a * limitation here. BIND 8's eventlib also has a problem, making * its RLIMIT_INFINITY setting useless, because it closes and ignores * any fd over FD_SETSIZE.) * * More troubling is the reference to some operating systems not being * able to set an unlimited value for the number of open files. I'd * hate to put in code that is really only there to support archaic * systems that the rest of libisc won't work on anyway. So what this * extremely verbose comment is here to say is the following: * * I'm aware there might be an issue with not limiting the value * for RLIMIT_NOFILE on some systems, but since I don't know yet * what those systems are and what the best workaround is (use * sysconf()? rlim_max from getrlimit()? FD_SETSIZE?) so nothing * is currently being done to clamp the value for open files. */ rl.rlim_cur = rl.rlim_max = rlim_value; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); else return (isc__errno2result(errno)); }
isc_result_t isc_resource_setlimit(isc_resource_t resource, isc_resourcevalue_t value) { struct rlimit rl; ISC_PLATFORM_RLIMITTYPE rlim_value; int unixresult; int unixresource; isc_result_t result; result = resource2rlim(resource, &unixresource); if (result != ISC_R_SUCCESS) return (result); if (value == ISC_RESOURCE_UNLIMITED) rlim_value = RLIM_INFINITY; else { /* * isc_resourcevalue_t was chosen as an unsigned 64 bit * integer so that it could contain the maximum range of * reasonable values. Unfortunately, this exceeds the typical * range on Unix systems. Ensure the range of * ISC_PLATFORM_RLIMITTYPE is not overflowed. */ isc_resourcevalue_t rlim_max; isc_boolean_t rlim_t_is_signed = ISC_TF(((double)(ISC_PLATFORM_RLIMITTYPE)-1) < 0); if (rlim_t_is_signed) rlim_max = ~((ISC_PLATFORM_RLIMITTYPE)1 << (sizeof(ISC_PLATFORM_RLIMITTYPE) * 8 - 1)); else rlim_max = (ISC_PLATFORM_RLIMITTYPE)-1; if (value > rlim_max) value = rlim_max; rlim_value = value; } rl.rlim_cur = rl.rlim_max = rlim_value; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); #if defined(OPEN_MAX) && defined(__APPLE__) /* * The Darwin kernel doesn't accept RLIM_INFINITY for rlim_cur; the * maximum possible value is OPEN_MAX. BIND8 used to use * sysconf(_SC_OPEN_MAX) for such a case, but this value is much * smaller than OPEN_MAX and is not really effective. */ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { rl.rlim_cur = OPEN_MAX; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); } #elif defined(__linux__) #ifndef NR_OPEN #define NR_OPEN (1024*1024) #endif /* * Some Linux kernels don't accept RLIM_INFINIT; the maximum * possible value is the NR_OPEN defined in linux/fs.h. */ if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { rl.rlim_cur = rl.rlim_max = NR_OPEN; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); } #elif defined(__hpux) && defined(HAVE_SYS_DYNTUNE_H) if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { uint64_t maxfiles; if (gettune("maxfiles_lim", &maxfiles) == 0) { rl.rlim_cur = rl.rlim_max = maxfiles; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); } } #endif if (resource == isc_resource_openfiles && rlim_value == RLIM_INFINITY) { if (getrlimit(unixresource, &rl) == 0) { rl.rlim_cur = rl.rlim_max; unixresult = setrlimit(unixresource, &rl); if (unixresult == 0) return (ISC_R_SUCCESS); } } return (isc__errno2result(errno)); }
static isc_boolean_t openssldsa_isprivate(const dst_key_t *key) { DSA *dsa = key->keydata.dsa; return (ISC_TF(dsa != NULL && dsa->priv_key != NULL)); }
isc_result_t cfg_acl_fromconfig(const cfg_obj_t *caml, const cfg_obj_t *cctx, isc_log_t *lctx, cfg_aclconfctx_t *ctx, isc_mem_t *mctx, unsigned int nest_level, dns_acl_t **target) { isc_result_t result; dns_acl_t *dacl = NULL, *inneracl = NULL; dns_aclelement_t *de; const cfg_listelt_t *elt; dns_iptable_t *iptab; int new_nest_level = 0; if (nest_level != 0) new_nest_level = nest_level - 1; REQUIRE(target != NULL); REQUIRE(*target == NULL || DNS_ACL_VALID(*target)); if (*target != NULL) { /* * If target already points to an ACL, then we're being * called recursively to configure a nested ACL. The * nested ACL's contents should just be absorbed into its * parent ACL. */ dns_acl_attach(*target, &dacl); dns_acl_detach(target); } else { /* * Need to allocate a new ACL structure. Count the items * in the ACL definition that will require space in the * elements table. (Note that if nest_level is nonzero, * *everything* goes in the elements table.) */ int nelem; if (nest_level == 0) nelem = count_acl_elements(caml, cctx, NULL); else nelem = cfg_list_length(caml, ISC_FALSE); result = dns_acl_create(mctx, nelem, &dacl); if (result != ISC_R_SUCCESS) return (result); } de = dacl->elements; for (elt = cfg_list_first(caml); elt != NULL; elt = cfg_list_next(elt)) { const cfg_obj_t *ce = cfg_listelt_value(elt); isc_boolean_t neg; if (cfg_obj_istuple(ce)) { /* This must be a negated element. */ ce = cfg_tuple_get(ce, "value"); neg = ISC_TRUE; dacl->has_negatives = ISC_TRUE; } else neg = ISC_FALSE; /* * If nest_level is nonzero, then every element is * to be stored as a separate, nested ACL rather than * merged into the main iptable. */ iptab = dacl->iptable; if (nest_level != 0) { result = dns_acl_create(mctx, cfg_list_length(ce, ISC_FALSE), &de->nestedacl); if (result != ISC_R_SUCCESS) goto cleanup; iptab = de->nestedacl->iptable; } if (cfg_obj_isnetprefix(ce)) { /* Network prefix */ isc_netaddr_t addr; unsigned int bitlen; cfg_obj_asnetprefix(ce, &addr, &bitlen); /* * If nesting ACLs (nest_level != 0), we negate * the nestedacl element, not the iptable entry. */ result = dns_iptable_addprefix(iptab, &addr, bitlen, ISC_TF(nest_level != 0 || !neg)); if (result != ISC_R_SUCCESS) goto cleanup; if (nest_level > 0) { de->type = dns_aclelementtype_nestedacl; de->negative = neg; } else continue; } else if (cfg_obj_islist(ce)) { /* * If we're nesting ACLs, put the nested * ACL onto the elements list; otherwise * merge it into *this* ACL. We nest ACLs * in two cases: 1) sortlist, 2) if the * nested ACL contains negated members. */ if (inneracl != NULL) dns_acl_detach(&inneracl); result = cfg_acl_fromconfig(ce, cctx, lctx, ctx, mctx, new_nest_level, &inneracl); if (result != ISC_R_SUCCESS) goto cleanup; nested_acl: if (nest_level > 0 || inneracl->has_negatives) { de->type = dns_aclelementtype_nestedacl; de->negative = neg; if (de->nestedacl != NULL) dns_acl_detach(&de->nestedacl); dns_acl_attach(inneracl, &de->nestedacl); dns_acl_detach(&inneracl); /* Fall through. */ } else { dns_acl_merge(dacl, inneracl, ISC_TF(!neg)); de += inneracl->length; /* elements added */ dns_acl_detach(&inneracl); continue; } } else if (cfg_obj_istype(ce, &cfg_type_keyref)) { /* Key name. */ de->type = dns_aclelementtype_keyname; de->negative = neg; dns_name_init(&de->keyname, NULL); result = convert_keyname(ce, lctx, mctx, &de->keyname); if (result != ISC_R_SUCCESS) goto cleanup; } else if (cfg_obj_isstring(ce)) { /* ACL name. */ const char *name = cfg_obj_asstring(ce); if (strcasecmp(name, "any") == 0) { /* Iptable entry with zero bit length. */ result = dns_iptable_addprefix(iptab, NULL, 0, ISC_TF(nest_level != 0 || !neg)); if (result != ISC_R_SUCCESS) goto cleanup; if (nest_level != 0) { de->type = dns_aclelementtype_nestedacl; de->negative = neg; } else continue; } else if (strcasecmp(name, "none") == 0) { /* none == !any */ /* * We don't unconditional set * dacl->has_negatives and * de->negative to true so we can handle * "!none;". */ result = dns_iptable_addprefix(iptab, NULL, 0, ISC_TF(nest_level != 0 || neg)); if (result != ISC_R_SUCCESS) goto cleanup; if (!neg) dacl->has_negatives = !neg; if (nest_level != 0) { de->type = dns_aclelementtype_nestedacl; de->negative = !neg; } else continue; #ifdef SUPPORT_GEOIP } else if ((0 == (strncmp("country_", name, 8))) && (10 == strlen(name))) { /* It is a country code */ de->type = dns_aclelementtype_ipcountry; de->country[0] = name[8]; de->country[1] = name[9]; de->country[2] = '\0'; #endif } else if (strcasecmp(name, "localhost") == 0) { de->type = dns_aclelementtype_localhost; de->negative = neg; } else if (strcasecmp(name, "localnets") == 0) { de->type = dns_aclelementtype_localnets; de->negative = neg; } else { if (inneracl != NULL) dns_acl_detach(&inneracl); result = convert_named_acl(ce, cctx, lctx, ctx, mctx, new_nest_level, &inneracl); if (result != ISC_R_SUCCESS) goto cleanup; goto nested_acl; } } else { cfg_obj_log(ce, lctx, ISC_LOG_WARNING, "address match list contains " "unsupported element type"); result = ISC_R_FAILURE; goto cleanup; } /* * This should only be reached for localhost, localnets * and keyname elements, and nested ACLs if nest_level is * nonzero (i.e., in sortlists). */ if (de->nestedacl != NULL && de->type != dns_aclelementtype_nestedacl) dns_acl_detach(&de->nestedacl); dacl->node_count++; de->node_num = dacl->node_count; dacl->length++; de++; INSIST(dacl->length <= dacl->alloc); } dns_acl_attach(dacl, target); result = ISC_R_SUCCESS; cleanup: if (inneracl != NULL) dns_acl_detach(&inneracl); dns_acl_detach(&dacl); return (result); }
static inline isc_result_t schedule(isc_timer_t *timer, isc_time_t *now, isc_boolean_t signal_ok) { isc_result_t result; isc_timermgr_t *manager; isc_time_t due; int cmp; #ifdef ISC_PLATFORM_USETHREADS isc_boolean_t timedwait; #endif /*! * Note: the caller must ensure locking. */ REQUIRE(timer->type != isc_timertype_inactive); #ifndef ISC_PLATFORM_USETHREADS UNUSED(signal_ok); #endif /* ISC_PLATFORM_USETHREADS */ manager = timer->manager; #ifdef ISC_PLATFORM_USETHREADS /*! * If the manager was timed wait, we may need to signal the * manager to force a wakeup. */ timedwait = ISC_TF(manager->nscheduled > 0 && isc_time_seconds(&manager->due) != 0); #endif /* * Compute the new due time. */ if (timer->type != isc_timertype_once) { result = isc_time_add(now, &timer->interval, &due); if (result != ISC_R_SUCCESS) return (result); if (timer->type == isc_timertype_limited && isc_time_compare(&timer->expires, &due) < 0) due = timer->expires; } else { if (isc_time_isepoch(&timer->idle)) due = timer->expires; else if (isc_time_isepoch(&timer->expires)) due = timer->idle; else if (isc_time_compare(&timer->idle, &timer->expires) < 0) due = timer->idle; else due = timer->expires; } /* * Schedule the timer. */ if (timer->index > 0) { /* * Already scheduled. */ cmp = isc_time_compare(&due, &timer->due); timer->due = due; switch (cmp) { case -1: isc_heap_increased(manager->heap, timer->index); break; case 1: isc_heap_decreased(manager->heap, timer->index); break; case 0: /* Nothing to do. */ break; } } else { timer->due = due; result = isc_heap_insert(manager->heap, timer); if (result != ISC_R_SUCCESS) { INSIST(result == ISC_R_NOMEMORY); return (ISC_R_NOMEMORY); } manager->nscheduled++; } XTRACETIMER(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SCHEDULE, "schedule"), timer, due); /* * If this timer is at the head of the queue, we need to ensure * that we won't miss it if it has a more recent due time than * the current "next" timer. We do this either by waking up the * run thread, or explicitly setting the value in the manager. */ #ifdef ISC_PLATFORM_USETHREADS /* * This is a temporary (probably) hack to fix a bug on tru64 5.1 * and 5.1a. Sometimes, pthread_cond_timedwait() doesn't actually * return when the time expires, so here, we check to see if * we're 15 seconds or more behind, and if we are, we signal * the dispatcher. This isn't such a bad idea as a general purpose * watchdog, so perhaps we should just leave it in here. */ if (signal_ok && timedwait) { isc_interval_t fifteen; isc_time_t then; isc_interval_set(&fifteen, 15, 0); result = isc_time_add(&manager->due, &fifteen, &then); if (result == ISC_R_SUCCESS && isc_time_compare(&then, now) < 0) { SIGNAL(&manager->wakeup); signal_ok = ISC_FALSE; isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL, ISC_LOGMODULE_TIMER, ISC_LOG_WARNING, "*** POKED TIMER ***"); } } if (timer->index == 1 && signal_ok) { XTRACE(isc_msgcat_get(isc_msgcat, ISC_MSGSET_TIMER, ISC_MSG_SIGNALSCHED, "signal (schedule)")); SIGNAL(&manager->wakeup); } #else /* ISC_PLATFORM_USETHREADS */ if (timer->index == 1 && isc_time_compare(&timer->due, &manager->due) < 0) manager->due = timer->due; #endif /* ISC_PLATFORM_USETHREADS */ return (ISC_R_SUCCESS); }
static void plus_option(char *option) { isc_result_t result; char option_store[256]; char *cmd, *value, *ptr; isc_boolean_t state = ISC_TRUE; strlcpy(option_store, option, sizeof(option_store)); ptr = option_store; cmd = next_token(&ptr,"="); if (cmd == NULL) { printf(";; Invalid option %s\n", option_store); return; } value = ptr; if (strncasecmp(cmd, "no", 2)==0) { cmd += 2; state = ISC_FALSE; } #define FULLCHECK(A) \ do { \ size_t _l = strlen(cmd); \ if (_l >= sizeof(A) || strncasecmp(cmd, A, _l) != 0) \ goto invalid_option; \ } while (/*CONSTCOND*/0) switch (cmd[0]) { case 'a': /* all */ FULLCHECK("all"); showcomments = state; rrcomments = state; showtrust = state; break; case 'c': switch (cmd[1]) { case 'd': /* cdflag */ FULLCHECK("cdflag"); cdflag = state; break; case 'l': /* class */ FULLCHECK("class"); noclass = ISC_TF(!state); break; case 'o': /* comments */ FULLCHECK("comments"); showcomments = state; break; case 'r': /* crypto */ FULLCHECK("crypto"); nocrypto = ISC_TF(!state); break; default: goto invalid_option; } break; case 'd': switch (cmd[1]) { case 'l': /* dlv */ FULLCHECK("dlv"); if (state && no_sigs) break; dlv_validation = state; if (value != NULL) { dlv_anchor = isc_mem_strdup(mctx, value); if (dlv_anchor == NULL) fatal("out of memory"); } break; case 'n': /* dnssec */ FULLCHECK("dnssec"); showdnssec = state; break; default: goto invalid_option; } break; case 'm': switch (cmd[1]) { case 't': /* mtrace */ message_trace = state; if (state) resolve_trace = state; break; case 'u': /* multiline */ FULLCHECK("multiline"); multiline = state; break; default: goto invalid_option; } break; case 'r': switch (cmd[1]) { case 'o': /* root */ FULLCHECK("root"); if (state && no_sigs) break; root_validation = state; if (value != NULL) { trust_anchor = isc_mem_strdup(mctx, value); if (trust_anchor == NULL) fatal("out of memory"); } break; case 'r': /* rrcomments */ FULLCHECK("rrcomments"); rrcomments = state; break; case 't': /* rtrace */ FULLCHECK("rtrace"); resolve_trace = state; break; default: goto invalid_option; } break; case 's': switch (cmd[1]) { case 'h': /* short */ FULLCHECK("short"); short_form = state; if (short_form) { multiline = ISC_FALSE; showcomments = ISC_FALSE; showtrust = ISC_FALSE; showdnssec = ISC_FALSE; } break; case 'p': /* split */ FULLCHECK("split"); if (value != NULL && !state) goto invalid_option; if (!state) { splitwidth = 0; break; } else if (value == NULL) break; result = parse_uint(&splitwidth, value, 1023, "split"); if (splitwidth % 4 != 0) { splitwidth = ((splitwidth + 3) / 4) * 4; warn("split must be a multiple of 4; " "adjusting to %d", splitwidth); } /* * There is an adjustment done in the * totext_<rrtype>() functions which causes * splitwidth to shrink. This is okay when we're * using the default width but incorrect in this * case, so we correct for it */ if (splitwidth) splitwidth += 3; if (result != ISC_R_SUCCESS) fatal("Couldn't parse split"); break; default: goto invalid_option; } break; case 't': switch (cmd[1]) { case 'r': /* trust */ FULLCHECK("trust"); showtrust = state; break; case 't': /* ttl */ FULLCHECK("ttl"); nottl = ISC_TF(!state); break; default: goto invalid_option; } break; case 'v': /* vtrace */ FULLCHECK("vtrace"); validator_trace = state; if (state) resolve_trace = state; break; default: invalid_option: /* * We can also add a "need_value:" case here if we ever * add a plus-option that requires a specified value */ fprintf(stderr, "Invalid option: +%s\n", option); usage(); } return; }
static isc_boolean_t openssldh_isprivate(const dst_key_t *key) { DH *dh = key->keydata.dh; return (ISC_TF(dh != NULL && dh->priv_key != NULL)); }
isc_result_t bind9_getaddresses(const char *hostname, in_port_t port, isc_sockaddr_t *addrs, int addrsize, int *addrcount) { struct in_addr in4; struct in6_addr in6; isc_boolean_t have_ipv4, have_ipv6; int i; #ifdef USE_GETADDRINFO struct addrinfo *ai = NULL, *tmpai, hints; int result; #else struct hostent *he; #endif REQUIRE(hostname != NULL); REQUIRE(addrs != NULL); REQUIRE(addrcount != NULL); REQUIRE(addrsize > 0); have_ipv4 = ISC_TF((isc_net_probeipv4() == ISC_R_SUCCESS)); have_ipv6 = ISC_TF((isc_net_probeipv6() == ISC_R_SUCCESS)); /* * Try IPv4, then IPv6. In order to handle the extended format * for IPv6 scoped addresses (address%scope_ID), we'll use a local * working buffer of 128 bytes. The length is an ad-hoc value, but * should be enough for this purpose; the buffer can contain a string * of at least 80 bytes for scope_ID in addition to any IPv6 numeric * addresses (up to 46 bytes), the delimiter character and the * terminating NULL character. */ if (inet_pton(AF_INET, hostname, &in4) == 1) { if (have_ipv4) isc_sockaddr_fromin(&addrs[0], &in4, port); else isc_sockaddr_v6fromin(&addrs[0], &in4, port); *addrcount = 1; return (ISC_R_SUCCESS); } else if (strlen(hostname) <= 127U) { char tmpbuf[128], *d; isc_uint32_t zone = 0; strcpy(tmpbuf, hostname); d = strchr(tmpbuf, '%'); if (d != NULL) *d = '\0'; if (inet_pton(AF_INET6, tmpbuf, &in6) == 1) { isc_netaddr_t na; if (!have_ipv6) return (ISC_R_FAMILYNOSUPPORT); if (d != NULL) { #ifdef ISC_PLATFORM_HAVESCOPEID isc_result_t result; result = isc_netscope_pton(AF_INET6, d + 1, &in6, &zone); if (result != ISC_R_SUCCESS) return (result); #else /* * The extended format is specified while the * system does not provide the ability to use * it. Throw an explicit error instead of * ignoring the specified value. */ return (ISC_R_BADADDRESSFORM); #endif } isc_netaddr_fromin6(&na, &in6); isc_netaddr_setzone(&na, zone); isc_sockaddr_fromnetaddr(&addrs[0], (const isc_netaddr_t *)&na, port); *addrcount = 1; return (ISC_R_SUCCESS); } } #ifdef USE_GETADDRINFO memset(&hints, 0, sizeof(hints)); if (!have_ipv6) hints.ai_family = PF_INET; else if (!have_ipv4) hints.ai_family = PF_INET6; else { hints.ai_family = PF_UNSPEC; #ifdef AI_ADDRCONFIG hints.ai_flags = AI_ADDRCONFIG; #endif } hints.ai_socktype = SOCK_STREAM; #ifdef AI_ADDRCONFIG again: #endif result = getaddrinfo(hostname, NULL, &hints, &ai); switch (result) { case 0: break; case EAI_NONAME: #if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME) case EAI_NODATA: #endif return (ISC_R_NOTFOUND); #ifdef AI_ADDRCONFIG case EAI_BADFLAGS: if ((hints.ai_flags & AI_ADDRCONFIG) != 0) { hints.ai_flags &= ~AI_ADDRCONFIG; goto again; } #endif default: return (ISC_R_FAILURE); } for (tmpai = ai, i = 0; tmpai != NULL && i < addrsize; tmpai = tmpai->ai_next) { if (tmpai->ai_family != AF_INET && tmpai->ai_family != AF_INET6) continue; if (tmpai->ai_family == AF_INET) { struct sockaddr_in *sin; sin = (struct sockaddr_in *)tmpai->ai_addr; isc_sockaddr_fromin(&addrs[i], &sin->sin_addr, port); } else { struct sockaddr_in6 *sin6; sin6 = (struct sockaddr_in6 *)tmpai->ai_addr; isc_sockaddr_fromin6(&addrs[i], &sin6->sin6_addr, port); } i++; } freeaddrinfo(ai); *addrcount = i; #else he = gethostbyname(hostname); if (he == NULL) { switch (h_errno) { case HOST_NOT_FOUND: #ifdef NO_DATA case NO_DATA: #endif #if defined(NO_ADDRESS) && (!defined(NO_DATA) || (NO_DATA != NO_ADDRESS)) case NO_ADDRESS: #endif return (ISC_R_NOTFOUND); default: return (ISC_R_FAILURE); } } if (he->h_addrtype != AF_INET && he->h_addrtype != AF_INET6) return (ISC_R_NOTFOUND); for (i = 0; i < addrsize; i++) { if (he->h_addrtype == AF_INET) { struct in_addr *inp; inp = (struct in_addr *)(he->h_addr_list[i]); if (inp == NULL) break; isc_sockaddr_fromin(&addrs[i], inp, port); } else { struct in6_addr *in6p; in6p = (struct in6_addr *)(he->h_addr_list[i]); if (in6p == NULL) break; isc_sockaddr_fromin6(&addrs[i], in6p, port); } } *addrcount = i; #endif if (*addrcount == 0) return (ISC_R_NOTFOUND); else return (ISC_R_SUCCESS); }
isc_result_t dns_rdataslab_merge(unsigned char *oslab, unsigned char *nslab, unsigned int reservelen, isc_mem_t *mctx, dns_rdataclass_t rdclass, dns_rdatatype_t type, unsigned int flags, unsigned char **tslabp) { unsigned char *ocurrent, *ostart, *ncurrent, *tstart, *tcurrent, *data; unsigned int ocount, ncount, count, olength, tlength, tcount, length; dns_rdata_t ordata = DNS_RDATA_INIT; dns_rdata_t nrdata = DNS_RDATA_INIT; isc_boolean_t added_something = ISC_FALSE; unsigned int oadded = 0; unsigned int nadded = 0; unsigned int nncount = 0; #if DNS_RDATASET_FIXED unsigned int oncount; unsigned int norder = 0; unsigned int oorder = 0; unsigned char *offsetbase; unsigned int *offsettable; #endif /* * XXX Need parameter to allow "delete rdatasets in nslab" merge, * or perhaps another merge routine for this purpose. */ REQUIRE(tslabp != NULL && *tslabp == NULL); REQUIRE(oslab != NULL && nslab != NULL); ocurrent = oslab + reservelen; ocount = *ocurrent++ * 256; ocount += *ocurrent++; #if DNS_RDATASET_FIXED ocurrent += (4 * ocount); #endif ostart = ocurrent; ncurrent = nslab + reservelen; ncount = *ncurrent++ * 256; ncount += *ncurrent++; #if DNS_RDATASET_FIXED ncurrent += (4 * ncount); #endif INSIST(ocount > 0 && ncount > 0); #if DNS_RDATASET_FIXED oncount = ncount; #endif /* * Yes, this is inefficient! */ /* * Figure out the length of the old slab's data. */ olength = 0; for (count = 0; count < ocount; count++) { length = *ocurrent++ * 256; length += *ocurrent++; #if DNS_RDATASET_FIXED olength += length + 8; ocurrent += length + 2; #else olength += length + 2; ocurrent += length; #endif } /* * Start figuring out the target length and count. */ tlength = reservelen + 2 + olength; tcount = ocount; /* * Add in the length of rdata in the new slab that aren't in * the old slab. */ do { dns_rdata_init(&nrdata); rdata_from_slab(&ncurrent, rdclass, type, &nrdata); if (!rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)) { /* * This rdata isn't in the old slab. */ #if DNS_RDATASET_FIXED tlength += nrdata.length + 8; #else tlength += nrdata.length + 2; #endif if (type == dns_rdatatype_rrsig) tlength++; tcount++; nncount++; added_something = ISC_TRUE; } ncount--; } while (ncount > 0); ncount = nncount; if (((flags & DNS_RDATASLAB_EXACT) != 0) && (tcount != ncount + ocount)) return (DNS_R_NOTEXACT); if (!added_something && (flags & DNS_RDATASLAB_FORCE) == 0) return (DNS_R_UNCHANGED); /* * Ensure that singleton types are actually singletons. */ if (tcount > 1 && dns_rdatatype_issingleton(type)) { /* * We have a singleton type, but there's more than one * RR in the rdataset. */ return (DNS_R_SINGLETON); } if (tcount > 0xffff) return (ISC_R_NOSPACE); /* * Copy the reserved area from the new slab. */ tstart = isc_mem_get(mctx, tlength); if (tstart == NULL) return (ISC_R_NOMEMORY); memmove(tstart, nslab, reservelen); tcurrent = tstart + reservelen; #if DNS_RDATASET_FIXED offsetbase = tcurrent; #endif /* * Write the new count. */ *tcurrent++ = (tcount & 0xff00) >> 8; *tcurrent++ = (tcount & 0x00ff); #if DNS_RDATASET_FIXED /* * Skip offset table. */ tcurrent += (tcount * 4); offsettable = isc_mem_get(mctx, (ocount + oncount) * sizeof(unsigned int)); if (offsettable == NULL) { isc_mem_put(mctx, tstart, tlength); return (ISC_R_NOMEMORY); } memset(offsettable, 0, (ocount + oncount) * sizeof(unsigned int)); #endif /* * Merge the two slabs. */ ocurrent = ostart; INSIST(ocount != 0); #if DNS_RDATASET_FIXED oorder = ocurrent[2] * 256 + ocurrent[3]; INSIST(oorder < ocount); #endif rdata_from_slab(&ocurrent, rdclass, type, &ordata); ncurrent = nslab + reservelen + 2; #if DNS_RDATASET_FIXED ncurrent += (4 * oncount); #endif if (ncount > 0) { do { dns_rdata_reset(&nrdata); #if DNS_RDATASET_FIXED norder = ncurrent[2] * 256 + ncurrent[3]; INSIST(norder < oncount); #endif rdata_from_slab(&ncurrent, rdclass, type, &nrdata); } while (rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)); } while (oadded < ocount || nadded < ncount) { isc_boolean_t fromold; if (oadded == ocount) fromold = ISC_FALSE; else if (nadded == ncount) fromold = ISC_TRUE; else fromold = ISC_TF(compare_rdata(&ordata, &nrdata) < 0); if (fromold) { #if DNS_RDATASET_FIXED offsettable[oorder] = tcurrent - offsetbase; #endif length = ordata.length; data = ordata.data; if (type == dns_rdatatype_rrsig) { length++; data--; } *tcurrent++ = (length & 0xff00) >> 8; *tcurrent++ = (length & 0x00ff); #if DNS_RDATASET_FIXED tcurrent += 2; /* fill in later */ #endif memmove(tcurrent, data, length); tcurrent += length; oadded++; if (oadded < ocount) { dns_rdata_reset(&ordata); #if DNS_RDATASET_FIXED oorder = ocurrent[2] * 256 + ocurrent[3]; INSIST(oorder < ocount); #endif rdata_from_slab(&ocurrent, rdclass, type, &ordata); } } else { #if DNS_RDATASET_FIXED offsettable[ocount + norder] = tcurrent - offsetbase; #endif length = nrdata.length; data = nrdata.data; if (type == dns_rdatatype_rrsig) { length++; data--; } *tcurrent++ = (length & 0xff00) >> 8; *tcurrent++ = (length & 0x00ff); #if DNS_RDATASET_FIXED tcurrent += 2; /* fill in later */ #endif memmove(tcurrent, data, length); tcurrent += length; nadded++; if (nadded < ncount) { do { dns_rdata_reset(&nrdata); #if DNS_RDATASET_FIXED norder = ncurrent[2] * 256 + ncurrent[3]; INSIST(norder < oncount); #endif rdata_from_slab(&ncurrent, rdclass, type, &nrdata); } while (rdata_in_slab(oslab, reservelen, rdclass, type, &nrdata)); } } }
static isc_boolean_t openssldsa_isprivate(const dst_key_t *key) { DSA *dsa = (DSA *) key->opaque; return (ISC_TF(dsa != NULL && dsa->priv_key != NULL)); }
isc_result_t ns_acl_fromconfig(cfg_obj_t *caml, cfg_obj_t *cctx, ns_aclconfctx_t *ctx, isc_mem_t *mctx, dns_acl_t **target) { isc_result_t result; unsigned int count; dns_acl_t *dacl = NULL; dns_aclelement_t *de; cfg_listelt_t *elt; REQUIRE(target != NULL && *target == NULL); count = 0; for (elt = cfg_list_first(caml); elt != NULL; elt = cfg_list_next(elt)) count++; result = dns_acl_create(mctx, count, &dacl); if (result != ISC_R_SUCCESS) return (result); de = dacl->elements; for (elt = cfg_list_first(caml); elt != NULL; elt = cfg_list_next(elt)) { cfg_obj_t *ce = cfg_listelt_value(elt); if (cfg_obj_istuple(ce)) { /* This must be a negated element. */ ce = cfg_tuple_get(ce, "value"); de->negative = ISC_TRUE; } else { de->negative = ISC_FALSE; } if (cfg_obj_isnetprefix(ce)) { /* Network prefix */ de->type = dns_aclelementtype_ipprefix; cfg_obj_asnetprefix(ce, &de->u.ip_prefix.address, &de->u.ip_prefix.prefixlen); } else if (cfg_obj_istype(ce, &cfg_type_keyref)) { /* Key name */ de->type = dns_aclelementtype_keyname; dns_name_init(&de->u.keyname, NULL); result = convert_keyname(ce, mctx, &de->u.keyname); if (result != ISC_R_SUCCESS) goto cleanup; } else if (cfg_obj_islist(ce)) { /* Nested ACL */ de->type = dns_aclelementtype_nestedacl; result = ns_acl_fromconfig(ce, cctx, ctx, mctx, &de->u.nestedacl); if (result != ISC_R_SUCCESS) goto cleanup; } else if (cfg_obj_isstring(ce)) { /* ACL name */ char *name = cfg_obj_asstring(ce); if (strcasecmp(name, "localhost") == 0) { de->type = dns_aclelementtype_localhost; } else if (strcasecmp(name, "localnets") == 0) { de->type = dns_aclelementtype_localnets; } else if (strcasecmp(name, "any") == 0) { de->type = dns_aclelementtype_any; } else if (strcasecmp(name, "none") == 0) { de->type = dns_aclelementtype_any; de->negative = ISC_TF(! de->negative); } else { de->type = dns_aclelementtype_nestedacl; result = convert_named_acl(ce, cctx, ctx, mctx, &de->u.nestedacl); if (result != ISC_R_SUCCESS) goto cleanup; } } else { cfg_obj_log(ce, dns_lctx, ISC_LOG_WARNING, "address match list contains " "unsupported element type"); result = ISC_R_FAILURE; goto cleanup; } de++; dacl->length++; } *target = dacl; return (ISC_R_SUCCESS); cleanup: dns_acl_detach(&dacl); return (result); }
isc_boolean_t isc_keyboard_canceled (isc_keyboard_t * keyboard) { return (ISC_TF (keyboard->result == ISC_R_CANCELED)); }
isc_boolean_t isc_file_iscurrentdir(const char *filename) { REQUIRE(filename != NULL); return (ISC_TF(filename[0] == '.' && filename[1] == '\0')); }
static isc_boolean_t dash_option(char *option, char *next, dig_lookup_t **lookup, isc_boolean_t *open_type_class, isc_boolean_t *need_clone, isc_boolean_t config_only, int argc, char **argv, isc_boolean_t *firstarg) { char opt, *value, *ptr, *ptr2, *ptr3; isc_result_t result; isc_boolean_t value_from_next; isc_textregion_t tr; dns_rdatatype_t rdtype; dns_rdataclass_t rdclass; char textname[MXNAME]; struct in_addr in4; struct in6_addr in6; in_port_t srcport; char *hash, *cmd; isc_uint32_t num; while (strpbrk(option, single_dash_opts) == &option[0]) { /* * Since the -[46dhimnv] options do not take an argument, * account for them (in any number and/or combination) * if they appear as the first character(s) of a q-opt. */ opt = option[0]; switch (opt) { case '4': if (have_ipv4) { isc_net_disableipv6(); have_ipv6 = ISC_FALSE; } else { fatal("can't find IPv4 networking"); /* NOTREACHED */ return (ISC_FALSE); } break; case '6': if (have_ipv6) { isc_net_disableipv4(); have_ipv4 = ISC_FALSE; } else { fatal("can't find IPv6 networking"); /* NOTREACHED */ return (ISC_FALSE); } break; case 'd': ptr = strpbrk(&option[1], dash_opts); if (ptr != &option[1]) { cmd = option; FULLCHECK("debug"); debugging = ISC_TRUE; return (ISC_FALSE); } else debugging = ISC_TRUE; break; case 'h': help(); exit(0); break; case 'i': ip6_int = ISC_TRUE; break; case 'm': /* memdebug */ /* memdebug is handled in preparse_args() */ break; case 'n': /* deprecated */ break; case 'v': version(); exit(0); break; } if (strlen(option) > 1U) option = &option[1]; else return (ISC_FALSE); } opt = option[0]; if (strlen(option) > 1U) { value_from_next = ISC_FALSE; value = &option[1]; } else { value_from_next = ISC_TRUE; value = next; } if (value == NULL) goto invalid_option; switch (opt) { case 'b': hash = strchr(value, '#'); if (hash != NULL) { result = parse_uint(&num, hash + 1, MAXPORT, "port number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); srcport = num; *hash = '\0'; } else srcport = 0; if (have_ipv6 && inet_pton(AF_INET6, value, &in6) == 1) { isc_sockaddr_fromin6(&bind_address, &in6, srcport); isc_net_disableipv4(); } else if (have_ipv4 && inet_pton(AF_INET, value, &in4) == 1) { isc_sockaddr_fromin(&bind_address, &in4, srcport); isc_net_disableipv6(); } else { if (hash != NULL) *hash = '#'; fatal("invalid address %s", value); } if (hash != NULL) *hash = '#'; specified_source = ISC_TRUE; return (value_from_next); case 'c': if ((*lookup)->rdclassset) { fprintf(stderr, ";; Warning, extra class option\n"); } *open_type_class = ISC_FALSE; tr.base = value; tr.length = strlen(value); result = dns_rdataclass_fromtext(&rdclass, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS) { (*lookup)->rdclass = rdclass; (*lookup)->rdclassset = ISC_TRUE; } else fprintf(stderr, ";; Warning, ignoring " "invalid class %s\n", value); return (value_from_next); case 'f': batchname = value; return (value_from_next); case 'k': strncpy(keyfile, value, sizeof(keyfile)); keyfile[sizeof(keyfile)-1]=0; return (value_from_next); case 'p': result = parse_uint(&num, value, MAXPORT, "port number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse port number"); port = num; return (value_from_next); case 'q': if (!config_only) { if (*need_clone) (*lookup) = clone_lookup(default_lookup, ISC_TRUE); *need_clone = ISC_TRUE; strncpy((*lookup)->textname, value, sizeof((*lookup)->textname)); (*lookup)->textname[sizeof((*lookup)->textname)-1]=0; (*lookup)->trace_root = ISC_TF((*lookup)->trace || (*lookup)->ns_search_only); (*lookup)->new_search = ISC_TRUE; if (*firstarg) { printgreeting(argc, argv, *lookup); *firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, (*lookup), link); debug("looking up %s", (*lookup)->textname); } return (value_from_next); case 't': *open_type_class = ISC_FALSE; if (strncasecmp(value, "ixfr=", 5) == 0) { rdtype = dns_rdatatype_ixfr; result = ISC_R_SUCCESS; } else { tr.base = value; tr.length = strlen(value); result = dns_rdatatype_fromtext(&rdtype, (isc_textregion_t *)&tr); if (result == ISC_R_SUCCESS && rdtype == dns_rdatatype_ixfr) { result = DNS_R_UNKNOWN; } } if (result == ISC_R_SUCCESS) { if ((*lookup)->rdtypeset) { fprintf(stderr, ";; Warning, " "extra type option\n"); } if (rdtype == dns_rdatatype_ixfr) { isc_uint32_t serial; (*lookup)->rdtype = dns_rdatatype_ixfr; (*lookup)->rdtypeset = ISC_TRUE; result = parse_uint(&serial, &value[5], MAXSERIAL, "serial number"); if (result != ISC_R_SUCCESS) fatal("Couldn't parse serial number"); (*lookup)->ixfr_serial = serial; (*lookup)->section_question = plusquest; (*lookup)->comments = pluscomm; (*lookup)->tcp_mode = ISC_TRUE; } else { (*lookup)->rdtype = rdtype; (*lookup)->rdtypeset = ISC_TRUE; if (rdtype == dns_rdatatype_axfr) { (*lookup)->section_question = plusquest; (*lookup)->comments = pluscomm; } (*lookup)->ixfr_serial = ISC_FALSE; } } else fprintf(stderr, ";; Warning, ignoring " "invalid type %s\n", value); return (value_from_next); case 'y': ptr = next_token(&value,":"); /* hmac type or name */ if (ptr == NULL) { usage(); } ptr2 = next_token(&value, ":"); /* name or secret */ if (ptr2 == NULL) usage(); ptr3 = next_token(&value,":"); /* secret or NULL */ if (ptr3 != NULL) { parse_hmac(ptr); ptr = ptr2; ptr2 = ptr3; } else { hmacname = DNS_TSIG_HMACMD5_NAME; digestbits = 0; } strncpy(keynametext, ptr, sizeof(keynametext)); keynametext[sizeof(keynametext)-1]=0; strncpy(keysecret, ptr2, sizeof(keysecret)); keysecret[sizeof(keysecret)-1]=0; return (value_from_next); case 'x': if (*need_clone) *lookup = clone_lookup(default_lookup, ISC_TRUE); *need_clone = ISC_TRUE; if (get_reverse(textname, sizeof(textname), value, ip6_int, ISC_FALSE) == ISC_R_SUCCESS) { strncpy((*lookup)->textname, textname, sizeof((*lookup)->textname)); debug("looking up %s", (*lookup)->textname); (*lookup)->trace_root = ISC_TF((*lookup)->trace || (*lookup)->ns_search_only); (*lookup)->ip6_int = ip6_int; if (!(*lookup)->rdtypeset) (*lookup)->rdtype = dns_rdatatype_ptr; if (!(*lookup)->rdclassset) (*lookup)->rdclass = dns_rdataclass_in; (*lookup)->new_search = ISC_TRUE; if (*firstarg) { printgreeting(argc, argv, *lookup); *firstarg = ISC_FALSE; } ISC_LIST_APPEND(lookup_list, *lookup, link); } else { fprintf(stderr, "Invalid IP address %s\n", value); exit(1); } return (value_from_next); invalid_option: default: fprintf(stderr, "Invalid option: -%s\n", option); usage(); } /* NOTREACHED */ return (ISC_FALSE); }