151440Smccanne /*
263207Sbostic * Copyright (c) 1990, 1991, 1993
363207Sbostic * The Regents of the University of California. 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*68168Scgd * @(#)bpf.c 8.4 (Berkeley) 01/09/95
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
2247584Smccanne #include <sys/param.h>
2347584Smccanne #include <sys/systm.h>
2447584Smccanne #include <sys/mbuf.h>
2547584Smccanne #include <sys/buf.h>
2653947Smccanne #include <sys/time.h>
2748932Smccanne #include <sys/proc.h>
2847584Smccanne #include <sys/user.h>
2947584Smccanne #include <sys/ioctl.h>
3047584Smccanne #include <sys/map.h>
3147584Smccanne
3247584Smccanne #include <sys/file.h>
3351425Smccanne #if defined(sparc) && BSD < 199103
3447584Smccanne #include <sys/stream.h>
3547584Smccanne #endif
3647584Smccanne #include <sys/tty.h>
3747584Smccanne #include <sys/uio.h>
3847584Smccanne
3947584Smccanne #include <sys/protosw.h>
4047584Smccanne #include <sys/socket.h>
4147584Smccanne #include <net/if.h>
4247584Smccanne
4347584Smccanne #include <net/bpf.h>
4447584Smccanne #include <net/bpfdesc.h>
4547584Smccanne
4647584Smccanne #include <sys/errno.h>
4747584Smccanne
4847584Smccanne #include <netinet/in.h>
4947584Smccanne #include <netinet/if_ether.h>
5047584Smccanne #include <sys/kernel.h>
5147584Smccanne
5251425Smccanne /*
5351425Smccanne * Older BSDs don't have kernel malloc.
5451425Smccanne */
5551425Smccanne #if BSD < 199103
5651425Smccanne extern bcopy();
5751425Smccanne static caddr_t bpf_alloc();
5853947Smccanne #include <net/bpf_compat.h>
5951425Smccanne #define BPF_BUFSIZE (MCLBYTES-8)
6053947Smccanne #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio)
6151425Smccanne #else
6251425Smccanne #define BPF_BUFSIZE 4096
6353947Smccanne #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio)
6451425Smccanne #endif
6551425Smccanne
6647584Smccanne #define PRINET 26 /* interruptible */
6747584Smccanne
6847584Smccanne /*
6948932Smccanne * The default read buffer size is patchable.
7048932Smccanne */
7151425Smccanne int bpf_bufsize = BPF_BUFSIZE;
7248932Smccanne
7348932Smccanne /*
7449202Smccanne * bpf_iflist is the list of interfaces; each corresponds to an ifnet
7549202Smccanne * bpf_dtab holds the descriptors, indexed by minor device #
7647584Smccanne */
7753947Smccanne struct bpf_if *bpf_iflist;
7853947Smccanne struct bpf_d bpf_dtab[NBPFILTER];
7947584Smccanne
8059122Storek #if BSD >= 199207
8159122Storek /*
8259122Storek * bpfilterattach() is called at boot time in new systems. We do
8359122Storek * nothing here since old systems will not call this.
8459122Storek */
8559122Storek /* ARGSUSED */
8659122Storek void
bpfilterattach(n)8759122Storek bpfilterattach(n)
8859122Storek int n;
8959122Storek {
9059122Storek }
9159122Storek #endif
9259122Storek
9361337Sbostic static int bpf_allocbufs __P((struct bpf_d *));
9461337Sbostic static int bpf_allocbufs __P((struct bpf_d *));
9561337Sbostic static void bpf_freed __P((struct bpf_d *));
9661337Sbostic static void bpf_freed __P((struct bpf_d *));
9761337Sbostic static void bpf_ifname __P((struct ifnet *, struct ifreq *));
9861337Sbostic static void bpf_ifname __P((struct ifnet *, struct ifreq *));
9966504Sbostic static void bpf_mcopy __P((const void *, void *, u_int));
10061337Sbostic static int bpf_movein __P((struct uio *, int,
10161337Sbostic struct mbuf **, struct sockaddr *, int *));
10261337Sbostic static int bpf_setif __P((struct bpf_d *, struct ifreq *));
10361337Sbostic static int bpf_setif __P((struct bpf_d *, struct ifreq *));
10467634Smckusick static __inline void
10561337Sbostic bpf_wakeup __P((struct bpf_d *));
10661337Sbostic static void catchpacket __P((struct bpf_d *, u_char *, u_int,
10766504Sbostic u_int, void (*)(const void *, void *, u_int)));
10861337Sbostic static void reset_d __P((struct bpf_d *));
10947584Smccanne
11047584Smccanne static int
bpf_movein(uio,linktype,mp,sockp,datlen)11155289Smckusick bpf_movein(uio, linktype, mp, sockp, datlen)
11247584Smccanne register struct uio *uio;
11355289Smckusick int linktype, *datlen;
11447584Smccanne register struct mbuf **mp;
11547584Smccanne register struct sockaddr *sockp;
11647584Smccanne {
11747584Smccanne struct mbuf *m;
11847584Smccanne int error;
11947584Smccanne int len;
12047584Smccanne int hlen;
12147584Smccanne
12247584Smccanne /*
12347584Smccanne * Build a sockaddr based on the data link layer type.
12447584Smccanne * We do this at this level because the ethernet header
12547584Smccanne * is copied directly into the data field of the sockaddr.
12647584Smccanne * In the case of SLIP, there is no header and the packet
12747584Smccanne * is forwarded as is.
12847584Smccanne * Also, we are careful to leave room at the front of the mbuf
12947584Smccanne * for the link level header.
13047584Smccanne */
13147584Smccanne switch (linktype) {
13253947Smccanne
13347584Smccanne case DLT_SLIP:
13447584Smccanne sockp->sa_family = AF_INET;
13547584Smccanne hlen = 0;
13647584Smccanne break;
13747584Smccanne
13847584Smccanne case DLT_EN10MB:
13947584Smccanne sockp->sa_family = AF_UNSPEC;
14047584Smccanne /* XXX Would MAXLINKHDR be better? */
14147584Smccanne hlen = sizeof(struct ether_header);
14247584Smccanne break;
14347584Smccanne
14453947Smccanne case DLT_FDDI:
14547584Smccanne sockp->sa_family = AF_UNSPEC;
14647584Smccanne /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
14747584Smccanne hlen = 24;
14847584Smccanne break;
14947584Smccanne
15053947Smccanne case DLT_NULL:
15153947Smccanne sockp->sa_family = AF_UNSPEC;
15253947Smccanne hlen = 0;
15353947Smccanne break;
15453947Smccanne
15547584Smccanne default:
15648932Smccanne return (EIO);
15747584Smccanne }
15847584Smccanne
15947584Smccanne len = uio->uio_resid;
16055289Smckusick *datlen = len - hlen;
16147584Smccanne if ((unsigned)len > MCLBYTES)
16248932Smccanne return (EIO);
16347584Smccanne
16447584Smccanne MGET(m, M_WAIT, MT_DATA);
16547584Smccanne if (m == 0)
16648932Smccanne return (ENOBUFS);
16747584Smccanne if (len > MLEN) {
16851425Smccanne #if BSD >= 199103
16948932Smccanne MCLGET(m, M_WAIT);
17048932Smccanne if ((m->m_flags & M_EXT) == 0) {
17151425Smccanne #else
17251425Smccanne MCLGET(m);
17353947Smccanne if (m->m_len != MCLBYTES) {
17451425Smccanne #endif
17553947Smccanne error = ENOBUFS;
17647584Smccanne goto bad;
17747584Smccanne }
17847584Smccanne }
17947584Smccanne m->m_len = len;
18047584Smccanne *mp = m;
18147584Smccanne /*
18247584Smccanne * Make room for link header.
18347584Smccanne */
18453947Smccanne if (hlen != 0) {
18547584Smccanne m->m_len -= hlen;
18651425Smccanne #if BSD >= 199103
18748932Smccanne m->m_data += hlen; /* XXX */
18851425Smccanne #else
18951425Smccanne m->m_off += hlen;
19051425Smccanne #endif
19153947Smccanne error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio);
19247584Smccanne if (error)
19347584Smccanne goto bad;
19447584Smccanne }
19553947Smccanne error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio);
19653947Smccanne if (!error)
19748932Smccanne return (0);
19847584Smccanne bad:
19947584Smccanne m_freem(m);
20048932Smccanne return (error);
20147584Smccanne }
20247584Smccanne
20347584Smccanne /*
20451425Smccanne * Attach file to the bpf interface, i.e. make d listen on bp.
20547584Smccanne * Must be called at splimp.
20647584Smccanne */
20747584Smccanne static void
bpf_attachd(d,bp)20847584Smccanne bpf_attachd(d, bp)
20947584Smccanne struct bpf_d *d;
21047584Smccanne struct bpf_if *bp;
21147584Smccanne {
21251425Smccanne /*
21351425Smccanne * Point d at bp, and add d to the interface's list of listeners.
21451425Smccanne * Finally, point the driver's bpf cookie at the interface so
21551425Smccanne * it will divert packets to bpf.
21651425Smccanne */
21747584Smccanne d->bd_bif = bp;
21847584Smccanne d->bd_next = bp->bif_dlist;
21947584Smccanne bp->bif_dlist = d;
22047584Smccanne
22147584Smccanne *bp->bif_driverp = bp;
22247584Smccanne }
22347584Smccanne
22451425Smccanne /*
22551425Smccanne * Detach a file from its interface.
22651425Smccanne */
22747584Smccanne static void
bpf_detachd(d)22847584Smccanne bpf_detachd(d)
22947584Smccanne struct bpf_d *d;
23047584Smccanne {
23147584Smccanne struct bpf_d **p;
23247584Smccanne struct bpf_if *bp;
23347584Smccanne
23447584Smccanne bp = d->bd_bif;
23547584Smccanne /*
23647584Smccanne * Check if this descriptor had requested promiscuous mode.
23747584Smccanne * If so, turn it off.
23847584Smccanne */
23947584Smccanne if (d->bd_promisc) {
24047584Smccanne d->bd_promisc = 0;
24147584Smccanne if (ifpromisc(bp->bif_ifp, 0))
24247584Smccanne /*
24347584Smccanne * Something is really wrong if we were able to put
24447584Smccanne * the driver into promiscuous mode, but can't
24547584Smccanne * take it out.
24647584Smccanne */
24751425Smccanne panic("bpf: ifpromisc failed");
24847584Smccanne }
24951425Smccanne /* Remove d from the interface's descriptor list. */
25047584Smccanne p = &bp->bif_dlist;
25147584Smccanne while (*p != d) {
25247584Smccanne p = &(*p)->bd_next;
25347584Smccanne if (*p == 0)
25447584Smccanne panic("bpf_detachd: descriptor not in list");
25547584Smccanne }
25647584Smccanne *p = (*p)->bd_next;
25747584Smccanne if (bp->bif_dlist == 0)
25847584Smccanne /*
25947584Smccanne * Let the driver know that there are no more listeners.
26047584Smccanne */
26147584Smccanne *d->bd_bif->bif_driverp = 0;
26247584Smccanne d->bd_bif = 0;
26347584Smccanne }
26447584Smccanne
26547584Smccanne
26647584Smccanne /*
26753947Smccanne * Mark a descriptor free by making it point to itself.
26847584Smccanne * This is probably cheaper than marking with a constant since
26947584Smccanne * the address should be in a register anyway.
27047584Smccanne */
27147584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next)
27247584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d))
27347584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0)
27447584Smccanne
27547584Smccanne /*
27653947Smccanne * Open ethernet device. Returns ENXIO for illegal minor device number,
27753947Smccanne * EBUSY if file is open by another process.
27847584Smccanne */
27947584Smccanne /* ARGSUSED */
28047584Smccanne int
bpfopen(dev,flag)28147584Smccanne bpfopen(dev, flag)
28247584Smccanne dev_t dev;
28347584Smccanne int flag;
28447584Smccanne {
28547584Smccanne register struct bpf_d *d;
28653947Smccanne
28747584Smccanne if (minor(dev) >= NBPFILTER)
28848932Smccanne return (ENXIO);
28947584Smccanne /*
29047584Smccanne * Each minor can be opened by only one process. If the requested
29147584Smccanne * minor is in use, return EBUSY.
29247584Smccanne */
29347584Smccanne d = &bpf_dtab[minor(dev)];
29453947Smccanne if (!D_ISFREE(d))
29548932Smccanne return (EBUSY);
29647584Smccanne
29753947Smccanne /* Mark "free" and do most initialization. */
29853947Smccanne bzero((char *)d, sizeof(*d));
29953947Smccanne d->bd_bufsize = bpf_bufsize;
30053947Smccanne
30148932Smccanne return (0);
30247584Smccanne }
30347584Smccanne
30447584Smccanne /*
30547584Smccanne * Close the descriptor by detaching it from its interface,
30647584Smccanne * deallocating its buffers, and marking it free.
30747584Smccanne */
30847584Smccanne /* ARGSUSED */
30953947Smccanne int
bpfclose(dev,flag)31047584Smccanne bpfclose(dev, flag)
31147584Smccanne dev_t dev;
31247584Smccanne int flag;
31347584Smccanne {
31447584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)];
31553947Smccanne register int s;
31647584Smccanne
31747584Smccanne s = splimp();
31847584Smccanne if (d->bd_bif)
31947584Smccanne bpf_detachd(d);
32047584Smccanne splx(s);
32153947Smccanne bpf_freed(d);
32247584Smccanne
32353947Smccanne return (0);
32447584Smccanne }
32547584Smccanne
32653947Smccanne /*
32753947Smccanne * Support for SunOS, which does not have tsleep.
32853947Smccanne */
32951425Smccanne #if BSD < 199103
33051425Smccanne static
bpf_timeout(arg)33151425Smccanne bpf_timeout(arg)
33251425Smccanne caddr_t arg;
33351425Smccanne {
33451425Smccanne struct bpf_d *d = (struct bpf_d *)arg;
33551425Smccanne d->bd_timedout = 1;
33651425Smccanne wakeup(arg);
33751425Smccanne }
33851425Smccanne
33953947Smccanne #define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan)
34053947Smccanne
34153947Smccanne int
bpf_sleep(d)34253947Smccanne bpf_sleep(d)
34353947Smccanne register struct bpf_d *d;
34451425Smccanne {
34553947Smccanne register int rto = d->bd_rtout;
34653947Smccanne register int st;
34751425Smccanne
34853947Smccanne if (rto != 0) {
34951425Smccanne d->bd_timedout = 0;
35053947Smccanne timeout(bpf_timeout, (caddr_t)d, rto);
35151425Smccanne }
35253947Smccanne st = sleep((caddr_t)d, PRINET|PCATCH);
35353947Smccanne if (rto != 0) {
35453947Smccanne if (d->bd_timedout == 0)
35553947Smccanne untimeout(bpf_timeout, (caddr_t)d);
35653947Smccanne else if (st == 0)
35751425Smccanne return EWOULDBLOCK;
35851425Smccanne }
35953947Smccanne return (st != 0) ? EINTR : 0;
36051425Smccanne }
36153947Smccanne #else
36253947Smccanne #define BPF_SLEEP tsleep
36351425Smccanne #endif
36451425Smccanne
36547584Smccanne /*
36648932Smccanne * Rotate the packet buffers in descriptor d. Move the store buffer
36753947Smccanne * into the hold slot, and the free buffer into the store slot.
36848932Smccanne * Zero the length of the new store buffer.
36948932Smccanne */
37048932Smccanne #define ROTATE_BUFFERS(d) \
37148932Smccanne (d)->bd_hbuf = (d)->bd_sbuf; \
37248932Smccanne (d)->bd_hlen = (d)->bd_slen; \
37348932Smccanne (d)->bd_sbuf = (d)->bd_fbuf; \
37448932Smccanne (d)->bd_slen = 0; \
37553947Smccanne (d)->bd_fbuf = 0;
37648932Smccanne /*
37747584Smccanne * bpfread - read next chunk of packets from buffers
37847584Smccanne */
37947584Smccanne int
bpfread(dev,uio)38047584Smccanne bpfread(dev, uio)
38147584Smccanne dev_t dev;
38247584Smccanne register struct uio *uio;
38347584Smccanne {
38447584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)];
38547584Smccanne int error;
38647584Smccanne int s;
38747584Smccanne
38847584Smccanne /*
38953947Smccanne * Restrict application to use a buffer the same size as
39047584Smccanne * as kernel buffers.
39147584Smccanne */
39248932Smccanne if (uio->uio_resid != d->bd_bufsize)
39349202Smccanne return (EINVAL);
39447584Smccanne
39547584Smccanne s = splimp();
39647584Smccanne /*
39753947Smccanne * If the hold buffer is empty, then do a timed sleep, which
39853947Smccanne * ends when the timeout expires or when enough packets
39953947Smccanne * have arrived to fill the store buffer.
40047584Smccanne */
40147584Smccanne while (d->bd_hbuf == 0) {
40248932Smccanne if (d->bd_immediate && d->bd_slen != 0) {
40347584Smccanne /*
40447584Smccanne * A packet(s) either arrived since the previous
40547584Smccanne * read or arrived while we were asleep.
40647584Smccanne * Rotate the buffers and return what's here.
40747584Smccanne */
40848932Smccanne ROTATE_BUFFERS(d);
40947584Smccanne break;
41047584Smccanne }
41153947Smccanne error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf",
41253947Smccanne d->bd_rtout);
41348932Smccanne if (error == EINTR || error == ERESTART) {
41448932Smccanne splx(s);
41548932Smccanne return (error);
41647584Smccanne }
41748932Smccanne if (error == EWOULDBLOCK) {
41847584Smccanne /*
41947584Smccanne * On a timeout, return what's in the buffer,
42048932Smccanne * which may be nothing. If there is something
42148932Smccanne * in the store buffer, we can rotate the buffers.
42247584Smccanne */
42347584Smccanne if (d->bd_hbuf)
42447584Smccanne /*
42553947Smccanne * We filled up the buffer in between
42647584Smccanne * getting the timeout and arriving
42747584Smccanne * here, so we don't need to rotate.
42847584Smccanne */
42947584Smccanne break;
43047584Smccanne
43148932Smccanne if (d->bd_slen == 0) {
43247584Smccanne splx(s);
43348932Smccanne return (0);
43447584Smccanne }
43548932Smccanne ROTATE_BUFFERS(d);
43647584Smccanne break;
43747584Smccanne }
43847584Smccanne }
43947584Smccanne /*
44047584Smccanne * At this point, we know we have something in the hold slot.
44147584Smccanne */
44247584Smccanne splx(s);
44353947Smccanne
44453947Smccanne /*
44547584Smccanne * Move data from hold buffer into user space.
44647584Smccanne * We know the entire buffer is transferred since
44748932Smccanne * we checked above that the read buffer is bpf_bufsize bytes.
44847584Smccanne */
44953947Smccanne error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio);
45053947Smccanne
45147584Smccanne s = splimp();
45248932Smccanne d->bd_fbuf = d->bd_hbuf;
45348932Smccanne d->bd_hbuf = 0;
45453947Smccanne d->bd_hlen = 0;
45547584Smccanne splx(s);
45653947Smccanne
45748932Smccanne return (error);
45847584Smccanne }
45947584Smccanne
46047584Smccanne
46147584Smccanne /*
46253947Smccanne * If there are processes sleeping on this descriptor, wake them up.
46347584Smccanne */
46467634Smckusick static __inline void
bpf_wakeup(d)46547584Smccanne bpf_wakeup(d)
46647584Smccanne register struct bpf_d *d;
46747584Smccanne {
46848932Smccanne wakeup((caddr_t)d);
46953947Smccanne #if BSD >= 199103
47053947Smccanne selwakeup(&d->bd_sel);
47153947Smccanne /* XXX */
47253947Smccanne d->bd_sel.si_pid = 0;
47353947Smccanne #else
47453947Smccanne if (d->bd_selproc) {
47553947Smccanne selwakeup(d->bd_selproc, (int)d->bd_selcoll);
47653947Smccanne d->bd_selcoll = 0;
47753947Smccanne d->bd_selproc = 0;
47853947Smccanne }
47953947Smccanne #endif
48047584Smccanne }
48147584Smccanne
48247584Smccanne int
bpfwrite(dev,uio)48347584Smccanne bpfwrite(dev, uio)
48447584Smccanne dev_t dev;
48547584Smccanne struct uio *uio;
48647584Smccanne {
48747584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)];
48847584Smccanne struct ifnet *ifp;
48947584Smccanne struct mbuf *m;
49047584Smccanne int error, s;
49147584Smccanne static struct sockaddr dst;
49255289Smckusick int datlen;
49347584Smccanne
49447584Smccanne if (d->bd_bif == 0)
49548932Smccanne return (ENXIO);
49647584Smccanne
49747584Smccanne ifp = d->bd_bif->bif_ifp;
49847584Smccanne
49947584Smccanne if (uio->uio_resid == 0)
50048932Smccanne return (0);
50147584Smccanne
50255289Smckusick error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen);
50347584Smccanne if (error)
50448932Smccanne return (error);
50547584Smccanne
50655289Smckusick if (datlen > ifp->if_mtu)
50755289Smckusick return (EMSGSIZE);
50855289Smckusick
50947584Smccanne s = splnet();
51051425Smccanne #if BSD >= 199103
51153947Smccanne error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0);
51251425Smccanne #else
51347584Smccanne error = (*ifp->if_output)(ifp, m, &dst);
51451425Smccanne #endif
51547584Smccanne splx(s);
51647584Smccanne /*
51753947Smccanne * The driver frees the mbuf.
51847584Smccanne */
51948932Smccanne return (error);
52047584Smccanne }
52147584Smccanne
52247584Smccanne /*
52353947Smccanne * Reset a descriptor by flushing its packet buffer and clearing the
52453947Smccanne * receive and drop counts. Should be called at splimp.
52547584Smccanne */
52647584Smccanne static void
reset_d(d)52747584Smccanne reset_d(d)
52847584Smccanne struct bpf_d *d;
52947584Smccanne {
53047584Smccanne if (d->bd_hbuf) {
53147584Smccanne /* Free the hold buffer. */
53247584Smccanne d->bd_fbuf = d->bd_hbuf;
53347584Smccanne d->bd_hbuf = 0;
53447584Smccanne }
53548932Smccanne d->bd_slen = 0;
53653947Smccanne d->bd_hlen = 0;
53747584Smccanne d->bd_rcount = 0;
53847584Smccanne d->bd_dcount = 0;
53947584Smccanne }
54047584Smccanne
54147584Smccanne /*
54247584Smccanne * FIONREAD Check for read packet available.
54347584Smccanne * SIOCGIFADDR Get interface address - convenient hook to driver.
54447584Smccanne * BIOCGBLEN Get buffer len [for read()].
54547584Smccanne * BIOCSETF Set ethernet read filter.
54647584Smccanne * BIOCFLUSH Flush read packet buffer.
54747584Smccanne * BIOCPROMISC Put interface into promiscuous mode.
54849202Smccanne * BIOCGDLT Get link layer type.
54947584Smccanne * BIOCGETIF Get interface name.
55047584Smccanne * BIOCSETIF Set interface.
55147584Smccanne * BIOCSRTIMEOUT Set read timeout.
55247584Smccanne * BIOCGRTIMEOUT Get read timeout.
55347584Smccanne * BIOCGSTATS Get packet stats.
55447584Smccanne * BIOCIMMEDIATE Set immediate mode.
55553947Smccanne * BIOCVERSION Get filter language version.
55647584Smccanne */
55747584Smccanne /* ARGSUSED */
55847584Smccanne int
bpfioctl(dev,cmd,addr,flag)55947584Smccanne bpfioctl(dev, cmd, addr, flag)
56047584Smccanne dev_t dev;
561*68168Scgd u_long cmd;
56247584Smccanne caddr_t addr;
56347584Smccanne int flag;
56447584Smccanne {
56547584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)];
56647584Smccanne int s, error = 0;
56747584Smccanne
56847584Smccanne switch (cmd) {
56947584Smccanne
57047584Smccanne default:
57147584Smccanne error = EINVAL;
57247584Smccanne break;
57347584Smccanne
57447584Smccanne /*
57547584Smccanne * Check for read packet available.
57647584Smccanne */
57747584Smccanne case FIONREAD:
57847584Smccanne {
57947584Smccanne int n;
58053947Smccanne
58147584Smccanne s = splimp();
58248932Smccanne n = d->bd_slen;
58353947Smccanne if (d->bd_hbuf)
58448932Smccanne n += d->bd_hlen;
58547584Smccanne splx(s);
58647584Smccanne
58747584Smccanne *(int *)addr = n;
58847584Smccanne break;
58947584Smccanne }
59047584Smccanne
59147584Smccanne case SIOCGIFADDR:
59247584Smccanne {
59347584Smccanne struct ifnet *ifp;
59447584Smccanne
59547584Smccanne if (d->bd_bif == 0)
59647584Smccanne error = EINVAL;
59747584Smccanne else {
59847584Smccanne ifp = d->bd_bif->bif_ifp;
59953947Smccanne error = (*ifp->if_ioctl)(ifp, cmd, addr);
60047584Smccanne }
60147584Smccanne break;
60247584Smccanne }
60347584Smccanne
60447584Smccanne /*
60547584Smccanne * Get buffer len [for read()].
60647584Smccanne */
60747584Smccanne case BIOCGBLEN:
60848932Smccanne *(u_int *)addr = d->bd_bufsize;
60947584Smccanne break;
61047584Smccanne
61147584Smccanne /*
61253947Smccanne * Set buffer length.
61353947Smccanne */
61453947Smccanne case BIOCSBLEN:
61553947Smccanne #if BSD < 199103
61653947Smccanne error = EINVAL;
61753947Smccanne #else
61853947Smccanne if (d->bd_bif != 0)
61953947Smccanne error = EINVAL;
62053947Smccanne else {
62153947Smccanne register u_int size = *(u_int *)addr;
62253947Smccanne
62353947Smccanne if (size > BPF_MAXBUFSIZE)
62453947Smccanne *(u_int *)addr = size = BPF_MAXBUFSIZE;
62553947Smccanne else if (size < BPF_MINBUFSIZE)
62653947Smccanne *(u_int *)addr = size = BPF_MINBUFSIZE;
62753947Smccanne d->bd_bufsize = size;
62853947Smccanne }
62953947Smccanne #endif
63053947Smccanne break;
63153947Smccanne
63253947Smccanne /*
63351425Smccanne * Set link layer read filter.
63447584Smccanne */
63553947Smccanne case BIOCSETF:
63647584Smccanne error = bpf_setf(d, (struct bpf_program *)addr);
63747584Smccanne break;
63847584Smccanne
63947584Smccanne /*
64047584Smccanne * Flush read packet buffer.
64147584Smccanne */
64247584Smccanne case BIOCFLUSH:
64347584Smccanne s = splimp();
64447584Smccanne reset_d(d);
64547584Smccanne splx(s);
64647584Smccanne break;
64747584Smccanne
64847584Smccanne /*
64947584Smccanne * Put interface into promiscuous mode.
65047584Smccanne */
65147584Smccanne case BIOCPROMISC:
65247584Smccanne if (d->bd_bif == 0) {
65347584Smccanne /*
65447584Smccanne * No interface attached yet.
65547584Smccanne */
65647584Smccanne error = EINVAL;
65747584Smccanne break;
65847584Smccanne }
65947584Smccanne s = splimp();
66047584Smccanne if (d->bd_promisc == 0) {
66147584Smccanne error = ifpromisc(d->bd_bif->bif_ifp, 1);
66251425Smccanne if (error == 0)
66351425Smccanne d->bd_promisc = 1;
66447584Smccanne }
66547584Smccanne splx(s);
66647584Smccanne break;
66747584Smccanne
66847584Smccanne /*
66947584Smccanne * Get device parameters.
67047584Smccanne */
67149202Smccanne case BIOCGDLT:
67247584Smccanne if (d->bd_bif == 0)
67347584Smccanne error = EINVAL;
67447584Smccanne else
67549202Smccanne *(u_int *)addr = d->bd_bif->bif_dlt;
67647584Smccanne break;
67747584Smccanne
67847584Smccanne /*
67947584Smccanne * Set interface name.
68047584Smccanne */
68147584Smccanne case BIOCGETIF:
68247584Smccanne if (d->bd_bif == 0)
68347584Smccanne error = EINVAL;
68447584Smccanne else
68547584Smccanne bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
68647584Smccanne break;
68747584Smccanne
68847584Smccanne /*
68947584Smccanne * Set interface.
69047584Smccanne */
69147584Smccanne case BIOCSETIF:
69247584Smccanne error = bpf_setif(d, (struct ifreq *)addr);
69347584Smccanne break;
69447584Smccanne
69547584Smccanne /*
69647584Smccanne * Set read timeout.
69747584Smccanne */
69853947Smccanne case BIOCSRTIMEOUT:
69947584Smccanne {
70047584Smccanne struct timeval *tv = (struct timeval *)addr;
70147584Smccanne u_long msec;
70247584Smccanne
70347584Smccanne /* Compute number of milliseconds. */
70447584Smccanne msec = tv->tv_sec * 1000 + tv->tv_usec / 1000;
70547584Smccanne /* Scale milliseconds to ticks. Assume hard
70647584Smccanne clock has millisecond or greater resolution
70747584Smccanne (i.e. tick >= 1000). For 10ms hardclock,
70847584Smccanne tick/1000 = 10, so rtout<-msec/10. */
70947584Smccanne d->bd_rtout = msec / (tick / 1000);
71047584Smccanne break;
71147584Smccanne }
71247584Smccanne
71347584Smccanne /*
71447584Smccanne * Get read timeout.
71547584Smccanne */
71653947Smccanne case BIOCGRTIMEOUT:
71747584Smccanne {
71847584Smccanne struct timeval *tv = (struct timeval *)addr;
71947584Smccanne u_long msec = d->bd_rtout;
72047584Smccanne
72147584Smccanne msec *= tick / 1000;
72247584Smccanne tv->tv_sec = msec / 1000;
72347584Smccanne tv->tv_usec = msec % 1000;
72447584Smccanne break;
72547584Smccanne }
72647584Smccanne
72747584Smccanne /*
72847584Smccanne * Get packet stats.
72947584Smccanne */
73047584Smccanne case BIOCGSTATS:
73147584Smccanne {
73247584Smccanne struct bpf_stat *bs = (struct bpf_stat *)addr;
73347584Smccanne
73447584Smccanne bs->bs_recv = d->bd_rcount;
73547584Smccanne bs->bs_drop = d->bd_dcount;
73647584Smccanne break;
73747584Smccanne }
73847584Smccanne
73947584Smccanne /*
74047584Smccanne * Set immediate mode.
74147584Smccanne */
74247584Smccanne case BIOCIMMEDIATE:
74347584Smccanne d->bd_immediate = *(u_int *)addr;
74447584Smccanne break;
74553947Smccanne
74653947Smccanne case BIOCVERSION:
74753947Smccanne {
74853947Smccanne struct bpf_version *bv = (struct bpf_version *)addr;
74953947Smccanne
75053947Smccanne bv->bv_major = BPF_MAJOR_VERSION;
75153947Smccanne bv->bv_minor = BPF_MINOR_VERSION;
75253947Smccanne break;
75353947Smccanne }
75447584Smccanne }
75548932Smccanne return (error);
75647584Smccanne }
75747584Smccanne
75853947Smccanne /*
75951425Smccanne * Set d's packet filter program to fp. If this file already has a filter,
76048932Smccanne * free it and replace it. Returns EINVAL for bogus requests.
76147584Smccanne */
76247584Smccanne int
bpf_setf(d,fp)76347584Smccanne bpf_setf(d, fp)
76447584Smccanne struct bpf_d *d;
76547584Smccanne struct bpf_program *fp;
76647584Smccanne {
76748932Smccanne struct bpf_insn *fcode, *old;
76847584Smccanne u_int flen, size;
76947584Smccanne int s;
77047584Smccanne
77148932Smccanne old = d->bd_filter;
77247584Smccanne if (fp->bf_insns == 0) {
77347584Smccanne if (fp->bf_len != 0)
77448932Smccanne return (EINVAL);
77548932Smccanne s = splimp();
77648967Smccanne d->bd_filter = 0;
77747584Smccanne reset_d(d);
77847584Smccanne splx(s);
77948967Smccanne if (old != 0)
78048932Smccanne free((caddr_t)old, M_DEVBUF);
78148932Smccanne return (0);
78247584Smccanne }
78347584Smccanne flen = fp->bf_len;
78448932Smccanne if (flen > BPF_MAXINSNS)
78548932Smccanne return (EINVAL);
78648932Smccanne
78747584Smccanne size = flen * sizeof(*fp->bf_insns);
78848932Smccanne fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
78950417Smccanne if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
79050417Smccanne bpf_validate(fcode, (int)flen)) {
79148967Smccanne s = splimp();
79248932Smccanne d->bd_filter = fcode;
79347584Smccanne reset_d(d);
79447584Smccanne splx(s);
79548967Smccanne if (old != 0)
79648932Smccanne free((caddr_t)old, M_DEVBUF);
79747584Smccanne
79848932Smccanne return (0);
79947584Smccanne }
80048932Smccanne free((caddr_t)fcode, M_DEVBUF);
80148932Smccanne return (EINVAL);
80247584Smccanne }
80347584Smccanne
80447584Smccanne /*
80553947Smccanne * Detach a file from its current interface (if attached at all) and attach
80653947Smccanne * to the interface indicated by the name stored in ifr.
80751425Smccanne * Return an errno or 0.
80847584Smccanne */
80947584Smccanne static int
bpf_setif(d,ifr)81047584Smccanne bpf_setif(d, ifr)
81147584Smccanne struct bpf_d *d;
81247584Smccanne struct ifreq *ifr;
81347584Smccanne {
81447584Smccanne struct bpf_if *bp;
81547584Smccanne char *cp;
81653947Smccanne int unit, s, error;
81747584Smccanne
81847584Smccanne /*
81947584Smccanne * Separate string into name part and unit number. Put a null
82053947Smccanne * byte at the end of the name part, and compute the number.
82147584Smccanne * If the a unit number is unspecified, the default is 0,
82248932Smccanne * as initialized above. XXX This should be common code.
82347584Smccanne */
82447584Smccanne unit = 0;
82547584Smccanne cp = ifr->ifr_name;
82647584Smccanne cp[sizeof(ifr->ifr_name) - 1] = '\0';
82747584Smccanne while (*cp++) {
82847584Smccanne if (*cp >= '0' && *cp <= '9') {
82947584Smccanne unit = *cp - '0';
83047584Smccanne *cp++ = '\0';
83147584Smccanne while (*cp)
83247584Smccanne unit = 10 * unit + *cp++ - '0';
83347584Smccanne break;
83447584Smccanne }
83547584Smccanne }
83647584Smccanne /*
83747584Smccanne * Look through attached interfaces for the named one.
83847584Smccanne */
83949202Smccanne for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
84047584Smccanne struct ifnet *ifp = bp->bif_ifp;
84147584Smccanne
84253947Smccanne if (ifp == 0 || unit != ifp->if_unit
84347584Smccanne || strcmp(ifp->if_name, ifr->ifr_name) != 0)
84447584Smccanne continue;
84547584Smccanne /*
84653947Smccanne * We found the requested interface.
84747584Smccanne * If it's not up, return an error.
84853947Smccanne * Allocate the packet buffers if we need to.
84953947Smccanne * If we're already attached to requested interface,
85053947Smccanne * just flush the buffer.
85147584Smccanne */
85247584Smccanne if ((ifp->if_flags & IFF_UP) == 0)
85348932Smccanne return (ENETDOWN);
85453947Smccanne
85553947Smccanne if (d->bd_sbuf == 0) {
85653947Smccanne error = bpf_allocbufs(d);
85753947Smccanne if (error != 0)
85853947Smccanne return (error);
85953947Smccanne }
86047584Smccanne s = splimp();
86147584Smccanne if (bp != d->bd_bif) {
86247584Smccanne if (d->bd_bif)
86353947Smccanne /*
86448932Smccanne * Detach if attached to something else.
86547584Smccanne */
86647584Smccanne bpf_detachd(d);
86747584Smccanne
86847584Smccanne bpf_attachd(d, bp);
86947584Smccanne }
87047584Smccanne reset_d(d);
87147584Smccanne splx(s);
87248932Smccanne return (0);
87347584Smccanne }
87447584Smccanne /* Not found. */
87548932Smccanne return (ENXIO);
87647584Smccanne }
87747584Smccanne
87847584Smccanne /*
87951425Smccanne * Convert an interface name plus unit number of an ifp to a single
88051425Smccanne * name which is returned in the ifr.
88147584Smccanne */
88247584Smccanne static void
bpf_ifname(ifp,ifr)88347584Smccanne bpf_ifname(ifp, ifr)
88447584Smccanne struct ifnet *ifp;
88547584Smccanne struct ifreq *ifr;
88647584Smccanne {
88747584Smccanne char *s = ifp->if_name;
88847584Smccanne char *d = ifr->ifr_name;
88947584Smccanne
89047584Smccanne while (*d++ = *s++)
89153947Smccanne continue;
89248932Smccanne /* XXX Assume that unit number is less than 10. */
89347584Smccanne *d++ = ifp->if_unit + '0';
89447584Smccanne *d = '\0';
89547584Smccanne }
89647584Smccanne
89747584Smccanne /*
89851425Smccanne * The new select interface passes down the proc pointer; the old select
89951425Smccanne * stubs had to grab it out of the user struct. This glue allows either case.
90051425Smccanne */
90151425Smccanne #if BSD >= 199103
90251425Smccanne #define bpf_select bpfselect
90351425Smccanne #else
90451425Smccanne int
bpfselect(dev,rw)90551425Smccanne bpfselect(dev, rw)
90651425Smccanne register dev_t dev;
90751425Smccanne int rw;
90851425Smccanne {
90953947Smccanne return (bpf_select(dev, rw, u.u_procp));
91051425Smccanne }
91151425Smccanne #endif
91251425Smccanne
91351425Smccanne /*
91447584Smccanne * Support for select() system call
91547584Smccanne *
91653947Smccanne * Return true iff the specific operation will not block indefinitely.
91753947Smccanne * Otherwise, return false but make a note that a selwakeup() must be done.
91847584Smccanne */
91947584Smccanne int
bpf_select(dev,rw,p)92051425Smccanne bpf_select(dev, rw, p)
92147584Smccanne register dev_t dev;
92247584Smccanne int rw;
92348932Smccanne struct proc *p;
92447584Smccanne {
92547584Smccanne register struct bpf_d *d;
92647584Smccanne register int s;
92753947Smccanne
92847584Smccanne if (rw != FREAD)
92948932Smccanne return (0);
93047584Smccanne /*
93147584Smccanne * An imitation of the FIONREAD ioctl code.
93247584Smccanne */
93347584Smccanne d = &bpf_dtab[minor(dev)];
93453947Smccanne
93547584Smccanne s = splimp();
93649723Smccanne if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) {
93747584Smccanne /*
93847584Smccanne * There is data waiting.
93947584Smccanne */
94047584Smccanne splx(s);
94148932Smccanne return (1);
94247584Smccanne }
94353947Smccanne #if BSD >= 199103
94453947Smccanne selrecord(p, &d->bd_sel);
94553947Smccanne #else
94647584Smccanne /*
94747584Smccanne * No data ready. If there's already a select() waiting on this
94853947Smccanne * minor device then this is a collision. This shouldn't happen
94947584Smccanne * because minors really should not be shared, but if a process
95047584Smccanne * forks while one of these is open, it is possible that both
95147584Smccanne * processes could select on the same descriptor.
95247584Smccanne */
95353947Smccanne if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait)
95453947Smccanne d->bd_selcoll = 1;
95553947Smccanne else
95653947Smccanne d->bd_selproc = p;
95753947Smccanne #endif
95853947Smccanne splx(s);
95948932Smccanne return (0);
96047584Smccanne }
96147584Smccanne
96247584Smccanne /*
96353947Smccanne * Incoming linkage from device drivers. Process the packet pkt, of length
96453947Smccanne * pktlen, which is stored in a contiguous buffer. The packet is parsed
96553947Smccanne * by each process' filter, and if accepted, stashed into the corresponding
96653947Smccanne * buffer.
96747584Smccanne */
96847584Smccanne void
bpf_tap(arg,pkt,pktlen)96948932Smccanne bpf_tap(arg, pkt, pktlen)
97047584Smccanne caddr_t arg;
97148932Smccanne register u_char *pkt;
97248932Smccanne register u_int pktlen;
97347584Smccanne {
97447584Smccanne struct bpf_if *bp;
97547584Smccanne register struct bpf_d *d;
97647584Smccanne register u_int slen;
97747584Smccanne /*
97847584Smccanne * Note that the ipl does not have to be raised at this point.
97947584Smccanne * The only problem that could arise here is that if two different
98047584Smccanne * interfaces shared any data. This is not the case.
98147584Smccanne */
98247584Smccanne bp = (struct bpf_if *)arg;
98347584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
98447584Smccanne ++d->bd_rcount;
98549202Smccanne slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
98647584Smccanne if (slen != 0)
98749202Smccanne catchpacket(d, pkt, pktlen, slen, bcopy);
98847584Smccanne }
98947584Smccanne }
99047584Smccanne
99147584Smccanne /*
99247584Smccanne * Copy data from an mbuf chain into a buffer. This code is derived
99347584Smccanne * from m_copydata in sys/uipc_mbuf.c.
99447584Smccanne */
99547584Smccanne static void
bpf_mcopy(src_arg,dst_arg,len)99661337Sbostic bpf_mcopy(src_arg, dst_arg, len)
99766504Sbostic const void *src_arg;
99866504Sbostic void *dst_arg;
99961337Sbostic register u_int len;
100047584Smccanne {
100166504Sbostic register const struct mbuf *m;
100261337Sbostic register u_int count;
100366504Sbostic u_char *dst;
100447584Smccanne
100566504Sbostic m = src_arg;
100661337Sbostic dst = dst_arg;
100747584Smccanne while (len > 0) {
100847584Smccanne if (m == 0)
100949202Smccanne panic("bpf_mcopy");
101055065Spendry count = min(m->m_len, len);
101149202Smccanne bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
101249202Smccanne m = m->m_next;
101349202Smccanne dst += count;
101447584Smccanne len -= count;
101547584Smccanne }
101647584Smccanne }
101747584Smccanne
101847584Smccanne /*
101953947Smccanne * Incoming linkage from device drivers, when packet is in an mbuf chain.
102047584Smccanne */
102147584Smccanne void
bpf_mtap(arg,m)102249202Smccanne bpf_mtap(arg, m)
102347584Smccanne caddr_t arg;
102449202Smccanne struct mbuf *m;
102547584Smccanne {
102647584Smccanne struct bpf_if *bp = (struct bpf_if *)arg;
102747584Smccanne struct bpf_d *d;
102849202Smccanne u_int pktlen, slen;
102949202Smccanne struct mbuf *m0;
103047584Smccanne
103148932Smccanne pktlen = 0;
103251425Smccanne for (m0 = m; m0 != 0; m0 = m0->m_next)
103349202Smccanne pktlen += m0->m_len;
103449723Smccanne
103547584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
103647584Smccanne ++d->bd_rcount;
103749202Smccanne slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
103847584Smccanne if (slen != 0)
103949202Smccanne catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
104047584Smccanne }
104147584Smccanne }
104247584Smccanne
104347584Smccanne /*
104449202Smccanne * Move the packet data from interface memory (pkt) into the
104547584Smccanne * store buffer. Return 1 if it's time to wakeup a listener (buffer full),
104653947Smccanne * otherwise 0. "copy" is the routine called to do the actual data
104751425Smccanne * transfer. bcopy is passed in to copy contiguous chunks, while
104851425Smccanne * bpf_mcopy is passed in to copy mbuf chains. In the latter case,
104951425Smccanne * pkt is really an mbuf.
105047584Smccanne */
105147584Smccanne static void
catchpacket(d,pkt,pktlen,snaplen,cpfn)105248932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn)
105348932Smccanne register struct bpf_d *d;
105448932Smccanne register u_char *pkt;
105548932Smccanne register u_int pktlen, snaplen;
105666504Sbostic register void (*cpfn)(const void *, void *, u_int);
105747584Smccanne {
105848932Smccanne register struct bpf_hdr *hp;
105948932Smccanne register int totlen, curlen;
106048932Smccanne register int hdrlen = d->bd_bif->bif_hdrlen;
106147584Smccanne /*
106247584Smccanne * Figure out how many bytes to move. If the packet is
106347584Smccanne * greater or equal to the snapshot length, transfer that
106447584Smccanne * much. Otherwise, transfer the whole packet (unless
106548932Smccanne * we hit the buffer size limit).
106647584Smccanne */
106755065Spendry totlen = hdrlen + min(snaplen, pktlen);
106850082Smccanne if (totlen > d->bd_bufsize)
106950082Smccanne totlen = d->bd_bufsize;
107047584Smccanne
107147584Smccanne /*
107247584Smccanne * Round up the end of the previous packet to the next longword.
107347584Smccanne */
107448932Smccanne curlen = BPF_WORDALIGN(d->bd_slen);
107548932Smccanne if (curlen + totlen > d->bd_bufsize) {
107647584Smccanne /*
107747584Smccanne * This packet will overflow the storage buffer.
107848932Smccanne * Rotate the buffers if we can, then wakeup any
107948932Smccanne * pending reads.
108047584Smccanne */
108147584Smccanne if (d->bd_fbuf == 0) {
108253947Smccanne /*
108353947Smccanne * We haven't completed the previous read yet,
108448932Smccanne * so drop the packet.
108547584Smccanne */
108647584Smccanne ++d->bd_dcount;
108747584Smccanne return;
108847584Smccanne }
108948932Smccanne ROTATE_BUFFERS(d);
109047584Smccanne bpf_wakeup(d);
109148932Smccanne curlen = 0;
109247584Smccanne }
109353947Smccanne else if (d->bd_immediate)
109447584Smccanne /*
109547584Smccanne * Immediate mode is set. A packet arrived so any
109647584Smccanne * reads should be woken up.
109747584Smccanne */
109847584Smccanne bpf_wakeup(d);
109948932Smccanne
110047584Smccanne /*
110147584Smccanne * Append the bpf header.
110247584Smccanne */
110348932Smccanne hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
110451425Smccanne #if BSD >= 199103
110547584Smccanne microtime(&hp->bh_tstamp);
110653947Smccanne #elif defined(sun)
110753947Smccanne uniqtime(&hp->bh_tstamp);
110847584Smccanne #else
110947584Smccanne hp->bh_tstamp = time;
111047584Smccanne #endif
111148932Smccanne hp->bh_datalen = pktlen;
111247584Smccanne hp->bh_hdrlen = hdrlen;
111347584Smccanne /*
111448932Smccanne * Copy the packet data into the store buffer and update its length.
111547584Smccanne */
111648932Smccanne (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
111748932Smccanne d->bd_slen = curlen + totlen;
111847584Smccanne }
111947584Smccanne
112053947Smccanne /*
112147584Smccanne * Initialize all nonzero fields of a descriptor.
112247584Smccanne */
112347584Smccanne static int
bpf_allocbufs(d)112453947Smccanne bpf_allocbufs(d)
112547584Smccanne register struct bpf_d *d;
112647584Smccanne {
112748932Smccanne d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
112848932Smccanne if (d->bd_fbuf == 0)
112948932Smccanne return (ENOBUFS);
113047584Smccanne
113148932Smccanne d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK);
113248932Smccanne if (d->bd_sbuf == 0) {
113348932Smccanne free(d->bd_fbuf, M_DEVBUF);
113448932Smccanne return (ENOBUFS);
113547584Smccanne }
113648932Smccanne d->bd_slen = 0;
113748932Smccanne d->bd_hlen = 0;
113848932Smccanne return (0);
113947584Smccanne }
114047584Smccanne
114147584Smccanne /*
114251425Smccanne * Free buffers currently in use by a descriptor.
114351425Smccanne * Called on close.
114447584Smccanne */
114553947Smccanne static void
bpf_freed(d)114651425Smccanne bpf_freed(d)
114751425Smccanne register struct bpf_d *d;
114851425Smccanne {
114951425Smccanne /*
115051425Smccanne * We don't need to lock out interrupts since this descriptor has
115153947Smccanne * been detached from its interface and it yet hasn't been marked
115251425Smccanne * free.
115351425Smccanne */
115453947Smccanne if (d->bd_sbuf != 0) {
115553947Smccanne free(d->bd_sbuf, M_DEVBUF);
115653947Smccanne if (d->bd_hbuf != 0)
115753947Smccanne free(d->bd_hbuf, M_DEVBUF);
115853947Smccanne if (d->bd_fbuf != 0)
115953947Smccanne free(d->bd_fbuf, M_DEVBUF);
116053947Smccanne }
116151425Smccanne if (d->bd_filter)
116251425Smccanne free((caddr_t)d->bd_filter, M_DEVBUF);
116353947Smccanne
116451425Smccanne D_MARKFREE(d);
116551425Smccanne }
116651425Smccanne
116751425Smccanne /*
116851425Smccanne * Attach an interface to bpf. driverp is a pointer to a (struct bpf_if *)
116951425Smccanne * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
117051425Smccanne * size of the link header (variable length headers not yet supported).
117151425Smccanne */
117247584Smccanne void
bpfattach(driverp,ifp,dlt,hdrlen)117349202Smccanne bpfattach(driverp, ifp, dlt, hdrlen)
117447584Smccanne caddr_t *driverp;
117547584Smccanne struct ifnet *ifp;
117649202Smccanne u_int dlt, hdrlen;
117747584Smccanne {
117847584Smccanne struct bpf_if *bp;
117947584Smccanne int i;
118051425Smccanne #if BSD < 199103
118151425Smccanne static struct bpf_if bpf_ifs[NBPFILTER];
118251425Smccanne static int bpfifno;
118347584Smccanne
118451425Smccanne bp = (bpfifno < NBPFILTER) ? &bpf_ifs[bpfifno++] : 0;
118551425Smccanne #else
118649202Smccanne bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
118751425Smccanne #endif
118849202Smccanne if (bp == 0)
118949202Smccanne panic("bpfattach");
119047584Smccanne
119147584Smccanne bp->bif_dlist = 0;
119247584Smccanne bp->bif_driverp = (struct bpf_if **)driverp;
119347584Smccanne bp->bif_ifp = ifp;
119449202Smccanne bp->bif_dlt = dlt;
119547584Smccanne
119649202Smccanne bp->bif_next = bpf_iflist;
119749202Smccanne bpf_iflist = bp;
119849202Smccanne
119948932Smccanne *bp->bif_driverp = 0;
120048932Smccanne
120147584Smccanne /*
120247584Smccanne * Compute the length of the bpf header. This is not necessarily
120353947Smccanne * equal to SIZEOF_BPF_HDR because we want to insert spacing such
120453947Smccanne * that the network layer header begins on a longword boundary (for
120547584Smccanne * performance reasons and to alleviate alignment restrictions).
120647584Smccanne */
120749202Smccanne bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
120847584Smccanne
120947584Smccanne /*
121047584Smccanne * Mark all the descriptors free if this hasn't been done.
121147584Smccanne */
121247584Smccanne if (!D_ISFREE(&bpf_dtab[0]))
121347584Smccanne for (i = 0; i < NBPFILTER; ++i)
121447584Smccanne D_MARKFREE(&bpf_dtab[i]);
121547584Smccanne
121647584Smccanne printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit);
121747584Smccanne }
121847584Smccanne
121951425Smccanne #if BSD >= 199103
122048967Smccanne /* XXX This routine belongs in net/if.c. */
122148932Smccanne /*
122253947Smccanne * Set/clear promiscuous mode on interface ifp based on the truth value
122348932Smccanne * of pswitch. The calls are reference counted so that only the first
122453947Smccanne * "on" request actually has an effect, as does the final "off" request.
122553947Smccanne * Results are undefined if the "off" and "on" requests are not matched.
122648932Smccanne */
122748932Smccanne int
ifpromisc(ifp,pswitch)122848932Smccanne ifpromisc(ifp, pswitch)
122948932Smccanne struct ifnet *ifp;
123048932Smccanne int pswitch;
123148932Smccanne {
123249726Smccanne struct ifreq ifr;
123353947Smccanne /*
123448932Smccanne * If the device is not configured up, we cannot put it in
123548932Smccanne * promiscuous mode.
123648932Smccanne */
123748932Smccanne if ((ifp->if_flags & IFF_UP) == 0)
123848932Smccanne return (ENETDOWN);
123948932Smccanne
124048932Smccanne if (pswitch) {
124148932Smccanne if (ifp->if_pcount++ != 0)
124248932Smccanne return (0);
124348932Smccanne ifp->if_flags |= IFF_PROMISC;
124448932Smccanne } else {
124548932Smccanne if (--ifp->if_pcount > 0)
124648932Smccanne return (0);
124748932Smccanne ifp->if_flags &= ~IFF_PROMISC;
124848932Smccanne }
124949726Smccanne ifr.ifr_flags = ifp->if_flags;
125049726Smccanne return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr));
125148932Smccanne }
125251425Smccanne #endif
125348932Smccanne
125451425Smccanne #if BSD < 199103
125551425Smccanne /*
125651425Smccanne * Allocate some memory for bpf. This is temporary SunOS support, and
125753947Smccanne * is admittedly a hack.
125851425Smccanne * If resources unavaiable, return 0.
125951425Smccanne */
126051425Smccanne static caddr_t
bpf_alloc(size,canwait)126151425Smccanne bpf_alloc(size, canwait)
126251425Smccanne register int size;
126351425Smccanne register int canwait;
126451425Smccanne {
126551425Smccanne register struct mbuf *m;
126651425Smccanne
126751425Smccanne if ((unsigned)size > (MCLBYTES-8))
126851425Smccanne return 0;
126951425Smccanne
127051425Smccanne MGET(m, canwait, MT_DATA);
127151425Smccanne if (m == 0)
127251425Smccanne return 0;
127351425Smccanne if ((unsigned)size > (MLEN-8)) {
127451425Smccanne MCLGET(m);
127551425Smccanne if (m->m_len != MCLBYTES) {
127651425Smccanne m_freem(m);
127751425Smccanne return 0;
127851425Smccanne }
127951425Smccanne }
128051425Smccanne *mtod(m, struct mbuf **) = m;
128151425Smccanne return mtod(m, caddr_t) + 8;
128251425Smccanne }
128351425Smccanne #endif
128451425Smccanne #endif
1285