From owner-svn-src-projects@FreeBSD.ORG Tue Aug 12 17:03:14 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B7EE229A for ; Tue, 12 Aug 2014 17:03:14 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1 with cipher ECDHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 985DA2B7F for ; Tue, 12 Aug 2014 17:03:14 +0000 (UTC) Received: from melifaro (uid 1268) (envelope-from melifaro@FreeBSD.org) id 6450 by svn.freebsd.org (DragonFly Mail Agent v0.9+); Tue, 12 Aug 2014 17:03:14 +0000 From: Alexander V. Chernikov Date: Tue, 12 Aug 2014 17:03:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r269883 - projects/ipfw/sys/netpfil/ipfw X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Message-Id: <53ea48d2.6450.c4e1e09@svn.freebsd.org> X-BeenThere: svn-src-projects@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: "SVN commit messages for the src " projects" tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 12 Aug 2014 17:03:14 -0000 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 _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 - * */ /*