kern/82157: [patch] bpf writes on DLT_NULL fail with IP MTU sized packets

Matthew Luckie mjl at luckie.org.nz
Sun Jun 12 05:50:13 GMT 2005


>Number:         82157
>Category:       kern
>Synopsis:       [patch] bpf writes on DLT_NULL fail with IP MTU sized packets
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Sun Jun 12 05:50:11 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Matthew Luckie
>Release:        5.4-RELEASE-p1
>Organization:
University of Waikato
>Environment:
FreeBSD mylar.plunket.luckie.org.nz 5.4-RELEASE-p1 FreeBSD 5.4-RELEASE-p1 #0: Wed May 18 13:44:40 NZST 2005     root at mylar.plunket.luckie.org.nz:/usr/obj/usr/src/sys/GENERIC  i386
>Description:
Some sockets RFCs (such as RFC 3542) say to use the BPF device to write complete IP packets onto the wire when the sockets API does not support some feature required but not available in the API.  However, there are many widely used link types not well supported by BPF for writing packets, particularly DLT_NULL.  This patch tidies up the BPF code associated with DLT_NULL in -current.

This patch does several things
* all DLT_NULL devices in the -current tree now support writing packets.  all devices expect a 4 byte psuedo header which corresponds to the underlying address family of the packet.  all DLT_NULL devices in the tree which currently support writing packets require this pseudo header, so the API as seen by a user process *does not* change.
* instead of the if_output function finding the pseudo header in the mbuf, it now finds it in dst->sa_data; this is where the if_output function for other types finds the appropriate header.
* fixes a long standing bug where a user process could only write packets up to 4 bytes less than the IP MTU of the device.

For more information, please read the thread on freebsd-net.  In particular, these posts are relevant:

http://lists.freebsd.org/pipermail/freebsd-net/2005-May/007371.html
http://lists.freebsd.org/pipermail/freebsd-net/2005-June/007503.html
http://lists.freebsd.org/pipermail/freebsd-net/2005-June/007504.html
http://lists.freebsd.org/pipermail/freebsd-net/2005-June/007511.html

Please consider committing this code to 6.0, if for no other reason other than it fixes a bug.
>How-To-Repeat:
Here's some code to write packets to a DLT_NULL bpf device.  I suggest the reader try writing an MTU sized packet on a DLT_NULL device such as if_tun.

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <sys/time.h>
#include <sys/ioctl.h>

#include <net/bpf.h>
#include <net/if.h>

#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/ip6.h>
#include <netinet/udp.h>
#include <netinet/tcp.h>
#include <netinet/ip_icmp.h>
#include <netinet/icmp6.h>
#include <arpa/inet.h>

#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>

#include <stdio.h>
#include <fcntl.h>

static int dl_bpf_open_dev(char *dev, const size_t len)
{
  int i=0, fd;

  do
    {
      snprintf(dev, len, "/dev/bpf%d", i);
      if((fd = open(dev, O_RDWR)) == -1)
	{
	  if(errno == EBUSY)
	    {
	      continue;
	    }
	  else
	    {
	      perror("could not open bpf");
	      return -1;
	    }
	}
      else break;
    }
  while(++i < 32768);

  return fd;
}

uint16_t in_cksum(const void *buf, const size_t len)
{
  uint16_t *w = (uint16_t *)buf;
  size_t l = len;
  int sum = 0;

  while(l > 1)
    {
      sum += *w++;
      l   -= 2;
    }

  if(l != 0)
    {
      sum += ((uint8_t *)w)[0];
    }

  sum  = (sum >> 16) + (sum & 0xffff);
  sum += (sum >> 16);

  return ~sum;
}

int main(int argc, char *argv[])
{
  struct ifreq    ifreq;
  char           *ifname, *src, *dst;
  int             ifindex;
  char            dev[16];
  int             fd;
  uint8_t        *pktbuf;
  struct ip      *ip;
  struct icmp    *icmp;
  ssize_t         wb, len = sizeof(int);
  int             af;

  if(argc != 5)
    {
      fprintf(stderr, "usage: bpf_null_tx <if> <src> <dst> <len>\n");
      return -1;
    }
  ifname = argv[1];
  src    = argv[2];
  dst    = argv[3];
  len    = sizeof(int) + atoi(argv[4]);

  printf("ifname: %s, src: %s, dst: %s, len: %d\n", ifname, src, dst, len);

  if((ifindex = if_nametoindex(ifname)) == 0)
    {
      perror("if_nametoindex");
      return -1;
    }

  if((pktbuf = malloc(len)) == NULL)
    {
      perror("malloc failed");
      return -1;
    }
  memset(pktbuf, 0, len);

  printf("ifindex: %d\n", ifindex);

  if((fd = dl_bpf_open_dev(dev, sizeof(dev))) == -1)
    {
      perror("could not open device");
      return -1;
    }

  /* set the interface that will be sniffed */
  memset(&ifreq, 0, sizeof(ifreq));
  strcpy(ifreq.ifr_name, ifname);
  if(ioctl(fd, BIOCSETIF, &ifreq) == -1)
    {
      perror("BIOCSETIF failed");
      close(fd);
      return -1;
    }

  af = AF_INET;

  memcpy(pktbuf, &af, sizeof(int));

  ip = (struct ip *)(pktbuf + sizeof(int));
  ip->ip_v   = 4;
  ip->ip_hl  = 5;
  ip->ip_tos = 0;
  ip->ip_len = htons(len - sizeof(int));
  ip->ip_id  = 0;
  ip->ip_off = htons(IP_DF);
  ip->ip_ttl = 255;
  ip->ip_p   = IPPROTO_ICMP;
  ip->ip_sum = 0;
  inet_pton(AF_INET, src, &ip->ip_src);
  inet_pton(AF_INET, dst, &ip->ip_dst);
  ip->ip_sum = in_cksum(ip, sizeof(struct ip));

  icmp = (struct icmp *)(pktbuf + sizeof(int) + sizeof(struct ip));
  icmp->icmp_type  = ICMP_ECHO;
  icmp->icmp_code  = 0;
  icmp->icmp_cksum = 0;
  icmp->icmp_id    = getpid();
  icmp->icmp_seq   = 0;
  icmp->icmp_cksum = in_cksum(icmp, len - sizeof(int) - sizeof(struct ip));

  if((wb = write(fd, pktbuf, len)) < len)
    {
      if(wb == -1)
	{
	  perror("could not send packet");
	}
      else
	{
	  fprintf(stderr, "%d bytes sent of %d total\n", wb, len);
	}

      return -1;
    }

  printf("sent %d bytes\n", wb);

  return 0;
}
>Fix:
Index: net/bpf.c
===================================================================
RCS file: /home/ncvs/src/sys/net/bpf.c,v
retrieving revision 1.151
diff -u -p -r1.151 bpf.c
--- net/bpf.c	10 Jun 2005 16:49:18 -0000	1.151
+++ net/bpf.c	12 Jun 2005 05:10:07 -0000
@@ -106,8 +106,8 @@ static void	bpf_attachd(struct bpf_d *d,
 static void	bpf_detachd(struct bpf_d *d);
 static void	bpf_freed(struct bpf_d *);
 static void	bpf_mcopy(const void *, void *, size_t);
-static int	bpf_movein(struct uio *, int,
-		    struct mbuf **, struct sockaddr *, int *);
+static int	bpf_movein(struct uio *, int, int,
+		    struct mbuf **, struct sockaddr *);
 static int	bpf_setif(struct bpf_d *, struct ifreq *);
 static void	bpf_timed_out(void *);
 static __inline void
@@ -148,9 +148,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, mtu, mp, sockp)
 	struct uio *uio;
-	int linktype, *datlen;
+	int linktype;
+	int mtu;
 	struct mbuf **mp;
 	struct sockaddr *sockp;
 {
@@ -187,11 +188,19 @@ 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:
+		/*
+		 * null interface types require a 4 byte pseudo header which
+		 * corresponds to the address family of the packet
+		 */
+		sockp->sa_family = AF_UNSPEC;
+		hlen = 4;
+		break;
+
 	case DLT_ATM_RFC1483:
 		/*
 		 * en atm driver requires 4-byte atm pseudo header.
@@ -212,7 +221,10 @@ bpf_movein(uio, linktype, mp, sockp, dat
 	}
 
 	len = uio->uio_resid;
-	*datlen = len - hlen;
+
+	if (len - hlen > mtu)
+		return (EMSGSIZE);
+
 	if ((unsigned)len > MCLBYTES)
 		return (EIO);
 
@@ -569,7 +581,6 @@ bpfwrite(dev, uio, ioflag)
 	struct mbuf *m;
 	int error;
 	struct sockaddr dst;
-	int datlen;
 
 	if (d->bd_bif == NULL)
 		return (ENXIO);
@@ -583,15 +594,10 @@ bpfwrite(dev, uio, ioflag)
 		return (0);
 
 	bzero(&dst, sizeof(dst));
-	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen);
+	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, ifp->if_mtu, &m, &dst);
 	if (error)
 		return (error);
 
-	if (datlen > ifp->if_mtu) {
-		m_freem(m);
-		return (EMSGSIZE);
-	}
-
 	if (d->bd_hdrcmplt)
 		dst.sa_family = pseudo_AF_HDRCMPLT;
 
Index: net/if_disc.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_disc.c,v
retrieving revision 1.47
diff -u -p -r1.47 if_disc.c
--- net/if_disc.c	10 Jun 2005 16:49:18 -0000	1.47
+++ net/if_disc.c	12 Jun 2005 05:10:07 -0000
@@ -102,7 +102,7 @@ disc_clone_create(struct if_clone *ifc, 
 	ifp->if_addrlen = 0;
 	ifp->if_snd.ifq_maxlen = 20;
 	if_attach(ifp);
-	bpfattach(ifp, DLT_NULL, sizeof(u_int));
+	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
 	mtx_lock(&disc_mtx);
 	LIST_INSERT_HEAD(&disc_softc_list, sc, sc_list);
 	mtx_unlock(&disc_mtx);
@@ -176,15 +176,13 @@ static int
 discoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
     struct rtentry *rt)
 {
-
 	M_ASSERTPKTHDR(m);
 
 	/* BPF write needs to be handled specially */
 	if (dst->sa_family == AF_UNSPEC) {
-		dst->sa_family = *(mtod(m, int *));
-		m->m_len -= sizeof(int);
-		m->m_pkthdr.len -= sizeof(int);
-		m->m_data += sizeof(int);
+		u_int32_t af;
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
 	}
 
 	if (ifp->if_bpf) {
Index: net/if_faith.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_faith.c,v
retrieving revision 1.35
diff -u -p -r1.35 if_faith.c
--- net/if_faith.c	10 Jun 2005 16:49:18 -0000	1.35
+++ net/if_faith.c	12 Jun 2005 05:10:09 -0000
@@ -187,7 +187,7 @@ faith_clone_create(ifc, unit)
 	ifp->if_addrlen = 0;
 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
 	if_attach(ifp);
-	bpfattach(ifp, DLT_NULL, sizeof(u_int));
+	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
 	mtx_lock(&faith_mtx);
 	LIST_INSERT_HEAD(&faith_softc_list, sc, sc_list);
 	mtx_unlock(&faith_mtx);
@@ -225,19 +225,18 @@ faithoutput(ifp, m, dst, rt)
 	struct rtentry *rt;
 {
 	int isr;
+	u_int32_t af;
 
 	M_ASSERTPKTHDR(m);
 
 	/* BPF write needs to be handled specially */
 	if (dst->sa_family == AF_UNSPEC) {
-		dst->sa_family = *(mtod(m, int *));
-		m->m_len -= sizeof(int);
-		m->m_pkthdr.len -= sizeof(int);
-		m->m_data += sizeof(int);
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
 	}
 
 	if (ifp->if_bpf) {
-		u_int32_t af = dst->sa_family;
+		af = dst->sa_family;
 		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
 	}
 
Index: net/if_gif.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_gif.c,v
retrieving revision 1.51
diff -u -p -r1.51 if_gif.c
--- net/if_gif.c	10 Jun 2005 16:49:18 -0000	1.51
+++ net/if_gif.c	12 Jun 2005 05:10:09 -0000
@@ -179,7 +179,7 @@ gifattach0(sc)
 	GIF2IFP(sc)->if_output = gif_output;
 	GIF2IFP(sc)->if_snd.ifq_maxlen = IFQ_MAXLEN;
 	if_attach(GIF2IFP(sc));
-	bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int));
+	bpfattach(GIF2IFP(sc), DLT_NULL, sizeof(u_int32_t));
 	if (ng_gif_attach_p != NULL)
 		(*ng_gif_attach_p)(GIF2IFP(sc));
 }
@@ -348,6 +348,7 @@ gif_output(ifp, m, dst, rt)
 	struct m_tag *mtag;
 	int error = 0;
 	int gif_called;
+	u_int32_t af;
 
 #ifdef MAC
 	error = mac_check_ifnet_transmit(ifp, m);
@@ -404,8 +405,14 @@ gif_output(ifp, m, dst, rt)
 		goto end;
 	}
 
+	/* BPF write needs to be handled specially */
+	if (dst->sa_family == AF_UNSPEC) {
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
+	}
+
 	if (ifp->if_bpf) {
-		u_int32_t af = dst->sa_family;
+		af = dst->sa_family;
 		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
 	}
 	ifp->if_opackets++;	
Index: net/if_gre.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_gre.c,v
retrieving revision 1.30
diff -u -p -r1.30 if_gre.c
--- net/if_gre.c	10 Jun 2005 16:49:18 -0000	1.30
+++ net/if_gre.c	12 Jun 2005 05:10:11 -0000
@@ -233,6 +233,7 @@ gre_output(struct ifnet *ifp, struct mbu
 	struct ip *ip;
 	u_int16_t etype = 0;
 	struct mobile_h mob_h;
+	u_int32_t af;
 
 	/*
 	 * gre may cause infinite recursion calls when misconfigured.
@@ -256,8 +257,14 @@ gre_output(struct ifnet *ifp, struct mbu
 	gh = NULL;
 	ip = NULL;
 
+	/* BPF write needs to be handled specially */
+	if (dst->sa_family == AF_UNSPEC) {
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
+	}
+
 	if (ifp->if_bpf) {
-		u_int32_t af = dst->sa_family;
+		af = dst->sa_family;
 		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
 	}
 
Index: net/if_loop.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_loop.c,v
retrieving revision 1.105
diff -u -p -r1.105 if_loop.c
--- net/if_loop.c	10 Jun 2005 16:49:18 -0000	1.105
+++ net/if_loop.c	12 Jun 2005 05:10:11 -0000
@@ -156,7 +156,7 @@ lo_clone_create(ifc, unit)
 	ifp->if_snd.ifq_maxlen = ifqmaxlen;
 	ifp->if_softc = sc;
 	if_attach(ifp);
-	bpfattach(ifp, DLT_NULL, sizeof(u_int));
+	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
 	mtx_lock(&lo_mtx);
 	LIST_INSERT_HEAD(&lo_list, sc, sc_next);
 	mtx_unlock(&lo_mtx);
@@ -199,6 +199,8 @@ looutput(ifp, m, dst, rt)
 	struct sockaddr *dst;
 	register struct rtentry *rt;
 {
+	u_int32_t af;
+
 	M_ASSERTPKTHDR(m); /* check if we have the packet header */
 
 	if (rt && rt->rt_flags & (RTF_REJECT|RTF_BLACKHOLE)) {
@@ -209,6 +211,13 @@ looutput(ifp, m, dst, rt)
 
 	ifp->if_opackets++;
 	ifp->if_obytes += m->m_pkthdr.len;
+
+	/* BPF write needs to be handled specially */
+	if(dst->sa_family == AF_UNSPEC) {
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
+	}
+
 #if 1	/* XXX */
 	switch (dst->sa_family) {
 	case AF_INET:
@@ -249,15 +258,6 @@ if_simloop(ifp, m, af, hlen)
 	m_tag_delete_nonpersistent(m);
 	m->m_pkthdr.rcvif = ifp;
 
-	/* BPF write needs to be handled specially */
-	if (af == AF_UNSPEC) {
-		KASSERT(m->m_len >= sizeof(int), ("if_simloop: m_len"));
-		af = *(mtod(m, int *));
-		m->m_len -= sizeof(int);
-		m->m_pkthdr.len -= sizeof(int);
-		m->m_data += sizeof(int);
-	}
-
 	/* Let BPF see incoming packet */
 	if (ifp->if_bpf) {
 		if (ifp->if_bpf->bif_dlt == DLT_NULL) {
Index: net/if_stf.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_stf.c,v
retrieving revision 1.48
diff -u -p -r1.48 if_stf.c
--- net/if_stf.c	10 Jun 2005 16:49:18 -0000	1.48
+++ net/if_stf.c	12 Jun 2005 05:10:12 -0000
@@ -243,7 +243,7 @@ stf_clone_create(struct if_clone *ifc, c
 	ifp->if_output = stf_output;
 	ifp->if_snd.ifq_maxlen = IFQ_MAXLEN;
 	if_attach(ifp);
-	bpfattach(ifp, DLT_NULL, sizeof(u_int));
+	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
 	mtx_lock(&stf_mtx);
 	LIST_INSERT_HEAD(&stf_softc_list, sc, sc_list);
 	mtx_unlock(&stf_mtx);
@@ -436,6 +436,7 @@ stf_output(ifp, m, dst, rt)
 	struct ip *ip;
 	struct ip6_hdr *ip6;
 	struct in6_ifaddr *ia6;
+	u_int32_t af;
 #ifdef MAC
 	int error;
 
@@ -479,6 +480,16 @@ stf_output(ifp, m, dst, rt)
 	tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
 
 	/*
+	 * BPF write needs to be handled specially.
+	 * this is a null operation.  nothing here checks the dst->sa_family
+	 * member.
+	 */
+	if (dst->sa_family == AF_UNSPEC) {
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
+	}
+
+	/*
 	 * Pickup the right outer dst addr from the list of candidates.
 	 * ip6_dst has priority as it may be able to give us shorter IPv4 hops.
 	 */
@@ -502,7 +513,7 @@ stf_output(ifp, m, dst, rt)
 		 * will only read from the mbuf (i.e., it won't
 		 * try to free it or keep a pointer a to it).
 		 */
-		u_int32_t af = AF_INET6;
+		af = AF_INET6;
 		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m);
 	}
 
Index: net/if_tun.c
===================================================================
RCS file: /home/ncvs/src/sys/net/if_tun.c,v
retrieving revision 1.151
diff -u -p -r1.151 if_tun.c
--- net/if_tun.c	10 Jun 2005 16:49:18 -0000	1.151
+++ net/if_tun.c	12 Jun 2005 05:10:12 -0000
@@ -285,7 +285,7 @@ tuncreate(struct cdev *dev)
 	IFQ_SET_READY(&ifp->if_snd);
 
 	if_attach(ifp);
-	bpfattach(ifp, DLT_NULL, sizeof(u_int));
+	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
 	dev->si_drv1 = sc;
 }
 
@@ -473,6 +473,7 @@ tunoutput(
 	struct tun_softc *tp = ifp->if_softc;
 	u_short cached_tun_flags;
 	int error;
+	u_int32_t af;
 
 	TUNDEBUG (ifp, "tunoutput\n");
 
@@ -501,14 +502,12 @@ tunoutput(
 
 	/* 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; 
 	}
 
 	if (ifp->if_bpf) {
-		uint32_t af = dst->sa_family;
+		af = dst->sa_family;
 		bpf_mtap2(ifp->if_bpf, &af, sizeof(af), m0);
 	}
 
Index: dev/iicbus/if_ic.c
===================================================================
RCS file: /home/ncvs/src/sys/dev/iicbus/if_ic.c,v
retrieving revision 1.22
diff -u -p -r1.22 if_ic.c
--- dev/iicbus/if_ic.c	10 Jun 2005 16:49:10 -0000	1.22
+++ dev/iicbus/if_ic.c	12 Jun 2005 05:10:15 -0000
@@ -374,7 +374,13 @@ icoutput(struct ifnet *ifp, struct mbuf 
 	int s, len, sent;
 	struct mbuf *mm;
 	u_char *cp;
-	u_int32_t hdr = dst->sa_family;
+	u_int32_t hdr;
+
+	/* BPF write needs to be handled specially */ 
+	if(dst->sa_family == AF_UNSPEC)
+		bcopy(dst->sa_data, &hdr, sizeof(hdr));
+	else 
+		hdr = dst->sa_family;
 
 	ifp->if_flags |= IFF_RUNNING;
 
Index: i4b/driver/i4b_ipr.c
===================================================================
RCS file: /home/ncvs/src/sys/i4b/driver/i4b_ipr.c,v
retrieving revision 1.32
diff -u -p -r1.32 i4b_ipr.c
--- i4b/driver/i4b_ipr.c	10 Jun 2005 16:49:18 -0000	1.32
+++ i4b/driver/i4b_ipr.c	12 Jun 2005 05:10:17 -0000
@@ -272,7 +272,7 @@ i4biprattach(void *dummy)
 		
 		if_attach(sc->sc_ifp);
 
-		bpfattach(sc->sc_ifp, DLT_NULL, sizeof(u_int));
+		bpfattach(sc->sc_ifp, DLT_NULL, sizeof(u_int32_t));
 	}
 }
 
@@ -293,6 +293,14 @@ i4biproutput(struct ifnet *ifp, struct m
 
 	sc = ifp->if_softc;
 	unit = ifp->if_dunit;
+
+	/* BPF write needs to be handled specially */
+	if(dst->sa_family == AF_UNSPEC)
+	{
+		u_int32_t af;
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
+	}
 
 	/* check for IP */
 	
Index: netgraph/ng_iface.c
===================================================================
RCS file: /home/ncvs/src/sys/netgraph/ng_iface.c,v
retrieving revision 1.42
diff -u -p -r1.42 ng_iface.c
--- netgraph/ng_iface.c	10 Jun 2005 16:49:21 -0000	1.42
+++ netgraph/ng_iface.c	12 Jun 2005 05:10:18 -0000
@@ -361,12 +361,9 @@ ng_iface_output(struct ifnet *ifp, struc
 
 	/* BPF writes need to be handled specially */
 	if (dst->sa_family == AF_UNSPEC) {
-		if (m->m_len < 4 && (m = m_pullup(m, 4)) == NULL)
-			return (ENOBUFS);
-		dst->sa_family = (sa_family_t)*mtod(m, int32_t *);
-		m->m_data += 4;
-		m->m_len -= 4;
-		m->m_pkthdr.len -= 4;
+		u_int32_t af;
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
 	}
 
 	/* Berkeley packet filter */
@@ -508,7 +505,7 @@ ng_iface_constructor(node_p node)
 
 	/* Attach the interface */
 	if_attach(ifp);
-	bpfattach(ifp, DLT_NULL, sizeof(u_int));
+	bpfattach(ifp, DLT_NULL, sizeof(u_int32_t));
 
 	/* Done */
 	return (0);
Index: netgraph/ng_sppp.c
===================================================================
RCS file: /home/ncvs/src/sys/netgraph/ng_sppp.c,v
retrieving revision 1.7
diff -u -p -r1.7 ng_sppp.c
--- netgraph/ng_sppp.c	10 Jun 2005 16:49:21 -0000	1.7
+++ netgraph/ng_sppp.c	12 Jun 2005 05:10:19 -0000
@@ -289,7 +289,7 @@ ng_sppp_constructor (node_p node)
 	/* Attach the interface */
 	sppp_attach (ifp);
 	if_attach (ifp);
-	bpfattach (ifp, DLT_NULL, sizeof(u_int));
+	bpfattach (ifp, DLT_NULL, sizeof(u_int32_t));
 
 	/* Done */
 	return (0);
Index: netinet/ip_carp.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/ip_carp.c,v
retrieving revision 1.25
diff -u -p -r1.25 ip_carp.c
--- netinet/ip_carp.c	10 Jun 2005 16:49:21 -0000	1.25
+++ netinet/ip_carp.c	12 Jun 2005 05:10:23 -0000
@@ -1930,6 +1930,13 @@ carp_looutput(struct ifnet *ifp, struct 
 
 	ifp->if_opackets++;
 	ifp->if_obytes += m->m_pkthdr.len;
+
+	if (dst->sa_family == AF_UNSPEC) {
+		u_int32_t af;
+		bcopy(dst->sa_data, &af, sizeof(af));
+		dst->sa_family = af;
+	}
+
 #if 1	/* XXX */
 	switch (dst->sa_family) {
 	case AF_INET:
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list