svn commit: r269883 - projects/ipfw/sys/netpfil/ipfw
Alexander V. Chernikov
melifaro at FreeBSD.org
Tue Aug 12 17:03:14 UTC 2014
Author: melifaro
Date: Tue Aug 12 17:03:13 2014
New Revision: 269883
URL: http://svnweb.freebsd.org/changeset/base/269883
Log:
* Clarify ipfw_swap_table operations
* Ensure <add|del>_table_entry handle ta change properly.
Modified:
projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Tue Aug 12 16:51:37 2014 (r269882)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Tue Aug 12 17:03:13 2014 (r269883)
@@ -681,7 +681,7 @@ commit_rules(struct ip_fw_chain *chain,
if (ci->table_opcodes == 0)
continue;
- ipfw_unbind_table_rule(chain, ci->krule);
+ ipfw_unref_rule_tables(chain, ci->krule);
}
IPFW_UH_WUNLOCK(chain);
}
@@ -741,7 +741,7 @@ ipfw_reap_add(struct ip_fw_chain *chain,
IPFW_UH_WLOCK_ASSERT(chain);
/* Unlink rule from everywhere */
- ipfw_unbind_table_rule(chain, rule);
+ ipfw_unref_rule_tables(chain, rule);
*((struct ip_fw **)rule) = *head;
*head = rule;
Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c
==============================================================================
--- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Aug 12 16:51:37 2014 (r269882)
+++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Tue Aug 12 17:03:13 2014 (r269883)
@@ -474,9 +474,14 @@ add_table_entry(struct ip_fw_chain *ch,
IPFW_UH_WLOCK(ch);
+ /* Drop reference we've used in first search */
+ tc->no.refcnt--;
+
/*
* Ensure we are able to add all entries without additional
* memory allocations. May release/reacquire UH_WLOCK.
+ * check_table_space() guarantees us @tc won't disappear
+ * by referencing it internally.
*/
kidx = tc->no.kidx;
error = check_table_space(ch, tc, KIDX_TO_TI(ch, kidx), count);
@@ -485,8 +490,16 @@ add_table_entry(struct ip_fw_chain *ch,
goto cleanup;
}
- /* Drop reference we've used in first search */
- tc->no.refcnt--;
+ /*
+ * Check if table algo is still the same.
+ * (changed ta may be the result of table swap).
+ */
+ if (ta != tc->ta) {
+ IPFW_UH_WUNLOCK(ch);
+ error = EINVAL;
+ goto cleanup;
+ }
+
/* We've got valid table in @tc. Let's try to add data */
kidx = tc->no.kidx;
ta = tc->ta;
@@ -582,6 +595,16 @@ del_table_entry(struct ip_fw_chain *ch,
/* Drop reference we've used in first search */
tc->no.refcnt--;
+ /*
+ * Check if table algo is still the same.
+ * (changed ta may be the result of table swap).
+ */
+ if (ta != tc->ta) {
+ IPFW_UH_WUNLOCK(ch);
+ error = EINVAL;
+ goto cleanup;
+ }
+
kidx = tc->no.kidx;
numdel = 0;
first_error = 0;
@@ -1113,14 +1136,28 @@ ipfw_swap_table(struct ip_fw_chain *ch,
* Swaps two tables of the same type/valtype.
*
* Checks if tables are compatible and limits
- * permits swap, than actually perform swap
- * by switching
- * 1) runtime data (ch->tablestate)
- * 2) runtime cache in @tc
- * 3) algo-specific data (tc->astate)
- * 4) number of items
+ * permits swap, than actually perform swap.
*
- * Since @ti has changed for each table, calls notification callbacks.
+ * Each table consists of 2 different parts:
+ * config:
+ * @tc (with name, set, kidx) and rule bindings, which is "stable".
+ * number of items
+ * table algo
+ * runtime:
+ * runtime data @ti (ch->tablestate)
+ * runtime cache in @tc
+ * algo-specific data (@tc->astate)
+ *
+ * So we switch:
+ * all runtime data
+ * number of items
+ * table algo
+ *
+ * After that we call @ti change handler for each table.
+ *
+ * Note that referencing @tc won't protect tc->ta from change.
+ * XXX: Do we need to restrict swap between locked tables?
+ * XXX: Do we need to exchange ftype?
*
* Returns 0 on success.
*/
@@ -1440,24 +1477,36 @@ ipfw_switch_tables_namespace(struct ip_f
return (0);
}
+/*
+ * Lookup an IP @addr in table @tbl.
+ * Stores found value in @val.
+ *
+ * Returns 1 if @addr was found.
+ */
int
ipfw_lookup_table(struct ip_fw_chain *ch, uint16_t tbl, in_addr_t addr,
uint32_t *val)
{
struct table_info *ti;
- ti = &(((struct table_info *)ch->tablestate)[tbl]);
+ ti = KIDX_TO_TI(ch, tbl);
return (ti->lookup(ti, &addr, sizeof(in_addr_t), val));
}
+/*
+ * Lookup an arbtrary key @paddr of legth @plen in table @tbl.
+ * Stores found value in @val.
+ *
+ * Returns 1 if key was found.
+ */
int
ipfw_lookup_table_extended(struct ip_fw_chain *ch, uint16_t tbl, uint16_t plen,
void *paddr, uint32_t *val)
{
struct table_info *ti;
- ti = &(((struct table_info *)ch->tablestate)[tbl]);
+ ti = KIDX_TO_TI(ch, tbl);
return (ti->lookup(ti, paddr, plen, val));
}
@@ -1656,7 +1705,7 @@ create_table_internal(struct ip_fw_chain
struct table_algo **pta, uint16_t *pkidx, int compat)
{
struct namedobj_instance *ni;
- struct table_config *tc, *tc_new, *tmp;;
+ struct table_config *tc, *tc_new, *tmp;
struct table_algo *ta;
uint16_t kidx;
@@ -2067,7 +2116,6 @@ ipfw_dump_table_v0(struct ip_fw_chain *c
return (0);
}
-
/*
* Legacy IP_FW_TABLE_GETSIZE handler
*/
@@ -2339,6 +2387,8 @@ ipfw_add_table_algo(struct ip_fw_chain *
/*
* Unregisters table algo using @idx as id.
+ * XXX: It is NOT safe to call this function in any place
+ * other than ipfw instance destroy handler.
*/
void
ipfw_del_table_algo(struct ip_fw_chain *ch, int idx)
@@ -2413,10 +2463,8 @@ ipfw_list_table_algo(struct ip_fw_chain
return (0);
}
-
/*
* Tables rewriting code
- *
*/
/*
More information about the svn-src-projects
mailing list