Date: Sun, 14 Mar 2004 09:26:16 +0200 From: Ian Freislich <ianf@freislich.nom.za> To: FreeBSD-gnats-submit@FreeBSD.org Subject: kern/64240: IPFW tee terminates rule processing Message-ID: <E1B2Q0m-000190-77@brane-dead.freislich.nom.za> Resent-Message-ID: <200403140730.i2E7UHPq030043@freefall.freebsd.org>
next in thread | raw e-mail | index | archive | help
>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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?E1B2Q0m-000190-77>