Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 31 Dec 2009 18:28:40 +0000 (UTC)
From:      Luigi Rizzo <luigi@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-user@freebsd.org
Subject:   svn commit: r201346 - in user/luigi/ipfw3-head/sys: net netgraph netinet netinet/ipfw
Message-ID:  <200912311828.nBVISeOm073676@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: luigi
Date: Thu Dec 31 18:28:40 2009
New Revision: 201346
URL: http://svn.freebsd.org/changeset/base/201346

Log:
  snapshot (probably not compiling)

Modified:
  user/luigi/ipfw3-head/sys/net/if_bridge.c
  user/luigi/ipfw3-head/sys/net/if_ethersubr.c
  user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c
  user/luigi/ipfw3-head/sys/netinet/ip_divert.c
  user/luigi/ipfw3-head/sys/netinet/ip_divert.h
  user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c
  user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h

Modified: user/luigi/ipfw3-head/sys/net/if_bridge.c
==============================================================================
--- user/luigi/ipfw3-head/sys/net/if_bridge.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/net/if_bridge.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -3040,25 +3040,26 @@ bridge_pfil(struct mbuf **mp, struct ifn
 	}
 
 	/* XXX this section is also in if_ethersubr.c */
-	if (V_ip_fw_chk_ptr && pfil_ipfw != 0 && dir == PFIL_OUT && ifp != NULL) {
+	// XXX PFIL_OUT or DIR_OUT ?
+	if (V_ip_fw_chk_ptr && pfil_ipfw != 0 &&
+			dir == PFIL_OUT && ifp != NULL) {
 		struct m_tag *mtag;
 
 		error = -1;
-		mtag = m_tag_find(*mp, PACKET_TAG_DUMMYNET, NULL);
+		/* fetch the start point from existing tags, if any */
+		mtag = m_tag_locate(*mp, MTAG_IPFW_RULE, 0, NULL);
 		if (mtag == NULL) {
-			args.slot = 0;
+			args.rule.slot = 0;
 		} else {
 			struct dn_pkt_tag *dn_tag;
 
+			/* XXX can we free the tag after use ? */
 			mtag->m_tag_id = PACKET_TAG_NONE;
 			dn_tag = (struct dn_pkt_tag *)(mtag + 1);
-			if (dn_tag->slot != 0 && V_fw_one_pass)
-				/* packet already partially processed */
+			/* packet already partially processed ? */
+			if (dn_tag->rule.slot != 0 && V_fw_one_pass)
 				goto ipfwpass;
-			args.slot = dn_tag->slot; /* next rule to use */
-			args.chain_id = dn_tag->chain_id;
-			args.rulenum = dn_tag->rulenum;
-			args.rule_id = dn_tag->rule_id;
+			args.rule = dn_tag->rule;
 		}
 
 		args.m = *mp;

Modified: user/luigi/ipfw3-head/sys/net/if_ethersubr.c
==============================================================================
--- user/luigi/ipfw3-head/sys/net/if_ethersubr.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/net/if_ethersubr.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -469,21 +469,20 @@ ether_ipfw_chk(struct mbuf **m0, struct 
 	struct ip_fw_args args;
 	struct m_tag *mtag;
 
-	mtag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
+	/* fetch start point from rule, if any */
+	mtag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
 	if (mtag == NULL) {
-		args.slot = 0;
+		args.rule.slot = 0;
 	} else {
 		struct dn_pkt_tag *dn_tag;
 
+		/* XXX can we free it after use ? */
 		mtag->m_tag_id = PACKET_TAG_NONE;
 		dn_tag = (struct dn_pkt_tag *)(mtag + 1);
-		if (dn_tag->slot != 0 && V_fw_one_pass)
+		if (dn_tag->rule.slot != 0 && V_fw_one_pass)
 			/* dummynet packet, already partially processed */
 			return (1);
-		args.slot = dn_tag->slot;	/* matching rule to restart */
-		args.rulenum = dn_tag->rulenum;
-		args.rule_id = dn_tag->rule_id;
-		args.chain_id = dn_tag->chain_id;
+		args.rule = dn_tag->rule;
 	}
 
 	/*

Modified: user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netgraph/ng_ipfw.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -221,19 +221,20 @@ ng_ipfw_findhook1(node_p node, u_int16_t
 static int
 ng_ipfw_rcvdata(hook_p hook, item_p item)
 {
-	struct ng_ipfw_tag	*ngit;
+	struct ipfw_start_info	*ngit;
 	struct mbuf *m;
 
 	NGI_GET_M(item, m);
 	NG_FREE_ITEM(item);
 
-	if ((ngit = (struct ng_ipfw_tag *)m_tag_locate(m, NGM_IPFW_COOKIE, 0,
-	    NULL)) == NULL) {
+	ngit = (struct ipfw_start_info *)
+		m_tag_locate(m, NGM_IPFW_COOKIE, 0, NULL);
+	if (ngit == NULL) {
 		NG_FREE_M(m);
 		return (EINVAL);	/* XXX: find smth better */
 	};
 
-	switch (ngit->dir) {
+	switch (ngit->info) {
 	case DIR_OUT:
 	    {
 		struct ip *ip;
@@ -263,7 +264,7 @@ static int
 ng_ipfw_input(struct mbuf **m0, int dir, struct ip_fw_args *fwa, int tee)
 {
 	struct mbuf *m;
-	struct ng_ipfw_tag *ngit;
+	struct ipfw_start_info *ngit;
 	struct ip *ip;
 	hook_p	hook;
 	int error = 0;
@@ -284,21 +285,21 @@ ng_ipfw_input(struct mbuf **m0, int dir,
 	 * a copy of a packet and forward it into netgraph without a tag.
 	 */
 	if (tee == 0) {
+		struct m_tag *tag;
+		struct ipfw_start_info *ngit;
 		m = *m0;
 		*m0 = NULL;	/* it belongs now to netgraph */
 
-		if ((ngit = (struct ng_ipfw_tag *)m_tag_alloc(NGM_IPFW_COOKIE,
-		    0, TAGSIZ, M_NOWAIT|M_ZERO)) == NULL) {
+		tag = m_tag_alloc(NGM_IPFW_COOKIE, sizeof(*mt),
+			M_NOWAIT|M_ZERO);
+		if (tagn == NULL) {
 			m_freem(m);
 			return (ENOMEM);
 		}
-		ngit->slot = fwa->slot;
-		ngit->rulenum = fwa->rulenum;
-		ngit->rule_id = fwa->rule_id;
-		ngit->chain_id = fwa->chain_id;
-		ngit->dir = dir;
-//		ngit->ifp = fwa->oif; /* XXX do we use it ? */
-		m_tag_prepend(m, &ngit->mt);
+		ngit = (struct ipfw_start_info *)(tag + 1);
+		*ngit = fwa->start
+		ngit->info = dir;
+		m_tag_prepend(m, tag);
 
 	} else
 		if ((m = m_dup(*m0, M_DONTWAIT)) == NULL)

Modified: user/luigi/ipfw3-head/sys/netinet/ip_divert.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_divert.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ip_divert.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -72,10 +72,10 @@ __FBSDID("$FreeBSD$");
 #include <netinet/in_systm.h>
 #include <netinet/in_var.h>
 #include <netinet/ip.h>
-#include <netinet/ip_divert.h>
 #include <netinet/ip_var.h>
 #include <netinet/ip_fw.h>
 #include <netinet/ipfw/ip_fw_private.h>
+#include <netinet/ip_divert.h>
 #ifdef SCTP
 #include <netinet/sctp_crc32.h>
 #endif
@@ -301,6 +301,9 @@ divert_packet(struct mbuf *m, int incomi
 	/* Put packet on socket queue, if any */
 	sa = NULL;
 	nport = htons((u_int16_t)divert_info(mtag));
+	printf("divert rule %d %s to port %d\n", divsrc.sin_port,
+		incoming ? "in" : "out",
+		ntohs(nport));
 	INP_INFO_RLOCK(&V_divcbinfo);
 	LIST_FOREACH(inp, &V_divcb, inp_list) {
 		/* XXX why does only one socket match? */
@@ -339,7 +342,7 @@ div_output(struct socket *so, struct mbu
     struct mbuf *control)
 {
 	struct m_tag *mtag;
-	struct divert_tag *dt;
+	struct ipfw_rule_ref *dt;
 	int error = 0;
 	struct mbuf *options;
 
@@ -354,23 +357,35 @@ div_output(struct socket *so, struct mbu
 	if (control)
 		m_freem(control);		/* XXX */
 
-	if ((mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL)) == NULL) {
-		mtag = m_tag_get(PACKET_TAG_DIVERT, sizeof(struct divert_tag),
-		    M_NOWAIT | M_ZERO);
+	mtag = m_tag_locate(m, MTAG_IPFW_RULE, 0, NULL);
+	if (mtag == NULL) {
+		/* this should be normal */
+		printf("create divert tag\n");
+		mtag = m_tag_alloc(MTAG_IPFW_RULE, 0,
+		    sizeof(struct ipfw_rule_ref), M_NOWAIT | M_ZERO);
 		if (mtag == NULL) {
 			error = ENOBUFS;
 			goto cantsend;
 		}
-		dt = (struct divert_tag *)(mtag+1);
 		m_tag_prepend(m, mtag);
-	} else
-		dt = (struct divert_tag *)(mtag+1);
+	}
+	dt = (struct ipfw_rule_ref *)(mtag+1);
 
+	printf("%s sin %p dst rule %d addr 0x%x\n", __FUNCTION__,
+		sin, sin? sin->sin_port : -1,
+		sin ? sin->sin_addr.s_addr : 0xdeaddead);
 	/* Loopback avoidance and state recovery */
 	if (sin) {
 		int i;
 
-		dt->cookie = sin->sin_port;
+		/* set the starting point. We provide a non-zero slot,
+		 * but a non_matching chain_id to skip that info and use
+		 * the rulenum/rule_id.
+		 */
+		dt->slot = 1; /* dummy, chain_id is invalid */
+		dt->chain_id = 0;
+		dt->rulenum = sin->sin_port+1; /* host format ? */
+		dt->rule_id = 0;
 		/*
 		 * Find receive interface with the given name, stuffed
 		 * (if it exists) in the sin_zero[] field.
@@ -455,6 +470,7 @@ div_output(struct socket *so, struct mbu
 		}
 	} else {
 		dt->info |= IP_FW_DIVERT_LOOPBACK_FLAG;
+		printf("divert to loopback\n");
 		if (m->m_pkthdr.rcvif == NULL) {
 			/*
 			 * No luck with the name, check by IP address.
@@ -467,6 +483,7 @@ div_output(struct socket *so, struct mbu
 			sin->sin_port = 0;
 			ifa = ifa_ifwithaddr((struct sockaddr *) sin);
 			if (ifa == NULL) {
+				printf("%s ifa not found ???\n", __FUNCTION__);
 				error = EADDRNOTAVAIL;
 				goto cantsend;
 			}

Modified: user/luigi/ipfw3-head/sys/netinet/ip_divert.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_divert.h	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ip_divert.h	Thu Dec 31 18:28:40 2009	(r201346)
@@ -45,10 +45,6 @@ SYSCTL_DECL(_net_inet_divert);
 /*
  * Divert socket definitions.
  */
-struct divert_tag {
-	u_int32_t	info;		/* port & flags */
-	u_int16_t	cookie;		/* ipfw rule number */
-};
 
 /*
  * Return the divert cookie associated with the mbuf; if any.
@@ -56,13 +52,7 @@ struct divert_tag {
 static __inline u_int16_t
 divert_cookie(struct m_tag *mtag)
 {
-	return ((struct divert_tag *)(mtag+1))->cookie;
-}
-static __inline u_int16_t
-divert_find_cookie(struct mbuf *m)
-{
-	struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
-	return mtag ? divert_cookie(mtag) : 0;
+	return ((struct ipfw_rule_ref *)(mtag+1))->rulenum;
 }
 
 /*
@@ -71,13 +61,7 @@ divert_find_cookie(struct mbuf *m)
 static __inline u_int32_t
 divert_info(struct m_tag *mtag)
 {
-	return ((struct divert_tag *)(mtag+1))->info;
-}
-static __inline u_int32_t
-divert_find_info(struct mbuf *m)
-{
-	struct m_tag *mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
-	return mtag ? divert_info(mtag) : 0;
+	return ((struct ipfw_rule_ref *)(mtag+1))->info;
 }
 
 typedef	void ip_divert_packet_t(struct mbuf *m, int incoming);

Modified: user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ip_dummynet.h	Thu Dec 31 18:28:40 2009	(r201346)
@@ -114,11 +114,7 @@ struct dn_heap {
  * other forms of packet reinjection.
  */
 struct dn_pkt_tag {
-    /* first part, reinject info */
-    uint32_t slot;		/* slot of next rule to use */
-    uint32_t rulenum;		/* matching rule number */
-    uint32_t rule_id;		/* matching rule id */
-    uint32_t chain_id;		/* ruleset id */
+	struct ipfw_rule_ref rule;	/* matching rule */
 
     /* second part, dummynet specific */
     int dn_dir;			/* action when packet comes out. */

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_dummynet.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -468,7 +468,7 @@ heap_free(struct dn_heap *h)
  */
 static __inline void *dn_free_pkt(struct mbuf *m)
 {
-	m_freem(m);
+	FREE_PKT(m);
 	return NULL;
 }
 
@@ -975,8 +975,10 @@ dummynet_send(struct mbuf *m)
 			dst = DIR_DROP;
 		} else {
 			struct dn_pkt_tag *pkt = dn_tag_get(m);
+			/* extract the dummynet info, rename the tag */
 			dst = pkt->dn_dir;
 			ifp = pkt->ifp;
+			// XXX rename the tag
 		}
 
 		switch (dst) {
@@ -1364,7 +1366,7 @@ dummynet_io(struct mbuf **m0, int dir, s
 	struct dn_pipe *pipe;
 	uint64_t len = m->m_pkthdr.len;
 	struct dn_flow_queue *q = NULL;
-	int is_pipe = fwa->cookie & 0x8000000 ? 0 : 1;
+	int is_pipe = fwa->rule.info & 0x8000000 ? 0 : 1;
 
 	KASSERT(m->m_nextpkt == NULL,
 	    ("dummynet_io: mbuf queue passed to dummynet"));
@@ -1378,11 +1380,11 @@ dummynet_io(struct mbuf **m0, int dir, s
 	 * below can be simplified.
 	 */
 	if (is_pipe) {
-		pipe = locate_pipe(fwa->cookie & 0xffff);
+		pipe = locate_pipe(fwa->rule.info & 0xffff);
 		if (pipe != NULL)
 			fs = &(pipe->fs);
 	} else
-		fs = locate_flowset(fwa->cookie & 0xffff);
+		fs = locate_flowset(fwa->rule.info & 0xffff);
 
 	if (fs == NULL)
 		goto dropit;	/* This queue/pipe does not exist! */
@@ -1428,12 +1430,8 @@ dummynet_io(struct mbuf **m0, int dir, s
 	 * Ok, i can handle the pkt now...
 	 * Build and enqueue packet + parameters.
 	 */
-	pkt->slot = fwa->slot;
-	pkt->rulenum = fwa->rulenum;
-	pkt->rule_id = fwa->rule_id;
-	pkt->chain_id = fwa->chain_id;
+	pkt->rule = fwa->rule;
 	pkt->dn_dir = dir;
-
 	pkt->ifp = fwa->oif;
 
 	if (q->head == NULL)

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw2.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -560,7 +560,7 @@ send_reject6(struct ip_fw_args *args, in
 				ip6_output(m0, NULL, NULL, 0, NULL, NULL,
 				    NULL);
 		}
-		m_freem(m);
+		FREE_PKT(m);
 	} else if (code != ICMP6_UNREACH_RST) { /* Send an ICMPv6 unreach. */
 #if 0
 		/*
@@ -576,7 +576,7 @@ send_reject6(struct ip_fw_args *args, in
 #endif
 		icmp6_error(m, ICMP6_DST_UNREACH, code, 0);
 	} else
-		m_freem(m);
+		FREE_PKT(m);
 
 	args->m = NULL;
 }
@@ -616,9 +616,9 @@ send_reject(struct ip_fw_args *args, int
 			if (m != NULL)
 				ip_output(m, NULL, NULL, 0, NULL, NULL);
 		}
-		m_freem(args->m);
+		FREE_PKT(args->m);
 	} else
-		m_freem(args->m);
+		FREE_PKT(args->m);
 	args->m = NULL;
 }
 
@@ -707,16 +707,18 @@ check_uidgid(ipfw_insn_u32 *insn, int pr
 }
 
 /*
- * Helper function to write the matching rule into args
+ * Helper function to set args with info on the rule after the matching
+ * one. slot is precise, whereas we guess rule_id as they are
+ * assigned sequentially.
  */
 static inline void
 set_match(struct ip_fw_args *args, int slot,
 	struct ip_fw_chain *chain)
 {
-	args->chain_id = chain->id;
-	args->slot = slot + 1; /* we use 0 as a marker */
-	args->rule_id = chain->map[slot]->id;
-	args->rulenum = chain->map[slot]->rulenum;
+	args->rule.chain_id = chain->id;
+	args->rule.slot = slot + 1; /* we use 0 as a marker */
+	args->rule.rule_id = 1 + chain->map[slot]->id;
+	args->rule.rulenum = chain->map[slot]->rulenum;
 }
 
 /*
@@ -741,7 +743,7 @@ set_match(struct ip_fw_args *args, int s
  *	args->rule	Pointer to the last matching rule (in/out)
  *	args->next_hop	Socket we are forwarding to (out).
  *	args->f_id	Addresses grabbed from the packet (out)
- * 	args->cookie	a cookie depending on rule action
+ * 	args->rule.info	a cookie depending on rule action
  *
  * Return value:
  *
@@ -751,6 +753,8 @@ set_match(struct ip_fw_args *args, int s
  *	IP_FW_TEE	tee packet, port in m_tag
  *	IP_FW_DUMMYNET	to dummynet, pipe in args->cookie
  *	IP_FW_NETGRAPH	into netgraph, cookie args->cookie
+ *		args->rule contains the matching rule,
+ *		args->rule.info has additional information.
  *
  */
 int
@@ -1133,45 +1137,25 @@ do {								\
 		IPFW_RUNLOCK(chain);
 		return (IP_FW_PASS);	/* accept */
 	}
-	/* XXX divert should be handled same as other tags */
-	mtag = m_tag_find(m, PACKET_TAG_DIVERT, NULL);
-	if (args->slot) {
+	if (args->rule.slot) {
 		/*
 		 * Packet has already been tagged as a result of a previous
 		 * match on rule args->rule aka args->rule_id (PIPE, QUEUE,
-		 * REASS, NETGRAPH and similar, never a skipto).
+		 * REASS, NETGRAPH, DIVERT/TEE...)
 		 * Validate the slot and continue from the next one
 		 * if still present, otherwise do a lookup.
 		 */
-		if (V_fw_one_pass) {
-			IPFW_RUNLOCK(chain);
-			return (IP_FW_PASS);
-		}
-		f_pos = (args->chain_id == chain->id) ?
-		    args->slot /* already incremented */ :
-		    ipfw_find_rule(chain, args->rulenum, args->rule_id+1);
+		f_pos = (args->rule.chain_id == chain->id) ?
+		    args->rule.slot :
+		    ipfw_find_rule(chain, args->rule.rulenum,
+			args->rule.rule_id);
 	} else {
-		/*
-		 * Find the starting rule. It can be either the first
-		 * one, or the one after divert_rule if asked so.
-		 */
-		int skipto = mtag ? divert_cookie(mtag) : 0;
-
 		f_pos = 0;
-		if (args->eh == NULL && skipto != 0) {
-			if (skipto >= IPFW_DEFAULT_RULE) {
-				IPFW_RUNLOCK(chain);
-				return (IP_FW_DENY); /* invalid */
-			}
-			f_pos = ipfw_find_rule(chain, skipto+1, 0);
-		}
 	}
-	/* reset divert rule to avoid confusion later */
-	if (mtag) {
+#if 0 // XXX to be fixed
 		divinput_flags = divert_info(mtag) &
 		    (IP_FW_DIVERT_OUTPUT_FLAG | IP_FW_DIVERT_LOOPBACK_FLAG);
-		m_tag_delete(m, mtag);
-	}
+#endif
 
 	/*
 	 * Now scan the rules, and parse microinstructions for each rule.
@@ -1761,12 +1745,13 @@ do {								\
 				if (cmd->len & F_NOT) { /* `untag' action */
 					if (mtag != NULL)
 						m_tag_delete(m, mtag);
+					match = 0;
 				} else if (mtag == NULL) {
 					if ((mtag = m_tag_alloc(MTAG_IPFW,
 					    tag, 0, M_NOWAIT)) != NULL)
 						m_tag_prepend(m, mtag);
+					match = 1;
 				}
-				match = (cmd->len & F_NOT) ? 0: 1;
 				break;
 			}
 
@@ -1916,10 +1901,10 @@ do {								\
 			case O_PIPE:
 			case O_QUEUE:
 				set_match(args, f_pos, chain);
-				args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ?
+				args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
 					tablearg : cmd->arg1;
 				if (cmd->opcode == O_QUEUE)
-					args->cookie |= 0x80000000;
+					args->rule.info |= 0x80000000;
 				retval = IP_FW_DUMMYNET;
 				l = 0;          /* exit inner loop */
 				done = 1;       /* exit outer loop */
@@ -1932,23 +1917,9 @@ do {								\
 				/* otherwise this is terminal */
 				l = 0;		/* exit inner loop */
 				done = 1;	/* exit outer loop */
-				mtag = m_tag_get(PACKET_TAG_DIVERT,
-					sizeof(struct divert_tag),
-					M_NOWAIT);
-				if (mtag == NULL) {
-				    retval = IP_FW_DENY;
-				} else {
-				    struct divert_tag *dt;
-				    dt = (struct divert_tag *)(mtag+1);
-				    dt->cookie = f->rulenum;
-				    if (cmd->arg1 == IP_FW_TABLEARG)
-					dt->info = tablearg;
-				    else
-					dt->info = cmd->arg1;
-				    m_tag_prepend(m, mtag);
-				    retval = (cmd->opcode == O_DIVERT) ?
-					IP_FW_DIVERT : IP_FW_TEE;
-				}
+				set_match(args, f_pos, chain);
+				args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
+				    tablearg : cmd->arg1;
 				break;
 
 			case O_COUNT:
@@ -2064,7 +2035,7 @@ do {								\
 			case O_NETGRAPH:
 			case O_NGTEE:
 				set_match(args, f_pos, chain);
-				args->cookie = (cmd->arg1 == IP_FW_TABLEARG) ?
+				args->rule.info = (cmd->arg1 == IP_FW_TABLEARG) ?
 					tablearg : cmd->arg1;
 				retval = (cmd->opcode == O_NETGRAPH) ?
 				    IP_FW_NETGRAPH : IP_FW_NGTEE;

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_dynamic.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -917,7 +917,7 @@ ipfw_send_pkt(struct mbuf *replyto, stru
 #endif
 	default:
 		/* XXX: log me?!? */
-		m_freem(m);
+		FREE_PKT(m);
 		return (NULL);
 	}
 	dir = ((flags & (TH_SYN | TH_RST)) == TH_SYN);

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_pfil.c	Thu Dec 31 18:28:40 2009	(r201346)
@@ -106,8 +106,7 @@ ipfw_check_hook(void *arg, struct mbuf *
     struct inpcb *inp)
 {
 	struct ip_fw_args args;
-	struct ng_ipfw_tag *ng_tag;
-	struct m_tag *dn_tag;
+	struct m_tag *tag;
 	int ipfw;
 	int ret;
 #ifdef IPFIREWALL_FORWARD
@@ -118,29 +117,11 @@ ipfw_check_hook(void *arg, struct mbuf *
 	dir = (dir == PFIL_IN) ? DIR_IN : DIR_OUT;
 	bzero(&args, sizeof(args));
 
-	ng_tag = (struct ng_ipfw_tag *)m_tag_locate(*m0, NGM_IPFW_COOKIE, 0,
-	    NULL);
-	if (ng_tag != NULL) {
-		KASSERT(ng_tag->dir == dir,
-		    ("ng_ipfw tag with wrong direction"));
-		args.slot = ng_tag->slot;
-		args.rulenum = ng_tag->rulenum;
-		args.rule_id = ng_tag->rule_id;
-		args.chain_id = ng_tag->chain_id;
-		m_tag_delete(*m0, (struct m_tag *)ng_tag);
-	}
-
 again:
-	dn_tag = m_tag_find(*m0, PACKET_TAG_DUMMYNET, NULL);
-	if (dn_tag != NULL) {
-		struct dn_pkt_tag *dt;
-
-		dt = (struct dn_pkt_tag *)(dn_tag+1);
-		args.slot = dt->slot;
-		args.rulenum = dt->rulenum;
-		args.rule_id = dt->rule_id;
-		args.chain_id = dt->chain_id;
-		m_tag_delete(*m0, dn_tag);
+	tag = m_tag_locate(*m0, MTAG_IPFW_RULE, 0, NULL);
+	if (tag != NULL) {
+		args.rule = *((struct ipfw_rule_ref *)(tag+1));
+		m_tag_delete(*m0, tag);
 	}
 
 	args.m = *m0;
@@ -150,7 +131,7 @@ again:
 	/* all the processing now uses ip_len in net format */
 	SET_NET_IPLEN(mtod(*m0, struct ip *));
 
-	if (V_fw_one_pass == 0 || args.slot == 0) {
+	if (V_fw_one_pass == 0 || args.rule.slot == 0) {
 		ipfw = ipfw_chk(&args);
 		*m0 = args.m;
 	} else
@@ -224,15 +205,19 @@ again:
 			ret = EACCES;
 			break; /* i.e. drop */
 		}
-		ipfw_divert(m0, dir, (ipfw == IP_FW_TEE) ? 1 : 0);
-		if (*m0) {
-			/* continue processing for this one. We set
-			 * args.slot=0, but the divert tag is processed
-			 * in ipfw_chk to jump to the right place.
-			 */
-			args.slot = 0;
-			goto again;	/* continue with packet */
+		tag = m_tag_alloc(MTAG_IPFW_RULE, 0,
+		    sizeof(struct ipfw_rule_ref), M_NOWAIT);
+		if (tag == NULL) {
+			ret = EACCES;
+			break; /* i.e. drop */
 		}
+		*((struct ipfw_rule_ref *)(tag+1)) = args.rule;
+		m_tag_prepend(*m0, tag);
+
+		ipfw_divert(m0, dir, (ipfw == IP_FW_TEE) ? 1 : 0);
+		/* continue processing for the original packet (tee) */
+		if (*m0)
+			goto again;
 		break;
 
 	case IP_FW_NGTEE:
@@ -257,7 +242,7 @@ again:
 
 	if (ret != 0) {
 		if (*m0)
-			m_freem(*m0);
+			FREE_PKT(*m0);
 		*m0 = NULL;
 	}
 	if (*m0)

Modified: user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h
==============================================================================
--- user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h	Thu Dec 31 18:02:48 2009	(r201345)
+++ user/luigi/ipfw3-head/sys/netinet/ipfw/ip_fw_private.h	Thu Dec 31 18:28:40 2009	(r201346)
@@ -36,6 +36,7 @@
 #ifdef _KERNEL
 
 #define MTAG_IPFW	1148380143	/* IPFW-tagged cookie */
+#define MTAG_IPFW_RULE	1262273568	/* rule reference */
 
 /* Return values from ipfw_chk() */
 enum {
@@ -70,6 +71,20 @@ struct _ip6dn_args {
 };
 
 /*
+ * Reference to an ipfw rule that can be carried outside critical sections.
+ * A rule is identified by rulenum:rule_id which is ordered.
+ * In version chain_id the rule can be found in slot 'slot', so
+ * we don't need a lookup if chain_id == chain->id.
+ */
+struct ipfw_rule_ref {
+	uint32_t	slot;		/* slot for matching rule	*/
+	uint32_t	rulenum;	/* matching rule number		*/
+	uint32_t	rule_id;	/* matching rule id		*/
+	uint32_t	chain_id;	/* ruleset id			*/
+	uint32_t	info;		/* reason for reinject		*/
+};
+
+/*
  * Arguments for calling ipfw_chk() and dummynet_io(). We put them
  * all into a structure because this way it is easier and more
  * efficient to pass variables around and extend the interface.
@@ -79,19 +94,19 @@ struct ip_fw_args {
 	struct ifnet	*oif;		/* output interface		*/
 	struct sockaddr_in *next_hop;	/* forward address		*/
 
-	/* chain_id validates 'slot', the location of the pointer to
-	 * a matching rule.
-	 * If invalid, we can lookup the rule using rule_id and rulenum
+	/*
+	 * On return, it points to the matching rule.
+	 * On entry, rule.slot > 0 means the info is valid and
+	 * contains the the starting rule for an ipfw search.
+	 * If chain_id == chain->id && slot >0 then jump to that slot.
+	 * Otherwise, we locate the first rule >= rulenum:rule_id
 	 */
-	uint32_t	slot;		/* slot for matching rule	*/
-	uint32_t	rulenum;	/* matching rule number		*/
-	uint32_t	rule_id;	/* matching rule id		*/
-	uint32_t	chain_id;	/* ruleset id			*/
+	struct ipfw_rule_ref rule;	/* match/restart info		*/
 
 	struct ether_header *eh;	/* for bridged packets		*/
 
 	struct ipfw_flow_id f_id;	/* grabbed from IP header	*/
-	uint32_t	cookie;		/* a cookie depending on rule action */
+	//uint32_t	cookie;		/* a cookie depending on rule action */
 	struct inpcb	*inp;
 
 	struct _ip6dn_args	dummypar; /* dummynet->ip6_output */
@@ -122,6 +137,9 @@ enum {
    /*	PROTO_OLDBDG =	0x14, unused, old bridge */
 };
 
+/* wrapper for freeing a packet, in case we need to do more work */
+#define FREE_PKT(m)	m_freem(m)
+
 /*
  * Function definitions.
  */
@@ -277,18 +295,6 @@ typedef int ng_ipfw_input_t(struct mbuf 
 extern  ng_ipfw_input_t *ng_ipfw_input_p;
 #define NG_IPFW_LOADED  (ng_ipfw_input_p != NULL)
 
-struct ng_ipfw_tag {
-        struct m_tag    mt;             /* tag header */
-	/* reinject info */
-        uint32_t        slot;           /* slot for next rule */
-        uint32_t        rulenum;        /* matching rule number */
-        uint32_t        rule_id;        /* matching rule id */
-        uint32_t        chain_id;       /* ruleset id */
-        int             dir;
-
-//        struct ifnet    *ifp;           /* interface, for ip_output */
-};
-
 #define TAGSIZ  (sizeof(struct ng_ipfw_tag) - sizeof(struct m_tag))
 
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200912311828.nBVISeOm073676>