Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 7 Jun 2005 22:19:29 +1200
From:      Matthew Luckie <mjl@luckie.org.nz>
To:        freebsd-net@freebsd.org
Subject:   Re: bpf writes on tun device
Message-ID:  <20050607101927.GA99034@lycra.luckie.org.nz>
In-Reply-To: <20050606204008.GA91353@lycra.luckie.org.nz>
References:  <4295A6CA.8080409@luckie.org.nz> <20050606081637.GA73886@lycra.luckie.org.nz> <20050606120851.GD734@empiric.icir.org> <20050606204008.GA91353@lycra.luckie.org.nz>

next in thread | previous in thread | raw e-mail | index | archive | help
> is there a good reason why _all_ DLT_NULL bpf devices could not simply
> have writes supported?  the user space application would pass the
> address family in the first 4 bytes of the packet; this is currently
> done anyway for if_disc, if_loop, if_tun, if_faith, and ng_iface.
> ip_carp could get bpf writes for free with AF_UNSPEC added to the
> carp_looutput() switch statement.

http://www.wand.net.nz/~mjl12/freebsd-current-dlt_null-write.diff

I spent some time going through all drivers in -current that export
DLT_NULL bpf devices that may support writing raw packets using BPF.
I did this by running

egrep -r 'bpfattach.+DLT_NULL' *

which corresponded to the following drivers:

sys/net/if_disc.c:        bpfattach(ifp, DLT_NULL, sizeof(u_int));
sys/net/if_faith.c:       bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
sys/net/if_gif.c:         bpfattach(&sc->gif_if, DLT_NULL, sizeof(u_int));
sys/net/if_gre.c:         bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t));
sys/net/if_loop.c:        bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
sys/net/if_stf.c:         bpfattach(ifp, DLT_NULL, sizeof(u_int));
sys/net/if_tun.c:         bpfattach(ifp, DLT_NULL, sizeof(u_int));
sys/netgraph/ng_iface.c:  bpfattach(ifp, DLT_NULL, sizeof(u_int));
sys/netgraph/ng_sppp.c:   bpfattach (&pp->pp_if, DLT_NULL, sizeof(u_int));
sys/dev/iicbus/if_ic.c:   bpfattach(ifp, DLT_NULL, ICHDRLEN);
sys/dev/ppbus/if_plip.c:  bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
sys/i4b/driver/i4b_ipr.c: bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int));
sys/netinet/ip_carp.c:    bpfattach(&sc->sc_if, DLT_NULL, sizeof(u_int32_t));

BPF writes were already supported (for packets up to 4 bytes less than
the IP MTU of the interface) for the following drivers:

 - if_disc
 - if_faith
 - if_gif
 - if_gre
 - if_loop
 - if_tun
 - ng_iface

I went through and altered the way BPF writes are handled in these drivers.
The code was basically changed as follows:

 	/* BPF write needs to be handled specially */
 	if (dst->sa_family == AF_UNSPEC) {
-		dst->sa_family = *(mtod(m0, int *));
-		m0->m_len -= sizeof(int);
-		m0->m_pkthdr.len -= sizeof(int);
-		m0->m_data += sizeof(int);
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af; 
 	}

The exception is if_loop.c, where the bpf write handling was in a weird
place.  BPF write was checked in if_simloop, rather than looutput.
However, anything supplying if_simloop a packet to write is not a DLT_NULL
BPF device, unless it is looutput.  So I shifted the BPF write check to
looutput.

Otherwise, i added BPF write support to the remaining drivers (if_stf,
if_ic, if_plip, i4b_ipr.c, and ip_carp.c).

I did not determine how to include the appropriate bpf write code in
ng_sppp.c - it does not appear to require it.

Please review.

Matthew



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