xref: /csrg-svn/sys/net/bpf.c (revision 55289)
151440Smccanne /*
251440Smccanne  * Copyright (c) 1990, 1991 Regents of the University of California.
347584Smccanne  * All rights reserved.
447584Smccanne  *
549343Sbostic  * This code is derived from the Stanford/CMU enet packet filter,
649343Sbostic  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
751425Smccanne  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
851425Smccanne  * Berkeley Laboratory.
947584Smccanne  *
1051440Smccanne  * %sccs.include.redist.c%
1149343Sbostic  *
12*55289Smckusick  *      @(#)bpf.c	7.12 (Berkeley) 07/16/92
1349343Sbostic  *
1449343Sbostic  * static char rcsid[] =
1551425Smccanne  * "$Header: bpf.c,v 1.33 91/10/27 21:21:58 mccanne Exp $";
1647584Smccanne  */
1747584Smccanne 
1847584Smccanne #include "bpfilter.h"
1947584Smccanne 
2051425Smccanne #if NBPFILTER > 0
2147584Smccanne 
2251425Smccanne #ifndef __GNUC__
2351425Smccanne #define inline
2451425Smccanne #else
2554970Smckusick #define inline __inline
2651425Smccanne #endif
2751425Smccanne 
2847584Smccanne #include <sys/param.h>
2947584Smccanne #include <sys/systm.h>
3047584Smccanne #include <sys/mbuf.h>
3147584Smccanne #include <sys/buf.h>
3247584Smccanne #include <sys/dir.h>
3353947Smccanne #include <sys/time.h>
3448932Smccanne #include <sys/proc.h>
3547584Smccanne #include <sys/user.h>
3647584Smccanne #include <sys/ioctl.h>
3747584Smccanne #include <sys/map.h>
3847584Smccanne 
3947584Smccanne #include <sys/file.h>
4051425Smccanne #if defined(sparc) && BSD < 199103
4147584Smccanne #include <sys/stream.h>
4247584Smccanne #endif
4347584Smccanne #include <sys/tty.h>
4447584Smccanne #include <sys/uio.h>
4547584Smccanne 
4647584Smccanne #include <sys/protosw.h>
4747584Smccanne #include <sys/socket.h>
4847584Smccanne #include <net/if.h>
4947584Smccanne 
5047584Smccanne #include <net/bpf.h>
5147584Smccanne #include <net/bpfdesc.h>
5247584Smccanne 
5347584Smccanne #include <sys/errno.h>
5447584Smccanne 
5547584Smccanne #include <netinet/in.h>
5647584Smccanne #include <netinet/if_ether.h>
5747584Smccanne #include <sys/kernel.h>
5847584Smccanne 
5951425Smccanne /*
6051425Smccanne  * Older BSDs don't have kernel malloc.
6151425Smccanne  */
6251425Smccanne #if BSD < 199103
6351425Smccanne extern bcopy();
6451425Smccanne static caddr_t bpf_alloc();
6553947Smccanne #include <net/bpf_compat.h>
6651425Smccanne #define BPF_BUFSIZE (MCLBYTES-8)
6753947Smccanne #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio)
6851425Smccanne #else
6951425Smccanne #define BPF_BUFSIZE 4096
7053947Smccanne #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio)
7151425Smccanne #endif
7251425Smccanne 
7347584Smccanne #define PRINET  26			/* interruptible */
7447584Smccanne 
7547584Smccanne /*
7648932Smccanne  * The default read buffer size is patchable.
7748932Smccanne  */
7851425Smccanne int bpf_bufsize = BPF_BUFSIZE;
7948932Smccanne 
8048932Smccanne /*
8149202Smccanne  *  bpf_iflist is the list of interfaces; each corresponds to an ifnet
8249202Smccanne  *  bpf_dtab holds the descriptors, indexed by minor device #
8347584Smccanne  */
8453947Smccanne struct bpf_if	*bpf_iflist;
8553947Smccanne struct bpf_d	bpf_dtab[NBPFILTER];
8647584Smccanne 
8747584Smccanne static void	bpf_ifname();
8847584Smccanne static void	catchpacket();
8953947Smccanne static void	bpf_freed();
9047584Smccanne static int	bpf_setif();
9147584Smccanne static int	bpf_initd();
9253947Smccanne static int	bpf_allocbufs();
9347584Smccanne 
9447584Smccanne static int
95*55289Smckusick bpf_movein(uio, linktype, mp, sockp, datlen)
9647584Smccanne 	register struct uio *uio;
97*55289Smckusick 	int linktype, *datlen;
9847584Smccanne 	register struct mbuf **mp;
9947584Smccanne 	register struct sockaddr *sockp;
10047584Smccanne {
10147584Smccanne 	struct mbuf *m;
10247584Smccanne 	int error;
10347584Smccanne 	int len;
10447584Smccanne 	int hlen;
10547584Smccanne 
10647584Smccanne 	/*
10747584Smccanne 	 * Build a sockaddr based on the data link layer type.
10847584Smccanne 	 * We do this at this level because the ethernet header
10947584Smccanne 	 * is copied directly into the data field of the sockaddr.
11047584Smccanne 	 * In the case of SLIP, there is no header and the packet
11147584Smccanne 	 * is forwarded as is.
11247584Smccanne 	 * Also, we are careful to leave room at the front of the mbuf
11347584Smccanne 	 * for the link level header.
11447584Smccanne 	 */
11547584Smccanne 	switch (linktype) {
11653947Smccanne 
11747584Smccanne 	case DLT_SLIP:
11847584Smccanne 		sockp->sa_family = AF_INET;
11947584Smccanne 		hlen = 0;
12047584Smccanne 		break;
12147584Smccanne 
12247584Smccanne 	case DLT_EN10MB:
12347584Smccanne 		sockp->sa_family = AF_UNSPEC;
12447584Smccanne 		/* XXX Would MAXLINKHDR be better? */
12547584Smccanne 		hlen = sizeof(struct ether_header);
12647584Smccanne 		break;
12747584Smccanne 
12853947Smccanne 	case DLT_FDDI:
12947584Smccanne 		sockp->sa_family = AF_UNSPEC;
13047584Smccanne 		/* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
13147584Smccanne 		hlen = 24;
13247584Smccanne 		break;
13347584Smccanne 
13453947Smccanne 	case DLT_NULL:
13553947Smccanne 		sockp->sa_family = AF_UNSPEC;
13653947Smccanne 		hlen = 0;
13753947Smccanne 		break;
13853947Smccanne 
13947584Smccanne 	default:
14048932Smccanne 		return (EIO);
14147584Smccanne 	}
14247584Smccanne 
14347584Smccanne 	len = uio->uio_resid;
144*55289Smckusick 	*datlen = len - hlen;
14547584Smccanne 	if ((unsigned)len > MCLBYTES)
14648932Smccanne 		return (EIO);
14747584Smccanne 
14847584Smccanne 	MGET(m, M_WAIT, MT_DATA);
14947584Smccanne 	if (m == 0)
15048932Smccanne 		return (ENOBUFS);
15147584Smccanne 	if (len > MLEN) {
15251425Smccanne #if BSD >= 199103
15348932Smccanne 		MCLGET(m, M_WAIT);
15448932Smccanne 		if ((m->m_flags & M_EXT) == 0) {
15551425Smccanne #else
15651425Smccanne 		MCLGET(m);
15753947Smccanne 		if (m->m_len != MCLBYTES) {
15851425Smccanne #endif
15953947Smccanne 			error = ENOBUFS;
16047584Smccanne 			goto bad;
16147584Smccanne 		}
16247584Smccanne 	}
16347584Smccanne 	m->m_len = len;
16447584Smccanne 	*mp = m;
16547584Smccanne 	/*
16647584Smccanne 	 * Make room for link header.
16747584Smccanne 	 */
16853947Smccanne 	if (hlen != 0) {
16947584Smccanne 		m->m_len -= hlen;
17051425Smccanne #if BSD >= 199103
17148932Smccanne 		m->m_data += hlen; /* XXX */
17251425Smccanne #else
17351425Smccanne 		m->m_off += hlen;
17451425Smccanne #endif
17553947Smccanne 		error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio);
17647584Smccanne 		if (error)
17747584Smccanne 			goto bad;
17847584Smccanne 	}
17953947Smccanne 	error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio);
18053947Smccanne 	if (!error)
18148932Smccanne 		return (0);
18247584Smccanne  bad:
18347584Smccanne 	m_freem(m);
18448932Smccanne 	return (error);
18547584Smccanne }
18647584Smccanne 
18747584Smccanne /*
18851425Smccanne  * Attach file to the bpf interface, i.e. make d listen on bp.
18947584Smccanne  * Must be called at splimp.
19047584Smccanne  */
19147584Smccanne static void
19247584Smccanne bpf_attachd(d, bp)
19347584Smccanne 	struct bpf_d *d;
19447584Smccanne 	struct bpf_if *bp;
19547584Smccanne {
19651425Smccanne 	/*
19751425Smccanne 	 * Point d at bp, and add d to the interface's list of listeners.
19851425Smccanne 	 * Finally, point the driver's bpf cookie at the interface so
19951425Smccanne 	 * it will divert packets to bpf.
20051425Smccanne 	 */
20147584Smccanne 	d->bd_bif = bp;
20247584Smccanne 	d->bd_next = bp->bif_dlist;
20347584Smccanne 	bp->bif_dlist = d;
20447584Smccanne 
20547584Smccanne 	*bp->bif_driverp = bp;
20647584Smccanne }
20747584Smccanne 
20851425Smccanne /*
20951425Smccanne  * Detach a file from its interface.
21051425Smccanne  */
21147584Smccanne static void
21247584Smccanne bpf_detachd(d)
21347584Smccanne 	struct bpf_d *d;
21447584Smccanne {
21547584Smccanne 	struct bpf_d **p;
21647584Smccanne 	struct bpf_if *bp;
21747584Smccanne 
21847584Smccanne 	bp = d->bd_bif;
21947584Smccanne 	/*
22047584Smccanne 	 * Check if this descriptor had requested promiscuous mode.
22147584Smccanne 	 * If so, turn it off.
22247584Smccanne 	 */
22347584Smccanne 	if (d->bd_promisc) {
22447584Smccanne 		d->bd_promisc = 0;
22547584Smccanne 		if (ifpromisc(bp->bif_ifp, 0))
22647584Smccanne 			/*
22747584Smccanne 			 * Something is really wrong if we were able to put
22847584Smccanne 			 * the driver into promiscuous mode, but can't
22947584Smccanne 			 * take it out.
23047584Smccanne 			 */
23151425Smccanne 			panic("bpf: ifpromisc failed");
23247584Smccanne 	}
23351425Smccanne 	/* Remove d from the interface's descriptor list. */
23447584Smccanne 	p = &bp->bif_dlist;
23547584Smccanne 	while (*p != d) {
23647584Smccanne 		p = &(*p)->bd_next;
23747584Smccanne 		if (*p == 0)
23847584Smccanne 			panic("bpf_detachd: descriptor not in list");
23947584Smccanne 	}
24047584Smccanne 	*p = (*p)->bd_next;
24147584Smccanne 	if (bp->bif_dlist == 0)
24247584Smccanne 		/*
24347584Smccanne 		 * Let the driver know that there are no more listeners.
24447584Smccanne 		 */
24547584Smccanne 		*d->bd_bif->bif_driverp = 0;
24647584Smccanne 	d->bd_bif = 0;
24747584Smccanne }
24847584Smccanne 
24947584Smccanne 
25047584Smccanne /*
25153947Smccanne  * Mark a descriptor free by making it point to itself.
25247584Smccanne  * This is probably cheaper than marking with a constant since
25347584Smccanne  * the address should be in a register anyway.
25447584Smccanne  */
25547584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next)
25647584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d))
25747584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0)
25847584Smccanne 
25947584Smccanne /*
26053947Smccanne  * Open ethernet device.  Returns ENXIO for illegal minor device number,
26153947Smccanne  * EBUSY if file is open by another process.
26247584Smccanne  */
26347584Smccanne /* ARGSUSED */
26447584Smccanne int
26547584Smccanne bpfopen(dev, flag)
26647584Smccanne 	dev_t dev;
26747584Smccanne 	int flag;
26847584Smccanne {
26947584Smccanne 	register struct bpf_d *d;
27053947Smccanne 
27147584Smccanne 	if (minor(dev) >= NBPFILTER)
27248932Smccanne 		return (ENXIO);
27347584Smccanne 	/*
27447584Smccanne 	 * Each minor can be opened by only one process.  If the requested
27547584Smccanne 	 * minor is in use, return EBUSY.
27647584Smccanne 	 */
27747584Smccanne 	d = &bpf_dtab[minor(dev)];
27853947Smccanne 	if (!D_ISFREE(d))
27948932Smccanne 		return (EBUSY);
28047584Smccanne 
28153947Smccanne 	/* Mark "free" and do most initialization. */
28253947Smccanne 	bzero((char *)d, sizeof(*d));
28353947Smccanne 	d->bd_bufsize = bpf_bufsize;
28453947Smccanne 
28548932Smccanne 	return (0);
28647584Smccanne }
28747584Smccanne 
28847584Smccanne /*
28947584Smccanne  * Close the descriptor by detaching it from its interface,
29047584Smccanne  * deallocating its buffers, and marking it free.
29147584Smccanne  */
29247584Smccanne /* ARGSUSED */
29353947Smccanne int
29447584Smccanne bpfclose(dev, flag)
29547584Smccanne 	dev_t dev;
29647584Smccanne 	int flag;
29747584Smccanne {
29847584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
29953947Smccanne 	register int s;
30047584Smccanne 
30147584Smccanne 	s = splimp();
30247584Smccanne 	if (d->bd_bif)
30347584Smccanne 		bpf_detachd(d);
30447584Smccanne 	splx(s);
30553947Smccanne 	bpf_freed(d);
30647584Smccanne 
30753947Smccanne 	return (0);
30847584Smccanne }
30947584Smccanne 
31053947Smccanne /*
31153947Smccanne  * Support for SunOS, which does not have tsleep.
31253947Smccanne  */
31351425Smccanne #if BSD < 199103
31451425Smccanne static
31551425Smccanne bpf_timeout(arg)
31651425Smccanne 	caddr_t arg;
31751425Smccanne {
31851425Smccanne 	struct bpf_d *d = (struct bpf_d *)arg;
31951425Smccanne 	d->bd_timedout = 1;
32051425Smccanne 	wakeup(arg);
32151425Smccanne }
32251425Smccanne 
32353947Smccanne #define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan)
32453947Smccanne 
32553947Smccanne int
32653947Smccanne bpf_sleep(d)
32753947Smccanne 	register struct bpf_d *d;
32851425Smccanne {
32953947Smccanne 	register int rto = d->bd_rtout;
33053947Smccanne 	register int st;
33151425Smccanne 
33253947Smccanne 	if (rto != 0) {
33351425Smccanne 		d->bd_timedout = 0;
33453947Smccanne 		timeout(bpf_timeout, (caddr_t)d, rto);
33551425Smccanne 	}
33653947Smccanne 	st = sleep((caddr_t)d, PRINET|PCATCH);
33753947Smccanne 	if (rto != 0) {
33853947Smccanne 		if (d->bd_timedout == 0)
33953947Smccanne 			untimeout(bpf_timeout, (caddr_t)d);
34053947Smccanne 		else if (st == 0)
34151425Smccanne 			return EWOULDBLOCK;
34251425Smccanne 	}
34353947Smccanne 	return (st != 0) ? EINTR : 0;
34451425Smccanne }
34553947Smccanne #else
34653947Smccanne #define BPF_SLEEP tsleep
34751425Smccanne #endif
34851425Smccanne 
34947584Smccanne /*
35048932Smccanne  * Rotate the packet buffers in descriptor d.  Move the store buffer
35153947Smccanne  * into the hold slot, and the free buffer into the store slot.
35248932Smccanne  * Zero the length of the new store buffer.
35348932Smccanne  */
35448932Smccanne #define ROTATE_BUFFERS(d) \
35548932Smccanne 	(d)->bd_hbuf = (d)->bd_sbuf; \
35648932Smccanne 	(d)->bd_hlen = (d)->bd_slen; \
35748932Smccanne 	(d)->bd_sbuf = (d)->bd_fbuf; \
35848932Smccanne 	(d)->bd_slen = 0; \
35953947Smccanne 	(d)->bd_fbuf = 0;
36048932Smccanne /*
36147584Smccanne  *  bpfread - read next chunk of packets from buffers
36247584Smccanne  */
36347584Smccanne int
36447584Smccanne bpfread(dev, uio)
36547584Smccanne 	dev_t dev;
36647584Smccanne 	register struct uio *uio;
36747584Smccanne {
36847584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
36947584Smccanne 	int error;
37047584Smccanne 	int s;
37147584Smccanne 
37247584Smccanne 	/*
37353947Smccanne 	 * Restrict application to use a buffer the same size as
37447584Smccanne 	 * as kernel buffers.
37547584Smccanne 	 */
37648932Smccanne 	if (uio->uio_resid != d->bd_bufsize)
37749202Smccanne 		return (EINVAL);
37847584Smccanne 
37947584Smccanne 	s = splimp();
38047584Smccanne 	/*
38153947Smccanne 	 * If the hold buffer is empty, then do a timed sleep, which
38253947Smccanne 	 * ends when the timeout expires or when enough packets
38353947Smccanne 	 * have arrived to fill the store buffer.
38447584Smccanne 	 */
38547584Smccanne 	while (d->bd_hbuf == 0) {
38648932Smccanne 		if (d->bd_immediate && d->bd_slen != 0) {
38747584Smccanne 			/*
38847584Smccanne 			 * A packet(s) either arrived since the previous
38947584Smccanne 			 * read or arrived while we were asleep.
39047584Smccanne 			 * Rotate the buffers and return what's here.
39147584Smccanne 			 */
39248932Smccanne 			ROTATE_BUFFERS(d);
39347584Smccanne 			break;
39447584Smccanne 		}
39553947Smccanne 		error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf",
39653947Smccanne 				  d->bd_rtout);
39748932Smccanne 		if (error == EINTR || error == ERESTART) {
39848932Smccanne 			splx(s);
39948932Smccanne 			return (error);
40047584Smccanne 		}
40148932Smccanne 		if (error == EWOULDBLOCK) {
40247584Smccanne 			/*
40347584Smccanne 			 * On a timeout, return what's in the buffer,
40448932Smccanne 			 * which may be nothing.  If there is something
40548932Smccanne 			 * in the store buffer, we can rotate the buffers.
40647584Smccanne 			 */
40747584Smccanne 			if (d->bd_hbuf)
40847584Smccanne 				/*
40953947Smccanne 				 * We filled up the buffer in between
41047584Smccanne 				 * getting the timeout and arriving
41147584Smccanne 				 * here, so we don't need to rotate.
41247584Smccanne 				 */
41347584Smccanne 				break;
41447584Smccanne 
41548932Smccanne 			if (d->bd_slen == 0) {
41647584Smccanne 				splx(s);
41748932Smccanne 				return (0);
41847584Smccanne 			}
41948932Smccanne 			ROTATE_BUFFERS(d);
42047584Smccanne 			break;
42147584Smccanne 		}
42247584Smccanne 	}
42347584Smccanne 	/*
42447584Smccanne 	 * At this point, we know we have something in the hold slot.
42547584Smccanne 	 */
42647584Smccanne 	splx(s);
42753947Smccanne 
42853947Smccanne 	/*
42947584Smccanne 	 * Move data from hold buffer into user space.
43047584Smccanne 	 * We know the entire buffer is transferred since
43148932Smccanne 	 * we checked above that the read buffer is bpf_bufsize bytes.
43247584Smccanne 	 */
43353947Smccanne 	error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio);
43453947Smccanne 
43547584Smccanne 	s = splimp();
43648932Smccanne 	d->bd_fbuf = d->bd_hbuf;
43748932Smccanne 	d->bd_hbuf = 0;
43853947Smccanne 	d->bd_hlen = 0;
43947584Smccanne 	splx(s);
44053947Smccanne 
44148932Smccanne 	return (error);
44247584Smccanne }
44347584Smccanne 
44447584Smccanne 
44547584Smccanne /*
44653947Smccanne  * If there are processes sleeping on this descriptor, wake them up.
44747584Smccanne  */
44847584Smccanne static inline void
44947584Smccanne bpf_wakeup(d)
45047584Smccanne 	register struct bpf_d *d;
45147584Smccanne {
45248932Smccanne 	wakeup((caddr_t)d);
45353947Smccanne #if BSD >= 199103
45453947Smccanne 	selwakeup(&d->bd_sel);
45553947Smccanne 	/* XXX */
45653947Smccanne 	d->bd_sel.si_pid = 0;
45753947Smccanne #else
45853947Smccanne 	if (d->bd_selproc) {
45953947Smccanne 		selwakeup(d->bd_selproc, (int)d->bd_selcoll);
46053947Smccanne 		d->bd_selcoll = 0;
46153947Smccanne 		d->bd_selproc = 0;
46253947Smccanne 	}
46353947Smccanne #endif
46447584Smccanne }
46547584Smccanne 
46647584Smccanne int
46747584Smccanne bpfwrite(dev, uio)
46847584Smccanne 	dev_t dev;
46947584Smccanne 	struct uio *uio;
47047584Smccanne {
47147584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
47247584Smccanne 	struct ifnet *ifp;
47347584Smccanne 	struct mbuf *m;
47447584Smccanne 	int error, s;
47547584Smccanne 	static struct sockaddr dst;
476*55289Smckusick 	int datlen;
47747584Smccanne 
47847584Smccanne 	if (d->bd_bif == 0)
47948932Smccanne 		return (ENXIO);
48047584Smccanne 
48147584Smccanne 	ifp = d->bd_bif->bif_ifp;
48247584Smccanne 
48347584Smccanne 	if (uio->uio_resid == 0)
48448932Smccanne 		return (0);
48547584Smccanne 
486*55289Smckusick 	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen);
48747584Smccanne 	if (error)
48848932Smccanne 		return (error);
48947584Smccanne 
490*55289Smckusick 	if (datlen > ifp->if_mtu)
491*55289Smckusick 		return (EMSGSIZE);
492*55289Smckusick 
49347584Smccanne 	s = splnet();
49451425Smccanne #if BSD >= 199103
49553947Smccanne 	error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0);
49651425Smccanne #else
49747584Smccanne 	error = (*ifp->if_output)(ifp, m, &dst);
49851425Smccanne #endif
49947584Smccanne 	splx(s);
50047584Smccanne 	/*
50153947Smccanne 	 * The driver frees the mbuf.
50247584Smccanne 	 */
50348932Smccanne 	return (error);
50447584Smccanne }
50547584Smccanne 
50647584Smccanne /*
50753947Smccanne  * Reset a descriptor by flushing its packet buffer and clearing the
50853947Smccanne  * receive and drop counts.  Should be called at splimp.
50947584Smccanne  */
51047584Smccanne static void
51147584Smccanne reset_d(d)
51247584Smccanne 	struct bpf_d *d;
51347584Smccanne {
51447584Smccanne 	if (d->bd_hbuf) {
51547584Smccanne 		/* Free the hold buffer. */
51647584Smccanne 		d->bd_fbuf = d->bd_hbuf;
51747584Smccanne 		d->bd_hbuf = 0;
51847584Smccanne 	}
51948932Smccanne 	d->bd_slen = 0;
52053947Smccanne 	d->bd_hlen = 0;
52147584Smccanne 	d->bd_rcount = 0;
52247584Smccanne 	d->bd_dcount = 0;
52347584Smccanne }
52447584Smccanne 
52547584Smccanne /*
52647584Smccanne  *  FIONREAD		Check for read packet available.
52747584Smccanne  *  SIOCGIFADDR		Get interface address - convenient hook to driver.
52847584Smccanne  *  BIOCGBLEN		Get buffer len [for read()].
52947584Smccanne  *  BIOCSETF		Set ethernet read filter.
53047584Smccanne  *  BIOCFLUSH		Flush read packet buffer.
53147584Smccanne  *  BIOCPROMISC		Put interface into promiscuous mode.
53249202Smccanne  *  BIOCGDLT		Get link layer type.
53347584Smccanne  *  BIOCGETIF		Get interface name.
53447584Smccanne  *  BIOCSETIF		Set interface.
53547584Smccanne  *  BIOCSRTIMEOUT	Set read timeout.
53647584Smccanne  *  BIOCGRTIMEOUT	Get read timeout.
53747584Smccanne  *  BIOCGSTATS		Get packet stats.
53847584Smccanne  *  BIOCIMMEDIATE	Set immediate mode.
53953947Smccanne  *  BIOCVERSION		Get filter language version.
54047584Smccanne  */
54147584Smccanne /* ARGSUSED */
54247584Smccanne int
54347584Smccanne bpfioctl(dev, cmd, addr, flag)
54447584Smccanne 	dev_t dev;
54547584Smccanne 	int cmd;
54647584Smccanne 	caddr_t addr;
54747584Smccanne 	int flag;
54847584Smccanne {
54947584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
55047584Smccanne 	int s, error = 0;
55147584Smccanne 
55247584Smccanne 	switch (cmd) {
55347584Smccanne 
55447584Smccanne 	default:
55547584Smccanne 		error = EINVAL;
55647584Smccanne 		break;
55747584Smccanne 
55847584Smccanne 	/*
55947584Smccanne 	 * Check for read packet available.
56047584Smccanne 	 */
56147584Smccanne 	case FIONREAD:
56247584Smccanne 		{
56347584Smccanne 			int n;
56453947Smccanne 
56547584Smccanne 			s = splimp();
56648932Smccanne 			n = d->bd_slen;
56753947Smccanne 			if (d->bd_hbuf)
56848932Smccanne 				n += d->bd_hlen;
56947584Smccanne 			splx(s);
57047584Smccanne 
57147584Smccanne 			*(int *)addr = n;
57247584Smccanne 			break;
57347584Smccanne 		}
57447584Smccanne 
57547584Smccanne 	case SIOCGIFADDR:
57647584Smccanne 		{
57747584Smccanne 			struct ifnet *ifp;
57847584Smccanne 
57947584Smccanne 			if (d->bd_bif == 0)
58047584Smccanne 				error = EINVAL;
58147584Smccanne 			else {
58247584Smccanne 				ifp = d->bd_bif->bif_ifp;
58353947Smccanne 				error = (*ifp->if_ioctl)(ifp, cmd, addr);
58447584Smccanne 			}
58547584Smccanne 			break;
58647584Smccanne 		}
58747584Smccanne 
58847584Smccanne 	/*
58947584Smccanne 	 * Get buffer len [for read()].
59047584Smccanne 	 */
59147584Smccanne 	case BIOCGBLEN:
59248932Smccanne 		*(u_int *)addr = d->bd_bufsize;
59347584Smccanne 		break;
59447584Smccanne 
59547584Smccanne 	/*
59653947Smccanne 	 * Set buffer length.
59753947Smccanne 	 */
59853947Smccanne 	case BIOCSBLEN:
59953947Smccanne #if BSD < 199103
60053947Smccanne 		error = EINVAL;
60153947Smccanne #else
60253947Smccanne 		if (d->bd_bif != 0)
60353947Smccanne 			error = EINVAL;
60453947Smccanne 		else {
60553947Smccanne 			register u_int size = *(u_int *)addr;
60653947Smccanne 
60753947Smccanne 			if (size > BPF_MAXBUFSIZE)
60853947Smccanne 				*(u_int *)addr = size = BPF_MAXBUFSIZE;
60953947Smccanne 			else if (size < BPF_MINBUFSIZE)
61053947Smccanne 				*(u_int *)addr = size = BPF_MINBUFSIZE;
61153947Smccanne 			d->bd_bufsize = size;
61253947Smccanne 		}
61353947Smccanne #endif
61453947Smccanne 		break;
61553947Smccanne 
61653947Smccanne 	/*
61751425Smccanne 	 * Set link layer read filter.
61847584Smccanne 	 */
61953947Smccanne 	case BIOCSETF:
62047584Smccanne 		error = bpf_setf(d, (struct bpf_program *)addr);
62147584Smccanne 		break;
62247584Smccanne 
62347584Smccanne 	/*
62447584Smccanne 	 * Flush read packet buffer.
62547584Smccanne 	 */
62647584Smccanne 	case BIOCFLUSH:
62747584Smccanne 		s = splimp();
62847584Smccanne 		reset_d(d);
62947584Smccanne 		splx(s);
63047584Smccanne 		break;
63147584Smccanne 
63247584Smccanne 	/*
63347584Smccanne 	 * Put interface into promiscuous mode.
63447584Smccanne 	 */
63547584Smccanne 	case BIOCPROMISC:
63647584Smccanne 		if (d->bd_bif == 0) {
63747584Smccanne 			/*
63847584Smccanne 			 * No interface attached yet.
63947584Smccanne 			 */
64047584Smccanne 			error = EINVAL;
64147584Smccanne 			break;
64247584Smccanne 		}
64347584Smccanne 		s = splimp();
64447584Smccanne 		if (d->bd_promisc == 0) {
64547584Smccanne 			error = ifpromisc(d->bd_bif->bif_ifp, 1);
64651425Smccanne 			if (error == 0)
64751425Smccanne 				d->bd_promisc = 1;
64847584Smccanne 		}
64947584Smccanne 		splx(s);
65047584Smccanne 		break;
65147584Smccanne 
65247584Smccanne 	/*
65347584Smccanne 	 * Get device parameters.
65447584Smccanne 	 */
65549202Smccanne 	case BIOCGDLT:
65647584Smccanne 		if (d->bd_bif == 0)
65747584Smccanne 			error = EINVAL;
65847584Smccanne 		else
65949202Smccanne 			*(u_int *)addr = d->bd_bif->bif_dlt;
66047584Smccanne 		break;
66147584Smccanne 
66247584Smccanne 	/*
66347584Smccanne 	 * Set interface name.
66447584Smccanne 	 */
66547584Smccanne 	case BIOCGETIF:
66647584Smccanne 		if (d->bd_bif == 0)
66747584Smccanne 			error = EINVAL;
66847584Smccanne 		else
66947584Smccanne 			bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
67047584Smccanne 		break;
67147584Smccanne 
67247584Smccanne 	/*
67347584Smccanne 	 * Set interface.
67447584Smccanne 	 */
67547584Smccanne 	case BIOCSETIF:
67647584Smccanne 		error = bpf_setif(d, (struct ifreq *)addr);
67747584Smccanne 		break;
67847584Smccanne 
67947584Smccanne 	/*
68047584Smccanne 	 * Set read timeout.
68147584Smccanne 	 */
68253947Smccanne 	case BIOCSRTIMEOUT:
68347584Smccanne 		{
68447584Smccanne 			struct timeval *tv = (struct timeval *)addr;
68547584Smccanne 			u_long msec;
68647584Smccanne 
68747584Smccanne 			/* Compute number of milliseconds. */
68847584Smccanne 			msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
68947584Smccanne 			/* Scale milliseconds to ticks.  Assume hard
69047584Smccanne 			   clock has millisecond or greater resolution
69147584Smccanne 			   (i.e. tick >= 1000).  For 10ms hardclock,
69247584Smccanne 			   tick/1000 = 10, so rtout<-msec/10. */
69347584Smccanne 			d->bd_rtout = msec / (tick / 1000);
69447584Smccanne 			break;
69547584Smccanne 		}
69647584Smccanne 
69747584Smccanne 	/*
69847584Smccanne 	 * Get read timeout.
69947584Smccanne 	 */
70053947Smccanne 	case BIOCGRTIMEOUT:
70147584Smccanne 		{
70247584Smccanne 			struct timeval *tv = (struct timeval *)addr;
70347584Smccanne 			u_long msec = d->bd_rtout;
70447584Smccanne 
70547584Smccanne 			msec *= tick / 1000;
70647584Smccanne 			tv->tv_sec = msec / 1000;
70747584Smccanne 			tv->tv_usec = msec % 1000;
70847584Smccanne 			break;
70947584Smccanne 		}
71047584Smccanne 
71147584Smccanne 	/*
71247584Smccanne 	 * Get packet stats.
71347584Smccanne 	 */
71447584Smccanne 	case BIOCGSTATS:
71547584Smccanne 		{
71647584Smccanne 			struct bpf_stat *bs = (struct bpf_stat *)addr;
71747584Smccanne 
71847584Smccanne 			bs->bs_recv = d->bd_rcount;
71947584Smccanne 			bs->bs_drop = d->bd_dcount;
72047584Smccanne 			break;
72147584Smccanne 		}
72247584Smccanne 
72347584Smccanne 	/*
72447584Smccanne 	 * Set immediate mode.
72547584Smccanne 	 */
72647584Smccanne 	case BIOCIMMEDIATE:
72747584Smccanne 		d->bd_immediate = *(u_int *)addr;
72847584Smccanne 		break;
72953947Smccanne 
73053947Smccanne 	case BIOCVERSION:
73153947Smccanne 		{
73253947Smccanne 			struct bpf_version *bv = (struct bpf_version *)addr;
73353947Smccanne 
73453947Smccanne 			bv->bv_major = BPF_MAJOR_VERSION;
73553947Smccanne 			bv->bv_minor = BPF_MINOR_VERSION;
73653947Smccanne 			break;
73753947Smccanne 		}
73847584Smccanne 	}
73948932Smccanne 	return (error);
74047584Smccanne }
74147584Smccanne 
74253947Smccanne /*
74351425Smccanne  * Set d's packet filter program to fp.  If this file already has a filter,
74448932Smccanne  * free it and replace it.  Returns EINVAL for bogus requests.
74547584Smccanne  */
74647584Smccanne int
74747584Smccanne bpf_setf(d, fp)
74847584Smccanne 	struct bpf_d *d;
74947584Smccanne 	struct bpf_program *fp;
75047584Smccanne {
75148932Smccanne 	struct bpf_insn *fcode, *old;
75247584Smccanne 	u_int flen, size;
75347584Smccanne 	int s;
75447584Smccanne 
75548932Smccanne 	old = d->bd_filter;
75647584Smccanne 	if (fp->bf_insns == 0) {
75747584Smccanne 		if (fp->bf_len != 0)
75848932Smccanne 			return (EINVAL);
75948932Smccanne 		s = splimp();
76048967Smccanne 		d->bd_filter = 0;
76147584Smccanne 		reset_d(d);
76247584Smccanne 		splx(s);
76348967Smccanne 		if (old != 0)
76448932Smccanne 			free((caddr_t)old, M_DEVBUF);
76548932Smccanne 		return (0);
76647584Smccanne 	}
76747584Smccanne 	flen = fp->bf_len;
76848932Smccanne 	if (flen > BPF_MAXINSNS)
76948932Smccanne 		return (EINVAL);
77048932Smccanne 
77147584Smccanne 	size = flen * sizeof(*fp->bf_insns);
77248932Smccanne 	fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
77350417Smccanne 	if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
77450417Smccanne 	    bpf_validate(fcode, (int)flen)) {
77548967Smccanne 		s = splimp();
77648932Smccanne 		d->bd_filter = fcode;
77747584Smccanne 		reset_d(d);
77847584Smccanne 		splx(s);
77948967Smccanne 		if (old != 0)
78048932Smccanne 			free((caddr_t)old, M_DEVBUF);
78147584Smccanne 
78248932Smccanne 		return (0);
78347584Smccanne 	}
78448932Smccanne 	free((caddr_t)fcode, M_DEVBUF);
78548932Smccanne 	return (EINVAL);
78647584Smccanne }
78747584Smccanne 
78847584Smccanne /*
78953947Smccanne  * Detach a file from its current interface (if attached at all) and attach
79053947Smccanne  * to the interface indicated by the name stored in ifr.
79151425Smccanne  * Return an errno or 0.
79247584Smccanne  */
79347584Smccanne static int
79447584Smccanne bpf_setif(d, ifr)
79547584Smccanne 	struct bpf_d *d;
79647584Smccanne 	struct ifreq *ifr;
79747584Smccanne {
79847584Smccanne 	struct bpf_if *bp;
79947584Smccanne 	char *cp;
80053947Smccanne 	int unit, s, error;
80147584Smccanne 
80247584Smccanne 	/*
80347584Smccanne 	 * Separate string into name part and unit number.  Put a null
80453947Smccanne 	 * byte at the end of the name part, and compute the number.
80547584Smccanne 	 * If the a unit number is unspecified, the default is 0,
80648932Smccanne 	 * as initialized above.  XXX This should be common code.
80747584Smccanne 	 */
80847584Smccanne 	unit = 0;
80947584Smccanne 	cp = ifr->ifr_name;
81047584Smccanne 	cp[sizeof(ifr->ifr_name) - 1] = '\0';
81147584Smccanne 	while (*cp++) {
81247584Smccanne 		if (*cp >= '0' && *cp <= '9') {
81347584Smccanne 			unit = *cp - '0';
81447584Smccanne 			*cp++ = '\0';
81547584Smccanne 			while (*cp)
81647584Smccanne 				unit = 10 * unit + *cp++ - '0';
81747584Smccanne 			break;
81847584Smccanne 		}
81947584Smccanne 	}
82047584Smccanne 	/*
82147584Smccanne 	 * Look through attached interfaces for the named one.
82247584Smccanne 	 */
82349202Smccanne 	for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
82447584Smccanne 		struct ifnet *ifp = bp->bif_ifp;
82547584Smccanne 
82653947Smccanne 		if (ifp == 0 || unit != ifp->if_unit
82747584Smccanne 		    || strcmp(ifp->if_name, ifr->ifr_name) != 0)
82847584Smccanne 			continue;
82947584Smccanne 		/*
83053947Smccanne 		 * We found the requested interface.
83147584Smccanne 		 * If it's not up, return an error.
83253947Smccanne 		 * Allocate the packet buffers if we need to.
83353947Smccanne 		 * If we're already attached to requested interface,
83453947Smccanne 		 * just flush the buffer.
83547584Smccanne 		 */
83647584Smccanne 		if ((ifp->if_flags & IFF_UP) == 0)
83748932Smccanne 			return (ENETDOWN);
83853947Smccanne 
83953947Smccanne 		if (d->bd_sbuf == 0) {
84053947Smccanne 			error = bpf_allocbufs(d);
84153947Smccanne 			if (error != 0)
84253947Smccanne 				return (error);
84353947Smccanne 		}
84447584Smccanne 		s = splimp();
84547584Smccanne 		if (bp != d->bd_bif) {
84647584Smccanne 			if (d->bd_bif)
84753947Smccanne 				/*
84848932Smccanne 				 * Detach if attached to something else.
84947584Smccanne 				 */
85047584Smccanne 				bpf_detachd(d);
85147584Smccanne 
85247584Smccanne 			bpf_attachd(d, bp);
85347584Smccanne 		}
85447584Smccanne 		reset_d(d);
85547584Smccanne 		splx(s);
85648932Smccanne 		return (0);
85747584Smccanne 	}
85847584Smccanne 	/* Not found. */
85948932Smccanne 	return (ENXIO);
86047584Smccanne }
86147584Smccanne 
86247584Smccanne /*
86351425Smccanne  * Convert an interface name plus unit number of an ifp to a single
86451425Smccanne  * name which is returned in the ifr.
86547584Smccanne  */
86647584Smccanne static void
86747584Smccanne bpf_ifname(ifp, ifr)
86847584Smccanne 	struct ifnet *ifp;
86947584Smccanne 	struct ifreq *ifr;
87047584Smccanne {
87147584Smccanne 	char *s = ifp->if_name;
87247584Smccanne 	char *d = ifr->ifr_name;
87347584Smccanne 
87447584Smccanne 	while (*d++ = *s++)
87553947Smccanne 		continue;
87648932Smccanne 	/* XXX Assume that unit number is less than 10. */
87747584Smccanne 	*d++ = ifp->if_unit + '0';
87847584Smccanne 	*d = '\0';
87947584Smccanne }
88047584Smccanne 
88147584Smccanne /*
88251425Smccanne  * The new select interface passes down the proc pointer; the old select
88351425Smccanne  * stubs had to grab it out of the user struct.  This glue allows either case.
88451425Smccanne  */
88551425Smccanne #if BSD >= 199103
88651425Smccanne #define bpf_select bpfselect
88751425Smccanne #else
88851425Smccanne int
88951425Smccanne bpfselect(dev, rw)
89051425Smccanne 	register dev_t dev;
89151425Smccanne 	int rw;
89251425Smccanne {
89353947Smccanne 	return (bpf_select(dev, rw, u.u_procp));
89451425Smccanne }
89551425Smccanne #endif
89651425Smccanne 
89751425Smccanne /*
89847584Smccanne  * Support for select() system call
89947584Smccanne  * Inspired by the code in tty.c for the same purpose.
90047584Smccanne  *
90153947Smccanne  * Return true iff the specific operation will not block indefinitely.
90253947Smccanne  * Otherwise, return false but make a note that a selwakeup() must be done.
90347584Smccanne  */
90447584Smccanne int
90551425Smccanne bpf_select(dev, rw, p)
90647584Smccanne 	register dev_t dev;
90747584Smccanne 	int rw;
90848932Smccanne 	struct proc *p;
90947584Smccanne {
91047584Smccanne 	register struct bpf_d *d;
91147584Smccanne 	register int s;
91253947Smccanne 
91347584Smccanne 	if (rw != FREAD)
91448932Smccanne 		return (0);
91547584Smccanne 	/*
91647584Smccanne 	 * An imitation of the FIONREAD ioctl code.
91747584Smccanne 	 */
91847584Smccanne 	d = &bpf_dtab[minor(dev)];
91953947Smccanne 
92047584Smccanne 	s = splimp();
92149723Smccanne 	if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) {
92247584Smccanne 		/*
92347584Smccanne 		 * There is data waiting.
92447584Smccanne 		 */
92547584Smccanne 		splx(s);
92648932Smccanne 		return (1);
92747584Smccanne 	}
92853947Smccanne #if BSD >= 199103
92953947Smccanne 	selrecord(p, &d->bd_sel);
93053947Smccanne #else
93147584Smccanne 	/*
93247584Smccanne 	 * No data ready.  If there's already a select() waiting on this
93353947Smccanne 	 * minor device then this is a collision.  This shouldn't happen
93447584Smccanne 	 * because minors really should not be shared, but if a process
93547584Smccanne 	 * forks while one of these is open, it is possible that both
93647584Smccanne 	 * processes could select on the same descriptor.
93747584Smccanne 	 */
93853947Smccanne 	if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait)
93953947Smccanne 		d->bd_selcoll = 1;
94053947Smccanne 	else
94153947Smccanne 		d->bd_selproc = p;
94253947Smccanne #endif
94353947Smccanne 	splx(s);
94448932Smccanne 	return (0);
94547584Smccanne }
94647584Smccanne 
94747584Smccanne /*
94853947Smccanne  * Incoming linkage from device drivers.  Process the packet pkt, of length
94953947Smccanne  * pktlen, which is stored in a contiguous buffer.  The packet is parsed
95053947Smccanne  * by each process' filter, and if accepted, stashed into the corresponding
95153947Smccanne  * buffer.
95247584Smccanne  */
95347584Smccanne void
95448932Smccanne bpf_tap(arg, pkt, pktlen)
95547584Smccanne 	caddr_t arg;
95648932Smccanne 	register u_char *pkt;
95748932Smccanne 	register u_int pktlen;
95847584Smccanne {
95947584Smccanne 	struct bpf_if *bp;
96047584Smccanne 	register struct bpf_d *d;
96147584Smccanne 	register u_int slen;
96247584Smccanne 	/*
96347584Smccanne 	 * Note that the ipl does not have to be raised at this point.
96447584Smccanne 	 * The only problem that could arise here is that if two different
96547584Smccanne 	 * interfaces shared any data.  This is not the case.
96647584Smccanne 	 */
96747584Smccanne 	bp = (struct bpf_if *)arg;
96847584Smccanne 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
96947584Smccanne 		++d->bd_rcount;
97049202Smccanne 		slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
97147584Smccanne 		if (slen != 0)
97249202Smccanne 			catchpacket(d, pkt, pktlen, slen, bcopy);
97347584Smccanne 	}
97447584Smccanne }
97547584Smccanne 
97647584Smccanne /*
97747584Smccanne  * Copy data from an mbuf chain into a buffer.  This code is derived
97847584Smccanne  * from m_copydata in sys/uipc_mbuf.c.
97947584Smccanne  */
98047584Smccanne static void
98149202Smccanne bpf_mcopy(src, dst, len)
98247584Smccanne 	u_char *src;
98347584Smccanne 	u_char *dst;
98447584Smccanne 	register int len;
98547584Smccanne {
98647584Smccanne 	register struct mbuf *m = (struct mbuf *)src;
98747584Smccanne 	register unsigned count;
98847584Smccanne 
98947584Smccanne 	while (len > 0) {
99047584Smccanne 		if (m == 0)
99149202Smccanne 			panic("bpf_mcopy");
99255065Spendry 		count = min(m->m_len, len);
99349202Smccanne 		bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
99449202Smccanne 		m = m->m_next;
99549202Smccanne 		dst += count;
99647584Smccanne 		len -= count;
99747584Smccanne 	}
99847584Smccanne }
99947584Smccanne 
100047584Smccanne /*
100153947Smccanne  * Incoming linkage from device drivers, when packet is in an mbuf chain.
100247584Smccanne  */
100347584Smccanne void
100449202Smccanne bpf_mtap(arg, m)
100547584Smccanne 	caddr_t arg;
100649202Smccanne 	struct mbuf *m;
100747584Smccanne {
100847584Smccanne 	struct bpf_if *bp = (struct bpf_if *)arg;
100947584Smccanne 	struct bpf_d *d;
101049202Smccanne 	u_int pktlen, slen;
101149202Smccanne 	struct mbuf *m0;
101247584Smccanne 
101348932Smccanne 	pktlen = 0;
101451425Smccanne 	for (m0 = m; m0 != 0; m0 = m0->m_next)
101549202Smccanne 		pktlen += m0->m_len;
101649723Smccanne 
101747584Smccanne 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
101847584Smccanne 		++d->bd_rcount;
101949202Smccanne 		slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
102047584Smccanne 		if (slen != 0)
102149202Smccanne 			catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
102247584Smccanne 	}
102347584Smccanne }
102447584Smccanne 
102547584Smccanne /*
102649202Smccanne  * Move the packet data from interface memory (pkt) into the
102747584Smccanne  * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
102853947Smccanne  * otherwise 0.  "copy" is the routine called to do the actual data
102951425Smccanne  * transfer.  bcopy is passed in to copy contiguous chunks, while
103051425Smccanne  * bpf_mcopy is passed in to copy mbuf chains.  In the latter case,
103151425Smccanne  * pkt is really an mbuf.
103247584Smccanne  */
103347584Smccanne static void
103448932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn)
103548932Smccanne 	register struct bpf_d *d;
103648932Smccanne 	register u_char *pkt;
103748932Smccanne 	register u_int pktlen, snaplen;
103848932Smccanne 	register void (*cpfn)();
103947584Smccanne {
104048932Smccanne 	register struct bpf_hdr *hp;
104148932Smccanne 	register int totlen, curlen;
104248932Smccanne 	register int hdrlen = d->bd_bif->bif_hdrlen;
104347584Smccanne 	/*
104447584Smccanne 	 * Figure out how many bytes to move.  If the packet is
104547584Smccanne 	 * greater or equal to the snapshot length, transfer that
104647584Smccanne 	 * much.  Otherwise, transfer the whole packet (unless
104748932Smccanne 	 * we hit the buffer size limit).
104847584Smccanne 	 */
104955065Spendry 	totlen = hdrlen + min(snaplen, pktlen);
105050082Smccanne 	if (totlen > d->bd_bufsize)
105150082Smccanne 		totlen = d->bd_bufsize;
105247584Smccanne 
105347584Smccanne 	/*
105447584Smccanne 	 * Round up the end of the previous packet to the next longword.
105547584Smccanne 	 */
105648932Smccanne 	curlen = BPF_WORDALIGN(d->bd_slen);
105748932Smccanne 	if (curlen + totlen > d->bd_bufsize) {
105847584Smccanne 		/*
105947584Smccanne 		 * This packet will overflow the storage buffer.
106048932Smccanne 		 * Rotate the buffers if we can, then wakeup any
106148932Smccanne 		 * pending reads.
106247584Smccanne 		 */
106347584Smccanne 		if (d->bd_fbuf == 0) {
106453947Smccanne 			/*
106553947Smccanne 			 * We haven't completed the previous read yet,
106648932Smccanne 			 * so drop the packet.
106747584Smccanne 			 */
106847584Smccanne 			++d->bd_dcount;
106947584Smccanne 			return;
107047584Smccanne 		}
107148932Smccanne 		ROTATE_BUFFERS(d);
107247584Smccanne 		bpf_wakeup(d);
107348932Smccanne 		curlen = 0;
107447584Smccanne 	}
107553947Smccanne 	else if (d->bd_immediate)
107647584Smccanne 		/*
107747584Smccanne 		 * Immediate mode is set.  A packet arrived so any
107847584Smccanne 		 * reads should be woken up.
107947584Smccanne 		 */
108047584Smccanne 		bpf_wakeup(d);
108148932Smccanne 
108247584Smccanne 	/*
108347584Smccanne 	 * Append the bpf header.
108447584Smccanne 	 */
108548932Smccanne 	hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
108651425Smccanne #if BSD >= 199103
108747584Smccanne 	microtime(&hp->bh_tstamp);
108853947Smccanne #elif defined(sun)
108953947Smccanne 	uniqtime(&hp->bh_tstamp);
109047584Smccanne #else
109147584Smccanne 	hp->bh_tstamp = time;
109247584Smccanne #endif
109348932Smccanne 	hp->bh_datalen = pktlen;
109447584Smccanne 	hp->bh_hdrlen = hdrlen;
109547584Smccanne 	/*
109648932Smccanne 	 * Copy the packet data into the store buffer and update its length.
109747584Smccanne 	 */
109848932Smccanne 	(*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
109948932Smccanne 	d->bd_slen = curlen + totlen;
110047584Smccanne }
110147584Smccanne 
110253947Smccanne /*
110347584Smccanne  * Initialize all nonzero fields of a descriptor.
110447584Smccanne  */
110547584Smccanne static int
110653947Smccanne bpf_allocbufs(d)
110747584Smccanne 	register struct bpf_d *d;
110847584Smccanne {
110948932Smccanne 	d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
111048932Smccanne 	if (d->bd_fbuf == 0)
111148932Smccanne 		return (ENOBUFS);
111247584Smccanne 
111348932Smccanne 	d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
111448932Smccanne 	if (d->bd_sbuf == 0) {
111548932Smccanne 		free(d->bd_fbuf, M_DEVBUF);
111648932Smccanne 		return (ENOBUFS);
111747584Smccanne 	}
111848932Smccanne 	d->bd_slen = 0;
111948932Smccanne 	d->bd_hlen = 0;
112048932Smccanne 	return (0);
112147584Smccanne }
112247584Smccanne 
112347584Smccanne /*
112451425Smccanne  * Free buffers currently in use by a descriptor.
112551425Smccanne  * Called on close.
112647584Smccanne  */
112753947Smccanne static void
112851425Smccanne bpf_freed(d)
112951425Smccanne 	register struct bpf_d *d;
113051425Smccanne {
113151425Smccanne 	/*
113251425Smccanne 	 * We don't need to lock out interrupts since this descriptor has
113353947Smccanne 	 * been detached from its interface and it yet hasn't been marked
113451425Smccanne 	 * free.
113551425Smccanne 	 */
113653947Smccanne 	if (d->bd_sbuf != 0) {
113753947Smccanne 		free(d->bd_sbuf, M_DEVBUF);
113853947Smccanne 		if (d->bd_hbuf != 0)
113953947Smccanne 			free(d->bd_hbuf, M_DEVBUF);
114053947Smccanne 		if (d->bd_fbuf != 0)
114153947Smccanne 			free(d->bd_fbuf, M_DEVBUF);
114253947Smccanne 	}
114351425Smccanne 	if (d->bd_filter)
114451425Smccanne 		free((caddr_t)d->bd_filter, M_DEVBUF);
114553947Smccanne 
114651425Smccanne 	D_MARKFREE(d);
114751425Smccanne }
114851425Smccanne 
114951425Smccanne /*
115051425Smccanne  * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if *)
115151425Smccanne  * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
115251425Smccanne  * size of the link header (variable length headers not yet supported).
115351425Smccanne  */
115447584Smccanne void
115549202Smccanne bpfattach(driverp, ifp, dlt, hdrlen)
115647584Smccanne 	caddr_t *driverp;
115747584Smccanne 	struct ifnet *ifp;
115849202Smccanne 	u_int dlt, hdrlen;
115947584Smccanne {
116047584Smccanne 	struct bpf_if *bp;
116147584Smccanne 	int i;
116251425Smccanne #if BSD < 199103
116351425Smccanne 	static struct bpf_if bpf_ifs[NBPFILTER];
116451425Smccanne 	static int bpfifno;
116547584Smccanne 
116651425Smccanne 	bp = (bpfifno < NBPFILTER) ? &bpf_ifs[bpfifno++] : 0;
116751425Smccanne #else
116849202Smccanne 	bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
116951425Smccanne #endif
117049202Smccanne 	if (bp == 0)
117149202Smccanne 		panic("bpfattach");
117247584Smccanne 
117347584Smccanne 	bp->bif_dlist = 0;
117447584Smccanne 	bp->bif_driverp = (struct bpf_if **)driverp;
117547584Smccanne 	bp->bif_ifp = ifp;
117649202Smccanne 	bp->bif_dlt = dlt;
117747584Smccanne 
117849202Smccanne 	bp->bif_next = bpf_iflist;
117949202Smccanne 	bpf_iflist = bp;
118049202Smccanne 
118148932Smccanne 	*bp->bif_driverp = 0;
118248932Smccanne 
118347584Smccanne 	/*
118447584Smccanne 	 * Compute the length of the bpf header.  This is not necessarily
118553947Smccanne 	 * equal to SIZEOF_BPF_HDR because we want to insert spacing such
118653947Smccanne 	 * that the network layer header begins on a longword boundary (for
118747584Smccanne 	 * performance reasons and to alleviate alignment restrictions).
118847584Smccanne 	 */
118949202Smccanne 	bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
119047584Smccanne 
119147584Smccanne 	/*
119247584Smccanne 	 * Mark all the descriptors free if this hasn't been done.
119347584Smccanne 	 */
119447584Smccanne 	if (!D_ISFREE(&bpf_dtab[0]))
119547584Smccanne 		for (i = 0; i < NBPFILTER; ++i)
119647584Smccanne 			D_MARKFREE(&bpf_dtab[i]);
119747584Smccanne 
119847584Smccanne 	printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit);
119947584Smccanne }
120047584Smccanne 
120151425Smccanne #if BSD >= 199103
120248967Smccanne /* XXX This routine belongs in net/if.c. */
120348932Smccanne /*
120453947Smccanne  * Set/clear promiscuous mode on interface ifp based on the truth value
120548932Smccanne  * of pswitch.  The calls are reference counted so that only the first
120653947Smccanne  * "on" request actually has an effect, as does the final "off" request.
120753947Smccanne  * Results are undefined if the "off" and "on" requests are not matched.
120848932Smccanne  */
120948932Smccanne int
121048932Smccanne ifpromisc(ifp, pswitch)
121148932Smccanne 	struct ifnet *ifp;
121248932Smccanne 	int pswitch;
121348932Smccanne {
121449726Smccanne 	struct ifreq ifr;
121553947Smccanne 	/*
121648932Smccanne 	 * If the device is not configured up, we cannot put it in
121748932Smccanne 	 * promiscuous mode.
121848932Smccanne 	 */
121948932Smccanne 	if ((ifp->if_flags & IFF_UP) == 0)
122048932Smccanne 		return (ENETDOWN);
122148932Smccanne 
122248932Smccanne 	if (pswitch) {
122348932Smccanne 		if (ifp->if_pcount++ != 0)
122448932Smccanne 			return (0);
122548932Smccanne 		ifp->if_flags |= IFF_PROMISC;
122648932Smccanne 	} else {
122748932Smccanne 		if (--ifp->if_pcount > 0)
122848932Smccanne 			return (0);
122948932Smccanne 		ifp->if_flags &= ~IFF_PROMISC;
123048932Smccanne 	}
123149726Smccanne 	ifr.ifr_flags = ifp->if_flags;
123249726Smccanne 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
123348932Smccanne }
123451425Smccanne #endif
123548932Smccanne 
123651425Smccanne #if BSD < 199103
123751425Smccanne /*
123851425Smccanne  * Allocate some memory for bpf.  This is temporary SunOS support, and
123953947Smccanne  * is admittedly a hack.
124051425Smccanne  * If resources unavaiable, return 0.
124151425Smccanne  */
124251425Smccanne static caddr_t
124351425Smccanne bpf_alloc(size, canwait)
124451425Smccanne 	register int size;
124551425Smccanne 	register int canwait;
124651425Smccanne {
124751425Smccanne 	register struct mbuf *m;
124851425Smccanne 
124951425Smccanne 	if ((unsigned)size > (MCLBYTES-8))
125051425Smccanne 		return 0;
125151425Smccanne 
125251425Smccanne 	MGET(m, canwait, MT_DATA);
125351425Smccanne 	if (m == 0)
125451425Smccanne 		return 0;
125551425Smccanne 	if ((unsigned)size > (MLEN-8)) {
125651425Smccanne 		MCLGET(m);
125751425Smccanne 		if (m->m_len != MCLBYTES) {
125851425Smccanne 			m_freem(m);
125951425Smccanne 			return 0;
126051425Smccanne 		}
126151425Smccanne 	}
126251425Smccanne 	*mtod(m, struct mbuf **) = m;
126351425Smccanne 	return mtod(m, caddr_t) + 8;
126451425Smccanne }
126551425Smccanne #endif
126651425Smccanne #endif
1267