Subject: Re: DLT_NULL and bpf writes
To: None <tech-net@netbsd.org>
From: Christos Zoulas <christos@tac.gw.com>
List: tech-net
Date: 06/09/2005 04:13:48
In article <20050608234150.GA11257@lycra.luckie.org.nz>,
Matthew Luckie  <mjl@luckie.org.nz> wrote:
>Hi
>
>I spent some time going through all drivers in NetBSD -current that export
>DLT_NULL bpf devices with an eye to enabling BPF write support on them.
>
>It seems that all but one or two interface types do not currently support
>BPF writes, returning EAFNOSUPPORT, as bpf_movein sets dst->sa_family to
>AF_UNSPEC before passing the packet to the appropriate if_output function.
>The exception was if_faith.c which expects a 4 byte pseudo header that
>contains the underlying address family of the packet for if_output to pick
>up in that case.
>
>The 4 byte pseudo header on write seems to have become the default method
>to accomplish a BPF write, as most DLT_NULL devices on FreeBSD permit writes
>on interfaces with this type.  (although due to a long standing bug in the
>implementation, the maximum packet size that can be written is 4 bytes less
>than the IP MTU of the interface, as the code did not correctly account for
>the 4 byte pseudo header when checking for packets which are too big to tx).
>
>To start with, I identified which interfaces expose DLT_NULL to BPF writers
>with egrep -r 'bpfattach.+DLT_NULL' *
>
>which corresponded to the following drivers:
>
>arch/alpha/a12/if_xb.c: bpfattach(&xbi, DLT_NULL, 0);
>dev/ppbus/if_plip.c:    bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
>net/if_faith.c:         bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
>net/if_gif.c:           bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
>net/if_gre.c:           bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t));
>net/if_loop.c:          bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
>net/if_ppp.c:           bpfattach(&sc->sc_if, DLT_NULL, 0);
>net/if_stf.c:           bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
>net/if_tun.c:           bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
>netisdn/i4b_ipr.c:      bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
>netisdn/i4b_ipr.c:      bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
>
>I went through and added BPF write support using the 4 byte pseudo header
>method for if_plip, if_faith (modified), if_gif, if_gre, if_loop, if_stf,
>if_tun, and i4b_ipr.  I've put a patch of this work at
>
>http://www.wand.net.nz/~mjl12/netbsd-current-dlt_null-write.diff
>
>I did not touch if_ppp with this patch.  It seems possible that there are
>BPF writers in the wild which may possibly be able to write packets without
>the 4 byte pseudo header, as pppoutput handles the AF_UNSPEC case currently.
>Is there a reason why if_ppp is not a DLT_PPP device, as is the case with
>the FreeBSD if_ppp?  I am happy to handle the grunt work of modifying if_ppp
>to DLT_PPP if it will help my chances of getting this patch accepted.
>
>I also did not touch if_xb with this patch.  I'm not sure if it is considered
>safe to write raw frames with BPF using this device.  Also, I'm not sure
>if it is a true DLT_NULL device with a 4 byte pseudo header on read based
>on the bpfattach function call.
>
>More information about the context of this work can be found at:
>http://lists.freebsd.org/pipermail/freebsd-net/2005-June/007503.html
>http://marc.theaimsgroup.com/?l=tcpdump-workers&m=111818619022560&w=2
>

Looks fine to me. Why don't you change bcopy -> memcpy, then int
to uint32_t consistently and send-pr it. The only question is what
is the effect on if_faith.c where you are actually changing the
current behavior.

christos