* Add number:array algorithm lookup method.
Kernel changes: * s/IPFW_TABLE_U32/IPFW_TABLE_NUMBER/ * Force "lookup <port|uid|gid|jid>" to be IPFW_TABLE_NUMBER * Support "lookup" method for number tables * Add number:array algorihm (i32 as key, auto-growing). Userland changes: * Support named tables in "lookup <tag> Table" * Fix handling of "table(NAME,val)" case * Support printing "number" table data.
This commit is contained in:
parent
ce2817b51c
commit
b23d5de9b6
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/projects/ipfw/; revision=269304
@ -1096,6 +1096,7 @@ print_ip(struct format_opts *fo, ipfw_insn_ip *cmd, char const *s)
|
|||||||
struct hostent *he = NULL;
|
struct hostent *he = NULL;
|
||||||
uint32_t len = F_LEN((ipfw_insn *)cmd);
|
uint32_t len = F_LEN((ipfw_insn *)cmd);
|
||||||
uint32_t *a = ((ipfw_insn_u32 *)cmd)->d;
|
uint32_t *a = ((ipfw_insn_u32 *)cmd)->d;
|
||||||
|
char *t;
|
||||||
|
|
||||||
if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) {
|
if (cmd->o.opcode == O_IP_DST_LOOKUP && len > F_INSN_SIZE(ipfw_insn_u32)) {
|
||||||
uint32_t d = a[1];
|
uint32_t d = a[1];
|
||||||
@ -1103,8 +1104,9 @@ print_ip(struct format_opts *fo, ipfw_insn_ip *cmd, char const *s)
|
|||||||
|
|
||||||
if (d < sizeof(lookup_key)/sizeof(lookup_key[0]))
|
if (d < sizeof(lookup_key)/sizeof(lookup_key[0]))
|
||||||
arg = match_value(rule_options, lookup_key[d]);
|
arg = match_value(rule_options, lookup_key[d]);
|
||||||
printf("%s lookup %s %d", cmd->o.len & F_NOT ? " not": "",
|
t = table_search_ctlv(fo->tstate, ((ipfw_insn *)cmd)->arg1);
|
||||||
arg, cmd->o.arg1);
|
printf("%s lookup %s %s", cmd->o.len & F_NOT ? " not": "",
|
||||||
|
arg, t);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s);
|
printf("%s%s ", cmd->o.len & F_NOT ? " not": "", s);
|
||||||
@ -1115,7 +1117,6 @@ print_ip(struct format_opts *fo, ipfw_insn_ip *cmd, char const *s)
|
|||||||
}
|
}
|
||||||
if (cmd->o.opcode == O_IP_SRC_LOOKUP ||
|
if (cmd->o.opcode == O_IP_SRC_LOOKUP ||
|
||||||
cmd->o.opcode == O_IP_DST_LOOKUP) {
|
cmd->o.opcode == O_IP_DST_LOOKUP) {
|
||||||
char *t;
|
|
||||||
t = table_search_ctlv(fo->tstate, ((ipfw_insn *)cmd)->arg1);
|
t = table_search_ctlv(fo->tstate, ((ipfw_insn *)cmd)->arg1);
|
||||||
printf("table(%s", t);
|
printf("table(%s", t);
|
||||||
if (len == F_INSN_SIZE(ipfw_insn_u32))
|
if (len == F_INSN_SIZE(ipfw_insn_u32))
|
||||||
@ -2624,14 +2625,9 @@ struct tidx {
|
|||||||
static uint16_t
|
static uint16_t
|
||||||
pack_table(struct tidx *tstate, char *name, uint32_t set)
|
pack_table(struct tidx *tstate, char *name, uint32_t set)
|
||||||
{
|
{
|
||||||
char *p;
|
|
||||||
int i;
|
int i;
|
||||||
ipfw_obj_ntlv *ntlv;
|
ipfw_obj_ntlv *ntlv;
|
||||||
|
|
||||||
if ((p = strchr(name, ')')) == NULL)
|
|
||||||
return (0);
|
|
||||||
*p = '\0';
|
|
||||||
|
|
||||||
if (table_check_name(name) != 0)
|
if (table_check_name(name) != 0)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
@ -2694,6 +2690,9 @@ fill_ip(ipfw_insn_ip *cmd, char *av, int cblen, struct tidx *tstate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (strncmp(av, "table(", 6) == 0) {
|
if (strncmp(av, "table(", 6) == 0) {
|
||||||
|
if ((p = strchr(av + 6, ')')) == NULL)
|
||||||
|
errx(EX_DATAERR, "forgotten parenthesis: '%s'", av);
|
||||||
|
*p = '\0';
|
||||||
p = strchr(av + 6, ',');
|
p = strchr(av + 6, ',');
|
||||||
if (p)
|
if (p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
@ -2983,6 +2982,7 @@ ipfw_delete(char *av[])
|
|||||||
static void
|
static void
|
||||||
fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate)
|
fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate)
|
||||||
{
|
{
|
||||||
|
char *p;
|
||||||
uint16_t uidx;
|
uint16_t uidx;
|
||||||
|
|
||||||
cmd->name[0] = '\0';
|
cmd->name[0] = '\0';
|
||||||
@ -2994,7 +2994,10 @@ fill_iface(ipfw_insn_if *cmd, char *arg, int cblen, struct tidx *tstate)
|
|||||||
if (strcmp(arg, "any") == 0)
|
if (strcmp(arg, "any") == 0)
|
||||||
cmd->o.len = 0; /* effectively ignore this command */
|
cmd->o.len = 0; /* effectively ignore this command */
|
||||||
else if (strncmp(arg, "table(", 6) == 0) {
|
else if (strncmp(arg, "table(", 6) == 0) {
|
||||||
char *p = strchr(arg + 6, ',');
|
if ((p = strchr(arg + 6, ')')) == NULL)
|
||||||
|
errx(EX_DATAERR, "forgotten parenthesis: '%s'", arg);
|
||||||
|
*p = '\0';
|
||||||
|
p = strchr(arg + 6, ',');
|
||||||
if (p)
|
if (p)
|
||||||
*p++ = '\0';
|
*p++ = '\0';
|
||||||
if ((uidx = pack_table(tstate, arg + 6, 0)) == 0)
|
if ((uidx = pack_table(tstate, arg + 6, 0)) == 0)
|
||||||
@ -4381,7 +4384,6 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
|||||||
|
|
||||||
case TOK_LOOKUP: {
|
case TOK_LOOKUP: {
|
||||||
ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd;
|
ipfw_insn_u32 *c = (ipfw_insn_u32 *)cmd;
|
||||||
char *p;
|
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
if (!av[0] || !av[1])
|
if (!av[0] || !av[1])
|
||||||
@ -4397,9 +4399,11 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
|||||||
errx(EX_USAGE, "format: cannot lookup on %s", *av);
|
errx(EX_USAGE, "format: cannot lookup on %s", *av);
|
||||||
__PAST_END(c->d, 1) = j; // i converted to option
|
__PAST_END(c->d, 1) = j; // i converted to option
|
||||||
av++;
|
av++;
|
||||||
cmd->arg1 = strtoul(*av, &p, 0);
|
|
||||||
if (p && *p)
|
if ((j = pack_table(tstate, *av, 0)) == 0)
|
||||||
errx(EX_USAGE, "format: lookup argument tablenum");
|
errx(EX_DATAERR, "Invalid table name: %s", *av);
|
||||||
|
|
||||||
|
cmd->arg1 = j;
|
||||||
av++;
|
av++;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -82,7 +82,7 @@ static int tables_foreach(table_cb_t *f, void *arg, int sort);
|
|||||||
static struct _s_x tabletypes[] = {
|
static struct _s_x tabletypes[] = {
|
||||||
{ "cidr", IPFW_TABLE_CIDR },
|
{ "cidr", IPFW_TABLE_CIDR },
|
||||||
{ "iface", IPFW_TABLE_INTERFACE },
|
{ "iface", IPFW_TABLE_INTERFACE },
|
||||||
{ "u32", IPFW_TABLE_U32 },
|
{ "number", IPFW_TABLE_NUMBER },
|
||||||
{ NULL, 0 }
|
{ NULL, 0 }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -654,7 +654,7 @@ tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type)
|
|||||||
/* Set mask to exact match */
|
/* Set mask to exact match */
|
||||||
masklen = 8 * IF_NAMESIZE;
|
masklen = 8 * IF_NAMESIZE;
|
||||||
break;
|
break;
|
||||||
case IPFW_TABLE_U32:
|
case IPFW_TABLE_NUMBER:
|
||||||
/* Port or any other key */
|
/* Port or any other key */
|
||||||
key = strtol(arg, &p, 10);
|
key = strtol(arg, &p, 10);
|
||||||
if (*p != '\0')
|
if (*p != '\0')
|
||||||
@ -899,6 +899,16 @@ table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent)
|
|||||||
inet_ntoa(*(struct in_addr *)&tval));
|
inet_ntoa(*(struct in_addr *)&tval));
|
||||||
} else
|
} else
|
||||||
printf("%s %u\n", tent->k.iface, tval);
|
printf("%s %u\n", tent->k.iface, tval);
|
||||||
|
break;
|
||||||
|
case IPFW_TABLE_NUMBER:
|
||||||
|
/* numbers */
|
||||||
|
if (co.do_value_as_ip) {
|
||||||
|
tval = htonl(tval);
|
||||||
|
printf("%u %s\n", tent->k.key,
|
||||||
|
inet_ntoa(*(struct in_addr *)&tval));
|
||||||
|
} else
|
||||||
|
printf("%u %u\n", tent->k.key, tval);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -674,7 +674,7 @@ struct _ipfw_dyn_rule {
|
|||||||
|
|
||||||
#define IPFW_TABLE_CIDR 1 /* Table for holding IPv4/IPv6 prefixes */
|
#define IPFW_TABLE_CIDR 1 /* Table for holding IPv4/IPv6 prefixes */
|
||||||
#define IPFW_TABLE_INTERFACE 2 /* Table for holding interface names */
|
#define IPFW_TABLE_INTERFACE 2 /* Table for holding interface names */
|
||||||
#define IPFW_TABLE_U32 3 /* Table for holidng ports/uid/gid/etc */
|
#define IPFW_TABLE_NUMBER 3 /* Table for holding ports/uid/gid/etc */
|
||||||
#define IPFW_TABLE_MAXTYPE 3 /* Maximum valid number */
|
#define IPFW_TABLE_MAXTYPE 3 /* Maximum valid number */
|
||||||
|
|
||||||
#define IPFW_VTYPE_U32 1 /* Skipto/tablearg integer */
|
#define IPFW_VTYPE_U32 1 /* Skipto/tablearg integer */
|
||||||
|
@ -1473,9 +1473,9 @@ do { \
|
|||||||
proto != IPPROTO_UDP)
|
proto != IPPROTO_UDP)
|
||||||
break;
|
break;
|
||||||
else if (v == 2)
|
else if (v == 2)
|
||||||
key = htonl(dst_port);
|
key = dst_port;
|
||||||
else if (v == 3)
|
else if (v == 3)
|
||||||
key = htonl(src_port);
|
key = src_port;
|
||||||
#ifndef USERSPACE
|
#ifndef USERSPACE
|
||||||
else if (v == 4 || v == 5) {
|
else if (v == 4 || v == 5) {
|
||||||
check_uidgid(
|
check_uidgid(
|
||||||
@ -1494,7 +1494,6 @@ do { \
|
|||||||
else if (v == 5 /* O_JAIL */)
|
else if (v == 5 /* O_JAIL */)
|
||||||
key = ucred_cache.xid;
|
key = ucred_cache.xid;
|
||||||
#endif /* !__FreeBSD__ */
|
#endif /* !__FreeBSD__ */
|
||||||
key = htonl(key);
|
|
||||||
} else
|
} else
|
||||||
#endif /* !USERSPACE */
|
#endif /* !USERSPACE */
|
||||||
break;
|
break;
|
||||||
|
@ -593,6 +593,9 @@ ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
|||||||
IPFW_UH_RUNLOCK(ch);
|
IPFW_UH_RUNLOCK(ch);
|
||||||
return (EINVAL);
|
return (EINVAL);
|
||||||
}
|
}
|
||||||
|
case IPFW_TABLE_NUMBER:
|
||||||
|
plen = sizeof(uint32_t);
|
||||||
|
break;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1744,17 +1747,19 @@ classify_table_opcode(ipfw_insn *cmd, uint16_t *puidx, uint8_t *ptype)
|
|||||||
case 2:
|
case 2:
|
||||||
case 3:
|
case 3:
|
||||||
/* src/dst port */
|
/* src/dst port */
|
||||||
//type = IPFW_TABLE_U16;
|
*ptype = IPFW_TABLE_NUMBER;
|
||||||
break;
|
break;
|
||||||
case 4:
|
case 4:
|
||||||
/* uid/gid */
|
/* uid/gid */
|
||||||
//type = IPFW_TABLE_U32;
|
*ptype = IPFW_TABLE_NUMBER;
|
||||||
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
//type = IPFW_TABLE_U32;
|
|
||||||
/* jid */
|
/* jid */
|
||||||
|
*ptype = IPFW_TABLE_NUMBER;
|
||||||
|
break;
|
||||||
case 6:
|
case 6:
|
||||||
//type = IPFW_TABLE_U16;
|
|
||||||
/* dscp */
|
/* dscp */
|
||||||
|
*ptype = IPFW_TABLE_NUMBER;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1376,7 +1376,7 @@ struct table_algo cidr_hash = {
|
|||||||
*
|
*
|
||||||
* Runtime part:
|
* Runtime part:
|
||||||
* - sorted array of "struct ifidx" pointed by ti->state.
|
* - sorted array of "struct ifidx" pointed by ti->state.
|
||||||
* Array is allocated with routing up to IFIDX_CHUNK. Only existing
|
* Array is allocated with rounding up to IFIDX_CHUNK. Only existing
|
||||||
* interfaces are stored in array, however its allocated size is
|
* interfaces are stored in array, however its allocated size is
|
||||||
* sufficient to hold all table records if needed.
|
* sufficient to hold all table records if needed.
|
||||||
* - current array size is stored in ti->data
|
* - current array size is stored in ti->data
|
||||||
@ -2025,6 +2025,368 @@ struct table_algo iface_idx = {
|
|||||||
.change_ti = ta_change_ti_ifidx,
|
.change_ti = ta_change_ti_ifidx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Number array cmds.
|
||||||
|
*
|
||||||
|
* Implementation:
|
||||||
|
*
|
||||||
|
* Runtime part:
|
||||||
|
* - sorted array of "struct numarray" pointed by ti->state.
|
||||||
|
* Array is allocated with rounding up to NUMARRAY_CHUNK.
|
||||||
|
* - current array size is stored in ti->data
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct numarray {
|
||||||
|
uint32_t number;
|
||||||
|
uint32_t value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct numarray_cfg {
|
||||||
|
void *main_ptr;
|
||||||
|
size_t size; /* Number of items allocated in array */
|
||||||
|
size_t used; /* Number of items _active_ now */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUMARRAY_CHUNK 16
|
||||||
|
|
||||||
|
int compare_numarray(const void *k, const void *v);
|
||||||
|
|
||||||
|
int
|
||||||
|
compare_numarray(const void *k, const void *v)
|
||||||
|
{
|
||||||
|
struct numarray *na;
|
||||||
|
uint32_t key;
|
||||||
|
|
||||||
|
key = *((uint32_t *)k);
|
||||||
|
na = (struct numarray *)v;
|
||||||
|
|
||||||
|
if (key < na->number)
|
||||||
|
return (-1);
|
||||||
|
else if (key > na->number)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct numarray *
|
||||||
|
numarray_find(struct table_info *ti, void *key)
|
||||||
|
{
|
||||||
|
struct numarray *ri;
|
||||||
|
|
||||||
|
ri = bsearch(key, ti->state, ti->data, sizeof(struct numarray),
|
||||||
|
compare_ifidx);
|
||||||
|
|
||||||
|
return (ri);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ta_lookup_numarray(struct table_info *ti, void *key, uint32_t keylen,
|
||||||
|
uint32_t *val)
|
||||||
|
{
|
||||||
|
struct numarray *ri;
|
||||||
|
|
||||||
|
ri = numarray_find(ti, key);
|
||||||
|
|
||||||
|
if (ri != NULL) {
|
||||||
|
*val = ri->value;
|
||||||
|
return (1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ta_init_numarray(struct ip_fw_chain *ch, void **ta_state, struct table_info *ti,
|
||||||
|
char *data)
|
||||||
|
{
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
|
||||||
|
cfg = malloc(sizeof(*cfg), M_IPFW, M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
|
cfg->size = NUMARRAY_CHUNK;
|
||||||
|
cfg->main_ptr = malloc(sizeof(struct numarray) * cfg->size, M_IPFW,
|
||||||
|
M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
|
*ta_state = cfg;
|
||||||
|
ti->state = cfg->main_ptr;
|
||||||
|
ti->lookup = ta_lookup_numarray;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Destroys table @ti
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ta_destroy_numarray(void *ta_state, struct table_info *ti)
|
||||||
|
{
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
|
||||||
|
if (cfg->main_ptr != NULL)
|
||||||
|
free(cfg->main_ptr, M_IPFW);
|
||||||
|
|
||||||
|
free(cfg, M_IPFW);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ta_buf_numarray
|
||||||
|
{
|
||||||
|
struct numarray na;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Prepare for addition/deletion to an array.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ta_prepare_add_numarray(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||||
|
void *ta_buf)
|
||||||
|
{
|
||||||
|
struct ta_buf_numarray *tb;
|
||||||
|
|
||||||
|
tb = (struct ta_buf_numarray *)ta_buf;
|
||||||
|
memset(tb, 0, sizeof(*tb));
|
||||||
|
|
||||||
|
tb->na.number = *((uint32_t *)tei->paddr);
|
||||||
|
tb->na.value = tei->value;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ta_add_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||||
|
void *ta_buf, uint64_t *pflags, uint32_t *pnum)
|
||||||
|
{
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
struct ta_buf_numarray *tb;
|
||||||
|
struct numarray *ri;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
tb = (struct ta_buf_numarray*)ta_buf;
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
|
||||||
|
ri = numarray_find(ti, &tb->na.number);
|
||||||
|
|
||||||
|
if (ri != NULL) {
|
||||||
|
if ((tei->flags & TEI_FLAGS_UPDATE) == 0)
|
||||||
|
return (EEXIST);
|
||||||
|
|
||||||
|
/* We need to update value */
|
||||||
|
ri->value = tb->na.value;
|
||||||
|
/* Indicate that update has happened instead of addition */
|
||||||
|
tei->flags |= TEI_FLAGS_UPDATED;
|
||||||
|
*pnum = 0;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
res = badd(&tb->na.number, &tb->na, cfg->main_ptr, cfg->used,
|
||||||
|
sizeof(struct numarray), compare_numarray);
|
||||||
|
|
||||||
|
KASSERT(res == 1, ("number %d already exists", tb->na.number));
|
||||||
|
cfg->used++;
|
||||||
|
ti->data = cfg->used;
|
||||||
|
|
||||||
|
if (cfg->used + 1 == cfg->size) {
|
||||||
|
/* Notify core we need to grow */
|
||||||
|
*pflags = cfg->size + NUMARRAY_CHUNK;
|
||||||
|
}
|
||||||
|
*pnum = 1;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Remove key from both configuration list and
|
||||||
|
* runtime array. Removed interface notification.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ta_del_numarray(void *ta_state, struct table_info *ti, struct tentry_info *tei,
|
||||||
|
void *ta_buf, uint64_t *pflags, uint32_t *pnum)
|
||||||
|
{
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
struct ta_buf_numarray *tb;
|
||||||
|
struct numarray *ri;
|
||||||
|
int res;
|
||||||
|
|
||||||
|
tb = (struct ta_buf_numarray *)ta_buf;
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
|
||||||
|
ri = numarray_find(ti, &tb->na.number);
|
||||||
|
if (ri == NULL)
|
||||||
|
return (ENOENT);
|
||||||
|
|
||||||
|
res = bdel(&tb->na.number, cfg->main_ptr, cfg->used,
|
||||||
|
sizeof(struct numarray), compare_numarray);
|
||||||
|
|
||||||
|
KASSERT(res == 1, ("number %u does not exist", tb->na.number));
|
||||||
|
cfg->used--;
|
||||||
|
ti->data = cfg->used;
|
||||||
|
|
||||||
|
*pnum = 1;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ta_flush_numarray_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
|
||||||
|
void *ta_buf)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* Do nothing */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Table growing callbacks.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate ned, larger runtime numarray array.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ta_prepare_mod_numarray(void *ta_buf, uint64_t *pflags)
|
||||||
|
{
|
||||||
|
struct mod_item *mi;
|
||||||
|
|
||||||
|
mi = (struct mod_item *)ta_buf;
|
||||||
|
|
||||||
|
memset(mi, 0, sizeof(struct mod_item));
|
||||||
|
mi->size = *pflags;
|
||||||
|
mi->main_ptr = malloc(sizeof(struct numarray) * mi->size, M_IPFW,
|
||||||
|
M_WAITOK | M_ZERO);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copy data from old runtime array to new one.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ta_fill_mod_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
|
||||||
|
uint64_t *pflags)
|
||||||
|
{
|
||||||
|
struct mod_item *mi;
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
|
||||||
|
mi = (struct mod_item *)ta_buf;
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
|
||||||
|
/* Check if we still need to grow array */
|
||||||
|
if (cfg->size >= mi->size) {
|
||||||
|
*pflags = 0;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(mi->main_ptr, cfg->main_ptr, cfg->used * sizeof(struct numarray));
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch old & new arrays.
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
ta_modify_numarray(void *ta_state, struct table_info *ti, void *ta_buf,
|
||||||
|
uint64_t pflags)
|
||||||
|
{
|
||||||
|
struct mod_item *mi;
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
void *old_ptr;
|
||||||
|
|
||||||
|
mi = (struct mod_item *)ta_buf;
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
|
||||||
|
old_ptr = cfg->main_ptr;
|
||||||
|
cfg->main_ptr = mi->main_ptr;
|
||||||
|
cfg->size = mi->size;
|
||||||
|
ti->state = cfg->main_ptr;
|
||||||
|
|
||||||
|
mi->main_ptr = old_ptr;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Free unneded array.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
ta_flush_mod_numarray(void *ta_buf)
|
||||||
|
{
|
||||||
|
struct mod_item *mi;
|
||||||
|
|
||||||
|
mi = (struct mod_item *)ta_buf;
|
||||||
|
if (mi->main_ptr != NULL)
|
||||||
|
free(mi->main_ptr, M_IPFW);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ta_dump_numarray_tentry(void *ta_state, struct table_info *ti, void *e,
|
||||||
|
ipfw_obj_tentry *tent)
|
||||||
|
{
|
||||||
|
struct numarray *na;
|
||||||
|
|
||||||
|
na = (struct numarray *)e;
|
||||||
|
|
||||||
|
tent->k.key = na->number;
|
||||||
|
tent->value = na->value;
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
ta_find_numarray_tentry(void *ta_state, struct table_info *ti, void *key,
|
||||||
|
uint32_t keylen, ipfw_obj_tentry *tent)
|
||||||
|
{
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
struct numarray *ri;
|
||||||
|
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
|
||||||
|
ri = numarray_find(ti, key);
|
||||||
|
|
||||||
|
if (ri != NULL) {
|
||||||
|
ta_dump_numarray_tentry(ta_state, ti, ri, tent);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ENOENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
ta_foreach_numarray(void *ta_state, struct table_info *ti, ta_foreach_f *f,
|
||||||
|
void *arg)
|
||||||
|
{
|
||||||
|
struct numarray_cfg *cfg;
|
||||||
|
struct numarray *array;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
cfg = (struct numarray_cfg *)ta_state;
|
||||||
|
array = cfg->main_ptr;
|
||||||
|
|
||||||
|
for (i = 0; i < cfg->used; i++)
|
||||||
|
f(&array[i], arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct table_algo number_array = {
|
||||||
|
.name = "number:array",
|
||||||
|
.type = IPFW_TABLE_NUMBER,
|
||||||
|
.init = ta_init_numarray,
|
||||||
|
.destroy = ta_destroy_numarray,
|
||||||
|
.prepare_add = ta_prepare_add_numarray,
|
||||||
|
.prepare_del = ta_prepare_add_numarray,
|
||||||
|
.add = ta_add_numarray,
|
||||||
|
.del = ta_del_numarray,
|
||||||
|
.flush_entry = ta_flush_numarray_entry,
|
||||||
|
.foreach = ta_foreach_numarray,
|
||||||
|
.dump_tentry = ta_dump_numarray_tentry,
|
||||||
|
.find_tentry = ta_find_numarray_tentry,
|
||||||
|
.prepare_mod = ta_prepare_mod_numarray,
|
||||||
|
.fill_mod = ta_fill_mod_numarray,
|
||||||
|
.modify = ta_modify_numarray,
|
||||||
|
.flush_mod = ta_flush_mod_numarray,
|
||||||
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
ipfw_table_algo_init(struct ip_fw_chain *ch)
|
ipfw_table_algo_init(struct ip_fw_chain *ch)
|
||||||
{
|
{
|
||||||
@ -2037,6 +2399,7 @@ ipfw_table_algo_init(struct ip_fw_chain *ch)
|
|||||||
ipfw_add_table_algo(ch, &cidr_radix, sz, &cidr_radix.idx);
|
ipfw_add_table_algo(ch, &cidr_radix, sz, &cidr_radix.idx);
|
||||||
ipfw_add_table_algo(ch, &cidr_hash, sz, &cidr_hash.idx);
|
ipfw_add_table_algo(ch, &cidr_hash, sz, &cidr_hash.idx);
|
||||||
ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx);
|
ipfw_add_table_algo(ch, &iface_idx, sz, &iface_idx.idx);
|
||||||
|
ipfw_add_table_algo(ch, &number_array, sz, &number_array.idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -2046,6 +2409,7 @@ ipfw_table_algo_destroy(struct ip_fw_chain *ch)
|
|||||||
ipfw_del_table_algo(ch, cidr_radix.idx);
|
ipfw_del_table_algo(ch, cidr_radix.idx);
|
||||||
ipfw_del_table_algo(ch, cidr_hash.idx);
|
ipfw_del_table_algo(ch, cidr_hash.idx);
|
||||||
ipfw_del_table_algo(ch, iface_idx.idx);
|
ipfw_del_table_algo(ch, iface_idx.idx);
|
||||||
|
ipfw_del_table_algo(ch, number_array.idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user