- Fix NPF config reload with dynamic rules present.

- Implement list and flush commands on a dynamic ruleset.
This commit is contained in:
rmind 2013-02-10 23:47:37 +00:00
parent 946e7a0ac0
commit 50c5afcad4
11 changed files with 221 additions and 40 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf.c,v 1.16 2013/02/09 03:35:33 rmind Exp $ */
/* $NetBSD: npf.c,v 1.17 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2010-2013 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.16 2013/02/09 03:35:33 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf.c,v 1.17 2013/02/10 23:47:37 rmind Exp $");
#include <sys/types.h>
#include <netinet/in_systm.h>
@ -320,6 +320,20 @@ npf_ruleset_remkey(int fd, const char *rname, const void *key, size_t len)
return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
}
int
npf_ruleset_flush(int fd, const char *rname)
{
prop_dictionary_t rldict;
rldict = prop_dictionary_create();
if (rldict == NULL) {
return ENOMEM;
}
prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_FLUSH);
return prop_dictionary_send_ioctl(rldict, fd, IOC_NPF_RULE);
}
/*
* _npf_ruleset_transform: transform the ruleset representing nested
* rules with lists into an array.
@ -569,6 +583,32 @@ _npf_rule_foreach(nl_config_t *ncf, nl_rule_callback_t func)
return _npf_rule_foreach1(ncf->ncf_rules_list, func);
}
int
_npf_ruleset_list(int fd, const char *rname, nl_config_t *ncf)
{
prop_dictionary_t rldict, ret;
int error;
rldict = prop_dictionary_create();
if (rldict == NULL) {
return ENOMEM;
}
prop_dictionary_set_cstring(rldict, "ruleset-name", rname);
prop_dictionary_set_uint32(rldict, "command", NPF_CMD_RULE_LIST);
error = prop_dictionary_sendrecv_ioctl(rldict, fd, IOC_NPF_RULE, &ret);
if (!error) {
prop_array_t rules;
rules = prop_dictionary_get(ret, "rules");
if (rules == NULL) {
return EINVAL;
}
prop_object_release(ncf->ncf_rules_list);
ncf->ncf_rules_list = rules;
}
return error;
}
pri_t
_npf_rule_getinfo(nl_rule_t *nrl, const char **rname, uint32_t *attr,
u_int *if_idx)

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf.h,v 1.13 2013/02/09 03:35:33 rmind Exp $ */
/* $NetBSD: npf.h,v 1.14 2013/02/10 23:47:38 rmind Exp $ */
/*-
* Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@ -82,6 +82,7 @@ int npf_config_flush(int);
int npf_ruleset_add(int, const char *, nl_rule_t *, uintptr_t *);
int npf_ruleset_remove(int, const char *, uintptr_t);
int npf_ruleset_remkey(int, const char *, const void *, size_t);
int npf_ruleset_flush(int, const char *);
nl_ext_t * npf_ext_construct(const char *name);
void npf_ext_param_u32(nl_ext_t *, const char *, uint32_t);
@ -121,6 +122,7 @@ int npf_sessions_recv(int, const char *);
void _npf_config_error(nl_config_t *, nl_error_t *);
void _npf_config_setsubmit(nl_config_t *, const char *);
int _npf_ruleset_list(int, const char *, nl_config_t *);
int _npf_rule_foreach(nl_config_t *, nl_rule_callback_t);
pri_t _npf_rule_getinfo(nl_rule_t *, const char **, uint32_t *,
u_int *);

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf.h,v 1.26 2013/02/09 03:35:31 rmind Exp $ */
/* $NetBSD: npf.h,v 1.27 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@ -235,7 +235,8 @@ bool npf_autounload_p(void);
#define NPF_CMD_RULE_INSERT 2
#define NPF_CMD_RULE_REMOVE 3
#define NPF_CMD_RULE_REMKEY 4
#define NPF_CMD_RULE_FLUSH 5
#define NPF_CMD_RULE_LIST 5
#define NPF_CMD_RULE_FLUSH 6
/*
* NPF ioctl(2): table commands and structures.

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_conf.c,v 1.1 2013/02/09 03:35:31 rmind Exp $ */
/* $NetBSD: npf_conf.c,v 1.2 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2013 The NetBSD Foundation, Inc.
@ -48,7 +48,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_conf.c,v 1.1 2013/02/09 03:35:31 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_conf.c,v 1.2 2013/02/10 23:47:37 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -185,6 +185,13 @@ npf_config_locked_p(void)
return mutex_owned(&npf_config_lock);
}
void
npf_config_sync(void)
{
KASSERT(npf_config_locked_p());
pserialize_perform(npf_config_psz);
}
/*
* Reader-side synchronisation routines.
*/

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_ctl.c,v 1.21 2013/02/09 03:35:31 rmind Exp $ */
/* $NetBSD: npf_ctl.c,v 1.22 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.21 2013/02/09 03:35:31 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_ctl.c,v 1.22 2013/02/10 23:47:37 rmind Exp $");
#include <sys/param.h>
#include <sys/conf.h>
@ -581,10 +581,7 @@ npfctl_rule(u_long cmd, void *data)
error = EINVAL;
break;
}
rl = npf_ruleset_remove(rlset, ruleset_name, (uintptr_t)id64);
if (rl == NULL) {
error = ENOENT;
}
error = npf_ruleset_remove(rlset, ruleset_name, (uintptr_t)id64);
break;
}
case NPF_CMD_RULE_REMKEY: {
@ -596,16 +593,27 @@ npfctl_rule(u_long cmd, void *data)
error = EINVAL;
break;
}
rl = npf_ruleset_remkey(rlset, ruleset_name, key, len);
if (rl == NULL) {
error = ENOENT;
}
error = npf_ruleset_remkey(rlset, ruleset_name, key, len);
break;
}
case NPF_CMD_RULE_LIST: {
retdict = npf_ruleset_list(rlset, ruleset_name);
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) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_impl.h,v 1.26 2013/02/09 03:35:32 rmind Exp $ */
/* $NetBSD: npf_impl.h,v 1.27 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@ -130,6 +130,7 @@ void npf_config_fini(void);
void npf_config_enter(void);
void npf_config_exit(void);
void npf_config_sync(void);
bool npf_config_locked_p(void);
int npf_config_read_enter(void);
void npf_config_read_exit(int);
@ -231,9 +232,12 @@ npf_rule_t * npf_ruleset_sharepm(npf_ruleset_t *, npf_natpolicy_t *);
void npf_ruleset_freealg(npf_ruleset_t *, npf_alg_t *);
int npf_ruleset_add(npf_ruleset_t *, const char *, npf_rule_t *);
npf_rule_t * npf_ruleset_remove(npf_ruleset_t *, const char *, uintptr_t);
npf_rule_t * npf_ruleset_remkey(npf_ruleset_t *, const char *,
int npf_ruleset_remove(npf_ruleset_t *, const char *, uintptr_t);
int npf_ruleset_remkey(npf_ruleset_t *, const char *,
const void *, size_t);
prop_dictionary_t npf_ruleset_list(npf_ruleset_t *, const char *);
int npf_ruleset_flush(npf_ruleset_t *, const char *);
void npf_ruleset_gc(npf_ruleset_t *);
npf_rule_t * npf_ruleset_inspect(npf_cache_t *, nbuf_t *,
const npf_ruleset_t *, const int, const int);

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_ruleset.c,v 1.17 2013/02/09 03:35:32 rmind Exp $ */
/* $NetBSD: npf_ruleset.c,v 1.18 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.17 2013/02/09 03:35:32 rmind Exp $");
__KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.18 2013/02/10 23:47:37 rmind Exp $");
#include <sys/param.h>
#include <sys/types.h>
@ -52,9 +52,14 @@ __KERNEL_RCSID(0, "$NetBSD: npf_ruleset.c,v 1.17 2013/02/09 03:35:32 rmind Exp $
#include "npf_impl.h"
struct npf_ruleset {
/* List of all rules and dynamic (i.e. named) rules. */
/*
* - List of all rules.
* - Dynamic (i.e. named) rules.
* - G/C list for convenience.
*/
LIST_HEAD(, npf_rule) rs_all;
LIST_HEAD(, npf_rule) rs_dynamic;
LIST_HEAD(, npf_rule) rs_gc;
/* Number of array slots and active rules. */
u_int rs_slots;
@ -95,6 +100,9 @@ struct npf_rule {
npf_rule_t * r_parent;
} /* C11 */;
/* Dictionary. */
prop_dictionary_t r_dict;
/* Rule name and all-list entry. */
char r_name[NPF_RULE_MAXNAMELEN];
LIST_ENTRY(npf_rule) r_aentry;
@ -143,6 +151,7 @@ npf_ruleset_destroy(npf_ruleset_t *rlset)
npf_rule_free(rl);
}
KASSERT(LIST_EMPTY(&rlset->rs_dynamic));
KASSERT(LIST_EMPTY(&rlset->rs_gc));
kmem_free(rlset, len);
}
@ -238,25 +247,26 @@ npf_ruleset_add(npf_ruleset_t *rlset, const char *rname, npf_rule_t *rl)
return 0;
}
npf_rule_t *
int
npf_ruleset_remove(npf_ruleset_t *rlset, const char *rname, uintptr_t id)
{
npf_rule_t *rg, *rl;
if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
return NULL;
return ENOENT;
}
TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
/* Compare ID. On match, remove and return. */
if ((uintptr_t)rl == id) {
npf_ruleset_unlink(rlset, rl);
LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
break;
}
}
return rl;
return 0;
}
npf_rule_t *
int
npf_ruleset_remkey(npf_ruleset_t *rlset, const char *rname,
const void *key, size_t len)
{
@ -265,17 +275,77 @@ npf_ruleset_remkey(npf_ruleset_t *rlset, const char *rname,
KASSERT(len && len <= NPF_RULE_MAXKEYLEN);
if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
return NULL;
return ENOENT;
}
/* Find the last in the list. */
TAILQ_FOREACH_REVERSE(rl, &rg->r_subset, npf_ruleq, r_entry) {
/* Compare the key. On match, remove and return. */
if (memcmp(rl->r_key, key, len) == 0) {
npf_ruleset_unlink(rlset, rl);
LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
break;
}
}
return rl;
return 0;
}
prop_dictionary_t
npf_ruleset_list(npf_ruleset_t *rlset, const char *rname)
{
prop_dictionary_t rldict;
prop_array_t rules;
npf_rule_t *rg, *rl;
if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
return NULL;
}
if ((rldict = prop_dictionary_create()) == NULL) {
return NULL;
}
if ((rules = prop_array_create()) == NULL) {
prop_object_release(rldict);
return NULL;
}
TAILQ_FOREACH(rl, &rg->r_subset, r_entry) {
if (rl->r_dict && !prop_array_add(rules, rl->r_dict)) {
prop_object_release(rldict);
return NULL;
}
}
if (!prop_dictionary_set(rldict, "rules", rules)) {
prop_object_release(rldict);
rldict = NULL;
}
prop_object_release(rules);
return rldict;
}
int
npf_ruleset_flush(npf_ruleset_t *rlset, const char *rname)
{
npf_rule_t *rg, *rl;
if ((rg = npf_ruleset_lookup(rlset, rname)) == NULL) {
return ENOENT;
}
while ((rl = TAILQ_FIRST(&rg->r_subset)) != NULL) {
npf_ruleset_unlink(rlset, rl);
LIST_INSERT_HEAD(&rlset->rs_gc, rl, r_aentry);
}
return 0;
}
void
npf_ruleset_gc(npf_ruleset_t *rlset)
{
npf_rule_t *rl;
while ((rl = LIST_FIRST(&rlset->rs_gc)) != NULL) {
LIST_REMOVE(rl, r_aentry);
npf_rule_free(rl);
}
}
/*
@ -284,17 +354,30 @@ npf_ruleset_remkey(npf_ruleset_t *rlset, const char *rname,
* => Active ruleset should be exclusively locked.
*/
void
npf_ruleset_reload(npf_ruleset_t *nrlset, npf_ruleset_t *arlset)
npf_ruleset_reload(npf_ruleset_t *rlset, npf_ruleset_t *arlset)
{
npf_rule_t *rl, *arl;
npf_rule_t *rl;
KASSERT(npf_config_locked_p());
LIST_FOREACH(rl, &nrlset->rs_dynamic, r_dentry) {
LIST_FOREACH(rl, &rlset->rs_dynamic, r_dentry) {
npf_rule_t *arl, *it;
if ((arl = npf_ruleset_lookup(arlset, rl->r_name)) == NULL) {
continue;
}
/*
* Copy the list-head structure and move the rules from the
* old ruleset to the new by reinserting to a new all-rules
* list. Note that the rules are still active and therefore
* accessible for inspection via the old ruleset.
*/
memcpy(&rl->r_subset, &arl->r_subset, sizeof(rl->r_subset));
TAILQ_FOREACH(it, &rl->r_subset, r_entry) {
LIST_REMOVE(rl, r_aentry);
LIST_INSERT_HEAD(&rlset->rs_all, rl, r_aentry);
}
}
}
@ -422,6 +505,11 @@ npf_rule_alloc(prop_dictionary_t rldict)
}
memcpy(rl->r_key, key, len);
}
if ((rl->r_attr & NPF_DYNAMIC_GROUP) == NPF_RULE_DYNAMIC) {
rl->r_dict = prop_dictionary_copy(rldict);
}
return rl;
}
@ -469,6 +557,10 @@ npf_rule_free(npf_rule_t *rl)
/* Free n-code. */
kmem_free(rl->r_code, rl->r_clen);
}
if (rl->r_dict) {
/* Destroy the dictionary. */
prop_object_release(rl->r_dict);
}
kmem_free(rl, sizeof(npf_rule_t));
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_build.c,v 1.18 2013/02/09 03:35:32 rmind Exp $ */
/* $NetBSD: npf_build.c,v 1.19 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2011-2013 The NetBSD Foundation, Inc.
@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_build.c,v 1.18 2013/02/09 03:35:32 rmind Exp $");
__RCSID("$NetBSD: npf_build.c,v 1.19 2013/02/10 23:47:37 rmind Exp $");
#include <sys/types.h>
#include <sys/ioctl.h>
@ -502,6 +502,7 @@ npfctl_build_rule(int attr, u_int if_idx, sa_family_t family,
{
nl_rule_t *rl;
attr |= (npf_conf ? 0 : NPF_RULE_DYNAMIC);
rl = npf_rule_create(NULL, attr, if_idx);
npfctl_build_ncode(rl, family, op, fopts, false);
if (rproc) {

View File

@ -1,4 +1,4 @@
/* $NetBSD: npf_disassemble.c,v 1.15 2013/02/09 03:35:32 rmind Exp $ */
/* $NetBSD: npf_disassemble.c,v 1.16 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2012 The NetBSD Foundation, Inc.
@ -35,7 +35,7 @@
* FIXME: config generation should be redesigned..
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npf_disassemble.c,v 1.15 2013/02/09 03:35:32 rmind Exp $");
__RCSID("$NetBSD: npf_disassemble.c,v 1.16 2013/02/10 23:47:37 rmind Exp $");
#include <stdio.h>
#include <stdlib.h>
@ -742,3 +742,18 @@ npfctl_config_show(int fd)
npf_config_destroy(ncf);
return error;
}
int
npfctl_ruleset_show(int fd, const char *ruleset_name)
{
nl_config_t *ncf;
int error;
ncf = npf_config_create();
if ((error = _npf_ruleset_list(fd, ruleset_name, ncf)) != 0) {
return error;
}
error = _npf_rule_foreach(ncf, npfctl_show_rule);
npf_config_destroy(ncf);
return error;
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: npfctl.c,v 1.29 2013/02/09 03:35:33 rmind Exp $ */
/* $NetBSD: npfctl.c,v 1.30 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: npfctl.c,v 1.29 2013/02/09 03:35:33 rmind Exp $");
__RCSID("$NetBSD: npfctl.c,v 1.30 2013/02/10 23:47:37 rmind Exp $");
#include <sys/ioctl.h>
#include <sys/stat.h>
@ -403,6 +403,8 @@ npfctl_rule(int fd, int argc, char **argv)
{ "rem", NPF_CMD_RULE_REMKEY },
{ "del", NPF_CMD_RULE_REMKEY },
{ "rem-id", NPF_CMD_RULE_REMOVE },
{ "list", NPF_CMD_RULE_LIST },
{ "flush", NPF_CMD_RULE_FLUSH },
{ NULL, 0 }
};
uint8_t key[NPF_RULE_MAXKEYLEN];
@ -419,7 +421,8 @@ npfctl_rule(int fd, int argc, char **argv)
}
}
if (!action || argc < 3) {
bool narg = action == NPF_CMD_RULE_LIST || action == NPF_CMD_RULE_FLUSH;
if (!action || (argc < 3 && !narg)) {
usage();
}
argc -= 2;
@ -441,6 +444,12 @@ npfctl_rule(int fd, int argc, char **argv)
rule_id = (uintptr_t)strtoull(argv[0], NULL, 16);
error = npf_ruleset_remove(fd, ruleset_name, rule_id);
break;
case NPF_CMD_RULE_LIST:
error = npfctl_ruleset_show(fd, ruleset_name);
break;
case NPF_CMD_RULE_FLUSH:
error = npf_ruleset_flush(fd, ruleset_name);
break;
default:
assert(false);
}

View File

@ -1,4 +1,4 @@
/* $NetBSD: npfctl.h,v 1.25 2013/02/09 03:35:33 rmind Exp $ */
/* $NetBSD: npfctl.h,v 1.26 2013/02/10 23:47:37 rmind Exp $ */
/*-
* Copyright (c) 2009-2013 The NetBSD Foundation, Inc.
@ -187,6 +187,8 @@ void npfctl_config_init(bool);
int npfctl_config_send(int, const char *);
nl_config_t * npfctl_config_ref(void);
int npfctl_config_show(int);
int npfctl_ruleset_show(int, const char *);
nl_rule_t * npfctl_rule_ref(void);
unsigned long npfctl_debug_addif(const char *);