svn commit: r269121 - in projects/ipfw: sbin/ipfw sys/netpfil/ipfw

Alexander V. Chernikov melifaro at FreeBSD.org
Sat Jul 26 13:37:26 UTC 2014


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;


More information about the svn-src-projects mailing list