svn commit: r269856 - projects/ipfw/sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Tue Aug 12 10:22:46 UTC 2014
Author: melifaro
Date: Tue Aug 12 10:22:46 2014
New Revision: 269856
URL: http://svnweb.freebsd.org/changeset/base/269856
Log:
No functional changes, do better functions grouping.
Modified:
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Aug 12 09:48:54 2014 (r269855)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Aug 12 10:22:46 2014 (r269856)
@@ -204,6 +204,14 @@ store_tei_result(struct tentry_info *tei
tei->flags |= flag;
}
+/*
+ * Creates and references table with default parameters.
+ * Saves table config, algo and allocated kidx info @ptc, @pta and
+ * @pkidx if non-zero.
+ * Used for table auto-creation to support old binaries.
+ *
+ * Returns 0 on success.
+ */
static int
create_table_compat(struct ip_fw_chain *ch, struct tid_info *ti,
struct table_config **ptc, struct table_algo **pta, uint16_t *pkidx)
@@ -212,6 +220,7 @@ create_table_compat(struct ip_fw_chain *
int error;
memset(&xi, 0, sizeof(xi));
+ /* Set u32 as default value type for legacy clients */
xi.vtype = IPFW_VTYPE_U32;
error = create_table_internal(ch, ti, NULL, &xi, ptc, pta, pkidx, 1);
@@ -1523,163 +1532,6 @@ ipfw_describe_table(struct ip_fw_chain *
return (0);
}
-struct dump_args {
- struct table_info *ti;
- struct table_config *tc;
- struct sockopt_data *sd;
- uint32_t cnt;
- uint16_t uidx;
- int error;
- ipfw_table_entry *ent;
- uint32_t size;
- ipfw_obj_tentry tent;
-};
-
-int
-ipfw_dump_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
- struct sockopt_data *sd)
-{
- int error;
-
- switch (op3->version) {
- case 0:
- error = ipfw_dump_table_v0(ch, sd);
- break;
- case 1:
- error = ipfw_dump_table_v1(ch, sd);
- break;
- default:
- error = ENOTSUP;
- }
-
- return (error);
-}
-
-/*
- * 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_obj_tentry x N ]
- *
- * Returns 0 on success
- */
-static int
-ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd)
-{
- 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 = sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
- oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
- if (oh == NULL)
- return (EINVAL);
-
- i = (ipfw_xtable_info *)(oh + 1);
- 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(ch, tc, i);
-
- if (sd->valsize < i->size) {
-
- /*
- * Submitted buffer size is not enough.
- * WE've already filled in @i structure with
- * relevant table info including size, so we
- * can return. Buffer will be flushed automatically.
- */
- IPFW_UH_RUNLOCK(ch);
- return (ENOMEM);
- }
-
- /*
- * 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.sd = sd;
-
- ta = tc->ta;
-
- ta->foreach(tc->astate, da.ti, dump_table_tentry, &da);
- IPFW_UH_RUNLOCK(ch);
-
- return (da.error);
-}
-
-/*
- * Dumps all table data
- * Data layout (version 0)(legacy):
- * 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_data *sd)
-{
- ipfw_xtable *xtbl;
- struct tid_info ti;
- struct table_config *tc;
- struct table_algo *ta;
- struct dump_args da;
- size_t sz;
-
- xtbl = (ipfw_xtable *)ipfw_get_sopt_header(sd, sizeof(ipfw_xtable));
- if (xtbl == NULL)
- return (EINVAL);
-
- memset(&ti, 0, sizeof(ti));
- 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 * sizeof(ipfw_table_xentry) + sizeof(ipfw_xtable);
-
- xtbl->cnt = tc->count;
- xtbl->size = sz;
- xtbl->type = tc->no.type;
- xtbl->tbl = ti.uidx;
-
- if (sd->valsize < sz) {
-
- /*
- * Submitted buffer size is not enough.
- * WE've already filled in @i structure with
- * relevant table info including size, so we
- * can return. Buffer will be flushed automatically.
- */
- IPFW_UH_RUNLOCK(ch);
- return (ENOMEM);
- }
-
- /* 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.sd = sd;
-
- ta = tc->ta;
-
- ta->foreach(tc->astate, da.ti, dump_table_xentry, &da);
- IPFW_UH_RUNLOCK(ch);
-
- return (0);
-}
-
/*
* Modifies existing table.
* Data layout (v0)(current):
@@ -1927,6 +1779,41 @@ ipfw_export_table_ntlv(struct ip_fw_chai
}
/*
+ * Marks every table kidx used in @rule with bit in @bmask.
+ * Used to generate bitmask of referenced tables for given ruleset.
+ *
+ * Returns number of newly-referenced tables.
+ */
+int
+ipfw_mark_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule,
+ uint32_t *bmask)
+{
+ int cmdlen, l, count;
+ ipfw_insn *cmd;
+ uint16_t kidx;
+ uint8_t type;
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ count = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+
+ if ((bmask[kidx / 32] & (1 << (kidx % 32))) == 0)
+ count++;
+
+ bmask[kidx / 32] |= 1 << (kidx % 32);
+ }
+
+ return (count);
+}
+
+
+/*
* Exports table @tc info into standard ipfw_xtable_info format.
*/
static void
@@ -2022,43 +1909,201 @@ 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)
-{
+struct dump_args {
+ struct table_info *ti;
struct table_config *tc;
+ struct sockopt_data *sd;
+ uint32_t cnt;
+ uint16_t uidx;
+ int error;
+ ipfw_table_entry *ent;
+ uint32_t size;
+ ipfw_obj_tentry tent;
+};
- if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
- return (ESRCH);
- *cnt = tc->count;
- return (0);
-}
-
-/*
- * Legacy IP_FW_TABLE_XGETSIZE handler
- */
int
-ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
+ipfw_dump_table(struct ip_fw_chain *ch, ip_fw3_opheader *op3,
+ struct sockopt_data *sd)
{
- struct table_config *tc;
+ int error;
- if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL) {
- *cnt = 0;
- return (0); /* 'table all list' requires success */
+ switch (op3->version) {
+ case 0:
+ error = ipfw_dump_table_v0(ch, sd);
+ break;
+ case 1:
+ error = ipfw_dump_table_v1(ch, sd);
+ break;
+ default:
+ error = ENOTSUP;
}
- *cnt = tc->count * sizeof(ipfw_table_xentry);
- if (tc->count > 0)
- *cnt += sizeof(ipfw_xtable);
- return (0);
+
+ return (error);
}
+/*
+ * 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_obj_tentry x N ]
+ *
+ * Returns 0 on success
+ */
static int
-dump_table_entry(void *e, void *arg)
+ipfw_dump_table_v1(struct ip_fw_chain *ch, struct sockopt_data *sd)
{
- struct dump_args *da;
- struct table_config *tc;
+ 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 = sizeof(ipfw_obj_header) + sizeof(ipfw_xtable_info);
+ oh = (struct _ipfw_obj_header *)ipfw_get_sopt_header(sd, sz);
+ if (oh == NULL)
+ return (EINVAL);
+
+ i = (ipfw_xtable_info *)(oh + 1);
+ 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(ch, tc, i);
+
+ if (sd->valsize < i->size) {
+
+ /*
+ * Submitted buffer size is not enough.
+ * WE've already filled in @i structure with
+ * relevant table info including size, so we
+ * can return. Buffer will be flushed automatically.
+ */
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+
+ /*
+ * 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.sd = sd;
+
+ ta = tc->ta;
+
+ ta->foreach(tc->astate, da.ti, dump_table_tentry, &da);
+ IPFW_UH_RUNLOCK(ch);
+
+ return (da.error);
+}
+
+/*
+ * Dumps all table data
+ * Data layout (version 0)(legacy):
+ * 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_data *sd)
+{
+ ipfw_xtable *xtbl;
+ struct tid_info ti;
+ struct table_config *tc;
+ struct table_algo *ta;
+ struct dump_args da;
+ size_t sz;
+
+ xtbl = (ipfw_xtable *)ipfw_get_sopt_header(sd, sizeof(ipfw_xtable));
+ if (xtbl == NULL)
+ return (EINVAL);
+
+ memset(&ti, 0, sizeof(ti));
+ 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 * sizeof(ipfw_table_xentry) + sizeof(ipfw_xtable);
+
+ xtbl->cnt = tc->count;
+ xtbl->size = sz;
+ xtbl->type = tc->no.type;
+ xtbl->tbl = ti.uidx;
+
+ if (sd->valsize < sz) {
+
+ /*
+ * Submitted buffer size is not enough.
+ * WE've already filled in @i structure with
+ * relevant table info including size, so we
+ * can return. Buffer will be flushed automatically.
+ */
+ IPFW_UH_RUNLOCK(ch);
+ return (ENOMEM);
+ }
+
+ /* 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.sd = sd;
+
+ ta = tc->ta;
+
+ ta->foreach(tc->astate, da.ti, dump_table_xentry, &da);
+ IPFW_UH_RUNLOCK(ch);
+
+ return (0);
+}
+
+
+/*
+ * Legacy IP_FW_TABLE_GETSIZE handler
+ */
+int
+ipfw_count_table(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
+{
+ struct table_config *tc;
+
+ if ((tc = find_table(CHAIN_TO_NI(ch), ti)) == NULL)
+ return (ESRCH);
+ *cnt = tc->count;
+ return (0);
+}
+
+/*
+ * Legacy IP_FW_TABLE_XGETSIZE handler
+ */
+int
+ipfw_count_xtable(struct ip_fw_chain *ch, struct tid_info *ti, uint32_t *cnt)
+{
+ struct table_config *tc;
+
+ 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);
+ return (0);
+}
+
+static int
+dump_table_entry(void *e, void *arg)
+{
+ struct dump_args *da;
+ struct table_config *tc;
struct table_algo *ta;
ipfw_table_entry *ent;
int error;
@@ -2610,11 +2655,7 @@ alloc_table_config(struct ip_fw_chain *c
tc->tflags = tflags;
tc->ta = ta;
strlcpy(tc->tablename, name, sizeof(tc->tablename));
- /* Set default value type to u32 for compability reasons */
- if (vtype == 0)
- tc->vtype = IPFW_VTYPE_U32;
- else
- tc->vtype = vtype;
+ tc->vtype = vtype;
if (ti->tlvs == NULL) {
tc->no.compat = 1;
@@ -2707,196 +2748,67 @@ unlink_table(struct ip_fw_chain *ch, str
tc->ta->change_ti(tc->astate, NULL);
}
+struct swap_table_args {
+ int set;
+ int new_set;
+ int mv;
+};
+
/*
- * Finds and bumps refcount for tables referenced by given @rule.
- * Allocates new indexes for non-existing tables.
- * Fills in @oib array with userland/kernel indexes.
- * First free oidx pointer is saved back in @oib.
+ * Change set for each matching table.
*
- * Returns 0 on success.
+ * Ensure we dispatch each table once by setting/checking ochange
+ * fields.
*/
-static int
-bind_table_rule(struct ip_fw_chain *ch, struct ip_fw *rule,
- struct rule_check_info *ci, struct obj_idx **oib, struct tid_info *ti)
+static void
+swap_table_set(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
{
struct table_config *tc;
- struct namedobj_instance *ni;
- struct named_object *no;
- int cmdlen, error, l, numnew;
- uint16_t kidx;
- ipfw_insn *cmd;
- struct obj_idx *pidx, *pidx_first, *p;
+ struct swap_table_args *sta;
- pidx_first = *oib;
- pidx = pidx_first;
- l = rule->cmd_len;
- cmd = rule->cmd;
- cmdlen = 0;
- error = 0;
- numnew = 0;
+ tc = (struct table_config *)no;
+ sta = (struct swap_table_args *)arg;
- IPFW_UH_WLOCK(ch);
- ni = CHAIN_TO_NI(ch);
+ if (no->set != sta->set && (no->set != sta->new_set || sta->mv != 0))
+ return;
- /*
- * Increase refcount on each referenced table.
- * Allocate table indexes for non-existing tables.
- */
- for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
- cmdlen = F_LEN(cmd);
+ if (tc->ochanged != 0)
+ return;
- if (classify_table_opcode(cmd, &ti->uidx, &ti->type) != 0)
- continue;
+ tc->ochanged = 1;
+ ipfw_objhash_del(ni, no);
+ if (no->set == sta->set)
+ no->set = sta->new_set;
+ else
+ no->set = sta->set;
+ ipfw_objhash_add(ni, no);
+}
- pidx->uidx = ti->uidx;
- pidx->type = ti->type;
+/*
+ * Cleans up ochange field for all tables.
+ */
+static void
+clean_table_set_data(struct namedobj_instance *ni, struct named_object *no,
+ void *arg)
+{
+ struct table_config *tc;
+ struct swap_table_args *sta;
- if ((tc = find_table(ni, ti)) != NULL) {
- if (tc->no.type != ti->type) {
- /* Incompatible types */
- error = EINVAL;
- break;
- }
+ tc = (struct table_config *)no;
+ sta = (struct swap_table_args *)arg;
- /* Reference found table and save kidx */
- tc->no.refcnt++;
- pidx->kidx = tc->no.kidx;
- pidx++;
- continue;
- }
+ tc->ochanged = 0;
+}
- /*
- * Compability stuff for old clients:
- * prepare to manually create non-existing tables.
- */
- pidx++;
- numnew++;
- }
-
- if (error != 0) {
- /* Unref everything we have already done */
- for (p = *oib; p < pidx; p++) {
- if (p->kidx == 0)
- continue;
-
- /* Find & unref by existing idx */
- no = ipfw_objhash_lookup_kidx(ni, p->kidx);
- KASSERT(no != NULL, ("Ref'd table %d disappeared",
- p->kidx));
-
- no->refcnt--;
- }
- }
-
- IPFW_UH_WUNLOCK(ch);
-
- if (numnew == 0) {
- *oib = pidx;
- return (error);
- }
-
- /*
- * Compatibility stuff: do actual creation for non-existing,
- * but referenced tables.
- */
- for (p = pidx_first; p < pidx; p++) {
- if (p->kidx != 0)
- continue;
-
- ti->uidx = p->uidx;
- ti->type = p->type;
- ti->atype = 0;
-
- error = create_table_compat(ch, ti, NULL, NULL, &kidx);
- if (error == 0) {
- p->kidx = kidx;
- continue;
- }
-
- /* Error. We have to drop references */
- IPFW_UH_WLOCK(ch);
- for (p = pidx_first; p < pidx; p++) {
- if (p->kidx == 0)
- continue;
-
- /* Find & unref by existing idx */
- no = ipfw_objhash_lookup_kidx(ni, p->kidx);
- KASSERT(no != NULL, ("Ref'd table %d disappeared",
- p->kidx));
-
- no->refcnt--;
- }
- IPFW_UH_WUNLOCK(ch);
-
- return (error);
- }
-
- *oib = pidx;
-
- return (error);
-}
-
-struct swap_table_args {
- int set;
- int new_set;
- int mv;
-};
-
-/*
- * Change set for each matching table.
- *
- * Ensure we dispatch each table once by setting/checking ochange
- * fields.
- */
-static void
-swap_table_set(struct namedobj_instance *ni, struct named_object *no,
- void *arg)
-{
- struct table_config *tc;
- struct swap_table_args *sta;
-
- tc = (struct table_config *)no;
- sta = (struct swap_table_args *)arg;
-
- if (no->set != sta->set && (no->set != sta->new_set || sta->mv != 0))
- return;
-
- if (tc->ochanged != 0)
- return;
-
- tc->ochanged = 1;
- ipfw_objhash_del(ni, no);
- if (no->set == sta->set)
- no->set = sta->new_set;
- else
- no->set = sta->set;
- ipfw_objhash_add(ni, no);
-}
-
-/*
- * Cleans up ochange field for all tables.
- */
-static void
-clean_table_set_data(struct namedobj_instance *ni, struct named_object *no,
- void *arg)
-{
- struct table_config *tc;
- struct swap_table_args *sta;
-
- tc = (struct table_config *)no;
- sta = (struct swap_table_args *)arg;
-
- tc->ochanged = 0;
-}
-
-/*
- * Swaps tables within two sets.
- */
-void
-ipfw_swap_tables_sets(struct ip_fw_chain *ch, uint32_t set,
- uint32_t new_set, int mv)
-{
- struct swap_table_args sta;
+/*
+ * Swaps tables within two sets.
+ */
+void
+ipfw_swap_tables_sets(struct ip_fw_chain *ch, uint32_t set,
+ uint32_t new_set, int mv)
+{
+ struct swap_table_args sta;
IPFW_UH_WLOCK_ASSERT(ch);
@@ -3026,6 +2938,172 @@ ipfw_move_tables_sets(struct ip_fw_chain
}
/*
+ * Finds and bumps refcount for tables referenced by given @rule.
+ * Allocates new indexes for non-existing tables.
+ * Fills in @oib array with userland/kernel indexes.
+ * First free oidx pointer is saved back in @oib.
+ *
+ * Returns 0 on success.
+ */
+static int
+bind_table_rule(struct ip_fw_chain *ch, struct ip_fw *rule,
+ struct rule_check_info *ci, struct obj_idx **oib, struct tid_info *ti)
+{
+ struct table_config *tc;
+ struct namedobj_instance *ni;
+ struct named_object *no;
+ int cmdlen, error, l, numnew;
+ uint16_t kidx;
+ ipfw_insn *cmd;
+ struct obj_idx *pidx, *pidx_first, *p;
+
+ pidx_first = *oib;
+ pidx = pidx_first;
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ error = 0;
+ numnew = 0;
+
+ IPFW_UH_WLOCK(ch);
+ ni = CHAIN_TO_NI(ch);
+
+ /*
+ * Increase refcount on each referenced table.
+ * Allocate table indexes for non-existing tables.
+ */
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &ti->uidx, &ti->type) != 0)
+ continue;
+
+ pidx->uidx = ti->uidx;
+ pidx->type = ti->type;
+
+ if ((tc = find_table(ni, ti)) != NULL) {
+ if (tc->no.type != ti->type) {
+ /* Incompatible types */
+ error = EINVAL;
+ break;
+ }
+
+ /* Reference found table and save kidx */
+ tc->no.refcnt++;
+ pidx->kidx = tc->no.kidx;
+ pidx++;
+ continue;
+ }
+
+ /*
+ * Compability stuff for old clients:
+ * prepare to manually create non-existing tables.
+ */
+ pidx++;
+ numnew++;
+ }
+
+ if (error != 0) {
+ /* Unref everything we have already done */
+ for (p = *oib; p < pidx; p++) {
+ if (p->kidx == 0)
+ continue;
+
+ /* Find & unref by existing idx */
+ no = ipfw_objhash_lookup_kidx(ni, p->kidx);
+ KASSERT(no != NULL, ("Ref'd table %d disappeared",
+ p->kidx));
+
+ no->refcnt--;
+ }
+ }
+
+ IPFW_UH_WUNLOCK(ch);
+
+ if (numnew == 0) {
+ *oib = pidx;
+ return (error);
+ }
+
+ /*
+ * Compatibility stuff: do actual creation for non-existing,
+ * but referenced tables.
+ */
+ for (p = pidx_first; p < pidx; p++) {
+ if (p->kidx != 0)
+ continue;
+
+ ti->uidx = p->uidx;
+ ti->type = p->type;
+ ti->atype = 0;
+
+ error = create_table_compat(ch, ti, NULL, NULL, &kidx);
+ if (error == 0) {
+ p->kidx = kidx;
+ continue;
+ }
+
+ /* Error. We have to drop references */
+ IPFW_UH_WLOCK(ch);
+ for (p = pidx_first; p < pidx; p++) {
+ if (p->kidx == 0)
+ continue;
+
+ /* Find & unref by existing idx */
+ no = ipfw_objhash_lookup_kidx(ni, p->kidx);
+ KASSERT(no != NULL, ("Ref'd table %d disappeared",
+ p->kidx));
+
+ no->refcnt--;
+ }
+ IPFW_UH_WUNLOCK(ch);
+
+ return (error);
+ }
+
+ *oib = pidx;
+
+ return (error);
+}
+
+/*
+ * Remove references from every table used in @rule.
+ */
+void
+ipfw_unbind_table_rule(struct ip_fw_chain *chain, struct ip_fw *rule)
+{
+ int cmdlen, l;
+ ipfw_insn *cmd;
+ struct namedobj_instance *ni;
+ struct named_object *no;
+ uint16_t kidx;
+ uint8_t type;
+
+ IPFW_UH_WLOCK_ASSERT(chain);
+ ni = CHAIN_TO_NI(chain);
+
+ l = rule->cmd_len;
+ cmd = rule->cmd;
+ cmdlen = 0;
+ for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
+ cmdlen = F_LEN(cmd);
+
+ if (classify_table_opcode(cmd, &kidx, &type) != 0)
+ continue;
+
+ no = ipfw_objhash_lookup_kidx(ni, kidx);
+
+ KASSERT(no != NULL, ("table id %d not found", kidx));
+ KASSERT(no->type == type, ("wrong type %d (%d) for table id %d",
+ no->type, type, kidx));
+ KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
+ kidx, no->refcnt));
+
+ no->refcnt--;
+ }
+}
+
+/*
* Compatibility function for old ipfw(8) binaries.
* Rewrites table kernel indices with userland ones.
* Convert tables matching '/^\d+$/' to their atoi() value.
@@ -3077,40 +3155,6 @@ ipfw_rewrite_table_kidx(struct ip_fw_cha
}
/*
- * Marks every table kidx used in @rule with bit in @bmask.
- * Used to generate bitmask of referenced tables for given ruleset.
- *
- * Returns number of newly-referenced tables.
- */
-int
-ipfw_mark_table_kidx(struct ip_fw_chain *chain, struct ip_fw *rule,
- uint32_t *bmask)
-{
- int cmdlen, l, count;
- ipfw_insn *cmd;
- uint16_t kidx;
- uint8_t type;
-
- l = rule->cmd_len;
- cmd = rule->cmd;
- cmdlen = 0;
- count = 0;
- for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
- cmdlen = F_LEN(cmd);
-
- if (classify_table_opcode(cmd, &kidx, &type) != 0)
- continue;
-
- if ((bmask[kidx / 32] & (1 << (kidx % 32))) == 0)
- count++;
-
- bmask[kidx / 32] |= 1 << (kidx % 32);
- }
-
- return (count);
-}
-
-/*
* Checks is opcode is referencing table of appropriate type.
* Adds reference count for found table if true.
* Rewrites user-supplied opcode values with kernel ones.
@@ -3186,40 +3230,4 @@ free:
return (error);
}
-/*
- * Remove references from every table used in @rule.
- */
-void
-ipfw_unbind_table_rule(struct ip_fw_chain *chain, struct ip_fw *rule)
-{
- int cmdlen, l;
- ipfw_insn *cmd;
- struct namedobj_instance *ni;
- struct named_object *no;
- uint16_t kidx;
- uint8_t type;
-
- IPFW_UH_WLOCK_ASSERT(chain);
- ni = CHAIN_TO_NI(chain);
-
- l = rule->cmd_len;
- cmd = rule->cmd;
- cmdlen = 0;
- for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) {
- cmdlen = F_LEN(cmd);
-
- if (classify_table_opcode(cmd, &kidx, &type) != 0)
- continue;
-
- no = ipfw_objhash_lookup_kidx(ni, kidx);
-
- KASSERT(no != NULL, ("table id %d not found", kidx));
- KASSERT(no->type == type, ("wrong type %d (%d) for table id %d",
- no->type, type, kidx));
- KASSERT(no->refcnt > 0, ("refcount for table %d is %d",
- kidx, no->refcnt));
-
- no->refcnt--;
- }
-}
More information about the svn-src-projects
mailing list