isc_boolean_t
dns_compress_getsensitive(dns_compress_t *cctx) {
	REQUIRE(VALID_CCTX(cctx));

	return (ISC_TF((cctx->allowed & DNS_COMPRESS_CASESENSITIVE) != 0));
}
Ejemplo n.º 2
0
isc_boolean_t
isc_file_isabsolute(const char *filename) {
	REQUIRE(filename != NULL);
	return (ISC_TF(filename[0] == '/'));
}
Ejemplo n.º 3
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);
}
Ejemplo n.º 4
0
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);
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
/*
 * 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);
}
Ejemplo n.º 7
0
/**
 * 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;
}
Ejemplo n.º 8
0
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);
}
Ejemplo n.º 9
0
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);
}
Ejemplo n.º 10
0
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));
}
Ejemplo n.º 11
0
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);
}
Ejemplo n.º 12
0
/*
 * 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);
}
Ejemplo n.º 13
0
isc_boolean_t
isc__taskmgr_ready(void) {
	if (taskmgr == NULL)
		return (ISC_FALSE);
	return (ISC_TF(!ISC_LIST_EMPTY(taskmgr->ready_tasks)));
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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));
}
Ejemplo n.º 16
0
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));
}
Ejemplo n.º 17
0
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));
}
Ejemplo n.º 18
0
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);
}
Ejemplo n.º 19
0
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);
}
Ejemplo n.º 20
0
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;
}
Ejemplo n.º 21
0
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));
}
Ejemplo n.º 22
0
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);
}
Ejemplo n.º 23
0
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));
			}
		}
	}
Ejemplo n.º 24
0
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));
}
Ejemplo n.º 25
0
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);
}
Ejemplo n.º 26
0
isc_boolean_t isc_keyboard_canceled (isc_keyboard_t * keyboard)
{
    return (ISC_TF (keyboard->result == ISC_R_CANCELED));
}
Ejemplo n.º 27
0
isc_boolean_t
isc_file_iscurrentdir(const char *filename) {
	REQUIRE(filename != NULL);
	return (ISC_TF(filename[0] == '.' && filename[1] == '\0'));
}
Ejemplo n.º 28
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);
}