Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 29 Mar 1999 11:26:45 -0800 (PST)
From:      cmsedore@maxwell.syr.edu
To:        freebsd-gnats-submit@freebsd.org
Subject:   kern/10860: bpf overwrites source ethernet addresses when writing to a bpf descriptor
Message-ID:  <19990329192645.8552714BD5@hub.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         10860
>Category:       kern
>Synopsis:       bpf overwrites source ethernet addresses when writing to a bpf descriptor
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Mon Mar 29 11:30:00 PST 1999
>Closed-Date:
>Last-Modified:
>Originator:     Chris Sedore
>Release:        3.1-RELEASE
>Organization:
>Environment:
FreeBSD fleegin.maxwell.syr.edu 3.1-RELEASE FreeBSD 3.1-RELEASE #10: Fri Mar 26 19:24:58 GMT 1999
>Description:
Writes to BPF descriptors bound to ethernet interfaces silently overwrite the source ethernet address field in packets.  BPF should reproduce the packets on the wire exactly as they are passed into write().  
>How-To-Repeat:
Write a packet to a bpf descriptor and observe the ethernet address with tcpdump or a similar tool
>Fix:
bpf routines need to use a different address family (or another methodology) to communicate with ether_output so ether_output doesn't mess with the packet.

My solution is attached.  Basically, rather than setting the dst->sa_family to AF_UNSPEC in the bpfwrite call, I set it to AF_LINK instead.  I added glue to if_ethersubr.c to handle AF_LINK, implying that this usage would not conflict with anything else since it wasn't handled previously.  

It works as expected in my testing.

-Chris

diff -c -r sys/net/bpf.c /usr/src/sys/net/bpf.c
*** sys/net/bpf.c       Mon Dec  7 21:58:36 1998
--- /usr/src/sys/net/bpf.c      Fri Mar 26 19:52:37 1999
***************
*** 177,185 ****
                break;

        case DLT_EN10MB:
!               sockp->sa_family = AF_UNSPEC;
!               /* XXX Would MAXLINKHDR be better? */
!               hlen = sizeof(struct ether_header);
                break;

        case DLT_FDDI:
--- 177,184 ----
                break;

        case DLT_EN10MB:
!               sockp->sa_family = AF_LINK;
!               hlen = 0;
                break;

        case DLT_FDDI:
diff -c -r sys/net/if_ethersubr.c /usr/src/sys/net/if_ethersubr.c
*** sys/net/if_ethersubr.c      Tue Jan 12 12:07:00 1999
--- /usr/src/sys/net/if_ethersubr.c     Fri Mar 26 18:58:58 1999
***************
*** 336,360 ****
                type = eh->ether_type;
                break;

        default:
                printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
                        dst->sa_family);
                senderr(EAFNOSUPPORT);
        }

!       /*
!        * Add local net header.  If no space in first mbuf,
!        * allocate another.
!        */
!       M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
!       if (m == 0)
!               senderr(ENOBUFS);
!       eh = mtod(m, struct ether_header *);
!       (void)memcpy(&eh->ether_type, &type,
!               sizeof(eh->ether_type));
!       (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
!       (void)memcpy(eh->ether_shost, ac->ac_enaddr,
!           sizeof(eh->ether_shost));

        /*
         * If a simplex interface, and the packet is being sent to our
--- 336,369 ----
                type = eh->ether_type;
                break;

+       case AF_LINK:
+               loop_copy = -1;
+               break;
+
        default:
                printf("%s%d: can't handle af%d\n", ifp->if_name, ifp->if_unit,
                        dst->sa_family);
                senderr(EAFNOSUPPORT);
        }

!       if (dst->sa_family!=AF_LINK) {
!
!               /*
!                * Add local net header.  If no space in first mbuf,
!                * allocate another.
!                */
!               M_PREPEND(m, sizeof (struct ether_header), M_DONTWAIT);
!               if (m == 0)
!                       senderr(ENOBUFS);
!               eh = mtod(m, struct ether_header *);
!               (void)memcpy(&eh->ether_type, &type,
!                       sizeof(eh->ether_type));
!               (void)memcpy(eh->ether_dhost, edst, sizeof (edst));
!               (void)memcpy(eh->ether_shost, ac->ac_enaddr,
!                   sizeof(eh->ether_shost));
!       } else {
!               eh = mtod(m, struct ether_header *);
!       }

        /*
         * If a simplex interface, and the packet is being sent to our

>Release-Note:
>Audit-Trail:
>Unformatted:


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19990329192645.8552714BD5>