svn commit: r268329 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Sun Jul 6 18:16:06 UTC 2014
Author: melifaro
Date: Sun Jul 6 18:16:04 2014
New Revision: 268329
URL: http://svnweb.freebsd.org/changeset/base/268329
Log:
* Add "lookup" table functionality to permit userland entry lookups.
* Bump table dump format preserving old ABI.
Kernel size:
* Add IP_FW_TABLE_XFIND to handle "lookup" request from userland.
* Add ta_find_tentry() algorithm callbacks/handlers to support lookups.
* Fully switch to ipfw_obj_tentry for various table dumps:
algorithms are now required to support the latest (ipfw_obj_tentry) entry
dump format, the rest is handled by generic dump code.
IP_FW_TABLE_XLIST opcode version bumped (0 -> 1).
* Eliminate legacy ta_dump_entry algo handler:
dump_table_entry() converts data from current to legacy format.
Userland side:
* Add "lookup" table parameter.
* Change the way table type is guessed: call table_get_info() first,
and check value for IPv4/IPv6 type IFF table does not exist.
* Fix table_get_list(): do more tries if supplied buffer is not enough.
* Sparate table_show_entry() from table_show_list().
Modified:
projects/ipfw/sbin/ipfw/tables.c
projects/ipfw/sys/netinet/ip_fw.h
projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c
Modified: projects/ipfw/sbin/ipfw/tables.c
==============================================================================
--- projects/ipfw/sbin/ipfw/tables.c Sun Jul 6 17:57:59 2014 (r268328)
+++ projects/ipfw/sbin/ipfw/tables.c Sun Jul 6 18:16:04 2014 (r268329)
@@ -55,6 +55,7 @@ static int table_flush(ipfw_obj_header *
static int table_destroy(ipfw_obj_header *oh);
static int table_do_create(ipfw_obj_header *oh, ipfw_xtable_info *i);
static void table_create(ipfw_obj_header *oh, int ac, char *av[]);
+static void table_lookup(ipfw_obj_header *oh, int ac, char *av[]);
static int table_get_info(ipfw_obj_header *oh, ipfw_xtable_info *i);
static int table_show_info(ipfw_xtable_info *i, void *arg);
static void table_fill_ntlv(ipfw_obj_ntlv *ntlv, char *name, uint32_t set,
@@ -64,9 +65,10 @@ static int table_flush_one(ipfw_xtable_i
static int table_show_one(ipfw_xtable_info *i, void *arg);
static int table_get_list(ipfw_xtable_info *i, ipfw_obj_header *oh);
static void table_show_list(ipfw_obj_header *oh, int need_header);
+static void table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent);
static void tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent,
- char *key, uint8_t *ptype, uint8_t *pvtype);
+ char *key, uint8_t *ptype, uint8_t *pvtype, ipfw_xtable_info *xi);
static void tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent,
char *arg, uint8_t type, uint8_t vtype);
@@ -99,6 +101,7 @@ static struct _s_x tablecmds[] = {
{ "flush", TOK_FLUSH },
{ "info", TOK_INFO },
{ "list", TOK_LIST },
+ { "lookup", TOK_LOOKUP },
{ NULL, 0 }
};
@@ -147,7 +150,6 @@ ipfw_table_handler(int ac, char *av[])
if (table_check_name(tablename) == 0) {
table_fill_ntlv(&oh.ntlv, *av, set, 1);
- //oh->set = set;
oh.idx = 1;
} else {
if (strcmp(tablename, "all") == 0)
@@ -220,6 +222,10 @@ ipfw_table_handler(int ac, char *av[])
err(EX_OSERR, "failed to request tables list");
}
break;
+ case TOK_LOOKUP:
+ ac--; av++;
+ table_lookup(&oh, ac, av);
+ break;
}
}
@@ -238,9 +244,8 @@ static void
table_fill_objheader(ipfw_obj_header *oh, ipfw_xtable_info *i)
{
- oh->set = i->set;
oh->idx = 1;
- table_fill_ntlv(&oh->ntlv, i->tablename, oh->set, 1);
+ table_fill_ntlv(&oh->ntlv, i->tablename, i->set, 1);
}
static struct _s_x tablenewcmds[] = {
@@ -284,7 +289,6 @@ table_create(ipfw_obj_header *oh, int ac
NEED1("table type required");
val = match_token(tabletypes, *av);
if (val != -1) {
- printf("av %s type %d\n", *av, xi.type);
xi.type = val;
ac--; av++;
break;
@@ -429,12 +433,17 @@ static int
table_show_one(ipfw_xtable_info *i, void *arg)
{
ipfw_obj_header *oh;
+ int error;
if ((oh = calloc(1, i->size)) == NULL)
return (ENOMEM);
- if (table_get_list(i, oh) == 0)
- table_show_list(oh, 1);
+ if ((error = table_get_list(i, oh)) != 0) {
+ err(EX_OSERR, "Error requesting table %s list", i->tablename);
+ return (error);
+ }
+
+ table_show_list(oh, 1);
free(oh);
return (0);
@@ -467,7 +476,7 @@ table_do_modify_record(int cmd, ipfw_obj
memcpy(oh + 1, tent, sizeof(*tent));
tent = (ipfw_obj_tentry *)(oh + 1);
if (update != 0)
- tent->flags |= IPFW_TF_UPDATE;
+ tent->head.flags |= IPFW_TF_UPDATE;
tent->head.length = sizeof(ipfw_obj_tentry);
error = do_set3(cmd, &oh->opheader, sizeof(xbuf));
@@ -479,6 +488,7 @@ static void
table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add, int update)
{
ipfw_obj_tentry tent;
+ ipfw_xtable_info xi;
uint8_t type, vtype;
int cmd;
char *texterr;
@@ -490,7 +500,7 @@ table_modify_record(ipfw_obj_header *oh,
tent.head.length = sizeof(tent);
tent.idx = 1;
- tentry_fill_key(oh, &tent, *av, &type, &vtype);
+ tentry_fill_key(oh, &tent, *av, &type, &vtype, &xi);
oh->ntlv.type = type;
ac--; av++;
@@ -508,6 +518,67 @@ table_modify_record(ipfw_obj_header *oh,
err(EX_OSERR, "%s", texterr);
}
+static int
+table_do_lookup(ipfw_obj_header *oh, char *key, ipfw_xtable_info *xi,
+ ipfw_obj_tentry *xtent)
+{
+ char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)];
+ ipfw_obj_tentry *tent;
+ uint8_t type, vtype;
+ int error;
+ size_t sz;
+
+ memcpy(xbuf, oh, sizeof(*oh));
+ oh = (ipfw_obj_header *)xbuf;
+ tent = (ipfw_obj_tentry *)(oh + 1);
+
+ memset(tent, 0, sizeof(*tent));
+ tent->head.length = sizeof(*tent);
+ tent->idx = 1;
+
+ tentry_fill_key(oh, tent, key, &type, &vtype, xi);
+ oh->ntlv.type = type;
+
+ sz = sizeof(xbuf);
+ if ((error = do_get3(IP_FW_TABLE_XFIND, &oh->opheader, &sz)) != 0)
+ return (error);
+
+ if (sz < sizeof(xbuf))
+ return (EINVAL);
+
+ *xtent = *tent;
+
+ return (0);
+}
+
+static void
+table_lookup(ipfw_obj_header *oh, int ac, char *av[])
+{
+ ipfw_obj_tentry xtent;
+ ipfw_xtable_info xi;
+ int error;
+
+ if (ac == 0)
+ errx(EX_USAGE, "address required");
+
+ error = table_do_lookup(oh, *av, &xi, &xtent);
+
+ switch (error) {
+ case 0:
+ break;
+ case ESRCH:
+ errx(EX_UNAVAILABLE, "Table %s not found", oh->ntlv.name);
+ case ENOENT:
+ errx(EX_UNAVAILABLE, "Entry %s not found", *av);
+ case ENOTSUP:
+ errx(EX_UNAVAILABLE, "Table %s algo does not support "
+ "\"lookup\" method", oh->ntlv.name);
+ default:
+ err(EX_OSERR, "getsockopt(IP_FW_TABLE_XFIND)");
+ }
+
+ table_show_entry(&xi, &xtent);
+}
static void
tentry_fill_key_type(char *arg, ipfw_obj_tentry *tentry, uint8_t type)
@@ -584,39 +655,43 @@ tentry_fill_key_type(char *arg, ipfw_obj
static void
tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key,
- uint8_t *ptype, uint8_t *pvtype)
+ uint8_t *ptype, uint8_t *pvtype, ipfw_xtable_info *xi)
{
- ipfw_xtable_info xi;
uint8_t type, vtype;
int error;
type = 0;
vtype = 0;
- /*
- * Compability layer. Try to interpret data as CIDR first.
- */
- if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 ||
- inet_pton(AF_INET6, key, &tent->k.addr6) == 1) {
- /* OK Prepare and send */
- type = IPFW_TABLE_CIDR;
- } else {
+ error = table_get_info(oh, xi);
+ if (error == 0) {
+ /* Table found. */
+ type = xi->type;
+ vtype = xi->vtype;
+ } else {
+ if (error != ESRCH)
+ errx(EX_OSERR, "Error requesting table %s info",
+ oh->ntlv.name);
/*
- * Non-CIDR of FQDN hostname. Ask kernel
- * about given table.
+ * Table does not exist.
+ * Compability layer: try to interpret data as CIDR
+ * before failing.
*/
- error = table_get_info(oh, &xi);
- if (error == ESRCH)
- errx(EX_USAGE, "Table %s does not exist, cannot intuit "
+ if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 ||
+ inet_pton(AF_INET6, key, &tent->k.addr6) == 1) {
+ /* OK Prepare and send */
+ type = IPFW_TABLE_CIDR;
+ /*
+ * XXX: Value type is forced to be u32.
+ * This should be changed for MFC.
+ */
+ vtype = IPFW_VTYPE_U32;
+ } else {
+ /* Inknown key */
+ errx(EX_USAGE, "Table %s does not exist, cannot guess "
"key type", oh->ntlv.name);
- else if (error != 0)
- errx(EX_OSERR, "Error requesting table %s info",
- oh->ntlv.name);
-
- /* Table found. */
- type = xi.type;
- vtype = xi.vtype;
+ }
}
tentry_fill_key_type(key, tent, type);
@@ -629,29 +704,9 @@ static void
tentry_fill_value(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *arg,
uint8_t type, uint8_t vtype)
{
- ipfw_xtable_info xi;
- int error;
int code;
char *p;
- if (vtype == 0) {
- /* Format type is unknown, ask kernel */
- error = table_get_info(oh, &xi);
- if (error == ESRCH) {
-
- /*
- * XXX: This one may break some scripts.
- * Change this behavior for MFC.
- */
- errx(EX_USAGE, "Table %s does not exist. Unable to "
- "guess value format.", oh->ntlv.name);
- } else if (error != 0)
- errx(EX_OSERR, "Error requesting table %s info",
- oh->ntlv.name);
-
- vtype = xi.vtype;
- }
-
switch (vtype) {
case IPFW_VTYPE_U32:
tent->value = strtoul(arg, &p, 0);
@@ -758,17 +813,22 @@ static int
table_get_list(ipfw_xtable_info *i, ipfw_obj_header *oh)
{
size_t sz;
- int error;
+ int error, c;
- table_fill_objheader(oh, i);
- sz = i->size;
+ sz = 0;
+ for (c = 0; c < 3; c++) {
+ table_fill_objheader(oh, i);
+ if (sz < i->size)
+ sz = i->size;
- oh->opheader.version = 1; /* Current version */
+ oh->opheader.version = 1; /* Current version */
+ error = do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz);
- if ((error = do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz)) != 0)
- return (errno);
+ if (error != ENOMEM)
+ return (errno);
+ }
- return (0);
+ return (ENOMEM);
}
/*
@@ -777,56 +837,52 @@ table_get_list(ipfw_xtable_info *i, ipfw
static void
table_show_list(ipfw_obj_header *oh, int need_header)
{
- ipfw_table_xentry *xent;
- uint32_t count, tval;
- char tbuf[128];
- struct in6_addr *addr6;
+ ipfw_obj_tentry *tent;
+ uint32_t count;
ipfw_xtable_info *i;
i = (ipfw_xtable_info *)(oh + 1);
- xent = (ipfw_table_xentry *)(i + 1);
+ tent = (ipfw_obj_tentry *)(i + 1);
if (need_header)
printf("--- table(%s), set(%u) ---\n", i->tablename, i->set);
count = i->count;
while (count > 0) {
- switch (i->type) {
- case IPFW_TABLE_CIDR:
- /* IPv4 or IPv6 prefixes */
- tval = xent->value;
- addr6 = &xent->k.addr6;
+ table_show_entry(i, tent);
+ tent = (ipfw_obj_tentry *)((caddr_t)tent + tent->head.length);
+ count--;
+ }
+}
+static void
+table_show_entry(ipfw_xtable_info *i, ipfw_obj_tentry *tent)
+{
+ char tbuf[128];
+ uint32_t tval;
- if ((xent->flags & IPFW_TCF_INET) != 0) {
- /* IPv4 address */
- inet_ntop(AF_INET, &addr6->s6_addr32[3], tbuf,
- sizeof(tbuf));
- } else {
- /* IPv6 address */
- inet_ntop(AF_INET6, addr6, tbuf, sizeof(tbuf));
- }
+ tval = tent->value;
- if (co.do_value_as_ip) {
- tval = htonl(tval);
- printf("%s/%u %s\n", tbuf, xent->masklen,
- inet_ntoa(*(struct in_addr *)&tval));
- } else
- printf("%s/%u %u\n", tbuf, xent->masklen, tval);
- break;
- case IPFW_TABLE_INTERFACE:
- /* Interface names */
- tval = xent->value;
- if (co.do_value_as_ip) {
- tval = htonl(tval);
- printf("%s %s\n", xent->k.iface,
- inet_ntoa(*(struct in_addr *)&tval));
- } else
- printf("%s %u\n", xent->k.iface, tval);
- }
+ switch (i->type) {
+ case IPFW_TABLE_CIDR:
+ /* IPv4 or IPv6 prefixes */
+ inet_ntop(tent->subtype, &tent->k, tbuf, sizeof(tbuf));
- xent = (ipfw_table_xentry *)((caddr_t)xent + xent->len);
- count--;
+ if (co.do_value_as_ip) {
+ tval = htonl(tval);
+ printf("%s/%u %s\n", tbuf, tent->masklen,
+ inet_ntoa(*(struct in_addr *)&tval));
+ } else
+ printf("%s/%u %u\n", tbuf, tent->masklen, tval);
+ break;
+ case IPFW_TABLE_INTERFACE:
+ /* Interface names */
+ if (co.do_value_as_ip) {
+ tval = htonl(tval);
+ printf("%s %s\n", tent->k.iface,
+ inet_ntoa(*(struct in_addr *)&tval));
+ } else
+ printf("%s %u\n", tent->k.iface, tval);
}
}
Modified: projects/ipfw/sys/netinet/ip_fw.h
==============================================================================
--- projects/ipfw/sys/netinet/ip_fw.h Sun Jul 6 17:57:59 2014 (r268328)
+++ projects/ipfw/sys/netinet/ip_fw.h Sun Jul 6 18:16:04 2014 (r268329)
@@ -89,6 +89,7 @@ typedef struct _ip_fw3_opheader {
//#define IP_FW_TABLE_XMODIFY 96 /* modify existing table */
#define IP_FW_XGET 97 /* Retrieve configuration */
#define IP_FW_XADD 98 /* add entry */
+#define IP_FW_TABLE_XFIND 99 /* finds an entry */
/*
* Usage guidelines:
@@ -713,10 +714,8 @@ typedef struct _ipfw_obj_tentry {
uint8_t subtype; /* subtype (IPv4,IPv6) */
uint8_t masklen; /* mask length */
uint16_t idx; /* Table name index */
- uint16_t flags; /* Entry flags */
- uint16_t spare0;
- uint32_t spare1;
uint32_t value; /* value */
+ uint64_t spare;
union {
/* Longest field needs to be aligned by 8-byte boundary */
struct in_addr addr; /* IPv4 address */
@@ -751,7 +750,7 @@ typedef struct _ipfw_xtable_info {
#define IPFW_OBJTYPE_TABLE 1
typedef struct _ipfw_obj_header {
ip_fw3_opheader opheader; /* IP_FW3 opcode */
- uint32_t set; /* Set we're operating */
+ uint32_t spare;
uint16_t idx; /* object name index */
uint8_t objtype; /* object type */
uint8_t objsubtype; /* object subtype */
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Jul 6 17:57:59 2014 (r268328)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Jul 6 18:16:04 2014 (r268329)
@@ -1726,6 +1726,9 @@ ipfw_ctl(struct sockopt *sopt)
case IP_FW_TABLE_XDEL: /* IP_FW3 */
error = ipfw_modify_table(chain, op3, &sdata);
break;
+ case IP_FW_TABLE_XFIND: /* IP_FW3 */
+ error = ipfw_find_table_entry(chain, op3, &sdata);
+ break;
/*--- LEGACY API ---*/
case IP_FW_TABLE_ADD:
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Sun Jul 6 17:57:59 2014 (r268328)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Sun Jul 6 18:16:04 2014 (r268329)
@@ -105,6 +105,7 @@ static int export_tables(struct ip_fw_ch
struct sockopt_data *sd);
static void export_table_info(struct ip_fw_chain *ch, struct table_config *tc,
ipfw_xtable_info *i);
+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);
@@ -406,19 +407,18 @@ ipfw_modify_table_v1(struct ip_fw_chain
tent->head.length + read > sd->valsize)
return (EINVAL);
+ /* Convert data into kernel request objects */
memset(&tei, 0, sizeof(tei));
tei.paddr = &tent->k;
tei.subtype = tent->subtype;
tei.masklen = tent->masklen;
- if (tent->flags & IPFW_TF_UPDATE)
+ if (tent->head.flags & IPFW_TF_UPDATE)
tei.flags |= TEI_FLAGS_UPDATE;
tei.value = tent->value;
- memset(&ti, 0, sizeof(ti));
- ti.uidx = tent->idx;
+ objheader_to_ti(oh, &ti);
ti.type = oh->ntlv.type;
- ti.tlvs = &oh->ntlv;
- ti.tlen = oh->ntlv.head.length;
+ ti.uidx = tent->idx;
error = (oh->opheader.opcode == IP_FW_TABLE_XADD) ?
add_table_entry(ch, &ti, &tei) :
@@ -427,6 +427,101 @@ ipfw_modify_table_v1(struct ip_fw_chain
return (error);
}
+/*
+ * Looks up an entry in given table.
+ * Data layout (v0)(current):
+ * Request: [ ipfw_obj_header ipfw_obj_tentry ]
+ * Reply: [ ipfw_obj_header ipfw_obj_tentry ]
+ *
+ * Returns 0 on success
+ */
+int
+ipfw_find_table_entry(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
+{
+ ipfw_obj_tentry *tent;
+ ipfw_obj_header *oh;
+ struct tid_info ti;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct table_info *kti;
+ struct namedobj_instance *ni;
+ int error, plen;
+ void *paddr;
+ size_t sz;
+
+ /* Check minimum header size */
+ sz = sizeof(*oh) + sizeof(*tent);
+ if (sd->valsize != sz)
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+ tent = (ipfw_obj_tentry *)(oh + 1);
+
+ /* Basic length checks for TLVs */
+ if (oh->ntlv.head.length != sizeof(oh->ntlv))
+ return (EINVAL);
+
+ objheader_to_ti(oh, &ti);
+ ti.type = oh->ntlv.type;
+ ti.uidx = tent->idx;
+
+ IPFW_UH_RLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+
+ /*
+ * Find existing table and check its type .
+ */
+ ta = NULL;
+ if ((tc = find_table(ni, &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ return (ESRCH);
+ }
+
+ /* check table type */
+ if (tc->no.type != ti.type) {
+ IPFW_UH_RUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ /* Check lookup key for validness */
+ plen = 0;
+ paddr = &tent->k;
+ switch (ti.type)
+ {
+ case IPFW_TABLE_CIDR:
+ if (tent->subtype == AF_INET)
+ plen = sizeof(struct in_addr);
+ else if (tent->subtype == AF_INET6)
+ plen = sizeof(struct in6_addr);
+ else {
+ IPFW_UH_RUNLOCK(ch);
+ return (EINVAL);
+ }
+ break;
+ case IPFW_TABLE_INTERFACE:
+ /* Check key first */
+ plen = sizeof(tent->k.iface);
+ if (strnlen(tent->k.iface, plen) == plen) {
+ IPFW_UH_RUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ break;
+ default:
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOTSUP);
+ }
+ kti = KIDX_TO_TI(ch, tc->no.kidx);
+ ta = tc->ta;
+
+ error = ta->find_tentry(tc->astate, kti, paddr, plen, tent);
+
+ IPFW_UH_RUNLOCK(ch);
+
+ return (error);
+}
+
int
ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd)
@@ -807,8 +902,10 @@ struct dump_args {
struct sockopt_data *sd;
uint32_t cnt;
uint16_t uidx;
+ int error;
ipfw_table_entry *ent;
uint32_t size;
+ ipfw_obj_tentry tent;
};
int
@@ -835,7 +932,7 @@ ipfw_dump_table(struct ip_fw_chain *ch,
* Dumps all table data
* Data layout (v1)(current):
* Request: [ ipfw_obj_header ], size = ipfw_xtable_info.size
- * Reply: [ ipfw_obj_header ipfw_xtable_info ipfw_table_xentry x N ]
+ * Reply: [ ipfw_obj_header ipfw_xtable_info ipfw_obj_tentry x N ]
*
* Returns 0 on success
*/
@@ -866,7 +963,7 @@ ipfw_dump_table_v1(struct ip_fw_chain *c
export_table_info(ch, tc, i);
sz = tc->count;
- if (sd->valsize < sz + tc->count * sizeof(ipfw_table_xentry)) {
+ if (sd->valsize < sz + tc->count * sizeof(ipfw_obj_tentry)) {
/*
* Submitted buffer size is not enough.
@@ -888,10 +985,10 @@ ipfw_dump_table_v1(struct ip_fw_chain *c
ta = tc->ta;
- ta->foreach(tc->astate, da.ti, dump_table_xentry, &da);
+ ta->foreach(tc->astate, da.ti, dump_table_tentry, &da);
IPFW_UH_RUNLOCK(ch);
- return (0);
+ return (da.error);
}
/*
@@ -1045,7 +1142,7 @@ objheader_to_ti(struct _ipfw_obj_header
{
memset(ti, 0, sizeof(struct tid_info));
- ti->set = oh->set;
+ ti->set = oh->ntlv.set;
ti->uidx = oh->idx;
ti->tlvs = &oh->ntlv;
ti->tlen = oh->ntlv.head.length;
@@ -1088,7 +1185,7 @@ export_table_info(struct ip_fw_chain *ch
i->kidx = tc->no.kidx;
i->refcnt = tc->no.refcnt;
i->count = tc->count;
- i->size = tc->count * sizeof(ipfw_table_xentry);
+ i->size = tc->count * sizeof(ipfw_obj_tentry);
i->size += sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
if (tc->ta->print_config != NULL) {
@@ -1155,6 +1252,9 @@ export_tables(struct ip_fw_chain *ch, ip
return (0);
}
+/*
+ * Legacy IP_FW_TABLE_GETSIZE handler
+ */
int
ipfw_count_table(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
{
@@ -1167,6 +1267,9 @@ ipfw_count_table(struct ip_fw_chain *ch,
}
+/*
+ * Legacy IP_FW_TABLE_XGETSIZE handler
+ */
int
ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
{
@@ -1189,6 +1292,7 @@ dump_table_entry(void *e, void *arg)
struct table_config *tc;
struct table_algo *ta;
ipfw_table_entry *ent;
+ int error;
da = (struct dump_args *)arg;
@@ -1202,7 +1306,15 @@ dump_table_entry(void *e, void *arg)
ent->tbl = da->uidx;
da->cnt++;
- return (ta->dump_entry(tc->astate, da->ti, e, ent));
+ error = ta->dump_tentry(tc->astate, da->ti, e, &da->tent);
+ if (error != 0)
+ return (error);
+
+ ent->addr = da->tent.k.addr.s_addr;
+ ent->masklen = da->tent.masklen;
+ ent->value = da->tent.value;
+
+ return (0);
}
/*
@@ -1223,8 +1335,9 @@ ipfw_dump_table_legacy(struct ip_fw_chai
ta = tc->ta;
- if (ta->dump_entry == NULL)
- return (0); /* Legacy dump support is not necessary */
+ /* This dump format supports IPv4 only */
+ if (tc->no.type != IPFW_TABLE_CIDR)
+ return (0);
memset(&da, 0, sizeof(da));
da.ti = KIDX_TO_TI(ch, tc->no.kidx);
@@ -1240,7 +1353,35 @@ ipfw_dump_table_legacy(struct ip_fw_chai
}
/*
- * Dumps table entry in eXtended format (current).
+ * Dumps table entry in eXtended format (v1)(current).
+ */
+static int
+dump_table_tentry(void *e, void *arg)
+{
+ struct dump_args *da;
+ struct table_config *tc;
+ struct table_algo *ta;
+ ipfw_obj_tentry *tent;
+
+ da = (struct dump_args *)arg;
+
+ tc = da->tc;
+ ta = tc->ta;
+
+ tent = (ipfw_obj_tentry *)ipfw_get_sopt_space(da->sd, sizeof(*tent));
+ /* Out of memory, returning */
+ if (tent == NULL) {
+ da->error = ENOMEM;
+ return (1);
+ }
+ tent->head.length = sizeof(ipfw_obj_tentry);
+ tent->idx = da->uidx;
+
+ return (ta->dump_tentry(tc->astate, da->ti, e, tent));
+}
+
+/*
+ * Dumps table entry in eXtended format (v0).
*/
static int
dump_table_xentry(void *e, void *arg)
@@ -1249,6 +1390,8 @@ dump_table_xentry(void *e, void *arg)
struct table_config *tc;
struct table_algo *ta;
ipfw_table_xentry *xent;
+ ipfw_obj_tentry *tent;
+ int error;
da = (struct dump_args *)arg;
@@ -1262,7 +1405,23 @@ dump_table_xentry(void *e, void *arg)
xent->len = sizeof(ipfw_table_xentry);
xent->tbl = da->uidx;
- return (ta->dump_xentry(tc->astate, da->ti, e, xent));
+ memset(&da->tent, 0, sizeof(da->tent));
+ tent = &da->tent;
+ error = ta->dump_tentry(tc->astate, da->ti, e, tent);
+ if (error != 0)
+ return (error);
+
+ /* Convert current format to previous one */
+ xent->masklen = tent->masklen;
+ xent->value = tent->value;
+ /* Apply some hacks */
+ if (tc->no.type == IPFW_TABLE_CIDR && tent->subtype == AF_INET) {
+ xent->k.addr6.s6_addr32[3] = tent->k.addr.s_addr;
+ xent->flags = IPFW_TCF_INET;
+ } else
+ memcpy(&xent->k, &tent->k, sizeof(xent->k));
+
+ return (0);
}
/*
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Sun Jul 6 17:57:59 2014 (r268328)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Sun Jul 6 18:16:04 2014 (r268329)
@@ -77,10 +77,10 @@ typedef void (ta_print_config)(void *ta_
typedef int ta_foreach_f(void *node, void *arg);
typedef void ta_foreach(void *ta_state, struct table_info *ti, ta_foreach_f *f,
void *arg);
-typedef int ta_dump_entry(void *ta_state, struct table_info *ti, void *e,
- ipfw_table_entry *ent);
-typedef int ta_dump_xentry(void *ta_state, struct table_info *ti, void *e,
- ipfw_table_xentry *xent);
+typedef int ta_dump_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent);
+typedef int ta_find_tentry(void *ta_state, struct table_info *ti, void *key,
+ uint32_t keylen, ipfw_obj_tentry *tent);
struct table_algo {
char name[16];
@@ -94,9 +94,9 @@ struct table_algo {
ta_del *del;
ta_flush_entry *flush_entry;
ta_foreach *foreach;
- ta_dump_entry *dump_entry;
- ta_dump_xentry *dump_xentry;
+ ta_dump_tentry *dump_tentry;
ta_print_config *print_config;
+ ta_find_tentry *find_tentry;
};
void ipfw_add_table_algo(struct ip_fw_chain *ch, struct table_algo *ta);
extern struct table_algo radix_cidr, radix_iface;
@@ -112,6 +112,8 @@ int ipfw_dump_table(struct ip_fw_chain *
struct sockopt_data *sd);
int ipfw_describe_table(struct ip_fw_chain *ch, 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,
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Sun Jul 6 17:57:59 2014 (r268328)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Sun Jul 6 18:16:04 2014 (r268329)
@@ -208,30 +208,8 @@ ta_destroy_radix(void *ta_state, struct
}
static int
-ta_dump_radix_entry(void *ta_state, struct table_info *ti, void *e,
- ipfw_table_entry *ent)
-{
- struct table_entry *n;
-
- n = (struct table_entry *)e;
-
- /* Guess IPv4/IPv6 radix by sockaddr family */
- if (n->addr.sin_family != AF_INET)
- return (0);
-
- if (in_nullhost(n->mask.sin_addr))
- ent->masklen = 0;
- else
- ent->masklen = 33 - ffs(ntohl(n->mask.sin_addr.s_addr));
- ent->addr = n->addr.sin_addr.s_addr;
- ent->value = n->value;
-
- return (0);
-}
-
-static int
-ta_dump_radix_xentry(void *ta_state, struct table_info *ti, void *e,
- ipfw_table_xentry *xent)
+ta_dump_radix_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
{
struct table_entry *n;
struct table_xentry *xn;
@@ -245,28 +223,59 @@ ta_dump_radix_xentry(void *ta_state, str
/* Guess IPv4/IPv6 radix by sockaddr family */
if (n->addr.sin_family == AF_INET) {
if (in_nullhost(n->mask.sin_addr))
- xent->masklen = 0;
+ tent->masklen = 0;
else
- xent->masklen = 33-ffs(ntohl(n->mask.sin_addr.s_addr));
+ tent->masklen = 33-ffs(ntohl(n->mask.sin_addr.s_addr));
/* Save IPv4 address as deprecated IPv6 compatible */
- xent->k.addr6.s6_addr32[3] = n->addr.sin_addr.s_addr;
- xent->flags = IPFW_TCF_INET;
- xent->value = n->value;
+ tent->k.addr.s_addr = n->addr.sin_addr.s_addr;
+ tent->subtype = AF_INET;
+ tent->value = n->value;
#ifdef INET6
} else {
xn = (struct table_xentry *)e;
/* Count IPv6 mask */
v = (uint32_t *)&xn->m.mask6.sin6_addr;
for (i = 0; i < sizeof(struct in6_addr) / 4; i++, v++)
- xent->masklen += bitcount32(*v);
- memcpy(&xent->k, &xn->a.addr6.sin6_addr, sizeof(struct in6_addr));
- xent->value = xn->value;
+ tent->masklen += bitcount32(*v);
+ memcpy(&tent->k, &xn->a.addr6.sin6_addr, sizeof(struct in6_addr));
+ tent->subtype = AF_INET6;
+ tent->value = xn->value;
#endif
}
return (0);
}
+static int
+ta_find_radix_tentry(void *ta_state, struct table_info *ti, void *key,
+ uint32_t keylen, ipfw_obj_tentry *tent)
+{
+ struct radix_node_head *rnh;
+ void *e;
+
+ e = NULL;
+ if (keylen == sizeof(in_addr_t)) {
+ struct sockaddr_in sa;
+ KEY_LEN(sa) = KEY_LEN_INET;
+ sa.sin_addr.s_addr = *((in_addr_t *)key);
+ rnh = (struct radix_node_head *)ti->state;
+ e = rnh->rnh_matchaddr(&sa, rnh);
+ } else {
+ struct sockaddr_in6 sa6;
+ KEY_LEN(sa6) = KEY_LEN_INET6;
+ memcpy(&sa6.sin6_addr, key, sizeof(struct in6_addr));
+ rnh = (struct radix_node_head *)ti->xstate;
+ e = rnh->rnh_matchaddr(&sa6, rnh);
+ }
+
+ if (e != NULL) {
+ ta_dump_radix_tentry(ta_state, ti, e, tent);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
static void
ta_foreach_radix(void *ta_state, struct table_info *ti, ta_foreach_f *f,
void *arg)
@@ -495,7 +504,7 @@ ta_del_cidr(void *ta_state, struct table
tb->ent_ptr = rn;
if (rn == NULL)
- return (ESRCH);
+ return (ENOENT);
return (0);
}
@@ -522,8 +531,8 @@ struct table_algo radix_cidr = {
.del = ta_del_cidr,
.flush_entry = ta_flush_cidr_entry,
.foreach = ta_foreach_radix,
- .dump_entry = ta_dump_radix_entry,
- .dump_xentry = ta_dump_radix_xentry,
+ .dump_tentry = ta_dump_radix_tentry,
+ .find_tentry = ta_find_radix_tentry,
};
@@ -724,7 +733,7 @@ ta_del_iface(void *ta_state, struct tabl
tb->ent_ptr = rn;
if (rn == NULL)
- return (ESRCH);
+ return (ENOENT);
return (0);
}
@@ -741,19 +750,42 @@ ta_flush_iface_entry(struct tentry_info
}
static int
-ta_dump_iface_xentry(void *ta_state, struct table_info *ti, void *e,
- ipfw_table_xentry *xent)
+ta_dump_iface_tentry(void *ta_state, struct table_info *ti, void *e,
+ ipfw_obj_tentry *tent)
{
struct table_xentry *xn;
xn = (struct table_xentry *)e;
- xent->masklen = 8 * IF_NAMESIZE;
- memcpy(&xent->k, &xn->a.iface.ifname, IF_NAMESIZE);
- xent->value = xn->value;
+ tent->masklen = 8 * IF_NAMESIZE;
+ memcpy(&tent->k, &xn->a.iface.ifname, IF_NAMESIZE);
+ tent->value = xn->value;
return (0);
}
+static int
+ta_find_iface_tentry(void *ta_state, struct table_info *ti, void *key,
+ uint32_t keylen, ipfw_obj_tentry *tent)
+{
+ struct radix_node_head *rnh;
+ struct xaddr_iface iface;
+ void *e;
+ e = NULL;
+
+ KEY_LEN(iface) = KEY_LEN_IFACE +
+ strlcpy(iface.ifname, (char *)key, IF_NAMESIZE) + 1;
+
+ rnh = (struct radix_node_head *)ti->xstate;
+ e = rnh->rnh_matchaddr(&iface, rnh);
+
+ if (e != NULL) {
+ ta_dump_iface_tentry(ta_state, ti, e, tent);
+ return (0);
+ }
+
+ return (ENOENT);
+}
+
static void
ta_foreach_iface(void *ta_state, struct table_info *ti, ta_foreach_f *f,
void *arg)
@@ -775,7 +807,8 @@ struct table_algo radix_iface = {
.del = ta_del_iface,
.flush_entry = ta_flush_iface_entry,
.foreach = ta_foreach_iface,
- .dump_xentry = ta_dump_iface_xentry,
+ .dump_tentry = ta_dump_iface_tentry,
+ .find_tentry = ta_find_iface_tentry,
};
void
More information about the svn-src-projects
mailing list