xref: /csrg-svn/sys/net/bpf.c (revision 49343)
1*49343Sbostic /*-
2*49343Sbostic  * Copyright (c) 1991 The Regents of the University of California.
347584Smccanne  * All rights reserved.
447584Smccanne  *
5*49343Sbostic  * This code is derived from the Stanford/CMU enet packet filter,
6*49343Sbostic  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
7*49343Sbostic  * to Berkeley by Steven McCanne of Lawrence Berkeley Laboratory.
847584Smccanne  *
9*49343Sbostic  * %sccs.include.redist.c%
10*49343Sbostic  *
11*49343Sbostic  *	@(#)bpf.c	7.1 (Berkeley) 05/07/91
12*49343Sbostic  *
13*49343Sbostic  * static char rcsid[] =
14*49343Sbostic  * "$Header: bpf.c,v 1.23 91/01/30 18:22:13 mccanne Exp $";
1547584Smccanne  */
1647584Smccanne 
1747584Smccanne #include "bpfilter.h"
1847584Smccanne 
1947584Smccanne #if (NBPFILTER > 0)
2047584Smccanne 
2147584Smccanne #include <sys/param.h>
2247584Smccanne #include <sys/systm.h>
2347584Smccanne #include <sys/mbuf.h>
2447584Smccanne #include <sys/buf.h>
2547584Smccanne #include <sys/dir.h>
2648932Smccanne #include <sys/proc.h>
2747584Smccanne #include <sys/user.h>
2847584Smccanne #include <sys/ioctl.h>
2947584Smccanne #include <sys/map.h>
3047584Smccanne 
3147584Smccanne #include <sys/file.h>
3247584Smccanne #ifdef sparc
3347584Smccanne #include <sys/stream.h>
3447584Smccanne #endif
3547584Smccanne #include <sys/tty.h>
3647584Smccanne #include <sys/uio.h>
3747584Smccanne 
3847584Smccanne #include <sys/protosw.h>
3947584Smccanne #include <sys/socket.h>
4047584Smccanne #include <net/if.h>
4147584Smccanne 
4247584Smccanne #include <net/bpf.h>
4347584Smccanne #include <net/bpfdesc.h>
4447584Smccanne 
4547584Smccanne #include <sys/errno.h>
4647584Smccanne 
4747584Smccanne #include <netinet/in.h>
4847584Smccanne #include <netinet/if_ether.h>
4947584Smccanne #include <sys/kernel.h>
5047584Smccanne 
5147584Smccanne #define PRINET  26			/* interruptible */
5247584Smccanne 
5347584Smccanne /*
5448932Smccanne  * The default read buffer size is patchable.
5548932Smccanne  */
5648932Smccanne int bpf_bufsize = MCLBYTES;
5748932Smccanne 
5848932Smccanne /*
5949202Smccanne  *  bpf_iflist is the list of interfaces; each corresponds to an ifnet
6049202Smccanne  *  bpf_dtab holds the descriptors, indexed by minor device #
6147584Smccanne  *
6247584Smccanne  * We really don't need NBPFILTER bpf_if entries, but this eliminates
6347584Smccanne  * the need to account for all possible drivers here.
6447584Smccanne  * This problem will go away when these structures are allocated dynamically.
6547584Smccanne  */
6649202Smccanne static struct bpf_if 	*bpf_iflist;
6747584Smccanne static struct bpf_d	bpf_dtab[NBPFILTER];
6847584Smccanne 
6947584Smccanne static void	bpf_ifname();
7047584Smccanne static void	catchpacket();
7147584Smccanne static int	bpf_setif();
7247584Smccanne static int	bpf_initd();
7347584Smccanne 
7447584Smccanne static int
7547584Smccanne bpf_movein(uio, linktype, mp, sockp)
7647584Smccanne 	register struct uio *uio;
7747584Smccanne 	int linktype;
7847584Smccanne 	register struct mbuf **mp;
7947584Smccanne 	register struct sockaddr *sockp;
8047584Smccanne {
8147584Smccanne 	struct mbuf *m;
8247584Smccanne 	int error;
8347584Smccanne 	int len;
8447584Smccanne 	int hlen;
8547584Smccanne 
8647584Smccanne 	/*
8747584Smccanne 	 * Build a sockaddr based on the data link layer type.
8847584Smccanne 	 * We do this at this level because the ethernet header
8947584Smccanne 	 * is copied directly into the data field of the sockaddr.
9047584Smccanne 	 * In the case of SLIP, there is no header and the packet
9147584Smccanne 	 * is forwarded as is.
9247584Smccanne 	 * Also, we are careful to leave room at the front of the mbuf
9347584Smccanne 	 * for the link level header.
9447584Smccanne 	 */
9547584Smccanne 	switch (linktype) {
9647584Smccanne 	case DLT_SLIP:
9747584Smccanne 		sockp->sa_family = AF_INET;
9847584Smccanne 		hlen = 0;
9947584Smccanne 		break;
10047584Smccanne 
10147584Smccanne 	case DLT_EN10MB:
10247584Smccanne 		sockp->sa_family = AF_UNSPEC;
10347584Smccanne 		/* XXX Would MAXLINKHDR be better? */
10447584Smccanne 		hlen = sizeof(struct ether_header);
10547584Smccanne 		break;
10647584Smccanne 
10747584Smccanne        case DLT_FDDI:
10847584Smccanne 		sockp->sa_family = AF_UNSPEC;
10947584Smccanne 		/* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
11047584Smccanne 		hlen = 24;
11147584Smccanne 		break;
11247584Smccanne 
11347584Smccanne 	default:
11448932Smccanne 		return (EIO);
11547584Smccanne 	}
11647584Smccanne 
11747584Smccanne 	len = uio->uio_resid;
11847584Smccanne 	if ((unsigned)len > MCLBYTES)
11948932Smccanne 		return (EIO);
12047584Smccanne 
12147584Smccanne 	MGET(m, M_WAIT, MT_DATA);
12247584Smccanne 	if (m == 0)
12348932Smccanne 		return (ENOBUFS);
12447584Smccanne 	if (len > MLEN) {
12548932Smccanne 		MCLGET(m, M_WAIT);
12648932Smccanne 		if ((m->m_flags & M_EXT) == 0) {
12747584Smccanne 			error = ENOBUFS;
12847584Smccanne 			goto bad;
12947584Smccanne 		}
13047584Smccanne 	}
13147584Smccanne 	m->m_len = len;
13247584Smccanne 	*mp = m;
13347584Smccanne 	/*
13447584Smccanne 	 * Make room for link header.
13547584Smccanne 	 */
13647584Smccanne 	if (hlen) {
13747584Smccanne 		m->m_len -= hlen;
13848932Smccanne 		m->m_data += hlen; /* XXX */
13947584Smccanne 
14048932Smccanne 		error = uiomove((caddr_t)sockp->sa_data, hlen, uio);
14147584Smccanne 		if (error)
14247584Smccanne 			goto bad;
14347584Smccanne 	}
14448932Smccanne 	error = uiomove(mtod(m, caddr_t), len - hlen, uio);
14547584Smccanne 	if (!error)
14648932Smccanne 		return (0);
14747584Smccanne  bad:
14847584Smccanne 	m_freem(m);
14948932Smccanne 	return (error);
15047584Smccanne }
15147584Smccanne 
15247584Smccanne /*
15347584Smccanne  * Attach 'd' to the bpf interface 'bp', i.e. make 'd' listen on 'bp'.
15447584Smccanne  * Must be called at splimp.
15547584Smccanne  */
15647584Smccanne static void
15747584Smccanne bpf_attachd(d, bp)
15847584Smccanne 	struct bpf_d *d;
15947584Smccanne 	struct bpf_if *bp;
16047584Smccanne {
16148932Smccanne 	/* Point d at bp. */
16247584Smccanne 	d->bd_bif = bp;
16347584Smccanne 
16448932Smccanne 	/* Add d to bp's list of listeners. */
16547584Smccanne 	d->bd_next = bp->bif_dlist;
16647584Smccanne 	bp->bif_dlist = d;
16747584Smccanne 
16847584Smccanne 	/*
16947584Smccanne 	 * Let the driver know we're here (if it doesn't already).
17047584Smccanne 	 */
17147584Smccanne 	*bp->bif_driverp = bp;
17247584Smccanne }
17347584Smccanne 
17447584Smccanne static void
17547584Smccanne bpf_detachd(d)
17647584Smccanne 	struct bpf_d *d;
17747584Smccanne {
17847584Smccanne 	struct bpf_d **p;
17947584Smccanne 	struct bpf_if *bp;
18047584Smccanne 
18147584Smccanne 	bp = d->bd_bif;
18247584Smccanne 	/*
18347584Smccanne 	 * Check if this descriptor had requested promiscuous mode.
18447584Smccanne 	 * If so, turn it off.
18547584Smccanne 	 */
18647584Smccanne 	if (d->bd_promisc) {
18747584Smccanne 		d->bd_promisc = 0;
18847584Smccanne 		if (ifpromisc(bp->bif_ifp, 0))
18947584Smccanne 			/*
19047584Smccanne 			 * Something is really wrong if we were able to put
19147584Smccanne 			 * the driver into promiscuous mode, but can't
19247584Smccanne 			 * take it out.
19347584Smccanne 			 */
19448932Smccanne 			panic("bpf_detachd: ifpromisc failed");
19547584Smccanne 	}
19647584Smccanne 	/* Remove 'd' from the interface's descriptor list. */
19747584Smccanne 	p = &bp->bif_dlist;
19847584Smccanne 	while (*p != d) {
19947584Smccanne 		p = &(*p)->bd_next;
20047584Smccanne 		if (*p == 0)
20147584Smccanne 			panic("bpf_detachd: descriptor not in list");
20247584Smccanne 	}
20347584Smccanne 	*p = (*p)->bd_next;
20447584Smccanne 	if (bp->bif_dlist == 0)
20547584Smccanne 		/*
20647584Smccanne 		 * Let the driver know that there are no more listeners.
20747584Smccanne 		 */
20847584Smccanne 		*d->bd_bif->bif_driverp = 0;
20947584Smccanne 	d->bd_bif = 0;
21047584Smccanne }
21147584Smccanne 
21247584Smccanne 
21347584Smccanne /*
21447584Smccanne  * Mark a descriptor free by making it point to itself.
21547584Smccanne  * This is probably cheaper than marking with a constant since
21647584Smccanne  * the address should be in a register anyway.
21747584Smccanne  */
21847584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next)
21947584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d))
22047584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0)
22147584Smccanne 
22247584Smccanne /*
22347584Smccanne  *  bpfopen - open ethernet device
22447584Smccanne  *
22547584Smccanne  *  Errors:	ENXIO	- illegal minor device number
22647584Smccanne  *		EBUSY	- too many files open
22747584Smccanne  */
22847584Smccanne /* ARGSUSED */
22947584Smccanne int
23047584Smccanne bpfopen(dev, flag)
23147584Smccanne 	dev_t dev;
23247584Smccanne 	int flag;
23347584Smccanne {
23447584Smccanne 	int error, s;
23547584Smccanne 	register struct bpf_d *d;
23647584Smccanne 
23747584Smccanne 	if (minor(dev) >= NBPFILTER)
23848932Smccanne 		return (ENXIO);
23947584Smccanne 
24047584Smccanne 	/*
24147584Smccanne 	 * Each minor can be opened by only one process.  If the requested
24247584Smccanne 	 * minor is in use, return EBUSY.
24347584Smccanne 	 */
24447584Smccanne 	s = splimp();
24547584Smccanne 	d = &bpf_dtab[minor(dev)];
24647584Smccanne 	if (!D_ISFREE(d)) {
24747584Smccanne 		splx(s);
24848932Smccanne 		return (EBUSY);
24947584Smccanne 	} else
25047584Smccanne 		/* Mark "free" and do most initialization. */
25147584Smccanne 		bzero((char *)d, sizeof(*d));
25247584Smccanne 	splx(s);
25347584Smccanne 
25447584Smccanne 	error = bpf_initd(d);
25547584Smccanne 	if (error) {
25647584Smccanne 		D_MARKFREE(d);
25748932Smccanne 		return (error);
25847584Smccanne 	}
25948932Smccanne 	return (0);
26047584Smccanne }
26147584Smccanne 
26247584Smccanne /*
26347584Smccanne  * Close the descriptor by detaching it from its interface,
26447584Smccanne  * deallocating its buffers, and marking it free.
26547584Smccanne  */
26647584Smccanne /* ARGSUSED */
26747584Smccanne bpfclose(dev, flag)
26847584Smccanne 	dev_t dev;
26947584Smccanne 	int flag;
27047584Smccanne {
27147584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
27247584Smccanne 	int s;
27347584Smccanne 
27447584Smccanne 	s = splimp();
27547584Smccanne 	if (d->bd_bif)
27647584Smccanne 		bpf_detachd(d);
27747584Smccanne 	splx(s);
27847584Smccanne 
27948932Smccanne 	/* Free the buffer space. */
28048932Smccanne 	if (d->bd_hbuf)
28148932Smccanne 		free(d->bd_hbuf, M_DEVBUF);
28248932Smccanne 	if (d->bd_fbuf)
28348932Smccanne 		free(d->bd_fbuf, M_DEVBUF);
28448932Smccanne 	free(d->bd_sbuf, M_DEVBUF);
28548967Smccanne 	if (d->bd_filter)
28648932Smccanne 		free((caddr_t)d->bd_filter, M_DEVBUF);
28747584Smccanne 
28847584Smccanne 	D_MARKFREE(d);
28947584Smccanne }
29047584Smccanne 
29147584Smccanne /*
29248932Smccanne  * Rotate the packet buffers in descriptor d.  Move the store buffer
29348932Smccanne  * into the hold slot, and the free buffer into the store slot.
29448932Smccanne  * Zero the length of the new store buffer.
29548932Smccanne  */
29648932Smccanne #define ROTATE_BUFFERS(d) \
29748932Smccanne 	(d)->bd_hbuf = (d)->bd_sbuf; \
29848932Smccanne 	(d)->bd_hlen = (d)->bd_slen; \
29948932Smccanne 	(d)->bd_sbuf = (d)->bd_fbuf; \
30048932Smccanne 	(d)->bd_slen = 0; \
30148932Smccanne 	(d)->bd_fbuf = 0;
30248932Smccanne /*
30347584Smccanne  *  bpfread - read next chunk of packets from buffers
30447584Smccanne  */
30547584Smccanne int
30647584Smccanne bpfread(dev, uio)
30747584Smccanne 	dev_t dev;
30847584Smccanne 	register struct uio *uio;
30947584Smccanne {
31047584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
31147584Smccanne 	int error;
31247584Smccanne 	int s;
31347584Smccanne 
31447584Smccanne 	/*
31547584Smccanne 	 * Restrict application to use a buffer the same size as
31647584Smccanne 	 * as kernel buffers.
31747584Smccanne 	 */
31848932Smccanne 	if (uio->uio_resid != d->bd_bufsize)
31949202Smccanne 		return (EINVAL);
32047584Smccanne 
32147584Smccanne 	s = splimp();
32247584Smccanne 	/*
32347584Smccanne 	 * If the hold buffer is empty, then set a timer and sleep
32447584Smccanne 	 * until either the timeout has occurred or enough packets have
32547584Smccanne 	 * arrived to fill the store buffer.
32647584Smccanne 	 */
32747584Smccanne 	while (d->bd_hbuf == 0) {
32848932Smccanne 		if (d->bd_immediate && d->bd_slen != 0) {
32947584Smccanne 			/*
33047584Smccanne 			 * A packet(s) either arrived since the previous
33147584Smccanne 			 * read or arrived while we were asleep.
33247584Smccanne 			 * Rotate the buffers and return what's here.
33347584Smccanne 			 */
33448932Smccanne 			ROTATE_BUFFERS(d);
33547584Smccanne 			break;
33647584Smccanne 		}
33748932Smccanne 		error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf", d->bd_rtout);
33848932Smccanne 		if (error == EINTR || error == ERESTART) {
33948932Smccanne 			splx(s);
34048932Smccanne 			return (error);
34147584Smccanne 		}
34248932Smccanne 		if (error == EWOULDBLOCK) {
34347584Smccanne 			/*
34447584Smccanne 			 * On a timeout, return what's in the buffer,
34548932Smccanne 			 * which may be nothing.  If there is something
34648932Smccanne 			 * in the store buffer, we can rotate the buffers.
34747584Smccanne 			 */
34847584Smccanne 			if (d->bd_hbuf)
34947584Smccanne 				/*
35047584Smccanne 				 * We filled up the buffer in between
35147584Smccanne 				 * getting the timeout and arriving
35247584Smccanne 				 * here, so we don't need to rotate.
35347584Smccanne 				 */
35447584Smccanne 				break;
35547584Smccanne 
35648932Smccanne 			if (d->bd_slen == 0) {
35747584Smccanne 				splx(s);
35848932Smccanne 				return (0);
35947584Smccanne 			}
36048932Smccanne 			ROTATE_BUFFERS(d);
36147584Smccanne 			break;
36247584Smccanne 		}
36347584Smccanne 	}
36447584Smccanne 	/*
36547584Smccanne 	 * At this point, we know we have something in the hold slot.
36647584Smccanne 	 */
36747584Smccanne 	splx(s);
36847584Smccanne 
36947584Smccanne 	/*
37047584Smccanne 	 * Move data from hold buffer into user space.
37147584Smccanne 	 * We know the entire buffer is transferred since
37248932Smccanne 	 * we checked above that the read buffer is bpf_bufsize bytes.
37347584Smccanne 	 */
37448932Smccanne 	error = uiomove(d->bd_hbuf, d->bd_hlen, uio);
37547584Smccanne 
37647584Smccanne 	s = splimp();
37748932Smccanne 	d->bd_fbuf = d->bd_hbuf;
37848932Smccanne 	d->bd_hbuf = 0;
37947584Smccanne 	splx(s);
38047584Smccanne 
38148932Smccanne 	return (error);
38247584Smccanne }
38347584Smccanne 
38447584Smccanne 
38547584Smccanne /*
38648932Smccanne  * If there are processes sleeping on this descriptor, wake them up.
38747584Smccanne  */
38847584Smccanne static inline void
38947584Smccanne bpf_wakeup(d)
39047584Smccanne 	register struct bpf_d *d;
39147584Smccanne {
39248932Smccanne 	wakeup((caddr_t)d);
39348932Smccanne 	if (d->bd_selproc) {
39448932Smccanne 		selwakeup(d->bd_selproc, (int)d->bd_selcoll);
39548932Smccanne 		d->bd_selcoll = 0;
39648932Smccanne 		d->bd_selproc = 0;
39747584Smccanne 	}
39847584Smccanne }
39947584Smccanne 
40047584Smccanne int
40147584Smccanne bpfwrite(dev, uio)
40247584Smccanne 	dev_t dev;
40347584Smccanne 	struct uio *uio;
40447584Smccanne {
40547584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
40647584Smccanne 	struct ifnet *ifp;
40747584Smccanne 	struct mbuf *m;
40847584Smccanne 	int error, s;
40947584Smccanne 	static struct sockaddr dst;
41047584Smccanne 
41147584Smccanne 	if (d->bd_bif == 0)
41248932Smccanne 		return (ENXIO);
41347584Smccanne 
41447584Smccanne 	ifp = d->bd_bif->bif_ifp;
41547584Smccanne 
41647584Smccanne 	if (uio->uio_resid == 0)
41748932Smccanne 		return (0);
41847584Smccanne 	if (uio->uio_resid > ifp->if_mtu)
41948932Smccanne 		return (EMSGSIZE);
42047584Smccanne 
42149202Smccanne 	error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst);
42247584Smccanne 	if (error)
42348932Smccanne 		return (error);
42447584Smccanne 
42547584Smccanne 	s = splnet();
42647584Smccanne 	error = (*ifp->if_output)(ifp, m, &dst);
42747584Smccanne 	splx(s);
42847584Smccanne 	/*
42947584Smccanne 	 * The driver frees the mbuf.
43047584Smccanne 	 */
43148932Smccanne 	return (error);
43247584Smccanne }
43347584Smccanne 
43447584Smccanne /*
43548932Smccanne  * Reset a descriptor by flushing its packet bufferand clearing the receive
43648932Smccanne  * and drop counts.  Should be called at splimp.
43747584Smccanne  */
43847584Smccanne static void
43947584Smccanne reset_d(d)
44047584Smccanne 	struct bpf_d *d;
44147584Smccanne {
44247584Smccanne 	if (d->bd_hbuf) {
44347584Smccanne 		/* Free the hold buffer. */
44447584Smccanne 		d->bd_fbuf = d->bd_hbuf;
44547584Smccanne 		d->bd_hbuf = 0;
44647584Smccanne 	}
44748932Smccanne 	d->bd_slen = 0;
44847584Smccanne 	d->bd_rcount = 0;
44947584Smccanne 	d->bd_dcount = 0;
45047584Smccanne }
45147584Smccanne 
45247584Smccanne /*
45347584Smccanne  *  FIONREAD		Check for read packet available.
45447584Smccanne  *  SIOCGIFADDR		Get interface address - convenient hook to driver.
45547584Smccanne  *  BIOCGFLEN		Get max filter len.
45647584Smccanne  *  BIOCGBLEN		Get buffer len [for read()].
45747584Smccanne  *  BIOCSETF		Set ethernet read filter.
45847584Smccanne  *  BIOCFLUSH		Flush read packet buffer.
45947584Smccanne  *  BIOCPROMISC		Put interface into promiscuous mode.
46049202Smccanne  *  BIOCGDLT		Get link layer type.
46147584Smccanne  *  BIOCGETIF		Get interface name.
46247584Smccanne  *  BIOCSETIF		Set interface.
46347584Smccanne  *  BIOCSRTIMEOUT	Set read timeout.
46447584Smccanne  *  BIOCGRTIMEOUT	Get read timeout.
46547584Smccanne  *  BIOCGSTATS		Get packet stats.
46647584Smccanne  *  BIOCIMMEDIATE	Set immediate mode.
46747584Smccanne  */
46847584Smccanne /* ARGSUSED */
46947584Smccanne int
47047584Smccanne bpfioctl(dev, cmd, addr, flag)
47147584Smccanne 	dev_t dev;
47247584Smccanne 	int cmd;
47347584Smccanne 	caddr_t addr;
47447584Smccanne 	int flag;
47547584Smccanne {
47647584Smccanne 	register struct bpf_d *d = &bpf_dtab[minor(dev)];
47747584Smccanne 	int s, error = 0;
47847584Smccanne 
47947584Smccanne 	switch (cmd) {
48047584Smccanne 
48147584Smccanne 	default:
48247584Smccanne 		error = EINVAL;
48347584Smccanne 		break;
48447584Smccanne 
48547584Smccanne 	/*
48647584Smccanne 	 * Check for read packet available.
48747584Smccanne 	 */
48847584Smccanne 	case FIONREAD:
48947584Smccanne 		{
49047584Smccanne 			int n;
49147584Smccanne 
49247584Smccanne 			s = splimp();
49348932Smccanne 			n = d->bd_slen;
49447584Smccanne 			if (d->bd_hbuf)
49548932Smccanne 				n += d->bd_hlen;
49647584Smccanne 			splx(s);
49747584Smccanne 
49847584Smccanne 			*(int *)addr = n;
49947584Smccanne 			break;
50047584Smccanne 		}
50147584Smccanne 
50247584Smccanne 	case SIOCGIFADDR:
50347584Smccanne 		{
50447584Smccanne 			struct ifnet *ifp;
50547584Smccanne 
50647584Smccanne 			if (d->bd_bif == 0)
50747584Smccanne 				error = EINVAL;
50847584Smccanne 			else {
50947584Smccanne 				ifp = d->bd_bif->bif_ifp;
51047584Smccanne 				error =  (*ifp->if_ioctl)(ifp, cmd, addr);
51147584Smccanne 			}
51247584Smccanne 			break;
51347584Smccanne 		}
51447584Smccanne 
51547584Smccanne 	/*
51647584Smccanne 	 * Get max filter len.
51747584Smccanne 	 */
51847584Smccanne 	case BIOCGFLEN:
51948932Smccanne 		*(u_int *)addr = BPF_MAXINSNS;
52047584Smccanne 		break;
52147584Smccanne 	/*
52247584Smccanne 	 * Get buffer len [for read()].
52347584Smccanne 	 */
52447584Smccanne 	case BIOCGBLEN:
52548932Smccanne 		*(u_int *)addr = d->bd_bufsize;
52647584Smccanne 		break;
52747584Smccanne 
52847584Smccanne 	/*
52947584Smccanne 	 * Set ethernet read filter.
53047584Smccanne 	 */
53147584Smccanne         case BIOCSETF:
53247584Smccanne 		error = bpf_setf(d, (struct bpf_program *)addr);
53347584Smccanne 		break;
53447584Smccanne 
53547584Smccanne 	/*
53647584Smccanne 	 * Flush read packet buffer.
53747584Smccanne 	 */
53847584Smccanne 	case BIOCFLUSH:
53947584Smccanne 		s = splimp();
54047584Smccanne 		reset_d(d);
54147584Smccanne 		splx(s);
54247584Smccanne 		break;
54347584Smccanne 
54447584Smccanne 	/*
54547584Smccanne 	 * Put interface into promiscuous mode.
54647584Smccanne 	 */
54747584Smccanne 	case BIOCPROMISC:
54847584Smccanne 		if (d->bd_bif == 0) {
54947584Smccanne 			/*
55047584Smccanne 			 * No interface attached yet.
55147584Smccanne 			 */
55247584Smccanne 			error = EINVAL;
55347584Smccanne 			break;
55447584Smccanne 		}
55547584Smccanne 		s = splimp();
55647584Smccanne 		if (d->bd_promisc == 0) {
55747584Smccanne 			d->bd_promisc = 1;
55847584Smccanne 			error = ifpromisc(d->bd_bif->bif_ifp, 1);
55947584Smccanne 		}
56047584Smccanne 		splx(s);
56147584Smccanne 		break;
56247584Smccanne 
56347584Smccanne 	/*
56447584Smccanne 	 * Get device parameters.
56547584Smccanne 	 */
56649202Smccanne 	case BIOCGDLT:
56747584Smccanne 		if (d->bd_bif == 0)
56847584Smccanne 			error = EINVAL;
56947584Smccanne 		else
57049202Smccanne 			*(u_int *)addr = d->bd_bif->bif_dlt;
57147584Smccanne 		break;
57247584Smccanne 
57347584Smccanne 	/*
57447584Smccanne 	 * Set interface name.
57547584Smccanne 	 */
57647584Smccanne 	case BIOCGETIF:
57747584Smccanne 		if (d->bd_bif == 0)
57847584Smccanne 			error = EINVAL;
57947584Smccanne 		else
58047584Smccanne 			bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
58147584Smccanne 		break;
58247584Smccanne 
58347584Smccanne 	/*
58447584Smccanne 	 * Set interface.
58547584Smccanne 	 */
58647584Smccanne 	case BIOCSETIF:
58747584Smccanne 		error = bpf_setif(d, (struct ifreq *)addr);
58847584Smccanne 		break;
58947584Smccanne 
59047584Smccanne 	/*
59147584Smccanne 	 * Set read timeout.
59247584Smccanne 	 */
59347584Smccanne  	case BIOCSRTIMEOUT:
59447584Smccanne 		{
59547584Smccanne 			struct timeval *tv = (struct timeval *)addr;
59647584Smccanne 			u_long msec;
59747584Smccanne 
59847584Smccanne 			/* Compute number of milliseconds. */
59947584Smccanne 			msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
60047584Smccanne 			/* Scale milliseconds to ticks.  Assume hard
60147584Smccanne 			   clock has millisecond or greater resolution
60247584Smccanne 			   (i.e. tick >= 1000).  For 10ms hardclock,
60347584Smccanne 			   tick/1000 = 10, so rtout<-msec/10. */
60447584Smccanne 			d->bd_rtout = msec / (tick / 1000);
60547584Smccanne 			break;
60647584Smccanne 		}
60747584Smccanne 
60847584Smccanne 	/*
60947584Smccanne 	 * Get read timeout.
61047584Smccanne 	 */
61147584Smccanne  	case BIOCGRTIMEOUT:
61247584Smccanne 		{
61347584Smccanne 			struct timeval *tv = (struct timeval *)addr;
61447584Smccanne 			u_long msec = d->bd_rtout;
61547584Smccanne 
61647584Smccanne 			msec *= tick / 1000;
61747584Smccanne 			tv->tv_sec = msec / 1000;
61847584Smccanne 			tv->tv_usec = msec % 1000;
61947584Smccanne 			break;
62047584Smccanne 		}
62147584Smccanne 
62247584Smccanne 	/*
62347584Smccanne 	 * Get packet stats.
62447584Smccanne 	 */
62547584Smccanne 	case BIOCGSTATS:
62647584Smccanne 		{
62747584Smccanne 			struct bpf_stat *bs = (struct bpf_stat *)addr;
62847584Smccanne 
62947584Smccanne 			bs->bs_recv = d->bd_rcount;
63047584Smccanne 			bs->bs_drop = d->bd_dcount;
63147584Smccanne 			break;
63247584Smccanne 		}
63347584Smccanne 
63447584Smccanne 	/*
63547584Smccanne 	 * Set immediate mode.
63647584Smccanne 	 */
63747584Smccanne 	case BIOCIMMEDIATE:
63847584Smccanne 		d->bd_immediate = *(u_int *)addr;
63947584Smccanne 		break;
64047584Smccanne 	}
64148932Smccanne 	return (error);
64247584Smccanne }
64347584Smccanne 
64447584Smccanne /*
64547584Smccanne  * Set d's packet filter program to 'fp'.  If 'd' already has a filter,
64648932Smccanne  * free it and replace it.  Returns EINVAL for bogus requests.
64747584Smccanne  */
64847584Smccanne int
64947584Smccanne bpf_setf(d, fp)
65047584Smccanne 	struct bpf_d *d;
65147584Smccanne 	struct bpf_program *fp;
65247584Smccanne {
65348932Smccanne 	struct bpf_insn *fcode, *old;
65447584Smccanne 	u_int flen, size;
65547584Smccanne 	int s;
65647584Smccanne 
65748932Smccanne 	old = d->bd_filter;
65847584Smccanne 	if (fp->bf_insns == 0) {
65947584Smccanne 		if (fp->bf_len != 0)
66048932Smccanne 			return (EINVAL);
66148932Smccanne 		s = splimp();
66248967Smccanne 		d->bd_filter = 0;
66347584Smccanne 		reset_d(d);
66447584Smccanne 		splx(s);
66548967Smccanne 		if (old != 0)
66648932Smccanne 			free((caddr_t)old, M_DEVBUF);
66748932Smccanne 		return (0);
66847584Smccanne 	}
66947584Smccanne 	flen = fp->bf_len;
67048932Smccanne 	if (flen > BPF_MAXINSNS)
67148932Smccanne 		return (EINVAL);
67248932Smccanne 
67347584Smccanne 	size = flen * sizeof(*fp->bf_insns);
67448932Smccanne 	fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
67548932Smccanne 	if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size))
67648932Smccanne 		return (EINVAL);
67747584Smccanne 
67847584Smccanne 	if (bpf_validate(fcode, (int)flen)) {
67948967Smccanne 		s = splimp();
68048932Smccanne 		d->bd_filter = fcode;
68147584Smccanne 		reset_d(d);
68247584Smccanne 		splx(s);
68348967Smccanne 		if (old != 0)
68448932Smccanne 			free((caddr_t)old, M_DEVBUF);
68547584Smccanne 
68648932Smccanne 		return (0);
68747584Smccanne 	}
68848932Smccanne 	free((caddr_t)fcode, M_DEVBUF);
68948932Smccanne 	return (EINVAL);
69047584Smccanne }
69147584Smccanne 
69247584Smccanne /*
69347584Smccanne  * Detach 'd' from its current interface (if attached at all) and attach to
69447584Smccanne  * the interface named 'name'.  Return ioctl error code or 0.
69547584Smccanne  */
69647584Smccanne static int
69747584Smccanne bpf_setif(d, ifr)
69847584Smccanne 	struct bpf_d *d;
69947584Smccanne 	struct ifreq *ifr;
70047584Smccanne {
70147584Smccanne 	struct bpf_if *bp;
70247584Smccanne 	char *cp;
70349202Smccanne 	int unit, s;
70447584Smccanne 
70547584Smccanne 	/*
70647584Smccanne 	 * Separate string into name part and unit number.  Put a null
70747584Smccanne 	 * byte at the end of the name part, and compute the number.
70847584Smccanne 	 * If the a unit number is unspecified, the default is 0,
70948932Smccanne 	 * as initialized above.  XXX This should be common code.
71047584Smccanne 	 */
71147584Smccanne 	unit = 0;
71247584Smccanne 	cp = ifr->ifr_name;
71347584Smccanne 	cp[sizeof(ifr->ifr_name) - 1] = '\0';
71447584Smccanne 	while (*cp++) {
71547584Smccanne 		if (*cp >= '0' && *cp <= '9') {
71647584Smccanne 			unit = *cp - '0';
71747584Smccanne 			*cp++ = '\0';
71847584Smccanne 			while (*cp)
71947584Smccanne 				unit = 10 * unit + *cp++ - '0';
72047584Smccanne 			break;
72147584Smccanne 		}
72247584Smccanne 	}
72347584Smccanne 	/*
72447584Smccanne 	 * Look through attached interfaces for the named one.
72547584Smccanne 	 */
72649202Smccanne 	for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
72747584Smccanne 		struct ifnet *ifp = bp->bif_ifp;
72847584Smccanne 
72947584Smccanne 		if (ifp == 0 || unit != ifp->if_unit
73047584Smccanne 		    || strcmp(ifp->if_name, ifr->ifr_name) != 0)
73147584Smccanne 			continue;
73247584Smccanne 		/*
73347584Smccanne 		 * We found the requested interface.  If we're
73447584Smccanne 		 * already attached to it, just flush the buffer.
73547584Smccanne 		 * If it's not up, return an error.
73647584Smccanne 		 */
73747584Smccanne 		if ((ifp->if_flags & IFF_UP) == 0)
73848932Smccanne 			return (ENETDOWN);
73947584Smccanne 		s = splimp();
74047584Smccanne 		if (bp != d->bd_bif) {
74147584Smccanne 			if (d->bd_bif)
74247584Smccanne 				/*
74348932Smccanne 				 * Detach if attached to something else.
74447584Smccanne 				 */
74547584Smccanne 				bpf_detachd(d);
74647584Smccanne 
74747584Smccanne 			bpf_attachd(d, bp);
74847584Smccanne 		}
74947584Smccanne 		reset_d(d);
75047584Smccanne 		splx(s);
75148932Smccanne 		return (0);
75247584Smccanne 	}
75347584Smccanne 	/* Not found. */
75448932Smccanne 	return (ENXIO);
75547584Smccanne }
75647584Smccanne 
75747584Smccanne /*
75847584Smccanne  * Lookup the name of the 'ifp' interface and return it in 'ifr->ifr_name'.
75947584Smccanne  * We augment the ifp's base name with its unit number.
76047584Smccanne  */
76147584Smccanne static void
76247584Smccanne bpf_ifname(ifp, ifr)
76347584Smccanne 	struct ifnet *ifp;
76447584Smccanne 	struct ifreq *ifr;
76547584Smccanne {
76647584Smccanne 	char *s = ifp->if_name;
76747584Smccanne 	char *d = ifr->ifr_name;
76847584Smccanne 
76947584Smccanne 	while (*d++ = *s++)
77047584Smccanne 		;
77148932Smccanne 	/* XXX Assume that unit number is less than 10. */
77247584Smccanne 	*d++ = ifp->if_unit + '0';
77347584Smccanne 	*d = '\0';
77447584Smccanne }
77547584Smccanne 
77647584Smccanne /*
77747584Smccanne  * Support for select() system call
77847584Smccanne  * Inspired by the code in tty.c for the same purpose.
77947584Smccanne  *
78047584Smccanne  * bpfselect - returns true iff the specific operation
78147584Smccanne  *	will not block indefinitely.  Otherwise, return
78247584Smccanne  *	false but make a note that a selwakeup() must be done.
78347584Smccanne  */
78447584Smccanne int
78548932Smccanne bpfselect(dev, rw, p)
78647584Smccanne 	register dev_t dev;
78747584Smccanne 	int rw;
78848932Smccanne 	struct proc *p;
78947584Smccanne {
79047584Smccanne 	register struct bpf_d *d;
79147584Smccanne 	register int s;
79247584Smccanne 
79347584Smccanne 	if (rw != FREAD)
79448932Smccanne 		return (0);
79547584Smccanne 	/*
79647584Smccanne 	 * An imitation of the FIONREAD ioctl code.
79747584Smccanne 	 */
79847584Smccanne 	d = &bpf_dtab[minor(dev)];
79947584Smccanne 
80047584Smccanne 	s = splimp();
80148932Smccanne 	if (d->bd_slen != 0 || d->bd_hbuf && d->bd_hlen != 0) {
80247584Smccanne 		/*
80347584Smccanne 		 * There is data waiting.
80447584Smccanne 		 */
80547584Smccanne 		splx(s);
80648932Smccanne 		return (1);
80747584Smccanne 	}
80847584Smccanne 	/*
80947584Smccanne 	 * No data ready.  If there's already a select() waiting on this
81047584Smccanne 	 * minor device then this is a collision.  This shouldn't happen
81147584Smccanne 	 * because minors really should not be shared, but if a process
81247584Smccanne 	 * forks while one of these is open, it is possible that both
81347584Smccanne 	 * processes could select on the same descriptor.
81447584Smccanne 	 */
81548932Smccanne 	if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait)
81648932Smccanne 		d->bd_selcoll = 1;
81747584Smccanne 	else
81848932Smccanne 		d->bd_selproc = p;
81948932Smccanne 
82047584Smccanne 	splx(s);
82148932Smccanne 	return (0);
82247584Smccanne }
82347584Smccanne 
82447584Smccanne /*
82547584Smccanne  * bpf_tap - incoming linkage from device drivers
82647584Smccanne  */
82747584Smccanne void
82848932Smccanne bpf_tap(arg, pkt, pktlen)
82947584Smccanne 	caddr_t arg;
83048932Smccanne 	register u_char *pkt;
83148932Smccanne 	register u_int pktlen;
83247584Smccanne {
83347584Smccanne 	struct bpf_if *bp;
83447584Smccanne 	register struct bpf_d *d;
83547584Smccanne 	register u_int slen;
83647584Smccanne 	/*
83747584Smccanne 	 * Note that the ipl does not have to be raised at this point.
83847584Smccanne 	 * The only problem that could arise here is that if two different
83947584Smccanne 	 * interfaces shared any data.  This is not the case.
84047584Smccanne 	 */
84147584Smccanne 	bp = (struct bpf_if *)arg;
84247584Smccanne 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
84347584Smccanne 		++d->bd_rcount;
84449202Smccanne 		if (d->bd_filter == 0) {
84549202Smccanne 			catchpacket(d, pkt, pktlen, (u_int)-1, bcopy);
84649202Smccanne 			continue;
84749202Smccanne 		}
84849202Smccanne 		slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
84947584Smccanne 		if (slen != 0)
85049202Smccanne 			catchpacket(d, pkt, pktlen, slen, bcopy);
85147584Smccanne 	}
85247584Smccanne }
85347584Smccanne 
85447584Smccanne /*
85547584Smccanne  * Copy data from an mbuf chain into a buffer.  This code is derived
85647584Smccanne  * from m_copydata in sys/uipc_mbuf.c.
85747584Smccanne  */
85847584Smccanne static void
85949202Smccanne bpf_mcopy(src, dst, len)
86047584Smccanne 	u_char *src;
86147584Smccanne 	u_char *dst;
86247584Smccanne 	register int len;
86347584Smccanne {
86447584Smccanne 	register struct mbuf *m = (struct mbuf *)src;
86547584Smccanne 	register unsigned count;
86647584Smccanne 
86747584Smccanne 	while (len > 0) {
86847584Smccanne 		if (m == 0)
86949202Smccanne 			panic("bpf_mcopy");
87047584Smccanne 		count = MIN(m->m_len, len);
87149202Smccanne 		bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
87249202Smccanne 		m = m->m_next;
87349202Smccanne 		dst += count;
87447584Smccanne 		len -= count;
87547584Smccanne 	}
87647584Smccanne }
87747584Smccanne 
87847584Smccanne /*
87948932Smccanne  * Length of ethernet and TCP/IP header with no IP options.
88047584Smccanne  */
88147584Smccanne #define BPF_MIN_SNAPLEN 50
88247584Smccanne 
88347584Smccanne /*
88447584Smccanne  * bpf_mtap - incoming linkage from device drivers, when packet
88547584Smccanne  *   is in an mbuf chain
88647584Smccanne  */
88747584Smccanne void
88849202Smccanne bpf_mtap(arg, m)
88947584Smccanne 	caddr_t arg;
89049202Smccanne 	struct mbuf *m;
89147584Smccanne {
89247584Smccanne 	struct bpf_if *bp = (struct bpf_if *)arg;
89347584Smccanne 	struct bpf_d *d;
89449202Smccanne 	u_int pktlen, slen;
89549202Smccanne 	struct mbuf *m0;
89647584Smccanne 
89748932Smccanne 	pktlen = 0;
89849202Smccanne 	m0 = m;
89949202Smccanne 	while (m0) {
90049202Smccanne 		pktlen += m0->m_len;
90149202Smccanne 		m0 = m0->m_next;
90247584Smccanne 	}
90347584Smccanne 	for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
90447584Smccanne 		++d->bd_rcount;
90549202Smccanne 		if (d->bd_filter == 0) {
90649202Smccanne 			catchpacket(d, (u_char *)m, pktlen, (u_int)-1,
90749202Smccanne 				    bpf_mcopy);
90849202Smccanne 			continue;
90949202Smccanne 		}
91049202Smccanne 		slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
91147584Smccanne 		if (slen != 0)
91249202Smccanne 			catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
91347584Smccanne 	}
91447584Smccanne }
91547584Smccanne 
91647584Smccanne /*
91749202Smccanne  * Move the packet data from interface memory (pkt) into the
91847584Smccanne  * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
91947584Smccanne  * otherwise 0.  'copy' is the routine called to do the actual data
92047584Smccanne  * transfer.  'bcopy' is passed in to copy contiguous chunks, while
92149202Smccanne  * 'bpf_mcopy' is passed in to copy mbuf chains.  In the latter
92248932Smccanne  * case, 'pkt' is really an mbuf.
92347584Smccanne  */
92447584Smccanne static void
92548932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn)
92648932Smccanne 	register struct bpf_d *d;
92748932Smccanne 	register u_char *pkt;
92848932Smccanne 	register u_int pktlen, snaplen;
92948932Smccanne 	register void (*cpfn)();
93047584Smccanne {
93148932Smccanne 	register struct bpf_hdr *hp;
93248932Smccanne 	register int totlen, curlen;
93348932Smccanne 	register int hdrlen = d->bd_bif->bif_hdrlen;
93447584Smccanne 	/*
93547584Smccanne 	 * Figure out how many bytes to move.  If the packet is
93647584Smccanne 	 * greater or equal to the snapshot length, transfer that
93747584Smccanne 	 * much.  Otherwise, transfer the whole packet (unless
93848932Smccanne 	 * we hit the buffer size limit).
93947584Smccanne 	 */
94048932Smccanne 	if (snaplen <= pktlen)
94147584Smccanne 		totlen = snaplen + hdrlen;
94247584Smccanne 	else {
94348932Smccanne 		totlen = pktlen + hdrlen;
94448932Smccanne 		if (totlen > d->bd_bufsize)
94548932Smccanne 			totlen = d->bd_bufsize;
94647584Smccanne 	}
94747584Smccanne 
94847584Smccanne 	/*
94947584Smccanne 	 * Round up the end of the previous packet to the next longword.
95047584Smccanne 	 */
95148932Smccanne 	curlen = BPF_WORDALIGN(d->bd_slen);
95248932Smccanne 	if (curlen + totlen > d->bd_bufsize) {
95347584Smccanne 		/*
95447584Smccanne 		 * This packet will overflow the storage buffer.
95548932Smccanne 		 * Rotate the buffers if we can, then wakeup any
95648932Smccanne 		 * pending reads.
95747584Smccanne 		 */
95847584Smccanne 		if (d->bd_fbuf == 0) {
95947584Smccanne 			/*
96048932Smccanne 			 * We haven't completed the previous read yet,
96148932Smccanne 			 * so drop the packet.
96247584Smccanne 			 */
96347584Smccanne 			++d->bd_dcount;
96447584Smccanne 			return;
96547584Smccanne 		}
96648932Smccanne 		ROTATE_BUFFERS(d);
96747584Smccanne 		bpf_wakeup(d);
96848932Smccanne 		curlen = 0;
96947584Smccanne 	}
97048932Smccanne 	else if (d->bd_immediate)
97147584Smccanne 		/*
97247584Smccanne 		 * Immediate mode is set.  A packet arrived so any
97347584Smccanne 		 * reads should be woken up.
97447584Smccanne 		 */
97547584Smccanne 		bpf_wakeup(d);
97648932Smccanne 
97747584Smccanne 	/*
97847584Smccanne 	 * Append the bpf header.
97947584Smccanne 	 */
98048932Smccanne 	hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
98147584Smccanne #ifdef sun
98247584Smccanne 	uniqtime(&hp->bh_tstamp);
98347584Smccanne #else
98447584Smccanne #ifdef hp300
98547584Smccanne 	microtime(&hp->bh_tstamp);
98647584Smccanne #else
98747584Smccanne 	hp->bh_tstamp = time;
98847584Smccanne #endif
98947584Smccanne #endif
99048932Smccanne 	hp->bh_datalen = pktlen;
99147584Smccanne 	hp->bh_hdrlen = hdrlen;
99247584Smccanne 	/*
99348932Smccanne 	 * Copy the packet data into the store buffer and update its length.
99447584Smccanne 	 */
99548932Smccanne 	(*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
99648932Smccanne 	d->bd_slen = curlen + totlen;
99747584Smccanne }
99847584Smccanne 
99947584Smccanne /*
100047584Smccanne  * Initialize all nonzero fields of a descriptor.
100147584Smccanne  */
100247584Smccanne static int
100347584Smccanne bpf_initd(d)
100447584Smccanne 	register struct bpf_d *d;
100547584Smccanne {
100648932Smccanne 	d->bd_bufsize = bpf_bufsize;
100748932Smccanne 	d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
100848932Smccanne 	if (d->bd_fbuf == 0)
100948932Smccanne 		return (ENOBUFS);
101047584Smccanne 
101148932Smccanne 	d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
101248932Smccanne 	if (d->bd_sbuf == 0) {
101348932Smccanne 		free(d->bd_fbuf, M_DEVBUF);
101448932Smccanne 		return (ENOBUFS);
101547584Smccanne 	}
101648932Smccanne 	d->bd_slen = 0;
101748932Smccanne 	d->bd_hlen = 0;
101848932Smccanne 	return (0);
101947584Smccanne }
102047584Smccanne 
102147584Smccanne /*
102249202Smccanne  * Register 'ifp' with bpf.  XXX
102347584Smccanne  * and 'driverp' is a pointer to the 'struct bpf_if *' in the driver's softc.
102447584Smccanne  */
102547584Smccanne void
102649202Smccanne bpfattach(driverp, ifp, dlt, hdrlen)
102747584Smccanne 	caddr_t *driverp;
102847584Smccanne 	struct ifnet *ifp;
102949202Smccanne 	u_int dlt, hdrlen;
103047584Smccanne {
103147584Smccanne 	struct bpf_if *bp;
103247584Smccanne 	int i;
103347584Smccanne 
103449202Smccanne 	bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
103549202Smccanne 	if (bp == 0)
103649202Smccanne 		panic("bpfattach");
103747584Smccanne 
103847584Smccanne 	bp->bif_dlist = 0;
103947584Smccanne 	bp->bif_driverp = (struct bpf_if **)driverp;
104047584Smccanne 	bp->bif_ifp = ifp;
104149202Smccanne 	bp->bif_dlt = dlt;
104247584Smccanne 
104349202Smccanne 	bp->bif_next = bpf_iflist;
104449202Smccanne 	bpf_iflist = bp;
104549202Smccanne 
104648932Smccanne 	*bp->bif_driverp = 0;
104748932Smccanne 
104847584Smccanne 	/*
104947584Smccanne 	 * Compute the length of the bpf header.  This is not necessarily
105047584Smccanne 	 * equal to SIZEOF_BPF_HDR because we want to insert spacing such
105147584Smccanne 	 * that the network layer header begins on a longword boundary (for
105247584Smccanne 	 * performance reasons and to alleviate alignment restrictions).
105347584Smccanne 	 */
105449202Smccanne 	bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
105547584Smccanne 
105647584Smccanne 	/*
105747584Smccanne 	 * Mark all the descriptors free if this hasn't been done.
105847584Smccanne 	 */
105947584Smccanne 	if (!D_ISFREE(&bpf_dtab[0]))
106047584Smccanne 		for (i = 0; i < NBPFILTER; ++i)
106147584Smccanne 			D_MARKFREE(&bpf_dtab[i]);
106247584Smccanne 
106347584Smccanne 	printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit);
106447584Smccanne }
106547584Smccanne 
106648967Smccanne /* XXX This routine belongs in net/if.c. */
106748932Smccanne /*
106848932Smccanne  * Set/clear promiscuous mode on interface ifp based on the truth value`
106948932Smccanne  * of pswitch.  The calls are reference counted so that only the first
107048932Smccanne  * on request actually has an effect, as does the final off request.
107148932Smccanne  * Results are undefined if the off and on requests are not matched.
107248932Smccanne  */
107348932Smccanne int
107448932Smccanne ifpromisc(ifp, pswitch)
107548932Smccanne 	struct ifnet *ifp;
107648932Smccanne 	int pswitch;
107748932Smccanne {
107848932Smccanne 	/*
107948932Smccanne 	 * If the device is not configured up, we cannot put it in
108048932Smccanne 	 * promiscuous mode.
108148932Smccanne 	 */
108248932Smccanne 	if ((ifp->if_flags & IFF_UP) == 0)
108348932Smccanne 		return (ENETDOWN);
108448932Smccanne 
108548932Smccanne 	if (pswitch) {
108648932Smccanne 		if (ifp->if_pcount++ != 0)
108748932Smccanne 			return (0);
108848932Smccanne 		ifp->if_flags |= IFF_PROMISC;
108948932Smccanne 	} else {
109048932Smccanne 		if (--ifp->if_pcount > 0)
109148932Smccanne 			return (0);
109248932Smccanne 		ifp->if_flags &= ~IFF_PROMISC;
109348932Smccanne 	}
109448932Smccanne 	return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)0));
109548932Smccanne }
109648932Smccanne 
109747584Smccanne #endif (NBPFILTER > 0)
1098