Generalize object reference handling in ipfw rules.
No ABI changes.
This commit is contained in:
parent
18c5321d06
commit
8963c5055d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=282004
@ -375,6 +375,13 @@ static int ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
|||||||
ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av);
|
ipfw_cfg_lheader *cfg, size_t sz, int ac, char **av);
|
||||||
static void ipfw_list_tifaces(void);
|
static void ipfw_list_tifaces(void);
|
||||||
|
|
||||||
|
struct tidx;
|
||||||
|
static uint16_t pack_object(struct tidx *tstate, char *name, int otype);
|
||||||
|
static uint16_t pack_table(struct tidx *tstate, char *name);
|
||||||
|
|
||||||
|
static char *table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx);
|
||||||
|
static void object_sort_ctlv(ipfw_obj_ctlv *ctlv);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Simple string buffer API.
|
* Simple string buffer API.
|
||||||
* Used to simplify buffer passing between function and for
|
* Used to simplify buffer passing between function and for
|
||||||
@ -2558,6 +2565,7 @@ ipfw_show_config(struct cmdline_opts *co, struct format_opts *fo,
|
|||||||
if (cfg->flags & IPFW_CFG_GET_STATIC) {
|
if (cfg->flags & IPFW_CFG_GET_STATIC) {
|
||||||
/* We've requested static rules */
|
/* We've requested static rules */
|
||||||
if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
|
if (ctlv->head.type == IPFW_TLV_TBLNAME_LIST) {
|
||||||
|
object_sort_ctlv(ctlv);
|
||||||
fo->tstate = ctlv;
|
fo->tstate = ctlv;
|
||||||
readsz += ctlv->head.length;
|
readsz += ctlv->head.length;
|
||||||
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
|
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv +
|
||||||
@ -2724,19 +2732,18 @@ struct tidx {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static uint16_t
|
static uint16_t
|
||||||
pack_table(struct tidx *tstate, char *name)
|
pack_object(struct tidx *tstate, char *name, int otype)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
ipfw_obj_ntlv *ntlv;
|
ipfw_obj_ntlv *ntlv;
|
||||||
|
|
||||||
if (table_check_name(name) != 0)
|
|
||||||
return (0);
|
|
||||||
|
|
||||||
for (i = 0; i < tstate->count; i++) {
|
for (i = 0; i < tstate->count; i++) {
|
||||||
if (strcmp(tstate->idx[i].name, name) != 0)
|
if (strcmp(tstate->idx[i].name, name) != 0)
|
||||||
continue;
|
continue;
|
||||||
if (tstate->idx[i].set != tstate->set)
|
if (tstate->idx[i].set != tstate->set)
|
||||||
continue;
|
continue;
|
||||||
|
if (tstate->idx[i].head.type != otype)
|
||||||
|
continue;
|
||||||
|
|
||||||
return (tstate->idx[i].idx);
|
return (tstate->idx[i].idx);
|
||||||
}
|
}
|
||||||
@ -2752,7 +2759,7 @@ pack_table(struct tidx *tstate, char *name)
|
|||||||
ntlv = &tstate->idx[i];
|
ntlv = &tstate->idx[i];
|
||||||
memset(ntlv, 0, sizeof(ipfw_obj_ntlv));
|
memset(ntlv, 0, sizeof(ipfw_obj_ntlv));
|
||||||
strlcpy(ntlv->name, name, sizeof(ntlv->name));
|
strlcpy(ntlv->name, name, sizeof(ntlv->name));
|
||||||
ntlv->head.type = IPFW_TLV_TBL_NAME;
|
ntlv->head.type = otype;
|
||||||
ntlv->head.length = sizeof(ipfw_obj_ntlv);
|
ntlv->head.length = sizeof(ipfw_obj_ntlv);
|
||||||
ntlv->set = tstate->set;
|
ntlv->set = tstate->set;
|
||||||
ntlv->idx = ++tstate->counter;
|
ntlv->idx = ++tstate->counter;
|
||||||
@ -2761,6 +2768,16 @@ pack_table(struct tidx *tstate, char *name)
|
|||||||
return (ntlv->idx);
|
return (ntlv->idx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static uint16_t
|
||||||
|
pack_table(struct tidx *tstate, char *name)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (table_check_name(name) != 0)
|
||||||
|
return (0);
|
||||||
|
|
||||||
|
return (pack_object(tstate, name, IPFW_TLV_TBL_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
|
fill_table(ipfw_insn *cmd, char *av, uint8_t opcode, struct tidx *tstate)
|
||||||
{
|
{
|
||||||
@ -3611,7 +3628,6 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
|||||||
break;
|
break;
|
||||||
} else
|
} else
|
||||||
goto chkarg;
|
goto chkarg;
|
||||||
|
|
||||||
case TOK_QUEUE:
|
case TOK_QUEUE:
|
||||||
action->opcode = O_QUEUE;
|
action->opcode = O_QUEUE;
|
||||||
goto chkarg;
|
goto chkarg;
|
||||||
@ -4656,6 +4672,101 @@ compile_rule(char *av[], uint32_t *rbuf, int *rbufsize, struct tidx *tstate)
|
|||||||
*rbufsize = (char *)dst - (char *)rule;
|
*rbufsize = (char *)dst - (char *)rule;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
compare_ntlv(const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
ipfw_obj_ntlv *a, *b;
|
||||||
|
|
||||||
|
a = (ipfw_obj_ntlv *)_a;
|
||||||
|
b = (ipfw_obj_ntlv *)_b;
|
||||||
|
|
||||||
|
if (a->set < b->set)
|
||||||
|
return (-1);
|
||||||
|
else if (a->set > b->set)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
if (a->idx < b->idx)
|
||||||
|
return (-1);
|
||||||
|
else if (a->idx > b->idx)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
if (a->head.type < b->head.type)
|
||||||
|
return (-1);
|
||||||
|
else if (a->head.type > b->head.type)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Provide kernel with sorted list of referenced objects
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
object_sort_ctlv(ipfw_obj_ctlv *ctlv)
|
||||||
|
{
|
||||||
|
|
||||||
|
qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct object_kt {
|
||||||
|
uint16_t uidx;
|
||||||
|
uint16_t type;
|
||||||
|
};
|
||||||
|
static int
|
||||||
|
compare_object_kntlv(const void *k, const void *v)
|
||||||
|
{
|
||||||
|
ipfw_obj_ntlv *ntlv;
|
||||||
|
struct object_kt key;
|
||||||
|
|
||||||
|
key = *((struct object_kt *)k);
|
||||||
|
ntlv = (ipfw_obj_ntlv *)v;
|
||||||
|
|
||||||
|
if (key.uidx < ntlv->idx)
|
||||||
|
return (-1);
|
||||||
|
else if (key.uidx > ntlv->idx)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
if (key.type < ntlv->head.type)
|
||||||
|
return (-1);
|
||||||
|
else if (key.type > ntlv->head.type)
|
||||||
|
return (1);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Finds object name in @ctlv by @idx and @type.
|
||||||
|
* Uses the following facts:
|
||||||
|
* 1) All TLVs are the same size
|
||||||
|
* 2) Kernel implementation provides already sorted list.
|
||||||
|
*
|
||||||
|
* Returns table name or NULL.
|
||||||
|
*/
|
||||||
|
static char *
|
||||||
|
object_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx, uint16_t type)
|
||||||
|
{
|
||||||
|
ipfw_obj_ntlv *ntlv;
|
||||||
|
struct object_kt key;
|
||||||
|
|
||||||
|
key.uidx = idx;
|
||||||
|
key.type = type;
|
||||||
|
|
||||||
|
ntlv = bsearch(&key, (ctlv + 1), ctlv->count, ctlv->objsize,
|
||||||
|
compare_object_kntlv);
|
||||||
|
|
||||||
|
if (ntlv != 0)
|
||||||
|
return (ntlv->name);
|
||||||
|
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx)
|
||||||
|
{
|
||||||
|
|
||||||
|
return (object_search_ctlv(ctlv, idx, IPFW_TLV_TBL_NAME));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Adds one or more rules to ipfw chain.
|
* Adds one or more rules to ipfw chain.
|
||||||
* Data layout:
|
* Data layout:
|
||||||
@ -4724,7 +4835,7 @@ ipfw_add(char *av[])
|
|||||||
ctlv->count = ts.count;
|
ctlv->count = ts.count;
|
||||||
ctlv->objsize = sizeof(ipfw_obj_ntlv);
|
ctlv->objsize = sizeof(ipfw_obj_ntlv);
|
||||||
memcpy(ctlv + 1, ts.idx, tlen);
|
memcpy(ctlv + 1, ts.idx, tlen);
|
||||||
table_sort_ctlv(ctlv);
|
object_sort_ctlv(ctlv);
|
||||||
tstate = ctlv;
|
tstate = ctlv;
|
||||||
/* Rule next */
|
/* Rule next */
|
||||||
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length);
|
ctlv = (ipfw_obj_ctlv *)((caddr_t)ctlv + ctlv->head.length);
|
||||||
|
@ -344,8 +344,6 @@ int fill_ext6hdr(struct _ipfw_insn *cmd, char *av);
|
|||||||
|
|
||||||
/* tables.c */
|
/* tables.c */
|
||||||
struct _ipfw_obj_ctlv;
|
struct _ipfw_obj_ctlv;
|
||||||
char *table_search_ctlv(struct _ipfw_obj_ctlv *ctlv, uint16_t idx);
|
|
||||||
void table_sort_ctlv(struct _ipfw_obj_ctlv *ctlv);
|
|
||||||
int table_check_name(char *tablename);
|
int table_check_name(char *tablename);
|
||||||
void ipfw_list_ta(int ac, char *av[]);
|
void ipfw_list_ta(int ac, char *av[]);
|
||||||
void ipfw_list_values(int ac, char *av[]);
|
void ipfw_list_values(int ac, char *av[]);
|
||||||
|
@ -1936,73 +1936,6 @@ ipfw_list_values(int ac, char *av[])
|
|||||||
free(olh);
|
free(olh);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
compare_ntlv(const void *_a, const void *_b)
|
|
||||||
{
|
|
||||||
ipfw_obj_ntlv *a, *b;
|
|
||||||
|
|
||||||
a = (ipfw_obj_ntlv *)_a;
|
|
||||||
b = (ipfw_obj_ntlv *)_b;
|
|
||||||
|
|
||||||
if (a->set < b->set)
|
|
||||||
return (-1);
|
|
||||||
else if (a->set > b->set)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
if (a->idx < b->idx)
|
|
||||||
return (-1);
|
|
||||||
else if (a->idx > b->idx)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
compare_kntlv(const void *k, const void *v)
|
|
||||||
{
|
|
||||||
ipfw_obj_ntlv *ntlv;
|
|
||||||
uint16_t key;
|
|
||||||
|
|
||||||
key = *((uint16_t *)k);
|
|
||||||
ntlv = (ipfw_obj_ntlv *)v;
|
|
||||||
|
|
||||||
if (key < ntlv->idx)
|
|
||||||
return (-1);
|
|
||||||
else if (key > ntlv->idx)
|
|
||||||
return (1);
|
|
||||||
|
|
||||||
return (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Finds table name in @ctlv by @idx.
|
|
||||||
* Uses the following facts:
|
|
||||||
* 1) All TLVs are the same size
|
|
||||||
* 2) Kernel implementation provides already sorted list.
|
|
||||||
*
|
|
||||||
* Returns table name or NULL.
|
|
||||||
*/
|
|
||||||
char *
|
|
||||||
table_search_ctlv(ipfw_obj_ctlv *ctlv, uint16_t idx)
|
|
||||||
{
|
|
||||||
ipfw_obj_ntlv *ntlv;
|
|
||||||
|
|
||||||
ntlv = bsearch(&idx, (ctlv + 1), ctlv->count, ctlv->objsize,
|
|
||||||
compare_kntlv);
|
|
||||||
|
|
||||||
if (ntlv != 0)
|
|
||||||
return (ntlv->name);
|
|
||||||
|
|
||||||
return (NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
table_sort_ctlv(ipfw_obj_ctlv *ctlv)
|
|
||||||
{
|
|
||||||
|
|
||||||
qsort(ctlv + 1, ctlv->count, ctlv->objsize, compare_ntlv);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
table_check_name(char *tablename)
|
table_check_name(char *tablename)
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user