xref: /csrg-svn/sys/net/bpf.c (revision 51440)
1*51440Smccanne /*
2*51440Smccanne  * 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  *
10*51440Smccanne  * %sccs.include.redist.c%
1149343Sbostic  *
12*51440Smccanne  *      @(#)bpf.c	7.7 (Berkeley) 10/29/91
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
2551425Smccanne #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>
3348932Smccanne #include <sys/proc.h>
3447584Smccanne #include <sys/user.h>
3547584Smccanne #include <sys/ioctl.h>
3647584Smccanne #include <sys/map.h>
3747584Smccanne 
3847584Smccanne #include <sys/file.h>
3951425Smccanne #if defined(sparc) && BSD < 199103
4047584Smccanne #include <sys/stream.h>
4147584Smccanne #endif
4247584Smccanne #include <sys/tty.h>
4347584Smccanne #include <sys/uio.h>
4447584Smccanne 
4547584Smccanne #include <sys/protosw.h>
4647584Smccanne #include <sys/socket.h>
4747584Smccanne #include <net/if.h>
4847584Smccanne 
4947584Smccanne #include <net/bpf.h>
5047584Smccanne #include <net/bpfdesc.h>
5147584Smccanne 
5247584Smccanne #include <sys/errno.h>
5347584Smccanne 
5447584Smccanne #include <netinet/in.h>
5547584Smccanne #include <netinet/if_ether.h>
5647584Smccanne #include <sys/kernel.h>
5747584Smccanne 
5851425Smccanne /*
5951425Smccanne  * Older BSDs don't have kernel malloc.
6051425Smccanne  */
6151425Smccanne #if BSD < 199103
6251425Smccanne extern bcopy();
6351425Smccanne static caddr_t bpf_alloc();
6451425Smccanne #define malloc(size, type, canwait) bpf_alloc(size, canwait)
6551425Smccanne #define free(cp, type) m_free(*(struct mbuf **)(cp - 8))
6651425Smccanne #define M_WAITOK M_WAIT
6751425Smccanne #define BPF_BUFSIZE (MCLBYTES-8)
6851425Smccanne #define ERESTART EINTR
6951425Smccanne #else
7051425Smccanne #define BPF_BUFSIZE 4096
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  *
8447584Smccanne  * We really don't need NBPFILTER bpf_if entries, but this eliminates
8547584Smccanne  * the need to account for all possible drivers here.
8647584Smccanne  * This problem will go away when these structures are allocated dynamically.
8747584Smccanne  */
8849202Smccanne static struct bpf_if 	*bpf_iflist;
8947584Smccanne static struct bpf_d	bpf_dtab[NBPFILTER];
9047584Smccanne 
9147584Smccanne static void	bpf_ifname();
9247584Smccanne static void	catchpacket();
9347584Smccanne static int	bpf_setif();
9447584Smccanne static int	bpf_initd();
9547584Smccanne 
9647584Smccanne static int
9747584Smccanne bpf_movein(uio, linktype, mp, sockp)
9847584Smccanne 	register struct uio *uio;
9947584Smccanne 	int linktype;
10047584Smccanne 	register struct mbuf **mp;
10147584Smccanne 	register struct sockaddr *sockp;
10247584Smccanne {
10347584Smccanne 	struct mbuf *m;
10447584Smccanne 	int error;
10547584Smccanne 	int len;
10647584Smccanne 	int hlen;
10747584Smccanne 
10847584Smccanne 	/*
10947584Smccanne 	 * Build a sockaddr based on the data link layer type.
11047584Smccanne 	 * We do this at this level because the ethernet header
11147584Smccanne 	 * is copied directly into the data field of the sockaddr.
11247584Smccanne 	 * In the case of SLIP, there is no header and the packet
11347584Smccanne 	 * is forwarded as is.
11447584Smccanne 	 * Also, we are careful to leave room at the front of the mbuf
11547584Smccanne 	 * for the link level header.
11647584Smccanne 	 */
11747584Smccanne 	switch (linktype) {
11847584Smccanne 	case DLT_SLIP:
11947584Smccanne 		sockp->sa_family = AF_INET;
12047584Smccanne 		hlen = 0;
12147584Smccanne 		break;
12247584Smccanne 
12347584Smccanne 	case DLT_EN10MB:
12447584Smccanne 		sockp->sa_family = AF_UNSPEC;
12547584Smccanne 		/* XXX Would MAXLINKHDR be better? */
12647584Smccanne 		hlen = sizeof(struct ether_header);
12747584Smccanne 		break;
12847584Smccanne 
12947584Smccanne        case DLT_FDDI:
13047584Smccanne 		sockp->sa_family = AF_UNSPEC;
13147584Smccanne 		/* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
13247584Smccanne 		hlen = 24;
13347584Smccanne 		break;
13447584Smccanne 
13547584Smccanne 	default:
13648932Smccanne 		return (EIO);
13747584Smccanne 	}
13847584Smccanne 
13947584Smccanne 	len = uio->uio_resid;
14047584Smccanne 	if ((unsigned)len > MCLBYTES)
14148932Smccanne 		return (EIO);
14247584Smccanne 
14347584Smccanne 	MGET(m, M_WAIT, MT_DATA);
14447584Smccanne 	if (m == 0)
14548932Smccanne 		return (ENOBUFS);
14647584Smccanne 	if (len > MLEN) {
14751425Smccanne #if BSD >= 199103
14848932Smccanne 		MCLGET(m, M_WAIT);
14948932Smccanne 		if ((m->m_flags & M_EXT) == 0) {
15051425Smccanne #else
15151425Smccanne 		MCLGET(m);
15251425Smccanne 		if (m->m_len == MCLBYTES) {
15351425Smccanne #endif
15451425Smccanne 			error = ENOBUFS;
15547584Smccanne 			goto bad;
15647584Smccanne 		}
15747584Smccanne 	}
15847584Smccanne 	m->m_len = len;
15947584Smccanne 	*mp = m;
16047584Smccanne 	/*
16147584Smccanne 	 * Make room for link header.
16247584Smccanne 	 */
16347584Smccanne 	if (hlen) {
16447584Smccanne 		m->m_len -= hlen;
16551425Smccanne #if BSD >= 199103
16648932Smccanne 		m->m_data += hlen; /* XXX */
16751425Smccanne #else
16851425Smccanne 		m->m_off += hlen;
16951425Smccanne #endif
17048932Smccanne 		error = uiomove((caddr_t)sockp->sa_data, hlen, uio);
17147584Smccanne 		if (error)
17247584Smccanne 			goto bad;
17347584Smccanne 	}
17448932Smccanne 	error = uiomove(mtod(m, caddr_t), len - hlen, uio);
17547584Smccanne 	if (!error)
17648932Smccanne 		return (0);
17747584Smccanne  bad:
17847584Smccanne 	m_freem(m);
17948932Smccanne 	return (error);
18047584Smccanne }
18147584Smccanne 
18247584Smccanne /*
18351425Smccanne  * Attach file to the bpf interface, i.e. make d listen on bp.
18447584Smccanne  * Must be called at splimp.
18547584Smccanne  */
18647584Smccanne static void
18747584Smccanne bpf_attachd(d, bp)
18847584Smccanne 	struct bpf_d *d;
18947584Smccanne 	struct bpf_if *bp;
19047584Smccanne {
19151425Smccanne 	/*
19251425Smccanne 	 * Point d at bp, and add d to the interface's list of listeners.
19351425Smccanne 	 * Finally, point the driver's bpf cookie at the interface so
19451425Smccanne 	 * it will divert packets to bpf.
19551425Smccanne 	 */
19647584Smccanne 	d->bd_bif = bp;
19747584Smccanne 	d->bd_next = bp->bif_dlist;
19847584Smccanne 	bp->bif_dlist = d;
19947584Smccanne 
20047584Smccanne 	*bp->bif_driverp = bp;
20147584Smccanne }
20247584Smccanne 
20351425Smccanne /*
20451425Smccanne  * Detach a file from its interface.
20551425Smccanne  */
20647584Smccanne static void
20747584Smccanne bpf_detachd(d)
20847584Smccanne 	struct bpf_d *d;
20947584Smccanne {
21047584Smccanne 	struct bpf_d **p;
21147584Smccanne 	struct bpf_if *bp;
21247584Smccanne 
21347584Smccanne 	bp = d->bd_bif;
21447584Smccanne 	/*
21547584Smccanne 	 * Check if this descriptor had requested promiscuous mode.
21647584Smccanne 	 * If so, turn it off.
21747584Smccanne 	 */
21847584Smccanne 	if (d->bd_promisc) {
21947584Smccanne 		d->bd_promisc = 0;
22047584Smccanne 		if (ifpromisc(bp->bif_ifp, 0))
22147584Smccanne 			/*
22247584Smccanne 			 * Something is really wrong if we were able to put
22347584Smccanne 			 * the driver into promiscuous mode, but can't
22447584Smccanne 			 * take it out.
22547584Smccanne 			 */
22651425Smccanne 			panic("bpf: ifpromisc failed");
22747584Smccanne 	}
22851425Smccanne 	/* Remove d from the interface's descriptor list. */
22947584Smccanne 	p = &bp->bif_dlist;
23047584Smccanne 	while (*p != d) {
23147584Smccanne 		p = &(*p)->bd_next;
23247584Smccanne 		if (*p == 0)
23347584Smccanne 			panic("bpf_detachd: descriptor not in list");
23447584Smccanne 	}
23547584Smccanne 	*p = (*p)->bd_next;
23647584Smccanne 	if (bp->bif_dlist == 0)
23747584Smccanne 		/*
23847584Smccanne 		 * Let the driver know that there are no more listeners.
23947584Smccanne 		 */
24047584Smccanne 		*d->bd_bif->bif_driverp = 0;
24147584Smccanne 	d->bd_bif = 0;
24247584Smccanne }
24347584Smccanne 
24447584Smccanne 
24547584Smccanne /*
24647584Smccanne  * Mark a descriptor free by making it point to itself.
24747584Smccanne  * This is probably cheaper than marking with a constant since
24847584Smccanne  * the address should be in a register anyway.
24947584Smccanne  */
25047584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next)
25147584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d))
25247584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0)
25347584Smccanne 
25447584Smccanne /*
25547584Smccanne  *  bpfopen - open ethernet device
25647584Smccanne  *
25747584Smccanne  *  Errors:	ENXIO	- illegal minor device number
25847584Smccanne  *		EBUSY	- too many files open
25947584Smccanne  */
26047584Smccanne /* ARGSUSED */
26147584Smccanne int
26247584Smccanne bpfopen(dev, flag)
26347584Smccanne 	dev_t dev;
26447584Smccanne 	int flag;
26547584Smccanne {
26647584Smccanne 	int error, s;
26747584Smccanne 	register struct bpf_d *d;
26847584Smccanne 
26947584Smccanne 	if (minor(dev) >= NBPFILTER)
27048932Smccanne 		return (ENXIO);
27147584Smccanne 
27247584Smccanne 	/*
27347584Smccanne 	 * Each minor can be opened by only one process.  If the requested
27447584Smccanne 	 * minor is in use, return EBUSY.
27547584Smccanne 	 */
27647584Smccanne 	s = splimp();
27747584Smccanne 	d = &bpf_dtab[minor(dev)];
27847584Smccanne 	if (!D_ISFREE(d)) {
27947584Smccanne 		splx(s);
28048932Smccanne 		return (EBUSY);
28147584Smccanne 	} else
28247584Smccanne 		/* Mark "free" and do most initialization. */
28347584Smccanne 		bzero((char *)d, sizeof(*d));
28447584Smccanne 	splx(s);
28547584Smccanne 
28647584Smccanne 	error = bpf_initd(d);
28747584Smccanne 	if (error) {
28847584Smccanne 		D_MARKFREE(d);
28948932Smccanne 		return (error);
29047584Smccanne 	}
29148932Smccanne 	return (0);
29247584Smccanne }
29347584Smccanne 
29447584Smccanne /*
29547584Smccanne  * Close the descriptor by detaching it from its interface,
29647584Smccanne  * deallocating its buffers, and marking it free.
29747584Smccanne  */
29847584Smccanne /* ARGSUSED */
29947584Smccanne bpfclose(dev, flag)
30047584Smccanne 	dev_t dev;
30147584Smccanne 	int flag;
30247584Smccanne {
30347584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
30447584Smccanne 	int s;
30547584Smccanne 
30647584Smccanne 	s = splimp();
30747584Smccanne 	if (d->bd_bif)
30847584Smccanne 		bpf_detachd(d);
30947584Smccanne 	splx(s);
31047584Smccanne 
31151425Smccanne 	bpf_freed(d);
31247584Smccanne }
31347584Smccanne 
31451425Smccanne #if BSD < 199103
31551425Smccanne static
31651425Smccanne bpf_timeout(arg)
31751425Smccanne 	caddr_t arg;
31851425Smccanne {
31951425Smccanne 	struct bpf_d *d = (struct bpf_d *)arg;
32051425Smccanne 	d->bd_timedout = 1;
32151425Smccanne 	wakeup(arg);
32251425Smccanne }
32351425Smccanne 
32451425Smccanne static int
32551425Smccanne tsleep(cp, pri, s, t)
32651425Smccanne 	register caddr_t cp;
32751425Smccanne 	register int pri;
32851425Smccanne 	char *s;
32951425Smccanne 	register int t;
33051425Smccanne {
33151425Smccanne 	register struct bpf_d *d = (struct bpf_d *)cp;
33251425Smccanne 	register int error;
33351425Smccanne 
33451425Smccanne 	if (t != 0) {
33551425Smccanne 		d->bd_timedout = 0;
33651425Smccanne 		timeout(bpf_timeout, cp);
33751425Smccanne 	}
33851425Smccanne 	error = sleep(cp, pri);
33951425Smccanne 	if (t != 0) {
34051425Smccanne 		if (d->bd_timedout != 0)
34151425Smccanne 			return EWOULDBLOCK;
34251425Smccanne 		untimeout(bpf_timeout, cp);
34351425Smccanne 	}
34451425Smccanne 	return error;
34551425Smccanne }
34651425Smccanne #endif
34751425Smccanne 
34847584Smccanne /*
34948932Smccanne  * Rotate the packet buffers in descriptor d.  Move the store buffer
35048932Smccanne  * into the hold slot, and the free buffer into the store slot.
35148932Smccanne  * Zero the length of the new store buffer.
35248932Smccanne  */
35348932Smccanne #define ROTATE_BUFFERS(d) \
35448932Smccanne 	(d)->bd_hbuf = (d)->bd_sbuf; \
35548932Smccanne 	(d)->bd_hlen = (d)->bd_slen; \
35648932Smccanne 	(d)->bd_sbuf = (d)->bd_fbuf; \
35748932Smccanne 	(d)->bd_slen = 0; \
35848932Smccanne 	(d)->bd_fbuf = 0;
35948932Smccanne /*
36047584Smccanne  *  bpfread - read next chunk of packets from buffers
36147584Smccanne  */
36247584Smccanne int
36347584Smccanne bpfread(dev, uio)
36447584Smccanne 	dev_t dev;
36547584Smccanne 	register struct uio *uio;
36647584Smccanne {
36747584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
36847584Smccanne 	int error;
36947584Smccanne 	int s;
37047584Smccanne 
37147584Smccanne 	/*
37247584Smccanne 	 * Restrict application to use a buffer the same size as
37347584Smccanne 	 * as kernel buffers.
37447584Smccanne 	 */
37548932Smccanne 	if (uio->uio_resid != d->bd_bufsize)
37649202Smccanne 		return (EINVAL);
37747584Smccanne 
37847584Smccanne 	s = splimp();
37947584Smccanne 	/*
38047584Smccanne 	 * If the hold buffer is empty, then set a timer and sleep
38147584Smccanne 	 * until either the timeout has occurred or enough packets have
38247584Smccanne 	 * arrived to fill the store buffer.
38347584Smccanne 	 */
38447584Smccanne 	while (d->bd_hbuf == 0) {
38548932Smccanne 		if (d->bd_immediate && d->bd_slen != 0) {
38647584Smccanne 			/*
38747584Smccanne 			 * A packet(s) either arrived since the previous
38847584Smccanne 			 * read or arrived while we were asleep.
38947584Smccanne 			 * Rotate the buffers and return what's here.
39047584Smccanne 			 */
39148932Smccanne 			ROTATE_BUFFERS(d);
39247584Smccanne 			break;
39347584Smccanne 		}
39448932Smccanne 		error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf", d->bd_rtout);
39548932Smccanne 		if (error == EINTR || error == ERESTART) {
39648932Smccanne 			splx(s);
39748932Smccanne 			return (error);
39847584Smccanne 		}
39948932Smccanne 		if (error == EWOULDBLOCK) {
40047584Smccanne 			/*
40147584Smccanne 			 * On a timeout, return what's in the buffer,
40248932Smccanne 			 * which may be nothing.  If there is something
40348932Smccanne 			 * in the store buffer, we can rotate the buffers.
40447584Smccanne 			 */
40547584Smccanne 			if (d->bd_hbuf)
40647584Smccanne 				/*
40747584Smccanne 				 * We filled up the buffer in between
40847584Smccanne 				 * getting the timeout and arriving
40947584Smccanne 				 * here, so we don't need to rotate.
41047584Smccanne 				 */
41147584Smccanne 				break;
41247584Smccanne 
41348932Smccanne 			if (d->bd_slen == 0) {
41447584Smccanne 				splx(s);
41548932Smccanne 				return (0);
41647584Smccanne 			}
41748932Smccanne 			ROTATE_BUFFERS(d);
41847584Smccanne 			break;
41947584Smccanne 		}
42047584Smccanne 	}
42147584Smccanne 	/*
42247584Smccanne 	 * At this point, we know we have something in the hold slot.
42347584Smccanne 	 */
42447584Smccanne 	splx(s);
42547584Smccanne 
42647584Smccanne 	/*
42747584Smccanne 	 * Move data from hold buffer into user space.
42847584Smccanne 	 * We know the entire buffer is transferred since
42948932Smccanne 	 * we checked above that the read buffer is bpf_bufsize bytes.
43047584Smccanne 	 */
43151425Smccanne #if BSD >= 199103
43248932Smccanne 	error = uiomove(d->bd_hbuf, d->bd_hlen, uio);
43351425Smccanne #else
43451425Smccanne 	error = uiomove(d->bd_hbuf, d->bd_hlen, UIO_READ, uio);
43551425Smccanne #endif
43647584Smccanne 	s = splimp();
43748932Smccanne 	d->bd_fbuf = d->bd_hbuf;
43848932Smccanne 	d->bd_hbuf = 0;
43947584Smccanne 	splx(s);
44047584Smccanne 
44148932Smccanne 	return (error);
44247584Smccanne }
44347584Smccanne 
44447584Smccanne 
44547584Smccanne /*
44648932Smccanne  * 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);
45348932Smccanne 	if (d->bd_selproc) {
45448932Smccanne 		selwakeup(d->bd_selproc, (int)d->bd_selcoll);
45548932Smccanne 		d->bd_selcoll = 0;
45648932Smccanne 		d->bd_selproc = 0;
45747584Smccanne 	}
45847584Smccanne }
45947584Smccanne 
46047584Smccanne int
46147584Smccanne bpfwrite(dev, uio)
46247584Smccanne 	dev_t dev;
46347584Smccanne 	struct uio *uio;
46447584Smccanne {
46547584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
46647584Smccanne 	struct ifnet *ifp;
46747584Smccanne 	struct mbuf *m;
46847584Smccanne 	int error, s;
46947584Smccanne 	static struct sockaddr dst;
47047584Smccanne 
47147584Smccanne 	if (d->bd_bif == 0)
47248932Smccanne 		return (ENXIO);
47347584Smccanne 
47447584Smccanne 	ifp = d->bd_bif->bif_ifp;
47547584Smccanne 
47647584Smccanne 	if (uio->uio_resid == 0)
47748932Smccanne 		return (0);
47847584Smccanne 	if (uio->uio_resid > ifp->if_mtu)
47948932Smccanne 		return (EMSGSIZE);
48047584Smccanne 
48149202Smccanne 	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst);
48247584Smccanne 	if (error)
48348932Smccanne 		return (error);
48447584Smccanne 
48547584Smccanne 	s = splnet();
48651425Smccanne #if BSD >= 199103
48751425Smccanne 	error = (*ifp->if_output)(ifp, m, &dst, (struct rtenty *)0);
48851425Smccanne #else
48947584Smccanne 	error = (*ifp->if_output)(ifp, m, &dst);
49051425Smccanne #endif
49147584Smccanne 	splx(s);
49247584Smccanne 	/*
49347584Smccanne 	 * The driver frees the mbuf.
49447584Smccanne 	 */
49548932Smccanne 	return (error);
49647584Smccanne }
49747584Smccanne 
49847584Smccanne /*
49948932Smccanne  * Reset a descriptor by flushing its packet bufferand clearing the receive
50048932Smccanne  * and drop counts.  Should be called at splimp.
50147584Smccanne  */
50247584Smccanne static void
50347584Smccanne reset_d(d)
50447584Smccanne 	struct bpf_d *d;
50547584Smccanne {
50647584Smccanne 	if (d->bd_hbuf) {
50747584Smccanne 		/* Free the hold buffer. */
50847584Smccanne 		d->bd_fbuf = d->bd_hbuf;
50947584Smccanne 		d->bd_hbuf = 0;
51047584Smccanne 	}
51148932Smccanne 	d->bd_slen = 0;
51247584Smccanne 	d->bd_rcount = 0;
51347584Smccanne 	d->bd_dcount = 0;
51447584Smccanne }
51547584Smccanne 
51647584Smccanne /*
51747584Smccanne  *  FIONREAD		Check for read packet available.
51847584Smccanne  *  SIOCGIFADDR		Get interface address - convenient hook to driver.
51947584Smccanne  *  BIOCGBLEN		Get buffer len [for read()].
52047584Smccanne  *  BIOCSETF		Set ethernet read filter.
52147584Smccanne  *  BIOCFLUSH		Flush read packet buffer.
52247584Smccanne  *  BIOCPROMISC		Put interface into promiscuous mode.
52349202Smccanne  *  BIOCGDLT		Get link layer type.
52447584Smccanne  *  BIOCGETIF		Get interface name.
52547584Smccanne  *  BIOCSETIF		Set interface.
52647584Smccanne  *  BIOCSRTIMEOUT	Set read timeout.
52747584Smccanne  *  BIOCGRTIMEOUT	Get read timeout.
52847584Smccanne  *  BIOCGSTATS		Get packet stats.
52947584Smccanne  *  BIOCIMMEDIATE	Set immediate mode.
53047584Smccanne  */
53147584Smccanne /* ARGSUSED */
53247584Smccanne int
53347584Smccanne bpfioctl(dev, cmd, addr, flag)
53447584Smccanne 	dev_t dev;
53547584Smccanne 	int cmd;
53647584Smccanne 	caddr_t addr;
53747584Smccanne 	int flag;
53847584Smccanne {
53947584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
54047584Smccanne 	int s, error = 0;
54147584Smccanne 
54247584Smccanne 	switch (cmd) {
54347584Smccanne 
54447584Smccanne 	default:
54547584Smccanne 		error = EINVAL;
54647584Smccanne 		break;
54747584Smccanne 
54847584Smccanne 	/*
54947584Smccanne 	 * Check for read packet available.
55047584Smccanne 	 */
55147584Smccanne 	case FIONREAD:
55247584Smccanne 		{
55347584Smccanne 			int n;
55447584Smccanne 
55547584Smccanne 			s = splimp();
55648932Smccanne 			n = d->bd_slen;
55747584Smccanne 			if (d->bd_hbuf)
55848932Smccanne 				n += d->bd_hlen;
55947584Smccanne 			splx(s);
56047584Smccanne 
56147584Smccanne 			*(int *)addr = n;
56247584Smccanne 			break;
56347584Smccanne 		}
56447584Smccanne 
56547584Smccanne 	case SIOCGIFADDR:
56647584Smccanne 		{
56747584Smccanne 			struct ifnet *ifp;
56847584Smccanne 
56947584Smccanne 			if (d->bd_bif == 0)
57047584Smccanne 				error = EINVAL;
57147584Smccanne 			else {
57247584Smccanne 				ifp = d->bd_bif->bif_ifp;
57347584Smccanne 				error =  (*ifp->if_ioctl)(ifp, cmd, addr);
57447584Smccanne 			}
57547584Smccanne 			break;
57647584Smccanne 		}
57747584Smccanne 
57847584Smccanne 	/*
57947584Smccanne 	 * Get buffer len [for read()].
58047584Smccanne 	 */
58147584Smccanne 	case BIOCGBLEN:
58248932Smccanne 		*(u_int *)addr = d->bd_bufsize;
58347584Smccanne 		break;
58447584Smccanne 
58547584Smccanne 	/*
58651425Smccanne 	 * Set link layer read filter.
58747584Smccanne 	 */
58847584Smccanne         case BIOCSETF:
58947584Smccanne 		error = bpf_setf(d, (struct bpf_program *)addr);
59047584Smccanne 		break;
59147584Smccanne 
59247584Smccanne 	/*
59347584Smccanne 	 * Flush read packet buffer.
59447584Smccanne 	 */
59547584Smccanne 	case BIOCFLUSH:
59647584Smccanne 		s = splimp();
59747584Smccanne 		reset_d(d);
59847584Smccanne 		splx(s);
59947584Smccanne 		break;
60047584Smccanne 
60147584Smccanne 	/*
60247584Smccanne 	 * Put interface into promiscuous mode.
60347584Smccanne 	 */
60447584Smccanne 	case BIOCPROMISC:
60547584Smccanne 		if (d->bd_bif == 0) {
60647584Smccanne 			/*
60747584Smccanne 			 * No interface attached yet.
60847584Smccanne 			 */
60947584Smccanne 			error = EINVAL;
61047584Smccanne 			break;
61147584Smccanne 		}
61247584Smccanne 		s = splimp();
61347584Smccanne 		if (d->bd_promisc == 0) {
61447584Smccanne 			error = ifpromisc(d->bd_bif->bif_ifp, 1);
61551425Smccanne 			if (error == 0)
61651425Smccanne 				d->bd_promisc = 1;
61747584Smccanne 		}
61847584Smccanne 		splx(s);
61947584Smccanne 		break;
62047584Smccanne 
62147584Smccanne 	/*
62247584Smccanne 	 * Get device parameters.
62347584Smccanne 	 */
62449202Smccanne 	case BIOCGDLT:
62547584Smccanne 		if (d->bd_bif == 0)
62647584Smccanne 			error = EINVAL;
62747584Smccanne 		else
62849202Smccanne 			*(u_int *)addr = d->bd_bif->bif_dlt;
62947584Smccanne 		break;
63047584Smccanne 
63147584Smccanne 	/*
63247584Smccanne 	 * Set interface name.
63347584Smccanne 	 */
63447584Smccanne 	case BIOCGETIF:
63547584Smccanne 		if (d->bd_bif == 0)
63647584Smccanne 			error = EINVAL;
63747584Smccanne 		else
63847584Smccanne 			bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
63947584Smccanne 		break;
64047584Smccanne 
64147584Smccanne 	/*
64247584Smccanne 	 * Set interface.
64347584Smccanne 	 */
64447584Smccanne 	case BIOCSETIF:
64547584Smccanne 		error = bpf_setif(d, (struct ifreq *)addr);
64647584Smccanne 		break;
64747584Smccanne 
64847584Smccanne 	/*
64947584Smccanne 	 * Set read timeout.
65047584Smccanne 	 */
65147584Smccanne  	case BIOCSRTIMEOUT:
65247584Smccanne 		{
65347584Smccanne 			struct timeval *tv = (struct timeval *)addr;
65447584Smccanne 			u_long msec;
65547584Smccanne 
65647584Smccanne 			/* Compute number of milliseconds. */
65747584Smccanne 			msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
65847584Smccanne 			/* Scale milliseconds to ticks.  Assume hard
65947584Smccanne 			   clock has millisecond or greater resolution
66047584Smccanne 			   (i.e. tick >= 1000).  For 10ms hardclock,
66147584Smccanne 			   tick/1000 = 10, so rtout<-msec/10. */
66247584Smccanne 			d->bd_rtout = msec / (tick / 1000);
66347584Smccanne 			break;
66447584Smccanne 		}
66547584Smccanne 
66647584Smccanne 	/*
66747584Smccanne 	 * Get read timeout.
66847584Smccanne 	 */
66947584Smccanne  	case BIOCGRTIMEOUT:
67047584Smccanne 		{
67147584Smccanne 			struct timeval *tv = (struct timeval *)addr;
67247584Smccanne 			u_long msec = d->bd_rtout;
67347584Smccanne 
67447584Smccanne 			msec *= tick / 1000;
67547584Smccanne 			tv->tv_sec = msec / 1000;
67647584Smccanne 			tv->tv_usec = msec % 1000;
67747584Smccanne 			break;
67847584Smccanne 		}
67947584Smccanne 
68047584Smccanne 	/*
68147584Smccanne 	 * Get packet stats.
68247584Smccanne 	 */
68347584Smccanne 	case BIOCGSTATS:
68447584Smccanne 		{
68547584Smccanne 			struct bpf_stat *bs = (struct bpf_stat *)addr;
68647584Smccanne 
68747584Smccanne 			bs->bs_recv = d->bd_rcount;
68847584Smccanne 			bs->bs_drop = d->bd_dcount;
68947584Smccanne 			break;
69047584Smccanne 		}
69147584Smccanne 
69247584Smccanne 	/*
69347584Smccanne 	 * Set immediate mode.
69447584Smccanne 	 */
69547584Smccanne 	case BIOCIMMEDIATE:
69647584Smccanne 		d->bd_immediate = *(u_int *)addr;
69747584Smccanne 		break;
69847584Smccanne 	}
69948932Smccanne 	return (error);
70047584Smccanne }
70147584Smccanne 
70247584Smccanne /*
70351425Smccanne  * Set d's packet filter program to fp.  If this file already has a filter,
70448932Smccanne  * free it and replace it.  Returns EINVAL for bogus requests.
70547584Smccanne  */
70647584Smccanne int
70747584Smccanne bpf_setf(d, fp)
70847584Smccanne 	struct bpf_d *d;
70947584Smccanne 	struct bpf_program *fp;
71047584Smccanne {
71148932Smccanne 	struct bpf_insn *fcode, *old;
71247584Smccanne 	u_int flen, size;
71347584Smccanne 	int s;
71447584Smccanne 
71548932Smccanne 	old = d->bd_filter;
71647584Smccanne 	if (fp->bf_insns == 0) {
71747584Smccanne 		if (fp->bf_len != 0)
71848932Smccanne 			return (EINVAL);
71948932Smccanne 		s = splimp();
72048967Smccanne 		d->bd_filter = 0;
72147584Smccanne 		reset_d(d);
72247584Smccanne 		splx(s);
72348967Smccanne 		if (old != 0)
72448932Smccanne 			free((caddr_t)old, M_DEVBUF);
72548932Smccanne 		return (0);
72647584Smccanne 	}
72747584Smccanne 	flen = fp->bf_len;
72848932Smccanne 	if (flen > BPF_MAXINSNS)
72948932Smccanne 		return (EINVAL);
73048932Smccanne 
73147584Smccanne 	size = flen * sizeof(*fp->bf_insns);
73248932Smccanne 	fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
73350417Smccanne 	if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
73450417Smccanne 	    bpf_validate(fcode, (int)flen)) {
73548967Smccanne 		s = splimp();
73648932Smccanne 		d->bd_filter = fcode;
73747584Smccanne 		reset_d(d);
73847584Smccanne 		splx(s);
73948967Smccanne 		if (old != 0)
74048932Smccanne 			free((caddr_t)old, M_DEVBUF);
74147584Smccanne 
74248932Smccanne 		return (0);
74347584Smccanne 	}
74448932Smccanne 	free((caddr_t)fcode, M_DEVBUF);
74548932Smccanne 	return (EINVAL);
74647584Smccanne }
74747584Smccanne 
74847584Smccanne /*
74951425Smccanne  * Detach a file from its current interface (if attached at all) and attach
75051425Smccanne  * to the interface indicated by the name stored in ifr.
75151425Smccanne  * Return an errno or 0.
75247584Smccanne  */
75347584Smccanne static int
75447584Smccanne bpf_setif(d, ifr)
75547584Smccanne 	struct bpf_d *d;
75647584Smccanne 	struct ifreq *ifr;
75747584Smccanne {
75847584Smccanne 	struct bpf_if *bp;
75947584Smccanne 	char *cp;
76049202Smccanne 	int unit, s;
76147584Smccanne 
76247584Smccanne 	/*
76347584Smccanne 	 * Separate string into name part and unit number.  Put a null
76447584Smccanne 	 * byte at the end of the name part, and compute the number.
76547584Smccanne 	 * If the a unit number is unspecified, the default is 0,
76648932Smccanne 	 * as initialized above.  XXX This should be common code.
76747584Smccanne 	 */
76847584Smccanne 	unit = 0;
76947584Smccanne 	cp = ifr->ifr_name;
77047584Smccanne 	cp[sizeof(ifr->ifr_name) - 1] = '\0';
77147584Smccanne 	while (*cp++) {
77247584Smccanne 		if (*cp >= '0' && *cp <= '9') {
77347584Smccanne 			unit = *cp - '0';
77447584Smccanne 			*cp++ = '\0';
77547584Smccanne 			while (*cp)
77647584Smccanne 				unit = 10 * unit + *cp++ - '0';
77747584Smccanne 			break;
77847584Smccanne 		}
77947584Smccanne 	}
78047584Smccanne 	/*
78147584Smccanne 	 * Look through attached interfaces for the named one.
78247584Smccanne 	 */
78349202Smccanne 	for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
78447584Smccanne 		struct ifnet *ifp = bp->bif_ifp;
78547584Smccanne 
78647584Smccanne 		if (ifp == 0 || unit != ifp->if_unit
78747584Smccanne 		    || strcmp(ifp->if_name, ifr->ifr_name) != 0)
78847584Smccanne 			continue;
78947584Smccanne 		/*
79047584Smccanne 		 * We found the requested interface.  If we're
79147584Smccanne 		 * already attached to it, just flush the buffer.
79247584Smccanne 		 * If it's not up, return an error.
79347584Smccanne 		 */
79447584Smccanne 		if ((ifp->if_flags & IFF_UP) == 0)
79548932Smccanne 			return (ENETDOWN);
79647584Smccanne 		s = splimp();
79747584Smccanne 		if (bp != d->bd_bif) {
79847584Smccanne 			if (d->bd_bif)
79947584Smccanne 				/*
80048932Smccanne 				 * Detach if attached to something else.
80147584Smccanne 				 */
80247584Smccanne 				bpf_detachd(d);
80347584Smccanne 
80447584Smccanne 			bpf_attachd(d, bp);
80547584Smccanne 		}
80647584Smccanne 		reset_d(d);
80747584Smccanne 		splx(s);
80848932Smccanne 		return (0);
80947584Smccanne 	}
81047584Smccanne 	/* Not found. */
81148932Smccanne 	return (ENXIO);
81247584Smccanne }
81347584Smccanne 
81447584Smccanne /*
81551425Smccanne  * Convert an interface name plus unit number of an ifp to a single
81651425Smccanne  * name which is returned in the ifr.
81747584Smccanne  */
81847584Smccanne static void
81947584Smccanne bpf_ifname(ifp, ifr)
82047584Smccanne 	struct ifnet *ifp;
82147584Smccanne 	struct ifreq *ifr;
82247584Smccanne {
82347584Smccanne 	char *s = ifp->if_name;
82447584Smccanne 	char *d = ifr->ifr_name;
82547584Smccanne 
82647584Smccanne 	while (*d++ = *s++)
82747584Smccanne 		;
82848932Smccanne 	/* XXX Assume that unit number is less than 10. */
82947584Smccanne 	*d++ = ifp->if_unit + '0';
83047584Smccanne 	*d = '\0';
83147584Smccanne }
83247584Smccanne 
83347584Smccanne /*
83451425Smccanne  * The new select interface passes down the proc pointer; the old select
83551425Smccanne  * stubs had to grab it out of the user struct.  This glue allows either case.
83651425Smccanne  */
83751425Smccanne #if BSD >= 199103
83851425Smccanne #define bpf_select bpfselect
83951425Smccanne #else
84051425Smccanne int
84151425Smccanne bpfselect(dev, rw)
84251425Smccanne 	register dev_t dev;
84351425Smccanne 	int rw;
84451425Smccanne {
84551425Smccanne 	bpf_select(dev, rw, u.u_procp);
84651425Smccanne }
84751425Smccanne #endif
84851425Smccanne 
84951425Smccanne /*
85047584Smccanne  * Support for select() system call
85147584Smccanne  * Inspired by the code in tty.c for the same purpose.
85247584Smccanne  *
85347584Smccanne  * bpfselect - returns true iff the specific operation
85447584Smccanne  *	will not block indefinitely.  Otherwise, return
85547584Smccanne  *	false but make a note that a selwakeup() must be done.
85647584Smccanne  */
85747584Smccanne int
85851425Smccanne bpf_select(dev, rw, p)
85947584Smccanne 	register dev_t dev;
86047584Smccanne 	int rw;
86148932Smccanne 	struct proc *p;
86247584Smccanne {
86347584Smccanne 	register struct bpf_d *d;
86447584Smccanne 	register int s;
86547584Smccanne 
86647584Smccanne 	if (rw != FREAD)
86748932Smccanne 		return (0);
86847584Smccanne 	/*
86947584Smccanne 	 * An imitation of the FIONREAD ioctl code.
87047584Smccanne 	 */
87147584Smccanne 	d = &bpf_dtab[minor(dev)];
87247584Smccanne 
87347584Smccanne 	s = splimp();
87449723Smccanne 	if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) {
87547584Smccanne 		/*
87647584Smccanne 		 * There is data waiting.
87747584Smccanne 		 */
87847584Smccanne 		splx(s);
87948932Smccanne 		return (1);
88047584Smccanne 	}
88147584Smccanne 	/*
88247584Smccanne 	 * No data ready.  If there's already a select() waiting on this
88347584Smccanne 	 * minor device then this is a collision.  This shouldn't happen
88447584Smccanne 	 * because minors really should not be shared, but if a process
88547584Smccanne 	 * forks while one of these is open, it is possible that both
88647584Smccanne 	 * processes could select on the same descriptor.
88747584Smccanne 	 */
88848932Smccanne 	if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait)
88948932Smccanne 		d->bd_selcoll = 1;
89047584Smccanne 	else
89148932Smccanne 		d->bd_selproc = p;
89248932Smccanne 
89347584Smccanne 	splx(s);
89448932Smccanne 	return (0);
89547584Smccanne }
89647584Smccanne 
89747584Smccanne /*
89847584Smccanne  * bpf_tap - incoming linkage from device drivers
89947584Smccanne  */
90047584Smccanne void
90148932Smccanne bpf_tap(arg, pkt, pktlen)
90247584Smccanne 	caddr_t arg;
90348932Smccanne 	register u_char *pkt;
90448932Smccanne 	register u_int pktlen;
90547584Smccanne {
90647584Smccanne 	struct bpf_if *bp;
90747584Smccanne 	register struct bpf_d *d;
90847584Smccanne 	register u_int slen;
90947584Smccanne 	/*
91047584Smccanne 	 * Note that the ipl does not have to be raised at this point.
91147584Smccanne 	 * The only problem that could arise here is that if two different
91247584Smccanne 	 * interfaces shared any data.  This is not the case.
91347584Smccanne 	 */
91447584Smccanne 	bp = (struct bpf_if *)arg;
91547584Smccanne 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
91647584Smccanne 		++d->bd_rcount;
91749202Smccanne 		slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
91847584Smccanne 		if (slen != 0)
91949202Smccanne 			catchpacket(d, pkt, pktlen, slen, bcopy);
92047584Smccanne 	}
92147584Smccanne }
92247584Smccanne 
92347584Smccanne /*
92447584Smccanne  * Copy data from an mbuf chain into a buffer.  This code is derived
92547584Smccanne  * from m_copydata in sys/uipc_mbuf.c.
92647584Smccanne  */
92747584Smccanne static void
92849202Smccanne bpf_mcopy(src, dst, len)
92947584Smccanne 	u_char *src;
93047584Smccanne 	u_char *dst;
93147584Smccanne 	register int len;
93247584Smccanne {
93347584Smccanne 	register struct mbuf *m = (struct mbuf *)src;
93447584Smccanne 	register unsigned count;
93547584Smccanne 
93647584Smccanne 	while (len > 0) {
93747584Smccanne 		if (m == 0)
93849202Smccanne 			panic("bpf_mcopy");
93947584Smccanne 		count = MIN(m->m_len, len);
94049202Smccanne 		bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
94149202Smccanne 		m = m->m_next;
94249202Smccanne 		dst += count;
94347584Smccanne 		len -= count;
94447584Smccanne 	}
94547584Smccanne }
94647584Smccanne 
94747584Smccanne /*
94851425Smccanne  * bpf_mtap -	incoming linkage from device drivers, when packet
94951425Smccanne  *		is in an mbuf chain
95047584Smccanne  */
95147584Smccanne void
95249202Smccanne bpf_mtap(arg, m)
95347584Smccanne 	caddr_t arg;
95449202Smccanne 	struct mbuf *m;
95547584Smccanne {
95647584Smccanne 	struct bpf_if *bp = (struct bpf_if *)arg;
95747584Smccanne 	struct bpf_d *d;
95849202Smccanne 	u_int pktlen, slen;
95949202Smccanne 	struct mbuf *m0;
96047584Smccanne 
96148932Smccanne 	pktlen = 0;
96251425Smccanne 	for (m0 = m; m0 != 0; m0 = m0->m_next)
96349202Smccanne 		pktlen += m0->m_len;
96449723Smccanne 
96547584Smccanne 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
96647584Smccanne 		++d->bd_rcount;
96749202Smccanne 		slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
96847584Smccanne 		if (slen != 0)
96949202Smccanne 			catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
97047584Smccanne 	}
97147584Smccanne }
97247584Smccanne 
97347584Smccanne /*
97449202Smccanne  * Move the packet data from interface memory (pkt) into the
97547584Smccanne  * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
97651425Smccanne  * otherwise 0.  "copy" is the routine called to do the actual data
97751425Smccanne  * transfer.  bcopy is passed in to copy contiguous chunks, while
97851425Smccanne  * bpf_mcopy is passed in to copy mbuf chains.  In the latter case,
97951425Smccanne  * pkt is really an mbuf.
98047584Smccanne  */
98147584Smccanne static void
98248932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn)
98348932Smccanne 	register struct bpf_d *d;
98448932Smccanne 	register u_char *pkt;
98548932Smccanne 	register u_int pktlen, snaplen;
98648932Smccanne 	register void (*cpfn)();
98747584Smccanne {
98848932Smccanne 	register struct bpf_hdr *hp;
98948932Smccanne 	register int totlen, curlen;
99048932Smccanne 	register int hdrlen = d->bd_bif->bif_hdrlen;
99147584Smccanne 	/*
99247584Smccanne 	 * Figure out how many bytes to move.  If the packet is
99347584Smccanne 	 * greater or equal to the snapshot length, transfer that
99447584Smccanne 	 * much.  Otherwise, transfer the whole packet (unless
99548932Smccanne 	 * we hit the buffer size limit).
99647584Smccanne 	 */
99750082Smccanne 	totlen = hdrlen + MIN(snaplen, pktlen);
99850082Smccanne 	if (totlen > d->bd_bufsize)
99950082Smccanne 		totlen = d->bd_bufsize;
100047584Smccanne 
100147584Smccanne 	/*
100247584Smccanne 	 * Round up the end of the previous packet to the next longword.
100347584Smccanne 	 */
100448932Smccanne 	curlen = BPF_WORDALIGN(d->bd_slen);
100548932Smccanne 	if (curlen + totlen > d->bd_bufsize) {
100647584Smccanne 		/*
100747584Smccanne 		 * This packet will overflow the storage buffer.
100848932Smccanne 		 * Rotate the buffers if we can, then wakeup any
100948932Smccanne 		 * pending reads.
101047584Smccanne 		 */
101147584Smccanne 		if (d->bd_fbuf == 0) {
101247584Smccanne 			/*
101348932Smccanne 			 * We haven't completed the previous read yet,
101448932Smccanne 			 * so drop the packet.
101547584Smccanne 			 */
101647584Smccanne 			++d->bd_dcount;
101747584Smccanne 			return;
101847584Smccanne 		}
101948932Smccanne 		ROTATE_BUFFERS(d);
102047584Smccanne 		bpf_wakeup(d);
102148932Smccanne 		curlen = 0;
102247584Smccanne 	}
102348932Smccanne 	else if (d->bd_immediate)
102447584Smccanne 		/*
102547584Smccanne 		 * Immediate mode is set.  A packet arrived so any
102647584Smccanne 		 * reads should be woken up.
102747584Smccanne 		 */
102847584Smccanne 		bpf_wakeup(d);
102948932Smccanne 
103047584Smccanne 	/*
103147584Smccanne 	 * Append the bpf header.
103247584Smccanne 	 */
103348932Smccanne 	hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
103447584Smccanne #ifdef sun
103547584Smccanne 	uniqtime(&hp->bh_tstamp);
103647584Smccanne #else
103751425Smccanne #if BSD >= 199103
103847584Smccanne 	microtime(&hp->bh_tstamp);
103947584Smccanne #else
104047584Smccanne 	hp->bh_tstamp = time;
104147584Smccanne #endif
104247584Smccanne #endif
104348932Smccanne 	hp->bh_datalen = pktlen;
104447584Smccanne 	hp->bh_hdrlen = hdrlen;
104547584Smccanne 	/*
104648932Smccanne 	 * Copy the packet data into the store buffer and update its length.
104747584Smccanne 	 */
104848932Smccanne 	(*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
104948932Smccanne 	d->bd_slen = curlen + totlen;
105047584Smccanne }
105147584Smccanne 
105247584Smccanne /*
105347584Smccanne  * Initialize all nonzero fields of a descriptor.
105447584Smccanne  */
105547584Smccanne static int
105647584Smccanne bpf_initd(d)
105747584Smccanne 	register struct bpf_d *d;
105847584Smccanne {
105948932Smccanne 	d->bd_bufsize = bpf_bufsize;
106048932Smccanne 	d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
106148932Smccanne 	if (d->bd_fbuf == 0)
106248932Smccanne 		return (ENOBUFS);
106347584Smccanne 
106448932Smccanne 	d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
106548932Smccanne 	if (d->bd_sbuf == 0) {
106648932Smccanne 		free(d->bd_fbuf, M_DEVBUF);
106748932Smccanne 		return (ENOBUFS);
106847584Smccanne 	}
106948932Smccanne 	d->bd_slen = 0;
107048932Smccanne 	d->bd_hlen = 0;
107148932Smccanne 	return (0);
107247584Smccanne }
107347584Smccanne 
107447584Smccanne /*
107551425Smccanne  * Free buffers currently in use by a descriptor.
107651425Smccanne  * Called on close.
107747584Smccanne  */
107851425Smccanne bpf_freed(d)
107951425Smccanne 	register struct bpf_d *d;
108051425Smccanne {
108151425Smccanne 	/*
108251425Smccanne 	 * We don't need to lock out interrupts since this descriptor has
108351425Smccanne 	 * been detached from its interface and it yet hasn't been marked
108451425Smccanne 	 * free.
108551425Smccanne 	 */
108651425Smccanne 	if (d->bd_hbuf)
108751425Smccanne 		free(d->bd_hbuf, M_DEVBUF);
108851425Smccanne 	if (d->bd_fbuf)
108951425Smccanne 		free(d->bd_fbuf, M_DEVBUF);
109051425Smccanne 	free(d->bd_sbuf, M_DEVBUF);
109151425Smccanne 	if (d->bd_filter)
109251425Smccanne 		free((caddr_t)d->bd_filter, M_DEVBUF);
109351425Smccanne 
109451425Smccanne 	D_MARKFREE(d);
109551425Smccanne }
109651425Smccanne 
109751425Smccanne /*
109851425Smccanne  * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if *)
109951425Smccanne  * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
110051425Smccanne  * size of the link header (variable length headers not yet supported).
110151425Smccanne  */
110247584Smccanne void
110349202Smccanne bpfattach(driverp, ifp, dlt, hdrlen)
110447584Smccanne 	caddr_t *driverp;
110547584Smccanne 	struct ifnet *ifp;
110649202Smccanne 	u_int dlt, hdrlen;
110747584Smccanne {
110847584Smccanne 	struct bpf_if *bp;
110947584Smccanne 	int i;
111051425Smccanne #if BSD < 199103
111151425Smccanne 	static struct bpf_if bpf_ifs[NBPFILTER];
111251425Smccanne 	static int bpfifno;
111347584Smccanne 
111451425Smccanne 	bp = (bpfifno < NBPFILTER) ? &bpf_ifs[bpfifno++] : 0;
111551425Smccanne #else
111649202Smccanne 	bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
111751425Smccanne #endif
111849202Smccanne 	if (bp == 0)
111949202Smccanne 		panic("bpfattach");
112047584Smccanne 
112147584Smccanne 	bp->bif_dlist = 0;
112247584Smccanne 	bp->bif_driverp = (struct bpf_if **)driverp;
112347584Smccanne 	bp->bif_ifp = ifp;
112449202Smccanne 	bp->bif_dlt = dlt;
112547584Smccanne 
112649202Smccanne 	bp->bif_next = bpf_iflist;
112749202Smccanne 	bpf_iflist = bp;
112849202Smccanne 
112948932Smccanne 	*bp->bif_driverp = 0;
113048932Smccanne 
113147584Smccanne 	/*
113247584Smccanne 	 * Compute the length of the bpf header.  This is not necessarily
113347584Smccanne 	 * equal to SIZEOF_BPF_HDR because we want to insert spacing such
113447584Smccanne 	 * that the network layer header begins on a longword boundary (for
113547584Smccanne 	 * performance reasons and to alleviate alignment restrictions).
113647584Smccanne 	 */
113749202Smccanne 	bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
113847584Smccanne 
113947584Smccanne 	/*
114047584Smccanne 	 * Mark all the descriptors free if this hasn't been done.
114147584Smccanne 	 */
114247584Smccanne 	if (!D_ISFREE(&bpf_dtab[0]))
114347584Smccanne 		for (i = 0; i < NBPFILTER; ++i)
114447584Smccanne 			D_MARKFREE(&bpf_dtab[i]);
114547584Smccanne 
114647584Smccanne 	printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit);
114747584Smccanne }
114847584Smccanne 
114951425Smccanne #if BSD >= 199103
115048967Smccanne /* XXX This routine belongs in net/if.c. */
115148932Smccanne /*
115248932Smccanne  * Set/clear promiscuous mode on interface ifp based on the truth value`
115348932Smccanne  * of pswitch.  The calls are reference counted so that only the first
115448932Smccanne  * on request actually has an effect, as does the final off request.
115548932Smccanne  * Results are undefined if the off and on requests are not matched.
115648932Smccanne  */
115748932Smccanne int
115848932Smccanne ifpromisc(ifp, pswitch)
115948932Smccanne 	struct ifnet *ifp;
116048932Smccanne 	int pswitch;
116148932Smccanne {
116249726Smccanne 	struct ifreq ifr;
116348932Smccanne 	/*
116448932Smccanne 	 * If the device is not configured up, we cannot put it in
116548932Smccanne 	 * promiscuous mode.
116648932Smccanne 	 */
116748932Smccanne 	if ((ifp->if_flags & IFF_UP) == 0)
116848932Smccanne 		return (ENETDOWN);
116948932Smccanne 
117048932Smccanne 	if (pswitch) {
117148932Smccanne 		if (ifp->if_pcount++ != 0)
117248932Smccanne 			return (0);
117348932Smccanne 		ifp->if_flags |= IFF_PROMISC;
117448932Smccanne 	} else {
117548932Smccanne 		if (--ifp->if_pcount > 0)
117648932Smccanne 			return (0);
117748932Smccanne 		ifp->if_flags &= ~IFF_PROMISC;
117848932Smccanne 	}
117949726Smccanne 	ifr.ifr_flags = ifp->if_flags;
118049726Smccanne 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
118148932Smccanne }
118251425Smccanne #endif
118348932Smccanne 
118451425Smccanne #if BSD < 199103
118551425Smccanne /*
118651425Smccanne  * Allocate some memory for bpf.  This is temporary SunOS support, and
118751425Smccanne  * is admittedly a gross hack.
118851425Smccanne  * If resources unavaiable, return 0.
118951425Smccanne  */
119051425Smccanne static caddr_t
119151425Smccanne bpf_alloc(size, canwait)
119251425Smccanne 	register int size;
119351425Smccanne 	register int canwait;
119451425Smccanne {
119551425Smccanne 	register struct mbuf *m;
119651425Smccanne 
119751425Smccanne 	if ((unsigned)size > (MCLBYTES-8))
119851425Smccanne 		return 0;
119951425Smccanne 
120051425Smccanne 	MGET(m, canwait, MT_DATA);
120151425Smccanne 	if (m == 0)
120251425Smccanne 		return 0;
120351425Smccanne 	if ((unsigned)size > (MLEN-8)) {
120451425Smccanne 		MCLGET(m);
120551425Smccanne 		if (m->m_len != MCLBYTES) {
120651425Smccanne 			m_freem(m);
120751425Smccanne 			return 0;
120851425Smccanne 		}
120951425Smccanne 	}
121051425Smccanne 	*mtod(m, struct mbuf **) = m;
121151425Smccanne 	return mtod(m, caddr_t) + 8;
121251425Smccanne }
121351425Smccanne #endif
121451425Smccanne #endif
1215