From owner-svn-src-projects@FreeBSD.ORG Mon Jun 16 13:05:09 2014 Return-Path: Delivered-To: svn-src-projects@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 00023CCB; Mon, 16 Jun 2014 13:05:08 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id E03F82EF4; Mon, 16 Jun 2014 13:05:08 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s5GD58PZ095815; Mon, 16 Jun 2014 13:05:08 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s5GD57aq095805; Mon, 16 Jun 2014 13:05:07 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201406161305.s5GD57aq095805@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Mon, 16 Jun 2014 13:05:07 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r267542 - in projects/ipfw/sys: netinet netpfil/ipfw X-SVN-Group: projects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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: Mon, 16 Jun 2014 13:05:09 -0000 Author: melifaro Date: Mon Jun 16 13:05:07 2014 New Revision: 267542 URL: http://svnweb.freebsd.org/changeset/base/267542 Log: * Add IP_FW_TABLE_XCREATE / IP_FW_TABLE_XMODIFY opcodes. * Add 'algoname' string to ipfw_xtable_info permitting to specify lookup algoritm with parameters. * Rework part of ipfw_rewrite_table_uidx() Sponsored by: Yandex LLC Modified: 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 projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Modified: projects/ipfw/sys/netinet/ip_fw.h ============================================================================== --- projects/ipfw/sys/netinet/ip_fw.h Mon Jun 16 12:37:10 2014 (r267541) +++ projects/ipfw/sys/netinet/ip_fw.h Mon Jun 16 13:05:07 2014 (r267542) @@ -81,10 +81,12 @@ typedef struct _ip_fw3_opheader { #define IP_FW_TABLE_XGETSIZE 88 /* get table size (deprecated) */ #define IP_FW_TABLE_XLIST 89 /* list table contents */ #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 */ +#define IP_FW_TABLES_XGETSIZE 91 /* get size for tables list */ +#define IP_FW_TABLES_XLIST 92 /* list all tables */ +#define IP_FW_TABLE_XINFO 93 /* request info for one table */ +#define IP_FW_TABLE_XFLUSH 94 /* flush table data */ +#define IP_FW_TABLE_XCREATE 95 /* create new table */ +#define IP_FW_TABLE_XMODIFY 96 /* modify existing table */ /* * Usage guidelines: @@ -693,7 +695,7 @@ typedef struct _ipfw_obj_ntlv { typedef struct _ipfw_xtable_info { uint8_t type; /* table type (cidr,iface,..) */ - uint8_t ftype; /* format table type */ + uint8_t ftype; /* table value format type */ uint8_t atype; /* algorithm type */ uint8_t spare0; uint32_t set; /* set table is in */ @@ -702,6 +704,7 @@ typedef struct _ipfw_xtable_info { uint32_t count; /* Number of records */ uint32_t size; /* Total size of records */ char tablename[64]; /* table name */ + char algoname[32]; /* algorithm name */ } ipfw_xtable_info; #define IPFW_OBJTYPE_TABLE 1 Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Mon Jun 16 12:37:10 2014 (r267541) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_private.h Mon Jun 16 13:05:07 2014 (r267542) @@ -362,6 +362,8 @@ struct named_object *ipfw_objhash_lookup uint32_t set, char *name); struct named_object *ipfw_objhash_lookup_idx(struct namedobj_instance *ni, uint32_t set, uint16_t idx); +int ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, + struct named_object *b); void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no); void ipfw_objhash_del(struct namedobj_instance *ni, struct named_object *no); uint32_t ipfw_objhash_count(struct namedobj_instance *ni); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Mon Jun 16 12:37:10 2014 (r267541) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Mon Jun 16 13:05:07 2014 (r267542) @@ -1172,6 +1172,14 @@ ipfw_ctl(struct sockopt *sopt) break; /*--- TABLE opcodes ---*/ + case IP_FW_TABLE_XCREATE: /* IP_FW3 */ + case IP_FW_TABLE_XMODIFY: /* IP_FW3 */ + if (opt == IP_FW_TABLE_XCREATE) + error = ipfw_create_table(chain, sopt, op3); + else + error= ipfw_modify_table(chain, sopt, op3); + break; + case IP_FW_TABLE_XDESTROY: /* IP_FW3 */ case IP_FW_TABLE_XFLUSH: /* IP_FW3 */ { @@ -1705,6 +1713,17 @@ ipfw_objhash_lookup_idx(struct namedobj_ return (NULL); } +int +ipfw_objhash_same_name(struct namedobj_instance *ni, struct named_object *a, + struct named_object *b) +{ + + if ((strcmp(a->name, b->name) == 0) && a->set == b->set) + return (1); + + return (0); +} + void ipfw_objhash_add(struct namedobj_instance *ni, struct named_object *no) { Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Mon Jun 16 12:37:10 2014 (r267541) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Mon Jun 16 13:05:07 2014 (r267542) @@ -69,8 +69,9 @@ __FBSDID("$FreeBSD$"); * `ta->atype` represents exact lookup algorithm. * For example, we can use more efficient search schemes if we plan * to use some specific table for storing host-routes only. - * `ftype` is pure userland field helping to properly format table data - * e.g. "value is IPv4 nexthop" or "key is port number" + * `ftype` (at the moment )is pure userland field helping to properly + * format value data e.g. "value is IPv4 nexthop" or "value is DSCP" + * or "value is port". * */ struct table_config { @@ -95,7 +96,7 @@ 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); + struct tid_info *ti, struct table_algo *ta, char *adata); static void free_table_config(struct namedobj_instance *ni, struct table_config *tc); static void link_table(struct ip_fw_chain *chain, struct table_config *tc); @@ -114,7 +115,7 @@ static int ipfw_dump_table_v1(struct ip_ ip_fw3_opheader *op3, size_t valsize); static struct table_algo *find_table_algo(struct tables_config *tableconf, - struct tid_info *ti); + struct tid_info *ti, char *name); #define CHAIN_TO_TCFG(chain) ((struct tables_config *)(chain)->tblcfg) #define CHAIN_TO_NI(chain) (CHAIN_TO_TCFG(chain)->namehash) @@ -161,10 +162,10 @@ ipfw_add_table_entry(struct ip_fw_chain tc_new = NULL; if (ta == NULL) { /* Table not found. We have to create new one */ - if ((ta = find_table_algo(CHAIN_TO_TCFG(ch), ti)) == NULL) + if ((ta = find_table_algo(CHAIN_TO_TCFG(ch), ti, NULL)) == NULL) return (ENOTSUP); - tc_new = alloc_table_config(ni, ti, ta); + tc_new = alloc_table_config(ni, ti, ta, NULL); if (tc_new == NULL) return (ENOMEM); } @@ -330,9 +331,10 @@ ipfw_flush_table(struct ip_fw_chain *ch, /* * Stage 2: allocate new table instance using same algo. + * TODO: pass startup parametes somehow. */ memset(&ti_new, 0, sizeof(struct table_info)); - if ((error = ta->init(&astate_new, &ti_new)) != 0) { + if ((error = ta->init(&astate_new, &ti_new, NULL)) != 0) { IPFW_UH_WLOCK(ch); tc->no.refcnt--; IPFW_UH_WUNLOCK(ch); @@ -885,6 +887,99 @@ ipfw_dump_table_v0(struct ip_fw_chain *c } /* + * High-level setsockopt cmds + */ +int +ipfw_modify_table(struct ip_fw_chain *ch, struct sockopt *sopt, + ip_fw3_opheader *op3) +{ + + return (ENOTSUP); +} + +/* + * Creates new table. + * Data layout: + * Request: [ ipfw_obj_header ipfw_xtable_info ] + * + * Returns 0 on success + */ +int +ipfw_create_table(struct ip_fw_chain *ch, struct sockopt *sopt, + ip_fw3_opheader *op3) +{ + struct _ipfw_obj_header *oh; + ipfw_xtable_info *i; + char *tname, *aname; + struct tid_info ti; + struct namedobj_instance *ni; + struct table_config *tc; + struct table_algo *ta; + uint16_t kidx; + + if (sopt->sopt_valsize < sizeof(*oh) + sizeof(ipfw_xtable_info)) + return (EINVAL); + + oh = (struct _ipfw_obj_header *)op3; + i = (ipfw_xtable_info *)(oh + 1); + + /* + * Verify user-supplied strings. + * Check for null-terminated/zero-lenght strings/ + */ + tname = i->tablename; + aname = i->algoname; + if (strnlen(tname, sizeof(i->tablename)) == sizeof(i->tablename) || + tname[0] == '\0' || + strnlen(aname, sizeof(i->algoname)) == sizeof(i->algoname)) + return (EINVAL); + + if (aname[0] == '\0') { + /* Use default algorithm */ + aname = NULL; + } + + objheader_to_ti(oh, &ti); + + ni = CHAIN_TO_NI(ch); + + IPFW_UH_RLOCK(ch); + if ((tc = find_table(ni, &ti)) != NULL) { + IPFW_UH_RUNLOCK(ch); + return (EEXIST); + } + ta = find_table_algo(CHAIN_TO_TCFG(ch), &ti, aname); + IPFW_UH_RUNLOCK(ch); + + if (ta == NULL) + return (ENOTSUP); + + if ((tc = alloc_table_config(ni, &ti, ta, aname)) == NULL) + return (ENOMEM); + + IPFW_UH_WLOCK(ch); + if (ipfw_objhash_alloc_idx(ni, ti.set, &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); + free_table_config(ni, tc); + return (EBUSY); + } + + tc->no.kidx = kidx; + + IPFW_WLOCK(ch); + link_table(ch, tc); + IPFW_WUNLOCK(ch); + + IPFW_UH_WUNLOCK(ch); + + return (0); +} + + +/* * Checks if supplied buffer size is "reasonable". * Permit valsize between current needed size and * 2x needed size + 1 @@ -1059,7 +1154,9 @@ ipfw_dump_table_legacy(struct ip_fw_chai return (0); } - +/* + * Dumps table entry in eXtended format (current). + */ static int dump_table_xentry(void *e, void *arg) { @@ -1089,11 +1186,13 @@ dump_table_xentry(void *e, void *arg) */ /* - * Finds algoritm by index or table type + * Finds algoritm by index, table type or supplied name */ static struct table_algo * -find_table_algo(struct tables_config *tcfg, struct tid_info *ti) +find_table_algo(struct tables_config *tcfg, struct tid_info *ti, char *name) { + int i, l; + struct table_algo *ta; /* Search by index */ if (ti->atype != 0) { @@ -1102,6 +1201,30 @@ find_table_algo(struct tables_config *tc return (tcfg->algo[ti->atype]); } + /* Search by name if supplied */ + if (name != NULL) { + /* TODO: better search */ + for (i = 1; i <= tcfg->algo_count; i++) { + ta = tcfg->algo[i]; + + /* + * One can supply additional algorithm + * parameters so we compare only the first word + * of supplied name: + * 'hash_cidr hsize=32' + * '^^^^^^^^^' + * + */ + l = strlen(ta->name); + if (strncmp(name, ta->name, l) == 0) { + if (name[l] == '\0' || name[l] == ' ') + return (ta); + } + } + + return (NULL); + } + /* Search by type */ switch (ti->type) { case IPFW_TABLE_CIDR: @@ -1272,7 +1395,7 @@ find_table(struct namedobj_instance *ni, static struct table_config * alloc_table_config(struct namedobj_instance *ni, struct tid_info *ti, - struct table_algo *ta) + struct table_algo *ta, char *aname) { char *name, bname[16]; struct table_config *tc; @@ -1300,7 +1423,7 @@ alloc_table_config(struct namedobj_insta } /* Preallocate data structures for new tables */ - error = ta->init(&tc->astate, &tc->ti); + error = ta->init(&tc->astate, &tc->ti, aname); if (error != 0) { free(tc, M_IPFW); return (NULL); @@ -1371,45 +1494,89 @@ unlink_table(struct ip_fw_chain *ch, str /* * Finds named object by @uidx number. * Refs found object, allocate new index for non-existing object. - * Fills in @pidx with userland/kernel indexes. + * Fills in @oib with userland/kernel indexes. + * First free oidx pointer is saved back in @oib. * * Returns 0 on success. */ static int -bind_table(struct namedobj_instance *ni, struct rule_check_info *ci, - struct obj_idx *pidx, struct tid_info *ti) +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 error, l, cmdlen; + ipfw_insn *cmd; + struct obj_idx *pidx, *p; + + pidx = *oib; + l = rule->cmd_len; + cmd = rule->cmd; + cmdlen = 0; + error = 0; - pidx->uidx = ti->uidx; - pidx->type = ti->type; + IPFW_UH_WLOCK(ch); + ni = CHAIN_TO_NI(ch); - tc = find_table(ni, ti); + for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { + cmdlen = F_LEN(cmd); - if (tc == NULL) { - /* Try to acquire refcount */ + 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; + } + + /* Table not found. Allocate new index and save for later */ if (ipfw_objhash_alloc_idx(ni, ti->set, &pidx->kidx) != 0) { printf("Unable to allocate table index in set %u." " Consider increasing net.inet.ip.fw.tables_max", - ti->set); - return (EBUSY); + ti->set); + error = EBUSY; + break; } - pidx->new = 1; ci->new_tables++; - - return (0); + pidx->new = 1; + pidx++; } - /* Check if table type if valid first */ - if (tc->no.type != ti->type) - return (EINVAL); + if (error != 0) { + /* Unref everything we have already done */ + for (p = *oib; p < pidx; p++) { + if (p->new != 0) { + ipfw_objhash_free_idx(ni, ci->tableset,p->kidx); + continue; + } - tc->no.refcnt++; + /* Find & unref by existing idx */ + no = ipfw_objhash_lookup_idx(ni, ci->tableset, p->kidx); + KASSERT(no != NULL, ("Ref'd table %d disappeared", + p->kidx)); - pidx->kidx = tc->no.kidx; + no->refcnt--; + } + } + IPFW_UH_WUNLOCK(ch); - return (0); + *oib = pidx; + + return (error); } /* @@ -1477,24 +1644,27 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha struct table_algo *ta; struct namedobj_instance *ni; struct named_object *no, *no_n, *no_tmp; - struct obj_idx *pidx, *p, *oib; + struct obj_idx *p, *pidx_first, *pidx_last; struct namedobjects_head nh; struct tid_info ti; ni = CHAIN_TO_NI(chain); + /* Prepare queue to store configs */ + TAILQ_INIT(&nh); + /* * Prepare an array for storing opcode indices. * Use stack allocation by default. */ if (ci->table_opcodes <= (sizeof(ci->obuf)/sizeof(ci->obuf[0]))) { /* Stack */ - pidx = ci->obuf; + pidx_first = ci->obuf; } else - pidx = malloc(ci->table_opcodes * sizeof(struct obj_idx), + pidx_first = malloc(ci->table_opcodes * sizeof(struct obj_idx), M_IPFW, M_WAITOK | M_ZERO); - oib = pidx; + pidx_last = pidx_first; error = 0; type = 0; @@ -1508,72 +1678,24 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha ti.tlen = ci->tlen; /* - * Stage 1: reference existing tables and determine number - * of tables we need to allocate + * Stage 1: reference existing tables, determine number + * of tables we need to allocate and allocate indexes for each. */ - IPFW_UH_WLOCK(chain); - - l = ci->krule->cmd_len; - cmd = ci->krule->cmd; - cmdlen = 0; - for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { - cmdlen = F_LEN(cmd); - - if (classify_table_opcode(cmd, &ti.uidx, &ti.type) != 0) - continue; - - /* - * Got table opcode with necessary info. - * Try to reference existing tables and allocate - * indices for non-existing one while holding write lock. - */ - if ((error = bind_table(ni, ci, pidx, &ti)) != 0) { - printf("error!\n"); - break; - } - - /* - * @pidx stores either existing ref'd table id or new one. - * Move to next index - */ - - pidx++; - } + error = bind_table_rule(chain, ci->krule, ci, &pidx_last, &ti); if (error != 0) { - /* Unref everything we have already done */ - for (p = oib; p < pidx; p++) { - if (p->new != 0) { - ipfw_objhash_free_idx(ni, ci->tableset,p->kidx); - continue; - } - - /* Find & unref by existing idx */ - no = ipfw_objhash_lookup_idx(ni, ci->tableset, p->kidx); - KASSERT(no!=NULL, ("Ref'd table %d disappeared", - p->kidx)); - - no->refcnt--; - } - - IPFW_UH_WUNLOCK(chain); - - if (oib != ci->obuf) - free(oib, M_IPFW); + if (pidx_first != ci->obuf) + free(pidx_first, M_IPFW); return (error); } - IPFW_UH_WUNLOCK(chain); - /* * Stage 2: allocate table configs for every non-existent table */ - /* Prepare queue to store configs */ - TAILQ_INIT(&nh); if (ci->new_tables > 0) { - for (p = oib; p < pidx; p++) { + for (p = pidx_first; p < pidx_last; p++) { if (p->new == 0) continue; @@ -1582,12 +1704,12 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha ti.type = p->type; ti.atype = 0; - ta = find_table_algo(CHAIN_TO_TCFG(chain), &ti); + ta = find_table_algo(CHAIN_TO_TCFG(chain), &ti, NULL); if (ta == NULL) { error = ENOTSUP; goto free; } - tc = alloc_table_config(ni, &ti, ta); + tc = alloc_table_config(ni, &ti, ta, NULL); if (tc == NULL) { error = ENOMEM; @@ -1607,7 +1729,7 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha */ TAILQ_FOREACH(no, &nh, nn_next) { TAILQ_FOREACH(no_tmp, &nh, nn_next) { - if (strcmp(no->name, no_tmp->name) != 0) + if (ipfw_objhash_same_name(ni, no, no_tmp) == 0) continue; if (no->type != no_tmp->type) { error = EINVAL; @@ -1649,7 +1771,6 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha * We have to rollback everything. */ IPFW_UH_WUNLOCK(chain); - goto free; } @@ -1662,24 +1783,28 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha IPFW_WLOCK(chain); TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) { no_n = ipfw_objhash_lookup_name(ni, no->set, no->name); - if (no_n != NULL) { - /* Increase refcount for existing table */ - no_n->refcnt++; - /* Keep oib array in sync: update kindx */ - for (p = oib; p < pidx; p++) { - if (p->kidx == no->kidx) { - p->kidx = no_n->kidx; - break; - } - } + if (no_n == NULL) { + /* New table. Attach to runtime hash */ + TAILQ_REMOVE(&nh, no, nn_next); + link_table(chain, (struct table_config *)no); continue; } - /* New table. Attach to runtime hash */ - TAILQ_REMOVE(&nh, no, nn_next); - - link_table(chain, (struct table_config *)no); + /* + * Newly-allocated table with the same type. + * Reference it and update out @pidx array + * rewrite info. + */ + no_n->refcnt++; + /* Keep oib array in sync: update kidx */ + for (p = pidx_first; p < pidx_last; p++) { + if (p->kidx != no->kidx) + continue; + /* Update kidx */ + p->kidx = no_n->kidx; + break; + } } IPFW_WUNLOCK(chain); } @@ -1688,14 +1813,14 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha l = ci->krule->cmd_len; cmd = ci->krule->cmd; cmdlen = 0; - pidx = oib; + p = pidx_first; for ( ; l > 0 ; l -= cmdlen, cmd += cmdlen) { cmdlen = F_LEN(cmd); if (classify_table_opcode(cmd, &uidx, &type) != 0) continue; - update_table_opcode(cmd, pidx->kidx); - pidx++; + update_table_opcode(cmd, p->kidx); + p++; } IPFW_UH_WUNLOCK(chain); @@ -1706,11 +1831,20 @@ ipfw_rewrite_table_uidx(struct ip_fw_cha * Stage 4: free resources */ free: - TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) - free_table_config(ni, tc); + if (!TAILQ_EMPTY(&nh)) { + /* Free indexes first */ + IPFW_UH_WLOCK(chain); + TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) { + ipfw_objhash_free_idx(ni, ci->tableset, no->kidx); + } + IPFW_UH_WUNLOCK(chain); + /* Free configs */ + TAILQ_FOREACH_SAFE(no, &nh, nn_next, no_tmp) + free_table_config(ni, tc); + } - if (oib != ci->obuf) - free(oib, M_IPFW); + if (pidx_first != ci->obuf) + free(pidx_first, M_IPFW); return (error); } Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Mon Jun 16 12:37:10 2014 (r267541) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Mon Jun 16 13:05:07 2014 (r267542) @@ -50,7 +50,7 @@ struct tentry_info { uint32_t value; /* value */ }; -typedef int (ta_init)(void **ta_state, struct table_info *ti); +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); @@ -69,7 +69,7 @@ typedef int ta_dump_xentry(void *ta_stat ipfw_table_xentry *xent); struct table_algo { - char name[64]; + char name[16]; int idx; ta_init *init; ta_destroy *destroy; @@ -100,6 +100,11 @@ int ipfw_dump_table(struct ip_fw_chain * int ipfw_describe_table(struct ip_fw_chain *ch, struct sockopt *sopt, ip_fw3_opheader *op3, size_t valsize); +int ipfw_create_table(struct ip_fw_chain *ch, struct sockopt *sopt, + ip_fw3_opheader *op3); +int ipfw_modify_table(struct ip_fw_chain *ch, struct sockopt *sopt, + ip_fw3_opheader *op3); + 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); int ipfw_add_table_entry(struct ip_fw_chain *ch, struct tid_info *ti, Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Mon Jun 16 12:37:10 2014 (r267541) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Mon Jun 16 13:05:07 2014 (r267542) @@ -164,7 +164,7 @@ ta_lookup_radix(struct table_info *ti, v * New table */ static int -ta_init_radix(void **ta_state, struct table_info *ti) +ta_init_radix(void **ta_state, struct table_info *ti, char *data) { if (!rn_inithead(&ti->state, OFF_LEN_INET)) @@ -537,7 +537,7 @@ flush_iface_entry(struct radix_node *rn, } static int -ta_init_iface(void **ta_state, struct table_info *ti) +ta_init_iface(void **ta_state, struct table_info *ti, char *data) { if (!rn_inithead(&ti->xstate, OFF_LEN_IFACE))