version 1.12, 2014/08/11 01:54:12 |
version 1.12.8.2, 2017/03/20 06:57:50 |
|
|
* NPF extension and rule procedure interface. |
* NPF extension and rule procedure interface. |
*/ |
*/ |
|
|
|
#ifdef _KERNEL |
#include <sys/cdefs.h> |
#include <sys/cdefs.h> |
__KERNEL_RCSID(0, "$NetBSD"); |
__KERNEL_RCSID(0, "$NetBSD"); |
|
|
Line 43 __KERNEL_RCSID(0, "$NetBSD"); |
|
Line 44 __KERNEL_RCSID(0, "$NetBSD"); |
|
#include <sys/kmem.h> |
#include <sys/kmem.h> |
#include <sys/mutex.h> |
#include <sys/mutex.h> |
#include <sys/module.h> |
#include <sys/module.h> |
|
#endif |
|
|
#include "npf_impl.h" |
#include "npf_impl.h" |
|
|
Line 77 struct npf_rproc { |
|
Line 79 struct npf_rproc { |
|
LIST_ENTRY(npf_rproc) rp_entry; |
LIST_ENTRY(npf_rproc) rp_entry; |
}; |
}; |
|
|
static LIST_HEAD(, npf_ext) ext_list __cacheline_aligned; |
|
static kmutex_t ext_lock __cacheline_aligned; |
|
|
|
void |
void |
npf_ext_sysinit(void) |
npf_ext_init(npf_t *npf) |
{ |
{ |
mutex_init(&ext_lock, MUTEX_DEFAULT, IPL_NONE); |
mutex_init(&npf->ext_lock, MUTEX_DEFAULT, IPL_NONE); |
LIST_INIT(&ext_list); |
LIST_INIT(&npf->ext_list); |
} |
} |
|
|
void |
void |
npf_ext_sysfini(void) |
npf_ext_fini(npf_t *npf) |
{ |
{ |
KASSERT(LIST_EMPTY(&ext_list)); |
KASSERT(LIST_EMPTY(&npf->ext_list)); |
mutex_destroy(&ext_lock); |
mutex_destroy(&npf->ext_lock); |
} |
} |
|
|
/* |
/* |
Line 102 static const char npf_ext_prefix[] = "np |
|
Line 101 static const char npf_ext_prefix[] = "np |
|
#define NPF_EXT_PREFLEN (sizeof(npf_ext_prefix) - 1) |
#define NPF_EXT_PREFLEN (sizeof(npf_ext_prefix) - 1) |
|
|
static npf_ext_t * |
static npf_ext_t * |
npf_ext_lookup(const char *name, bool autoload) |
npf_ext_lookup(npf_t *npf, const char *name, bool autoload) |
{ |
{ |
npf_ext_t *ext; |
npf_ext_t *ext; |
char modname[RPROC_NAME_LEN + NPF_EXT_PREFLEN]; |
char modname[RPROC_NAME_LEN + NPF_EXT_PREFLEN]; |
int error; |
int error; |
|
|
KASSERT(mutex_owned(&ext_lock)); |
KASSERT(mutex_owned(&npf->ext_lock)); |
|
|
again: |
again: |
LIST_FOREACH(ext, &ext_list, ext_entry) |
LIST_FOREACH(ext, &npf->ext_list, ext_entry) |
if (strcmp(ext->ext_callname, name) == 0) |
if (strcmp(ext->ext_callname, name) == 0) |
break; |
break; |
|
|
if (ext != NULL || !autoload) |
if (ext != NULL || !autoload) |
return ext; |
return ext; |
|
|
mutex_exit(&ext_lock); |
mutex_exit(&npf->ext_lock); |
autoload = false; |
autoload = false; |
snprintf(modname, sizeof(modname), "%s%s", npf_ext_prefix, name); |
snprintf(modname, sizeof(modname), "%s%s", npf_ext_prefix, name); |
error = module_autoload(modname, MODULE_CLASS_MISC); |
error = module_autoload(modname, MODULE_CLASS_MISC); |
mutex_enter(&ext_lock); |
mutex_enter(&npf->ext_lock); |
|
|
if (error) |
if (error) |
return NULL; |
return NULL; |
|
|
} |
} |
|
|
void * |
void * |
npf_ext_register(const char *name, const npf_ext_ops_t *ops) |
npf_ext_register(npf_t *npf, const char *name, const npf_ext_ops_t *ops) |
{ |
{ |
npf_ext_t *ext; |
npf_ext_t *ext; |
|
|
Line 138 npf_ext_register(const char *name, const |
|
Line 137 npf_ext_register(const char *name, const |
|
strlcpy(ext->ext_callname, name, EXT_NAME_LEN); |
strlcpy(ext->ext_callname, name, EXT_NAME_LEN); |
ext->ext_ops = ops; |
ext->ext_ops = ops; |
|
|
mutex_enter(&ext_lock); |
mutex_enter(&npf->ext_lock); |
if (npf_ext_lookup(name, false)) { |
if (npf_ext_lookup(npf, name, false)) { |
mutex_exit(&ext_lock); |
mutex_exit(&npf->ext_lock); |
kmem_free(ext, sizeof(npf_ext_t)); |
kmem_free(ext, sizeof(npf_ext_t)); |
return NULL; |
return NULL; |
} |
} |
LIST_INSERT_HEAD(&ext_list, ext, ext_entry); |
LIST_INSERT_HEAD(&npf->ext_list, ext, ext_entry); |
mutex_exit(&ext_lock); |
mutex_exit(&npf->ext_lock); |
|
|
return (void *)ext; |
return (void *)ext; |
} |
} |
|
|
int |
int |
npf_ext_unregister(void *extid) |
npf_ext_unregister(npf_t *npf, void *extid) |
{ |
{ |
npf_ext_t *ext = extid; |
npf_ext_t *ext = extid; |
|
|
Line 162 npf_ext_unregister(void *extid) |
|
Line 161 npf_ext_unregister(void *extid) |
|
return EBUSY; |
return EBUSY; |
} |
} |
|
|
mutex_enter(&ext_lock); |
mutex_enter(&npf->ext_lock); |
if (ext->ext_refcnt) { |
if (ext->ext_refcnt) { |
mutex_exit(&ext_lock); |
mutex_exit(&npf->ext_lock); |
return EBUSY; |
return EBUSY; |
} |
} |
KASSERT(npf_ext_lookup(ext->ext_callname, false)); |
KASSERT(npf_ext_lookup(npf, ext->ext_callname, false)); |
LIST_REMOVE(ext, ext_entry); |
LIST_REMOVE(ext, ext_entry); |
mutex_exit(&ext_lock); |
mutex_exit(&npf->ext_lock); |
|
|
kmem_free(ext, sizeof(npf_ext_t)); |
kmem_free(ext, sizeof(npf_ext_t)); |
return 0; |
return 0; |
} |
} |
|
|
int |
int |
npf_ext_construct(const char *name, npf_rproc_t *rp, prop_dictionary_t params) |
npf_ext_construct(npf_t *npf, const char *name, |
|
npf_rproc_t *rp, prop_dictionary_t params) |
{ |
{ |
const npf_ext_ops_t *extops; |
const npf_ext_ops_t *extops; |
npf_ext_t *ext; |
npf_ext_t *ext; |
Line 187 npf_ext_construct(const char *name, npf_ |
|
Line 187 npf_ext_construct(const char *name, npf_ |
|
return ENOSPC; |
return ENOSPC; |
} |
} |
|
|
mutex_enter(&ext_lock); |
mutex_enter(&npf->ext_lock); |
ext = npf_ext_lookup(name, true); |
ext = npf_ext_lookup(npf, name, true); |
if (ext) { |
if (ext) { |
atomic_inc_uint(&ext->ext_refcnt); |
atomic_inc_uint(&ext->ext_refcnt); |
} |
} |
mutex_exit(&ext_lock); |
mutex_exit(&npf->ext_lock); |
|
|
if (!ext) { |
if (!ext) { |
return ENOENT; |
return ENOENT; |
Line 269 npf_rprocset_export(const npf_rprocset_t |
|
Line 269 npf_rprocset_export(const npf_rprocset_t |
|
|
|
LIST_FOREACH(rp, &rpset->rps_list, rp_entry) { |
LIST_FOREACH(rp, &rpset->rps_list, rp_entry) { |
rpdict = prop_dictionary_create(); |
rpdict = prop_dictionary_create(); |
|
prop_array_t extcalls = prop_array_create(); |
|
prop_dictionary_set_and_rel(rpdict, "extcalls", extcalls); |
prop_dictionary_set_cstring(rpdict, "name", rp->rp_name); |
prop_dictionary_set_cstring(rpdict, "name", rp->rp_name); |
prop_dictionary_set_uint32(rpdict, "flags", rp->rp_flags); |
prop_dictionary_set_uint32(rpdict, "flags", rp->rp_flags); |
prop_array_add(rprocs, rpdict); |
prop_array_add(rprocs, rpdict); |
Line 309 npf_rproc_acquire(npf_rproc_t *rp) |
|
Line 311 npf_rproc_acquire(npf_rproc_t *rp) |
|
} |
} |
|
|
/* |
/* |
|
* npf_rproc_getname: return the name of the given rproc |
|
*/ |
|
const char * |
|
npf_rproc_getname(const npf_rproc_t *rp) |
|
{ |
|
return rp->rp_name; |
|
} |
|
|
|
/* |
* npf_rproc_release: drop the reference count and destroy the rule |
* npf_rproc_release: drop the reference count and destroy the rule |
* procedure on the last reference. |
* procedure on the last reference. |
*/ |
*/ |
Line 347 npf_rproc_assign(npf_rproc_t *rp, void * |
|
Line 358 npf_rproc_assign(npf_rproc_t *rp, void * |
|
* => Reference on the rule procedure must be held. |
* => Reference on the rule procedure must be held. |
*/ |
*/ |
bool |
bool |
npf_rproc_run(npf_cache_t *npc, npf_rproc_t *rp, int *decision) |
npf_rproc_run(npf_cache_t *npc, npf_rproc_t *rp, const npf_match_info_t *mi, |
|
int *decision) |
{ |
{ |
const unsigned extcount = rp->rp_ext_count; |
const unsigned extcount = rp->rp_ext_count; |
|
|
Line 359 npf_rproc_run(npf_cache_t *npc, npf_rpro |
|
Line 371 npf_rproc_run(npf_cache_t *npc, npf_rpro |
|
const npf_ext_ops_t *extops = ext->ext_ops; |
const npf_ext_ops_t *extops = ext->ext_ops; |
|
|
KASSERT(ext->ext_refcnt > 0); |
KASSERT(ext->ext_refcnt > 0); |
if (!extops->proc(npc, rp->rp_ext_meta[i], decision)) { |
if (!extops->proc(npc, rp->rp_ext_meta[i], mi, decision)) { |
return false; |
return false; |
} |
} |
|
|