From owner-svn-src-projects@FreeBSD.ORG Fri Jul 25 20:44:05 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 871CCAFA; Fri, 25 Jul 2014 20:44:05 +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 749652BB4; Fri, 25 Jul 2014 20:44:05 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6PKi5tF060512; Fri, 25 Jul 2014 20:44:05 GMT (envelope-from sjg@svn.freebsd.org) Received: (from sjg@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6PKi5TN060511; Fri, 25 Jul 2014 20:44:05 GMT (envelope-from sjg@svn.freebsd.org) Message-Id: <201407252044.s6PKi5TN060511@svn.freebsd.org> From: "Simon J. Gerraty" Date: Fri, 25 Jul 2014 20:44:05 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r269096 - projects/bmake/share/mk 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: Fri, 25 Jul 2014 20:44:05 -0000 Author: sjg Date: Fri Jul 25 20:44:04 2014 New Revision: 269096 URL: http://svnweb.freebsd.org/changeset/base/269096 Log: Crude cross-build support thanks to clang Modified: projects/bmake/share/mk/local.sys.mk Modified: projects/bmake/share/mk/local.sys.mk ============================================================================== --- projects/bmake/share/mk/local.sys.mk Fri Jul 25 20:21:02 2014 (r269095) +++ projects/bmake/share/mk/local.sys.mk Fri Jul 25 20:44:04 2014 (r269096) @@ -220,7 +220,7 @@ STAGE_SYMLINKS_DIR= ${STAGE_OBJTOP} .ifdef WITH_SYSROOT SYSROOT?= ${STAGE_OBJTOP}/ .endif -LDFLAGS_LAST+= -Wl,-rpath-link,${STAGE_LIBDIR} +LDFLAGS_LAST+= -Wl,-rpath-link -Wl,${STAGE_LIBDIR} STAGED_INCLUDE_DIR= ${STAGE_OBJTOP}/usr/include .endif .endif # EARLY_BUILD for host @@ -309,4 +309,16 @@ HOST_CC?= ${TOOLSDIR}/usr/bin/cc .endif .endif +.if ${MACHINE:Nhost:Ncommon} != "" && ${MACHINE} != ${HOST_MACHINE} +# cross-building +.if !defined(FREEBSD_REVISION) +FREEBSD_REVISION!= sed -n '/^REVISION=/{s,.*=,,;s,",,g;p; }' ${SRCTOP}/sys/conf/newvers.sh +.export FREEBSD_REVISION +.endif +CROSS_TARGET_FLAGS= -target ${MACHINE_ARCH}-unknown-freebsd${FREEBSD_REVISION} +CFLAGS+= ${CROSS_TARGET_FLAGS} +ACFLAGS+= ${CROSS_TARGET_FLAGS} +LDFLAGS+= -Wl,-m -Wl,elf_${MACHINE_ARCH}_fbsd +.endif + .endif # bmake From owner-svn-src-projects@FreeBSD.ORG Sat Jul 26 13:37:26 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 CFD234D5; Sat, 26 Jul 2014 13:37:26 +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 BC6012CC6; Sat, 26 Jul 2014 13:37:26 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s6QDbQHW024754; Sat, 26 Jul 2014 13:37:26 GMT (envelope-from melifaro@svn.freebsd.org) Received: (from melifaro@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s6QDbPsP024747; Sat, 26 Jul 2014 13:37:25 GMT (envelope-from melifaro@svn.freebsd.org) Message-Id: <201407261337.s6QDbPsP024747@svn.freebsd.org> From: "Alexander V. Chernikov" Date: Sat, 26 Jul 2014 13:37:25 +0000 (UTC) To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r269121 - in projects/ipfw: sbin/ipfw sys/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: Sat, 26 Jul 2014 13:37:26 -0000 Author: melifaro Date: Sat Jul 26 13:37:25 2014 New Revision: 269121 URL: http://svnweb.freebsd.org/changeset/base/269121 Log: * 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 Modified: projects/ipfw/sbin/ipfw/tables.c 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/sbin/ipfw/tables.c ============================================================================== --- projects/ipfw/sbin/ipfw/tables.c Sat Jul 26 13:14:28 2014 (r269120) +++ projects/ipfw/sbin/ipfw/tables.c Sat Jul 26 13:37:25 2014 (r269121) @@ -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 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, 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, ipf { uint8_t type, vtype; int error; + char *del; type = 0; vtype = 0; @@ -678,6 +697,8 @@ tentry_fill_key(ipfw_obj_header *oh, ipf * 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, ipf } 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); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sat Jul 26 13:14:28 2014 (r269120) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_sockopt.c Sat Jul 26 13:37:25 2014 (r269121) @@ -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); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Sat Jul 26 13:14:28 2014 (r269120) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.c Sat Jul 26 13:37:25 2014 (r269121) @@ -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, vo 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, /* 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); - - tc_new = alloc_table_config(ni, ti, ta, NULL); - if (tc_new == NULL) - return (ENOMEM); + /* 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) { + + /* + * 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, 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, 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 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, 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, 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, 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 * 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 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 /* * 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 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 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 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, 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_insta 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_cha 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; Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Sat Jul 26 13:14:28 2014 (r269120) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table.h Sat Jul 26 13:37:25 2014 (r269121) @@ -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_c 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); Modified: projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c ============================================================================== --- projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Sat Jul 26 13:14:28 2014 (r269120) +++ projects/ipfw/sys/netpfil/ipfw/ip_fw_table_algo.c Sat Jul 26 13:37:25 2014 (r269121) @@ -380,7 +380,7 @@ ta_prepare_add_cidr(struct tentry_info * 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 * 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 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 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;