bpf writes on tun device
Matthew Luckie
mjl at luckie.org.nz
Mon Jun 6 08:17:42 GMT 2005
> I can successfully write BPF packets up to 1500 bytes in size (1496 IP
> bytes without the address family integer). Writes larger than this
> return EMSGSIZE.
http://lists.freebsd.org/pipermail/freebsd-net/2005-May/007371.html
Just for the record, the patch below fixes this on 4.11; the same
problem exists in HEAD today. I'm pondering making an effort to add
write support to all interface types. I would do this by adding an
extra parameter to bpf_if that specifies the size of the 'link layer'
it expects to encounter when bpfwrite is called.
struct bpf_if {
LIST_ENTRY(bpf_if) bif_next; /* list of all interfaces */
LIST_HEAD(, bpf_d) bif_dlist; /* descriptor list */
struct bpf_if **bif_driverp; /* pointer into softc */
u_int bif_dlt; /* link layer type */
- u_int bif_hdrlen; /* length of header (with padding) */
+ u_int bif_hdrlen_rx; /* link header passed to bpf reader */
+ u_int bif_hdrlen_tx; /* link header passed by bpf writer */
struct ifnet *bif_ifp; /* corresponding interface */
struct mtx bif_mtx; /* mutex for interface */
};
If I was to pursue this, would someone on this list consider committing the
work to current?
Index: bpf.c
===================================================================
RCS file: /home/ncvs/src/sys/net/bpf.c,v
retrieving revision 1.59.2.13
diff -u -p -r1.59.2.13 bpf.c
--- bpf.c 21 Aug 2003 23:50:54 -0000 1.59.2.13
+++ bpf.c 6 Jun 2005 07:54:12 -0000
@@ -120,7 +120,7 @@ static void bpf_detachd __P((struct bpf_
static void bpf_freed __P((struct bpf_d *));
static void bpf_mcopy __P((const void *, void *, size_t));
static int bpf_movein __P((struct uio *, int,
- struct mbuf **, struct sockaddr *, int *));
+ struct mbuf **, struct sockaddr *, struct ifnet *));
static int bpf_setif __P((struct bpf_d *, struct ifreq *));
static void bpf_timed_out __P((void *));
static inline void
@@ -164,9 +164,10 @@ static struct filterops bpfread_filtops
{ 1, NULL, filt_bpfdetach, filt_bpfread };
static int
-bpf_movein(uio, linktype, mp, sockp, datlen)
+bpf_movein(uio, linktype, mp, sockp, ifp)
register struct uio *uio;
- int linktype, *datlen;
+ int linktype;
+ struct ifnet *ifp;
register struct mbuf **mp;
register struct sockaddr *sockp;
{
@@ -209,11 +210,18 @@ bpf_movein(uio, linktype, mp, sockp, dat
break;
case DLT_RAW:
- case DLT_NULL:
sockp->sa_family = AF_UNSPEC;
hlen = 0;
break;
+ case DLT_NULL:
+ sockp->sa_family = AF_UNSPEC;
+ if(strcmp(ifp->if_name, "tun") == 0)
+ hlen = sizeof(int);
+ else
+ hlen = 0;
+ break;
+
#ifdef __FreeBSD__
case DLT_ATM_RFC1483:
/*
@@ -235,7 +243,10 @@ bpf_movein(uio, linktype, mp, sockp, dat
}
len = uio->uio_resid;
- *datlen = len - hlen;
+
+ if (len - hlen > ifp->if_mtu)
+ return (EMSGSIZE);
+
if ((unsigned)len > MCLBYTES)
return (EIO);
@@ -619,7 +630,6 @@ bpfwrite(dev, uio, ioflag)
struct mbuf *m;
int error, s;
static struct sockaddr dst;
- int datlen;
if (d->bd_bif == 0)
return (ENXIO);
@@ -629,12 +639,9 @@ bpfwrite(dev, uio, ioflag)
if (uio->uio_resid == 0)
return (0);
- error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen);
+ error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, ifp);
if (error)
return (error);
-
- if (datlen > ifp->if_mtu)
- return (EMSGSIZE);
if (d->bd_hdrcmplt)
dst.sa_family = pseudo_AF_HDRCMPLT;
Index: if_tun.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_tun.c,v
retrieving revision 1.74.2.8
diff -u -p -r1.74.2.8 if_tun.c
--- if_tun.c 13 Feb 2002 00:43:11 -0000 1.74.2.8
+++ if_tun.c 6 Jun 2005 07:54:13 -0000
@@ -328,10 +328,8 @@ tunoutput(ifp, m0, dst, rt)
/* 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, &s, 4);
+ dst->sa_family = s;
}
if (ifp->if_bpf) {
More information about the freebsd-net
mailing list