示例#1
0
/*
 * npfctl_sessions_load: import a list of sessions, reconstruct them and load.
 */
int
npfctl_sessions_load(u_long cmd, void *data)
{
	const struct plistref *pref = data;
	npf_sehash_t *sehasht = NULL;
	prop_dictionary_t sesdict, sedict;
	prop_object_iterator_t it;
	prop_array_t selist;
	int error;

	/* Retrieve the dictionary containing session and NAT policy lists. */
	error = prop_dictionary_copyin_ioctl(pref, cmd, &sesdict);
	if (error)
		return error;

	/*
	 * Note: session objects contain the references to the NAT policy
	 * entries.  Therefore, no need to directly access it.
	 */
	selist = prop_dictionary_get(sesdict, "session-list");
	if (prop_object_type(selist) != PROP_TYPE_ARRAY) {
		error = EINVAL;
		goto fail;
	}

	/* Create a session hash table. */
	sehasht = sess_htable_create();
	if (sehasht == NULL) {
		error = ENOMEM;
		goto fail;
	}

	/*
	 * Iterate through and construct each session.
	 */
	error = 0;
	it = prop_array_iterator(selist);
	npf_core_enter();
	while ((sedict = prop_object_iterator_next(it)) != NULL) {
		/* Session - dictionary. */
		if (prop_object_type(sedict) != PROP_TYPE_DICTIONARY) {
			error = EINVAL;
			goto fail;
		}
		/* Construct and insert real session structure. */
		error = npf_session_restore(sehasht, sedict);
		if (error) {
			goto fail;
		}
	}
	npf_core_exit();
	sess_htable_reload(sehasht);
fail:
	prop_object_release(selist);
	if (error && sehasht) {
		/* Destroy session table. */
		sess_htable_destroy(sehasht);
	}
	return error;
}
示例#2
0
int
npfctl_remove_rule(u_long cmd, void *data)
{
	struct plistref *pref = data;
	prop_dictionary_t dict, errdict;
	prop_object_t obj;
	const char *name;
	int error, numrules;

	/* Retrieve and construct the rule. */
	error = prop_dictionary_copyin_ioctl(pref, cmd, &dict);
	if (error) {
		return error;
	}

	/* Dictionary for error reporting. */
	errdict = prop_dictionary_create();

	obj = prop_dictionary_get(dict, "name");
	name = prop_string_cstring_nocopy(obj);
	npf_rule_t *rl;
	error = npf_mk_singlerule(dict, prop_array_create(), &rl, errdict);

	npf_core_enter();
	numrules = npf_named_ruleset_remove(name, npf_core_ruleset(), rl);
	npf_core_exit();
	prop_object_release(dict);

	/* Error report. */
	prop_dictionary_set_int32(errdict, "errno", error);
	prop_dictionary_set_int32(errdict, "numrules", numrules);
	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
	prop_object_release(errdict);
	return error;
}
示例#3
0
static int
dmioctl(struct dev_ioctl_args *ap)
{
	cdev_t dev = ap->a_head.a_dev;
	u_long cmd = ap->a_cmd;
	void *data = ap->a_data;

	int r, err;
	prop_dictionary_t dm_dict_in;

	err = r = 0;

	aprint_debug("dmioctl called\n");

	KKASSERT(data != NULL);

	if (( r = disk_ioctl_switch(dev, cmd, data)) == ENOTTY) {
		struct plistref *pref = (struct plistref *) data;

		/* Check if we were called with NETBSD_DM_IOCTL ioctl
		   otherwise quit. */
		if ((r = dm_ioctl_switch(cmd)) != 0)
			return r;

		if((r = prop_dictionary_copyin_ioctl(pref, cmd, &dm_dict_in)) != 0)
			return r;

		if ((r = dm_check_version(dm_dict_in)) != 0)
			goto cleanup_exit;

		/* run ioctl routine */
		if ((err = dm_cmd_to_fun(dm_dict_in)) != 0)
			goto cleanup_exit;

cleanup_exit:
		r = prop_dictionary_copyout_ioctl(pref, cmd, dm_dict_in);
		prop_object_release(dm_dict_in);
	}

	/*
	 * Return the error of the actual command if one one has
	 * happened. Otherwise return 'r' which indicates errors
	 * that occurred during helper operations.
	 */
	return (err != 0)?err:r;
}
示例#4
0
/*
 * npfctl_update_rule: reload a specific rule identified by the name.
 */
int
npfctl_update_rule(u_long cmd, void *data)
{
	struct plistref *pref = data;
	prop_dictionary_t dict, errdict;
	prop_array_t subrules;
	prop_object_t obj;
	npf_ruleset_t *rlset;
	const char *name;
	int error;

	/* Retrieve and construct the rule. */
	error = prop_dictionary_copyin_ioctl(pref, cmd, &dict);
	if (error) {
		return error;
	}

	/* Dictionary for error reporting. */
	errdict = prop_dictionary_create();

	/* Create the ruleset and construct sub-rules. */
	rlset = npf_ruleset_create();
	subrules = prop_dictionary_get(dict, "subrules");
	error = npf_mk_subrules(rlset, subrules, NULL, errdict);
	if (error) {
		goto out;
	}

	/* Lookup the rule by name, and replace its subset (sub-rules). */
	obj = prop_dictionary_get(dict, "name");
	name = prop_string_cstring_nocopy(obj);
	if (npf_ruleset_replace(name, rlset) == NULL) {
		/* Not found. */
		error = ENOENT;
out:		/* Error path. */
		npf_ruleset_destroy(rlset);
	}
	prop_object_release(dict);

	/* Error report. */
	prop_dictionary_set_int32(errdict, "errno", error);
	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
	prop_object_release(errdict);
	return error;
}
int
bthubioctl(dev_t devno, unsigned long cmd, void *data, int flag, struct lwp *l)
{
	prop_dictionary_t dict;
	int err;

	switch(cmd) {
	case BTDEV_ATTACH:
	case BTDEV_DETACH:
		/* load dictionary */
		err = prop_dictionary_copyin_ioctl(data, cmd, &dict);
		if (err == 0) {
			err = bthub_pioctl(devno, cmd, dict, flag, l);
			prop_object_release(dict);
		}
		break;

	default:
		err = EPASSTHROUGH;
		break;
	}

	return err;
}
示例#6
0
static int
dmioctl(dev_t dev, const u_long cmd, void *data, int flag, struct lwp *l)
{
	int r;
	prop_dictionary_t dm_dict_in;

	r = 0;

	aprint_debug("dmioctl called\n");
	KASSERT(data != NULL);
	
	if (( r = disk_ioctl_switch(dev, cmd, data)) == ENOTTY) {
		struct plistref *pref = (struct plistref *) data;

		/* Check if we were called with NETBSD_DM_IOCTL ioctl
		   otherwise quit. */
		if ((r = dm_ioctl_switch(cmd)) != 0)
			return r;

		if((r = prop_dictionary_copyin_ioctl(pref, cmd, &dm_dict_in)) != 0)
			return r;

		if ((r = dm_check_version(dm_dict_in)) != 0)
			goto cleanup_exit;

		/* run ioctl routine */
		if ((r = dm_cmd_to_fun(dm_dict_in)) != 0)
			goto cleanup_exit;

cleanup_exit:
		r = prop_dictionary_copyout_ioctl(pref, cmd, dm_dict_in);
		prop_object_release(dm_dict_in);
	}

	return r;
}
示例#7
0
int
npfctl_add_nat_rule(u_long cmd, void *data)
{
	struct plistref *pref = data;
	prop_dictionary_t dict, errdict;
	int error;

	/* Retrieve and construct the rule. */
	error = prop_dictionary_copyin_ioctl(pref, cmd, &dict);
	if (error) {
		return error;
	}

	/* Dictionary for error reporting. */
	errdict = prop_dictionary_create();

	npf_insert_nat_rule(dict, errdict);

	prop_object_release(dict);

	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
	prop_object_release(errdict);
	return error;
}
示例#8
0
/*
 * npfctl_rule: add or remove dynamic rules in the specified ruleset.
 */
int
npfctl_rule(u_long cmd, void *data)
{
	struct plistref *pref = data;
	prop_dictionary_t npf_rule, retdict = NULL;
	npf_ruleset_t *rlset;
	npf_rule_t *rl = NULL;
	const char *ruleset_name;
	uint32_t rcmd = 0;
	int error;

	error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_rule);
	if (error) {
		return error;
	}
	prop_dictionary_get_uint32(npf_rule, "command", &rcmd);
	if (!prop_dictionary_get_cstring_nocopy(npf_rule,
	    "ruleset-name", &ruleset_name)) {
		error = EINVAL;
		goto out;
	}

	if (rcmd == NPF_CMD_RULE_ADD) {
		retdict = prop_dictionary_create();
		if (npf_mk_singlerule(npf_rule, NULL, &rl, retdict) != 0) {
			error = EINVAL;
			goto out;
		}
	}

	npf_config_enter();
	rlset = npf_config_ruleset();

	switch (rcmd) {
	case NPF_CMD_RULE_ADD: {
		if ((error = npf_ruleset_add(rlset, ruleset_name, rl)) == 0) {
			/* Success. */
			uint64_t id = npf_rule_getid(rl);
			prop_dictionary_set_uint64(retdict, "id", id);
			rl = NULL;
		}
		break;
	}
	case NPF_CMD_RULE_REMOVE: {
		uint64_t id;

		if (!prop_dictionary_get_uint64(npf_rule, "id", &id)) {
			error = EINVAL;
			break;
		}
		error = npf_ruleset_remove(rlset, ruleset_name, id);
		break;
	}
	case NPF_CMD_RULE_REMKEY: {
		prop_object_t obj = prop_dictionary_get(npf_rule, "key");
		const void *key = prop_data_data_nocopy(obj);
		size_t len = prop_data_size(obj);

		if (len == 0 || len > NPF_RULE_MAXKEYLEN) {
			error = EINVAL;
			break;
		}
		error = npf_ruleset_remkey(rlset, ruleset_name, key, len);
		break;
	}
	case NPF_CMD_RULE_LIST: {
		retdict = npf_ruleset_list(rlset, ruleset_name);
		if (!retdict) {
			error = ESRCH;
		}
		break;
	}
	case NPF_CMD_RULE_FLUSH: {
		error = npf_ruleset_flush(rlset, ruleset_name);
		break;
	}
	default:
		error = EINVAL;
		break;
	}

	/* Destroy any removed rules. */
	if (!error && rcmd != NPF_CMD_RULE_ADD && rcmd != NPF_CMD_RULE_LIST) {
		npf_config_sync();
		npf_ruleset_gc(rlset);
	}
	npf_config_exit();

	if (rl) {
		KASSERT(error);
		npf_rule_free(rl);
	}
out:
	if (retdict) {
		prop_object_release(npf_rule);
		prop_dictionary_copyout_ioctl(pref, cmd, retdict);
		prop_object_release(retdict);
	}
	return error;
}
示例#9
0
/*
 * npfctl_load: store passed data i.e. update settings, create passed
 * tables, rules and atomically activate all them.
 */
int
npfctl_load(u_long cmd, void *data)
{
	struct plistref *pref = data;
	prop_dictionary_t npf_dict, errdict;
	prop_array_t alglist, natlist, tables, rprocs, rules, conlist;
	npf_tableset_t *tblset = NULL;
	npf_rprocset_t *rpset = NULL;
	npf_ruleset_t *rlset = NULL;
	npf_ruleset_t *nset = NULL;
	npf_conndb_t *conndb = NULL;
	uint32_t ver = 0;
	size_t nitems;
	bool flush;
	int error;

	/* Retrieve the dictionary. */
#ifndef _NPF_TESTING
	error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_dict);
	if (error)
		return error;
#else
	npf_dict = (prop_dictionary_t)pref;
#endif

	/* Dictionary for error reporting and version check. */
	errdict = prop_dictionary_create();
	prop_dictionary_get_uint32(npf_dict, "version", &ver);
	if (ver != NPF_VERSION) {
		error = EPROGMISMATCH;
		goto fail;
	}

	/* ALGs. */
	alglist = prop_dictionary_get(npf_dict, "algs");
	error = npf_mk_algs(alglist, errdict);
	if (error) {
		goto fail;
	}

	/* NAT policies. */
	natlist = prop_dictionary_get(npf_dict, "nat");
	if ((nitems = prop_array_count(natlist)) > NPF_MAX_RULES) {
		error = E2BIG;
		goto fail;
	}

	nset = npf_ruleset_create(nitems);
	error = npf_mk_natlist(nset, natlist, errdict);
	if (error) {
		goto fail;
	}

	/* Tables. */
	tables = prop_dictionary_get(npf_dict, "tables");
	if ((nitems = prop_array_count(tables)) > NPF_MAX_TABLES) {
		error = E2BIG;
		goto fail;
	}
	tblset = npf_tableset_create(nitems);
	error = npf_mk_tables(tblset, tables, errdict);
	if (error) {
		goto fail;
	}

	/* Rule procedures. */
	rprocs = prop_dictionary_get(npf_dict, "rprocs");
	if ((nitems = prop_array_count(rprocs)) > NPF_MAX_RPROCS) {
		error = E2BIG;
		goto fail;
	}
	rpset = npf_rprocset_create();
	error = npf_mk_rprocs(rpset, rprocs, errdict);
	if (error) {
		goto fail;
	}

	/* Rules. */
	rules = prop_dictionary_get(npf_dict, "rules");
	if ((nitems = prop_array_count(rules)) > NPF_MAX_RULES) {
		error = E2BIG;
		goto fail;
	}

	rlset = npf_ruleset_create(nitems);
	error = npf_mk_rules(rlset, rules, rpset, errdict);
	if (error) {
		goto fail;
	}

	/* Connections (if loading any). */
	if ((conlist = prop_dictionary_get(npf_dict, "conn-list")) != NULL) {
		error = npf_mk_connlist(conlist, nset, &conndb, errdict);
		if (error) {
			goto fail;
		}
	}

	flush = false;
	prop_dictionary_get_bool(npf_dict, "flush", &flush);

	/*
	 * Finally - perform the load.
	 */
	npf_config_load(rlset, tblset, nset, rpset, conndb, flush);

	/* Done.  Since data is consumed now, we shall not destroy it. */
	tblset = NULL;
	rpset = NULL;
	rlset = NULL;
	nset = NULL;
fail:
	/*
	 * Note: destroy rulesets first, to drop references to the tableset.
	 */
	KASSERT(error == 0 || (nset || rpset || rlset || tblset));
	if (nset) {
		npf_ruleset_destroy(nset);
	}
	if (rlset) {
		npf_ruleset_destroy(rlset);
	}
	if (rpset) {
		npf_rprocset_destroy(rpset);
	}
	if (tblset) {
		npf_tableset_destroy(tblset);
	}
	prop_object_release(npf_dict);

	/* Error report. */
#ifndef _NPF_TESTING
	prop_dictionary_set_int32(errdict, "errno", error);
	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
	prop_object_release(errdict);
	error = 0;
#endif
	return error;
}
示例#10
0
/*
 * npfctl_reload: store passed data i.e. update settings, create passed
 * tables, rules and atomically activate all them.
 */
int
npfctl_reload(u_long cmd, void *data)
{
	struct plistref *pref = data;
	prop_dictionary_t npf_dict, errdict;
	prop_array_t natlist, tables, rprocs, rules;
	npf_tableset_t *tblset = NULL;
	npf_ruleset_t *rlset = NULL;
	npf_ruleset_t *nset = NULL;
	bool flush;
	int error;

	/* Retrieve the dictionary. */
#ifndef _NPF_TESTING
	error = prop_dictionary_copyin_ioctl(pref, cmd, &npf_dict);
	if (error)
		return error;
#else
	npf_dict = (prop_dictionary_t)pref;
#endif

	/* Dictionary for error reporting. */
	errdict = prop_dictionary_create();

	/* NAT policies. */
	nset = npf_ruleset_create();
	natlist = prop_dictionary_get(npf_dict, "translation");
	error = npf_mk_natlist(nset, natlist, errdict);
	if (error) {
		goto fail;
	}

	/* Tables. */
	tblset = npf_tableset_create();
	tables = prop_dictionary_get(npf_dict, "tables");
	error = npf_mk_tables(tblset, tables, errdict);
	if (error) {
		goto fail;
	}

	/* Rules and rule procedures. */
	rlset = npf_ruleset_create();
	rprocs = prop_dictionary_get(npf_dict, "rprocs");
	rules = prop_dictionary_get(npf_dict, "rules");
	error = npf_mk_rules(rlset, rules, rprocs, errdict);
	if (error) {
		goto fail;
	}

	flush = false;
	prop_dictionary_get_bool(npf_dict, "flush", &flush);

	/*
	 * Finally - reload ruleset, tableset and NAT policies.
	 * Operation will be performed as a single transaction.
	 */
	npf_reload(npf_dict, rlset, tblset, nset, flush);

	/* Turn on/off session tracking accordingly. */
	npf_session_tracking(!flush);

	/* Done.  Since data is consumed now, we shall not destroy it. */
	tblset = NULL;
	rlset = NULL;
	nset = NULL;
fail:
	/*
	 * Note: destroy rulesets first, to drop references to the tableset.
	 */
	KASSERT(error == 0 || (nset || rlset || tblset));
	if (nset) {
		npf_ruleset_destroy(nset);
	}
	if (rlset) {
		npf_ruleset_destroy(rlset);
	}
	if (tblset) {
		npf_tableset_destroy(tblset);
	}
	if (error) {
		prop_object_release(npf_dict);
	}

	/* Error report. */
	prop_dictionary_set_int32(errdict, "errno", error);
#ifndef _NPF_TESTING
	prop_dictionary_copyout_ioctl(pref, cmd, errdict);
#endif
	prop_object_release(errdict);
	return 0;
}