コード例 #1
0
ファイル: statschannel.c プロジェクト: w796933/bind99damp
static isc_result_t
add_listener(ns_server_t *server, ns_statschannel_t **listenerp,
	     const cfg_obj_t *listen_params, const cfg_obj_t *config,
	     isc_sockaddr_t *addr, cfg_aclconfctx_t *aclconfctx,
	     const char *socktext)
{
	isc_result_t result;
	ns_statschannel_t *listener;
	isc_task_t *task = NULL;
	isc_socket_t *sock = NULL;
	const cfg_obj_t *allow;
	dns_acl_t *new_acl = NULL;

	listener = isc_mem_get(server->mctx, sizeof(*listener));
	if (listener == NULL)
		return (ISC_R_NOMEMORY);

	listener->httpdmgr = NULL;
	listener->address = *addr;
	listener->acl = NULL;
	listener->mctx = NULL;
	ISC_LINK_INIT(listener, link);

	result = isc_mutex_init(&listener->lock);
	if (result != ISC_R_SUCCESS) {
		isc_mem_put(server->mctx, listener, sizeof(*listener));
		return (ISC_R_FAILURE);
	}

	isc_mem_attach(server->mctx, &listener->mctx);

	allow = cfg_tuple_get(listen_params, "allow");
	if (allow != NULL && cfg_obj_islist(allow)) {
		result = cfg_acl_fromconfig(allow, config, ns_g_lctx,
					    aclconfctx, listener->mctx, 0,
					    &new_acl);
	} else
		result = dns_acl_any(listener->mctx, &new_acl);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	dns_acl_attach(new_acl, &listener->acl);
	dns_acl_detach(&new_acl);

	result = isc_task_create(ns_g_taskmgr, 0, &task);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	isc_task_setname(task, "statchannel", NULL);

	result = isc_socket_create(ns_g_socketmgr, isc_sockaddr_pf(addr),
				   isc_sockettype_tcp, &sock);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	isc_socket_setname(sock, "statchannel", NULL);

#ifndef ISC_ALLOW_MAPPED
	isc_socket_ipv6only(sock, ISC_TRUE);
#endif

	result = isc_socket_bind(sock, addr, ISC_SOCKET_REUSEADDRESS);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	result = isc_httpdmgr_create(server->mctx, sock, task, client_ok,
				     destroy_listener, listener, ns_g_timermgr,
				     &listener->httpdmgr);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

#ifdef HAVE_LIBXML2
	isc_httpdmgr_addurl(listener->httpdmgr, "/", render_index, server);
#endif
	isc_httpdmgr_addurl(listener->httpdmgr, "/bind9.xsl", render_xsl,
			    server);

	*listenerp = listener;
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
		      NS_LOGMODULE_SERVER, ISC_LOG_NOTICE,
		      "statistics channel listening on %s", socktext);

cleanup:
	if (result != ISC_R_SUCCESS) {
		if (listener->acl != NULL)
			dns_acl_detach(&listener->acl);
		DESTROYLOCK(&listener->lock);
		isc_mem_putanddetach(&listener->mctx, listener,
				     sizeof(*listener));
	}
	if (task != NULL)
		isc_task_detach(&task);
	if (sock != NULL)
		isc_socket_detach(&sock);

	return (result);
}
コード例 #2
0
ファイル: zoneconf.c プロジェクト: ElRevo/xia-core
/*%
 * Parse the zone update-policy statement.
 */
static isc_result_t
configure_zone_ssutable(const cfg_obj_t *zconfig, dns_zone_t *zone,
			const char *zname)
{
	const cfg_obj_t *updatepolicy = NULL;
	const cfg_listelt_t *element, *element2;
	dns_ssutable_t *table = NULL;
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	isc_boolean_t autoddns = ISC_FALSE;
	isc_result_t result;

	(void)cfg_map_get(zconfig, "update-policy", &updatepolicy);

	if (updatepolicy == NULL) {
		dns_zone_setssutable(zone, NULL);
		return (ISC_R_SUCCESS);
	}

	if (cfg_obj_isstring(updatepolicy) &&
	    strcmp("local", cfg_obj_asstring(updatepolicy)) == 0) {
		autoddns = ISC_TRUE;
		updatepolicy = NULL;
	}

	result = dns_ssutable_create(mctx, &table);
	if (result != ISC_R_SUCCESS)
		return (result);

	for (element = cfg_list_first(updatepolicy);
	     element != NULL;
	     element = cfg_list_next(element))
	{
		const cfg_obj_t *stmt = cfg_listelt_value(element);
		const cfg_obj_t *mode = cfg_tuple_get(stmt, "mode");
		const cfg_obj_t *identity = cfg_tuple_get(stmt, "identity");
		const cfg_obj_t *matchtype = cfg_tuple_get(stmt, "matchtype");
		const cfg_obj_t *dname = cfg_tuple_get(stmt, "name");
		const cfg_obj_t *typelist = cfg_tuple_get(stmt, "types");
		const char *str;
		isc_boolean_t grant = ISC_FALSE;
		isc_boolean_t usezone = ISC_FALSE;
		unsigned int mtype = DNS_SSUMATCHTYPE_NAME;
		dns_fixedname_t fname, fident;
		isc_buffer_t b;
		dns_rdatatype_t *types;
		unsigned int i, n;

		str = cfg_obj_asstring(mode);
		if (strcasecmp(str, "grant") == 0)
			grant = ISC_TRUE;
		else if (strcasecmp(str, "deny") == 0)
			grant = ISC_FALSE;
		else
			INSIST(0);

		str = cfg_obj_asstring(matchtype);
		if (strcasecmp(str, "name") == 0)
			mtype = DNS_SSUMATCHTYPE_NAME;
		else if (strcasecmp(str, "subdomain") == 0)
			mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
		else if (strcasecmp(str, "wildcard") == 0)
			mtype = DNS_SSUMATCHTYPE_WILDCARD;
		else if (strcasecmp(str, "self") == 0)
			mtype = DNS_SSUMATCHTYPE_SELF;
		else if (strcasecmp(str, "selfsub") == 0)
			mtype = DNS_SSUMATCHTYPE_SELFSUB;
		else if (strcasecmp(str, "selfwild") == 0)
			mtype = DNS_SSUMATCHTYPE_SELFWILD;
		else if (strcasecmp(str, "ms-self") == 0)
			mtype = DNS_SSUMATCHTYPE_SELFMS;
		else if (strcasecmp(str, "krb5-self") == 0)
			mtype = DNS_SSUMATCHTYPE_SELFKRB5;
		else if (strcasecmp(str, "ms-subdomain") == 0)
			mtype = DNS_SSUMATCHTYPE_SUBDOMAINMS;
		else if (strcasecmp(str, "krb5-subdomain") == 0)
			mtype = DNS_SSUMATCHTYPE_SUBDOMAINKRB5;
		else if (strcasecmp(str, "tcp-self") == 0)
			mtype = DNS_SSUMATCHTYPE_TCPSELF;
		else if (strcasecmp(str, "6to4-self") == 0)
			mtype = DNS_SSUMATCHTYPE_6TO4SELF;
		else if (strcasecmp(str, "zonesub") == 0) {
			mtype = DNS_SSUMATCHTYPE_SUBDOMAIN;
			usezone = ISC_TRUE;
		} else if (strcasecmp(str, "external") == 0)
			mtype = DNS_SSUMATCHTYPE_EXTERNAL;
		else
			INSIST(0);

		dns_fixedname_init(&fident);
		str = cfg_obj_asstring(identity);
		isc_buffer_init(&b, str, strlen(str));
		isc_buffer_add(&b, strlen(str));
		result = dns_name_fromtext(dns_fixedname_name(&fident), &b,
					   dns_rootname, 0, NULL);
		if (result != ISC_R_SUCCESS) {
			cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
				    "'%s' is not a valid name", str);
			goto cleanup;
		}

		dns_fixedname_init(&fname);
		if (usezone) {
			result = dns_name_copy(dns_zone_getorigin(zone),
					       dns_fixedname_name(&fname),
					       NULL);
			if (result != ISC_R_SUCCESS) {
				cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
					    "error copying origin: %s",
					    isc_result_totext(result));
				goto cleanup;
			}
		} else {
			str = cfg_obj_asstring(dname);
			isc_buffer_init(&b, str, strlen(str));
			isc_buffer_add(&b, strlen(str));
			result = dns_name_fromtext(dns_fixedname_name(&fname),
						   &b, dns_rootname, 0, NULL);
			if (result != ISC_R_SUCCESS) {
				cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
					    "'%s' is not a valid name", str);
				goto cleanup;
			}
		}

		n = ns_config_listcount(typelist);
		if (n == 0)
			types = NULL;
		else {
			types = isc_mem_get(mctx, n * sizeof(dns_rdatatype_t));
			if (types == NULL) {
				result = ISC_R_NOMEMORY;
				goto cleanup;
			}
		}

		i = 0;
		for (element2 = cfg_list_first(typelist);
		     element2 != NULL;
		     element2 = cfg_list_next(element2))
		{
			const cfg_obj_t *typeobj;
			isc_textregion_t r;

			INSIST(i < n);

			typeobj = cfg_listelt_value(element2);
			str = cfg_obj_asstring(typeobj);
			DE_CONST(str, r.base);
			r.length = strlen(str);

			result = dns_rdatatype_fromtext(&types[i++], &r);
			if (result != ISC_R_SUCCESS) {
				cfg_obj_log(identity, ns_g_lctx, ISC_LOG_ERROR,
					    "'%s' is not a valid type", str);
				isc_mem_put(mctx, types,
					    n * sizeof(dns_rdatatype_t));
				goto cleanup;
			}
		}
		INSIST(i == n);

		result = dns_ssutable_addrule(table, grant,
					      dns_fixedname_name(&fident),
					      mtype,
					      dns_fixedname_name(&fname),
					      n, types);
		if (types != NULL)
			isc_mem_put(mctx, types, n * sizeof(dns_rdatatype_t));
		if (result != ISC_R_SUCCESS) {
			goto cleanup;
		}
	}

	/*
	 * If "update-policy local;" and a session key exists,
	 * then use the default policy, which is equivalent to:
	 * update-policy { grant <session-keyname> zonesub any; };
	 */
	if (autoddns) {
		dns_rdatatype_t any = dns_rdatatype_any;

		if (ns_g_server->session_keyname == NULL) {
			isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
				      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
				      "failed to enable auto DDNS policy "
				      "for zone %s: session key not found",
				      zname);
			result = ISC_R_NOTFOUND;
			goto cleanup;
		}

		result = dns_ssutable_addrule(table, ISC_TRUE,
					      ns_g_server->session_keyname,
					      DNS_SSUMATCHTYPE_SUBDOMAIN,
					      dns_zone_getorigin(zone),
					      1, &any);

		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}

	result = ISC_R_SUCCESS;
	dns_zone_setssutable(zone, table);

 cleanup:
	dns_ssutable_detach(&table);
	return (result);
}
コード例 #3
0
ファイル: zoneconf.c プロジェクト: ElRevo/xia-core
isc_result_t
ns_zone_configure(const cfg_obj_t *config, const cfg_obj_t *vconfig,
		  const cfg_obj_t *zconfig, cfg_aclconfctx_t *ac,
		  dns_zone_t *zone)
{
	isc_result_t result;
	const char *zname;
	dns_rdataclass_t zclass;
	dns_rdataclass_t vclass;
	const cfg_obj_t *maps[5];
	const cfg_obj_t *zoptions = NULL;
	const cfg_obj_t *options = NULL;
	const cfg_obj_t *obj;
	const char *filename = NULL;
	dns_notifytype_t notifytype = dns_notifytype_yes;
	isc_sockaddr_t *addrs;
	dns_name_t **keynames;
	isc_uint32_t count;
	char *cpval;
	unsigned int dbargc;
	char **dbargv;
	static char default_dbtype[] = "rbt";
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	dns_dialuptype_t dialup = dns_dialuptype_no;
	dns_zonetype_t ztype;
	int i;
	isc_int32_t journal_size;
	isc_boolean_t multi;
	isc_boolean_t alt;
	dns_view_t *view;
	isc_boolean_t check = ISC_FALSE, fail = ISC_FALSE;
	isc_boolean_t warn = ISC_FALSE, ignore = ISC_FALSE;
	isc_boolean_t ixfrdiff;
	dns_masterformat_t masterformat;
	isc_stats_t *zoneqrystats;
	isc_boolean_t zonestats_on;
	int seconds;

	i = 0;
	if (zconfig != NULL) {
		zoptions = cfg_tuple_get(zconfig, "options");
		maps[i++] = zoptions;
	}
	if (vconfig != NULL)
		maps[i++] = cfg_tuple_get(vconfig, "options");
	if (config != NULL) {
		(void)cfg_map_get(config, "options", &options);
		if (options != NULL)
			maps[i++] = options;
	}
	maps[i++] = ns_g_defaults;
	maps[i] = NULL;

	if (vconfig != NULL)
		RETERR(ns_config_getclass(cfg_tuple_get(vconfig, "class"),
					  dns_rdataclass_in, &vclass));
	else
		vclass = dns_rdataclass_in;

	/*
	 * Configure values common to all zone types.
	 */

	zname = cfg_obj_asstring(cfg_tuple_get(zconfig, "name"));

	RETERR(ns_config_getclass(cfg_tuple_get(zconfig, "class"),
				  vclass, &zclass));
	dns_zone_setclass(zone, zclass);

	ztype = zonetype_fromconfig(zoptions);
	dns_zone_settype(zone, ztype);

	obj = NULL;
	result = cfg_map_get(zoptions, "database", &obj);
	if (result == ISC_R_SUCCESS)
		cpval = isc_mem_strdup(mctx, cfg_obj_asstring(obj));
	else
		cpval = default_dbtype;

	if (cpval == NULL)
		return(ISC_R_NOMEMORY);

	result = strtoargv(mctx, cpval, &dbargc, &dbargv);
	if (result != ISC_R_SUCCESS && cpval != default_dbtype) {
		isc_mem_free(mctx, cpval);
		return (result);
	}

	/*
	 * ANSI C is strange here.  There is no logical reason why (char **)
	 * cannot be promoted automatically to (const char * const *) by the
	 * compiler w/o generating a warning.
	 */
	result = dns_zone_setdbtype(zone, dbargc, (const char * const *)dbargv);
	isc_mem_put(mctx, dbargv, dbargc * sizeof(*dbargv));
	if (cpval != default_dbtype)
		isc_mem_free(mctx, cpval);
	if (result != ISC_R_SUCCESS)
		return (result);

	obj = NULL;
	result = cfg_map_get(zoptions, "file", &obj);
	if (result == ISC_R_SUCCESS)
		filename = cfg_obj_asstring(obj);

	/*
	 * Unless we're using some alternative database, a master zone
	 * will be needing a master file.
	 */
	if (ztype == dns_zone_master && cpval == default_dbtype &&
	    filename == NULL) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
			      "zone '%s': 'file' not specified",
			      zname);
		return (ISC_R_FAILURE);
	}

	masterformat = dns_masterformat_text;
	obj = NULL;
	result= ns_config_get(maps, "masterfile-format", &obj);
	if (result == ISC_R_SUCCESS) {
		const char *masterformatstr = cfg_obj_asstring(obj);

		if (strcasecmp(masterformatstr, "text") == 0)
			masterformat = dns_masterformat_text;
		else if (strcasecmp(masterformatstr, "raw") == 0)
			masterformat = dns_masterformat_raw;
		else
			INSIST(0);
	}
	RETERR(dns_zone_setfile2(zone, filename, masterformat));

	obj = NULL;
	result = cfg_map_get(zoptions, "journal", &obj);
	if (result == ISC_R_SUCCESS)
		RETERR(dns_zone_setjournal(zone, cfg_obj_asstring(obj)));

	if (ztype == dns_zone_slave)
		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_notify, ac, zone,
					  dns_zone_setnotifyacl,
					  dns_zone_clearnotifyacl));
	/*
	 * XXXAG This probably does not make sense for stubs.
	 */
	RETERR(configure_zone_acl(zconfig, vconfig, config,
				  allow_query, ac, zone,
				  dns_zone_setqueryacl,
				  dns_zone_clearqueryacl));

	obj = NULL;
	result = ns_config_get(maps, "dialup", &obj);
	INSIST(result == ISC_R_SUCCESS && obj != NULL);
	if (cfg_obj_isboolean(obj)) {
		if (cfg_obj_asboolean(obj))
			dialup = dns_dialuptype_yes;
		else
			dialup = dns_dialuptype_no;
	} else {
		const char *dialupstr = cfg_obj_asstring(obj);
		if (strcasecmp(dialupstr, "notify") == 0)
			dialup = dns_dialuptype_notify;
		else if (strcasecmp(dialupstr, "notify-passive") == 0)
			dialup = dns_dialuptype_notifypassive;
		else if (strcasecmp(dialupstr, "refresh") == 0)
			dialup = dns_dialuptype_refresh;
		else if (strcasecmp(dialupstr, "passive") == 0)
			dialup = dns_dialuptype_passive;
		else
			INSIST(0);
	}
	dns_zone_setdialup(zone, dialup);

	obj = NULL;
	result = ns_config_get(maps, "zone-statistics", &obj);
	INSIST(result == ISC_R_SUCCESS && obj != NULL);
	zonestats_on = cfg_obj_asboolean(obj);
	zoneqrystats = NULL;
	if (zonestats_on) {
		RETERR(isc_stats_create(mctx, &zoneqrystats,
					dns_nsstatscounter_max));
	}
	dns_zone_setrequeststats(zone, zoneqrystats);
	if (zoneqrystats != NULL)
		isc_stats_detach(&zoneqrystats);

	/*
	 * Configure master functionality.  This applies
	 * to primary masters (type "master") and slaves
	 * acting as masters (type "slave"), but not to stubs.
	 */
	if (ztype != dns_zone_stub && ztype != dns_zone_staticstub) {
		obj = NULL;
		result = ns_config_get(maps, "notify", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (cfg_obj_isboolean(obj)) {
			if (cfg_obj_asboolean(obj))
				notifytype = dns_notifytype_yes;
			else
				notifytype = dns_notifytype_no;
		} else {
			const char *notifystr = cfg_obj_asstring(obj);
			if (strcasecmp(notifystr, "explicit") == 0)
				notifytype = dns_notifytype_explicit;
			else if (strcasecmp(notifystr, "master-only") == 0)
				notifytype = dns_notifytype_masteronly;
			else
				INSIST(0);
		}
		dns_zone_setnotifytype(zone, notifytype);

		obj = NULL;
		result = ns_config_get(maps, "also-notify", &obj);
		if (result == ISC_R_SUCCESS) {
			isc_sockaddr_t *addrs = NULL;
			isc_uint32_t addrcount;
			result = ns_config_getiplist(config, obj, 0, mctx,
						     &addrs, &addrcount);
			if (result != ISC_R_SUCCESS)
				return (result);
			result = dns_zone_setalsonotify(zone, addrs,
							addrcount);
			ns_config_putiplist(mctx, &addrs, addrcount);
			if (result != ISC_R_SUCCESS)
				return (result);
		} else
			RETERR(dns_zone_setalsonotify(zone, NULL, 0));

		obj = NULL;
		result = ns_config_get(maps, "notify-source", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setnotifysrc4(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "notify-source-v6", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setnotifysrc6(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "notify-to-soa", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_NOTIFYTOSOA,
				   cfg_obj_asboolean(obj));

		dns_zone_setisself(zone, ns_client_isself, NULL);

		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_transfer, ac, zone,
					  dns_zone_setxfracl,
					  dns_zone_clearxfracl));

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-time-out", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxxfrout(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-idle-out", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setidleout(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result =  ns_config_get(maps, "max-journal-size", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setjournalsize(zone, -1);
		if (cfg_obj_isstring(obj)) {
			const char *str = cfg_obj_asstring(obj);
			INSIST(strcasecmp(str, "unlimited") == 0);
			journal_size = ISC_UINT32_MAX / 2;
		} else {
			isc_resourcevalue_t value;
			value = cfg_obj_asuint64(obj);
			if (value > ISC_UINT32_MAX / 2) {
				cfg_obj_log(obj, ns_g_lctx,
					    ISC_LOG_ERROR,
					    "'max-journal-size "
					    "%" ISC_PRINT_QUADFORMAT "d' "
					    "is too large",
					    value);
				RETERR(ISC_R_RANGE);
			}
			journal_size = (isc_uint32_t)value;
		}
		dns_zone_setjournalsize(zone, journal_size);

		obj = NULL;
		result = ns_config_get(maps, "ixfr-from-differences", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (cfg_obj_isboolean(obj))
			ixfrdiff = cfg_obj_asboolean(obj);
		else if (!strcasecmp(cfg_obj_asstring(obj), "master") &&
			 ztype == dns_zone_master)
			ixfrdiff = ISC_TRUE;
		else if (!strcasecmp(cfg_obj_asstring(obj), "slave") &&
			ztype == dns_zone_slave)
			ixfrdiff = ISC_TRUE;
		else
			ixfrdiff = ISC_FALSE;
		dns_zone_setoption(zone, DNS_ZONEOPT_IXFRFROMDIFFS, ixfrdiff);

		checknames(ztype, maps, &obj);
		INSIST(obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			fail = ISC_FALSE;
			check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			fail = check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			fail = check = ISC_FALSE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMES, check);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKNAMESFAIL, fail);

		obj = NULL;
		result = ns_config_get(maps, "notify-delay", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setnotifydelay(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "check-sibling", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKSIBLING,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "zero-no-soa-ttl", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setzeronosoattl(zone, cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "nsec3-test-zone", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_NSEC3TESTZONE,
				   cfg_obj_asboolean(obj));
	}

	/*
	 * Configure update-related options.  These apply to
	 * primary masters only.
	 */
	if (ztype == dns_zone_master) {
		dns_acl_t *updateacl;

		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_update, ac, zone,
					  dns_zone_setupdateacl,
					  dns_zone_clearupdateacl));

		updateacl = dns_zone_getupdateacl(zone);
		if (updateacl != NULL  && dns_acl_isinsecure(updateacl))
			isc_log_write(ns_g_lctx, DNS_LOGCATEGORY_SECURITY,
				      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
				      "zone '%s' allows updates by IP "
				      "address, which is insecure",
				      zname);

		RETERR(configure_zone_ssutable(zoptions, zone, zname));

		obj = NULL;
		result = ns_config_get(maps, "sig-validity-interval", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		{
			const cfg_obj_t *validity, *resign;

			validity = cfg_tuple_get(obj, "validity");
			seconds = cfg_obj_asuint32(validity) * 86400;
			dns_zone_setsigvalidityinterval(zone, seconds);

			resign = cfg_tuple_get(obj, "re-sign");
			if (cfg_obj_isvoid(resign)) {
				seconds /= 4;
			} else {
				if (seconds > 7 * 86400)
					seconds = cfg_obj_asuint32(resign) *
							86400;
				else
					seconds = cfg_obj_asuint32(resign) *
							3600;
			}
			dns_zone_setsigresigninginterval(zone, seconds);
		}

		obj = NULL;
		result = ns_config_get(maps, "key-directory", &obj);
		if (result == ISC_R_SUCCESS) {
			filename = cfg_obj_asstring(obj);
			RETERR(dns_zone_setkeydirectory(zone, filename));
		}

		obj = NULL;
		result = ns_config_get(maps, "sig-signing-signatures", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setsignatures(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "sig-signing-nodes", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setnodes(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "sig-signing-type", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setprivatetype(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "update-check-ksk", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_UPDATECHECKKSK,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "dnssec-dnskey-kskonly", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_DNSKEYKSKONLY,
				   cfg_obj_asboolean(obj));
	} else if (ztype == dns_zone_slave) {
		RETERR(configure_zone_acl(zconfig, vconfig, config,
					  allow_update_forwarding, ac, zone,
					  dns_zone_setforwardacl,
					  dns_zone_clearforwardacl));
	}

	/*%
	 * Primary master functionality.
	 */
	if (ztype == dns_zone_master) {
		isc_boolean_t allow = ISC_FALSE, maint = ISC_FALSE;

		obj = NULL;
		result = ns_config_get(maps, "check-wildcard", &obj);
		if (result == ISC_R_SUCCESS)
			check = cfg_obj_asboolean(obj);
		else
			check = ISC_FALSE;
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKWILDCARD, check);

		obj = NULL;
		result = ns_config_get(maps, "check-dup-records", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			fail = ISC_FALSE;
			check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			fail = check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			fail = check = ISC_FALSE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRR, check);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKDUPRRFAIL, fail);

		obj = NULL;
		result = ns_config_get(maps, "check-mx", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			fail = ISC_FALSE;
			check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			fail = check = ISC_TRUE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			fail = check = ISC_FALSE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMX, check);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKMXFAIL, fail);

		obj = NULL;
		result = ns_config_get(maps, "check-integrity", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_CHECKINTEGRITY,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = ns_config_get(maps, "check-mx-cname", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			warn = ISC_TRUE;
			ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			warn = ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			warn = ignore = ISC_TRUE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_WARNMXCNAME, warn);
		dns_zone_setoption(zone, DNS_ZONEOPT_IGNOREMXCNAME, ignore);

		obj = NULL;
		result = ns_config_get(maps, "check-srv-cname", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		if (strcasecmp(cfg_obj_asstring(obj), "warn") == 0) {
			warn = ISC_TRUE;
			ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "fail") == 0) {
			warn = ignore = ISC_FALSE;
		} else if (strcasecmp(cfg_obj_asstring(obj), "ignore") == 0) {
			warn = ignore = ISC_TRUE;
		} else
			INSIST(0);
		dns_zone_setoption(zone, DNS_ZONEOPT_WARNSRVCNAME, warn);
		dns_zone_setoption(zone, DNS_ZONEOPT_IGNORESRVCNAME, ignore);

		obj = NULL;
		result = ns_config_get(maps, "dnssec-secure-to-insecure", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setoption(zone, DNS_ZONEOPT_SECURETOINSECURE,
				   cfg_obj_asboolean(obj));

		obj = NULL;
		result = cfg_map_get(zoptions, "auto-dnssec", &obj);
		if (result == ISC_R_SUCCESS) {
			const char *arg = cfg_obj_asstring(obj);
			if (strcasecmp(arg, "allow") == 0)
				allow = ISC_TRUE;
			else if (strcasecmp(arg, "maintain") == 0)
				allow = maint = ISC_TRUE;
			else if (strcasecmp(arg, "off") == 0)
				;
			else
				INSIST(0);
			dns_zone_setkeyopt(zone, DNS_ZONEKEY_ALLOW, allow);
			dns_zone_setkeyopt(zone, DNS_ZONEKEY_MAINTAIN, maint);
		}
	}

	/*
	 * Configure slave functionality.
	 */
	switch (ztype) {
	case dns_zone_slave:
	case dns_zone_stub:
		count = 0;
		obj = NULL;
		(void)cfg_map_get(zoptions, "masters", &obj);
		if (obj != NULL) {
			addrs = NULL;
			keynames = NULL;
			RETERR(ns_config_getipandkeylist(config, obj, mctx,
							 &addrs, &keynames,
							 &count));
			result = dns_zone_setmasterswithkeys(zone, addrs,
							     keynames, count);
			ns_config_putipandkeylist(mctx, &addrs, &keynames,
						  count);
		} else
			result = dns_zone_setmasters(zone, NULL, 0);
		RETERR(result);

		multi = ISC_FALSE;
		if (count > 1) {
			obj = NULL;
			result = ns_config_get(maps, "multi-master", &obj);
			INSIST(result == ISC_R_SUCCESS && obj != NULL);
			multi = cfg_obj_asboolean(obj);
		}
		dns_zone_setoption(zone, DNS_ZONEOPT_MULTIMASTER, multi);

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-time-in", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxxfrin(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result = ns_config_get(maps, "max-transfer-idle-in", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setidlein(zone, cfg_obj_asuint32(obj) * 60);

		obj = NULL;
		result = ns_config_get(maps, "max-refresh-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxrefreshtime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "min-refresh-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setminrefreshtime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "max-retry-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setmaxretrytime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "min-retry-time", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		dns_zone_setminretrytime(zone, cfg_obj_asuint32(obj));

		obj = NULL;
		result = ns_config_get(maps, "transfer-source", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setxfrsource4(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "transfer-source-v6", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setxfrsource6(zone, cfg_obj_assockaddr(obj)));
		ns_add_reserved_dispatch(ns_g_server, cfg_obj_assockaddr(obj));

		obj = NULL;
		result = ns_config_get(maps, "alt-transfer-source", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setaltxfrsource4(zone, cfg_obj_assockaddr(obj)));

		obj = NULL;
		result = ns_config_get(maps, "alt-transfer-source-v6", &obj);
		INSIST(result == ISC_R_SUCCESS && obj != NULL);
		RETERR(dns_zone_setaltxfrsource6(zone, cfg_obj_assockaddr(obj)));

		obj = NULL;
		(void)ns_config_get(maps, "use-alt-transfer-source", &obj);
		if (obj == NULL) {
			/*
			 * Default off when views are in use otherwise
			 * on for BIND 8 compatibility.
			 */
			view = dns_zone_getview(zone);
			if (view != NULL && strcmp(view->name, "_default") == 0)
				alt = ISC_TRUE;
			else
				alt = ISC_FALSE;
		} else
			alt = cfg_obj_asboolean(obj);
		dns_zone_setoption(zone, DNS_ZONEOPT_USEALTXFRSRC, alt);

		obj = NULL;
		(void)ns_config_get(maps, "try-tcp-refresh", &obj);
		dns_zone_setoption(zone, DNS_ZONEOPT_TRYTCPREFRESH,
				   cfg_obj_asboolean(obj));
		break;

	case dns_zone_staticstub:
		RETERR(configure_staticstub(zoptions, zone, zname,
					    default_dbtype));
		break;

	default:
		break;
	}

	return (ISC_R_SUCCESS);
}
コード例 #4
0
ファイル: rootns.c プロジェクト: enukane/netbsd-src
void
dns_root_checkhints(dns_view_t *view, dns_db_t *hints, dns_db_t *db) {
	isc_result_t result;
	dns_rdata_t rdata = DNS_RDATA_INIT;
	dns_rdata_ns_t ns;
	dns_rdataset_t hintns, rootns;
	const char *viewname = "", *sep = "";
	isc_stdtime_t now;
	dns_name_t *name;
	dns_fixedname_t fixed;

	REQUIRE(hints != NULL);
	REQUIRE(db != NULL);
	REQUIRE(view != NULL);

	isc_stdtime_get(&now);

	if (strcmp(view->name, "_bind") != 0 &&
	    strcmp(view->name, "_default") != 0) {
		viewname = view->name;
		sep = ": view ";
	}

	dns_rdataset_init(&hintns);
	dns_rdataset_init(&rootns);
	dns_fixedname_init(&fixed);
	name = dns_fixedname_name(&fixed);

	result = dns_db_find(hints, dns_rootname, NULL, dns_rdatatype_ns, 0,
			     now, NULL, name, &hintns, NULL);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
			      "checkhints%s%s: unable to get root NS rrset "
			      "from hints: %s", sep, viewname,
			      dns_result_totext(result));
		goto cleanup;
	}

	result = dns_db_find(db, dns_rootname, NULL, dns_rdatatype_ns, 0,
			     now, NULL, name, &rootns, NULL);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
			      "checkhints%s%s: unable to get root NS rrset "
			      "from cache: %s", sep, viewname,
			      dns_result_totext(result));
		goto cleanup;
	}

	/*
	 * Look for missing root NS names.
	 */
	result = dns_rdataset_first(&rootns);
	while (result == ISC_R_SUCCESS) {
		dns_rdataset_current(&rootns, &rdata);
		result = dns_rdata_tostruct(&rdata, &ns, NULL);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
		result = in_rootns(&hintns, &ns.name);
		if (result != ISC_R_SUCCESS) {
			char namebuf[DNS_NAME_FORMATSIZE];
			/* missing from hints */
			dns_name_format(&ns.name, namebuf, sizeof(namebuf));
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
				      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
				      "checkhints%s%s: unable to find root "
				      "NS '%s' in hints", sep, viewname,
				      namebuf);
		} else
			check_address_records(view, hints, db, &ns.name, now);
		dns_rdata_reset(&rdata);
		result = dns_rdataset_next(&rootns);
	}
	if (result != ISC_R_NOMORE) {
		goto cleanup;
	}

	/*
	 * Look for extra root NS names.
	 */
	result = dns_rdataset_first(&hintns);
	while (result == ISC_R_SUCCESS) {
		dns_rdataset_current(&hintns, &rdata);
		result = dns_rdata_tostruct(&rdata, &ns, NULL);
		RUNTIME_CHECK(result == ISC_R_SUCCESS);
		result = in_rootns(&rootns, &ns.name);
		if (result != ISC_R_SUCCESS) {
			char namebuf[DNS_NAME_FORMATSIZE];
			/* extra entry in hints */
			dns_name_format(&ns.name, namebuf, sizeof(namebuf));
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
				      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
				      "checkhints%s%s: extra NS '%s' in hints",
				      sep, viewname, namebuf);
		}
		dns_rdata_reset(&rdata);
		result = dns_rdataset_next(&hintns);
	}
	if (result != ISC_R_NOMORE) {
		goto cleanup;
	}

 cleanup:
	if (dns_rdataset_isassociated(&rootns))
		dns_rdataset_disassociate(&rootns);
	if (dns_rdataset_isassociated(&hintns))
		dns_rdataset_disassociate(&hintns);
}
コード例 #5
0
ファイル: diff.c プロジェクト: 274914765/C
isc_result_t dns_diff_load (dns_diff_t * diff, dns_addrdatasetfunc_t addfunc, void *add_private)
{
    dns_difftuple_t *t;

    isc_result_t result;

    REQUIRE (DNS_DIFF_VALID (diff));

    t = ISC_LIST_HEAD (diff->tuples);
    while (t != NULL)
    {
        dns_name_t *name;

        name = &t->name;
        while (t != NULL && dns_name_equal (&t->name, name))
        {
            dns_rdatatype_t type, covers;

            dns_diffop_t op;

            dns_rdatalist_t rdl;

            dns_rdataset_t rds;

            op = t->op;
            type = t->rdata.type;
            covers = rdata_covers (&t->rdata);

            rdl.type = type;
            rdl.covers = covers;
            rdl.rdclass = t->rdata.rdclass;
            rdl.ttl = t->ttl;
            ISC_LIST_INIT (rdl.rdata);
            ISC_LINK_INIT (&rdl, link);

            while (t != NULL && dns_name_equal (&t->name, name) &&
                   t->op == op && t->rdata.type == type && rdata_covers (&t->rdata) == covers)
            {
                ISC_LIST_APPEND (rdl.rdata, &t->rdata, link);
                t = ISC_LIST_NEXT (t, link);
            }

            /*
             * Convert the rdatalist into a rdataset.
             */
            dns_rdataset_init (&rds);
            CHECK (dns_rdatalist_tordataset (&rdl, &rds));
            rds.trust = dns_trust_ultimate;

            INSIST (op == DNS_DIFFOP_ADD);
            result = (*addfunc) (add_private, name, &rds);
            if (result == DNS_R_UNCHANGED)
            {
                isc_log_write (DIFF_COMMON_LOGARGS, ISC_LOG_WARNING, "dns_diff_load: " "update with no effect");
            }
            else if (result == ISC_R_SUCCESS || result == DNS_R_NXRRSET)
            {
                /*
                 * OK.
                 */
            }
            else
            {
                CHECK (result);
            }
        }
    }
    result = ISC_R_SUCCESS;
  failure:
    return (result);
}
コード例 #6
0
ファイル: control.c プロジェクト: 2014-class/freerouter
/*%
 * This function is called to process the incoming command
 * when a control channel message is received.
 */
isc_result_t
ns_control_docommand(isccc_sexpr_t *message, isc_buffer_t *text) {
	isccc_sexpr_t *data;
	char *command;
	isc_result_t result;
	int log_level;
#ifdef HAVE_LIBSCF
	ns_smf_want_disable = 0;
#endif

	data = isccc_alist_lookup(message, "_data");
	if (data == NULL) {
		/*
		 * No data section.
		 */
		return (ISC_R_FAILURE);
	}

	result = isccc_cc_lookupstring(data, "type", &command);
	if (result != ISC_R_SUCCESS) {
		/*
		 * We have no idea what this is.
		 */
		return (result);
	}

	/*
	 * Compare the 'command' parameter against all known control commands.
	 */
	if (command_compare(command, NS_COMMAND_NULL) ||
	    command_compare(command, NS_COMMAND_STATUS)) {
		log_level = ISC_LOG_DEBUG(1);
	} else {
		log_level = ISC_LOG_INFO;
	}
	isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
		      NS_LOGMODULE_CONTROL, log_level,
		      "received control channel command '%s'",
		      command);

	if (command_compare(command, NS_COMMAND_RELOAD)) {
		result = ns_server_reloadcommand(ns_g_server, command, text);
	} else if (command_compare(command, NS_COMMAND_RECONFIG)) {
		result = ns_server_reconfigcommand(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_REFRESH)) {
		result = ns_server_refreshcommand(ns_g_server, command, text);
	} else if (command_compare(command, NS_COMMAND_RETRANSFER)) {
		result = ns_server_retransfercommand(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_HALT)) {
#ifdef HAVE_LIBSCF
		/*
		 * If we are managed by smf(5), AND in chroot, then
		 * we cannot connect to the smf repository, so just
		 * return with an appropriate message back to rndc.
		 */
		if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
			result = ns_smf_add_message(text);
			return (result);
		}
		/*
		 * If we are managed by smf(5) but not in chroot,
		 * try to disable ourselves the smf way.
		 */
		if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
			ns_smf_want_disable = 1;
		/*
		 * If ns_smf_got_instance = 0, ns_smf_chroot
		 * is not relevant and we fall through to
		 * isc_app_shutdown below.
		 */
#endif
		/* Do not flush master files */
		ns_server_flushonshutdown(ns_g_server, ISC_FALSE);
		ns_os_shutdownmsg(command, text);
		isc_app_shutdown();
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NS_COMMAND_STOP)) {
		/*
		 * "stop" is the same as "halt" except it does
		 * flush master files.
		 */
#ifdef HAVE_LIBSCF
		if (ns_smf_got_instance == 1 && ns_smf_chroot == 1) {
			result = ns_smf_add_message(text);
			return (result);
		}
		if (ns_smf_got_instance == 1 && ns_smf_chroot == 0)
			ns_smf_want_disable = 1;
#endif
		ns_server_flushonshutdown(ns_g_server, ISC_TRUE);
		ns_os_shutdownmsg(command, text);
		isc_app_shutdown();
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NS_COMMAND_DUMPSTATS)) {
		result = ns_server_dumpstats(ns_g_server);
	} else if (command_compare(command, NS_COMMAND_QUERYLOG)) {
		result = ns_server_togglequerylog(ns_g_server);
	} else if (command_compare(command, NS_COMMAND_DUMPDB)) {
		ns_server_dumpdb(ns_g_server, command);
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NS_COMMAND_SECROOTS)) {
		result = ns_server_dumpsecroots(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_TRACE)) {
		result = ns_server_setdebuglevel(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_NOTRACE)) {
		ns_g_debuglevel = 0;
		isc_log_setdebuglevel(ns_g_lctx, ns_g_debuglevel);
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NS_COMMAND_FLUSH)) {
		result = ns_server_flushcache(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_FLUSHNAME)) {
		result = ns_server_flushname(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_STATUS)) {
		result = ns_server_status(ns_g_server, text);
	} else if (command_compare(command, NS_COMMAND_TSIGLIST)) {
		result = ns_server_tsiglist(ns_g_server, text);
	} else if (command_compare(command, NS_COMMAND_TSIGDELETE)) {
		result = ns_server_tsigdelete(ns_g_server, command, text);
	} else if (command_compare(command, NS_COMMAND_FREEZE)) {
		result = ns_server_freeze(ns_g_server, ISC_TRUE, command,
					  text);
	} else if (command_compare(command, NS_COMMAND_UNFREEZE) ||
		   command_compare(command, NS_COMMAND_THAW)) {
		result = ns_server_freeze(ns_g_server, ISC_FALSE, command,
					  text);
	} else if (command_compare(command, NS_COMMAND_RECURSING)) {
		result = ns_server_dumprecursing(ns_g_server);
	} else if (command_compare(command, NS_COMMAND_TIMERPOKE)) {
		result = ISC_R_SUCCESS;
		isc_timermgr_poke(ns_g_timermgr);
	} else if (command_compare(command, NS_COMMAND_NULL)) {
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NS_COMMAND_NOTIFY)) {
		result = ns_server_notifycommand(ns_g_server, command, text);
	} else if (command_compare(command, NS_COMMAND_VALIDATION)) {
		result = ns_server_validation(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_SIGN) ||
		   command_compare(command, NS_COMMAND_LOADKEYS)) {
		result = ns_server_rekey(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_ADDZONE)) {
		result = ns_server_add_zone(ns_g_server, command);
	} else if (command_compare(command, NS_COMMAND_DELZONE)) {
		result = ns_server_del_zone(ns_g_server, command);
	} else {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_CONTROL, ISC_LOG_WARNING,
			      "unknown control channel command '%s'",
			      command);
		result = DNS_R_UNKNOWNCOMMAND;
	}

	return (result);
}
コード例 #7
0
ファイル: tsig.c プロジェクト: BII-Lab/BIND9.9.6-Always-TC
isc_result_t
dns_tsigkey_createfromkey(dns_name_t *name, dns_name_t *algorithm,
			  dst_key_t *dstkey, isc_boolean_t generated,
			  dns_name_t *creator, isc_stdtime_t inception,
			  isc_stdtime_t expire, isc_mem_t *mctx,
			  dns_tsig_keyring_t *ring, dns_tsigkey_t **key)
{
	dns_tsigkey_t *tkey;
	isc_result_t ret;
	unsigned int refs = 0;

	REQUIRE(key == NULL || *key == NULL);
	REQUIRE(name != NULL);
	REQUIRE(algorithm != NULL);
	REQUIRE(mctx != NULL);
	REQUIRE(key != NULL || ring != NULL);

	tkey = (dns_tsigkey_t *) isc_mem_get(mctx, sizeof(dns_tsigkey_t));
	if (tkey == NULL)
		return (ISC_R_NOMEMORY);

	dns_name_init(&tkey->name, NULL);
	ret = dns_name_dup(name, mctx, &tkey->name);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_key;
	(void)dns_name_downcase(&tkey->name, &tkey->name, NULL);

	if (dns_name_equal(algorithm, DNS_TSIG_HMACMD5_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACMD5_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACMD5) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA1_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA1_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_HMACSHA1) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA224_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA224_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA224) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA256_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA256_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA256) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA384_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA384_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA384) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_HMACSHA512_NAME)) {
		tkey->algorithm = DNS_TSIG_HMACSHA512_NAME;
		if (dstkey != NULL &&
		    dst_key_alg(dstkey) != DST_ALG_HMACSHA512) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPI_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else if (dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		tkey->algorithm = DNS_TSIG_GSSAPIMS_NAME;
		if (dstkey != NULL && dst_key_alg(dstkey) != DST_ALG_GSSAPI) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
	} else {
		if (dstkey != NULL) {
			ret = DNS_R_BADALG;
			goto cleanup_name;
		}
		tkey->algorithm = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->algorithm == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_name;
		}
		dns_name_init(tkey->algorithm, NULL);
		ret = dns_name_dup(algorithm, mctx, tkey->algorithm);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_algorithm;
		(void)dns_name_downcase(tkey->algorithm, tkey->algorithm,
					NULL);
	}

	if (creator != NULL) {
		tkey->creator = isc_mem_get(mctx, sizeof(dns_name_t));
		if (tkey->creator == NULL) {
			ret = ISC_R_NOMEMORY;
			goto cleanup_algorithm;
		}
		dns_name_init(tkey->creator, NULL);
		ret = dns_name_dup(creator, mctx, tkey->creator);
		if (ret != ISC_R_SUCCESS) {
			isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
			goto cleanup_algorithm;
		}
	} else
		tkey->creator = NULL;

	tkey->key = NULL;
	if (dstkey != NULL)
		dst_key_attach(dstkey, &tkey->key);
	tkey->ring = ring;

	if (key != NULL)
		refs = 1;
	if (ring != NULL)
		refs++;
	ret = isc_refcount_init(&tkey->refs, refs);
	if (ret != ISC_R_SUCCESS)
		goto cleanup_creator;

	tkey->generated = generated;
	tkey->inception = inception;
	tkey->expire = expire;
	tkey->mctx = NULL;
	isc_mem_attach(mctx, &tkey->mctx);

	tkey->magic = TSIG_MAGIC;

	if (ring != NULL) {
		ret = keyring_add(ring, name, tkey);
		if (ret != ISC_R_SUCCESS)
			goto cleanup_refs;
	}

	/*
	 * Ignore this if it's a GSS key, since the key size is meaningless.
	 */
	if (dstkey != NULL && dst_key_size(dstkey) < 64 &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPI_NAME) &&
	    !dns_name_equal(algorithm, DNS_TSIG_GSSAPIMS_NAME)) {
		char namestr[DNS_NAME_FORMATSIZE];
		dns_name_format(name, namestr, sizeof(namestr));
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DNSSEC,
			      DNS_LOGMODULE_TSIG, ISC_LOG_INFO,
			      "the key '%s' is too short to be secure",
			      namestr);
	}

	if (key != NULL)
		*key = tkey;

	return (ISC_R_SUCCESS);

 cleanup_refs:
	tkey->magic = 0;
	while (refs-- > 0)
		isc_refcount_decrement(&tkey->refs, NULL);
	isc_refcount_destroy(&tkey->refs);
 cleanup_creator:
	if (tkey->key != NULL)
		dst_key_free(&tkey->key);
	if (tkey->creator != NULL) {
		dns_name_free(tkey->creator, mctx);
		isc_mem_put(mctx, tkey->creator, sizeof(dns_name_t));
	}
 cleanup_algorithm:
	if (algname_is_allocated(tkey->algorithm)) {
		if (dns_name_dynamic(tkey->algorithm))
			dns_name_free(tkey->algorithm, mctx);
		isc_mem_put(mctx, tkey->algorithm, sizeof(dns_name_t));
	}
 cleanup_name:
	dns_name_free(&tkey->name, mctx);
 cleanup_key:
	isc_mem_put(mctx, tkey, sizeof(dns_tsigkey_t));

	return (ret);
}
コード例 #8
0
static isc_result_t
odbc_connect(odbc_instance_t *dbi, odbc_db_t **dbc) {

	odbc_db_t *ndb = *dbc;
	SQLRETURN sqlRes;
	isc_result_t result = ISC_R_SUCCESS;

	if (ndb != NULL) {
		/*
		 * if db != null, we have to do some cleanup
		 * if statement handle != null free it
		 */
		if (ndb->stmnt != NULL) {
			SQLFreeHandle(SQL_HANDLE_STMT, ndb->stmnt);
			ndb->stmnt = NULL;
		}

		/* if connection handle != null free it */
		if (ndb->dbc != NULL) {
			SQLFreeHandle(SQL_HANDLE_DBC, ndb->dbc);
			ndb->dbc = NULL;
		}
	} else {
		ndb = isc_mem_allocate(ns_g_mctx, sizeof(odbc_db_t));
		if (ndb == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver unable to allocate memory");
			return ISC_R_NOMEMORY;
		}
		memset(ndb, 0, sizeof(odbc_db_t));
	}

	sqlRes = SQLAllocHandle(SQL_HANDLE_DBC, dbi->sql_env, &(ndb->dbc));
	if (!sqlOK(sqlRes)) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver unable to allocate memory");
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	sqlRes = SQLConnect(ndb->dbc, dbi->dsn, safeLen(dbi->dsn), dbi->user,
			    safeLen(dbi->user), dbi->pass, safeLen(dbi->pass));
	if (!sqlOK(sqlRes)) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver unable to connect");
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	sqlRes = SQLAllocHandle(SQL_HANDLE_STMT, ndb->dbc, &(ndb->stmnt));
	if (!sqlOK(sqlRes)) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver unable to allocate memory");
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	*dbc = ndb;

	return ISC_R_SUCCESS;

 cleanup:

	if (ndb != NULL) {

		/* if statement handle != null free it */
		if (ndb->stmnt != NULL) {
			SQLFreeHandle(SQL_HANDLE_STMT, ndb->stmnt);
			ndb->stmnt = NULL;
		}

		/* if connection handle != null free it */
		if (ndb->dbc != NULL) {
			SQLDisconnect(ndb->dbc);
			SQLFreeHandle(SQL_HANDLE_DBC, ndb->dbc);
			ndb->dbc = NULL;
		}
		/* free memory holding ndb */
		isc_mem_free(ns_g_mctx, ndb);
	}

	return result;
}
コード例 #9
0
static isc_result_t
odbc_get_resultset(const char *zone, const char *record,
		   const char *client, unsigned int query,
		   void *dbdata, dbinstance_t **r_dbi)
{

	isc_result_t result;
	dbinstance_t *dbi = NULL;
	char *querystring = NULL;
	unsigned int j = 0;
	SQLRETURN sqlRes;

	REQUIRE(*r_dbi == NULL);

	/* get db instance / connection */
#ifdef ISC_PLATFORM_USETHREADS

	/* find an available DBI from the list */
	dbi = odbc_find_avail_conn(((odbc_instance_t *) dbdata)->db);

#else /* ISC_PLATFORM_USETHREADS */

	/*
	 * only 1 DBI - no need to lock instance lock either
	 * only 1 thread in the whole process, no possible contention.
	 */
	dbi =  (dbinstance_t *) ((odbc_instance_t *) dbdata)->db;

#endif /* ISC_PLATFORM_USETHREADS */

	/* if DBI is null, can't do anything else */
	if (dbi == NULL) {
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/* what type of query are we going to run? */
	switch(query) {
	case ALLNODES:
		/*
		 * if the query was not passed in from the config file
		 * then we can't run it.  return not_implemented, so
		 * it's like the code for that operation was never
		 * built into the driver.... AHHH flexibility!!!
		 */
		if (dbi->allnodes_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case ALLOWXFR:
		/* same as comments as ALLNODES */
		if (dbi->allowxfr_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case AUTHORITY:
		/* same as comments as ALLNODES */
		if (dbi->authority_q == NULL) {
			result = ISC_R_NOTIMPLEMENTED;
			goto cleanup;
		}
		break;
	case FINDZONE:
		/* this is required.  It's the whole point of DLZ! */
		if (dbi->findzone_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for findzone.  "
				      "Findzone requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	case LOOKUP:
		/* this is required.  It's also a major point of DLZ! */
		if (dbi->lookup_q == NULL) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(2),
				      "No query specified for lookup.  "
				      "Lookup requires a query");
			result = ISC_R_FAILURE;
			goto cleanup;
		}
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "odbc_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}


	/*
	 * was a zone string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (zone != NULL) {
		dbi->zone = odbc_escape_string(zone);
		if (dbi->zone == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->zone = NULL;
	}

	/*
	 * was a record string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (record != NULL) {
		dbi->record = odbc_escape_string(record);
		if (dbi->record == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->record = NULL;
	}

	/*
	 * was a client string passed?  If so, make it safe for use in
	 * queries.
	 */
	if (client != NULL) {
		dbi->client = odbc_escape_string(client);
		if (dbi->client == NULL) {
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	} else {	/* no string passed, set the string pointer to NULL */
		dbi->client = NULL;
	}

	/*
	 * what type of query are we going to run?
	 * this time we build the actual query to run.
	 */
	switch(query) {
	case ALLNODES:
		querystring = build_querystring(ns_g_mctx, dbi->allnodes_q);
		break;
	case ALLOWXFR:
		querystring = build_querystring(ns_g_mctx, dbi->allowxfr_q);
		break;
	case AUTHORITY:
		querystring = build_querystring(ns_g_mctx, dbi->authority_q);
		break;
	case FINDZONE:
		querystring = build_querystring(ns_g_mctx, dbi->findzone_q);
		break;
	case LOOKUP:
		querystring = build_querystring(ns_g_mctx, dbi->lookup_q);
		break;
	default:
		/*
		 * this should never happen.  If it does, the code is
		 * screwed up!
		 */
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "Incorrect query flag passed to "
				 "odbc_get_resultset");
		result = ISC_R_UNEXPECTED;
		goto cleanup;
	}

	/* if the querystring is null, Bummer, outta RAM.  UPGRADE TIME!!!   */
	if (querystring  == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}

	/* output the full query string during debug so we can see */
	/* what lame error the query has. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "\nQuery String: %s\n", querystring);

	/* attempt query up to 3 times. */
	for (j=0; j < 3; j++) {
		/* try to get result set */
		sqlRes = SQLExecDirect(((odbc_db_t *) dbi->dbconn)->stmnt,
				       (SQLCHAR *) querystring,
				       (SQLINTEGER) strlen(querystring));

		/* if error, reset DB connection */
		if (!sqlOK(sqlRes)) {
			/* close cursor */
			SQLCloseCursor(((odbc_db_t *) dbi->dbconn)->stmnt);
			/* attempt to reconnect */
			result = odbc_connect((odbc_instance_t *) dbdata,
					      (odbc_db_t **) &(dbi->dbconn));
			/* check if we reconnected */
			if (result != ISC_R_SUCCESS)
				break;
			/* incase this is the last time through the loop */
			result = ISC_R_FAILURE;
		} else {
			result = ISC_R_SUCCESS;
			/* return dbi */
			*r_dbi = dbi;
			/* result set ok, break loop */
			break;
		}
	}	/* end for loop */

 cleanup:	/* it's always good to cleanup after yourself */

		/* if we couldn't even allocate DBI, just return NULL */
	if (dbi == NULL)
		return ISC_R_FAILURE;

	/* free dbi->zone string */
	if (dbi->zone != NULL)
		isc_mem_free(ns_g_mctx, dbi->zone);

	/* free dbi->record string */
	if (dbi->record != NULL)
		isc_mem_free(ns_g_mctx, dbi->record);

	/* free dbi->client string */
	if (dbi->client != NULL)
		isc_mem_free(ns_g_mctx, dbi->client);

#ifdef ISC_PLATFORM_USETHREADS

	/* if we are done using this dbi, release the lock */
	if (result != ISC_R_SUCCESS)
		isc_mutex_unlock(&dbi->instance_lock);

#endif /* ISC_PLATFORM_USETHREADS */

	/* release query string */
	if (querystring  != NULL)
		isc_mem_free(ns_g_mctx, querystring );

	/* return result */
	return result;

}
コード例 #10
0
static isc_result_t
odbc_allnodes(const char *zone, void *driverarg, void *dbdata,
	      dns_sdlzallnodes_t *allnodes)
{

	isc_result_t result;
	dbinstance_t *dbi = NULL;
	SQLHSTMT  *stmnt;
	SQLSMALLINT fields;
	char *data;
	char *type;
	char *ttl_s;
	int ttl;
	char *host;
	char *endp;

	UNUSED(driverarg);

	/* run the query and get the result set from the database. */
	result = odbc_get_resultset(zone, NULL, NULL, ALLNODES, dbdata, &dbi);

	/* if we get "not implemented", send it along */
	if (result == ISC_R_NOTIMPLEMENTED)
		return result;

	/* if we didn't get a result set, log an err msg. */
	if (result != ISC_R_SUCCESS) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver unable to return "
			      "result set for all nodes query");
		return (ISC_R_FAILURE);
	}

	stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt;

	/* get number of columns */
	if (!sqlOK(SQLNumResultCols(stmnt, &fields))) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver unable to process result set");
		result = ISC_R_FAILURE;
		goto allnodes_cleanup;
	}

	if (fields < 4) {	/* gotta have at least 4 columns */
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver too few fields returned by "
			      "all nodes query");
		result = ISC_R_FAILURE;
		goto allnodes_cleanup;
	}

	/* get things ready for processing */
	result = ISC_R_FAILURE;

	while (sqlOK(SQLFetch(stmnt))) {

		/* set to null for next pass through */
		data = host = type = ttl_s = NULL;

		/*
		 * attempt to get DNS ttl, type, host, data then tell
		 * Bind about them
		 */
		if ((result = odbc_getField(stmnt, 1,
					    &ttl_s)) == ISC_R_SUCCESS &&
		    (result = odbc_getField(stmnt, 2,
					    &type)) == ISC_R_SUCCESS &&
		    (result = odbc_getField(stmnt, 3,
					    &host)) == ISC_R_SUCCESS &&
		    (result = odbc_getManyFields(stmnt, 4, fields,
						 &data)) == ISC_R_SUCCESS) {
			/* convert ttl string to int */
			ttl = strtol(ttl_s, &endp, 10);
			/* failure converting ttl. */
			if (*endp != '\0' || ttl < 0) {
				isc_log_write(dns_lctx,
					      DNS_LOGCATEGORY_DATABASE,
					      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
					      "Odbc driver ttl must be "
					      "a postive number");
				result = ISC_R_FAILURE;
			} else {
				/* successful converting TTL, tell Bind  */
				result = dns_sdlz_putnamedrr(allnodes, host,
							     type, ttl, data);
			}
		} /* closes big if () */

		/* clean up mem */
		if (ttl_s != NULL)
			isc_mem_free(ns_g_mctx, ttl_s);
		if (type != NULL)
			isc_mem_free(ns_g_mctx, type);
		if (host != NULL)
			isc_mem_free(ns_g_mctx, host);
		if (data != NULL)
			isc_mem_free(ns_g_mctx, data);

		/* if we weren't successful, log err msg */
		if (result != ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "dns_sdlz_putnamedrr returned error. "
				      "Error code was: %s",
				      isc_result_totext(result));
			result = ISC_R_FAILURE;
			goto allnodes_cleanup;
		}
	} /* closes while loop */

 allnodes_cleanup:

	/* close cursor */
	SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);

#ifdef ISC_PLATFORM_USETHREADS

	/* free lock on dbi so someone else can use it. */
	isc_mutex_unlock(&dbi->instance_lock);

#endif

	return result;
}
コード例 #11
0
/*%
 * create an instance of the driver.  Remember, only 1 copy of the driver's
 * code is ever loaded, the driver has to remember which context it's
 * operating in.  This is done via use of the dbdata argument which is
 * passed into all query functions.
 */
static isc_result_t
odbc_create(const char *dlzname, unsigned int argc, char *argv[],
	    void *driverarg, void **dbdata)
{
	isc_result_t result;
	odbc_instance_t *odbc_inst = NULL;
	dbinstance_t *db = NULL;
	SQLRETURN sqlRes;

#ifdef ISC_PLATFORM_USETHREADS
	/* if multi-threaded, we need a few extra variables. */
	int dbcount;
	int i;
	char *endp;

#endif /* ISC_PLATFORM_USETHREADS */

	UNUSED(dlzname);
	UNUSED(driverarg);

#ifdef ISC_PLATFORM_USETHREADS
	/* if debugging, let user know we are multithreaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Odbc driver running multithreaded");
#else /* ISC_PLATFORM_USETHREADS */
	/* if debugging, let user know we are single threaded. */
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
		      DNS_LOGMODULE_DLZ, ISC_LOG_DEBUG(1),
		      "Odbc driver running single threaded");
#endif /* ISC_PLATFORM_USETHREADS */

	/* verify we have at least 5 arg's passed to the driver */
	if (argc < 5) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver requires at least "
			      "4 command line args.");
		return (ISC_R_FAILURE);
	}

	/* no more than 8 arg's should be passed to the driver */
	if (argc > 8) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver cannot accept more than "
			      "7 command line args.");
		return (ISC_R_FAILURE);
	}

	/* multithreaded build can have multiple DB connections */
#ifdef ISC_PLATFORM_USETHREADS

	/* check how many db connections we should create */
	dbcount = strtol(argv[1], &endp, 10);
	if (*endp != '\0' || dbcount < 0) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver database connection count "
			      "must be positive.");
		return (ISC_R_FAILURE);
	}

#endif /* ISC_PLATFORM_USETHREADS */

	/* allocate memory for odbc instance */
	odbc_inst = isc_mem_get(ns_g_mctx, sizeof(odbc_instance_t));
	if (odbc_inst == NULL)
		return (ISC_R_NOMEMORY);
	memset(odbc_inst, 0, sizeof(odbc_instance_t));

	/* parse connection string and get paramters. */

	/* get odbc database dsn - required */
	odbc_inst->dsn = (SQLCHAR *) getParameterValue(argv[2],
						       "dsn=");
	if (odbc_inst->dsn == NULL) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "odbc driver requires a dns parameter.");
		result = ISC_R_FAILURE;
		goto cleanup;
	}
	/* get odbc database username */
	/* if no username was passed, set odbc_inst.user = NULL; */
	odbc_inst->user = (SQLCHAR *) getParameterValue(argv[2],
							"user=");

	/* get odbc database password */
	/* if no password was passed, set odbc_inst.pass = NULL; */
	odbc_inst->pass = (SQLCHAR *) getParameterValue(argv[2], "pass=");

	/* create odbc environment & set environment to ODBC V3 */
	if (odbc_inst->sql_env == NULL) {
		/* create environment handle */
		sqlRes = SQLAllocHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE,
					&(odbc_inst->sql_env));
		if (!sqlOK(sqlRes)) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
				      "Odbc driver unable to allocate memory");
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
		/*set ODBC version = 3 */
		sqlRes = SQLSetEnvAttr(odbc_inst->sql_env,
				       SQL_ATTR_ODBC_VERSION,
				       (void *) SQL_OV_ODBC3, 0);
		if (!sqlOK(sqlRes)) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_INFO,
				      "Unable to configure ODBC environment");
			result = ISC_R_NOMEMORY;
			goto cleanup;
		}
	}

#ifdef ISC_PLATFORM_USETHREADS

	/* allocate memory for database connection list */
	odbc_inst->db = isc_mem_get(ns_g_mctx, sizeof(db_list_t));
	if (odbc_inst->db == NULL) {
		result = ISC_R_NOMEMORY;
		goto cleanup;
	}


	/* initialize DB connection list */
	ISC_LIST_INIT(*odbc_inst->db);

	/* create the appropriate number of database instances (DBI) */
	/* append each new DBI to the end of the list */
	for (i=0; i < dbcount; i++) {

#endif /* ISC_PLATFORM_USETHREADS */

		/* how many queries were passed in from config file? */
		switch(argc) {
		case 5:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     NULL, argv[3], argv[4],
						     NULL, &db);
			break;
		case 6:
			result = build_sqldbinstance(ns_g_mctx, NULL, NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &db);
			break;
		case 7:
			result = build_sqldbinstance(ns_g_mctx, argv[6], NULL,
						     argv[5], argv[3], argv[4],
						     NULL, &db);
			break;
		case 8:
			result = build_sqldbinstance(ns_g_mctx, argv[6],
						     argv[7], argv[5], argv[3],
						     argv[4], NULL, &db);
			break;
		default:
			/* not really needed, should shut up compiler. */
			result = ISC_R_FAILURE;
		}

		/* unsuccessful?, log err msg and cleanup. */
		if (result != ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver could not create "
				      "database instance object.");
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* when multithreaded, build a list of DBI's */
		ISC_LINK_INIT(db, link);
		ISC_LIST_APPEND(*odbc_inst->db, db, link);

#endif

		result = odbc_connect(odbc_inst, (odbc_db_t **) &(db->dbconn));

		if (result != ISC_R_SUCCESS) {

#ifdef ISC_PLATFORM_USETHREADS

			/*
			 * if multi threaded, let user know which
			 * connection failed.  user could be
			 * attempting to create 10 db connections and
			 * for some reason the db backend only allows
			 * 9.
			 */
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver failed to create database "
				      "connection number %u after 3 attempts",
				      i+1);
#else
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "Odbc driver failed to create database "
				      "connection after 3 attempts");
#endif
			goto cleanup;
		}

#ifdef ISC_PLATFORM_USETHREADS

		/* set DB = null for next loop through. */
		db = NULL;

	}	/* end for loop */

#else
	/* tell odbc_inst about the db connection we just created. */
	odbc_inst->db = db;

#endif

	/* set dbdata to the odbc_instance we created. */
	*dbdata = odbc_inst;

	/* hey, we got through all of that ok, return success. */
	return(ISC_R_SUCCESS);

 cleanup:

	destroy_odbc_instance(odbc_inst);

	return result;
}
コード例 #12
0
ファイル: timer.c プロジェクト: execunix/vinos
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 USE_TIMER_THREAD
	isc_boolean_t timedwait;
#endif

	/*!
	 * Note: the caller must ensure locking.
	 */

	REQUIRE(timer->type != isc_timertype_inactive);

#ifndef USE_TIMER_THREAD
	UNUSED(signal_ok);
#endif /* USE_TIMER_THREAD */

	manager = timer->manager;

#ifdef USE_TIMER_THREAD
	/*!
	 * 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 USE_TIMER_THREAD

	/*
	 * 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 /* USE_TIMER_THREAD */
	if (timer->index == 1 &&
	    isc_time_compare(&timer->due, &manager->due) < 0)
		manager->due = timer->due;
#endif /* USE_TIMER_THREAD */

	return (ISC_R_SUCCESS);
}
コード例 #13
0
ファイル: control.c プロジェクト: each/bind9-collab
/*%
 * This function is called to process the incoming command
 * when a control channel message is received.
 */
isc_result_t
named_control_docommand(isccc_sexpr_t *message, isc_boolean_t readonly,
			isc_buffer_t **text)
{
	isccc_sexpr_t *data;
	char *cmdline = NULL;
	char *command = NULL;
	isc_result_t result;
	int log_level;
	isc_buffer_t src;
	isc_lex_t *lex = NULL;
#ifdef HAVE_LIBSCF
	named_smf_want_disable = 0;
#endif

	data = isccc_alist_lookup(message, "_data");
	if (!isccc_alist_alistp(data)) {
		/*
		 * No data section.
		 */
		return (ISC_R_FAILURE);
	}

	result = isccc_cc_lookupstring(data, "type", &cmdline);
	if (result != ISC_R_SUCCESS) {
		/*
		 * We have no idea what this is.
		 */
		return (result);
	}

	result = isc_lex_create(named_g_mctx, strlen(cmdline), &lex);
	if (result != ISC_R_SUCCESS)
		return (result);

	isc_buffer_init(&src, cmdline, strlen(cmdline));
	isc_buffer_add(&src, strlen(cmdline));
	result = isc_lex_openbuffer(lex, &src);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	result = getcommand(lex, &command);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	/*
	 * Compare the 'command' parameter against all known control commands.
	 */
	if (command_compare(command, NAMED_COMMAND_NULL) ||
	    command_compare(command, NAMED_COMMAND_STATUS))
	{
		log_level = ISC_LOG_DEBUG(1);
	} else {
		log_level = ISC_LOG_INFO;
	}

	/*
	 * If this listener should have read-only access, reject
	 * restricted commands here. rndc nta is handled specially
	 * below.
	 */
	if (readonly &&
	    !command_compare(command, NAMED_COMMAND_NTA) &&
	    !command_compare(command, NAMED_COMMAND_NULL) &&
	    !command_compare(command, NAMED_COMMAND_STATUS) &&
	    !command_compare(command, NAMED_COMMAND_SHOWZONE) &&
	    !command_compare(command, NAMED_COMMAND_TESTGEN) &&
	    !command_compare(command, NAMED_COMMAND_ZONESTATUS))
	{
		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
			      NAMED_LOGMODULE_CONTROL, log_level,
			      "rejecting restricted control channel "
			      "command '%s'", cmdline);
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
		      NAMED_LOGMODULE_CONTROL, log_level,
		      "received control channel command '%s'",
		      cmdline);

	if (command_compare(command, NAMED_COMMAND_RELOAD)) {
		result = named_server_reloadcommand(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_RECONFIG)) {
		result = named_server_reconfigcommand(named_g_server);
	} else if (command_compare(command, NAMED_COMMAND_REFRESH)) {
		result = named_server_refreshcommand(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_RETRANSFER)) {
		result = named_server_retransfercommand(named_g_server,
							lex, text);
	} else if (command_compare(command, NAMED_COMMAND_HALT)) {
#ifdef HAVE_LIBSCF
		/*
		 * If we are managed by smf(5), AND in chroot, then
		 * we cannot connect to the smf repository, so just
		 * return with an appropriate message back to rndc.
		 */
		if (named_smf_got_instance == 1 && named_smf_chroot == 1) {
			result = named_smf_add_message(text);
			goto cleanup;
		}
		/*
		 * If we are managed by smf(5) but not in chroot,
		 * try to disable ourselves the smf way.
		 */
		if (named_smf_got_instance == 1 && named_smf_chroot == 0)
			named_smf_want_disable = 1;
		/*
		 * If named_smf_got_instance = 0, named_smf_chroot
		 * is not relevant and we fall through to
		 * isc_app_shutdown below.
		 */
#endif
		/* Do not flush master files */
		named_server_flushonshutdown(named_g_server, ISC_FALSE);
		named_os_shutdownmsg(cmdline, *text);
		isc_app_shutdown();
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NAMED_COMMAND_STOP)) {
		/*
		 * "stop" is the same as "halt" except it does
		 * flush master files.
		 */
#ifdef HAVE_LIBSCF
		if (named_smf_got_instance == 1 && named_smf_chroot == 1) {
			result = named_smf_add_message(text);
			goto cleanup;
		}
		if (named_smf_got_instance == 1 && named_smf_chroot == 0)
			named_smf_want_disable = 1;
#endif
		named_server_flushonshutdown(named_g_server, ISC_TRUE);
		named_os_shutdownmsg(cmdline, *text);
		isc_app_shutdown();
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NAMED_COMMAND_DUMPSTATS)) {
		result = named_server_dumpstats(named_g_server);
	} else if (command_compare(command, NAMED_COMMAND_QUERYLOG)) {
		result = named_server_togglequerylog(named_g_server, lex);
	} else if (command_compare(command, NAMED_COMMAND_DUMPDB)) {
		named_server_dumpdb(named_g_server, lex, text);
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NAMED_COMMAND_SECROOTS)) {
		result = named_server_dumpsecroots(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_TRACE)) {
		result = named_server_setdebuglevel(named_g_server, lex);
	} else if (command_compare(command, NAMED_COMMAND_NOTRACE)) {
		named_g_debuglevel = 0;
		isc_log_setdebuglevel(named_g_lctx, named_g_debuglevel);
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NAMED_COMMAND_FLUSH)) {
		result = named_server_flushcache(named_g_server, lex);
	} else if (command_compare(command, NAMED_COMMAND_FLUSHNAME)) {
		result = named_server_flushnode(named_g_server, lex, ISC_FALSE);
	} else if (command_compare(command, NAMED_COMMAND_FLUSHTREE)) {
		result = named_server_flushnode(named_g_server, lex, ISC_TRUE);
	} else if (command_compare(command, NAMED_COMMAND_STATUS)) {
		result = named_server_status(named_g_server, text);
	} else if (command_compare(command, NAMED_COMMAND_TSIGLIST)) {
		result = named_server_tsiglist(named_g_server, text);
	} else if (command_compare(command, NAMED_COMMAND_TSIGDELETE)) {
		result = named_server_tsigdelete(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_FREEZE)) {
		result = named_server_freeze(named_g_server, ISC_TRUE, lex,
					     text);
	} else if (command_compare(command, NAMED_COMMAND_UNFREEZE) ||
		   command_compare(command, NAMED_COMMAND_THAW)) {
		result = named_server_freeze(named_g_server, ISC_FALSE, lex,
					     text);
	} else if (command_compare(command, NAMED_COMMAND_SCAN)) {
		result = ISC_R_SUCCESS;
		named_server_scan_interfaces(named_g_server);
	} else if (command_compare(command, NAMED_COMMAND_SYNC)) {
		result = named_server_sync(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_RECURSING)) {
		result = named_server_dumprecursing(named_g_server);
	} else if (command_compare(command, NAMED_COMMAND_TIMERPOKE)) {
		result = ISC_R_SUCCESS;
		isc_timermgr_poke(named_g_timermgr);
	} else if (command_compare(command, NAMED_COMMAND_NULL)) {
		result = ISC_R_SUCCESS;
	} else if (command_compare(command, NAMED_COMMAND_NOTIFY)) {
		result = named_server_notifycommand(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_VALIDATION)) {
		result = named_server_validation(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_SIGN) ||
		   command_compare(command, NAMED_COMMAND_LOADKEYS)) {
		result = named_server_rekey(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_ADDZONE) ||
		   command_compare(command, NAMED_COMMAND_MODZONE)) {
		result = named_server_changezone(named_g_server, cmdline, text);
	} else if (command_compare(command, NAMED_COMMAND_DELZONE)) {
		result = named_server_delzone(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_SHOWZONE)) {
		result = named_server_showzone(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_SIGNING)) {
		result = named_server_signing(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_ZONESTATUS)) {
		result = named_server_zonestatus(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_NTA)) {
		result = named_server_nta(named_g_server, lex, readonly, text);
	} else if (command_compare(command, NAMED_COMMAND_TESTGEN)) {
		result = named_server_testgen(lex, text);
	} else if (command_compare(command, NAMED_COMMAND_MKEYS)) {
		result = named_server_mkeys(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_DNSTAP) ||
		   command_compare(command, NAMED_COMMAND_DNSTAPREOPEN)) {
		result = named_server_dnstap(named_g_server, lex, text);
	} else if (command_compare(command, NAMED_COMMAND_TCPTIMEOUTS)) {
		result = named_server_tcptimeouts(lex, text);
	} else if (command_compare(command, NAMED_COMMAND_SERVESTALE)) {
		result = named_server_servestale(named_g_server, lex, text);
	} else {
		isc_log_write(named_g_lctx, NAMED_LOGCATEGORY_GENERAL,
			      NAMED_LOGMODULE_CONTROL, ISC_LOG_WARNING,
			      "unknown control channel command '%s'",
			      command);
		result = DNS_R_UNKNOWNCOMMAND;
	}

 cleanup:
	if (lex != NULL)
		isc_lex_destroy(&lex);

	return (result);
}
コード例 #14
0
ファイル: statschannel.c プロジェクト: w796933/bind99damp
isc_result_t
ns_statschannels_configure(ns_server_t *server, const cfg_obj_t *config,
			 cfg_aclconfctx_t *aclconfctx)
{
	ns_statschannel_t *listener, *listener_next;
	ns_statschannellist_t new_listeners;
	const cfg_obj_t *statschannellist = NULL;
	const cfg_listelt_t *element, *element2;
	char socktext[ISC_SOCKADDR_FORMATSIZE];

	RUNTIME_CHECK(isc_once_do(&once, init_desc) == ISC_R_SUCCESS);

	ISC_LIST_INIT(new_listeners);

	/*
	 * Get the list of named.conf 'statistics-channels' statements.
	 */
	(void)cfg_map_get(config, "statistics-channels", &statschannellist);

	/*
	 * Run through the new address/port list, noting sockets that are
	 * already being listened on and moving them to the new list.
	 *
	 * Identifying duplicate addr/port combinations is left to either
	 * the underlying config code, or to the bind attempt getting an
	 * address-in-use error.
	 */
	if (statschannellist != NULL) {
#ifndef HAVE_LIBXML2
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER, ISC_LOG_WARNING,
			      "statistics-channels specified but not effective "
			      "due to missing XML library");
#endif

		for (element = cfg_list_first(statschannellist);
		     element != NULL;
		     element = cfg_list_next(element)) {
			const cfg_obj_t *statschannel;
			const cfg_obj_t *listenercfg = NULL;

			statschannel = cfg_listelt_value(element);
			(void)cfg_map_get(statschannel, "inet",
					  &listenercfg);
			if (listenercfg == NULL)
				continue;

			for (element2 = cfg_list_first(listenercfg);
			     element2 != NULL;
			     element2 = cfg_list_next(element2)) {
				const cfg_obj_t *listen_params;
				const cfg_obj_t *obj;
				isc_sockaddr_t addr;

				listen_params = cfg_listelt_value(element2);

				obj = cfg_tuple_get(listen_params, "address");
				addr = *cfg_obj_assockaddr(obj);
				if (isc_sockaddr_getport(&addr) == 0)
					isc_sockaddr_setport(&addr, NS_STATSCHANNEL_HTTPPORT);

				isc_sockaddr_format(&addr, socktext,
						    sizeof(socktext));

				isc_log_write(ns_g_lctx,
					      NS_LOGCATEGORY_GENERAL,
					      NS_LOGMODULE_SERVER,
					      ISC_LOG_DEBUG(9),
					      "processing statistics "
					      "channel %s",
					      socktext);

				update_listener(server, &listener,
						listen_params, config, &addr,
						aclconfctx, socktext);

				if (listener != NULL) {
					/*
					 * Remove the listener from the old
					 * list, so it won't be shut down.
					 */
					ISC_LIST_UNLINK(server->statschannels,
							listener, link);
				} else {
					/*
					 * This is a new listener.
					 */
					isc_result_t r;

					r = add_listener(server, &listener,
							 listen_params, config,
							 &addr, aclconfctx,
							 socktext);
					if (r != ISC_R_SUCCESS) {
						cfg_obj_log(listen_params,
							    ns_g_lctx,
							    ISC_LOG_WARNING,
							    "couldn't allocate "
							    "statistics channel"
							    " %s: %s",
							    socktext,
							    isc_result_totext(r));
					}
				}

				if (listener != NULL)
					ISC_LIST_APPEND(new_listeners, listener,
							link);
			}
		}
	}

	for (listener = ISC_LIST_HEAD(server->statschannels);
	     listener != NULL;
	     listener = listener_next) {
		listener_next = ISC_LIST_NEXT(listener, link);
		ISC_LIST_UNLINK(server->statschannels, listener, link);
		shutdown_listener(listener);
	}

	ISC_LIST_APPENDLIST(server->statschannels, new_listeners, link);
	return (ISC_R_SUCCESS);
}
コード例 #15
0
ファイル: ifiter_ioctl.c プロジェクト: sambuc/netbsd
static isc_result_t
getbuf6(isc_interfaceiter_t *iter) {
	char strbuf[ISC_STRERRORSIZE];
	isc_result_t result;

	iter->bufsize6 = IFCONF_BUFSIZE_INITIAL;

	for (;;) {
		iter->buf6 = isc_mem_get(iter->mctx, iter->bufsize6);
		if (iter->buf6 == NULL)
			return (ISC_R_NOMEMORY);

		memset(&iter->lifc, 0, sizeof(iter->lifc));
#ifdef ISC_HAVE_LIFC_FAMILY
		iter->lifc.lifc_family = AF_INET6;
#endif
#ifdef ISC_HAVE_LIFC_FLAGS
		iter->lifc.lifc_flags = 0;
#endif
		iter->lifc.lifc_len = iter->bufsize6;
		iter->lifc.lifc_buf = iter->buf6;
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion".  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (isc_ioctl(iter->socket6, SIOCGLIFCONF, (char *)&iter->lifc)
		    == -1) {
#ifdef __hpux
			/*
			 * IPv6 interface scanning is not available on all
			 * kernels w/ IPv6 sockets.
			 */
			if (errno == ENOENT) {
				isc__strerror(errno, strbuf, sizeof(strbuf));
				isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
					      ISC_LOGMODULE_INTERFACE,
					      ISC_LOG_DEBUG(1),
					      isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_GETIFCONFIG,
							"get interface "
							"configuration: %s"),
					       strbuf);
				result = ISC_R_FAILURE;
				goto cleanup;
			}
#endif
			if (errno != EINVAL) {
				isc__strerror(errno, strbuf, sizeof(strbuf));
				UNEXPECTED_ERROR(__FILE__, __LINE__,
						 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_GETIFCONFIG,
							"get interface "
							"configuration: %s"),
						 strbuf);
				result = ISC_R_UNEXPECTED;
				goto cleanup;
			}
			/*
			 * EINVAL.  Retry with a bigger buffer.
			 */
		} else {
			/*
			 * The ioctl succeeded.
			 * Some OS's just return what will fit rather
			 * than set EINVAL if the buffer is too small
			 * to fit all the interfaces in.  If
			 * ifc.ifc_len is too near to the end of the
			 * buffer we will grow it just in case and
			 * retry.
			 */
			if (iter->lifc.lifc_len + 2 * sizeof(struct LIFREQ)
			    < iter->bufsize6)
				break;
		}
		if (iter->bufsize6 >= IFCONF_BUFSIZE_MAX) {
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_IFITERIOCTL,
							ISC_MSG_BUFFERMAX,
							"get interface "
							"configuration: "
							"maximum buffer "
							"size exceeded"));
			result = ISC_R_UNEXPECTED;
			goto cleanup;
		}
		isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);

		iter->bufsize6 *= 2;
	}

	if (iter->lifc.lifc_len != 0)
		iter->mode = 6;
	return (ISC_R_SUCCESS);

 cleanup:
	isc_mem_put(iter->mctx, iter->buf6, iter->bufsize6);
	iter->buf6 = NULL;
	return (result);
}
コード例 #16
0
static isc_result_t
odbc_process_rs(dns_sdlzlookup_t *lookup, dbinstance_t *dbi)
{


	isc_result_t result;
	SQLSMALLINT fields;
	SQLHSTMT  *stmnt;
	char *ttl_s;
	char *type;
	char *data;
	char *endp;
	int ttl;

	REQUIRE(dbi != NULL);

	stmnt = ((odbc_db_t *) (dbi->dbconn))->stmnt;

	/* get number of columns */
	if (!sqlOK(SQLNumResultCols(stmnt, &fields))) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
			      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
			      "Odbc driver unable to process result set");
		result = ISC_R_FAILURE;
		goto process_rs_cleanup;
	}

	/* get things ready for processing */
	result = ISC_R_FAILURE;

	while (sqlOK(SQLFetch(stmnt))) {

		/* set to null for next pass through */
		data = type = ttl_s = NULL;

		switch(fields) {
		case 1:
			/*
			 * one column in rs, it's the data field.  use
			 * default type of A record, and default TTL
			 * of 86400.  attempt to get data, & tell bind
			 * about it.
			 */
			if ((result = odbc_getField(stmnt, 1,
						    &data)) == ISC_R_SUCCESS) {
				result = dns_sdlz_putrr(lookup, "a",
							86400, data);
			}
			break;
		case 2:
			/*
			 * two columns, data field, and data type.
			 * use default TTL of 86400.  attempt to get
			 * DNS type & data, then tell bind about it.
			 */
			if ((result = odbc_getField(stmnt, 1,
						    &type)) == ISC_R_SUCCESS &&
			    (result = odbc_getField(stmnt, 2,
						    &data)) == ISC_R_SUCCESS) {
				result = dns_sdlz_putrr(lookup, type,
							86400, data);
			}
			break;
		default:
			/*
			 * 3 fields or more, concatenate the last ones
			 * together.  attempt to get DNS ttl, type,
			 * data then tell Bind about them.
			 */
			if ((result = odbc_getField(stmnt, 1, &ttl_s))
				== ISC_R_SUCCESS &&
			    (result = odbc_getField(stmnt, 2, &type))
				== ISC_R_SUCCESS &&
			    (result = odbc_getManyFields(stmnt, 3,
							 fields, &data))
				== ISC_R_SUCCESS) {
				/* try to convert ttl string to int */
				ttl = strtol(ttl_s, &endp, 10);
				/* failure converting ttl. */
				if (*endp != '\0' || ttl < 0) {
					isc_log_write(dns_lctx,
						      DNS_LOGCATEGORY_DATABASE,
						      DNS_LOGMODULE_DLZ,
						      ISC_LOG_ERROR,
						      "Odbc driver ttl must "
						      "be a postive number");
					result = ISC_R_FAILURE;
				} else {
					/*
					 * successful converting TTL,
					 * tell Bind everything
					 */
					result = dns_sdlz_putrr(lookup, type,
								ttl, data);
				}
			} /* closes bid if () */
		} /* closes switch(fields) */

		/* clean up mem */
		if (ttl_s != NULL)
			isc_mem_free(ns_g_mctx, ttl_s);
		if (type != NULL)
			isc_mem_free(ns_g_mctx, type);
		if (data != NULL)
			isc_mem_free(ns_g_mctx, data);

		/* I sure hope we were successful */
		if (result != ISC_R_SUCCESS) {
			isc_log_write(dns_lctx, DNS_LOGCATEGORY_DATABASE,
				      DNS_LOGMODULE_DLZ, ISC_LOG_ERROR,
				      "dns_sdlz_putrr returned error. "
				      "Error code was: %s",
				      isc_result_totext(result));
			result = ISC_R_FAILURE;
			goto process_rs_cleanup;
		}
	} /* closes while loop */

 process_rs_cleanup:

	/* close cursor */
	SQLCloseCursor(((odbc_db_t *) (dbi->dbconn))->stmnt);

#ifdef ISC_PLATFORM_USETHREADS

	/* free lock on dbi so someone else can use it. */
	isc_mutex_unlock(&dbi->instance_lock);

#endif

	return result;
}
コード例 #17
0
ファイル: ifiter_ioctl.c プロジェクト: sambuc/netbsd
static isc_result_t
internal_current4(isc_interfaceiter_t *iter) {
	struct ifreq *ifrp;
	struct ifreq ifreq;
	int family;
	char strbuf[ISC_STRERRORSIZE];
#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
	struct lifreq lifreq;
#else
	char sabuf[256];
#endif
	int i, bits, prefixlen;

	REQUIRE(VALID_IFITER(iter));

	if (iter->ifc.ifc_len == 0 ||
	    iter->pos == (unsigned int)iter->ifc.ifc_len) {
#ifdef __linux
		return (linux_if_inet6_current(iter));
#else
		return (ISC_R_NOMORE);
#endif
	}

	INSIST( iter->pos < (unsigned int) iter->ifc.ifc_len);

	ifrp = (void *)((char *) iter->ifc.ifc_req + iter->pos);

	memset(&ifreq, 0, sizeof(ifreq));
	memcpy(&ifreq, ifrp, sizeof(ifreq));

	family = ifreq.ifr_addr.sa_family;
#if defined(ISC_PLATFORM_HAVEIPV6)
	if (family != AF_INET && family != AF_INET6)
#else
	if (family != AF_INET)
#endif
		return (ISC_R_IGNORE);

	memset(&iter->current, 0, sizeof(iter->current));
	iter->current.af = family;

	INSIST(sizeof(ifreq.ifr_name) <= sizeof(iter->current.name));
	memset(iter->current.name, 0, sizeof(iter->current.name));
	memcpy(iter->current.name, ifreq.ifr_name, sizeof(ifreq.ifr_name));

	get_addr(family, &iter->current.address,
		 (struct sockaddr *)&ifrp->ifr_addr, ifreq.ifr_name);

	/*
	 * If the interface does not have a address ignore it.
	 */
	switch (family) {
	case AF_INET:
		if (iter->current.address.type.in.s_addr == htonl(INADDR_ANY))
			return (ISC_R_IGNORE);
		break;
	case AF_INET6:
		if (memcmp(&iter->current.address.type.in6, &in6addr_any,
			   sizeof(in6addr_any)) == 0)
			return (ISC_R_IGNORE);
		break;
	}

	/*
	 * Get interface flags.
	 */

	iter->current.flags = 0;

	/*
	 * Ignore the HP/UX warning about "integer overflow during
	 * conversion.  It comes from its own macro definition,
	 * and is really hard to shut up.
	 */
	if (isc_ioctl(iter->socket, SIOCGIFFLAGS, (char *) &ifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "%s: getting interface flags: %s",
				 ifreq.ifr_name, strbuf);
		return (ISC_R_IGNORE);
	}

	if ((ifreq.ifr_flags & IFF_UP) != 0)
		iter->current.flags |= INTERFACE_F_UP;

#ifdef IFF_POINTOPOINT
	if ((ifreq.ifr_flags & IFF_POINTOPOINT) != 0)
		iter->current.flags |= INTERFACE_F_POINTTOPOINT;
#endif

	if ((ifreq.ifr_flags & IFF_LOOPBACK) != 0)
		iter->current.flags |= INTERFACE_F_LOOPBACK;

	if ((ifreq.ifr_flags & IFF_BROADCAST) != 0)
		iter->current.flags |= INTERFACE_F_BROADCAST;

#ifdef IFF_MULTICAST
	if ((ifreq.ifr_flags & IFF_MULTICAST) != 0)
		iter->current.flags |= INTERFACE_F_MULTICAST;
#endif

	if (family == AF_INET)
		goto inet;

#if !defined(ISC_PLATFORM_HAVEIF_LADDRREQ) && defined(SIOCGLIFADDR)
	memset(&lifreq, 0, sizeof(lifreq));
	memcpy(lifreq.lifr_name, iter->current.name, sizeof(lifreq.lifr_name));
	memcpy(&lifreq.lifr_addr, &iter->current.address.type.in6,
	       sizeof(iter->current.address.type.in6));

	if (isc_ioctl(iter->socket, SIOCGLIFADDR, &lifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "%s: getting interface address: %s",
				 ifreq.ifr_name, strbuf);
		return (ISC_R_IGNORE);
	}
	prefixlen = lifreq.lifr_addrlen;
#else
	isc_netaddr_format(&iter->current.address, sabuf, sizeof(sabuf));
	isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
		      ISC_LOGMODULE_INTERFACE,
		      ISC_LOG_INFO,
		      isc_msgcat_get(isc_msgcat,
				     ISC_MSGSET_IFITERIOCTL,
				     ISC_MSG_GETIFCONFIG,
				     "prefix length for %s is unknown "
				     "(assume 128)"), sabuf);
	prefixlen = 128;
#endif

	/*
	 * Netmask already zeroed.
	 */
	iter->current.netmask.family = family;
	for (i = 0; i < 16; i++) {
		if (prefixlen > 8) {
			bits = 0;
			prefixlen -= 8;
		} else {
			bits = 8 - prefixlen;
			prefixlen = 0;
		}
		iter->current.netmask.type.in6.s6_addr[i] = (~0 << bits) & 0xff;
	}
#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
	iter->current.ifindex = if_nametoindex(iter->current.name);
#endif
	return (ISC_R_SUCCESS);

 inet:
	if (family != AF_INET)
		return (ISC_R_IGNORE);
#ifdef IFF_POINTOPOINT
	/*
	 * If the interface is point-to-point, get the destination address.
	 */
	if ((iter->current.flags & INTERFACE_F_POINTTOPOINT) != 0) {
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion.  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (isc_ioctl(iter->socket, SIOCGIFDSTADDR, (char *)&ifreq)
		    < 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
				isc_msgcat_get(isc_msgcat,
					       ISC_MSGSET_IFITERIOCTL,
					       ISC_MSG_GETDESTADDR,
					       "%s: getting "
					       "destination address: %s"),
					 ifreq.ifr_name, strbuf);
			return (ISC_R_IGNORE);
		}
		get_addr(family, &iter->current.dstaddress,
			 (struct sockaddr *)&ifreq.ifr_dstaddr, ifreq.ifr_name);
	}
#endif

	if ((iter->current.flags & INTERFACE_F_BROADCAST) != 0) {
		/*
		 * Ignore the HP/UX warning about "integer overflow during
		 * conversion.  It comes from its own macro definition,
		 * and is really hard to shut up.
		 */
		if (isc_ioctl(iter->socket, SIOCGIFBRDADDR, (char *)&ifreq)
		    < 0) {
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
				isc_msgcat_get(isc_msgcat,
					       ISC_MSGSET_IFITERIOCTL,
					       ISC_MSG_GETBCSTADDR,
					       "%s: getting "
					       "broadcast address: %s"),
					 ifreq.ifr_name, strbuf);
			return (ISC_R_IGNORE);
		}
		get_addr(family, &iter->current.broadcast,
			 (struct sockaddr *)&ifreq.ifr_broadaddr, ifreq.ifr_name);
	}

	/*
	 * Get the network mask.
	 */
	memset(&ifreq, 0, sizeof(ifreq));
	memcpy(&ifreq, ifrp, sizeof(ifreq));
	/*
	 * Ignore the HP/UX warning about "integer overflow during
	 * conversion.  It comes from its own macro definition,
	 * and is really hard to shut up.
	 */
	if (isc_ioctl(iter->socket, SIOCGIFNETMASK, (char *)&ifreq) < 0) {
		isc__strerror(errno, strbuf, sizeof(strbuf));
		UNEXPECTED_ERROR(__FILE__, __LINE__,
			isc_msgcat_get(isc_msgcat,
				       ISC_MSGSET_IFITERIOCTL,
				       ISC_MSG_GETNETMASK,
				       "%s: getting netmask: %s"),
				       ifreq.ifr_name, strbuf);
		return (ISC_R_IGNORE);
	}
	get_addr(family, &iter->current.netmask,
		 (struct sockaddr *)&ifreq.ifr_addr, ifreq.ifr_name);
#ifdef ISC_PLATFORM_HAVEIFNAMETOINDEX
	iter->current.ifindex = if_nametoindex(iter->current.name);
#endif
	return (ISC_R_SUCCESS);
}
コード例 #18
0
ファイル: net.c プロジェクト: VargMon/netbsd-cvs-mirror
static isc_result_t
try_proto(int domain) {
	int s;
	isc_result_t result = ISC_R_SUCCESS;
	char strbuf[ISC_STRERRORSIZE];

	s = socket(domain, SOCK_STREAM, 0);
	if (s == -1) {
		switch (errno) {
#ifdef EAFNOSUPPORT
		case EAFNOSUPPORT:
#endif
#ifdef EPROTONOSUPPORT
		case EPROTONOSUPPORT:
#endif
#ifdef EINVAL
		case EINVAL:
#endif
			return (ISC_R_NOTFOUND);
		default:
			isc__strerror(errno, strbuf, sizeof(strbuf));
			UNEXPECTED_ERROR(__FILE__, __LINE__,
					 "socket() %s: %s",
					 isc_msgcat_get(isc_msgcat,
							ISC_MSGSET_GENERAL,
							ISC_MSG_FAILED,
							"failed"),
					 strbuf);
			return (ISC_R_UNEXPECTED);
		}
	}

#ifdef ISC_PLATFORM_HAVEIPV6
#ifdef WANT_IPV6
#ifdef ISC_PLATFORM_HAVEIN6PKTINFO
	if (domain == PF_INET6) {
		struct sockaddr_in6 sin6;
		GETSOCKNAME_SOCKLEN_TYPE len;	/* NTP local change */

		/*
		 * Check to see if IPv6 is broken, as is common on Linux.
		 */
		len = sizeof(sin6);
		if (getsockname(s, (struct sockaddr *)&sin6, &len) < 0)
		{
			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
				      "retrieving the address of an IPv6 "
				      "socket from the kernel failed.");
			isc_log_write(isc_lctx, ISC_LOGCATEGORY_GENERAL,
				      ISC_LOGMODULE_SOCKET, ISC_LOG_ERROR,
				      "IPv6 is not supported.");
			result = ISC_R_NOTFOUND;
		} else {
			if (len == sizeof(struct sockaddr_in6))
				result = ISC_R_SUCCESS;
			else {
				isc_log_write(isc_lctx,
					      ISC_LOGCATEGORY_GENERAL,
					      ISC_LOGMODULE_SOCKET,
					      ISC_LOG_ERROR,
					      "IPv6 structures in kernel and "
					      "user space do not match.");
				isc_log_write(isc_lctx,
					      ISC_LOGCATEGORY_GENERAL,
					      ISC_LOGMODULE_SOCKET,
					      ISC_LOG_ERROR,
					      "IPv6 is not supported.");
				result = ISC_R_NOTFOUND;
			}
		}
	}
#endif
#endif
#endif

	(void)close(s);

	return (result);
}
コード例 #19
0
ファイル: dst_parse.c プロジェクト: VargMon/netbsd-cvs-mirror
isc_result_t
dst__privstruct_writefile(const dst_key_t *key, const dst_private_t *priv,
			  const char *directory)
{
	FILE *fp;
	isc_result_t result;
	char filename[ISC_DIR_NAMEMAX];
	char buffer[MAXFIELDSIZE * 2];
	isc_fsaccess_t access;
	isc_stdtime_t when;
	isc_uint32_t value;
	isc_buffer_t b;
	isc_region_t r;
	int major, minor;
	mode_t mode;
	int i, ret;

	REQUIRE(priv != NULL);

	ret = check_data(priv, dst_key_alg(key), ISC_FALSE, key->external);
	if (ret < 0)
		return (DST_R_INVALIDPRIVATEKEY);
	else if (ret != ISC_R_SUCCESS)
		return (ret);

	isc_buffer_init(&b, filename, sizeof(filename));
	result = dst_key_buildfilename(key, DST_TYPE_PRIVATE, directory, &b);
	if (result != ISC_R_SUCCESS)
		return (result);

	result = isc_file_mode(filename, &mode);
	if (result == ISC_R_SUCCESS && mode != 0600) {
		/* File exists; warn that we are changing its permissions */
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
			      DNS_LOGMODULE_DNSSEC, ISC_LOG_WARNING,
			      "Permissions on the file %s "
			      "have changed from 0%o to 0600 as "
			      "a result of this operation.",
			      filename, (unsigned int)mode);
	}

	if ((fp = fopen(filename, "w")) == NULL)
		return (DST_R_WRITEERROR);

	access = 0;
	isc_fsaccess_add(ISC_FSACCESS_OWNER,
			 ISC_FSACCESS_READ | ISC_FSACCESS_WRITE,
			 &access);
	(void)isc_fsaccess_set(filename, access);

	dst_key_getprivateformat(key, &major, &minor);
	if (major == 0 && minor == 0) {
		major = DST_MAJOR_VERSION;
		minor = DST_MINOR_VERSION;
	}

	/* XXXDCL return value should be checked for full filesystem */
	fprintf(fp, "%s v%d.%d\n", PRIVATE_KEY_STR, major, minor);

	fprintf(fp, "%s %d ", ALGORITHM_STR, dst_key_alg(key));

	/* XXXVIX this switch statement is too sparse to gen a jump table. */
	switch (dst_key_alg(key)) {
	case DST_ALG_RSAMD5:
		fprintf(fp, "(RSA)\n");
		break;
	case DST_ALG_DH:
		fprintf(fp, "(DH)\n");
		break;
	case DST_ALG_DSA:
		fprintf(fp, "(DSA)\n");
		break;
	case DST_ALG_RSASHA1:
		fprintf(fp, "(RSASHA1)\n");
		break;
	case DST_ALG_NSEC3RSASHA1:
		fprintf(fp, "(NSEC3RSASHA1)\n");
		break;
	case DST_ALG_NSEC3DSA:
		fprintf(fp, "(NSEC3DSA)\n");
		break;
	case DST_ALG_RSASHA256:
		fprintf(fp, "(RSASHA256)\n");
		break;
	case DST_ALG_RSASHA512:
		fprintf(fp, "(RSASHA512)\n");
		break;
	case DST_ALG_ECCGOST:
		fprintf(fp, "(ECC-GOST)\n");
		break;
	case DST_ALG_ECDSA256:
		fprintf(fp, "(ECDSAP256SHA256)\n");
		break;
	case DST_ALG_ECDSA384:
		fprintf(fp, "(ECDSAP384SHA384)\n");
		break;
	case DST_ALG_HMACMD5:
		fprintf(fp, "(HMAC_MD5)\n");
		break;
	case DST_ALG_HMACSHA1:
		fprintf(fp, "(HMAC_SHA1)\n");
		break;
	case DST_ALG_HMACSHA224:
		fprintf(fp, "(HMAC_SHA224)\n");
		break;
	case DST_ALG_HMACSHA256:
		fprintf(fp, "(HMAC_SHA256)\n");
		break;
	case DST_ALG_HMACSHA384:
		fprintf(fp, "(HMAC_SHA384)\n");
		break;
	case DST_ALG_HMACSHA512:
		fprintf(fp, "(HMAC_SHA512)\n");
		break;
	default:
		fprintf(fp, "(?)\n");
		break;
	}

	for (i = 0; i < priv->nelements; i++) {
		const char *s;

		s = find_tag(priv->elements[i].tag);

		r.base = priv->elements[i].data;
		r.length = priv->elements[i].length;
		isc_buffer_init(&b, buffer, sizeof(buffer));
		result = isc_base64_totext(&r, sizeof(buffer), "", &b);
		if (result != ISC_R_SUCCESS) {
			fclose(fp);
			return (DST_R_INVALIDPRIVATEKEY);
		}
		isc_buffer_usedregion(&b, &r);

	       fprintf(fp, "%s %.*s\n", s, (int)r.length, r.base);
	}

	if (key->external)
	       fprintf(fp, "External:\n");

	/* Add the metadata tags */
	if (major > 1 || (major == 1 && minor >= 3)) {
		for (i = 0; i < NUMERIC_NTAGS; i++) {
			result = dst_key_getnum(key, i, &value);
			if (result != ISC_R_SUCCESS)
				continue;
			fprintf(fp, "%s %u\n", numerictags[i], value);
		}
		for (i = 0; i < TIMING_NTAGS; i++) {
			result = dst_key_gettime(key, i, &when);
			if (result != ISC_R_SUCCESS)
				continue;

			isc_buffer_init(&b, buffer, sizeof(buffer));
			result = dns_time32_totext(when, &b);
		       if (result != ISC_R_SUCCESS) {
			       fclose(fp);
			       return (DST_R_INVALIDPRIVATEKEY);
		       }

			isc_buffer_usedregion(&b, &r);

		       fprintf(fp, "%s %.*s\n", timetags[i], (int)r.length,
				r.base);
		}
	}

	fflush(fp);
	result = ferror(fp) ? DST_R_WRITEERROR : ISC_R_SUCCESS;
	fclose(fp);
	return (result);
}
コード例 #20
0
static isc_result_t
ns_interface_create(ns_interfacemgr_t *mgr, isc_sockaddr_t *addr,
		    const char *name, ns_interface_t **ifpret)
{
	ns_interface_t *ifp;
	isc_result_t result;
	int disp;

	REQUIRE(NS_INTERFACEMGR_VALID(mgr));

	ifp = isc_mem_get(mgr->mctx, sizeof(*ifp));
	if (ifp == NULL)
		return (ISC_R_NOMEMORY);

	ifp->mgr = NULL;
	ifp->generation = mgr->generation;
	ifp->addr = *addr;
	ifp->flags = 0;
	strlcpy(ifp->name, name, sizeof(ifp->name));
	ifp->clientmgr = NULL;

	result = isc_mutex_init(&ifp->lock);
	if (result != ISC_R_SUCCESS)
		goto lock_create_failure;

	result = ns_clientmgr_create(mgr->mctx, mgr->taskmgr,
				     ns_g_timermgr,
				     &ifp->clientmgr);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
			      "ns_clientmgr_create() failed: %s",
			      isc_result_totext(result));
		goto clientmgr_create_failure;
	}

	for (disp = 0; disp < MAX_UDP_DISPATCH; disp++)
		ifp->udpdispatch[disp] = NULL;

	ifp->tcpsocket = NULL;

	/*
	 * Create a single TCP client object.  It will replace itself
	 * with a new one as soon as it gets a connection, so the actual
	 * connections will be handled in parallel even though there is
	 * only one client initially.
	 */
	ifp->ntcptarget = 1;
	ifp->ntcpcurrent = 0;
	ifp->nudpdispatch = 0;

	ifp->dscp = -1;

	ISC_LINK_INIT(ifp, link);

	ns_interfacemgr_attach(mgr, &ifp->mgr);
	ISC_LIST_APPEND(mgr->interfaces, ifp, link);

	ifp->references = 1;
	ifp->magic = IFACE_MAGIC;
	*ifpret = ifp;

	return (ISC_R_SUCCESS);

 clientmgr_create_failure:
	DESTROYLOCK(&ifp->lock);

 lock_create_failure:
	ifp->magic = 0;
	isc_mem_put(mgr->mctx, ifp, sizeof(*ifp));

	return (ISC_R_UNEXPECTED);
}
コード例 #21
0
ファイル: rootns.c プロジェクト: enukane/netbsd-src
isc_result_t
dns_rootns_create(isc_mem_t *mctx, dns_rdataclass_t rdclass,
		  const char *filename, dns_db_t **target)
{
	isc_result_t result, eresult;
	isc_buffer_t source;
	unsigned int len;
	dns_rdatacallbacks_t callbacks;
	dns_db_t *db = NULL;

	REQUIRE(target != NULL && *target == NULL);

	result = dns_db_create(mctx, "rbt", dns_rootname, dns_dbtype_zone,
			       rdclass, 0, NULL, &db);
	if (result != ISC_R_SUCCESS)
		return (result);

	len = strlen(root_ns);
	isc_buffer_init(&source, root_ns, len);
	isc_buffer_add(&source, len);

	dns_rdatacallbacks_init(&callbacks);
	result = dns_db_beginload(db, &callbacks);
	if (result != ISC_R_SUCCESS)
		return (result);
	if (filename != NULL) {
		/*
		 * Load the hints from the specified filename.
		 */
		result = dns_master_loadfile(filename, &db->origin,
					     &db->origin, db->rdclass,
					     DNS_MASTER_HINT,
					     &callbacks, db->mctx);
	} else if (rdclass == dns_rdataclass_in) {
		/*
		 * Default to using the Internet root servers.
		 */
		result = dns_master_loadbuffer(&source, &db->origin,
					       &db->origin, db->rdclass,
					       DNS_MASTER_HINT,
					       &callbacks, db->mctx);
	} else
		result = ISC_R_NOTFOUND;
	eresult = dns_db_endload(db, &callbacks);
	if (result == ISC_R_SUCCESS || result == DNS_R_SEENINCLUDE)
		result = eresult;
	if (result != ISC_R_SUCCESS && result != DNS_R_SEENINCLUDE)
		goto db_detach;
	if (check_hints(db) != ISC_R_SUCCESS)
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
			      DNS_LOGMODULE_HINTS, ISC_LOG_WARNING,
			      "extra data in root hints '%s'",
			      (filename != NULL) ? filename : "<BUILT-IN>");
	*target = db;
	return (ISC_R_SUCCESS);

 db_detach:
	dns_db_detach(&db);

	return (result);
}
コード例 #22
0
static isc_result_t
ns_interface_listenudp(ns_interface_t *ifp) {
	isc_result_t result;
	unsigned int attrs;
	unsigned int attrmask;
	int disp, i;

	attrs = 0;
	attrs |= DNS_DISPATCHATTR_UDP;
	if (isc_sockaddr_pf(&ifp->addr) == AF_INET)
		attrs |= DNS_DISPATCHATTR_IPV4;
	else
		attrs |= DNS_DISPATCHATTR_IPV6;
	attrs |= DNS_DISPATCHATTR_NOLISTEN;
	attrmask = 0;
	attrmask |= DNS_DISPATCHATTR_UDP | DNS_DISPATCHATTR_TCP;
	attrmask |= DNS_DISPATCHATTR_IPV4 | DNS_DISPATCHATTR_IPV6;

	ifp->nudpdispatch = ISC_MIN(ns_g_udpdisp, MAX_UDP_DISPATCH);
	for (disp = 0; disp < ifp->nudpdispatch; disp++) {
		result = dns_dispatch_getudp_dup(ifp->mgr->dispatchmgr,
						 ns_g_socketmgr,
						 ns_g_taskmgr, &ifp->addr,
						 4096, UDPBUFFERS,
						 32768, 8219, 8237,
						 attrs, attrmask,
						 &ifp->udpdispatch[disp],
						 disp == 0
						    ? NULL
						    : ifp->udpdispatch[0]);
		if (result != ISC_R_SUCCESS) {
			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				      "could not listen on UDP socket: %s",
				      isc_result_totext(result));
			goto udp_dispatch_failure;
		}

	}

	result = ns_clientmgr_createclients(ifp->clientmgr, ifp->nudpdispatch,
					    ifp, ISC_FALSE);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "UDP ns_clientmgr_createclients(): %s",
				 isc_result_totext(result));
		goto addtodispatch_failure;
	}

	return (ISC_R_SUCCESS);

 addtodispatch_failure:
	for (i = disp - 1; i >= 0; i--) {
		dns_dispatch_changeattributes(ifp->udpdispatch[i], 0,
					      DNS_DISPATCHATTR_NOLISTEN);
		dns_dispatch_detach(&(ifp->udpdispatch[i]));
	}
	ifp->nudpdispatch = 0;

 udp_dispatch_failure:
	return (result);
}
コード例 #23
0
ファイル: diff.c プロジェクト: 274914765/C
static isc_result_t diff_apply (dns_diff_t * diff, dns_db_t * db, dns_dbversion_t * ver, isc_boolean_t warn)
{
    dns_difftuple_t *t;

    dns_dbnode_t *node = NULL;

    isc_result_t result;

    char namebuf[DNS_NAME_FORMATSIZE];

    char typebuf[DNS_RDATATYPE_FORMATSIZE];

    char classbuf[DNS_RDATACLASS_FORMATSIZE];

    REQUIRE (DNS_DIFF_VALID (diff));
    REQUIRE (DNS_DB_VALID (db));

    t = ISC_LIST_HEAD (diff->tuples);
    while (t != NULL)
    {
        dns_name_t *name;

        INSIST (node == NULL);
        name = &t->name;
        /*
         * Find the node.
         * We create the node if it does not exist.
         * This will cause an empty node to be created if the diff
         * contains a deletion of an RR at a nonexistent name,
         * but such diffs should never be created in the first
         * place.
         */

        while (t != NULL && dns_name_equal (&t->name, name))
        {
            dns_rdatatype_t type, covers;

            dns_diffop_t op;

            dns_rdatalist_t rdl;

            dns_rdataset_t rds;

            dns_rdataset_t ardataset;

            dns_rdataset_t *modified = NULL;

            op = t->op;
            type = t->rdata.type;
            covers = rdata_covers (&t->rdata);

            /*
             * Collect a contiguous set of updates with
             * the same operation (add/delete) and RR type
             * into a single rdatalist so that the
             * database rrset merging/subtraction code
             * can work more efficiently than if each
             * RR were merged into / subtracted from
             * the database separately.
             *
             * This is done by linking rdata structures from the
             * diff into "rdatalist".  This uses the rdata link
             * field, not the diff link field, so the structure
             * of the diff itself is not affected.
             */

            rdl.type = type;
            rdl.covers = covers;
            rdl.rdclass = t->rdata.rdclass;
            rdl.ttl = t->ttl;
            ISC_LIST_INIT (rdl.rdata);
            ISC_LINK_INIT (&rdl, link);

            node = NULL;
            if (type != dns_rdatatype_nsec3 && covers != dns_rdatatype_nsec3)
                CHECK (dns_db_findnode (db, name, ISC_TRUE, &node));
            else
                CHECK (dns_db_findnsec3node (db, name, ISC_TRUE, &node));

            while (t != NULL &&
                   dns_name_equal (&t->name, name) &&
                   t->op == op && t->rdata.type == type && rdata_covers (&t->rdata) == covers)
            {
                dns_name_format (name, namebuf, sizeof (namebuf));
                dns_rdatatype_format (t->rdata.type, typebuf, sizeof (typebuf));
                dns_rdataclass_format (t->rdata.rdclass, classbuf, sizeof (classbuf));
                if (t->ttl != rdl.ttl && warn)
                    isc_log_write (DIFF_COMMON_LOGARGS,
                                   ISC_LOG_WARNING,
                                   "'%s/%s/%s': TTL differs in "
                                   "rdataset, adjusting "
                                   "%lu -> %lu",
                                   namebuf, typebuf, classbuf, (unsigned long) t->ttl, (unsigned long) rdl.ttl);
                ISC_LIST_APPEND (rdl.rdata, &t->rdata, link);
                t = ISC_LIST_NEXT (t, link);
            }

            /*
             * Convert the rdatalist into a rdataset.
             */
            dns_rdataset_init (&rds);
            CHECK (dns_rdatalist_tordataset (&rdl, &rds));
            if (rds.type == dns_rdatatype_rrsig)
                switch (op)
                {
                    case DNS_DIFFOP_ADDRESIGN:
                    case DNS_DIFFOP_DELRESIGN:
                        modified = &ardataset;
                        dns_rdataset_init (modified);
                        break;
                    default:
                        break;
                }
            rds.trust = dns_trust_ultimate;

            /*
             * Merge the rdataset into the database.
             */
            switch (op)
            {
                case DNS_DIFFOP_ADD:
                case DNS_DIFFOP_ADDRESIGN:
                    result = dns_db_addrdataset (db, node, ver,
                                                 0, &rds,
                                                 DNS_DBADD_MERGE | DNS_DBADD_EXACT | DNS_DBADD_EXACTTTL, modified);
                    break;
                case DNS_DIFFOP_DEL:
                case DNS_DIFFOP_DELRESIGN:
                    result = dns_db_subtractrdataset (db, node, ver, &rds, DNS_DBSUB_EXACT, modified);
                    break;
                default:
                    INSIST (0);
            }

            if (result == ISC_R_SUCCESS)
            {
                if (modified != NULL)
                {
                    isc_stdtime_t resign;

                    resign = setresign (modified, diff->resign);
                    dns_db_setsigningtime (db, modified, resign);
                    if (diff->resign == 0 && (op == DNS_DIFFOP_ADDRESIGN || op == DNS_DIFFOP_DELRESIGN))
                        isc_log_write (DIFF_COMMON_LOGARGS,
                                       ISC_LOG_WARNING, "resign requested " "with 0 resign " "interval");
                }
            }
            else if (result == DNS_R_UNCHANGED)
            {
                /*
                 * This will not happen when executing a
                 * dynamic update, because that code will
                 * generate strictly minimal diffs.
                 * It may happen when receiving an IXFR
                 * from a server that is not as careful.
                 * Issue a warning and continue.
                 */
                if (warn)
                {
                    char classbuf[DNS_RDATATYPE_FORMATSIZE];

                    char namebuf[DNS_NAME_FORMATSIZE];

                    dns_name_format (dns_db_origin (db), namebuf, sizeof (namebuf));
                    dns_rdataclass_format (dns_db_class (db), classbuf, sizeof (classbuf));
                    isc_log_write (DIFF_COMMON_LOGARGS,
                                   ISC_LOG_WARNING,
                                   "%s/%s: dns_diff_apply: " "update with no effect", namebuf, classbuf);
                }
            }
            else if (result == DNS_R_NXRRSET)
            {
                /*
                 * OK.
                 */
            }
            else
            {
                if (modified != NULL && dns_rdataset_isassociated (modified))
                    dns_rdataset_disassociate (modified);
                CHECK (result);
            }
            dns_db_detachnode (db, &node);
            if (modified != NULL && dns_rdataset_isassociated (modified))
                dns_rdataset_disassociate (modified);
        }
    }
    return (ISC_R_SUCCESS);

  failure:
    if (node != NULL)
        dns_db_detachnode (db, &node);
    return (result);
}
コード例 #24
0
static isc_result_t
ns_interface_accepttcp(ns_interface_t *ifp) {
	isc_result_t result;

	/*
	 * Open a TCP socket.
	 */
	result = isc_socket_create(ifp->mgr->socketmgr,
				   isc_sockaddr_pf(&ifp->addr),
				   isc_sockettype_tcp,
				   &ifp->tcpsocket);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				 "creating TCP socket: %s",
				 isc_result_totext(result));
		goto tcp_socket_failure;
	}
	isc_socket_setname(ifp->tcpsocket, "dispatcher", NULL);
#ifndef ISC_ALLOW_MAPPED
	isc_socket_ipv6only(ifp->tcpsocket, ISC_TRUE);
#endif
	result = isc_socket_bind(ifp->tcpsocket, &ifp->addr,
				 ISC_SOCKET_REUSEADDRESS);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				 "binding TCP socket: %s",
				 isc_result_totext(result));
		goto tcp_bind_failure;
	}

	if (ifp->dscp != -1)
		isc_socket_dscp(ifp->tcpsocket, ifp->dscp);

	result = isc_socket_listen(ifp->tcpsocket, ns_g_listen);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				 "listening on TCP socket: %s",
				 isc_result_totext(result));
		goto tcp_listen_failure;
	}

	/*
	 * If/when there a multiple filters listen to the
	 * result.
	 */
	(void)isc_socket_filter(ifp->tcpsocket, "dataready");

	result = ns_clientmgr_createclients(ifp->clientmgr,
					    ifp->ntcptarget, ifp,
					    ISC_TRUE);
	if (result != ISC_R_SUCCESS) {
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "TCP ns_clientmgr_createclients(): %s",
				 isc_result_totext(result));
		goto accepttcp_failure;
	}
	return (ISC_R_SUCCESS);

 accepttcp_failure:
 tcp_listen_failure:
 tcp_bind_failure:
	isc_socket_detach(&ifp->tcpsocket);
 tcp_socket_failure:
	return (ISC_R_SUCCESS);
}
コード例 #25
0
ファイル: diff.c プロジェクト: 274914765/C
isc_result_t dns_diff_print (dns_diff_t * diff, FILE * file)
{
    isc_result_t result;

    dns_difftuple_t *t;

    char *mem = NULL;

    unsigned int size = 2048;

    const char *op = NULL;

    REQUIRE (DNS_DIFF_VALID (diff));

    mem = isc_mem_get (diff->mctx, size);
    if (mem == NULL)
        return (ISC_R_NOMEMORY);

    for (t = ISC_LIST_HEAD (diff->tuples); t != NULL; t = ISC_LIST_NEXT (t, link))
    {
        isc_buffer_t buf;

        isc_region_t r;

        dns_rdatalist_t rdl;

        dns_rdataset_t rds;

        dns_rdata_t rd = DNS_RDATA_INIT;

        result = diff_tuple_tordataset (t, &rd, &rdl, &rds);
        if (result != ISC_R_SUCCESS)
        {
            UNEXPECTED_ERROR (__FILE__, __LINE__, "diff_tuple_tordataset failed: %s", dns_result_totext (result));
            result = ISC_R_UNEXPECTED;
            goto cleanup;
        }
      again:
        isc_buffer_init (&buf, mem, size);
        result = dns_rdataset_totext (&rds, &t->name, ISC_FALSE, ISC_FALSE, &buf);

        if (result == ISC_R_NOSPACE)
        {
            isc_mem_put (diff->mctx, mem, size);
            size += 1024;
            mem = isc_mem_get (diff->mctx, size);
            if (mem == NULL)
            {
                result = ISC_R_NOMEMORY;
                goto cleanup;
            }
            goto again;
        }

        if (result != ISC_R_SUCCESS)
            goto cleanup;
        /*
         * Get rid of final newline.
         */
        INSIST (buf.used >= 1 && ((char *) buf.base)[buf.used - 1] == '\n');
        buf.used--;

        isc_buffer_usedregion (&buf, &r);
        switch (t->op)
        {
            case DNS_DIFFOP_EXISTS:
                op = "exists";
                break;
            case DNS_DIFFOP_ADD:
                op = "add";
                break;
            case DNS_DIFFOP_DEL:
                op = "del";
                break;
            case DNS_DIFFOP_ADDRESIGN:
                op = "add re-sign";
                break;
            case DNS_DIFFOP_DELRESIGN:
                op = "del re-sign";
                break;
        }
        if (file != NULL)
            fprintf (file, "%s %.*s\n", op, (int) r.length, (char *) r.base);
        else
            isc_log_write (DIFF_COMMON_LOGARGS, ISC_LOG_DEBUG (7), "%s %.*s", op, (int) r.length, (char *) r.base);
    }
    result = ISC_R_SUCCESS;
  cleanup:
    if (mem != NULL)
        isc_mem_put (diff->mctx, mem, size);
    return (result);
}
コード例 #26
0
static isc_result_t
do_scan(ns_interfacemgr_t *mgr, ns_listenlist_t *ext_listen,
	isc_boolean_t verbose)
{
	isc_interfaceiter_t *iter = NULL;
	isc_boolean_t scan_ipv4 = ISC_FALSE;
	isc_boolean_t scan_ipv6 = ISC_FALSE;
	isc_boolean_t adjusting = ISC_FALSE;
	isc_boolean_t ipv6only = ISC_TRUE;
	isc_boolean_t ipv6pktinfo = ISC_TRUE;
	isc_result_t result;
	isc_netaddr_t zero_address, zero_address6;
	ns_listenelt_t *le;
	isc_sockaddr_t listen_addr;
	ns_interface_t *ifp;
	isc_boolean_t log_explicit = ISC_FALSE;
	isc_boolean_t dolistenon;
	char sabuf[ISC_SOCKADDR_FORMATSIZE];

	if (ext_listen != NULL)
		adjusting = ISC_TRUE;

	if (isc_net_probeipv6() == ISC_R_SUCCESS)
		scan_ipv6 = ISC_TRUE;
#ifdef WANT_IPV6
	else if (!ns_g_disable6)
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
			      "no IPv6 interfaces found");
#endif

	if (isc_net_probeipv4() == ISC_R_SUCCESS)
		scan_ipv4 = ISC_TRUE;
	else if (!ns_g_disable4)
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      verbose ? ISC_LOG_INFO : ISC_LOG_DEBUG(1),
			      "no IPv4 interfaces found");

	/*
	 * A special, but typical case; listen-on-v6 { any; }.
	 * When we can make the socket IPv6-only, open a single wildcard
	 * socket for IPv6 communication.  Otherwise, make separate socket
	 * for each IPv6 address in order to avoid accepting IPv4 packets
	 * as the form of mapped addresses unintentionally unless explicitly
	 * allowed.
	 */
#ifndef ISC_ALLOW_MAPPED
	if (scan_ipv6 == ISC_TRUE &&
	    isc_net_probe_ipv6only() != ISC_R_SUCCESS) {
		ipv6only = ISC_FALSE;
		log_explicit = ISC_TRUE;
	}
#endif
	if (scan_ipv6 == ISC_TRUE &&
	    isc_net_probe_ipv6pktinfo() != ISC_R_SUCCESS) {
		ipv6pktinfo = ISC_FALSE;
		log_explicit = ISC_TRUE;
	}
	if (scan_ipv6 == ISC_TRUE && ipv6only && ipv6pktinfo) {
		for (le = ISC_LIST_HEAD(mgr->listenon6->elts);
		     le != NULL;
		     le = ISC_LIST_NEXT(le, link)) {
			struct in6_addr in6a;

			if (!listenon_is_ip6_any(le))
				continue;

			in6a = in6addr_any;
			isc_sockaddr_fromin6(&listen_addr, &in6a, le->port);

			ifp = find_matching_interface(mgr, &listen_addr);
			if (ifp != NULL) {
				ifp->generation = mgr->generation;
				if (le->dscp != -1 && ifp->dscp == -1)
					ifp->dscp = le->dscp;
				else if (le->dscp != ifp->dscp) {
					isc_sockaddr_format(&listen_addr,
							    sabuf,
							    sizeof(sabuf));
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      ISC_LOG_WARNING,
						      "%s: conflicting DSCP "
						      "values, using %d",
						      sabuf, ifp->dscp);
				}
			} else {
				isc_log_write(IFMGR_COMMON_LOGARGS,
					      ISC_LOG_INFO,
					      "listening on IPv6 "
					      "interfaces, port %u",
					      le->port);
				result = ns_interface_setup(mgr, &listen_addr,
							    "<any>", &ifp,
							    ISC_TRUE,
							    le->dscp);
				if (result == ISC_R_SUCCESS)
					ifp->flags |= NS_INTERFACEFLAG_ANYADDR;
				else
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      ISC_LOG_ERROR,
						      "listening on all IPv6 "
						      "interfaces failed");
				/* Continue. */
			}
		}
	}

	isc_netaddr_any(&zero_address);
	isc_netaddr_any6(&zero_address6);

	result = isc_interfaceiter_create(mgr->mctx, &iter);
	if (result != ISC_R_SUCCESS)
		return (result);

	if (adjusting == ISC_FALSE) {
		result = clearacl(mgr->mctx, &mgr->aclenv.localhost);
		if (result != ISC_R_SUCCESS)
			goto cleanup_iter;
		result = clearacl(mgr->mctx, &mgr->aclenv.localnets);
		if (result != ISC_R_SUCCESS)
			goto cleanup_iter;
		clearlistenon(mgr);
	}

	for (result = isc_interfaceiter_first(iter);
	     result == ISC_R_SUCCESS;
	     result = isc_interfaceiter_next(iter))
	{
		isc_interface_t interface;
		ns_listenlist_t *ll;
		unsigned int family;

		result = isc_interfaceiter_current(iter, &interface);
		if (result != ISC_R_SUCCESS)
			break;

		family = interface.address.family;
		if (family != AF_INET && family != AF_INET6)
			continue;
		if (scan_ipv4 == ISC_FALSE && family == AF_INET)
			continue;
		if (scan_ipv6 == ISC_FALSE && family == AF_INET6)
			continue;

		/*
		 * Test for the address being nonzero rather than testing
		 * INTERFACE_F_UP, because on some systems the latter
		 * follows the media state and we could end up ignoring
		 * the interface for an entire rescan interval due to
		 * a temporary media glitch at rescan time.
		 */
		if (family == AF_INET &&
		    isc_netaddr_equal(&interface.address, &zero_address)) {
			continue;
		}
		if (family == AF_INET6 &&
		    isc_netaddr_equal(&interface.address, &zero_address6)) {
			continue;
		}

		if (adjusting == ISC_FALSE) {
			/*
			 * If running with -T fixedlocal, then we only
			 * want 127.0.0.1 and ::1 in the localhost ACL.
			 */
			if (ns_g_fixedlocal &&
			    !isc_netaddr_isloopback(&interface.address))
			{
				goto listenon;
			}

			result = setup_locals(mgr, &interface);
			if (result != ISC_R_SUCCESS)
				goto ignore_interface;
		}

 listenon:
		ll = (family == AF_INET) ? mgr->listenon4 : mgr->listenon6;
		dolistenon = ISC_TRUE;
		for (le = ISC_LIST_HEAD(ll->elts);
		     le != NULL;
		     le = ISC_LIST_NEXT(le, link))
		{
			int match;
			isc_boolean_t ipv6_wildcard = ISC_FALSE;
			isc_netaddr_t listen_netaddr;
			isc_sockaddr_t listen_sockaddr;

			/*
			 * Construct a socket address for this IP/port
			 * combination.
			 */
			if (family == AF_INET) {
				isc_netaddr_fromin(&listen_netaddr,
						   &interface.address.type.in);
			} else {
				isc_netaddr_fromin6(&listen_netaddr,
						    &interface.address.type.in6);
				isc_netaddr_setzone(&listen_netaddr,
						    interface.address.zone);
			}
			isc_sockaddr_fromnetaddr(&listen_sockaddr,
						 &listen_netaddr,
						 le->port);

			/*
			 * See if the address matches the listen-on statement;
			 * if not, ignore the interface.
			 */
			(void)dns_acl_match(&listen_netaddr, NULL, le->acl,
					    &mgr->aclenv, &match, NULL);
			if (match <= 0)
				continue;

			if (adjusting == ISC_FALSE && dolistenon == ISC_TRUE) {
				setup_listenon(mgr, &interface, le->port);
				dolistenon = ISC_FALSE;
			}

			/*
			 * The case of "any" IPv6 address will require
			 * special considerations later, so remember it.
			 */
			if (family == AF_INET6 && ipv6only && ipv6pktinfo &&
			    listenon_is_ip6_any(le))
				ipv6_wildcard = ISC_TRUE;

			/*
			 * When adjusting interfaces with extra a listening
			 * list, see if the address matches the extra list.
			 * If it does, and is also covered by a wildcard
			 * interface, we need to listen on the address
			 * explicitly.
			 */
			if (adjusting == ISC_TRUE) {
				ns_listenelt_t *ele;

				match = 0;
				for (ele = ISC_LIST_HEAD(ext_listen->elts);
				     ele != NULL;
				     ele = ISC_LIST_NEXT(ele, link)) {
					(void)dns_acl_match(&listen_netaddr,
							    NULL, ele->acl,
							    NULL, &match, NULL);
					if (match > 0 &&
					    (ele->port == le->port ||
					    ele->port == 0))
						break;
					else
						match = 0;
				}
				if (ipv6_wildcard == ISC_TRUE && match == 0)
					continue;
			}

			ifp = find_matching_interface(mgr, &listen_sockaddr);
			if (ifp != NULL) {
				ifp->generation = mgr->generation;
				if (le->dscp != -1 && ifp->dscp == -1)
					ifp->dscp = le->dscp;
				else if (le->dscp != ifp->dscp) {
					isc_sockaddr_format(&listen_sockaddr,
							    sabuf,
							    sizeof(sabuf));
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      ISC_LOG_WARNING,
						      "%s: conflicting DSCP "
						      "values, using %d",
						      sabuf, ifp->dscp);
				}
			} else {
				if (adjusting == ISC_FALSE &&
				    ipv6_wildcard == ISC_TRUE)
					continue;

				if (log_explicit && family == AF_INET6 &&
				    !adjusting && listenon_is_ip6_any(le)) {
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      verbose ? ISC_LOG_INFO :
							      ISC_LOG_DEBUG(1),
						      "IPv6 socket API is "
						      "incomplete; explicitly "
						      "binding to each IPv6 "
						      "address separately");
					log_explicit = ISC_FALSE;
				}
				isc_sockaddr_format(&listen_sockaddr,
						    sabuf, sizeof(sabuf));
				isc_log_write(IFMGR_COMMON_LOGARGS,
					      ISC_LOG_INFO,
					      "%s"
					      "listening on %s interface "
					      "%s, %s",
					      (adjusting == ISC_TRUE) ?
					      "additionally " : "",
					      (family == AF_INET) ?
					      "IPv4" : "IPv6",
					      interface.name, sabuf);

				result = ns_interface_setup(mgr,
						    &listen_sockaddr,
						    interface.name,
						    &ifp,
						    (adjusting == ISC_TRUE) ?
						    ISC_FALSE : ISC_TRUE,
						    le->dscp);

				if (result != ISC_R_SUCCESS) {
					isc_log_write(IFMGR_COMMON_LOGARGS,
						      ISC_LOG_ERROR,
						      "creating %s interface "
						      "%s failed; interface "
						      "ignored",
						      (family == AF_INET) ?
						      "IPv4" : "IPv6",
						      interface.name);
				}
				/* Continue. */
			}

		}
		continue;

	ignore_interface:
		isc_log_write(IFMGR_COMMON_LOGARGS,
			      ISC_LOG_ERROR,
			      "ignoring %s interface %s: %s",
			      (family == AF_INET) ? "IPv4" : "IPv6",
			      interface.name, isc_result_totext(result));
		continue;
	}
	if (result != ISC_R_NOMORE)
		UNEXPECTED_ERROR(__FILE__, __LINE__,
				 "interface iteration failed: %s",
				 isc_result_totext(result));
	else
		result = ISC_R_SUCCESS;
 cleanup_iter:
	isc_interfaceiter_destroy(&iter);
	return (result);
}
コード例 #27
0
ファイル: zoneconf.c プロジェクト: ElRevo/xia-core
/*%
 * Configure static-stub zone.
 */
static isc_result_t
configure_staticstub(const cfg_obj_t *zconfig, dns_zone_t *zone,
		     const char *zname, const char *dbtype)
{
	int i = 0;
	const cfg_obj_t *obj;
	isc_mem_t *mctx = dns_zone_getmctx(zone);
	dns_db_t *db = NULL;
	dns_dbversion_t *dbversion = NULL;
	dns_dbnode_t *apexnode = NULL;
	dns_name_t apexname;
	isc_result_t result;
	dns_rdataset_t rdataset;
	dns_rdatalist_t rdatalist_ns, rdatalist_a, rdatalist_aaaa;
	dns_rdatalist_t* rdatalists[] = {
		&rdatalist_ns, &rdatalist_a, &rdatalist_aaaa, NULL
	};
	dns_rdata_t *rdata;
	isc_region_t region;

	/* Create the DB beforehand */
	RETERR(dns_db_create(mctx, dbtype, dns_zone_getorigin(zone),
			     dns_dbtype_stub, dns_zone_getclass(zone),
			     0, NULL, &db));
	dns_zone_setdb(zone, db);

	dns_rdatalist_init(&rdatalist_ns);
	rdatalist_ns.rdclass = dns_zone_getclass(zone);
	rdatalist_ns.type = dns_rdatatype_ns;
	rdatalist_ns.ttl = STATICSTUB_SERVER_TTL;

	dns_rdatalist_init(&rdatalist_a);
	rdatalist_a.rdclass = dns_zone_getclass(zone);
	rdatalist_a.type = dns_rdatatype_a;
	rdatalist_a.ttl = STATICSTUB_SERVER_TTL;

	dns_rdatalist_init(&rdatalist_aaaa);
	rdatalist_aaaa.rdclass = dns_zone_getclass(zone);
	rdatalist_aaaa.type = dns_rdatatype_aaaa;
	rdatalist_aaaa.ttl = STATICSTUB_SERVER_TTL;

	/* Prepare zone RRs from the configuration */
	obj = NULL;
	result = cfg_map_get(zconfig, "server-addresses", &obj);
	if (result == ISC_R_SUCCESS) {
		INSIST(obj != NULL);
		result = configure_staticstub_serveraddrs(obj, zone,
							  &rdatalist_ns,
							  &rdatalist_a,
							  &rdatalist_aaaa);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}

	obj = NULL;
	result = cfg_map_get(zconfig, "server-names", &obj);
	if (result == ISC_R_SUCCESS) {
		INSIST(obj != NULL);
		result = configure_staticstub_servernames(obj, zone,
							  &rdatalist_ns,
							  zname);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}

	/*
	 * Sanity check: there should be at least one NS RR at the zone apex
	 * to trigger delegation.
	 */
	if (ISC_LIST_EMPTY(rdatalist_ns.rdata)) {
		isc_log_write(ns_g_lctx, NS_LOGCATEGORY_GENERAL,
			      NS_LOGMODULE_SERVER, ISC_LOG_ERROR,
			      "No NS record is configured for a "
			      "static-stub zone '%s'", zname);
		result = ISC_R_FAILURE;
		goto cleanup;
	}

	/*
	 * Now add NS and glue A/AAAA RRsets to the zone DB.
	 * First open a new version for the add operation and get a pointer
	 * to the apex node (all RRs are of the apex name).
	 */
	result = dns_db_newversion(db, &dbversion);
	if (result != ISC_R_SUCCESS)
		goto cleanup;
	dns_name_init(&apexname, NULL);
	dns_name_clone(dns_zone_getorigin(zone), &apexname);
	result = dns_db_findnode(db, &apexname, ISC_FALSE, &apexnode);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	/* Add NS RRset */
	dns_rdataset_init(&rdataset);
	RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_ns, &rdataset)
		      == ISC_R_SUCCESS);
	result = dns_db_addrdataset(db, apexnode, dbversion, 0, &rdataset,
				    0, NULL);
	dns_rdataset_disassociate(&rdataset);
	if (result != ISC_R_SUCCESS)
		goto cleanup;

	/* Add glue A RRset, if any */
	if (!ISC_LIST_EMPTY(rdatalist_a.rdata)) {
		RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_a, &rdataset)
			      == ISC_R_SUCCESS);
		result = dns_db_addrdataset(db, apexnode, dbversion, 0,
					    &rdataset, 0, NULL);
		dns_rdataset_disassociate(&rdataset);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}

	/* Add glue AAAA RRset, if any */
	if (!ISC_LIST_EMPTY(rdatalist_aaaa.rdata)) {
		RUNTIME_CHECK(dns_rdatalist_tordataset(&rdatalist_aaaa,
						       &rdataset)
			      == ISC_R_SUCCESS);
		result = dns_db_addrdataset(db, apexnode, dbversion, 0,
					    &rdataset, 0, NULL);
		dns_rdataset_disassociate(&rdataset);
		if (result != ISC_R_SUCCESS)
			goto cleanup;
	}

	result = ISC_R_SUCCESS;

  cleanup:
	if (apexnode != NULL)
		dns_db_detachnode(db, &apexnode);
	if (dbversion != NULL)
		dns_db_closeversion(db, &dbversion, ISC_TRUE);
	if (db != NULL)
		dns_db_detach(&db);
	for (i = 0; rdatalists[i] != NULL; i++) {
		while ((rdata = ISC_LIST_HEAD(rdatalists[i]->rdata)) != NULL) {
			ISC_LIST_UNLINK(rdatalists[i]->rdata, rdata, link);
			dns_rdata_toregion(rdata, &region);
			isc_mem_put(mctx, rdata,
				    sizeof(*rdata) + region.length);
		}
	}

	return (result);
}
コード例 #28
0
static void
route_event(isc_task_t *task, isc_event_t *event) {
	isc_socketevent_t *sevent = NULL;
	ns_interfacemgr_t *mgr = NULL;
	isc_region_t r;
	isc_result_t result;
	struct MSGHDR *rtm;
	isc_boolean_t done = ISC_TRUE;

	UNUSED(task);

	REQUIRE(event->ev_type == ISC_SOCKEVENT_RECVDONE);
	mgr = event->ev_arg;
	sevent = (isc_socketevent_t *)event;

	if (sevent->result != ISC_R_SUCCESS) {
		if (sevent->result != ISC_R_CANCELED)
			isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
				      "automatic interface scanning "
				      "terminated: %s",
				      isc_result_totext(sevent->result));
		ns_interfacemgr_detach(&mgr);
		isc_event_free(&event);
		return;
	}

	rtm = (struct MSGHDR *)mgr->buf;
#ifdef RTM_VERSION
	if (rtm->rtm_version != RTM_VERSION) {
		isc_log_write(IFMGR_COMMON_LOGARGS, ISC_LOG_ERROR,
			      "automatic interface rescanning disabled: "
			      "rtm->rtm_version mismatch (%u != %u) "
			      "recompile required", rtm->rtm_version,
			      RTM_VERSION);
		ns_interfacemgr_detach(&mgr);
		isc_event_free(&event);
		return;
	}
#endif

	switch (rtm->MSGTYPE) {
	case RTM_NEWADDR:
	case RTM_DELADDR:
		if (mgr->route != NULL && ns_g_server->interface_auto)
			ns_server_scan_interfaces(ns_g_server);
		break;
	default:
		break;
	}

	LOCK(&mgr->lock);
	if (mgr->route != NULL) {
		/*
		 * Look for next route event.
		 */
		r.base = mgr->buf;
		r.length = sizeof(mgr->buf);
		result = isc_socket_recv(mgr->route, &r, 1, mgr->task,
					 route_event, mgr);
		if (result == ISC_R_SUCCESS)
			done = ISC_FALSE;
	}
	UNLOCK(&mgr->lock);

	if (done)
		ns_interfacemgr_detach(&mgr);
	isc_event_free(&event);
	return;
}
コード例 #29
0
ファイル: xfrout.c プロジェクト: ystk/debian-bind9
void
ns_xfr_start(ns_client_t *client, dns_rdatatype_t reqtype) {
	isc_result_t result;
	dns_name_t *question_name;
	dns_rdataset_t *question_rdataset;
	dns_zone_t *zone = NULL;
	dns_db_t *db = NULL;
	dns_dbversion_t *ver = NULL;
	dns_rdataclass_t question_class;
	rrstream_t *soa_stream = NULL;
	rrstream_t *data_stream = NULL;
	rrstream_t *stream = NULL;
	dns_difftuple_t *current_soa_tuple = NULL;
	dns_name_t *soa_name;
	dns_rdataset_t *soa_rdataset;
	dns_rdata_t soa_rdata = DNS_RDATA_INIT;
	isc_boolean_t have_soa = ISC_FALSE;
	const char *mnemonic = NULL;
	isc_mem_t *mctx = client->mctx;
	dns_message_t *request = client->message;
	xfrout_ctx_t *xfr = NULL;
	isc_quota_t *quota = NULL;
	dns_transfer_format_t format = client->view->transfer_format;
	isc_netaddr_t na;
	dns_peer_t *peer = NULL;
	isc_buffer_t *tsigbuf = NULL;
	char *journalfile;
	char msg[NS_CLIENT_ACLMSGSIZE("zone transfer")];
	char keyname[DNS_NAME_FORMATSIZE];
	isc_boolean_t is_poll = ISC_FALSE;
#ifdef DLZ
	isc_boolean_t is_dlz = ISC_FALSE;
#endif

	switch (reqtype) {
	case dns_rdatatype_axfr:
		mnemonic = "AXFR";
		break;
	case dns_rdatatype_ixfr:
		mnemonic = "IXFR";
		break;
	default:
		INSIST(0);
		break;
	}

	ns_client_log(client,
		      DNS_LOGCATEGORY_XFER_OUT, NS_LOGMODULE_XFER_OUT,
		      ISC_LOG_DEBUG(6), "%s request", mnemonic);
	/*
	 * Apply quota.
	 */
	result = isc_quota_attach(&ns_g_server->xfroutquota, &quota);
	if (result != ISC_R_SUCCESS) {
		isc_log_write(XFROUT_COMMON_LOGARGS, ISC_LOG_WARNING,
			      "%s request denied: %s", mnemonic,
			      isc_result_totext(result));
		goto failure;
	}

	/*
	 * Interpret the question section.
	 */
	result = dns_message_firstname(request, DNS_SECTION_QUESTION);
	INSIST(result == ISC_R_SUCCESS);

	/*
	 * The question section must contain exactly one question, and
	 * it must be for AXFR/IXFR as appropriate.
	 */
	question_name = NULL;
	dns_message_currentname(request, DNS_SECTION_QUESTION, &question_name);
	question_rdataset = ISC_LIST_HEAD(question_name->list);
	question_class = question_rdataset->rdclass;
	INSIST(question_rdataset->type == reqtype);
	if (ISC_LIST_NEXT(question_rdataset, link) != NULL)
		FAILC(DNS_R_FORMERR, "multiple questions");
	result = dns_message_nextname(request, DNS_SECTION_QUESTION);
	if (result != ISC_R_NOMORE)
		FAILC(DNS_R_FORMERR, "multiple questions");

	result = dns_zt_find(client->view->zonetable, question_name, 0, NULL,
			     &zone);

	if (result != ISC_R_SUCCESS)
#ifdef DLZ
	{
		/*
		 * Normal zone table does not have a match.
		 * Try the DLZ database
		 */
		if (client->view->dlzdatabase != NULL) {
			result = dns_dlzallowzonexfr(client->view,
						     question_name,
						     &client->peeraddr,
						     &db);

			if (result == ISC_R_NOPERM) {
				char _buf1[DNS_NAME_FORMATSIZE];
				char _buf2[DNS_RDATACLASS_FORMATSIZE];

				result = DNS_R_REFUSED;
				dns_name_format(question_name, _buf1,
						sizeof(_buf1));
				dns_rdataclass_format(question_class,
						      _buf2, sizeof(_buf2));
				ns_client_log(client, DNS_LOGCATEGORY_SECURITY,
					      NS_LOGMODULE_XFER_OUT,
					      ISC_LOG_ERROR,
					      "zone transfer '%s/%s' denied",
					      _buf1, _buf2);
				goto failure;
			}
			if (result != ISC_R_SUCCESS)
#endif
			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
				  question_name, question_class);
#ifdef DLZ
			is_dlz = ISC_TRUE;
			/*
			 * DLZ only support full zone transfer, not incremental
			 */
			if (reqtype != dns_rdatatype_axfr) {
				mnemonic = "AXFR-style IXFR";
				reqtype = dns_rdatatype_axfr;
			}

		} else {
			/*
			 * not DLZ and not in normal zone table, we are
			 * not authoritative
			 */
			FAILQ(DNS_R_NOTAUTH, "non-authoritative zone",
			      question_name, question_class);
		}
	} else {
		/* zone table has a match */
#endif
		switch(dns_zone_gettype(zone)) {
			case dns_zone_master:
			case dns_zone_slave:
				break;	/* Master and slave zones are OK for transfer. */
			default:
				FAILQ(DNS_R_NOTAUTH, "non-authoritative zone", question_name, question_class);
			}
		CHECK(dns_zone_getdb(zone, &db));
		dns_db_currentversion(db, &ver);
#ifdef DLZ
	}
#endif

	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
		    "%s question section OK", mnemonic);

	/*
	 * Check the authority section.  Look for a SOA record with
	 * the same name and class as the question.
	 */
	for (result = dns_message_firstname(request, DNS_SECTION_AUTHORITY);
	     result == ISC_R_SUCCESS;
	     result = dns_message_nextname(request, DNS_SECTION_AUTHORITY))
	{
		soa_name = NULL;
		dns_message_currentname(request, DNS_SECTION_AUTHORITY,
					&soa_name);

		/*
		 * Ignore data whose owner name is not the zone apex.
		 */
		if (! dns_name_equal(soa_name, question_name))
			continue;

		for (soa_rdataset = ISC_LIST_HEAD(soa_name->list);
		     soa_rdataset != NULL;
		     soa_rdataset = ISC_LIST_NEXT(soa_rdataset, link))
		{
			/*
			 * Ignore non-SOA data.
			 */
			if (soa_rdataset->type != dns_rdatatype_soa)
				continue;
			if (soa_rdataset->rdclass != question_class)
				continue;

			CHECK(dns_rdataset_first(soa_rdataset));
			dns_rdataset_current(soa_rdataset, &soa_rdata);
			result = dns_rdataset_next(soa_rdataset);
			if (result == ISC_R_SUCCESS)
				FAILC(DNS_R_FORMERR,
				      "IXFR authority section "
				      "has multiple SOAs");
			have_soa = ISC_TRUE;
			goto got_soa;
		}
	}
 got_soa:
	if (result != ISC_R_NOMORE)
		CHECK(result);

	xfrout_log1(client, question_name, question_class, ISC_LOG_DEBUG(6),
		    "%s authority section OK", mnemonic);

	/*
	 * Decide whether to allow this transfer.
	 */
#ifdef DLZ
	/*
	 * if not a DLZ zone decide whether to allow this transfer.
	 */
	if (!is_dlz) {
#endif
		ns_client_aclmsg("zone transfer", question_name, reqtype,
				 client->view->rdclass, msg, sizeof(msg));
		CHECK(ns_client_checkacl(client, NULL, msg,
					 dns_zone_getxfracl(zone),
					 ISC_TRUE, ISC_LOG_ERROR));
#ifdef DLZ
	}
#endif

	/*
	 * AXFR over UDP is not possible.
	 */
	if (reqtype == dns_rdatatype_axfr &&
	    (client->attributes & NS_CLIENTATTR_TCP) == 0)
		FAILC(DNS_R_FORMERR, "attempted AXFR over UDP");

	/*
	 * Look up the requesting server in the peer table.
	 */
	isc_netaddr_fromsockaddr(&na, &client->peeraddr);
	(void)dns_peerlist_peerbyaddr(client->view->peers, &na, &peer);

	/*
	 * Decide on the transfer format (one-answer or many-answers).
	 */
	if (peer != NULL)
		(void)dns_peer_gettransferformat(peer, &format);

	/*
	 * Get a dynamically allocated copy of the current SOA.
	 */
#ifdef DLZ
	if (is_dlz)
		dns_db_currentversion(db, &ver);
#endif
	CHECK(dns_db_createsoatuple(db, ver, mctx, DNS_DIFFOP_EXISTS,
				    &current_soa_tuple));

	if (reqtype == dns_rdatatype_ixfr) {
		isc_uint32_t begin_serial, current_serial;
		isc_boolean_t provide_ixfr;

		/*
		 * Outgoing IXFR may have been disabled for this peer
		 * or globally.
		 */
		provide_ixfr = client->view->provideixfr;
		if (peer != NULL)
			(void) dns_peer_getprovideixfr(peer, &provide_ixfr);
		if (provide_ixfr == ISC_FALSE)
			goto axfr_fallback;

		if (! have_soa)
			FAILC(DNS_R_FORMERR,
			      "IXFR request missing SOA");

		begin_serial = dns_soa_getserial(&soa_rdata);
		current_serial = dns_soa_getserial(&current_soa_tuple->rdata);

		/*
		 * RFC1995 says "If an IXFR query with the same or
		 * newer version number than that of the server
		 * is received, it is replied to with a single SOA
		 * record of the server's current version, just as
		 * in AXFR".  The claim about AXFR is incorrect,
		 * but other than that, we do as the RFC says.
		 *
		 * Sending a single SOA record is also how we refuse
		 * IXFR over UDP (currently, we always do).
		 */
		if (DNS_SERIAL_GE(begin_serial, current_serial) ||
		    (client->attributes & NS_CLIENTATTR_TCP) == 0)
		{
			CHECK(soa_rrstream_create(mctx, db, ver, &stream));
			is_poll = ISC_TRUE;
			goto have_stream;
		}
		journalfile = dns_zone_getjournal(zone);
		if (journalfile != NULL)
			result = ixfr_rrstream_create(mctx,
						      journalfile,
						      begin_serial,
						      current_serial,
						      &data_stream);
		else
			result = ISC_R_NOTFOUND;
		if (result == ISC_R_NOTFOUND ||
		    result == ISC_R_RANGE) {
			xfrout_log1(client, question_name, question_class,
				    ISC_LOG_DEBUG(4),
				    "IXFR version not in journal, "
				    "falling back to AXFR");
			mnemonic = "AXFR-style IXFR";
			goto axfr_fallback;
		}
		CHECK(result);
	} else {
	axfr_fallback:
		CHECK(axfr_rrstream_create(mctx, db, ver,
					   &data_stream));
	}

	/*
	 * Bracket the data stream with SOAs.
	 */
	CHECK(soa_rrstream_create(mctx, db, ver, &soa_stream));
	CHECK(compound_rrstream_create(mctx, &soa_stream, &data_stream,
				       &stream));
	soa_stream = NULL;
	data_stream = NULL;

 have_stream:
	CHECK(dns_message_getquerytsig(request, mctx, &tsigbuf));
	/*
	 * Create the xfrout context object.  This transfers the ownership
	 * of "stream", "db", "ver", and "quota" to the xfrout context object.
	 */



#ifdef DLZ
	if (is_dlz)
		CHECK(xfrout_ctx_create(mctx, client, request->id,
					question_name, reqtype, question_class,
					zone, db, ver, quota, stream,
					dns_message_gettsigkey(request),
					tsigbuf,
					3600,
					3600,
					(format == dns_many_answers) ?
					ISC_TRUE : ISC_FALSE,
					&xfr));
	else
#endif
		CHECK(xfrout_ctx_create(mctx, client, request->id,
					question_name, reqtype, question_class,
					zone, db, ver, quota, stream,
					dns_message_gettsigkey(request),
					tsigbuf,
					dns_zone_getmaxxfrout(zone),
					dns_zone_getidleout(zone),
					(format == dns_many_answers) ?
					ISC_TRUE : ISC_FALSE,
					&xfr));

	xfr->mnemonic = mnemonic;
	stream = NULL;
	quota = NULL;

	CHECK(xfr->stream->methods->first(xfr->stream));

	if (xfr->tsigkey != NULL) {
		dns_name_format(&xfr->tsigkey->name, keyname, sizeof(keyname));
	} else
		keyname[0] = '\0';
	if (is_poll)
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_DEBUG(1), "IXFR poll up to date%s%s",
			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);
	else
		xfrout_log1(client, question_name, question_class,
			    ISC_LOG_INFO, "%s started%s%s", mnemonic,
			    (xfr->tsigkey != NULL) ? ": TSIG " : "", keyname);

	/*
	 * Hand the context over to sendstream().  Set xfr to NULL;
	 * sendstream() is responsible for either passing the
	 * context on to a later event handler or destroying it.
	 */
	sendstream(xfr);
	xfr = NULL;

	result = ISC_R_SUCCESS;

 failure:
	if (result == DNS_R_REFUSED)
		inc_stats(zone, dns_nsstatscounter_xfrrej);
	if (quota != NULL)
		isc_quota_detach(&quota);
	if (current_soa_tuple != NULL)
		dns_difftuple_free(&current_soa_tuple);
	if (stream != NULL)
		stream->methods->destroy(&stream);
	if (soa_stream != NULL)
		soa_stream->methods->destroy(&soa_stream);
	if (data_stream != NULL)
		data_stream->methods->destroy(&data_stream);
	if (ver != NULL)
		dns_db_closeversion(db, &ver, ISC_FALSE);
	if (db != NULL)
		dns_db_detach(&db);
	if (zone != NULL)
		dns_zone_detach(&zone);
	/* XXX kludge */
	if (xfr != NULL) {
		xfrout_fail(xfr, result, "setting up zone transfer");
	} else if (result != ISC_R_SUCCESS) {
		ns_client_log(client, DNS_LOGCATEGORY_XFER_OUT,
			      NS_LOGMODULE_XFER_OUT,
			      ISC_LOG_DEBUG(3), "zone transfer setup failed");
		ns_client_error(client, result);
	}
}
コード例 #30
0
ファイル: tcldb.c プロジェクト: enukane/netbsd-src
static isc_result_t
tcldb_lookup(const char *zone, const char *name, void *dbdata,
	      dns_sdblookup_t *lookup)
#endif /* DNS_CLIENTINFO_VERSION */
{
	isc_result_t result = ISC_R_SUCCESS;
	int tclres;
	int rrc;	/* RR count */
	char **rrv;	/* RR vector */
	int i;
	char *cmdv[3];
	char *cmd;

#ifdef DNS_CLIENTINFO_VERSION
	UNUSED(methods);
	UNUSED(clientinfo);
#endif /* DNS_CLIENTINFO_VERSION */

	tcldb_driver_t *driver = (tcldb_driver_t *) dbdata;

	cmdv[0] = "lookup";
	cmdv[1] = zone;
	cmdv[2] = name;
	cmd = Tcl_Merge(3, cmdv);
	tclres = Tcl_Eval(driver->interp, cmd);
	Tcl_Free(cmd);

	if (tclres != TCL_OK) {
		isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
			      DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
			      "zone '%s': tcl lookup function failed: %s",
			      zone, driver->interp->result);
		return (ISC_R_FAILURE);
	}

	if (strcmp(driver->interp->result, "NXDOMAIN") == 0) {
		result = ISC_R_NOTFOUND;
		goto fail;
	}

	tclres = Tcl_SplitList(driver->interp, driver->interp->result,
			       &rrc, &rrv);
	if (tclres != TCL_OK)
		goto malformed;

	for (i = 0; i < rrc; i++) {
		isc_result_t tmpres;
		int fieldc;	/* Field count */
		char **fieldv;	/* Field vector */
		tclres = Tcl_SplitList(driver->interp, rrv[i],
				       &fieldc, &fieldv);
		if (tclres != TCL_OK) {
			tmpres = ISC_R_FAILURE;
			goto failrr;
		}
		if (fieldc != 3)
			goto malformed;
		tmpres = dns_sdb_putrr(lookup, fieldv[0], atoi(fieldv[1]),
				       fieldv[2]);
		Tcl_Free((char *) fieldv);
	failrr:
		if (tmpres != ISC_R_SUCCESS)
			result = tmpres;
	}
	Tcl_Free((char *) rrv);
	if (result == ISC_R_SUCCESS)
		return (result);

 malformed:
	isc_log_write(dns_lctx, DNS_LOGCATEGORY_GENERAL,
		      DNS_LOGMODULE_SDB, ISC_LOG_ERROR,
		      "zone '%s': "
		      "malformed return value from tcl lookup function: %s",
		      zone, driver->interp->result);
	result = ISC_R_FAILURE;
 fail:
	return (result);
}