* Use modular opcode handling inside ipfw_ctl3() instead of static switch.
* Provide hints for subsystem initializers if they are called for the first/last time. * Convert every IP_FW3 opcode user to use new sopt API.
This commit is contained in:
parent
e822d9364e
commit
6b988f3a27
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/ipfw/; revision=271158
@ -2667,6 +2667,7 @@ ipfw_init(void)
|
||||
if (default_fw_tables > IPFW_TABLES_MAX)
|
||||
default_fw_tables = IPFW_TABLES_MAX;
|
||||
|
||||
ipfw_init_sopt_handler();
|
||||
ipfw_log_bpf(1); /* init */
|
||||
ipfw_iface_init();
|
||||
return (error);
|
||||
@ -2681,6 +2682,7 @@ ipfw_destroy(void)
|
||||
|
||||
ipfw_iface_destroy();
|
||||
ipfw_log_bpf(0); /* uninit */
|
||||
ipfw_destroy_sopt_handler();
|
||||
printf("IP firewall unloaded\n");
|
||||
}
|
||||
|
||||
@ -2691,12 +2693,14 @@ ipfw_destroy(void)
|
||||
static int
|
||||
vnet_ipfw_init(const void *unused)
|
||||
{
|
||||
int error;
|
||||
int error, first;
|
||||
struct ip_fw *rule = NULL;
|
||||
struct ip_fw_chain *chain;
|
||||
|
||||
chain = &V_layer3_chain;
|
||||
|
||||
first = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
|
||||
|
||||
/* First set up some values that are compile time options */
|
||||
V_autoinc_step = 100; /* bounded to 1..1000 in add_rule() */
|
||||
V_fw_deny_unknown_exthdrs = 1;
|
||||
@ -2718,7 +2722,7 @@ vnet_ipfw_init(const void *unused)
|
||||
|
||||
/* Set initial number of tables */
|
||||
V_fw_tables_max = default_fw_tables;
|
||||
error = ipfw_init_tables(chain);
|
||||
error = ipfw_init_tables(chain, first);
|
||||
if (error) {
|
||||
printf("ipfw2: setting up tables failed\n");
|
||||
free(chain->map, M_IPFW);
|
||||
@ -2771,7 +2775,7 @@ vnet_ipfw_uninit(const void *unused)
|
||||
{
|
||||
struct ip_fw *reap;
|
||||
struct ip_fw_chain *chain = &V_layer3_chain;
|
||||
int i;
|
||||
int i, last;
|
||||
|
||||
V_ipfw_vnet_ready = 0; /* tell new callers to go away */
|
||||
/*
|
||||
@ -2781,6 +2785,9 @@ vnet_ipfw_uninit(const void *unused)
|
||||
*/
|
||||
(void)ipfw_attach_hooks(0 /* detach */);
|
||||
V_ip_fw_ctl_ptr = NULL;
|
||||
|
||||
last = IS_DEFAULT_VNET(curvnet) ? 1 : 0;
|
||||
|
||||
IPFW_UH_WLOCK(chain);
|
||||
IPFW_UH_WUNLOCK(chain);
|
||||
IPFW_UH_WLOCK(chain);
|
||||
@ -2797,7 +2804,7 @@ vnet_ipfw_uninit(const void *unused)
|
||||
ipfw_destroy_skipto_cache(chain);
|
||||
IPFW_WUNLOCK(chain);
|
||||
IPFW_UH_WUNLOCK(chain);
|
||||
ipfw_destroy_tables(chain);
|
||||
ipfw_destroy_tables(chain, last);
|
||||
if (reap != NULL)
|
||||
ipfw_reap_rules(reap);
|
||||
vnet_ipfw_iface_destroy(chain);
|
||||
|
@ -65,6 +65,12 @@ static void handle_ifdetach(struct ip_fw_chain *ch, struct ipfw_iface *iif,
|
||||
uint16_t ifindex);
|
||||
static void handle_ifattach(struct ip_fw_chain *ch, struct ipfw_iface *iif,
|
||||
uint16_t ifindex);
|
||||
static int list_ifaces(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
static struct ipfw_sopt_handler scodes[] = {
|
||||
{ IP_FW_XIFLIST, 0, HDIR_GET, list_ifaces },
|
||||
};
|
||||
|
||||
/*
|
||||
* FreeBSD Kernel interface.
|
||||
@ -200,6 +206,7 @@ ipfw_iface_init()
|
||||
{
|
||||
|
||||
mtx_init(&vnet_mtx, "IPFW ifhandler mtx", NULL, MTX_DEF);
|
||||
IPFW_ADD_SOPT_HANDLER(1, scodes);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -211,6 +218,7 @@ void
|
||||
ipfw_iface_destroy()
|
||||
{
|
||||
|
||||
IPFW_DEL_SOPT_HANDLER(1, scodes);
|
||||
mtx_destroy(&vnet_mtx);
|
||||
}
|
||||
|
||||
@ -483,8 +491,8 @@ export_iface_internal(struct namedobj_instance *ii, struct named_object *no,
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_list_ifaces(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
list_ifaces(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct namedobj_instance *ii;
|
||||
|
@ -520,8 +520,6 @@ int ipfw_iface_ref(struct ip_fw_chain *ch, char *name,
|
||||
void ipfw_iface_unref(struct ip_fw_chain *ch, struct ipfw_ifc *ic);
|
||||
void ipfw_iface_add_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic);
|
||||
void ipfw_iface_del_notify(struct ip_fw_chain *ch, struct ipfw_ifc *ic);
|
||||
int ipfw_list_ifaces(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
/* In ip_fw_sockopt.c */
|
||||
void ipfw_init_skipto_cache(struct ip_fw_chain *chain);
|
||||
@ -537,8 +535,35 @@ void ipfw_destroy_counters(void);
|
||||
struct ip_fw *ipfw_alloc_rule(struct ip_fw_chain *chain, size_t rulesize);
|
||||
int ipfw_match_range(struct ip_fw *rule, ipfw_range_tlv *rt);
|
||||
|
||||
typedef int (sopt_handler_f)(struct ip_fw_chain *ch,
|
||||
ip_fw3_opheader *op3, struct sockopt_data *sd);
|
||||
struct ipfw_sopt_handler {
|
||||
uint16_t opcode;
|
||||
uint8_t version;
|
||||
uint8_t dir;
|
||||
sopt_handler_f *handler;
|
||||
uint64_t refcnt;
|
||||
};
|
||||
#define HDIR_SET 0x01 /* Handler is used to set some data */
|
||||
#define HDIR_GET 0x02 /* Handler is used to retrieve data */
|
||||
#define HDIR_BOTH HDIR_GET|HDIR_SET
|
||||
|
||||
void ipfw_init_sopt_handler(void);
|
||||
void ipfw_destroy_sopt_handler(void);
|
||||
void ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count);
|
||||
int ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count);
|
||||
caddr_t ipfw_get_sopt_space(struct sockopt_data *sd, size_t needed);
|
||||
caddr_t ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed);
|
||||
#define IPFW_ADD_SOPT_HANDLER(f, c) do { \
|
||||
if ((f) != 0) \
|
||||
ipfw_add_sopt_handler(c, \
|
||||
sizeof(c) / sizeof(c[0])); \
|
||||
} while(0)
|
||||
#define IPFW_DEL_SOPT_HANDLER(l, c) do { \
|
||||
if ((l) != 0) \
|
||||
ipfw_del_sopt_handler(c, \
|
||||
sizeof(c) / sizeof(c[0])); \
|
||||
} while(0)
|
||||
|
||||
typedef void (objhash_cb_t)(struct namedobj_instance *ni, struct named_object *,
|
||||
void *arg);
|
||||
@ -580,10 +605,10 @@ int ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
|
||||
uint32_t *val);
|
||||
int ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
|
||||
void *paddr, uint32_t *val);
|
||||
int ipfw_init_tables(struct ip_fw_chain *ch);
|
||||
int ipfw_init_tables(struct ip_fw_chain *ch, int first);
|
||||
int ipfw_resize_tables(struct ip_fw_chain *ch, unsigned int ntables);
|
||||
int ipfw_switch_tables_namespace(struct ip_fw_chain *ch, unsigned int nsets);
|
||||
void ipfw_destroy_tables(struct ip_fw_chain *ch);
|
||||
void ipfw_destroy_tables(struct ip_fw_chain *ch, int last);
|
||||
|
||||
/* In ip_fw_nat.c -- XXX to be moved to ip_var.h */
|
||||
|
||||
|
@ -98,9 +98,47 @@ static uint32_t objhash_hash_name(struct namedobj_instance *ni, void *key,
|
||||
static uint32_t objhash_hash_idx(struct namedobj_instance *ni, uint32_t val);
|
||||
static int objhash_cmp_name(struct named_object *no, void *name, uint32_t set);
|
||||
|
||||
MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
|
||||
|
||||
static int dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int del_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int clear_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int move_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int manage_sets(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
/* ctl3 handler data */
|
||||
struct mtx ctl3_lock;
|
||||
#define CTL3_LOCK_INIT() mtx_init(&ctl3_lock, "ctl3_lock", NULL, MTX_DEF)
|
||||
#define CTL3_LOCK_DESTROY() mtx_destroy(&ctl3_lock)
|
||||
#define CTL3_LOCK() mtx_lock(&ctl3_lock)
|
||||
#define CTL3_UNLOCK() mtx_unlock(&ctl3_lock)
|
||||
|
||||
static struct ipfw_sopt_handler *ctl3_handlers;
|
||||
static size_t ctl3_hsize;
|
||||
static uint64_t ctl3_refct, ctl3_gencnt;
|
||||
#define CTL3_SMALLBUF 4096 /* small page-size write buffer */
|
||||
#define CTL3_LARGEBUF 16 * 1024 * 1024 /* handle large rulesets */
|
||||
|
||||
static int ipfw_flush_sopt_data(struct sockopt_data *sd);
|
||||
|
||||
MALLOC_DEFINE(M_IPFW, "IpFw/IpAcct", "IpFw/IpAcct chain's");
|
||||
static struct ipfw_sopt_handler scodes[] = {
|
||||
{ IP_FW_XGET, 0, HDIR_GET, dump_config },
|
||||
{ IP_FW_XADD, 0, HDIR_BOTH, add_rules },
|
||||
{ IP_FW_XDEL, 0, HDIR_BOTH, del_rules },
|
||||
{ IP_FW_XZERO, 0, HDIR_SET, clear_rules },
|
||||
{ IP_FW_XRESETLOG, 0, HDIR_SET, clear_rules },
|
||||
{ IP_FW_XMOVE, 0, HDIR_SET, move_rules },
|
||||
{ IP_FW_SET_SWAP, 0, HDIR_SET, manage_sets },
|
||||
{ IP_FW_SET_MOVE, 0, HDIR_SET, manage_sets },
|
||||
{ IP_FW_SET_ENABLE, 0, HDIR_SET, manage_sets },
|
||||
};
|
||||
|
||||
/*
|
||||
* static variables followed by global ones
|
||||
@ -2027,11 +2065,6 @@ dump_config(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
return (error);
|
||||
}
|
||||
|
||||
#define IP_FW3_OPLENGTH(x) ((x)->sopt_valsize - sizeof(ip_fw3_opheader))
|
||||
#define IP_FW3_WRITEBUF 4096 /* small page-size write buffer */
|
||||
#define IP_FW3_READBUF 16 * 1024 * 1024 /* handle large rulesets */
|
||||
|
||||
|
||||
static int
|
||||
check_object_name(ipfw_obj_ntlv *ntlv)
|
||||
{
|
||||
@ -2085,9 +2118,6 @@ add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
struct rule_check_info rci, *ci, *cbuf;
|
||||
int i, rsize;
|
||||
|
||||
if (sd->valsize > IP_FW3_READBUF)
|
||||
return (EINVAL);
|
||||
|
||||
op3 = (ip_fw3_opheader *)ipfw_get_sopt_space(sd, sd->valsize);
|
||||
ctlv = (ipfw_obj_ctlv *)(op3 + 1);
|
||||
|
||||
@ -2251,6 +2281,189 @@ add_rules(struct ip_fw_chain *chain, ip_fw3_opheader *op3,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Compares two sopt handlers (code, version and handler ptr).
|
||||
* Used both as qsort() and bsearch().
|
||||
* Does not compare handler for latter case.
|
||||
*
|
||||
* Returns 0 if match is found.
|
||||
*/
|
||||
static int
|
||||
compare_sh(const void *_a, const void *_b)
|
||||
{
|
||||
struct ipfw_sopt_handler *a, *b;
|
||||
|
||||
a = (struct ipfw_sopt_handler *)_a;
|
||||
b = (struct ipfw_sopt_handler *)_b;
|
||||
|
||||
if (a->opcode < b->opcode)
|
||||
return (-1);
|
||||
else if (a->opcode > b->opcode)
|
||||
return (1);
|
||||
|
||||
if (a->version < b->version)
|
||||
return (-1);
|
||||
else if (a->version > b->version)
|
||||
return (1);
|
||||
|
||||
/* bsearch helper */
|
||||
if (a->handler == NULL)
|
||||
return (0);
|
||||
|
||||
if ((uintptr_t)a->handler < (uintptr_t)b->handler)
|
||||
return (-1);
|
||||
else if ((uintptr_t)b->handler > (uintptr_t)b->handler)
|
||||
return (1);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Finds sopt handler based on @code and @version.
|
||||
*
|
||||
* Returns pointer to handler or NULL.
|
||||
*/
|
||||
static struct ipfw_sopt_handler *
|
||||
find_sh(uint16_t code, uint8_t version, void *handler)
|
||||
{
|
||||
struct ipfw_sopt_handler *sh, h;
|
||||
|
||||
memset(&h, 0, sizeof(h));
|
||||
h.opcode = code;
|
||||
h.version = version;
|
||||
h.handler = handler;
|
||||
|
||||
sh = (struct ipfw_sopt_handler *)bsearch(&h, ctl3_handlers,
|
||||
ctl3_hsize, sizeof(h), compare_sh);
|
||||
|
||||
return (sh);
|
||||
}
|
||||
|
||||
static int
|
||||
find_ref_sh(uint16_t opcode, uint8_t version, struct ipfw_sopt_handler *psh)
|
||||
{
|
||||
struct ipfw_sopt_handler *sh;
|
||||
|
||||
CTL3_LOCK();
|
||||
if ((sh = find_sh(opcode, version, NULL)) == NULL) {
|
||||
CTL3_UNLOCK();
|
||||
printf("ipfw: ipfw_ctl3 invalid option %d""v""%d\n",
|
||||
opcode, version);
|
||||
return (EINVAL);
|
||||
}
|
||||
sh->refcnt++;
|
||||
ctl3_refct++;
|
||||
/* Copy handler data to requested buffer */
|
||||
*psh = *sh;
|
||||
CTL3_UNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
find_unref_sh(struct ipfw_sopt_handler *psh)
|
||||
{
|
||||
struct ipfw_sopt_handler *sh;
|
||||
|
||||
CTL3_LOCK();
|
||||
sh = find_sh(psh->opcode, psh->version, NULL);
|
||||
KASSERT(sh != NULL, ("ctl3 handler disappeared"));
|
||||
sh->refcnt--;
|
||||
ctl3_refct--;
|
||||
CTL3_UNLOCK();
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_init_sopt_handler()
|
||||
{
|
||||
|
||||
CTL3_LOCK_INIT();
|
||||
IPFW_ADD_SOPT_HANDLER(1, scodes);
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_destroy_sopt_handler()
|
||||
{
|
||||
|
||||
IPFW_DEL_SOPT_HANDLER(1, scodes);
|
||||
CTL3_LOCK_DESTROY();
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds one or more sockopt handlers to the global array.
|
||||
* Function may sleep.
|
||||
*/
|
||||
void
|
||||
ipfw_add_sopt_handler(struct ipfw_sopt_handler *sh, size_t count)
|
||||
{
|
||||
size_t sz;
|
||||
struct ipfw_sopt_handler *tmp;
|
||||
|
||||
CTL3_LOCK();
|
||||
|
||||
for (;;) {
|
||||
sz = ctl3_hsize + count;
|
||||
CTL3_UNLOCK();
|
||||
tmp = malloc(sizeof(*sh) * sz, M_IPFW, M_WAITOK | M_ZERO);
|
||||
CTL3_LOCK();
|
||||
if (ctl3_hsize + count <= sz)
|
||||
break;
|
||||
|
||||
/* Retry */
|
||||
free(tmp, M_IPFW);
|
||||
}
|
||||
|
||||
/* Merge old & new arrays */
|
||||
sz = ctl3_hsize + count;
|
||||
memcpy(tmp, ctl3_handlers, ctl3_hsize * sizeof(*sh));
|
||||
memcpy(&tmp[ctl3_hsize], sh, count * sizeof(*sh));
|
||||
qsort(tmp, sz, sizeof(*sh), compare_sh);
|
||||
/* Switch new and free old */
|
||||
if (ctl3_handlers != NULL)
|
||||
free(ctl3_handlers, M_IPFW);
|
||||
ctl3_handlers = tmp;
|
||||
ctl3_hsize = sz;
|
||||
ctl3_gencnt++;
|
||||
|
||||
CTL3_UNLOCK();
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes one or more sockopt handlers from the global array.
|
||||
*/
|
||||
int
|
||||
ipfw_del_sopt_handler(struct ipfw_sopt_handler *sh, size_t count)
|
||||
{
|
||||
size_t sz;
|
||||
struct ipfw_sopt_handler *tmp, *h;
|
||||
int i;
|
||||
|
||||
CTL3_LOCK();
|
||||
|
||||
for (i = 0; i < count; i++) {
|
||||
tmp = &sh[i];
|
||||
h = find_sh(tmp->opcode, tmp->version, tmp->handler);
|
||||
if (h == NULL)
|
||||
continue;
|
||||
|
||||
sz = (ctl3_handlers + ctl3_hsize - (h + 1)) * sizeof(*h);
|
||||
memmove(h, h + 1, sz);
|
||||
ctl3_hsize--;
|
||||
}
|
||||
|
||||
if (ctl3_hsize == 0) {
|
||||
if (ctl3_handlers != NULL)
|
||||
free(ctl3_handlers, M_IPFW);
|
||||
ctl3_handlers = NULL;
|
||||
}
|
||||
|
||||
ctl3_gencnt++;
|
||||
|
||||
CTL3_UNLOCK();
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes data accumulated in @sd to sockopt buffer.
|
||||
* Zeroes internal @sd buffer.
|
||||
@ -2341,12 +2554,12 @@ ipfw_get_sopt_header(struct sockopt_data *sd, size_t needed)
|
||||
int
|
||||
ipfw_ctl3(struct sockopt *sopt)
|
||||
{
|
||||
int error, ctype;
|
||||
size_t bsize_max, size, valsize;
|
||||
int error;
|
||||
size_t size, valsize;
|
||||
struct ip_fw_chain *chain;
|
||||
uint32_t opt;
|
||||
char xbuf[256];
|
||||
struct sockopt_data sdata;
|
||||
struct ipfw_sopt_handler h;
|
||||
ip_fw3_opheader *op3 = NULL;
|
||||
|
||||
error = priv_check(sopt->sopt_td, PRIV_NETINET_IPFW);
|
||||
@ -2367,52 +2580,55 @@ ipfw_ctl3(struct sockopt *sopt)
|
||||
error = sooptcopyin(sopt, op3, sizeof(*op3), sizeof(*op3));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
opt = op3->opcode;
|
||||
sopt->sopt_valsize = valsize;
|
||||
|
||||
/*
|
||||
* Determine opcode type/buffer size:
|
||||
* use on-stack xbuf for short request,
|
||||
* allocate sliding-window buf for data export or
|
||||
* contigious buffer for special ops.
|
||||
* Find and reference command.
|
||||
*/
|
||||
ctype = (sopt->sopt_dir == SOPT_GET) ? SOPT_GET : SOPT_SET;
|
||||
switch (opt) {
|
||||
case IP_FW_XADD:
|
||||
case IP_FW_XDEL:
|
||||
case IP_FW_TABLE_XADD:
|
||||
case IP_FW_TABLE_XDEL:
|
||||
ctype = SOPT_SET;
|
||||
bsize_max = IP_FW3_READBUF;
|
||||
break;
|
||||
default:
|
||||
bsize_max = IP_FW3_WRITEBUF;
|
||||
}
|
||||
error = find_ref_sh(op3->opcode, op3->version, &h);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
/*
|
||||
* Disallow modifications in really-really secure mode, but still allow
|
||||
* the logging counters to be reset.
|
||||
*/
|
||||
if (ctype == SOPT_SET && opt != IP_FW_XRESETLOG) {
|
||||
if ((h.dir & HDIR_SET) != 0 && h.opcode != IP_FW_XRESETLOG) {
|
||||
error = securelevel_ge(sopt->sopt_td->td_ucred, 3);
|
||||
if (error != 0)
|
||||
if (error != 0) {
|
||||
find_unref_sh(&h);
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in sockopt_data structure that may be useful for
|
||||
* IP_FW3 get requests.
|
||||
*/
|
||||
|
||||
if (valsize <= sizeof(xbuf)) {
|
||||
/* use on-stack buffer */
|
||||
sdata.kbuf = xbuf;
|
||||
sdata.ksize = sizeof(xbuf);
|
||||
sdata.kavail = valsize;
|
||||
} else {
|
||||
if (valsize < bsize_max)
|
||||
|
||||
/*
|
||||
* Determine opcode type/buffer size:
|
||||
* allocate sliding-window buf for data export or
|
||||
* contigious buffer for special ops.
|
||||
*/
|
||||
if ((h.dir & HDIR_SET) != 0) {
|
||||
/* Set request. Allocate contigous buffer. */
|
||||
if (valsize > CTL3_LARGEBUF) {
|
||||
find_unref_sh(&h);
|
||||
return (EFBIG);
|
||||
}
|
||||
|
||||
size = valsize;
|
||||
else
|
||||
size = bsize_max;
|
||||
} else {
|
||||
/* Get request. Allocate sliding window buffer */
|
||||
size = (valsize<CTL3_SMALLBUF) ? valsize:CTL3_SMALLBUF;
|
||||
}
|
||||
|
||||
sdata.kbuf = malloc(size, M_TEMP, M_WAITOK | M_ZERO);
|
||||
sdata.ksize = size;
|
||||
@ -2433,95 +2649,10 @@ ipfw_ctl3(struct sockopt *sopt)
|
||||
sizeof(ip_fw3_opheader))) != 0)
|
||||
return (error);
|
||||
op3 = (ip_fw3_opheader *)sdata.kbuf;
|
||||
opt = op3->opcode;
|
||||
|
||||
switch (opt) {
|
||||
case IP_FW_XGET:
|
||||
error = dump_config(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_XADD:
|
||||
error = add_rules(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_XDEL:
|
||||
error = del_rules(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_XZERO:
|
||||
case IP_FW_XRESETLOG:
|
||||
error = clear_rules(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_XMOVE:
|
||||
error = move_rules(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_SET_SWAP:
|
||||
case IP_FW_SET_MOVE:
|
||||
case IP_FW_SET_ENABLE:
|
||||
error = manage_sets(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_XIFLIST:
|
||||
error = ipfw_list_ifaces(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
/*--- TABLE opcodes ---*/
|
||||
case IP_FW_TABLE_XCREATE:
|
||||
error = ipfw_create_table(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XDESTROY:
|
||||
case IP_FW_TABLE_XFLUSH:
|
||||
error = ipfw_flush_table(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XMODIFY:
|
||||
error = ipfw_modify_table(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XINFO:
|
||||
error = ipfw_describe_table(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLES_XLIST:
|
||||
error = ipfw_list_tables(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XLIST:
|
||||
error = ipfw_dump_table(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XADD:
|
||||
case IP_FW_TABLE_XDEL:
|
||||
error = ipfw_manage_table_ent(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XFIND:
|
||||
error = ipfw_find_table_entry(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XSWAP:
|
||||
error = ipfw_swap_table(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLES_ALIST:
|
||||
error = ipfw_list_table_algo(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_VLIST:
|
||||
error = ipfw_list_table_values(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
case IP_FW_TABLE_XGETSIZE:
|
||||
error = ipfw_get_table_size(chain, op3, &sdata);
|
||||
break;
|
||||
|
||||
default:
|
||||
printf("ipfw: ipfw_ctl3 invalid option %d\n", opt);
|
||||
error = EINVAL;
|
||||
}
|
||||
/* Finally, run handler */
|
||||
error = h.handler(chain, op3, &sdata);
|
||||
find_unref_sh(&h);
|
||||
|
||||
/* Flush state and free buffers */
|
||||
if (error == 0)
|
||||
|
@ -107,12 +107,6 @@ static void export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
|
||||
static int dump_table_tentry(void *e, void *arg);
|
||||
static int dump_table_xentry(void *e, void *arg);
|
||||
|
||||
static int ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd);
|
||||
static int ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd);
|
||||
static int ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
static int swap_tables(struct ip_fw_chain *ch, struct tid_info *a,
|
||||
struct tid_info *b);
|
||||
|
||||
@ -886,30 +880,6 @@ check_table_space(struct ip_fw_chain *ch, struct tableop_state *ts,
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Selects appropriate table operation handler
|
||||
* depending on opcode version.
|
||||
*/
|
||||
int
|
||||
ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (op3->version) {
|
||||
case 0:
|
||||
error = ipfw_manage_table_ent_v0(ch, op3, sd);
|
||||
break;
|
||||
case 1:
|
||||
error = ipfw_manage_table_ent_v1(ch, op3, sd);
|
||||
break;
|
||||
default:
|
||||
error = ENOTSUP;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds or deletes record in table.
|
||||
* Data layout (v0):
|
||||
@ -918,7 +888,7 @@ ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int
|
||||
ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
ipfw_table_xentry *xent;
|
||||
@ -975,7 +945,7 @@ ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int
|
||||
ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
ipfw_obj_tentry *tent, *ptent;
|
||||
@ -1095,8 +1065,8 @@ ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
ipfw_obj_tentry *tent;
|
||||
@ -1163,8 +1133,8 @@ ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
flush_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
int error;
|
||||
@ -1323,8 +1293,8 @@ flush_table(struct ip_fw_chain *ch, struct tid_info *ti)
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_swap_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
swap_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
int error;
|
||||
@ -1508,64 +1478,6 @@ destroy_table(struct ip_fw_chain *ch, struct tid_info *ti)
|
||||
return (0);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_table_locked(struct namedobj_instance *ni, struct named_object *no,
|
||||
void *arg)
|
||||
{
|
||||
|
||||
unlink_table((struct ip_fw_chain *)arg, (struct table_config *)no);
|
||||
if (ipfw_objhash_free_idx(ni, no->kidx) != 0)
|
||||
printf("Error unlinking kidx %d from table %s\n",
|
||||
no->kidx, no->name);
|
||||
free_table_config(ni, (struct table_config *)no);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shuts tables module down.
|
||||
*/
|
||||
void
|
||||
ipfw_destroy_tables(struct ip_fw_chain *ch)
|
||||
{
|
||||
|
||||
/* Remove all tables from working set */
|
||||
IPFW_UH_WLOCK(ch);
|
||||
IPFW_WLOCK(ch);
|
||||
ipfw_objhash_foreach(CHAIN_TO_NI(ch), destroy_table_locked, ch);
|
||||
IPFW_WUNLOCK(ch);
|
||||
IPFW_UH_WUNLOCK(ch);
|
||||
|
||||
/* Free pointers itself */
|
||||
free(ch->tablestate, M_IPFW);
|
||||
|
||||
ipfw_table_value_destroy(ch);
|
||||
ipfw_table_algo_destroy(ch);
|
||||
|
||||
ipfw_objhash_destroy(CHAIN_TO_NI(ch));
|
||||
free(CHAIN_TO_TCFG(ch), M_IPFW);
|
||||
}
|
||||
|
||||
/*
|
||||
* Starts tables module.
|
||||
*/
|
||||
int
|
||||
ipfw_init_tables(struct ip_fw_chain *ch)
|
||||
{
|
||||
struct tables_config *tcfg;
|
||||
|
||||
/* Allocate pointers */
|
||||
ch->tablestate = malloc(V_fw_tables_max * sizeof(struct table_info),
|
||||
M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
tcfg = malloc(sizeof(struct tables_config), M_IPFW, M_WAITOK | M_ZERO);
|
||||
tcfg->namehash = ipfw_objhash_create(V_fw_tables_max);
|
||||
ch->tblcfg = tcfg;
|
||||
|
||||
ipfw_table_value_init(ch);
|
||||
ipfw_table_algo_init(ch);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Grow tables index.
|
||||
*
|
||||
@ -1753,8 +1665,8 @@ ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_list_tables(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
list_tables(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_lheader *olh;
|
||||
@ -1781,8 +1693,8 @@ ipfw_list_tables(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
*
|
||||
* Returns 0 on success.
|
||||
*/
|
||||
int
|
||||
ipfw_describe_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
describe_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_header *oh;
|
||||
@ -1816,8 +1728,8 @@ ipfw_describe_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_header *oh;
|
||||
@ -1873,8 +1785,8 @@ ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_header *oh;
|
||||
@ -2243,26 +2155,6 @@ export_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh,
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
ipfw_dump_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
int error;
|
||||
|
||||
switch (op3->version) {
|
||||
case 0:
|
||||
error = ipfw_dump_table_v0(ch, sd);
|
||||
break;
|
||||
case 1:
|
||||
error = ipfw_dump_table_v1(ch, sd);
|
||||
break;
|
||||
default:
|
||||
error = ENOTSUP;
|
||||
}
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Dumps all table data
|
||||
* Data layout (v1)(current):
|
||||
@ -2272,7 +2164,8 @@ ipfw_dump_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int
|
||||
ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd)
|
||||
dump_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_header *oh;
|
||||
ipfw_xtable_info *i;
|
||||
@ -2335,7 +2228,8 @@ ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd)
|
||||
* Returns 0 on success
|
||||
*/
|
||||
static int
|
||||
ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd)
|
||||
dump_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
ipfw_xtable *xtbl;
|
||||
struct tid_info ti;
|
||||
@ -2394,8 +2288,8 @@ ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd)
|
||||
/*
|
||||
* Legacy function to retrieve number of items in table.
|
||||
*/
|
||||
int
|
||||
ipfw_get_table_size(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
get_table_size(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
uint32_t *tbl;
|
||||
@ -2800,8 +2694,8 @@ ipfw_del_table_algo(struct ip_fw_chain *ch, int idx)
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_list_table_algo(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
list_table_algo(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_lheader *olh;
|
||||
@ -3666,3 +3560,85 @@ ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
|
||||
return (error);
|
||||
}
|
||||
|
||||
static struct ipfw_sopt_handler scodes[] = {
|
||||
{ IP_FW_TABLE_XCREATE, 0, HDIR_SET, create_table },
|
||||
{ IP_FW_TABLE_XDESTROY, 0, HDIR_SET, flush_table_v0 },
|
||||
{ IP_FW_TABLE_XFLUSH, 0, HDIR_SET, flush_table_v0 },
|
||||
{ IP_FW_TABLE_XMODIFY, 0, HDIR_BOTH, modify_table },
|
||||
{ IP_FW_TABLE_XINFO, 0, HDIR_GET, describe_table },
|
||||
{ IP_FW_TABLES_XLIST, 0, HDIR_GET, list_tables },
|
||||
{ IP_FW_TABLE_XLIST, 0, HDIR_GET, dump_table_v0 },
|
||||
{ IP_FW_TABLE_XLIST, 1, HDIR_GET, dump_table_v1 },
|
||||
{ IP_FW_TABLE_XADD, 0, HDIR_BOTH, manage_table_ent_v0 },
|
||||
{ IP_FW_TABLE_XADD, 1, HDIR_BOTH, manage_table_ent_v1 },
|
||||
{ IP_FW_TABLE_XDEL, 0, HDIR_BOTH, manage_table_ent_v0 },
|
||||
{ IP_FW_TABLE_XDEL, 1, HDIR_BOTH, manage_table_ent_v1 },
|
||||
{ IP_FW_TABLE_XFIND, 0, HDIR_GET, find_table_entry },
|
||||
{ IP_FW_TABLE_XSWAP, 0, HDIR_SET, swap_table },
|
||||
{ IP_FW_TABLES_ALIST, 0, HDIR_GET, list_table_algo },
|
||||
{ IP_FW_TABLE_XGETSIZE, 0, HDIR_GET, get_table_size },
|
||||
};
|
||||
|
||||
static void
|
||||
destroy_table_locked(struct namedobj_instance *ni, struct named_object *no,
|
||||
void *arg)
|
||||
{
|
||||
|
||||
unlink_table((struct ip_fw_chain *)arg, (struct table_config *)no);
|
||||
if (ipfw_objhash_free_idx(ni, no->kidx) != 0)
|
||||
printf("Error unlinking kidx %d from table %s\n",
|
||||
no->kidx, no->name);
|
||||
free_table_config(ni, (struct table_config *)no);
|
||||
}
|
||||
|
||||
/*
|
||||
* Shuts tables module down.
|
||||
*/
|
||||
void
|
||||
ipfw_destroy_tables(struct ip_fw_chain *ch, int last)
|
||||
{
|
||||
|
||||
IPFW_DEL_SOPT_HANDLER(last, scodes);
|
||||
|
||||
/* Remove all tables from working set */
|
||||
IPFW_UH_WLOCK(ch);
|
||||
IPFW_WLOCK(ch);
|
||||
ipfw_objhash_foreach(CHAIN_TO_NI(ch), destroy_table_locked, ch);
|
||||
IPFW_WUNLOCK(ch);
|
||||
IPFW_UH_WUNLOCK(ch);
|
||||
|
||||
/* Free pointers itself */
|
||||
free(ch->tablestate, M_IPFW);
|
||||
|
||||
ipfw_table_value_destroy(ch, last);
|
||||
ipfw_table_algo_destroy(ch);
|
||||
|
||||
ipfw_objhash_destroy(CHAIN_TO_NI(ch));
|
||||
free(CHAIN_TO_TCFG(ch), M_IPFW);
|
||||
}
|
||||
|
||||
/*
|
||||
* Starts tables module.
|
||||
*/
|
||||
int
|
||||
ipfw_init_tables(struct ip_fw_chain *ch, int first)
|
||||
{
|
||||
struct tables_config *tcfg;
|
||||
|
||||
/* Allocate pointers */
|
||||
ch->tablestate = malloc(V_fw_tables_max * sizeof(struct table_info),
|
||||
M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
tcfg = malloc(sizeof(struct tables_config), M_IPFW, M_WAITOK | M_ZERO);
|
||||
tcfg->namehash = ipfw_objhash_create(V_fw_tables_max);
|
||||
ch->tblcfg = tcfg;
|
||||
|
||||
ipfw_table_value_init(ch, first);
|
||||
ipfw_table_algo_init(ch);
|
||||
|
||||
IPFW_ADD_SOPT_HANDLER(first, scodes);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -161,29 +161,6 @@ void ipfw_del_table_algo(struct ip_fw_chain *ch, int idx);
|
||||
void ipfw_table_algo_init(struct ip_fw_chain *chain);
|
||||
void ipfw_table_algo_destroy(struct ip_fw_chain *chain);
|
||||
|
||||
|
||||
/* direct ipfw_ctl handlers */
|
||||
int ipfw_list_tables(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_dump_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_describe_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
int ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_list_table_algo(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
int ipfw_swap_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
/* Exported to support legacy opcodes */
|
||||
int add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
||||
struct tentry_info *tei, uint8_t flags, uint32_t count);
|
||||
@ -196,12 +173,10 @@ int ipfw_get_table_size(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
/* ipfw_table_value.c functions */
|
||||
int ipfw_list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
struct table_config;
|
||||
struct tableop_state;
|
||||
void ipfw_table_value_init(struct ip_fw_chain *ch);
|
||||
void ipfw_table_value_destroy(struct ip_fw_chain *ch);
|
||||
void ipfw_table_value_init(struct ip_fw_chain *ch, int first);
|
||||
void ipfw_table_value_destroy(struct ip_fw_chain *ch, int last);
|
||||
int ipfw_link_table_values(struct ip_fw_chain *ch, struct tableop_state *ts);
|
||||
void ipfw_garbage_table_values(struct ip_fw_chain *ch, struct table_config *tc,
|
||||
struct tentry_info *tei, uint32_t count, int rollback);
|
||||
|
@ -60,6 +60,13 @@ static uint32_t hash_table_value(struct namedobj_instance *ni, void *key,
|
||||
uint32_t kopt);
|
||||
static int cmp_table_value(struct named_object *no, void *key, uint32_t kopt);
|
||||
|
||||
static int list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd);
|
||||
|
||||
static struct ipfw_sopt_handler scodes[] = {
|
||||
{ IP_FW_TABLE_VLIST, 0, HDIR_GET, list_table_values },
|
||||
};
|
||||
|
||||
#define CHAIN_TO_VI(chain) (CHAIN_TO_TCFG(chain)->valhash)
|
||||
|
||||
struct table_val_link
|
||||
@ -77,39 +84,6 @@ struct vdump_args {
|
||||
};
|
||||
|
||||
|
||||
void
|
||||
ipfw_table_value_init(struct ip_fw_chain *ch)
|
||||
{
|
||||
struct tables_config *tcfg;
|
||||
|
||||
ch->valuestate = malloc(VALDATA_START_SIZE * sizeof(struct table_value),
|
||||
M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
tcfg = ch->tblcfg;
|
||||
|
||||
tcfg->val_size = VALDATA_START_SIZE;
|
||||
tcfg->valhash = ipfw_objhash_create(tcfg->val_size);
|
||||
ipfw_objhash_set_funcs(tcfg->valhash, hash_table_value,
|
||||
cmp_table_value);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_value(struct namedobj_instance *ni, struct named_object *no,
|
||||
void *arg)
|
||||
{
|
||||
|
||||
free(no, M_IPFW);
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_table_value_destroy(struct ip_fw_chain *ch)
|
||||
{
|
||||
|
||||
free(ch->valuestate, M_IPFW);
|
||||
ipfw_objhash_foreach(CHAIN_TO_VI(ch), destroy_value, ch);
|
||||
ipfw_objhash_destroy(CHAIN_TO_VI(ch));
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
hash_table_value(struct namedobj_instance *ni, void *key, uint32_t kopt)
|
||||
{
|
||||
@ -734,8 +708,8 @@ dump_tvalue(struct namedobj_instance *ni, struct named_object *no, void *arg)
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int
|
||||
ipfw_list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
static int
|
||||
list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
struct sockopt_data *sd)
|
||||
{
|
||||
struct _ipfw_obj_lheader *olh;
|
||||
@ -779,3 +753,40 @@ ipfw_list_table_values(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_table_value_init(struct ip_fw_chain *ch, int first)
|
||||
{
|
||||
struct tables_config *tcfg;
|
||||
|
||||
ch->valuestate = malloc(VALDATA_START_SIZE * sizeof(struct table_value),
|
||||
M_IPFW, M_WAITOK | M_ZERO);
|
||||
|
||||
tcfg = ch->tblcfg;
|
||||
|
||||
tcfg->val_size = VALDATA_START_SIZE;
|
||||
tcfg->valhash = ipfw_objhash_create(tcfg->val_size);
|
||||
ipfw_objhash_set_funcs(tcfg->valhash, hash_table_value,
|
||||
cmp_table_value);
|
||||
|
||||
IPFW_ADD_SOPT_HANDLER(first, scodes);
|
||||
}
|
||||
|
||||
static void
|
||||
destroy_value(struct namedobj_instance *ni, struct named_object *no,
|
||||
void *arg)
|
||||
{
|
||||
|
||||
free(no, M_IPFW);
|
||||
}
|
||||
|
||||
void
|
||||
ipfw_table_value_destroy(struct ip_fw_chain *ch, int last)
|
||||
{
|
||||
|
||||
IPFW_DEL_SOPT_HANDLER(last, scodes);
|
||||
|
||||
free(ch->valuestate, M_IPFW);
|
||||
ipfw_objhash_foreach(CHAIN_TO_VI(ch), destroy_value, ch);
|
||||
ipfw_objhash_destroy(CHAIN_TO_VI(ch));
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user