From owner-freebsd-bugs@FreeBSD.ORG Sat Mar 13 23:30:18 2004 Return-Path: Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 29C6316A4CF for ; Sat, 13 Mar 2004 23:30:18 -0800 (PST) Received: from freefall.freebsd.org (freefall.freebsd.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 1C0AC43D1F for ; Sat, 13 Mar 2004 23:30:18 -0800 (PST) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) i2E7UIbv030044 for ; Sat, 13 Mar 2004 23:30:18 -0800 (PST) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.10/8.12.10/Submit) id i2E7UHPq030043; Sat, 13 Mar 2004 23:30:17 -0800 (PST) (envelope-from gnats) Resent-Date: Sat, 13 Mar 2004 23:30:17 -0800 (PST) Resent-Message-Id: <200403140730.i2E7UHPq030043@freefall.freebsd.org> Resent-From: FreeBSD-gnats-submit@FreeBSD.org (GNATS Filer) Resent-To: freebsd-bugs@FreeBSD.org Resent-Reply-To: FreeBSD-gnats-submit@FreeBSD.org, Ian Freislich Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 97C9A16A4CE for ; 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 ; 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: Date: Sun, 14 Mar 2004 09:26:16 +0200 From: Ian Freislich Sender: Ian Freislich To: FreeBSD-gnats-submit@FreeBSD.org X-Send-Pr-Version: 3.113 Subject: kern/64240: IPFW tee terminates rule processing X-BeenThere: freebsd-bugs@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list Reply-To: Ian Freislich List-Id: Bug reports List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 14 Mar 2004 07:30:18 -0000 >Number: 64240 >Category: kern >Synopsis: IPFW tee terminates rule processing >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sat Mar 13 23:30:17 PST 2004 >Closed-Date: >Last-Modified: >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: >Unformatted: