From nobody@FreeBSD.org  Thu Mar 25 08:13:55 2004
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 E840C16A4D0
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 25 Mar 2004 08:13:31 -0800 (PST)
Received: from www.freebsd.org (www.freebsd.org [216.136.204.117])
	by mx1.FreeBSD.org (Postfix) with ESMTP id E1E2243D49
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 25 Mar 2004 08:13:31 -0800 (PST)
	(envelope-from nobody@FreeBSD.org)
Received: from www.freebsd.org (localhost [127.0.0.1])
	by www.freebsd.org (8.12.10/8.12.10) with ESMTP id i2PGDV72090256
	for <freebsd-gnats-submit@FreeBSD.org>; Thu, 25 Mar 2004 08:13:31 -0800 (PST)
	(envelope-from nobody@www.freebsd.org)
Received: (from nobody@localhost)
	by www.freebsd.org (8.12.10/8.12.10/Submit) id i2PGDVHB090255;
	Thu, 25 Mar 2004 08:13:31 -0800 (PST)
	(envelope-from nobody)
Message-Id: <200403251613.i2PGDVHB090255@www.freebsd.org>
Date: Thu, 25 Mar 2004 08:13:31 -0800 (PST)
From: Ed Maste <emaste@sandvine.com>
To: freebsd-gnats-submit@FreeBSD.org
Subject: [patch] Bridged packets still seen by BPF listener after BIOCSEESENT ioctl.
X-Send-Pr-Version: www-2.3

>Number:         64718
>Category:       kern
>Synopsis:       [patch] Bridged packets still seen by BPF listener after BIOCSEESENT ioctl.
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    bms
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Mar 25 08:20:22 PST 2004
>Closed-Date:    Fri Nov 26 05:27:58 GMT 2004
>Last-Modified:  Fri Nov 26 05:27:58 GMT 2004
>Originator:     Ed Maste
>Release:        4.7
>Organization:
Sandvine Inc.
>Environment:
FreeBSD 4.7

>Description:
The BIOCSSEESENT ioctl sets a flag that controls whether received packets only, or both transmitted and received packets, are captured by BPF.

This flag does not have any effect for packets transmitted by an interface as a result of bridging.  These packets are always seen by the BPF listener.

>How-To-Repeat:
sysctl net.link.ether.bridge=1
sysctl net.link.ether.bridge_cfg="em0 em1"

Open a bpf listener on em0 and set the BIOCSEESENT flag to zero.  Observe that both packets received on em0, and packets bridged from em1 to em0, are caught by BPF.

It seems that bpf_mtap uses m->m_pkthdr.rcvif == NULL as an indication that the packet is was transmitted, and that bridged packets still have the rcvif set.
>Fix:
This is one way to get around the problem:

--- bridge.c.orig    2003-12-29 14:07:02.000000000 -0500
+++ bridge.c    2004-03-22 16:52:27.000000000 -0500
@@ -1080,6 +1080,11 @@
                    return m0;
                bcopy(&save_eh, mtod(m, struct ether_header *), ETHER_HDR_LEN);
            }
+            /* 
+             * Clear rcvif so that a bpf listener on the output interface
+             * won't see this packet if it has SEESENT off.
+             */
+            m->m_pkthdr.rcvif = 0;
            if (!IF_HANDOFF(&last->if_snd, m, last)) {
 #if 0
                BDG_MUTE(last); /* should I also mute ? */

>Release-Note:
>Audit-Trail:

From: Ed Maste <emaste@sandvine.com>
To: freebsd-gnats-submit@FreeBSD.org, emaste@sandvine.com
Cc:  
Subject: Re: kern/64718: [patch] Bridged packets still seen by BPF listener
 after BIOCSEESENT ioctl.
Date: Mon, 29 Mar 2004 15:59:15 -0500

 Here's a better patch for this issue.  This was actually my first
 idea, but it didn't work due to a bug in ether_input and bpf_mtap.
 
 ether_input creates an m_hdr on the stack to put back the ether
 header for bpf_mtap.  It then casts this to a struct mbuf *. 
 However, it doesn't set mh_flags.  In the non-seesent case, bpf_mtap
 checks m->m_pkthdr.rcvif, but that's not valid on the passed in
 "mbuf."  Clearing mh_flags before calling bpf_mtap fixed this issue.
 
 Here's my new patches:
 
 --- if_ethersubr.c.orig     2004-02-05 12:33:44.000000000 -0500
 +++ if_ethersubr.c      2004-03-29 14:36:20.000000000 -0500
 @@ -599,6 +599,7 @@
                 struct m_hdr mh;
  
                 /* This kludge is OK; BPF treats the "mbuf" as read-only */
 +                mh.mh_flags = 0;
                 mh.mh_next = m;
                 mh.mh_data = (char *)eh;
                 mh.mh_len = ETHER_HDR_LEN;
 
 
 --- bpf.c.orig       2004-03-04 12:34:26.000000000 -0500
 +++ bpf.c       2004-03-29 15:09:45.000000000 -0500
 @@ -1249,8 +1249,14 @@
                 pktlen += m0->m_len;
  
         for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
 -               if (!d->bd_seesent && (m->m_pkthdr.rcvif == NULL))
 -                       continue;
 +               if (!d->bd_seesent) {
 +                        for (m0 = m; m0 != 0; m0 = m0->m_next)
 +                                if (m0->m_flags & M_PKTHDR)
 +                                        break;
 +                        if (m0 && m0->m_pkthdr.rcvif != ifp)
 +                               continue;
 +                }
                 ++d->bd_rcount;
                 slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
                 if (slen != 0)

From: darrenr@FreeBSD.ORG (Darren Reed)
To: freebsd-gnats-submit@FreeBSD.org, emaste@sandvine.com
Cc:  
Subject: Re: kern/64718: [patch] Bridged packets still seen by BPF listener after BIOCSEESENT ioctl.
Date: Sat, 10 Apr 2004 18:45:28 -0700 (PDT)

 Read the man page for bpf(4):
      BIOCGSEESENT   (u_int) Set or get the flag determining whether locally
                     generated packets on the interface should be returned by
                     BPF.
 ....
 
 Now compare this to the first line of your problem description:
 "The BIOCSSEESENT ioctl sets a flag that controls whether received packets
  only, or both transmitted and received packets, are captured by BPF."
 
 There is no bug, as such here.
 
 What you are expecting is for BIOCSEESENT to toggle the feedback of
 packets being output in the forwarded case, not just the locally
 generated case.  It is your expectation that is wrong here.
 
 Darren

From: Ed Maste <emaste@sandvine.com>
To: Darren Reed <darrenr@FreeBSD.ORG>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/64718: [patch] Bridged packets still seen by BPF listener
 after BIOCSEESENT ioctl.
Date: Sat, 10 Apr 2004 22:15:07 -0400

 > It is your expectation that is wrong here.
 
 No, I'm sorry, but at the very least the documentation is 
 inconsistent.  You left out part of the man page:
 
 BIOCGSEESENT  (u_int) Set or get the flag determining whether locally
               generated packets on the interface should be returned by
               BPF.  Set to zero to see only incoming packets on the
               interface.  
 
 The above makes no reference to packets that are not locally 
 generated nor received on the interface.  However, according to
 the above if I set the flag to zero I should see only received
 packets on the interface, which is not the case.  So yes, there
 is a bug here.
 
 I would argue that the behaviour implied by the second sentence
 is more generally useful, but that's just my opinion.
 
 Note however that independent of the above, there's still a bug 
 with the seesent code.  A struct m_hdr is allocated on the stack
 and cast to a struct mbuf * in ether_input before the call to
 bpf_mtap.  The seesent check then accesses m->m_pkthdr.rcvif.
 
 Regards,
 -ed
 
 

From: Darren Reed <darrenr@hub.freebsd.org>
To: Ed Maste <emaste@sandvine.com>
Cc: Darren Reed <darrenr@FreeBSD.ORG>,
	freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/64718: [patch] Bridged packets still seen by BPF listener after BIOCSEESENT ioctl.
Date: Sat, 10 Apr 2004 20:43:59 -0700

 On Sat, Apr 10, 2004 at 10:15:07PM -0400, Ed Maste wrote:
 > >It is your expectation that is wrong here.
 > 
 > No, I'm sorry, but at the very least the documentation is 
 > inconsistent.  You left out part of the man page:
 > 
 > BIOCGSEESENT  (u_int) Set or get the flag determining whether locally
 >              generated packets on the interface should be returned by
 >              BPF.  Set to zero to see only incoming packets on the
 >              interface.  
 > 
 > The above makes no reference to packets that are not locally 
 > generated nor received on the interface. 
 
 Ok, can we agree the man page is, perhaps, ambiguous about what
 should happen to forwarded packets ?
 
 In the case of a host that is not a gateway, the above entry does
 make sense.  Agreed ?
 
 > Note however that independent of the above, there's still a bug 
 > with the seesent code.  A struct m_hdr is allocated on the stack
 > and cast to a struct mbuf * in ether_input before the call to
 > bpf_mtap.  The seesent check then accesses m->m_pkthdr.rcvif.
 
 Yes, I can see that.
 However, FreeBSD-current doesn't work this way any more, so this
 fix would be a 4.x one only, if something were to be changed.
 
 Darren

From: Ed Maste <emaste@sandvine.com>
To: Darren Reed <darrenr@hub.freebsd.org>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: kern/64718: [patch] Bridged packets still seen by BPF listener
 after BIOCSEESENT ioctl.
Date: Sat, 10 Apr 2004 23:59:03 -0400

  > Ok, can we agree the man page is, perhaps, ambiguous about what
  > should happen to forwarded packets ?
  >
  > In the case of a host that is not a gateway, the above entry does
  > make sense. Agreed ?
 
 Yep.  I'll agree the description's correct for an end host that's
 not routing or bridging.
 
 Thanks,
 - ed
 
Responsible-Changed-From-To: freebsd-bugs->bms 
Responsible-Changed-By: bms 
Responsible-Changed-When: Mon Jun 14 17:59:16 GMT 2004 
Responsible-Changed-Why:  
I'll take this. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64718 
State-Changed-From-To: open->patched 
State-Changed-By: bms 
State-Changed-When: Mon Jun 14 18:31:55 GMT 2004 
State-Changed-Why:  
Fixed by design in -CURRENT, as it no longer uses those evil on-stack mbufs. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=64718 
State-Changed-From-To: patched->closed 
State-Changed-By: bms 
State-Changed-When: Fri Nov 26 05:27:49 GMT 2004 
State-Changed-Why:  
-current is now -stable 

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