* Dump available table algorithms via "ipfw talist" cmd.
Kernel changes: * Add type/refcount fields to table algo instances. * Add IP_FW_TABLES_ALIST opcode to export available algorihms to userland. Userland changes: * Fix cores on empty input inside "ipfw table" handler. * Add "ipfw talist" cmd to print availabled kernel algorithms. * Change "table info" output to reflect long algorithm config lines.
This commit is contained in:
parent
0b565ac0e6
commit
9d099b4f38
@ -297,6 +297,7 @@ void ipfw_flush(int force);
|
|||||||
void ipfw_zero(int ac, char *av[], int optname);
|
void ipfw_zero(int ac, char *av[], int optname);
|
||||||
void ipfw_list(int ac, char *av[], int show_counters);
|
void ipfw_list(int ac, char *av[], int show_counters);
|
||||||
void ipfw_list_tifaces(void);
|
void ipfw_list_tifaces(void);
|
||||||
|
void ipfw_list_ta(int ac, char *av[]);
|
||||||
|
|
||||||
#ifdef PF
|
#ifdef PF
|
||||||
/* altq.c */
|
/* altq.c */
|
||||||
|
@ -440,6 +440,8 @@ ipfw_main(int oldac, char **oldav)
|
|||||||
ipfw_table_handler(ac, av);
|
ipfw_table_handler(ac, av);
|
||||||
else if (_substrcmp(*av, "iflist") == 0)
|
else if (_substrcmp(*av, "iflist") == 0)
|
||||||
ipfw_list_tifaces();
|
ipfw_list_tifaces();
|
||||||
|
else if (_substrcmp(*av, "talist") == 0)
|
||||||
|
ipfw_list_ta(ac, av);
|
||||||
else
|
else
|
||||||
errx(EX_USAGE, "bad command `%s'", *av);
|
errx(EX_USAGE, "bad command `%s'", *av);
|
||||||
}
|
}
|
||||||
|
@ -146,6 +146,7 @@ ipfw_table_handler(int ac, char *av[])
|
|||||||
set = 0;
|
set = 0;
|
||||||
|
|
||||||
ac--; av++;
|
ac--; av++;
|
||||||
|
NEED1("table needs name");
|
||||||
tablename = *av;
|
tablename = *av;
|
||||||
|
|
||||||
if (table_check_name(tablename) == 0) {
|
if (table_check_name(tablename) == 0) {
|
||||||
@ -158,11 +159,11 @@ ipfw_table_handler(int ac, char *av[])
|
|||||||
errx(EX_USAGE, "table name %s is invalid", tablename);
|
errx(EX_USAGE, "table name %s is invalid", tablename);
|
||||||
}
|
}
|
||||||
ac--; av++;
|
ac--; av++;
|
||||||
|
NEED1("table needs command");
|
||||||
|
|
||||||
if ((tcmd = match_token(tablecmds, *av)) == -1)
|
if ((tcmd = match_token(tablecmds, *av)) == -1)
|
||||||
errx(EX_USAGE, "invalid table command %s", *av);
|
errx(EX_USAGE, "invalid table command %s", *av);
|
||||||
|
|
||||||
NEED1("table needs command");
|
|
||||||
switch (tcmd) {
|
switch (tcmd) {
|
||||||
case TOK_LIST:
|
case TOK_LIST:
|
||||||
case TOK_INFO:
|
case TOK_INFO:
|
||||||
@ -416,8 +417,8 @@ table_show_info(ipfw_xtable_info *i, void *arg)
|
|||||||
vtype = "unknown";
|
vtype = "unknown";
|
||||||
|
|
||||||
printf(" type: %s, kindex: %d\n", ttype, i->kidx);
|
printf(" type: %s, kindex: %d\n", ttype, i->kidx);
|
||||||
printf(" valtype: %s, algorithm: %s\n", vtype, i->algoname);
|
printf(" valtype: %s, references: %u\n", vtype, i->refcnt);
|
||||||
printf(" references: %u\n", i->refcnt);
|
printf(" algorithm: %s\n", i->algoname);
|
||||||
printf(" items: %u, size: %u\n", i->count, i->size);
|
printf(" items: %u, size: %u\n", i->count, i->size);
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
@ -901,6 +902,59 @@ table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
table_do_get_algolist(ipfw_obj_lheader **polh)
|
||||||
|
{
|
||||||
|
ipfw_obj_lheader req, *olh;
|
||||||
|
size_t sz;
|
||||||
|
int error;
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
sz = sizeof(req);
|
||||||
|
|
||||||
|
error = do_get3(IP_FW_TABLES_ALIST, &req.opheader, &sz);
|
||||||
|
if (error != 0 && error != ENOMEM)
|
||||||
|
return (error);
|
||||||
|
|
||||||
|
sz = req.size;
|
||||||
|
if ((olh = calloc(1, sz)) == NULL)
|
||||||
|
return (ENOMEM);
|
||||||
|
|
||||||
|
olh->size = sz;
|
||||||
|
if ((error = do_get3(IP_FW_TABLES_ALIST, &olh->opheader, &sz)) != 0) {
|
||||||
|
free(olh);
|
||||||
|
return (error);
|
||||||
|
}
|
||||||
|
|
||||||
|
*polh = olh;
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
ipfw_list_ta(int ac, char *av[])
|
||||||
|
{
|
||||||
|
ipfw_obj_lheader *olh;
|
||||||
|
ipfw_ta_info *info;
|
||||||
|
int error, i;
|
||||||
|
const char *atype;
|
||||||
|
|
||||||
|
error = table_do_get_algolist(&olh);
|
||||||
|
if (error != 0)
|
||||||
|
err(EX_OSERR, "Unable to request algorithm list");
|
||||||
|
|
||||||
|
info = (ipfw_ta_info *)(olh + 1);
|
||||||
|
for (i = 0; i < olh->count; i++) {
|
||||||
|
if ((atype = match_value(tabletypes, info->type)) == NULL)
|
||||||
|
atype = "unknown";
|
||||||
|
|
||||||
|
printf("%s type: %s references: %u\n", info->algoname,
|
||||||
|
atype, info->refcnt);
|
||||||
|
info = (ipfw_ta_info *)((caddr_t)info + olh->objsize);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(olh);
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
compare_ntlv(const void *_a, const void *_b)
|
compare_ntlv(const void *_a, const void *_b)
|
||||||
{
|
{
|
||||||
|
@ -89,6 +89,7 @@ typedef struct _ip_fw3_opheader {
|
|||||||
#define IP_FW_XADD 98 /* add entry */
|
#define IP_FW_XADD 98 /* add entry */
|
||||||
#define IP_FW_TABLE_XFIND 99 /* finds an entry */
|
#define IP_FW_TABLE_XFIND 99 /* finds an entry */
|
||||||
#define IP_FW_XIFLIST 100 /* list tracked interfaces */
|
#define IP_FW_XIFLIST 100 /* list tracked interfaces */
|
||||||
|
#define IP_FW_TABLES_ALIST 101 /* list table algorithms */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Usage guidelines:
|
* Usage guidelines:
|
||||||
@ -799,6 +800,15 @@ typedef struct _ipfw_iface_info {
|
|||||||
} ipfw_iface_info;
|
} ipfw_iface_info;
|
||||||
#define IPFW_IFFLAG_RESOLVED 0x01 /* Interface exists */
|
#define IPFW_IFFLAG_RESOLVED 0x01 /* Interface exists */
|
||||||
|
|
||||||
|
typedef struct _ipfw_ta_info {
|
||||||
|
char algoname[32]; /* algorithm name */
|
||||||
|
uint32_t type; /* lookup type */
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t refcnt;
|
||||||
|
uint32_t spare0;
|
||||||
|
uint64_t spare1;
|
||||||
|
} ipfw_ta_info;
|
||||||
|
|
||||||
#define IPFW_OBJTYPE_TABLE 1
|
#define IPFW_OBJTYPE_TABLE 1
|
||||||
typedef struct _ipfw_obj_header {
|
typedef struct _ipfw_obj_header {
|
||||||
ip_fw3_opheader opheader; /* IP_FW3 opcode */
|
ip_fw3_opheader opheader; /* IP_FW3 opcode */
|
||||||
|
@ -2001,6 +2001,9 @@ ipfw_ctl(struct sockopt *sopt)
|
|||||||
case IP_FW_TABLE_XFIND: /* IP_FW3 */
|
case IP_FW_TABLE_XFIND: /* IP_FW3 */
|
||||||
error = ipfw_find_table_entry(chain, op3, &sdata);
|
error = ipfw_find_table_entry(chain, op3, &sdata);
|
||||||
break;
|
break;
|
||||||
|
case IP_FW_TABLES_ALIST: /* IP_FW3 */
|
||||||
|
error = ipfw_list_table_algo(chain, &sdata);
|
||||||
|
break;
|
||||||
|
|
||||||
/*--- LEGACY API ---*/
|
/*--- LEGACY API ---*/
|
||||||
case IP_FW_TABLE_ADD:
|
case IP_FW_TABLE_ADD:
|
||||||
|
@ -1641,6 +1641,59 @@ ipfw_del_table_algo(struct ip_fw_chain *ch, int idx)
|
|||||||
free(ta, M_IPFW);
|
free(ta, M_IPFW);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lists all table algorithms currently available.
|
||||||
|
* Data layout (v0)(current):
|
||||||
|
* Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
|
||||||
|
* Reply: [ ipfw_obj_lheader ipfw_ta_info x N ]
|
||||||
|
*
|
||||||
|
* Returns 0 on success
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
ipfw_list_table_algo(struct ip_fw_chain *ch, struct sockopt_data *sd)
|
||||||
|
{
|
||||||
|
struct _ipfw_obj_lheader *olh;
|
||||||
|
struct tables_config *tcfg;
|
||||||
|
ipfw_ta_info *i;
|
||||||
|
struct table_algo *ta;
|
||||||
|
uint32_t count, n, size;
|
||||||
|
|
||||||
|
olh = (struct _ipfw_obj_lheader *)ipfw_get_sopt_header(sd,sizeof(*olh));
|
||||||
|
if (olh == NULL)
|
||||||
|
return (EINVAL);
|
||||||
|
if (sd->valsize < olh->size)
|
||||||
|
return (EINVAL);
|
||||||
|
|
||||||
|
IPFW_UH_RLOCK(ch);
|
||||||
|
tcfg = CHAIN_TO_TCFG(ch);
|
||||||
|
count = tcfg->algo_count;
|
||||||
|
size = count * sizeof(ipfw_ta_info) + sizeof(ipfw_obj_lheader);
|
||||||
|
|
||||||
|
/* Fill in header regadless of buffer size */
|
||||||
|
olh->count = count;
|
||||||
|
olh->objsize = sizeof(ipfw_ta_info);
|
||||||
|
|
||||||
|
if (size > olh->size) {
|
||||||
|
olh->size = size;
|
||||||
|
IPFW_UH_RUNLOCK(ch);
|
||||||
|
return (ENOMEM);
|
||||||
|
}
|
||||||
|
olh->size = size;
|
||||||
|
|
||||||
|
for (n = 1; n <= count; n++) {
|
||||||
|
i = (ipfw_ta_info *)ipfw_get_sopt_space(sd, sizeof(*i));
|
||||||
|
KASSERT(i != 0, ("previously checked buffer is not enough"));
|
||||||
|
ta = tcfg->algo[n];
|
||||||
|
strlcpy(i->algoname, ta->name, sizeof(i->algoname));
|
||||||
|
i->type = ta->type;
|
||||||
|
i->refcnt = ta->refcnt;
|
||||||
|
}
|
||||||
|
|
||||||
|
IPFW_UH_RUNLOCK(ch);
|
||||||
|
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Tables rewriting code
|
* Tables rewriting code
|
||||||
@ -1925,6 +1978,7 @@ link_table(struct ip_fw_chain *ch, struct table_config *tc)
|
|||||||
tc->ta->change_ti(tc->astate, ti);
|
tc->ta->change_ti(tc->astate, ti);
|
||||||
|
|
||||||
tc->linked = 1;
|
tc->linked = 1;
|
||||||
|
tc->ta->refcnt++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1949,6 +2003,7 @@ unlink_table(struct ip_fw_chain *ch, struct table_config *tc)
|
|||||||
ti = KIDX_TO_TI(ch, kidx);
|
ti = KIDX_TO_TI(ch, kidx);
|
||||||
memset(ti, 0, sizeof(struct table_info));
|
memset(ti, 0, sizeof(struct table_info));
|
||||||
tc->linked = 0;
|
tc->linked = 0;
|
||||||
|
tc->ta->refcnt--;
|
||||||
|
|
||||||
/* Notify algo on real @ti address */
|
/* Notify algo on real @ti address */
|
||||||
if (tc->ta->change_ti != NULL)
|
if (tc->ta->change_ti != NULL)
|
||||||
|
@ -98,6 +98,9 @@ typedef int ta_find_tentry(void *ta_state, struct table_info *ti, void *key,
|
|||||||
struct table_algo {
|
struct table_algo {
|
||||||
char name[16];
|
char name[16];
|
||||||
int idx;
|
int idx;
|
||||||
|
int type;
|
||||||
|
int refcnt;
|
||||||
|
int spare;
|
||||||
ta_init *init;
|
ta_init *init;
|
||||||
ta_destroy *destroy;
|
ta_destroy *destroy;
|
||||||
ta_prepare_add *prepare_add;
|
ta_prepare_add *prepare_add;
|
||||||
@ -140,6 +143,7 @@ int ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
|||||||
struct sockopt_data *sd);
|
struct sockopt_data *sd);
|
||||||
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
|
||||||
struct sockopt_data *sd);
|
struct sockopt_data *sd);
|
||||||
|
int ipfw_list_table_algo(struct ip_fw_chain *ch, struct sockopt_data *sd);
|
||||||
/* Exported to support legacy opcodes */
|
/* Exported to support legacy opcodes */
|
||||||
int add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
int add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
|
||||||
struct tentry_info *tei);
|
struct tentry_info *tei);
|
||||||
|
@ -516,6 +516,7 @@ ta_flush_cidr_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
|
|||||||
|
|
||||||
struct table_algo cidr_radix = {
|
struct table_algo cidr_radix = {
|
||||||
.name = "cidr:radix",
|
.name = "cidr:radix",
|
||||||
|
.type = IPFW_TABLE_CIDR,
|
||||||
.init = ta_init_radix,
|
.init = ta_init_radix,
|
||||||
.destroy = ta_destroy_radix,
|
.destroy = ta_destroy_radix,
|
||||||
.prepare_add = ta_prepare_add_cidr,
|
.prepare_add = ta_prepare_add_cidr,
|
||||||
@ -1194,6 +1195,7 @@ ta_flush_chash_entry(struct ip_fw_chain *ch, struct tentry_info *tei,
|
|||||||
|
|
||||||
struct table_algo cidr_hash = {
|
struct table_algo cidr_hash = {
|
||||||
.name = "cidr:hash",
|
.name = "cidr:hash",
|
||||||
|
.type = IPFW_TABLE_CIDR,
|
||||||
.init = ta_init_chash,
|
.init = ta_init_chash,
|
||||||
.destroy = ta_destroy_chash,
|
.destroy = ta_destroy_chash,
|
||||||
.prepare_add = ta_prepare_add_chash,
|
.prepare_add = ta_prepare_add_chash,
|
||||||
@ -1846,6 +1848,7 @@ ta_foreach_ifidx(void *ta_state, struct table_info *ti, ta_foreach_f *f,
|
|||||||
|
|
||||||
struct table_algo iface_idx = {
|
struct table_algo iface_idx = {
|
||||||
.name = "iface:array",
|
.name = "iface:array",
|
||||||
|
.type = IPFW_TABLE_INTERFACE,
|
||||||
.init = ta_init_ifidx,
|
.init = ta_init_ifidx,
|
||||||
.destroy = ta_destroy_ifidx,
|
.destroy = ta_destroy_ifidx,
|
||||||
.prepare_add = ta_prepare_add_ifidx,
|
.prepare_add = ta_prepare_add_ifidx,
|
||||||
|
Loading…
Reference in New Issue
Block a user