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*67634Smckusick * @(#)bpf.c 8.3 (Berkeley) 08/10/94 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 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 *)); 104*67634Smckusick 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 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 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 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 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 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 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 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 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 */ 464*67634Smckusick static __inline void 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 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 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 55947584Smccanne bpfioctl(dev, cmd, addr, flag) 56047584Smccanne dev_t dev; 56147584Smccanne int 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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