Subject: kern/28339: M_HASFCS not honored in bpf(4)
To: None <kern-bug-people@netbsd.org, gnats-admin@netbsd.org,>
From: Thilo Manske <Thilo.Manske@HEH.Uni-Oldenburg.DE>
List: netbsd-bugs
Date: 11/17/2004 08:56:02
>Number: 28339
>Category: kern
>Synopsis: M_HASFCS not honored in bpf(4)
>Confidential: no
>Severity: non-critical
>Priority: medium
>Responsible: kern-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Wed Nov 17 08:56:00 +0000 2004
>Originator: Thilo Manske
>Release: NetBSD 2.99.10 and below
>Organization:
>Environment:
System: NetBSD Voigt 2.99.10 NetBSD 2.99.10 (Voigt) #69: Sat Nov 13 14:17:08 MET 2004 root@Voigt:/sys/arch/i386/compile/Voigt i386
Architecture: <all>
Machine: <all>
>Description:
Some ethernet network drivers (bce,sip,rtk,vr,wm..) deliver frames including
the 4 byte CRC sum at the end of the buffer, some don't (de, epic, ex, txp,
..) Drivers set the M_LINK0 (=M_HASFCS) flag according to that, but the flag
is neither honored nor passed to the next layer by bpf(4)
>How-To-Repeat:
- tcpdump ping traffic and notice received frames being 4 bytes larger
- use ethereal with tcpdumps taken from different interfaces
- watch dhclient complain like this:
"ip length 328 disagrees with bytes received 332"
>Fix:
This is a simple patch/workaround, it works with drivers
using bpf_mtap() (tested with rtk(4)). For drivers using bpf_mtap2() a
very similar piece of code could be used, but there's no way for me to test
it, so I left it out.
Index: bpf.c
===================================================================
RCS file: /cvsroot/src/sys/net/bpf.c,v
retrieving revision 1.104
diff -c -u -r1.104 bpf.c
--- bpf.c 19 Aug 2004 20:58:23 -0000 1.104
+++ bpf.c 17 Nov 2004 08:42:25 -0000
@@ -1271,12 +1271,32 @@
{
void *(*cpfn)(void *, const void *, size_t);
struct bpf_if *bp = arg;
- u_int pktlen, buflen;
+ u_int frmlen, pktlen, buflen;
void *marg;
- pktlen = m_length(m);
+ frmlen = pktlen = m_length(m);
+ /*
+ * try to find out if the mbuf is comming from an ethernet interface,
+ * since M_LINK0 (M_HASFCS) meaning depends on the type of the interface
+ */
+ if (m->m_pkthdr.rcvif != NULL)
+ {
+ switch (m->m_pkthdr.rcvif->if_dlt)
+ {
+ case DLT_EN10MB:
+ case DLT_EN3MB:
+ case DLT_IEEE802:
+ case DLT_IEEE802_11:
+ case DLT_IEEE802_11_RADIO:
+ if (m->m_flags & M_HASFCS)
+ pktlen-=ETHER_CRC_LEN;
+ break;
+ default:
+ break;
+ }
+ }
- if (pktlen == m->m_len) {
+ if (frmlen == m->m_len) {
cpfn = memcpy;
marg = mtod(m, void *);
buflen = pktlen;