From nobody@FreeBSD.org  Wed Oct 23 11:03:22 2002
Return-Path: <nobody@FreeBSD.org>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 29FA237B401
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 23 Oct 2002 11:03:22 -0700 (PDT)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id D8E8943E6E
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 23 Oct 2002 11:03:21 -0700 (PDT)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.6/8.12.6) with ESMTP id g9NI3L7R088115
	for <freebsd-gnats-submit@FreeBSD.org>; Wed, 23 Oct 2002 11:03:21 -0700 (PDT)
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.6/8.12.6/Submit) id g9NI3LDs088114;
	Wed, 23 Oct 2002 11:03:21 -0700 (PDT)
Message-Id: <200210231803.g9NI3LDs088114@www.freebsd.org>
Date: Wed, 23 Oct 2002 11:03:21 -0700 (PDT)
From: Andriy Gapon <avg@icyb.net.ua>
To: freebsd-gnats-submit@FreeBSD.org
Subject: ipfw layer2 rules are not checked for ether_output_frame() on bridged interface
X-Send-Pr-Version: www-1.0

>Number:         44417
>Category:       kern
>Synopsis:       [bridge] [patch] ipfw layer2 rules are not checked for ether_output_frame() on bridged interface
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    luigi
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Oct 23 11:10:01 PDT 2002
>Closed-Date:    Sun Nov 12 10:49:56 GMT 2006
>Last-Modified:  Sun Nov 12 10:49:56 GMT 2006
>Originator:     Andriy Gapon
>Release:        4.7-RELEASE
>Organization:
>Environment:
FreeBSD terminus.foundation.invalid 4.7-RELEASE FreeBSD 4.7-RELEASE #3: Fri Oct 18 16:09:53 EDT 2002     avg@edge.foundation.invalid:/sys-devel/obj/sys-devel/src/sys/TERMINUS.bridge  i386
>Description:
      with both net.link.ether.ipfw=1 and  net.link.ether.bridge_ipfw=1 packets transmitted via an interface that is a part of a bridge cluster are not checked against ipfw rules in either ether_output_frame() or bdg_forward(). This means that traffic originating from a bridging host or routed from non-bridged interface will not be checked agains layer2-specific ipfw rules. this problem is only specific IPFW2, because with IPFW1 you can set layer2 rules anyway.
>How-To-Repeat:
      on a bridinging host with IPFW2,
Actions:
1. sysctl net.link.ether.ipfw=1 
2. sysctl net.link.ether.bridge_ipfw=1 
3. ipfw add 1 allow mac <mac address of host H on bridged subnet> any
4. ping H
Result:
rule 1 will not have any matches 
>Fix:
      it's very tempting to suggest to remove check for src != NULL at sys/net/bridge.c:860, but not being an expert in the network code, I am not sure about possible interdependencies/side-effects.
>Release-Note:
>Audit-Trail:

From: Andriy Gapon <avg@icyb.net.ua>
To: FreeBSD-gnats-submit@FreeBSD.org
Cc: freebsd-ipfw@freebsd.org
Subject: Re: kern/44417: ipfw layer2 rules are not checked for
 ether_output_frame() on bridged interface
Date: Mon, 28 Oct 2002 11:47:41 -0500 (EST)

 Here's a patch that I think fixes this problem, it works for me.
 If anybody else could test this that would be great.
 
 --- if_ethersubr.c.orig	Wed Oct 23 15:27:08 2002
 +++ if_ethersubr.c	Wed Oct 23 15:28:06 2002
 @@ -388,9 +388,6 @@
  		if (m->m_flags == PACKET_TAG_DUMMYNET)
  			rule = ((struct dn_pkt *)m)->rule;
 
 -	if (rule)	/* packet was already bridged */
 -		goto no_bridge;
 -
  	if (BDG_ACTIVE(ifp) ) {
  		struct ether_header *eh; /* a ptr suffices */
 
 --- bridge.c.orig	Wed Oct 23 15:28:16 2002
 +++ bridge.c	Wed Oct 23 15:29:06 2002
 @@ -857,11 +857,11 @@
       * Additional restrictions may apply e.g. non-IP, short packets,
       * and pkts already gone through a pipe.
       */
 -    if (src != NULL && (
 +    if (
  #ifdef PFIL_HOOKS
  	((pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh)) != NULL && bdg_ipf !=0) ||
  #endif
 -	(IPFW_LOADED && bdg_ipfw != 0))) {
 +	(IPFW_LOADED && bdg_ipfw != 0)) {
 
  	int i;
 
 
 -- 
 Andriy Gapon
 *
 "Never try to outstubborn a cat." Lazarus Long, "Time Enough for Love"
 

From: Luigi Rizzo <rizzo@icir.org>
To: Andriy Gapon <avg@icyb.net.ua>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-ipfw@FreeBSD.ORG
Subject: Re: kern/44417: ipfw layer2 rules are not checked for ether_output_frame() on bridged interface
Date: Tue, 29 Oct 2002 09:55:21 -0800

 let me think about it, i am not 100% sure that it is the correct fix.
 Could you summarise the bug and the logic for the fix ?
 
 	thanks
 	luigi
 
 On Mon, Oct 28, 2002 at 11:47:41AM -0500, Andriy Gapon wrote:
 > 
 > Here's a patch that I think fixes this problem, it works for me.
 > If anybody else could test this that would be great.
 > 
 > --- if_ethersubr.c.orig	Wed Oct 23 15:27:08 2002
 > +++ if_ethersubr.c	Wed Oct 23 15:28:06 2002
 > @@ -388,9 +388,6 @@
 >  		if (m->m_flags == PACKET_TAG_DUMMYNET)
 >  			rule = ((struct dn_pkt *)m)->rule;
 > 
 > -	if (rule)	/* packet was already bridged */
 > -		goto no_bridge;
 > -
 >  	if (BDG_ACTIVE(ifp) ) {
 >  		struct ether_header *eh; /* a ptr suffices */
 > 
 > --- bridge.c.orig	Wed Oct 23 15:28:16 2002
 > +++ bridge.c	Wed Oct 23 15:29:06 2002
 > @@ -857,11 +857,11 @@
 >       * Additional restrictions may apply e.g. non-IP, short packets,
 >       * and pkts already gone through a pipe.
 >       */
 > -    if (src != NULL && (
 > +    if (
 >  #ifdef PFIL_HOOKS
 >  	((pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh)) != NULL && bdg_ipf !=0) ||
 >  #endif
 > -	(IPFW_LOADED && bdg_ipfw != 0))) {
 > +	(IPFW_LOADED && bdg_ipfw != 0)) {
 > 
 >  	int i;
 > 
 > 
 > -- 
 > Andriy Gapon
 > *
 > "Never try to outstubborn a cat." Lazarus Long, "Time Enough for Love"
 > 
 > 
 > To Unsubscribe: send mail to majordomo@FreeBSD.org
 > with "unsubscribe freebsd-ipfw" in the body of the message

From: Andriy Gapon <avg@icyb.net.ua>
To: Luigi Rizzo <rizzo@icir.org>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-ipfw@FreeBSD.ORG
Subject: Re: kern/44417: ipfw layer2 rules are not checked for
 ether_output_frame() on bridged interface
Date: Tue, 29 Oct 2002 15:01:57 -0500 (EST)

 On Tue, 29 Oct 2002, Luigi Rizzo wrote:
 
 > let me think about it, i am not 100% sure that it is the correct fix.
 > Could you summarise the bug and the logic for the fix ?
 
 Luigi,
 
 url for this PR is:
 http://www.freebsd.org/cgi/query-pr.cgi?pr=kern/44417
 
 more detailed explanation of the problem and the proposed patch follows.
 it appears that a packet going out through a bridged interface will never
 be checked against ipfw rules in layer2 (this applies only to ipfw2 of
 course).
 
 I will be speaking about 4.7-RELEASE code.
 In ether_output_frame():
 
     394         if (BDG_ACTIVE(ifp) ) {
     395                 struct ether_header *eh; /* a ptr suffices */
     396
     397                 m->m_pkthdr.rcvif = NULL;
     398                 eh = mtod(m, struct ether_header *);
     399                 m_adj(m, ETHER_HDR_LEN);
     400                 m = bdg_forward_ptr(m, eh, ifp);
     401                 if (m != NULL)
     402                         m_freem(m);
     403                 return (0);
     404         }
 
 i.e. a packet is handed off to bdg_forward() at line 400 without any
 ipfw checks and its rcvif is set to NULL at line 397.
 Then in bdg_forward():
 
     853     /*
     854      * Do filtering in a very similar way to what is done in ip_output.
     855      * Only if firewall is loaded, enabled, and the packet is not
     856      * from ether_output() (src==NULL, or we would filter it twice).
     857      * Additional restrictions may apply e.g. non-IP, short packets,
     858      * and pkts already gone through a pipe.
     859      */
     860     if (src != NULL && (
     861 #ifdef PFIL_HOOKS
     862         ((pfh = pfil_hook_get(PFIL_IN, &inetsw[ip_protox[IPPROTO_IP]].pr_pfh)) != NULL && bdg_ipf !=0) ||
     863 #endif
     864         (IPFW_LOADED && bdg_ipfw != 0))) {
 
 
 condition at line 860 makes sure that firewall rules are not checked here
 too. That means that layer2-specific rules are never applied to the said
 packet. The change to bridge.c was intended to fix that. I believe that it
 shouldn't break something else.
 
 I've made the change to if_ethersubr.c, because I didn't quite understand
 what this code:
 
     386         /* Extract info from dummynet tag, ignore others */
     387         for (; m->m_type == MT_TAG; m = m->m_next)
     388                 if (m->m_flags == PACKET_TAG_DUMMYNET)
     389                         rule = ((struct dn_pkt *)m)->rule;
     390
     391         if (rule)       /* packet was already bridged */
     392                 goto no_bridge;
 
 was doing. The condition appears to check if a packet was passed through a
 pipe or queue, but the action is to by-pass bridge-specific code.
 My vision was that the said packet should go again to bdg_forward(), where
 it will be taken care of by:
 
     868         if (args.rule != NULL) /* packet already partially processed */
     869             goto forward; /* HACK! I should obey the fw_one_pass */
 
 If the interface in question is not bridged, the patch should not make any
 difference at all.
 
 I have a system that has 3 interfaces, does bridging between two of them
 and routing with the third one, and also limits traffic to/from a particular
 host on one of the bridged LANs based on its MAC address. Everything seems
 to work properly with this patch. I don't see any strange/unexpected
 behaviour. But I understand that this fact alone is not a sufficient
 proof, I'm not sure right now that I'm not doing an extra pass somewhere.
 
 Hope this explains the problem and the idea for the patches.
 Thanks a lot.
 
 -- 
 Andriy Gapon
 *
 "Never try to outstubborn a cat." Lazarus Long, "Time Enough for Love"
 
 

From: Andriy Gapon <avg@icyb.net.ua>
To: Luigi Rizzo <rizzo@icir.org>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-ipfw@FreeBSD.ORG
Subject: Re: kern/44417: ipfw layer2 rules are not checked for
 ether_output_frame() on bridged interface
Date: Wed, 30 Oct 2002 12:37:15 -0500 (EST)

 Luigi,
 
 you are right - my patch is incorrect, firewall rules are checked at the
 wrong place.
 This one should be better:
 
 391,406d390
 < 	if (rule)	/* packet was already bridged */
 < 		goto no_bridge;
 <
 < 	if (BDG_ACTIVE(ifp) ) {
 < 		struct ether_header *eh; /* a ptr suffices */
 <
 < 		m->m_pkthdr.rcvif = NULL;
 < 		eh = mtod(m, struct ether_header *);
 < 		m_adj(m, ETHER_HDR_LEN);
 < 		m = bdg_forward_ptr(m, eh, ifp);
 < 		if (m != NULL)
 < 			m_freem(m);
 < 		return (0);
 < 	}
 <
 < no_bridge:
 432a417,429
 > 	}
 >
 > 	if (BDG_ACTIVE(ifp) ) {
 > 		splx(s); /* XXX */
 > 		struct ether_header *eh; /* a ptr suffices */
 >
 > 		m->m_pkthdr.rcvif = NULL;
 > 		eh = mtod(m, struct ether_header *);
 > 		m_adj(m, ETHER_HDR_LEN);
 > 		m = bdg_forward_ptr(m, eh, ifp);
 > 		if (m != NULL)
 > 			m_freem(m);
 > 		return (0);
 
 basically it moves check for bridging to after ipfw stuff.
 What do you think ?
 Thank you.
 
 -- 
 Andriy Gapon
 

From: Andriy Gapon <avg@icyb.net.ua>
To: Luigi Rizzo <rizzo@icir.org>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-ipfw@FreeBSD.ORG
Subject: Re: kern/44417: ipfw layer2 rules are not checked for
 ether_output_frame() on bridged interface
Date: Wed, 30 Oct 2002 19:07:17 -0500 (EST)

 sorry, sent that patch before even trying to compile it.
 of course it should be:
 
 391,406d390
 < 	if (rule)	/* packet was already bridged */
 < 		goto no_bridge;
 <
 < 	if (BDG_ACTIVE(ifp) ) {
 < 		struct ether_header *eh; /* a ptr suffices */
 <
 < 		m->m_pkthdr.rcvif = NULL;
 < 		eh = mtod(m, struct ether_header *);
 < 		m_adj(m, ETHER_HDR_LEN);
 < 		m = bdg_forward_ptr(m, eh, ifp);
 < 		if (m != NULL)
 < 			m_freem(m);
 < 		return (0);
 < 	}
 <
 < no_bridge:
 432a417,429
 > 	}
 >
 > 	if (BDG_ACTIVE(ifp) ) {
 > 		struct ether_header *eh; /* a ptr suffices */
 >
 > 		splx(s); /* XXX */
 > 		m->m_pkthdr.rcvif = NULL;
 > 		eh = mtod(m, struct ether_header *);
 > 		m_adj(m, ETHER_HDR_LEN);
 > 		m = bdg_forward_ptr(m, eh, ifp);
 > 		if (m != NULL)
 > 			m_freem(m);
 > 		return (0);
 
 damn C++ :-)
 
 Btw, could you please educate me a little bit about this splXXX() stuff ?
 I've tried to understand it from man page, but failed...
 What purpose does it serve here ? Is this like some kind of locking ?
 Is it ok that there are return statements after ether_ipfw_chk() call in
 ether_output_frame() without splx(s) ?
 Thank you!
 
 -- 
 Andriy Gapon
 *
 "The worst part of communication is the illusion that it has
 actually occurred".   M. Jenkins.
 
Responsible-Changed-From-To: freebsd-bugs->luigi 
Responsible-Changed-By: luigi 
Responsible-Changed-When: Sun Nov 17 15:37:15 PST 2002 
Responsible-Changed-Why:  
need to look at this 


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

From: Andriy Gapon <agapon@cv-nj.com>
To: Luigi Rizzo <rizzo@icir.org>
Cc: FreeBSD-gnats-submit@FreeBSD.ORG
Subject: Re: kern/44417: ipfw layer2 rules are not checked for
 ether_output_frame() on bridged interface
Date: Tue, 01 Apr 2003 15:01:45 -0500 (EST)

 Luigi,
 
 it's been a while since you said you would look at this PR, did you
 actually have a chance ?
 Maybe you need some additional information from me ?
 The patch for if_ethersubr.c that I sent in my last submission for the PR
 seems to work very well for me without causing any interference or
 side effects.
 
 -- 
 Andriy Gapon
 *
 "In my view XML is to data representation
 what Roman numerals are to math." (c) Bakul Shah
State-Changed-From-To: open->feedback 
State-Changed-By: bms 
State-Changed-When: Mon Sep 25 16:55:00 UTC 2006 
State-Changed-Why:  
Please update to 6.1-RELEASE or later and/or try switching 
to if_bridge (bridge is deprecated in 7.0) 

http://www.freebsd.org/cgi/query-pr.cgi?pr=44417 
State-Changed-From-To: feedback->closed 
State-Changed-By: remko 
State-Changed-When: Sun Nov 12 10:49:50 UTC 2006 
State-Changed-Why:  
No feedback had been recieved, please submit feedback so that we can 
futher look into this issue. Till that is the case, we will be closing 
the PR. 

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