svn commit: r267509 - in projects/ipfw: sbin/ipfw sys/netinet sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Sun Jun 15 13:40:29 UTC 2014
Author: melifaro
Date: Sun Jun 15 13:40:27 2014
New Revision: 267509
URL: http://svnweb.freebsd.org/changeset/base/267509
Log:
Simplify opcode handling.
* Use one u16 from op3 header to implement opcode versioning.
* IP_FW_TABLE_XLIST has now 2 handlers, for ver.0 (old) and ver.1 (current).
* Every getsockopt request is now handled in ip_fw_table.c
* Rename new opcodes:
IP_FW_OBJ_DEL -> IP_FW_TABLE_XDESTROY
IP_FW_OBJ_LISTSIZE -> IP_FW_TABLES_XGETSIZE
IP_FW_OBJ_LIST -> IP_FW_TABLES_XLIST
IP_FW_OBJ_INFO -> IP_FW_TABLE_XINFO
IP_FW_OBJ_INFO -> IP_FW_TABLE_XFLUSH
* Add some docs about using given opcodes.
* Group some legacy opcode/handlers.
Modified:
projects/ipfw/sbin/ipfw/tables.c
projects/ipfw/sys/netinet/ip_fw.h
projects/ipfw/sys/netpfil/ipfw/ip_fw_private.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
Modified: projects/ipfw/sbin/ipfw/tables.c
==============================================================================
--- projects/ipfw/sbin/ipfw/tables.c Sun Jun 15 12:21:06 2014 (r267508)
+++ projects/ipfw/sbin/ipfw/tables.c Sun Jun 15 13:40:27 2014 (r267509)
@@ -317,7 +317,6 @@ table_fill_objheader(ipfw_obj_header *oh
oh->set = i->set;
oh->idx = 1;
- oh->objtype = IPFW_OBJTYPE_TABLE;
table_fill_ntlv(&oh->ntlv, i->tablename, 1);
}
@@ -332,9 +331,8 @@ table_destroy(char *name, uint32_t set)
memset(&oh, 0, sizeof(oh));
oh.idx = 1;
- oh.objtype = IPFW_OBJTYPE_TABLE;
table_fill_ntlv(&oh.ntlv, name, 1);
- if (do_set3(IP_FW_OBJ_DEL, &oh.opheader, sizeof(oh)) != 0)
+ if (do_set3(IP_FW_TABLE_XDESTROY, &oh.opheader, sizeof(oh)) != 0)
return (-1);
return (0);
@@ -351,9 +349,8 @@ table_flush(char *name, uint32_t set)
memset(&oh, 0, sizeof(oh));
oh.idx = 1;
- oh.objtype = IPFW_OBJTYPE_TABLE;
table_fill_ntlv(&oh.ntlv, name, 1);
- if (do_set3(IP_FW_OBJ_FLUSH, &oh.opheader, sizeof(oh)) != 0)
+ if (do_set3(IP_FW_TABLE_XFLUSH, &oh.opheader, sizeof(oh)) != 0)
return (-1);
return (0);
@@ -380,7 +377,7 @@ table_get_info(char *name, uint32_t set,
table_fill_objheader(oh, i);
- if (do_get3(IP_FW_OBJ_INFO, &oh->opheader, &sz) < 0)
+ if (do_get3(IP_FW_TABLE_XINFO, &oh->opheader, &sz) < 0)
return (-1);
if (sz < sizeof(tbuf))
@@ -486,17 +483,15 @@ tables_foreach(table_cb_t *f, void *arg,
memset(&req, 0, sizeof(req));
sz = sizeof(req);
- req.objtype = IPFW_OBJTYPE_TABLE;
- if ((error = do_get3(IP_FW_OBJ_LISTSIZE, &req.opheader, &sz)) != 0)
+ if ((error = do_get3(IP_FW_TABLES_XGETSIZE, &req.opheader, &sz)) != 0)
return (errno);
sz = req.size;
if ((olh = calloc(1, sz)) == NULL)
return (ENOMEM);
- olh->objtype = IPFW_OBJTYPE_TABLE;
olh->size = sz;
- if ((error = do_get3(IP_FW_OBJ_LIST, &olh->opheader, &sz)) != 0) {
+ if ((error = do_get3(IP_FW_TABLES_XLIST, &olh->opheader, &sz)) != 0) {
free(olh);
return (errno);
}
@@ -517,7 +512,8 @@ tables_foreach(table_cb_t *f, void *arg,
/*
* Retrieves all entries for given table @i in
- * eXtended format, returning pointer vi @ooh.
+ * eXtended format. Assumes buffer of size
+ * @i->size has already been allocated by caller.
*
* Returns 0 on success.
*/
@@ -530,7 +526,9 @@ table_get_list(ipfw_xtable_info *i, ipfw
table_fill_objheader(oh, i);
sz = i->size;
- if ((error = do_get3(IP_FW_OBJ_DUMP, &oh->opheader, &sz)) != 0)
+ oh->opheader.version = 1; /* Current version */
+
+ if ((error = do_get3(IP_FW_TABLE_XLIST, &oh->opheader, &sz)) != 0)
return (errno);
return (0);
Modified: projects/ipfw/sys/netinet/ip_fw.h
==============================================================================
--- projects/ipfw/sys/netinet/ip_fw.h Sun Jun 15 12:21:06 2014 (r267508)
+++ projects/ipfw/sys/netinet/ip_fw.h Sun Jun 15 13:40:27 2014 (r267509)
@@ -70,21 +70,47 @@
/* IP_FW3 header/opcodes */
typedef struct _ip_fw3_opheader {
uint16_t opcode; /* Operation opcode */
- uint16_t reserved[3]; /* Align to 64-bit boundary */
+ uint16_t version; /* Opcode version */
+ uint16_t reserved[2]; /* Align to 64-bit boundary */
} ip_fw3_opheader;
/* IPFW extented tables support */
#define IP_FW_TABLE_XADD 86 /* add entry */
#define IP_FW_TABLE_XDEL 87 /* delete entry */
-#define IP_FW_TABLE_XGETSIZE 88 /* get table size */
+#define IP_FW_TABLE_XGETSIZE 88 /* get table size (deprecated) */
#define IP_FW_TABLE_XLIST 89 /* list table contents */
-#define IP_FW_OBJ_DEL 90 /* del table/pipe/etc */
-#define IP_FW_OBJ_LISTSIZE 91 /* get size for table/etc list */
-#define IP_FW_OBJ_LIST 92 /* list all objects of given type */
-#define IP_FW_OBJ_INFO 93 /* request info for one object */
-#define IP_FW_OBJ_FLUSH 94 /* flush data for given object */
-#define IP_FW_OBJ_DUMP 95 /* dump all data for given object */
+#define IP_FW_TABLE_XDESTROY 90 /* destroy table */
+#define IP_FW_TABLES_XGETSIZE 91 /* get size for table/etc list */
+#define IP_FW_TABLES_XLIST 92 /* list all objects of given type */
+#define IP_FW_TABLE_XINFO 93 /* request info for one object */
+#define IP_FW_TABLE_XFLUSH 94 /* flush data for given object */
+
+/*
+ * Usage guidelines:
+ *
+ * IP_FW_TABLE_XLIST(ver 1): Dumps all table data
+ * Request(getsockopt): [ ipfw_obj_lheader ], size = ipfw_xtable_info.size
+ * Reply: [ ipfw_obj_lheader ipfw_xtable_info ipfw_table_xentry x N ]
+ *
+ * IP_FW_TABLE_XDESTROY: Destroys given table
+ * Request(setsockopt): [ ipfw_obj_header ]
+ *
+ * IP_FW_TABLES_XGETSIZE: Get buffer size needed to list info for all tables.
+ * Request(getsockopt): [ empty ], size = sizeof(ipfw_obj_lheader)
+ * Reply: [ ipfw_obj_lheader ]
+ *
+ * IP_FW_TABLES_XLIST: Lists all tables currently available in kernel.
+ * Request(getsockopt): [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_xtable_info x N ]
+ *
+ * IP_FW_TABLE_XINFO: Store table info to buffer.
+ * Request(getsockopt): [ ipfw_obj_header ipfw_xtable_info(empty)]
+ * Reply: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * IP_FW_TABLE_XFLUSH: Removes all data from given table leaving type etc..
+ * Request(setsockopt): [ ipfw_obj_header ]
+ */
/*
* The kernel representation of ipfw rules is made of a list of
@@ -679,10 +705,6 @@ typedef struct _ipfw_xtable_info {
} ipfw_xtable_info;
#define IPFW_OBJTYPE_TABLE 1
-/*
- * IP_FW_OBJ_DEL, IP_FW_OBJ_INFO (followed by ipfw_xtable_info),
- * IP_FW_OBJ_DUMP (followed by ipfw_xtable_info and ipfw_table_xentry'xN )
- */
typedef struct _ipfw_obj_header {
ip_fw3_opheader opheader; /* IP_FW3 opcode */
uint32_t set; /* Set we're operating */
@@ -692,12 +714,9 @@ typedef struct _ipfw_obj_header {
ipfw_obj_ntlv ntlv; /* object name tlv */
} ipfw_obj_header;
-/* IP_FW_OBJ_LISTSIZE, IP_FW_OBJ_LIST (followd by ipfw_xtable_info) */
typedef struct _ipfw_obj_lheader {
ip_fw3_opheader opheader; /* IP_FW3 opcode */
- uint8_t objtype; /* object type */
- uint8_t spare0;
- uint16_t spare1;
+ uint32_t spare;
uint32_t count; /* Total objects count */
uint32_t size; /* Total objects size */
uint32_t objsize; /* Size of one object */
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Sun Jun 15 12:21:06 2014 (r267508)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Sun Jun 15 13:40:27 2014 (r267509)
@@ -327,15 +327,6 @@ struct rule_check_info {
struct obj_idx obuf[8]; /* table references storage */
};
-struct tentry_info {
- void *paddr;
- int plen; /* Total entry length */
- uint8_t masklen; /* mask length */
- uint8_t spare;
- uint16_t flags; /* record flags */
- uint32_t value; /* value */
-};
-
/* In ip_fw_sockopt.c */
int ipfw_find_rule(struct ip_fw_chain *chain, uint32_t key, uint32_t id);
int ipfw_ctl(struct sockopt *sopt);
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Jun 15 12:21:06 2014 (r267508)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sun Jun 15 13:40:27 2014 (r267509)
@@ -1171,10 +1171,9 @@ ipfw_ctl(struct sockopt *sopt)
sopt->sopt_name == IP_FW_RESETLOG);
break;
- /*--- TABLE manipulations are protected by the IPFW_LOCK ---*/
- case IP_FW_OBJ_DEL: /* IP_FW3 */
- case IP_FW_OBJ_INFO: /* IP_FW3 */
- case IP_FW_OBJ_FLUSH: /* IP_FW3 */
+ /*--- TABLE opcodes ---*/
+ case IP_FW_TABLE_XDESTROY: /* IP_FW3 */
+ case IP_FW_TABLE_XFLUSH: /* IP_FW3 */
{
struct _ipfw_obj_header *oh;
struct tid_info ti;
@@ -1186,64 +1185,31 @@ ipfw_ctl(struct sockopt *sopt)
oh = (struct _ipfw_obj_header *)op3;
- switch (oh->objtype) {
- case IPFW_OBJTYPE_TABLE:
- memset(&ti, 0, sizeof(ti));
- ti.set = oh->set;
- ti.uidx = oh->idx;
- ti.tlvs = &oh->ntlv;
- ti.tlen = oh->ntlv.head.length;
- if (opt == IP_FW_OBJ_DEL)
- error = ipfw_destroy_table(chain, &ti);
- else if (opt == IP_FW_OBJ_FLUSH)
- error = ipfw_flush_table(chain, &ti);
- else {
- /* IP_FW_OBJ_INFO */
- if (sopt->sopt_valsize < sizeof(*oh) +
- sizeof(ipfw_xtable_info)) {
- error = EINVAL;
- break;
- }
-
- error = ipfw_describe_table(chain, &ti,
- (ipfw_xtable_info *)(oh + 1));
- if (error == 0)
- error = sooptcopyout(sopt, oh,
- sopt->sopt_valsize);
- }
- break;
- default:
+ objheader_to_ti(oh, &ti);
+
+ if (opt == IP_FW_TABLE_XDESTROY)
+ error = ipfw_destroy_table(chain, &ti);
+ else if (opt == IP_FW_TABLE_XFLUSH)
+ error = ipfw_flush_table(chain, &ti);
+ else
error = ENOTSUP;
- break;
- }
break;
}
- case IP_FW_TABLE_ADD:
- case IP_FW_TABLE_DEL:
- {
- ipfw_table_entry ent;
- struct tentry_info tei;
- struct tid_info ti;
- error = sooptcopyin(sopt, &ent,
- sizeof(ent), sizeof(ent));
- if (error)
- break;
+ case IP_FW_TABLE_XINFO: /* IP_FW3 */
+ error = ipfw_describe_table(chain, sopt, op3, valsize);
+ break;
- memset(&tei, 0, sizeof(tei));
- tei.paddr = &ent.addr;
- tei.plen = sizeof(ent.addr);
- tei.masklen = ent.masklen;
- tei.value = ent.value;
- memset(&ti, 0, sizeof(ti));
- ti.set = RESVD_SET;
- ti.uidx = ent.tbl;
- ti.type = IPFW_TABLE_CIDR;
+ case IP_FW_TABLES_XGETSIZE: /* IP_FW3 */
+ error = ipfw_listsize_tables(chain, sopt, op3, valsize);
+ break;
- error = (opt == IP_FW_TABLE_ADD) ?
- ipfw_add_table_entry(chain, &ti, &tei) :
- ipfw_del_table_entry(chain, &ti, &tei);
- }
+ case IP_FW_TABLES_XLIST: /* IP_FW3 */
+ error = ipfw_list_tables(chain, sopt, op3, valsize);
+ break;
+
+ case IP_FW_TABLE_XLIST: /* IP_FW3 */
+ error = ipfw_dump_table(chain, sopt, op3, valsize);
break;
case IP_FW_TABLE_XADD: /* IP_FW3 */
@@ -1283,6 +1249,36 @@ ipfw_ctl(struct sockopt *sopt)
}
break;
+ /*--- LEGACY API ---*/
+ case IP_FW_TABLE_ADD:
+ case IP_FW_TABLE_DEL:
+ {
+ ipfw_table_entry ent;
+ struct tentry_info tei;
+ struct tid_info ti;
+
+ error = sooptcopyin(sopt, &ent,
+ sizeof(ent), sizeof(ent));
+ if (error)
+ break;
+
+ memset(&tei, 0, sizeof(tei));
+ tei.paddr = &ent.addr;
+ tei.plen = sizeof(ent.addr);
+ tei.masklen = ent.masklen;
+ tei.value = ent.value;
+ memset(&ti, 0, sizeof(ti));
+ ti.set = RESVD_SET;
+ ti.uidx = ent.tbl;
+ ti.type = IPFW_TABLE_CIDR;
+
+ error = (opt == IP_FW_TABLE_ADD) ?
+ ipfw_add_table_entry(chain, &ti, &tei) :
+ ipfw_del_table_entry(chain, &ti, &tei);
+ }
+ break;
+
+
case IP_FW_TABLE_FLUSH:
{
u_int16_t tbl;
@@ -1375,110 +1371,6 @@ ipfw_ctl(struct sockopt *sopt)
error = sooptcopyout(sopt, op3, sopt->sopt_valsize);
}
break;
-
- case IP_FW_TABLE_XLIST: /* IP_FW3 */
- {
- ipfw_xtable *tbl;
- struct tid_info ti;
-
- if ((size = valsize) < sizeof(ipfw_xtable)) {
- error = EINVAL;
- break;
- }
-
- tbl = malloc(size, M_TEMP, M_ZERO | M_WAITOK);
- memcpy(tbl, op3, sizeof(ipfw_xtable));
-
- /* Get maximum number of entries we can store */
- tbl->size = (size - sizeof(ipfw_xtable)) /
- sizeof(ipfw_table_xentry);
- memset(&ti, 0, sizeof(ti));
- ti.set = 0; /* XXX: No way to specify set */
- ti.uidx = tbl->tbl;
- IPFW_UH_RLOCK(chain);
- error = ipfw_dump_xtable(chain, &ti, tbl);
- IPFW_UH_RUNLOCK(chain);
- if (error) {
- free(tbl, M_TEMP);
- break;
- }
-
- /* Revert size field back to bytes */
- tbl->size = tbl->size * sizeof(ipfw_table_xentry) +
- sizeof(ipfw_table);
- /*
- * Since we call sooptcopyin() with small buffer, sopt_valsize is
- * decreased to reflect supplied buffer size. Set it back to original value
- */
- sopt->sopt_valsize = valsize;
- error = sooptcopyout(sopt, tbl, size);
- free(tbl, M_TEMP);
- }
- break;
- case IP_FW_OBJ_LISTSIZE: /* IP_FW3 */
- {
- struct _ipfw_obj_lheader *olh;
-
- if (sopt->sopt_valsize < sizeof(*olh)) {
- error = EINVAL;
- break;
- }
-
- olh = (struct _ipfw_obj_lheader *)op3;
-
- switch (olh->objtype) {
- case IPFW_OBJTYPE_TABLE:
- error = ipfw_listsize_tables(chain, sopt, op3,
- valsize);
- break;
- default:
- error = ENOTSUP;
- break;
- }
- break;
- }
- case IP_FW_OBJ_LIST: /* IP_FW3 */
- {
- struct _ipfw_obj_lheader *olh;
-
- if (sopt->sopt_valsize < sizeof(*olh)) {
- error = EINVAL;
- break;
- }
-
- olh = (struct _ipfw_obj_lheader *)op3;
- switch (olh->objtype) {
- case IPFW_OBJTYPE_TABLE:
- error = ipfw_list_tables(chain, sopt, op3,
- valsize);
- break;
- default:
- error = ENOTSUP;
- break;
- }
- break;
- }
- case IP_FW_OBJ_DUMP: /* IP_FW3 */
- {
- struct _ipfw_obj_header *oh;
-
- if (sopt->sopt_valsize < sizeof(*oh)) {
- error = EINVAL;
- break;
- }
-
- oh = (struct _ipfw_obj_header *)op3;
- switch (oh->objtype) {
- case IPFW_OBJTYPE_TABLE:
- error = ipfw_dump_table(chain, sopt, op3,
- valsize);
- break;
- default:
- error = ENOTSUP;
- break;
- }
- break;
- }
/*--- NAT operations are protected by the IPFW_LOCK ---*/
case IP_FW_NAT_CFG:
if (IPFW_NAT_LOADED)
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Sun Jun 15 12:21:06 2014 (r267508)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Sun Jun 15 13:40:27 2014 (r267509)
@@ -105,6 +105,14 @@ static int export_tables(struct ip_fw_ch
static void export_table_info(struct table_config *tc, ipfw_xtable_info *i);
static int dump_table_xentry(void *e, void *arg);
+static int check_buffer(size_t items, size_t item_size, size_t header,
+ size_t bufsize);
+
+static int ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt *sopt,
+ ip_fw3_opheader *op3, size_t valsize);
+static int ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt *sopt,
+ ip_fw3_opheader *op3, size_t valsize);
+
static struct table_algo *find_table_algo(struct tables_config *tableconf,
struct tid_info *ti);
@@ -538,7 +546,16 @@ ipfw_lookup_table_extended(struct ip_fw_
*/
/*
- * High-level handlers for setsockopt
+ * High-level 'get' cmds sysctl handlers
+ */
+
+/*
+ * Get buffer size needed to list info for all tables.
+ * Data layout:
+ * Request: [ empty ], size = sizeof(ipfw_obj_lheader)
+ * Reply: [ ipfw_obj_lheader ]
+ *
+ * Returns 0 on success
*/
int
ipfw_listsize_tables(struct ip_fw_chain *ch, struct sockopt *sopt,
@@ -546,6 +563,9 @@ ipfw_listsize_tables(struct ip_fw_chain
{
struct _ipfw_obj_lheader *olh;
+ if (sopt->sopt_valsize < sizeof(*olh))
+ return (EINVAL);
+
olh = (struct _ipfw_obj_lheader *)op3;
olh->size = sizeof(*olh); /* Make export_table store needed size */
@@ -558,15 +578,25 @@ ipfw_listsize_tables(struct ip_fw_chain
return (sooptcopyout(sopt, olh, sopt->sopt_valsize));
}
-
+/*
+ * Lists all tables currently available in kernel.
+ * Data layout:
+ * Request: [ ipfw_obj_lheader ], size = ipfw_obj_lheader.size
+ * Reply: [ ipfw_obj_lheader ipfw_xtable_info x N ]
+ *
+ * Returns 0 on success
+ */
int
ipfw_list_tables(struct ip_fw_chain *ch, struct sockopt *sopt,
ip_fw3_opheader *op3, size_t valsize)
{
struct _ipfw_obj_lheader *olh;
- uint32_t sz, sz_min, sz_max;
+ uint32_t sz;
int error;
+ if (sopt->sopt_valsize < sizeof(*olh))
+ return (EINVAL);
+
olh = (struct _ipfw_obj_lheader *)op3;
if (valsize != olh->size)
@@ -580,11 +610,9 @@ ipfw_list_tables(struct ip_fw_chain *ch,
IPFW_UH_RLOCK(ch);
sz = ipfw_objhash_count(CHAIN_TO_NI(ch));
IPFW_UH_RUNLOCK(ch);
-
- sz_min = sz * sizeof(ipfw_xtable_info) + sizeof(*olh);
- sz_max = sz_min + (sz + 1) * sizeof(ipfw_xtable_info);
- if (valsize < sz_min || valsize > sz_max)
+ if (check_buffer(sz, sizeof(ipfw_xtable_info),
+ sizeof(*olh), valsize) != 0)
return (EINVAL);
olh = malloc(valsize, M_TEMP, M_ZERO | M_WAITOK);
@@ -612,6 +640,46 @@ ipfw_list_tables(struct ip_fw_chain *ch,
return (0);
}
+/*
+ * Store table info to buffer provided by @op3.
+ * Data layout:
+ * Request: [ ipfw_obj_header ipfw_xtable_info(empty)]
+ * Reply: [ ipfw_obj_header ipfw_xtable_info ]
+ *
+ * Returns 0 on success.
+ */
+int
+ipfw_describe_table(struct ip_fw_chain *ch, struct sockopt *sopt,
+ ip_fw3_opheader *op3, size_t valsize)
+{
+ struct _ipfw_obj_header *oh;
+ struct table_config *tc;
+ struct tid_info ti;
+ size_t sz;
+ int error;
+
+ sz = sizeof(*oh) + sizeof(ipfw_xtable_info);
+ if (sopt->sopt_valsize < sz)
+ return (EINVAL);
+
+ oh = (struct _ipfw_obj_header *)op3;
+
+ objheader_to_ti(oh, &ti);
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ return (ESRCH);
+ }
+
+ export_table_info(tc, (ipfw_xtable_info *)(oh + 1));
+ IPFW_UH_RUNLOCK(ch);
+
+ error = sooptcopyout(sopt, oh, sz);
+
+ return (error);
+}
+
struct dump_args {
struct table_info *ti;
struct table_config *tc;
@@ -626,22 +694,49 @@ int
ipfw_dump_table(struct ip_fw_chain *ch, struct sockopt *sopt,
ip_fw3_opheader *op3, size_t valsize)
{
+ int error;
+
+ switch (op3->version) {
+ case 0:
+ error = ipfw_dump_table_v0(ch, sopt, op3, valsize);
+ break;
+ case 1:
+ error = ipfw_dump_table_v1(ch, sopt, op3, valsize);
+ break;
+ default:
+ error = ENOTSUP;
+ }
+
+ return (error);
+}
+
+/*
+ * Dumps all table data
+ * Data layout (version 1):
+ * Request: [ ipfw_obj_lheader ], size = ipfw_xtable_info.size
+ * Reply: [ ipfw_obj_lheader ipfw_xtable_info ipfw_table_xentry x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt *sopt,
+ ip_fw3_opheader *op3, size_t valsize)
+{
struct _ipfw_obj_header *oh;
ipfw_xtable_info *i;
struct tid_info ti;
struct table_config *tc;
struct table_algo *ta;
struct dump_args da;
- uint32_t sz, sz_min, sz_max;
+ uint32_t sz;
int error;
+ if (sopt->sopt_valsize < sizeof(*oh))
+ return (EINVAL);
+
oh = (struct _ipfw_obj_header *)op3;
- memset(&ti, 0, sizeof(ti));
- ti.set = oh->set;
- ti.uidx = oh->idx;
- ti.tlvs = &oh->ntlv;
- ti.tlen = oh->ntlv.head.length;
+ objheader_to_ti(oh, &ti);
IPFW_UH_RLOCK(ch);
if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
@@ -651,20 +746,10 @@ ipfw_dump_table(struct ip_fw_chain *ch,
sz = tc->count;
IPFW_UH_RUNLOCK(ch);
- /*
- * Check if array size is "reasonable":
- * Permit valsize between current size and
- * 2x current size + 1
- */
-
- sz_min = sz * sizeof(ipfw_table_xentry) + sizeof(ipfw_xtable_info) +
- sizeof(*oh);
-
- sz_max = sz_min + (sz + 1) * sizeof(ipfw_table_xentry);
-
- if (valsize < sz_min || valsize > sz_max)
+ if (check_buffer(sz, sizeof(ipfw_table_xentry),
+ sizeof(ipfw_xtable_info) + sizeof(*oh), valsize) != 0)
return (EINVAL);
-
+
oh = malloc(valsize, M_TEMP, M_ZERO | M_WAITOK);
i = (ipfw_xtable_info *)(oh + 1);
/* Copy header to new storage */
@@ -689,6 +774,7 @@ ipfw_dump_table(struct ip_fw_chain *ch,
/*
* Do the actual dump in eXtended format
*/
+ memset(&da, 0, sizeof(da));
da.ti = KIDX_TO_TI(ch, tc->no.kidx);
da.tc = tc;
da.xent = (ipfw_table_xentry *)(i + 1);
@@ -712,6 +798,122 @@ ipfw_dump_table(struct ip_fw_chain *ch,
return (0);
}
+/*
+ * Dumps all table data
+ * Data layout (version 0):
+ * Request: [ ipfw_xtable ], size = IP_FW_TABLE_XGETSIZE()
+ * Reply: [ ipfw_xtable ipfw_table_xentry x N ]
+ *
+ * Returns 0 on success
+ */
+static int
+ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt *sopt,
+ ip_fw3_opheader *op3, size_t valsize)
+{
+ ipfw_xtable *xtbl;
+ struct tid_info ti;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct dump_args da;
+ int error;
+ size_t sz;
+
+ if (valsize < sizeof(ipfw_xtable))
+ return (EINVAL);
+
+ xtbl = (ipfw_xtable *)op3;
+
+ memset(&ti, 0, sizeof(ti));
+ ti.set = 0; /* XXX: No way to specify set */
+ ti.uidx = xtbl->tbl;
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ return (0);
+ }
+ sz = tc->count;
+ IPFW_UH_RUNLOCK(ch);
+
+ if (check_buffer(sz, sizeof(ipfw_table_xentry),
+ sizeof(ipfw_xtable) - sizeof(ipfw_table_xentry), valsize) != 0)
+ return (EINVAL);
+
+ xtbl = malloc(valsize, M_TEMP, M_ZERO | M_WAITOK);
+ memcpy(xtbl, op3, sizeof(ipfw_xtable));
+
+ IPFW_UH_RLOCK(ch);
+ if ((tc = find_table(CHAIN_TO_NI(ch), &ti)) == NULL) {
+ IPFW_UH_RUNLOCK(ch);
+ free(xtbl, M_TEMP);
+ return (0);
+ }
+
+ /* Check size another time */
+ sz = tc->count * sizeof(ipfw_table_xentry) + sizeof(ipfw_xtable);
+ if (sz > valsize) {
+ IPFW_UH_RUNLOCK(ch);
+ free(xtbl, M_TEMP);
+ return (EINVAL);
+ }
+
+ /* Do the actual dump in eXtended format */
+ memset(&da, 0, sizeof(da));
+ da.ti = KIDX_TO_TI(ch, tc->no.kidx);
+ da.tc = tc;
+ da.xent = &xtbl->xent[0];
+ da.size = tc->count;
+ xtbl->type = tc->no.type;
+ xtbl->tbl = ti.uidx;
+ ta = tc->ta;
+
+ ta->foreach(tc->astate, da.ti, dump_table_xentry, &da);
+ xtbl->cnt = da.cnt;
+ xtbl->size = sz;
+
+ IPFW_UH_RUNLOCK(ch);
+
+ /*
+ * Since we call sooptcopyin() with small buffer, sopt_valsize is
+ * decreased to reflect supplied buffer size. Set it back to original value
+ */
+ sopt->sopt_valsize = valsize;
+ error = sooptcopyout(sopt, xtbl, sz);
+ free(xtbl, M_TEMP);
+
+ return (error);
+}
+
+/*
+ * Checks if supplied buffer size is "reasonable".
+ * Permit valsize between current needed size and
+ * 2x needed size + 1
+ */
+static int
+check_buffer(size_t items, size_t item_size, size_t header, size_t bufsize)
+{
+ size_t sz_min, sz_max;
+
+ sz_min = items * item_size + header;
+ sz_max = (2 * items + 1) * item_size + header;
+
+ if (bufsize < sz_min || bufsize > sz_max)
+ return (EINVAL);
+
+ return (0);
+}
+
+void
+objheader_to_ti(struct _ipfw_obj_header *oh, struct tid_info *ti)
+{
+
+ memset(ti, 0, sizeof(struct tid_info));
+ ti->set = oh->set;
+ ti->uidx = oh->idx;
+ ti->tlvs = &oh->ntlv;
+ ti->tlen = oh->ntlv.head.length;
+}
+
static void
export_table_info(struct table_config *tc, ipfw_xtable_info *i)
{
@@ -728,34 +930,6 @@ export_table_info(struct table_config *t
strlcpy(i->tablename, tc->tablename, sizeof(i->tablename));
}
-int
-ipfw_count_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh)
-{
- uint32_t count;
-
- count = ipfw_objhash_count(CHAIN_TO_NI(ch));
-
- olh->count = count;
- olh->size = count * sizeof(ipfw_xtable_info) + sizeof(ipfw_obj_lheader);
- olh->objsize = sizeof(ipfw_xtable_info);
-
- return (0);
-}
-
-int
-ipfw_describe_table(struct ip_fw_chain *ch, struct tid_info *ti,
- ipfw_xtable_info *i)
-{
- struct table_config *tc;
-
- if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
- return (ESRCH);
-
- export_table_info(tc, i);
-
- return (0);
-}
-
static void
export_table_internal(struct namedobj_instance *ni, struct named_object *no,
void *arg)
@@ -818,8 +992,10 @@ ipfw_count_xtable(struct ip_fw_chain *ch
{
struct table_config *tc;
- if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
+ if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL) {
+ *cnt = 0;
return (0); /* 'table all list' requires success */
+ }
*cnt = tc->count * sizeof(ipfw_table_xentry);
if (tc->count > 0)
*cnt += sizeof(ipfw_xtable);
@@ -870,10 +1046,10 @@ ipfw_dump_table_legacy(struct ip_fw_chai
if (ta->dump_entry == NULL)
return (0); /* Legacy dump support is not necessary */
+ memset(&da, 0, sizeof(da));
da.ti = KIDX_TO_TI(ch, tc->no.kidx);
da.tc = tc;
da.ent = &tbl->ent[0];
- da.cnt = 0;
da.size = tbl->size;
tbl->cnt = 0;
@@ -921,11 +1097,11 @@ ipfw_dump_xtable(struct ip_fw_chain *ch,
if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
return (0); /* XXX: We should return ESRCH */
+ memset(&da, 0, sizeof(da));
da.ti = KIDX_TO_TI(ch, tc->no.kidx);
da.tc = tc;
da.xent = &xtbl->xent[0];
da.size = xtbl->size;
- da.cnt = 0;
xtbl->type = tc->no.type;
xtbl->tbl = ti->uidx;
ta = tc->ta;
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Sun Jun 15 12:21:06 2014 (r267508)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Sun Jun 15 13:40:27 2014 (r267509)
@@ -41,6 +41,15 @@ struct table_info {
u_long data; /* Hints for given func */
};
+struct tentry_info {
+ void *paddr;
+ int plen; /* Total entry length */
+ uint8_t masklen; /* mask length */
+ uint8_t spare;
+ uint16_t flags; /* record flags */
+ uint32_t value; /* value */
+};
+
typedef int (ta_init)(void **ta_state, struct table_info *ti);
typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
typedef int (ta_prepare_add)(struct tentry_info *tei, void *ta_buf);
@@ -77,6 +86,10 @@ struct table_algo {
void ipfw_add_table_algo(struct ip_fw_chain *ch, struct table_algo *ta);
extern struct table_algo radix_cidr, radix_iface;
+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_listsize_tables(struct ip_fw_chain *ch, struct sockopt *sopt,
ip_fw3_opheader *op3, size_t valsize);
@@ -84,6 +97,8 @@ int ipfw_list_tables(struct ip_fw_chain
ip_fw3_opheader *op3, size_t valsize);
int ipfw_dump_table(struct ip_fw_chain *ch, struct sockopt *sopt,
ip_fw3_opheader *op3, size_t valsize);
+int ipfw_describe_table(struct ip_fw_chain *ch, struct sockopt *sopt,
+ ip_fw3_opheader *op3, size_t valsize);
int ipfw_destroy_table(struct ip_fw_chain *ch, struct tid_info *ti);
int ipfw_flush_table(struct ip_fw_chain *ch, struct tid_info *ti);
@@ -91,6 +106,16 @@ int ipfw_add_table_entry(struct ip_fw_ch
struct tentry_info *tei);
int ipfw_del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
struct tentry_info *tei);
+int ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
+ struct rule_check_info *ci);
+int ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule);
+void ipfw_unbind_table_rule(struct ip_fw_chain *chain, struct ip_fw *rule);
+void ipfw_unbind_table_list(struct ip_fw_chain *chain, struct ip_fw *head);
+
+/* utility functions */
+void objheader_to_ti(struct _ipfw_obj_header *oh, struct tid_info *ti);
+
+/* Legacy interfaces */
int ipfw_count_table(struct ip_fw_chain *ch, struct tid_info *ti,
uint32_t *cnt);
int ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti,
@@ -99,17 +124,6 @@ int ipfw_dump_table_legacy(struct ip_fw_
ipfw_table *tbl);
int ipfw_dump_xtable(struct ip_fw_chain *ch, struct tid_info *ti,
ipfw_xtable *tbl);
-int ipfw_describe_table(struct ip_fw_chain *ch, struct tid_info *ti,
- ipfw_xtable_info *i);
-int ipfw_count_tables(struct ip_fw_chain *ch, ipfw_obj_lheader *olh);
-int ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
- struct rule_check_info *ci);
-int ipfw_rewrite_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule);
-void ipfw_unbind_table_rule(struct ip_fw_chain *chain, struct ip_fw *rule);
-void ipfw_unbind_table_list(struct ip_fw_chain *chain, struct ip_fw *head);
-
-void ipfw_table_algo_init(struct ip_fw_chain *chain);
-void ipfw_table_algo_destroy(struct ip_fw_chain *chain);
#endif /* _KERNEL */
More information about the svn-src-projects
mailing list