From ianf@brane-dead.freislich.nom.za  Sat Mar 13 23:26:28 2004
Return-Path: <ianf@brane-dead.freislich.nom.za>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 97C9A16A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 13 Mar 2004 23:26:28 -0800 (PST)
Received: from brane-dead.freislich.nom.za (www.freislich.nom.za [196.7.162.29])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 5F56C43D1F
	for <FreeBSD-gnats-submit@freebsd.org>; Sat, 13 Mar 2004 23:26:21 -0800 (PST)
	(envelope-from ianf@brane-dead.freislich.nom.za)
Received: from ianf by brane-dead.freislich.nom.za with local (Exim 4.30; FreeBSD)
	id 1B2Q0m-000190-77
	for FreeBSD-gnats-submit@freebsd.org; Sun, 14 Mar 2004 09:26:16 +0200
Message-Id: <E1B2Q0m-000190-77@brane-dead.freislich.nom.za>
Date: Sun, 14 Mar 2004 09:26:16 +0200
From: Ian Freislich <ianf@freislich.nom.za>
Sender: Ian Freislich <ianf@brane-dead.freislich.nom.za>
Reply-To: Ian Freislich <ianf@freislich.nom.za>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: IPFW tee terminates rule processing
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         64240
>Category:       kern
>Synopsis:       IPFW tee terminates rule processing
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    andre
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat Mar 13 23:30:17 PST 2004
>Closed-Date:    Thu Sep 16 20:36:09 GMT 2004
>Last-Modified:  Thu Sep 16 20:36:09 GMT 2004
>Originator:     Ian Freislich
>Release:        FreeBSD 5.2-CURRENT i386
>Organization:
private
>Environment:
System: FreeBSD brane-dead.freislich.nom.za 5.2-CURRENT FreeBSD 5.2-CURRENT #6: Sat Mar 13 23:50:41 SAST 2004     ianf@brane-dead.freislich.nom.za:/usr/src/sys/i386/compile/BRANE-DEAD  i386


>Description:
Noted in the BUGS section of the ipfw manual page:

    Packets that match a tee rule should not be immediately accepted,
    but should continue going through the rule list.  This may be
    fixed in a later version.

The following set of rules will cause IP packets to be accepted
unconditionally:

00001 tee 5000 ip from any to any
00002 deny ip from any to any

>How-To-Repeat:

Add a tee rule early in the ipfw ruleset and all packets matching
that rule will be copied to the divert port and accepted by the
firewall.

>Fix:

Apply the following patch (5-CURRENT > 20040314)

This patch removes a stale comment in ip_fw2.c - args->divert_rule
does not exist in the structure.  It adds tee_continue to the
ip_fw_args structure to defeat the one_pass check when continuing
with the checks after teeing the packet.


Index: sbin/ipfw/ipfw.8
===================================================================
RCS file: /home/ncvs/src/sbin/ipfw/ipfw.8,v
retrieving revision 1.139
diff -u -d -r1.139 ipfw.8
--- sbin/ipfw/ipfw.8	23 Jan 2004 06:37:19 -0000	1.139
+++ sbin/ipfw/ipfw.8	10 Mar 2004 09:03:06 -0000
@@ -658,10 +658,7 @@
 .Xr divert 4
 socket bound to port
 .Ar port .
-The search terminates and the original packet is accepted
-(but see Section
-.Sx BUGS
-below).
+The search continues at the next rule.
 .It Cm unreach Ar code
 Discard packets that match this rule, and try to send an ICMP
 unreachable notice with code
@@ -2169,12 +2166,6 @@
 are reassembled before delivery to the socket.
 The action used on those packet is the one from the
 rule which matches the first fragment of the packet.
-.Pp
-Packets that match a
-.Cm tee
-rule should not be immediately accepted, but should continue
-going through the rule list.
-This may be fixed in a later version.
 .Pp
 Packets diverted to userland, and then reinserted by a userland process
 may lose various packet attributes.
Index: sys/netinet/ip_fw.h
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v
retrieving revision 1.83
diff -u -d -r1.83 ip_fw.h
--- sys/netinet/ip_fw.h	25 Feb 2004 19:55:28 -0000	1.83
+++ sys/netinet/ip_fw.h	13 Mar 2004 21:43:03 -0000
@@ -400,6 +400,7 @@
 	int flags;			/* for dummynet			*/
 
 	struct ipfw_flow_id f_id;	/* grabbed from IP header	*/
+	int		tee_continue;	/* continue after packet tee	*/
 	u_int32_t	retval;
 };
 
Index: sys/netinet/ip_fw2.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
retrieving revision 1.56
diff -u -d -r1.56 ip_fw2.c
--- sys/netinet/ip_fw2.c	25 Feb 2004 19:55:28 -0000	1.56
+++ sys/netinet/ip_fw2.c	13 Mar 2004 21:58:28 -0000
@@ -1361,10 +1361,6 @@
  *	args->eh (in)	Mac header if present, or NULL for layer3 packet.
  *	args->oif	Outgoing interface, or NULL if packet is incoming.
  *		The incoming interface is in the mbuf. (in)
- *	args->divert_rule (in/out)
- *		Skip up to the first rule past this rule number;
- *		upon return, non-zero port number for divert or tee.
- *
  *	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)
@@ -1554,13 +1550,18 @@
 		 * to restart processing.
 		 *
 		 * If fw_one_pass != 0 then just accept it.
-		 * XXX should not happen here, but optimized out in
-		 * the caller.
+		 * XXX should not happen here unless the packet was tee'd,
+		 * but optimized out in the caller.
 		 */
-		if (fw_one_pass) {
+		if (fw_one_pass && !args->tee_continue) {
 			IPFW_UNLOCK(chain);	/* XXX optimize */
 			return 0;
 		}
+		/*
+		 * Reset this so that fw_one_pass is obeyed if we
+		 * land up here again for reasons other than tee_continue
+		 */
+		args->tee_continue = 0;
 
 		f = args->rule->next_rule;
 		if (f == NULL)
@@ -2044,6 +2045,7 @@
 				    cmd->arg1 | IP_FW_PORT_TEE_FLAG;
 				m_tag_prepend(m, mtag);
 				retval = dt->info;
+				args->rule = f; /* report matching rule */
 				goto done;
 			}
 
Index: sys/netinet/ip_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
retrieving revision 1.266
diff -u -d -r1.266 ip_input.c
--- sys/netinet/ip_input.c	1 Mar 2004 22:37:01 -0000	1.266
+++ sys/netinet/ip_input.c	13 Mar 2004 21:58:37 -0000
@@ -473,6 +473,9 @@
 		if (args.next_hop)
 			goto ours;
 
+#ifdef IPDIVERT
+again:
+#endif
 		args.m = m;
 		i = ip_fw_chk_ptr(&args);
 		m = args.m;
@@ -854,12 +857,11 @@
 		divert_packet(m, 1);
 		ipstat.ips_delivered++;
 
-		/* If 'tee', continue with original packet */
+		/* If 'tee', continue processing firewall rules
+		 * with the original packet */
 		if (clone == NULL)
 			return;
 		m = clone;
-		ip = mtod(m, struct ip *);
-		ip->ip_len += hlen;
 		/*
 		 * Jump backwards to complete processing of the
 		 * packet.  We do not need to clear args.next_hop
@@ -867,7 +869,8 @@
 		 * doesn't contain a divert packet tag so we won't
 		 * re-entry this block.
 		 */
-		goto pass;
+		args.tee_continue = 1;
+		goto again;
 	}
 #endif
 
Index: sys/netinet/ip_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
retrieving revision 1.211
diff -u -d -r1.211 ip_output.c
--- sys/netinet/ip_output.c	2 Mar 2004 14:37:23 -0000	1.211
+++ sys/netinet/ip_output.c	13 Mar 2004 21:58:51 -0000
@@ -731,6 +731,9 @@
 	if (fw_enable && IPFW_LOADED && !args.next_hop) {
 		struct sockaddr_in *old = dst;
 
+#ifdef IPDIVERT
+again:
+#endif
 		args.m = m;
 		args.next_hop = dst;
 		args.oif = ifp;
@@ -807,11 +810,14 @@
 			/* Deliver packet to divert input routine */
 			divert_packet(m, 0);
 
-			/* If 'tee', continue with original packet */
+			/*
+			 * If 'tee', continue processing firewall
+			 * rules with the original packet
+			 */
 			if (clone != NULL) {
 				m = clone;
-				ip = mtod(m, struct ip *);
-				goto pass;
+				args.tee_continue = 1;
+				goto again;
 			}
 			goto done;
 		}
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->ipfw 
Responsible-Changed-By: kris 
Responsible-Changed-When: Mon Mar 15 16:35:19 PST 2004 
Responsible-Changed-Why:  
Assign to ipfw mailing list 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64240 

From: Ian FREISLICH <if@hetzner.co.za>
To: freebsd-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: kern/64240: IPFW tee terminates rule processing
Date: Tue, 16 Mar 2004 15:29:55 +0200

 The patch in this PR is not quite right.  The packet is cloned in
 the wrong place for reinsertion into the firewall which results in
 packets being silently dropped.
 
 Here is a corrected patch.
 
 --
 Ian Freislich
 
 
 Index: sbin/ipfw/ipfw.8
 ===================================================================
 RCS file: /home/ncvs/src/sbin/ipfw/ipfw.8,v
 retrieving revision 1.139
 diff -u -d -r1.139 ipfw.8
 --- sbin/ipfw/ipfw.8	23 Jan 2004 06:37:19 -0000	1.139
 +++ sbin/ipfw/ipfw.8	10 Mar 2004 09:03:06 -0000
 @@ -658,10 +658,7 @@
  .Xr divert 4
  socket bound to port
  .Ar port .
 -The search terminates and the original packet is accepted
 -(but see Section
 -.Sx BUGS
 -below).
 +The search continues at the next rule.
  .It Cm unreach Ar code
  Discard packets that match this rule, and try to send an ICMP
  unreachable notice with code
 @@ -2169,12 +2166,6 @@
  are reassembled before delivery to the socket.
  The action used on those packet is the one from the
  rule which matches the first fragment of the packet.
 -.Pp
 -Packets that match a
 -.Cm tee
 -rule should not be immediately accepted, but should continue
 -going through the rule list.
 -This may be fixed in a later version.
  .Pp
  Packets diverted to userland, and then reinserted by a userland process
  may lose various packet attributes.
 Index: sys/netinet/ip_fastfwd.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/ip_fastfwd.c,v
 retrieving revision 1.8
 diff -u -d -r1.8 ip_fastfwd.c
 --- sys/netinet/ip_fastfwd.c	25 Feb 2004 19:55:28 -0000	1.8
 +++ sys/netinet/ip_fastfwd.c	16 Mar 2004 13:23:21 -0000
 @@ -337,11 +337,20 @@
  		bzero(&args, sizeof(args));
  		args.m = m;
  
 +#ifdef IPDIVERT
 +tee_again:
 +#endif
  		ipfw = ip_fw_chk_ptr(&args);
  		m = args.m;
  
  		M_ASSERTVALID(m);
  		M_ASSERTPKTHDR(m);
 +#ifdef IPDIVERT
 +		if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
 +			clone = divert_clone(m);
 +		else
 +			clone = m;
 +#endif
  
  		/*
  		 * Packet denied, drop it
 @@ -368,10 +377,6 @@
  			/*
  			 * Tee packet
  			 */
 -			if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
 -				clone = divert_clone(m);
 -			else
 -				clone = m;
  			if (clone == NULL)
  				goto passin;
  
 @@ -395,11 +400,12 @@
  			/*
  			 * If this was not tee, we are done
  			 */
 -			m = clone;
  			if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0)
  				return 1;
  			/* Continue if it was tee */
 -			goto passin;
 +			args.m = clone;
 +			args.tee_continue = 1;
 +			goto tee_again;
  		}
  #endif
  		if (ipfw == 0 && args.next_hop != NULL) {
 @@ -512,11 +518,20 @@
  		args.m = m;
  		args.oif = ifp;
  
 +#ifdef IPDIVERT
 +tee_again2:
 +#endif
  		ipfw = ip_fw_chk_ptr(&args);
  		m = args.m;
  
  		M_ASSERTVALID(m);
  		M_ASSERTPKTHDR(m);
 +#ifdef IPDIVERT
 +		if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
 +			clone = divert_clone(m);
 +		else
 +			clone = m;
 +#endif
  
  		if ((ipfw & IP_FW_PORT_DENY_FLAG) || m == NULL) {
  			RTFREE(ro.ro_rt);
 @@ -544,10 +559,6 @@
  			/*
  			 * Tee packet
  			 */
 -			if ((ipfw & IP_FW_PORT_TEE_FLAG) != 0)
 -				clone = divert_clone(m);
 -			else
 -				clone = m;
  			if (clone == NULL)
  				goto passout;
  
 @@ -571,13 +582,14 @@
  			/*
  			 * If this was not tee, we are done
  			 */
 -			m = clone;
  			if ((ipfw & IP_FW_PORT_TEE_FLAG) == 0) {
  				RTFREE(ro.ro_rt);
  				return 1;
  			}
  			/* Continue if it was tee */
 -			goto passout;
 +			args.m =clone;
 +			args.tee_continue = 1;
 +			goto tee_again2;
  		}
  #endif
  		if (ipfw == 0 && args.next_hop != NULL) {
 Index: sys/netinet/ip_fw.h
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/ip_fw.h,v
 retrieving revision 1.83
 diff -u -d -r1.83 ip_fw.h
 --- sys/netinet/ip_fw.h	25 Feb 2004 19:55:28 -0000	1.83
 +++ sys/netinet/ip_fw.h	15 Mar 2004 11:33:07 -0000
 @@ -400,6 +400,7 @@
  	int flags;			/* for dummynet			*/
  
  	struct ipfw_flow_id f_id;	/* grabbed from IP header	*/
 +	int		tee_continue;	/* continue after packet tee	*/
  	u_int32_t	retval;
  };
  
 Index: sys/netinet/ip_fw2.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/ip_fw2.c,v
 retrieving revision 1.56
 diff -u -d -r1.56 ip_fw2.c
 --- sys/netinet/ip_fw2.c	25 Feb 2004 19:55:28 -0000	1.56
 +++ sys/netinet/ip_fw2.c	16 Mar 2004 12:47:24 -0000
 @@ -1361,10 +1361,6 @@
   *	args->eh (in)	Mac header if present, or NULL for layer3 packet.
   *	args->oif	Outgoing interface, or NULL if packet is incoming.
   *		The incoming interface is in the mbuf. (in)
 - *	args->divert_rule (in/out)
 - *		Skip up to the first rule past this rule number;
 - *		upon return, non-zero port number for divert or tee.
 - *
   *	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)
 @@ -1554,13 +1550,18 @@
  		 * to restart processing.
  		 *
  		 * If fw_one_pass != 0 then just accept it.
 -		 * XXX should not happen here, but optimized out in
 -		 * the caller.
 +		 * XXX should not happen here unless the packet was tee'd,
 +		 * but optimized out in the caller.
  		 */
 -		if (fw_one_pass) {
 +		if (fw_one_pass && !args->tee_continue) {
  			IPFW_UNLOCK(chain);	/* XXX optimize */
  			return 0;
  		}
 +		/*
 +		 * Reset this so that fw_one_pass is obeyed if we
 +		 * land up here again for reasons other than tee_continue
 +		 */
 +		args->tee_continue = 0;
  
  		f = args->rule->next_rule;
  		if (f == NULL)
 @@ -2044,6 +2045,7 @@
  				    cmd->arg1 | IP_FW_PORT_TEE_FLAG;
  				m_tag_prepend(m, mtag);
  				retval = dt->info;
 +				args->rule = f; /* report matching rule */
  				goto done;
  			}
  
 Index: sys/netinet/ip_input.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/ip_input.c,v
 retrieving revision 1.266
 diff -u -d -r1.266 ip_input.c
 --- sys/netinet/ip_input.c	1 Mar 2004 22:37:01 -0000	1.266
 +++ sys/netinet/ip_input.c	16 Mar 2004 10:48:36 -0000
 @@ -304,6 +304,7 @@
  	struct in_addr pkt_dst;
  #ifdef IPDIVERT
  	u_int32_t divert_info;			/* packet divert/tee info */
 +	struct mbuf *clone = NULL;		/* saved mbuf for tee */
  #endif
  	struct ip_fw_args args;
  	int dchg = 0;				/* dest changed after fw */
 @@ -474,8 +475,17 @@
  			goto ours;
  
  		args.m = m;
 +#ifdef IPDIVERT
 +tee_again:
 +#endif
  		i = ip_fw_chk_ptr(&args);
  		m = args.m;
 +#ifdef IPDIVERT
 +		if ((i & IP_FW_PORT_TEE_FLAG) != 0)
 +			clone = divert_clone(m);
 +		else
 +			clone = NULL;
 +#endif
  
  		if ( (i & IP_FW_PORT_DENY_FLAG) || m == NULL) { /* drop */
  			if (m)
 @@ -837,14 +847,6 @@
  	 */
  	divert_info = divert_find_info(m);
  	if (divert_info != 0) {
 -		struct mbuf *clone;
 -
 -		/* Clone packet if we're doing a 'tee' */
 -		if ((divert_info & IP_FW_PORT_TEE_FLAG) != 0)
 -			clone = divert_clone(m);
 -		else
 -			clone = NULL;
 -
  		/* Restore packet header fields to original values */
  		ip->ip_len += hlen;
  		ip->ip_len = htons(ip->ip_len);
 @@ -854,12 +856,10 @@
  		divert_packet(m, 1);
  		ipstat.ips_delivered++;
  
 -		/* If 'tee', continue with original packet */
 +		/* If 'tee', continue processing firewall rules
 +		 * with the original packet */
  		if (clone == NULL)
  			return;
 -		m = clone;
 -		ip = mtod(m, struct ip *);
 -		ip->ip_len += hlen;
  		/*
  		 * Jump backwards to complete processing of the
  		 * packet.  We do not need to clear args.next_hop
 @@ -867,7 +867,9 @@
  		 * doesn't contain a divert packet tag so we won't
  		 * re-entry this block.
  		 */
 -		goto pass;
 +		args.m = clone;
 +		args.tee_continue = 1;
 +		goto tee_again;
  	}
  #endif
  
 Index: sys/netinet/ip_output.c
 ===================================================================
 RCS file: /home/ncvs/src/sys/netinet/ip_output.c,v
 retrieving revision 1.211
 diff -u -d -r1.211 ip_output.c
 --- sys/netinet/ip_output.c	2 Mar 2004 14:37:23 -0000	1.211
 +++ sys/netinet/ip_output.c	16 Mar 2004 13:25:22 -0000
 @@ -730,14 +730,27 @@
  	 */
  	if (fw_enable && IPFW_LOADED && !args.next_hop) {
  		struct sockaddr_in *old = dst;
 +#ifdef IPDIVERT
 +		struct mbuf *clone = NULL;
 +#endif
  
  		args.m = m;
  		args.next_hop = dst;
  		args.oif = ifp;
 +#ifdef IPDIVERT
 +tee_again:
 +#endif
  		off = ip_fw_chk_ptr(&args);
  		m = args.m;
  		dst = args.next_hop;
  
 +#ifdef IPDIVERT
 +		/* Clone packet if we're doing a 'tee' */
 +		if ((off & IP_FW_PORT_TEE_FLAG) != 0)
 +			clone = divert_clone(m);
 +		else
 +			clone = NULL;
 +#endif
                  /*
  		 * On return we must do the following:
  		 * m == NULL	-> drop the pkt (old interface, deprecated)
 @@ -782,14 +795,6 @@
  		}
  #ifdef IPDIVERT
  		if (off != 0 && (off & IP_FW_PORT_DYNT_FLAG) == 0) {
 -			struct mbuf *clone;
 -
 -			/* Clone packet if we're doing a 'tee' */
 -			if ((off & IP_FW_PORT_TEE_FLAG) != 0)
 -				clone = divert_clone(m);
 -			else
 -				clone = NULL;
 -
  			/*
  			 * XXX
  			 * delayed checksums are not currently compatible
 @@ -807,11 +812,14 @@
  			/* Deliver packet to divert input routine */
  			divert_packet(m, 0);
  
 -			/* If 'tee', continue with original packet */
 +			/*
 +			 * If 'tee', continue processing firewall
 +			 * rules with the original packet
 +			 */
  			if (clone != NULL) {
 -				m = clone;
 -				ip = mtod(m, struct ip *);
 -				goto pass;
 +				args.m = clone;
 +				args.tee_continue = 1;
 +				goto tee_again;
  			}
  			goto done;
  		}
Responsible-Changed-From-To: ipfw->andre 
Responsible-Changed-By: andre 
Responsible-Changed-When: Tue Aug 24 18:30:41 GMT 2004 
Responsible-Changed-Why:  
Take over. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64240 
State-Changed-From-To: open->analyzed 
State-Changed-By: andre 
State-Changed-When: Fri Aug 27 18:52:25 GMT 2004 
State-Changed-Why:  
Ian, 

could you please try the following patch (against -current or 5.3-BETA1), 
(maybe whitespace mangled): 

Index: ip_fw_pfil.c 
=================================================================== 
RCS file: /home/ncvs/src/sys/netinet/ip_fw_pfil.c,v 
retrieving revision 1.7 
diff -u -p -r1.7 ip_fw_pfil.c 
--- ip_fw_pfil.c        27 Aug 2004 15:16:22 -0000      1.7 
+++ ip_fw_pfil.c        27 Aug 2004 18:52:08 -0000 
@@ -100,6 +100,7 @@ ipfw_check_in(void *arg, struct mbuf **m 
m_tag_delete(*m0, dn_tag); 
} 

+again: 
args.m = *m0; 
ipfw = ipfw_chk(&args); 
*m0 = args.m; 
@@ -127,7 +128,7 @@ ipfw_check_in(void *arg, struct mbuf **m 
*m0 = NULL; 
return 0;       /* packet consumed */ 
} else 
-                       goto pass;      /* continue with packet */ 
+                       goto again;     /* continue with packet */ 
} 

#ifdef IPFIREWALL_FORWARD 
@@ -182,6 +183,7 @@ ipfw_check_out(void *arg, struct mbuf ** 
m_tag_delete(*m0, dn_tag); 
} 

+again: 
args.m = *m0; 
args.oif = ifp; 
ipfw = ipfw_chk(&args); 
@@ -209,7 +211,7 @@ ipfw_check_out(void *arg, struct mbuf ** 
*m0 = NULL; 
return 0;       /* packet consumed */ 
} else 
-                       goto pass;      /* continue with packet */ 
+                       goto again;     /* continue with packet */ 
} 

#ifdef IPFIREWALL_FORWARD 

Thanks 
--  
Andre 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64240 

From: Ian Freislich <ian@freislich.nom.za>
To: Andre Oppermann <andre@freebsd.org>
Cc:  
Subject: Re: kern/64240: IPFW tee terminates rule processing 
Date: Wed, 01 Sep 2004 10:55:23 +0200

 Andre Oppermann wrote:
 > Ian Freislich wrote:
 > > 
 > > Andre Oppermann wrote:
 > > > Synopsis: IPFW tee terminates rule processing
 > > >
 > > > State-Changed-From-To: open->analyzed
 > > > State-Changed-By: andre
 > > > State-Changed-When: Fri Aug 27 18:52:25 GMT 2004
 > > > State-Changed-Why:
 > > > Ian,
 > > >
 > > > could you please try the following patch (against -current or 5.3-BETA1),
 > > > (maybe whitespace mangled):
 > > 
 > > Applied by hand because of white-space problems.  My computer
 > > -CURRENT locked up when I added the tee rule with this patch.
 > 
 > It got into an infinite loop.  IPFW2 doesn't update the args.rules
 > field when 'tee' is hit.  Try the attached patch to netinet/ip_fw2.c
 > in addition to the one you already have.
 
 Ok, I've tried it.  The tee works, but the packet is still allowed:
 
 [brane-dead] ~ # ipfw l |head -4
 00001 tee 300 ip from any to any
 00050 divert 5000 ip from 196.7.162.24/29 to 192.168.0.0/24
 00300 reject tcp from me to 196.33.166.202 dst-port 80
 00300 reject tcp from me to 62.26.220.2 dst-port 80
 
 brane-dead] ~ # telnet 196.33.166.202 80
 Trying 196.33.166.202...
 Connected to a196-33-166-202.deploy.akamaitechnologies.com.
 Escape character is '^]'.
 
 At least it doesn't panic.  Have a look at what I did closely.  It
 was a bit of a hack and a cludge, but what is killing you is the
 one_pass flag.  Your patch works fine under the following condition:
 
 [brane-dead] ~ # sysctl net.inet.ip.fw.one_pass=0
 net.inet.ip.fw.one_pass: 1 -> 0
 [brane-dead] ~ # telnet 196.33.166.202 80
 Trying 196.33.166.202...
 telnet: connect to address 196.33.166.202: Permission denied
 telnet: Unable to connect to remote host
 [brane-dead] ~ # telnet /tmp/ipacct/ipacct.300 
 Trying /tmp/ipacct/ipacct.300...
 No connection.
 Escape character is '^]'.
 196.7.162.29    3       196.7.162.29    1       icmp    112     2
 196.7.162.29    58846   196.7.162.29    53      udp     146     2
 196.7.162.29    53      196.7.162.29    58846   udp     512     2
 196.7.162.29    65386   196.33.166.202  80      tcp     64      1 <---
 196.7.162.29    22      196.7.18.226    4187    tcp     2232    18
 196.7.18.226    4187    196.7.162.29    22      tcp     1872    24
 
 ---> only on packet - presumeably the SYN.
 
 You need to get the information back into ipfw that even if one_pass
 is true, we need to give this packet another pass because it
 re-entered because of a tee rule, and it needs to enter after the
 tee rule (not sure if you're doing that explicitly or if it just
 happens).  Line 1834 of /usr/src/sys/netinet/ip_fw2.c is where this
 happens.
 
 Ian
 
 --
 Ian Freislich
State-Changed-From-To: analyzed->patched 
State-Changed-By: andre 
State-Changed-When: Mon Sep 13 16:49:10 GMT 2004 
State-Changed-Why:  
A fix for 'ipfw tee' to behave correctly is in sys/netinet/ip_fw_pfil.c rev. 1.8. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64240 
State-Changed-From-To: patched->closed 
State-Changed-By: andre 
State-Changed-When: Thu Sep 16 20:35:06 GMT 2004 
State-Changed-Why:  
MFC to RELENG_5 is done.  Originator reported everything work as expected 
now.  Case closed. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64240 
>Unformatted:
