From pkern@cns.utoronto.ca  Thu Dec 18 14:44:01 2003
Return-Path: <pkern@cns.utoronto.ca>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 9833616A4CE
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 18 Dec 2003 14:44:01 -0800 (PST)
Received: from rodent.utcs.utoronto.ca (rodent.utcs.utoronto.ca [128.100.102.5])
	by mx1.FreeBSD.org (Postfix) with SMTP id C529A43D41
	for <FreeBSD-gnats-submit@freebsd.org>; Thu, 18 Dec 2003 14:43:59 -0800 (PST)
	(envelope-from pkern@cns.utoronto.ca)
Received: by rodent.utcs.utoronto.ca id <1650876>; Thu, 18 Dec 2003 17:43:56 -0500
Message-Id: <03Dec18.174356est.1650876@rodent.utcs.utoronto.ca>
Date: Thu, 18 Dec 2003 17:43:56 -0500
From: pak@cns.utoronto.ca
Reply-To: pak@cns.utoronto.ca
To: FreeBSD-gnats-submit@freebsd.org
Cc: pak@cns.utoronto.ca
Subject: [patch] to make "ipfw tee" behave as intended.
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         60377
>Category:       kern
>Synopsis:       [patch] to make "ipfw tee" behave as intended.
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    andre
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Dec 18 14:50:20 PST 2003
>Closed-Date:    Thu Sep 09 12:28:40 GMT 2004
>Last-Modified:  Thu Sep 09 12:28:40 GMT 2004
>Originator:     P Kern <pak@cns.utoronto.ca>
>Release:        FreeBSD 4.9-RELEASE i386
>Organization:
U of Toronto Computing and Networking Services
>Environment:
System: FreeBSD work 4.9-RELEASE FreeBSD 4.9-RELEASE #14: Wed Dec 17 16:05:21 EST 2003 root@work:/usr/src/sys/compile/WORK i386


>Description:

	Currently with "ipfw tee" [as noted in ipfw(8)]
	  "the search terminates and the original packet is accepted."
	Here is a patch to make "ipfw tee" behave as intended(?).
	With this patch, after a matching packet is sent to the divert
	socket, instead of terminating the search and accepting the
	packet, the search continues so that the packet is checked
	against any further IPFW rules.

	Hope this helps.

>How-To-Repeat:
>Fix:

*** sys/netinet/ip_input.c	2003/12/17 16:20:23	1.1
--- sys/netinet/ip_input.c	2003/12/17 19:49:21
***************
*** 845,865 ****
		divert_packet(m, 1, divert_info & 0xffff, args.divert_rule);
		ipstat.ips_delivered++;
  
! 		/* If 'tee', continue with 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. But first clear divert_info to avoid
! 		 * entering this block again.
! 		 * We do not need to clear args.divert_rule
! 		 * or args.next_hop as they will not be used.
! 		 */
! 		divert_info = 0;
! 		goto pass;
	}
  #endif
  
--- 845,879 ----
		divert_packet(m, 1, divert_info & 0xffff, args.divert_rule);
		ipstat.ips_delivered++;
  
! 		/* If 'tee', restart the packet at this divert rule. */
! 		if (clone != NULL) {
! 			struct m_hdr divert_tag;
! 
! 			m = clone;
! 			ip = mtod(m, struct ip *);
! 
! 			/* Restore packet header fields to original values */
! 			ip->ip_len += hlen;
! 			ip->ip_len = htons(ip->ip_len);
! 			ip->ip_off = htons(ip->ip_off);
! 
! 			/*
! 			 * set the IPFW restart point.
! 			 * adapted from div_output() in ip_divert.c
! 			 */
! 			divert_tag.mh_type = MT_TAG;
! 			divert_tag.mh_flags = PACKET_TAG_DIVERT;
! 			divert_tag.mh_next = m;
! 			divert_tag.mh_data = (caddr_t)(int)args.divert_rule;	/* the matching rule # */
! 
! 			/*
! 			 * resubmit packet to input processing.
! 			 * XXX - need to decrement some ipstats
! 			 *	 to avoid overcounting?
! 			 */
! 			ip_input((struct mbuf *)&divert_tag);
			return;
! 		}
	}
  #endif
  
*** sys/netinet/ip_output.c	2003/12/17 16:31:48	1.1
--- sys/netinet/ip_output.c	2003/12/17 19:54:31
***************
*** 812,822 ****
			/* Deliver packet to divert input routine */
			divert_packet(m, 0, off & 0xffff, args.divert_rule);
  
! 			/* If 'tee', continue with original packet */
			if (clone != NULL) {
! 				m = clone;
! 				ip = mtod(m, struct ip *);
! 				goto pass;
			}
			goto done;
		}
--- 812,836 ----
			/* Deliver packet to divert input routine */
			divert_packet(m, 0, off & 0xffff, args.divert_rule);
  
! 			/* If 'tee', restart the packet at this divert rule. */
			if (clone != NULL) {
! 				struct m_hdr divert_tag;
! 
! 				/*
! 				 * set the IPFW restart point.
! 				 * adapted from div_output() in ip_divert.c
! 				 */
! 				divert_tag.mh_type = MT_TAG;
! 				divert_tag.mh_flags = PACKET_TAG_DIVERT;
! 				divert_tag.mh_next = clone;
! 				divert_tag.mh_data = (caddr_t)(int)args.divert_rule;	/* the matching rule # */
! 
! 				/*
! 				 * resubmit packet to output processing
! 				 * XXX - need to decrement some ipstats
! 				 *	 to avoid overcounting?
! 				 */
! 				return (ip_output((struct mbuf *)&divert_tag, opt, ro, flags, imo, inp));
			}
			goto done;
		}
*** sbin/ipfw/ipfw.8	2003/12/17 19:58:31	1.1
--- sbin/ipfw/ipfw.8	2003/12/18 14:33:25
***************
*** 654,663 ****
  .Xr divert 4
  socket bound to port
  .Ar port .
- The search terminates and the original packet is accepted
- (but see Section
- .Sx BUGS
- below).
  .It Cm unreach Ar code
  Discard packets that match this rule, and try to send an ICMP
  unreachable notice with code
--- 654,659 ----
***************
*** 2133,2144 ****
  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.
--- 2129,2134 ----


>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->luigi 
Responsible-Changed-By: roam 
Responsible-Changed-When: Thu Dec 18 22:55:43 PST 2003 
Responsible-Changed-Why:  
Over to the IPFW author/maintainer. 

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

From: P Kern <pak@cns.utoronto.ca>
To: freebsd-gnats-submit@FreeBSD.org, pak@cns.utoronto.ca
Cc:  
Subject: Re: kern/60377: [patch] to make "ipfw tee" behave as intended.
Date: Thu, 15 Jan 2004 16:46:31 -0500

 Sorry but this patch as it is now will break "ipfw divert".
 The problem is that in the changed to ip_input.c, the final
 'return;' should follow the 'if (clone != NULL) { ... }'
 portion instead of being inside it.
 i.e. where it now reads ....
 
 	if (clone != NULL) {
 		...
 		return;
 	}
 
 ... it should instead read ...
 
 	if (clone != NULL) {
 		...
 	}
 	return;
 
 
 Sorry about that. Hope this helps. pak.
 
Responsible-Changed-From-To: luigi->andre 
Responsible-Changed-By: andre 
Responsible-Changed-When: Tue Aug 24 18:10:04 GMT 2004 
Responsible-Changed-Why:  
Take over. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=60377 
State-Changed-From-To: open->closed 
State-Changed-By: andre 
State-Changed-When: Thu Sep 9 12:27:06 GMT 2004 
State-Changed-Why:  
Ipfw tee will not be fixed in 4.x due to complexity.  For 5.x a fix has been prepared 
and is tracked under kern/64240. 

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