summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormelifaro <melifaro@FreeBSD.org>2014-07-26 13:37:25 +0000
committermelifaro <melifaro@FreeBSD.org>2014-07-26 13:37:25 +0000
commit505e5ae08158dae524fad92308b69c209a5f69d9 (patch)
tree992bd8b8c50d4af7fe911750b6c929b8a8fe07c6
parentdeb9ca0f18daa165fa9fe29716230066af8c4707 (diff)
downloadFreeBSD-src-505e5ae08158dae524fad92308b69c209a5f69d9.zip
FreeBSD-src-505e5ae08158dae524fad92308b69c209a5f69d9.tar.gz
* Require explicit table creation before use on kernel side.
* Add resize callbacks for upcoming table-based algorithms. Kernel changes: * s/ipfw_modify_table/ipfw_manage_table_ent/ * Simplify add_table_entry(): make table creation a separate piece of code. Do not perform creation if not in "compat" mode. * Add ability to perform modification of algorithm state (like table resize). The following callbacks were added: - prepare_mod (allocate new state, without locks) - fill_mod (UH_WLOCK, copy old state to new one) - modify (UH_WLOCK + WLOCK, switch state) - flush_mod (no locks, flushes allocated data) Given callbacks are called if table modification has been requested by add or delete callbacks. Additional u64 tc->'flags' field was added to pass these requests. * Change add/del table ent format: permit adding/removing multiple entries at once (only 1 supported at the moment). Userland changes: * Auto-create tables with warning
-rw-r--r--sbin/ipfw/tables.c31
-rw-r--r--sys/netpfil/ipfw/ip_fw_sockopt.c2
-rw-r--r--sys/netpfil/ipfw/ip_fw_table.c279
-rw-r--r--sys/netpfil/ipfw/ip_fw_table.h20
-rw-r--r--sys/netpfil/ipfw/ip_fw_table_algo.c8
5 files changed, 243 insertions, 97 deletions
diff --git a/sbin/ipfw/tables.c b/sbin/ipfw/tables.c
index 670b8ce..c0393e1 100644
--- a/sbin/ipfw/tables.c
+++ b/sbin/ipfw/tables.c
@@ -465,7 +465,8 @@ static int
table_do_modify_record(int cmd, ipfw_obj_header *oh,
ipfw_obj_tentry *tent, int update)
{
- char xbuf[sizeof(ipfw_obj_header) + sizeof(ipfw_obj_tentry)];
+ ipfw_obj_ctlv *ctlv;
+ char xbuf[sizeof(*oh) + sizeof(ipfw_obj_ctlv) + sizeof(*tent)];
int error;
memset(xbuf, 0, sizeof(xbuf));
@@ -473,8 +474,12 @@ table_do_modify_record(int cmd, ipfw_obj_header *oh,
oh = (ipfw_obj_header *)xbuf;
oh->opheader.version = 1;
- memcpy(oh + 1, tent, sizeof(*tent));
- tent = (ipfw_obj_tentry *)(oh + 1);
+ ctlv = (ipfw_obj_ctlv *)(oh + 1);
+ ctlv->count = 1;
+ ctlv->head.length = sizeof(*ctlv) + sizeof(*tent);
+
+ memcpy(ctlv + 1, tent, sizeof(*tent));
+ tent = (ipfw_obj_tentry *)(ctlv + 1);
if (update != 0)
tent->head.flags |= IPFW_TF_UPDATE;
tent->head.length = sizeof(ipfw_obj_tentry);
@@ -501,6 +506,19 @@ table_modify_record(ipfw_obj_header *oh, int ac, char *av[], int add, int update
tent.idx = 1;
tentry_fill_key(oh, &tent, *av, &type, &vtype, &xi);
+
+ /*
+ * compability layer: auto-create table if not exists
+ */
+ if (xi.tablename[0] == '\0') {
+ xi.type = type;
+ xi.vtype = vtype;
+ strlcpy(xi.tablename, oh->ntlv.name, sizeof(xi.tablename));
+ fprintf(stderr, "DEPRECATED: inserting data info non-existent "
+ "table %s. (auto-created)\n", xi.tablename);
+ table_do_create(oh, &xi);
+ }
+
oh->ntlv.type = type;
ac--; av++;
@@ -659,6 +677,7 @@ tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key,
{
uint8_t type, vtype;
int error;
+ char *del;
type = 0;
vtype = 0;
@@ -678,6 +697,8 @@ tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key,
* Compability layer: try to interpret data as CIDR
* before failing.
*/
+ if ((del = strchr(key, '/')) != NULL)
+ *del = '\0';
if (inet_pton(AF_INET, key, &tent->k.addr6) == 1 ||
inet_pton(AF_INET6, key, &tent->k.addr6) == 1) {
/* OK Prepare and send */
@@ -690,8 +711,10 @@ tentry_fill_key(ipfw_obj_header *oh, ipfw_obj_tentry *tent, char *key,
} else {
/* Inknown key */
errx(EX_USAGE, "Table %s does not exist, cannot guess "
- "key type", oh->ntlv.name);
+ "key '%s' type", oh->ntlv.name, key);
}
+ if (del != NULL)
+ *del = '/';
}
tentry_fill_key_type(key, tent, type);
diff --git a/sys/netpfil/ipfw/ip_fw_sockopt.c b/sys/netpfil/ipfw/ip_fw_sockopt.c
index 8d60ca4..64f9fb4 100644
--- a/sys/netpfil/ipfw/ip_fw_sockopt.c
+++ b/sys/netpfil/ipfw/ip_fw_sockopt.c
@@ -1992,7 +1992,7 @@ ipfw_ctl(struct sockopt *sopt)
case IP_FW_TABLE_XADD: /* IP_FW3 */
case IP_FW_TABLE_XDEL: /* IP_FW3 */
- error = ipfw_modify_table(chain, op3, &sdata);
+ error = ipfw_manage_table_ent(chain, op3, &sdata);
break;
case IP_FW_TABLE_XFIND: /* IP_FW3 */
error = ipfw_find_table_entry(chain, op3, &sdata);
diff --git a/sys/netpfil/ipfw/ip_fw_table.c b/sys/netpfil/ipfw/ip_fw_table.c
index c75a398..766c4a1 100644
--- a/sys/netpfil/ipfw/ip_fw_table.c
+++ b/sys/netpfil/ipfw/ip_fw_table.c
@@ -77,14 +77,14 @@ struct table_config {
struct named_object no;
uint8_t vtype; /* format table type */
uint8_t linked; /* 1 if already linked */
- uint16_t spare0;
+ uint16_t spare;
uint32_t count; /* Number of records */
+ uint64_t flags; /* state flags */
char tablename[64]; /* table name */
struct table_algo *ta; /* Callbacks for given algo */
void *astate; /* algorithm state */
struct table_info ti; /* data to put to table_info */
};
-#define TABLE_SET(set) ((V_fw_tables_sets != 0) ? set : 0)
struct tables_config {
struct namedobj_instance *namehash;
@@ -95,9 +95,11 @@ struct tables_config {
static struct table_config *find_table(struct namedobj_instance *ni,
struct tid_info *ti);
static struct table_config *alloc_table_config(struct namedobj_instance *ni,
- struct tid_info *ti, struct table_algo *ta, char *adata);
+ struct tid_info *ti, struct table_algo *ta, char *adata, uint8_t vtype);
static void free_table_config(struct namedobj_instance *ni,
struct table_config *tc);
+static int create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
+ char *aname, uint8_t vtype);
static void link_table(struct ip_fw_chain *chain, struct table_config *tc);
static void unlink_table(struct ip_fw_chain *chain, struct table_config *tc);
static void free_table_state(void **state, void **xstate, uint8_t type);
@@ -110,11 +112,13 @@ static int dump_table_xentry(void *e, void *arg);
static int ipfw_dump_table_v0(struct ip_fw_chain *ch, struct sockopt_data *sd);
static int ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd);
-static int ipfw_modify_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+static int ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd);
-static int ipfw_modify_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+static int ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd);
+static int modify_table(struct ip_fw_chain *ch, struct table_config *tc,
+ struct table_algo *ta, void *ta_buf, uint64_t pflags);
static int destroy_table(struct ip_fw_chain *ch, struct tid_info *ti);
static struct table_algo *find_table_algo(struct tables_config *tableconf,
@@ -130,11 +134,12 @@ int
add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
struct tentry_info *tei)
{
- struct table_config *tc, *tc_new;
+ struct table_config *tc;
struct table_algo *ta;
struct namedobj_instance *ni;
uint16_t kidx;
int error;
+ uint64_t aflags;
char ta_buf[128];
IPFW_UH_WLOCK(ch);
@@ -154,72 +159,65 @@ add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
/* Reference and unlock */
tc->no.refcnt++;
ta = tc->ta;
+ aflags = tc->flags;
}
IPFW_UH_WUNLOCK(ch);
- tc_new = NULL;
if (tc == NULL) {
- /* Table not found. We have to create new one */
- if ((ta = find_table_algo(CHAIN_TO_TCFG(ch), ti, NULL)) == NULL)
- return (ENOTSUP);
+ /* Compability mode: create new table for old clients */
+ if ((tei->flags & TEI_FLAGS_COMPAT) == 0)
+ return (ESRCH);
+
+ error = create_table_internal(ch, ti, NULL, IPFW_VTYPE_U32);
+
+ if (error != 0)
+ return (error);
+
+ /* Let's try to find & reference another time */
+ IPFW_UH_WLOCK(ch);
+ if ((tc = find_table(ni, ti)) == NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ if (tc->no.type != ti->type) {
+ IPFW_UH_WUNLOCK(ch);
+ return (EINVAL);
+ }
+
+ /* Reference and unlock */
+ tc->no.refcnt++;
+ ta = tc->ta;
+ aflags = tc->flags;
+
+ IPFW_UH_WUNLOCK(ch);
+ }
+
+ if (aflags != 0) {
- tc_new = alloc_table_config(ni, ti, ta, NULL);
- if (tc_new == NULL)
- return (ENOMEM);
+ /*
+ * Previous add/delete call returned non-zero state.
+ * Run appropriate handler.
+ */
+ error = modify_table(ch, tc, ta, &ta_buf, aflags);
+ if (error != 0)
+ return (error);
}
/* Prepare record (allocate memory) */
memset(&ta_buf, 0, sizeof(ta_buf));
error = ta->prepare_add(tei, &ta_buf);
- if (error != 0) {
- if (tc_new != NULL)
- free_table_config(ni, tc_new);
+ if (error != 0)
return (error);
- }
IPFW_UH_WLOCK(ch);
ni = CHAIN_TO_NI(ch);
- if (tc == NULL) {
- /* Check if another table has been allocated by other thread */
- if ((tc = find_table(ni, ti)) != NULL) {
-
- /*
- * Check if algoritm is the same since we've
- * already allocated state using @ta algoritm
- * callbacks.
- */
- if (tc->ta != ta) {
- IPFW_UH_WUNLOCK(ch);
- error = EINVAL;
- goto done;
- }
- } else {
- /* Table still does not exists */
-
- /* Allocate table index. */
- if (ipfw_objhash_alloc_idx(ni, &kidx) != 0) {
- /* Index full. */
- IPFW_UH_WUNLOCK(ch);
- printf("Unable to allocate index for table %s"
- "in set %u. Consider increasing "
- "net.inet.ip.fw.tables_max",
- tc_new->no.name, ti->set);
- error = EBUSY;
- goto done;
- }
-
- /* Set tc_new to zero not to free it afterwards. */
- tc = tc_new;
- tc_new = NULL;
- /* Save kidx */
- tc->no.kidx = kidx;
- }
- } else {
- /* Drop reference we've used in first search */
- tc->no.refcnt--;
- }
+ /* Drop reference we've used in first search */
+ tc->no.refcnt--;
+ /* Update aflags since it can be changed after previous read */
+ aflags = tc->flags;
/* We've got valid table in @tc. Let's add data */
kidx = tc->no.kidx;
@@ -227,10 +225,7 @@ add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
IPFW_WLOCK(ch);
- if (tc->linked == 0)
- link_table(ch, tc);
-
- error = ta->add(tc->astate, KIDX_TO_TI(ch, kidx), tei, &ta_buf);
+ error = ta->add(tc->astate, KIDX_TO_TI(ch, kidx), tei, &ta_buf, &aflags);
IPFW_WUNLOCK(ch);
@@ -238,11 +233,10 @@ add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
if (error == 0 && (tei->flags & TEI_FLAGS_UPDATED) == 0)
tc->count++;
+ tc->flags = aflags;
+
IPFW_UH_WUNLOCK(ch);
-done:
- if (tc_new != NULL)
- free_table_config(ni, tc_new);
/* Run cleaning callback anyway */
ta->flush_entry(tei, &ta_buf);
@@ -258,6 +252,7 @@ del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
struct namedobj_instance *ni;
uint16_t kidx;
int error;
+ uint64_t aflags;
char ta_buf[128];
IPFW_UH_WLOCK(ch);
@@ -272,8 +267,34 @@ del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
return (EINVAL);
}
+ aflags = tc->flags;
ta = tc->ta;
+ if (aflags != 0) {
+
+ /*
+ * Give the chance to algo to shrink its state.
+ */
+ tc->no.refcnt++;
+ IPFW_UH_WUNLOCK(ch);
+ memset(&ta_buf, 0, sizeof(ta_buf));
+
+ error = modify_table(ch, tc, ta, &ta_buf, aflags);
+
+ IPFW_UH_WLOCK(ch);
+ tc->no.refcnt--;
+ aflags = tc->flags;
+
+ if (error != 0) {
+ IPFW_UH_WUNLOCK(ch);
+ return (error);
+ }
+ }
+
+ /*
+ * We assume ta_buf size is enough for storing
+ * prepare_del() key, so we're running under UH_LOCK here.
+ */
memset(&ta_buf, 0, sizeof(ta_buf));
if ((error = ta->prepare_del(tei, &ta_buf)) != 0) {
IPFW_UH_WUNLOCK(ch);
@@ -283,11 +304,12 @@ del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
kidx = tc->no.kidx;
IPFW_WLOCK(ch);
- error = ta->del(tc->astate, KIDX_TO_TI(ch, kidx), tei, &ta_buf);
+ error = ta->del(tc->astate, KIDX_TO_TI(ch, kidx), tei, &ta_buf,&aflags);
IPFW_WUNLOCK(ch);
if (error == 0)
tc->count--;
+ tc->flags = aflags;
IPFW_UH_WUNLOCK(ch);
@@ -296,18 +318,62 @@ del_table_entry(struct ip_fw_chain *ch, struct tid_info *ti,
return (error);
}
+/*
+ * Runs callbacks to modify algo state (typically, table resize).
+ *
+ * Callbacks order:
+ * 1) alloc_modify (no locks, M_WAITOK) - alloc new state based on @pflags.
+ * 2) prepare_modifyt (UH_WLOCK) - copy old data into new storage
+ * 3) modify (UH_WLOCK + WLOCK) - switch pointers
+ * 4) flush_modify (no locks) - free state, if needed
+ */
+static int
+modify_table(struct ip_fw_chain *ch, struct table_config *tc,
+ struct table_algo *ta, void *ta_buf, uint64_t pflags)
+{
+ struct table_info *ti;
+ int error;
+
+ error = ta->prepare_mod(ta_buf, &pflags);
+ if (error != 0)
+ return (error);
+
+ IPFW_UH_WLOCK(ch);
+ ti = KIDX_TO_TI(ch, tc->no.kidx);
+
+ error = ta->fill_mod(tc->astate, ti, &ta_buf, &pflags);
+
+ /*
+ * prepare_mofify may return zero in @pflags to
+ * indicate that modifications are not unnesessary.
+ */
+
+ if (error == 0 && pflags != 0) {
+ /* Do actual modification */
+ IPFW_WLOCK(ch);
+ ta->modify(tc->astate, ti, &ta_buf, pflags);
+ IPFW_WUNLOCK(ch);
+ }
+
+ IPFW_UH_WUNLOCK(ch);
+
+ ta->flush_mod(ta_buf);
+
+ return (error);
+}
+
int
-ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd)
{
int error;
switch (op3->version) {
case 0:
- error = ipfw_modify_table_v0(ch, op3, sd);
+ error = ipfw_manage_table_ent_v0(ch, op3, sd);
break;
case 1:
- error = ipfw_modify_table_v1(ch, op3, sd);
+ error = ipfw_manage_table_ent_v1(ch, op3, sd);
break;
default:
error = ENOTSUP;
@@ -324,7 +390,7 @@ ipfw_modify_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
* Returns 0 on success
*/
static int
-ipfw_modify_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ipfw_manage_table_ent_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd)
{
ipfw_table_xentry *xent;
@@ -350,6 +416,7 @@ ipfw_modify_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
tei.masklen = xent->masklen;
tei.value = xent->value;
/* Old requests compability */
+ tei.flags = TEI_FLAGS_COMPAT;
if (xent->type == IPFW_TABLE_CIDR) {
if (xent->len - hdrlen == sizeof(in_addr_t))
tei.subtype = AF_INET;
@@ -371,22 +438,25 @@ ipfw_modify_table_v0(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
/*
* Adds or deletes record in table.
* Data layout (v1)(current):
- * Request: [ ipfw_obj_header ipfw_obj_tentry ]
+ * Request: [ ipfw_obj_header
+ * ipfw_obj_ctlv(IPFW_TLV_TBLENT_LIST) [ ipfw_obj_tentry x N ]
+ * ]
*
* Returns 0 on success
*/
static int
-ipfw_modify_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ipfw_manage_table_ent_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd)
{
ipfw_obj_tentry *tent;
+ ipfw_obj_ctlv *ctlv;
ipfw_obj_header *oh;
struct tentry_info tei;
struct tid_info ti;
int error, read;
/* Check minimum header size */
- if (sd->valsize < (sizeof(*oh) + sizeof(*tent)))
+ if (sd->valsize < (sizeof(*oh) + sizeof(*ctlv)))
return (EINVAL);
/* Check if passed data is too long */
@@ -401,8 +471,21 @@ ipfw_modify_table_v1(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
read = sizeof(*oh);
+ ctlv = (ipfw_obj_ctlv *)(oh + 1);
+ if (ctlv->head.length + read != sd->valsize)
+ return (EINVAL);
+
+ /*
+ * TODO: permit adding multiple entries for given table
+ * at once
+ */
+ if (ctlv->count != 1)
+ return (EOPNOTSUPP);
+
+ read += sizeof(*ctlv);
+
/* Assume tentry may grow to support larger keys */
- tent = (ipfw_obj_tentry *)(oh + 1);
+ tent = (ipfw_obj_tentry *)(ctlv + 1);
if (tent->head.length < sizeof(*tent) ||
tent->head.length + read > sd->valsize)
return (EINVAL);
@@ -1071,8 +1154,6 @@ ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct tid_info ti;
struct namedobj_instance *ni;
struct table_config *tc;
- struct table_algo *ta;
- uint16_t kidx;
if (sd->valsize != sizeof(*oh) + sizeof(ipfw_xtable_info))
return (EINVAL);
@@ -1105,23 +1186,50 @@ ipfw_create_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
IPFW_UH_RUNLOCK(ch);
return (EEXIST);
}
- ta = find_table_algo(CHAIN_TO_TCFG(ch), &ti, aname);
IPFW_UH_RUNLOCK(ch);
+ return (create_table_internal(ch, &ti, aname, i->vtype));
+}
+
+/*
+ * Creates new table based on @ti and @aname.
+ *
+ * Relies on table name checking inside find_name_tlv()
+ * Assume @aname to be checked and valid.
+ *
+ * Returns 0 on success.
+ */
+static int
+create_table_internal(struct ip_fw_chain *ch, struct tid_info *ti,
+ char *aname, uint8_t vtype)
+{
+ struct namedobj_instance *ni;
+ struct table_config *tc;
+ struct table_algo *ta;
+ uint16_t kidx;
+
+ ni = CHAIN_TO_NI(ch);
+
+ ta = find_table_algo(CHAIN_TO_TCFG(ch), ti, aname);
if (ta == NULL)
return (ENOTSUP);
- if ((tc = alloc_table_config(ni, &ti, ta, aname)) == NULL)
+ if ((tc = alloc_table_config(ni, ti, ta, aname, vtype)) == NULL)
return (ENOMEM);
- /* TODO: move inside alloc_table_config() */
- tc->vtype = i->vtype;
IPFW_UH_WLOCK(ch);
+
+ /* Check if table has been already created */
+ if (find_table(ni, ti) != NULL) {
+ IPFW_UH_WUNLOCK(ch);
+ free_table_config(ni, tc);
+ return (EEXIST);
+ }
+
if (ipfw_objhash_alloc_idx(ni, &kidx) != 0) {
IPFW_UH_WUNLOCK(ch);
- printf("Unable to allocate table index for table %s in set %u."
- " Consider increasing net.inet.ip.fw.tables_max",
- tname, ti.set);
+ printf("Unable to allocate table index."
+ " Consider increasing net.inet.ip.fw.tables_max");
free_table_config(ni, tc);
return (EBUSY);
}
@@ -1692,7 +1800,7 @@ find_table(struct namedobj_instance *ni, struct tid_info *ti)
static struct table_config *
alloc_table_config(struct namedobj_instance *ni, struct tid_info *ti,
- struct table_algo *ta, char *aname)
+ struct table_algo *ta, char *aname, uint8_t vtype)
{
char *name, bname[16];
struct table_config *tc;
@@ -1719,7 +1827,10 @@ alloc_table_config(struct namedobj_instance *ni, struct tid_info *ti,
tc->ta = ta;
strlcpy(tc->tablename, name, sizeof(tc->tablename));
/* Set default value type to u32 for compability reasons */
- tc->vtype = IPFW_VTYPE_U32;
+ if (vtype == 0)
+ tc->vtype = IPFW_VTYPE_U32;
+ else
+ tc->vtype = vtype;
if (ti->tlvs == NULL) {
tc->no.compat = 1;
@@ -2058,7 +2169,7 @@ ipfw_rewrite_table_uidx(struct ip_fw_chain *chain,
error = ENOTSUP;
goto free;
}
- tc = alloc_table_config(ni, &ti, ta, NULL);
+ tc = alloc_table_config(ni, &ti, ta, NULL, IPFW_VTYPE_U32);
if (tc == NULL) {
error = ENOMEM;
diff --git a/sys/netpfil/ipfw/ip_fw_table.h b/sys/netpfil/ipfw/ip_fw_table.h
index 4db0837..d6875ab 100644
--- a/sys/netpfil/ipfw/ip_fw_table.h
+++ b/sys/netpfil/ipfw/ip_fw_table.h
@@ -41,7 +41,6 @@ struct table_info {
u_long data; /* Hints for given func */
};
-
/* Internal structures for handling sockopt data */
struct tid_info {
uint32_t set; /* table set */
@@ -61,16 +60,25 @@ struct tentry_info {
};
#define TEI_FLAGS_UPDATE 0x01 /* Update record if exists */
#define TEI_FLAGS_UPDATED 0x02 /* Entry has been updated */
+#define TEI_FLAGS_COMPAT 0x04 /* Called from old ABI */
typedef int (ta_init)(void **ta_state, struct table_info *ti, char *data);
typedef void (ta_destroy)(void *ta_state, struct table_info *ti);
typedef int (ta_prepare_add)(struct tentry_info *tei, void *ta_buf);
typedef int (ta_prepare_del)(struct tentry_info *tei, void *ta_buf);
typedef int (ta_add)(void *ta_state, struct table_info *ti,
- struct tentry_info *tei, void *ta_buf);
+ struct tentry_info *tei, void *ta_buf, uint64_t *pflags);
typedef int (ta_del)(void *ta_state, struct table_info *ti,
- struct tentry_info *tei, void *ta_buf);
+ struct tentry_info *tei, void *ta_buf, uint64_t *pflags);
typedef void (ta_flush_entry)(struct tentry_info *tei, void *ta_buf);
+
+typedef int (ta_prepare_mod)(void *ta_buf, uint64_t *pflags);
+typedef int (ta_fill_mod)(void *ta_state, struct table_info *ti,
+ void *ta_buf, uint64_t *pflags);
+typedef int (ta_modify)(void *ta_state, struct table_info *ti,
+ void *ta_buf, uint64_t pflags);
+typedef void (ta_flush_mod)(void *ta_buf);
+
typedef void (ta_print_config)(void *ta_state, struct table_info *ti, char *buf,
size_t bufsize);
@@ -93,6 +101,10 @@ struct table_algo {
ta_add *add;
ta_del *del;
ta_flush_entry *flush_entry;
+ ta_prepare_mod *prepare_mod;
+ ta_fill_mod *fill_mod;
+ ta_modify *modify;
+ ta_flush_mod *flush_mod;
ta_foreach *foreach;
ta_dump_tentry *dump_tentry;
ta_print_config *print_config;
@@ -116,7 +128,7 @@ 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,
+int ipfw_manage_table_ent(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd);
int ipfw_flush_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
struct sockopt_data *sd);
diff --git a/sys/netpfil/ipfw/ip_fw_table_algo.c b/sys/netpfil/ipfw/ip_fw_table_algo.c
index 7f48735..7dcfe6a 100644
--- a/sys/netpfil/ipfw/ip_fw_table_algo.c
+++ b/sys/netpfil/ipfw/ip_fw_table_algo.c
@@ -380,7 +380,7 @@ ta_prepare_add_cidr(struct tentry_info *tei, void *ta_buf)
static int
ta_add_cidr(void *ta_state, struct table_info *ti,
- struct tentry_info *tei, void *ta_buf)
+ struct tentry_info *tei, void *ta_buf, uint64_t *pflags)
{
struct radix_node_head *rnh;
struct radix_node *rn;
@@ -488,7 +488,7 @@ ta_prepare_del_cidr(struct tentry_info *tei, void *ta_buf)
static int
ta_del_cidr(void *ta_state, struct table_info *ti,
- struct tentry_info *tei, void *ta_buf)
+ struct tentry_info *tei, void *ta_buf, uint64_t *pflags)
{
struct radix_node_head *rnh;
struct radix_node *rn;
@@ -644,7 +644,7 @@ ta_prepare_add_iface(struct tentry_info *tei, void *ta_buf)
static int
ta_add_iface(void *ta_state, struct table_info *ti,
- struct tentry_info *tei, void *ta_buf)
+ struct tentry_info *tei, void *ta_buf, uint64_t *pflags)
{
struct radix_node_head *rnh;
struct radix_node *rn;
@@ -718,7 +718,7 @@ ta_prepare_del_iface(struct tentry_info *tei, void *ta_buf)
static int
ta_del_iface(void *ta_state, struct table_info *ti,
- struct tentry_info *tei, void *ta_buf)
+ struct tentry_info *tei, void *ta_buf, uint64_t *pflags)
{
struct radix_node_head *rnh;
struct radix_node *rn;
OpenPOWER on IntegriCloud