151440Smccanne /* 251440Smccanne * Copyright (c) 1990, 1991 Regents of the University of California. 347584Smccanne * All rights reserved. 447584Smccanne * 549343Sbostic * This code is derived from the Stanford/CMU enet packet filter, 649343Sbostic * (net/enet.c) distributed as part of 4.3BSD, and code contributed 751425Smccanne * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence 851425Smccanne * Berkeley Laboratory. 947584Smccanne * 1051440Smccanne * %sccs.include.redist.c% 1149343Sbostic * 12*55065Spendry * @(#)bpf.c 7.11 (Berkeley) 07/12/92 1349343Sbostic * 1449343Sbostic * static char rcsid[] = 1551425Smccanne * "$Header: bpf.c,v 1.33 91/10/27 21:21:58 mccanne Exp $"; 1647584Smccanne */ 1747584Smccanne 1847584Smccanne #include "bpfilter.h" 1947584Smccanne 2051425Smccanne #if NBPFILTER > 0 2147584Smccanne 2251425Smccanne #ifndef __GNUC__ 2351425Smccanne #define inline 2451425Smccanne #else 2554970Smckusick #define inline __inline 2651425Smccanne #endif 2751425Smccanne 2847584Smccanne #include <sys/param.h> 2947584Smccanne #include <sys/systm.h> 3047584Smccanne #include <sys/mbuf.h> 3147584Smccanne #include <sys/buf.h> 3247584Smccanne #include <sys/dir.h> 3353947Smccanne #include <sys/time.h> 3448932Smccanne #include <sys/proc.h> 3547584Smccanne #include <sys/user.h> 3647584Smccanne #include <sys/ioctl.h> 3747584Smccanne #include <sys/map.h> 3847584Smccanne 3947584Smccanne #include <sys/file.h> 4051425Smccanne #if defined(sparc) && BSD < 199103 4147584Smccanne #include <sys/stream.h> 4247584Smccanne #endif 4347584Smccanne #include <sys/tty.h> 4447584Smccanne #include <sys/uio.h> 4547584Smccanne 4647584Smccanne #include <sys/protosw.h> 4747584Smccanne #include <sys/socket.h> 4847584Smccanne #include <net/if.h> 4947584Smccanne 5047584Smccanne #include <net/bpf.h> 5147584Smccanne #include <net/bpfdesc.h> 5247584Smccanne 5347584Smccanne #include <sys/errno.h> 5447584Smccanne 5547584Smccanne #include <netinet/in.h> 5647584Smccanne #include <netinet/if_ether.h> 5747584Smccanne #include <sys/kernel.h> 5847584Smccanne 5951425Smccanne /* 6051425Smccanne * Older BSDs don't have kernel malloc. 6151425Smccanne */ 6251425Smccanne #if BSD < 199103 6351425Smccanne extern bcopy(); 6451425Smccanne static caddr_t bpf_alloc(); 6553947Smccanne #include <net/bpf_compat.h> 6651425Smccanne #define BPF_BUFSIZE (MCLBYTES-8) 6753947Smccanne #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio) 6851425Smccanne #else 6951425Smccanne #define BPF_BUFSIZE 4096 7053947Smccanne #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio) 7151425Smccanne #endif 7251425Smccanne 7347584Smccanne #define PRINET 26 /* interruptible */ 7447584Smccanne 7547584Smccanne /* 7648932Smccanne * The default read buffer size is patchable. 7748932Smccanne */ 7851425Smccanne int bpf_bufsize = BPF_BUFSIZE; 7948932Smccanne 8048932Smccanne /* 8149202Smccanne * bpf_iflist is the list of interfaces; each corresponds to an ifnet 8249202Smccanne * bpf_dtab holds the descriptors, indexed by minor device # 8347584Smccanne */ 8453947Smccanne struct bpf_if *bpf_iflist; 8553947Smccanne struct bpf_d bpf_dtab[NBPFILTER]; 8647584Smccanne 8747584Smccanne static void bpf_ifname(); 8847584Smccanne static void catchpacket(); 8953947Smccanne static void bpf_freed(); 9047584Smccanne static int bpf_setif(); 9147584Smccanne static int bpf_initd(); 9253947Smccanne static int bpf_allocbufs(); 9347584Smccanne 9447584Smccanne static int 9547584Smccanne bpf_movein(uio, linktype, mp, sockp) 9647584Smccanne register struct uio *uio; 9747584Smccanne int linktype; 9847584Smccanne register struct mbuf **mp; 9947584Smccanne register struct sockaddr *sockp; 10047584Smccanne { 10147584Smccanne struct mbuf *m; 10247584Smccanne int error; 10347584Smccanne int len; 10447584Smccanne int hlen; 10547584Smccanne 10647584Smccanne /* 10747584Smccanne * Build a sockaddr based on the data link layer type. 10847584Smccanne * We do this at this level because the ethernet header 10947584Smccanne * is copied directly into the data field of the sockaddr. 11047584Smccanne * In the case of SLIP, there is no header and the packet 11147584Smccanne * is forwarded as is. 11247584Smccanne * Also, we are careful to leave room at the front of the mbuf 11347584Smccanne * for the link level header. 11447584Smccanne */ 11547584Smccanne switch (linktype) { 11653947Smccanne 11747584Smccanne case DLT_SLIP: 11847584Smccanne sockp->sa_family = AF_INET; 11947584Smccanne hlen = 0; 12047584Smccanne break; 12147584Smccanne 12247584Smccanne case DLT_EN10MB: 12347584Smccanne sockp->sa_family = AF_UNSPEC; 12447584Smccanne /* XXX Would MAXLINKHDR be better? */ 12547584Smccanne hlen = sizeof(struct ether_header); 12647584Smccanne break; 12747584Smccanne 12853947Smccanne case DLT_FDDI: 12947584Smccanne sockp->sa_family = AF_UNSPEC; 13047584Smccanne /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */ 13147584Smccanne hlen = 24; 13247584Smccanne break; 13347584Smccanne 13453947Smccanne case DLT_NULL: 13553947Smccanne sockp->sa_family = AF_UNSPEC; 13653947Smccanne hlen = 0; 13753947Smccanne break; 13853947Smccanne 13947584Smccanne default: 14048932Smccanne return (EIO); 14147584Smccanne } 14247584Smccanne 14347584Smccanne len = uio->uio_resid; 14447584Smccanne if ((unsigned)len > MCLBYTES) 14548932Smccanne return (EIO); 14647584Smccanne 14747584Smccanne MGET(m, M_WAIT, MT_DATA); 14847584Smccanne if (m == 0) 14948932Smccanne return (ENOBUFS); 15047584Smccanne if (len > MLEN) { 15151425Smccanne #if BSD >= 199103 15248932Smccanne MCLGET(m, M_WAIT); 15348932Smccanne if ((m->m_flags & M_EXT) == 0) { 15451425Smccanne #else 15551425Smccanne MCLGET(m); 15653947Smccanne if (m->m_len != MCLBYTES) { 15751425Smccanne #endif 15853947Smccanne error = ENOBUFS; 15947584Smccanne goto bad; 16047584Smccanne } 16147584Smccanne } 16247584Smccanne m->m_len = len; 16347584Smccanne *mp = m; 16447584Smccanne /* 16547584Smccanne * Make room for link header. 16647584Smccanne */ 16753947Smccanne if (hlen != 0) { 16847584Smccanne m->m_len -= hlen; 16951425Smccanne #if BSD >= 199103 17048932Smccanne m->m_data += hlen; /* XXX */ 17151425Smccanne #else 17251425Smccanne m->m_off += hlen; 17351425Smccanne #endif 17453947Smccanne error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio); 17547584Smccanne if (error) 17647584Smccanne goto bad; 17747584Smccanne } 17853947Smccanne error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio); 17953947Smccanne if (!error) 18048932Smccanne return (0); 18147584Smccanne bad: 18247584Smccanne m_freem(m); 18348932Smccanne return (error); 18447584Smccanne } 18547584Smccanne 18647584Smccanne /* 18751425Smccanne * Attach file to the bpf interface, i.e. make d listen on bp. 18847584Smccanne * Must be called at splimp. 18947584Smccanne */ 19047584Smccanne static void 19147584Smccanne bpf_attachd(d, bp) 19247584Smccanne struct bpf_d *d; 19347584Smccanne struct bpf_if *bp; 19447584Smccanne { 19551425Smccanne /* 19651425Smccanne * Point d at bp, and add d to the interface's list of listeners. 19751425Smccanne * Finally, point the driver's bpf cookie at the interface so 19851425Smccanne * it will divert packets to bpf. 19951425Smccanne */ 20047584Smccanne d->bd_bif = bp; 20147584Smccanne d->bd_next = bp->bif_dlist; 20247584Smccanne bp->bif_dlist = d; 20347584Smccanne 20447584Smccanne *bp->bif_driverp = bp; 20547584Smccanne } 20647584Smccanne 20751425Smccanne /* 20851425Smccanne * Detach a file from its interface. 20951425Smccanne */ 21047584Smccanne static void 21147584Smccanne bpf_detachd(d) 21247584Smccanne struct bpf_d *d; 21347584Smccanne { 21447584Smccanne struct bpf_d **p; 21547584Smccanne struct bpf_if *bp; 21647584Smccanne 21747584Smccanne bp = d->bd_bif; 21847584Smccanne /* 21947584Smccanne * Check if this descriptor had requested promiscuous mode. 22047584Smccanne * If so, turn it off. 22147584Smccanne */ 22247584Smccanne if (d->bd_promisc) { 22347584Smccanne d->bd_promisc = 0; 22447584Smccanne if (ifpromisc(bp->bif_ifp, 0)) 22547584Smccanne /* 22647584Smccanne * Something is really wrong if we were able to put 22747584Smccanne * the driver into promiscuous mode, but can't 22847584Smccanne * take it out. 22947584Smccanne */ 23051425Smccanne panic("bpf: ifpromisc failed"); 23147584Smccanne } 23251425Smccanne /* Remove d from the interface's descriptor list. */ 23347584Smccanne p = &bp->bif_dlist; 23447584Smccanne while (*p != d) { 23547584Smccanne p = &(*p)->bd_next; 23647584Smccanne if (*p == 0) 23747584Smccanne panic("bpf_detachd: descriptor not in list"); 23847584Smccanne } 23947584Smccanne *p = (*p)->bd_next; 24047584Smccanne if (bp->bif_dlist == 0) 24147584Smccanne /* 24247584Smccanne * Let the driver know that there are no more listeners. 24347584Smccanne */ 24447584Smccanne *d->bd_bif->bif_driverp = 0; 24547584Smccanne d->bd_bif = 0; 24647584Smccanne } 24747584Smccanne 24847584Smccanne 24947584Smccanne /* 25053947Smccanne * Mark a descriptor free by making it point to itself. 25147584Smccanne * This is probably cheaper than marking with a constant since 25247584Smccanne * the address should be in a register anyway. 25347584Smccanne */ 25447584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next) 25547584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d)) 25647584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0) 25747584Smccanne 25847584Smccanne /* 25953947Smccanne * Open ethernet device. Returns ENXIO for illegal minor device number, 26053947Smccanne * EBUSY if file is open by another process. 26147584Smccanne */ 26247584Smccanne /* ARGSUSED */ 26347584Smccanne int 26447584Smccanne bpfopen(dev, flag) 26547584Smccanne dev_t dev; 26647584Smccanne int flag; 26747584Smccanne { 26847584Smccanne register struct bpf_d *d; 26953947Smccanne 27047584Smccanne if (minor(dev) >= NBPFILTER) 27148932Smccanne return (ENXIO); 27247584Smccanne /* 27347584Smccanne * Each minor can be opened by only one process. If the requested 27447584Smccanne * minor is in use, return EBUSY. 27547584Smccanne */ 27647584Smccanne d = &bpf_dtab[minor(dev)]; 27753947Smccanne if (!D_ISFREE(d)) 27848932Smccanne return (EBUSY); 27947584Smccanne 28053947Smccanne /* Mark "free" and do most initialization. */ 28153947Smccanne bzero((char *)d, sizeof(*d)); 28253947Smccanne d->bd_bufsize = bpf_bufsize; 28353947Smccanne 28448932Smccanne return (0); 28547584Smccanne } 28647584Smccanne 28747584Smccanne /* 28847584Smccanne * Close the descriptor by detaching it from its interface, 28947584Smccanne * deallocating its buffers, and marking it free. 29047584Smccanne */ 29147584Smccanne /* ARGSUSED */ 29253947Smccanne int 29347584Smccanne bpfclose(dev, flag) 29447584Smccanne dev_t dev; 29547584Smccanne int flag; 29647584Smccanne { 29747584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 29853947Smccanne register int s; 29947584Smccanne 30047584Smccanne s = splimp(); 30147584Smccanne if (d->bd_bif) 30247584Smccanne bpf_detachd(d); 30347584Smccanne splx(s); 30453947Smccanne bpf_freed(d); 30547584Smccanne 30653947Smccanne return (0); 30747584Smccanne } 30847584Smccanne 30953947Smccanne /* 31053947Smccanne * Support for SunOS, which does not have tsleep. 31153947Smccanne */ 31251425Smccanne #if BSD < 199103 31351425Smccanne static 31451425Smccanne bpf_timeout(arg) 31551425Smccanne caddr_t arg; 31651425Smccanne { 31751425Smccanne struct bpf_d *d = (struct bpf_d *)arg; 31851425Smccanne d->bd_timedout = 1; 31951425Smccanne wakeup(arg); 32051425Smccanne } 32151425Smccanne 32253947Smccanne #define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan) 32353947Smccanne 32453947Smccanne int 32553947Smccanne bpf_sleep(d) 32653947Smccanne register struct bpf_d *d; 32751425Smccanne { 32853947Smccanne register int rto = d->bd_rtout; 32953947Smccanne register int st; 33051425Smccanne 33153947Smccanne if (rto != 0) { 33251425Smccanne d->bd_timedout = 0; 33353947Smccanne timeout(bpf_timeout, (caddr_t)d, rto); 33451425Smccanne } 33553947Smccanne st = sleep((caddr_t)d, PRINET|PCATCH); 33653947Smccanne if (rto != 0) { 33753947Smccanne if (d->bd_timedout == 0) 33853947Smccanne untimeout(bpf_timeout, (caddr_t)d); 33953947Smccanne else if (st == 0) 34051425Smccanne return EWOULDBLOCK; 34151425Smccanne } 34253947Smccanne return (st != 0) ? EINTR : 0; 34351425Smccanne } 34453947Smccanne #else 34553947Smccanne #define BPF_SLEEP tsleep 34651425Smccanne #endif 34751425Smccanne 34847584Smccanne /* 34948932Smccanne * Rotate the packet buffers in descriptor d. Move the store buffer 35053947Smccanne * into the hold slot, and the free buffer into the store slot. 35148932Smccanne * Zero the length of the new store buffer. 35248932Smccanne */ 35348932Smccanne #define ROTATE_BUFFERS(d) \ 35448932Smccanne (d)->bd_hbuf = (d)->bd_sbuf; \ 35548932Smccanne (d)->bd_hlen = (d)->bd_slen; \ 35648932Smccanne (d)->bd_sbuf = (d)->bd_fbuf; \ 35748932Smccanne (d)->bd_slen = 0; \ 35853947Smccanne (d)->bd_fbuf = 0; 35948932Smccanne /* 36047584Smccanne * bpfread - read next chunk of packets from buffers 36147584Smccanne */ 36247584Smccanne int 36347584Smccanne bpfread(dev, uio) 36447584Smccanne dev_t dev; 36547584Smccanne register struct uio *uio; 36647584Smccanne { 36747584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 36847584Smccanne int error; 36947584Smccanne int s; 37047584Smccanne 37147584Smccanne /* 37253947Smccanne * Restrict application to use a buffer the same size as 37347584Smccanne * as kernel buffers. 37447584Smccanne */ 37548932Smccanne if (uio->uio_resid != d->bd_bufsize) 37649202Smccanne return (EINVAL); 37747584Smccanne 37847584Smccanne s = splimp(); 37947584Smccanne /* 38053947Smccanne * If the hold buffer is empty, then do a timed sleep, which 38153947Smccanne * ends when the timeout expires or when enough packets 38253947Smccanne * have arrived to fill the store buffer. 38347584Smccanne */ 38447584Smccanne while (d->bd_hbuf == 0) { 38548932Smccanne if (d->bd_immediate && d->bd_slen != 0) { 38647584Smccanne /* 38747584Smccanne * A packet(s) either arrived since the previous 38847584Smccanne * read or arrived while we were asleep. 38947584Smccanne * Rotate the buffers and return what's here. 39047584Smccanne */ 39148932Smccanne ROTATE_BUFFERS(d); 39247584Smccanne break; 39347584Smccanne } 39453947Smccanne error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf", 39553947Smccanne d->bd_rtout); 39648932Smccanne if (error == EINTR || error == ERESTART) { 39748932Smccanne splx(s); 39848932Smccanne return (error); 39947584Smccanne } 40048932Smccanne if (error == EWOULDBLOCK) { 40147584Smccanne /* 40247584Smccanne * On a timeout, return what's in the buffer, 40348932Smccanne * which may be nothing. If there is something 40448932Smccanne * in the store buffer, we can rotate the buffers. 40547584Smccanne */ 40647584Smccanne if (d->bd_hbuf) 40747584Smccanne /* 40853947Smccanne * We filled up the buffer in between 40947584Smccanne * getting the timeout and arriving 41047584Smccanne * here, so we don't need to rotate. 41147584Smccanne */ 41247584Smccanne break; 41347584Smccanne 41448932Smccanne if (d->bd_slen == 0) { 41547584Smccanne splx(s); 41648932Smccanne return (0); 41747584Smccanne } 41848932Smccanne ROTATE_BUFFERS(d); 41947584Smccanne break; 42047584Smccanne } 42147584Smccanne } 42247584Smccanne /* 42347584Smccanne * At this point, we know we have something in the hold slot. 42447584Smccanne */ 42547584Smccanne splx(s); 42653947Smccanne 42753947Smccanne /* 42847584Smccanne * Move data from hold buffer into user space. 42947584Smccanne * We know the entire buffer is transferred since 43048932Smccanne * we checked above that the read buffer is bpf_bufsize bytes. 43147584Smccanne */ 43253947Smccanne error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio); 43353947Smccanne 43447584Smccanne s = splimp(); 43548932Smccanne d->bd_fbuf = d->bd_hbuf; 43648932Smccanne d->bd_hbuf = 0; 43753947Smccanne d->bd_hlen = 0; 43847584Smccanne splx(s); 43953947Smccanne 44048932Smccanne return (error); 44147584Smccanne } 44247584Smccanne 44347584Smccanne 44447584Smccanne /* 44553947Smccanne * If there are processes sleeping on this descriptor, wake them up. 44647584Smccanne */ 44747584Smccanne static inline void 44847584Smccanne bpf_wakeup(d) 44947584Smccanne register struct bpf_d *d; 45047584Smccanne { 45148932Smccanne wakeup((caddr_t)d); 45253947Smccanne #if BSD >= 199103 45353947Smccanne selwakeup(&d->bd_sel); 45453947Smccanne /* XXX */ 45553947Smccanne d->bd_sel.si_pid = 0; 45653947Smccanne #else 45753947Smccanne if (d->bd_selproc) { 45853947Smccanne selwakeup(d->bd_selproc, (int)d->bd_selcoll); 45953947Smccanne d->bd_selcoll = 0; 46053947Smccanne d->bd_selproc = 0; 46153947Smccanne } 46253947Smccanne #endif 46347584Smccanne } 46447584Smccanne 46547584Smccanne int 46647584Smccanne bpfwrite(dev, uio) 46747584Smccanne dev_t dev; 46847584Smccanne struct uio *uio; 46947584Smccanne { 47047584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 47147584Smccanne struct ifnet *ifp; 47247584Smccanne struct mbuf *m; 47347584Smccanne int error, s; 47447584Smccanne static struct sockaddr dst; 47547584Smccanne 47647584Smccanne if (d->bd_bif == 0) 47748932Smccanne return (ENXIO); 47847584Smccanne 47947584Smccanne ifp = d->bd_bif->bif_ifp; 48047584Smccanne 48147584Smccanne if (uio->uio_resid == 0) 48248932Smccanne return (0); 48347584Smccanne if (uio->uio_resid > ifp->if_mtu) 48448932Smccanne return (EMSGSIZE); 48547584Smccanne 48649202Smccanne error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst); 48747584Smccanne if (error) 48848932Smccanne return (error); 48947584Smccanne 49047584Smccanne s = splnet(); 49151425Smccanne #if BSD >= 199103 49253947Smccanne error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0); 49351425Smccanne #else 49447584Smccanne error = (*ifp->if_output)(ifp, m, &dst); 49551425Smccanne #endif 49647584Smccanne splx(s); 49747584Smccanne /* 49853947Smccanne * The driver frees the mbuf. 49947584Smccanne */ 50048932Smccanne return (error); 50147584Smccanne } 50247584Smccanne 50347584Smccanne /* 50453947Smccanne * Reset a descriptor by flushing its packet buffer and clearing the 50553947Smccanne * receive and drop counts. Should be called at splimp. 50647584Smccanne */ 50747584Smccanne static void 50847584Smccanne reset_d(d) 50947584Smccanne struct bpf_d *d; 51047584Smccanne { 51147584Smccanne if (d->bd_hbuf) { 51247584Smccanne /* Free the hold buffer. */ 51347584Smccanne d->bd_fbuf = d->bd_hbuf; 51447584Smccanne d->bd_hbuf = 0; 51547584Smccanne } 51648932Smccanne d->bd_slen = 0; 51753947Smccanne d->bd_hlen = 0; 51847584Smccanne d->bd_rcount = 0; 51947584Smccanne d->bd_dcount = 0; 52047584Smccanne } 52147584Smccanne 52247584Smccanne /* 52347584Smccanne * FIONREAD Check for read packet available. 52447584Smccanne * SIOCGIFADDR Get interface address - convenient hook to driver. 52547584Smccanne * BIOCGBLEN Get buffer len [for read()]. 52647584Smccanne * BIOCSETF Set ethernet read filter. 52747584Smccanne * BIOCFLUSH Flush read packet buffer. 52847584Smccanne * BIOCPROMISC Put interface into promiscuous mode. 52949202Smccanne * BIOCGDLT Get link layer type. 53047584Smccanne * BIOCGETIF Get interface name. 53147584Smccanne * BIOCSETIF Set interface. 53247584Smccanne * BIOCSRTIMEOUT Set read timeout. 53347584Smccanne * BIOCGRTIMEOUT Get read timeout. 53447584Smccanne * BIOCGSTATS Get packet stats. 53547584Smccanne * BIOCIMMEDIATE Set immediate mode. 53653947Smccanne * BIOCVERSION Get filter language version. 53747584Smccanne */ 53847584Smccanne /* ARGSUSED */ 53947584Smccanne int 54047584Smccanne bpfioctl(dev, cmd, addr, flag) 54147584Smccanne dev_t dev; 54247584Smccanne int cmd; 54347584Smccanne caddr_t addr; 54447584Smccanne int flag; 54547584Smccanne { 54647584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 54747584Smccanne int s, error = 0; 54847584Smccanne 54947584Smccanne switch (cmd) { 55047584Smccanne 55147584Smccanne default: 55247584Smccanne error = EINVAL; 55347584Smccanne break; 55447584Smccanne 55547584Smccanne /* 55647584Smccanne * Check for read packet available. 55747584Smccanne */ 55847584Smccanne case FIONREAD: 55947584Smccanne { 56047584Smccanne int n; 56153947Smccanne 56247584Smccanne s = splimp(); 56348932Smccanne n = d->bd_slen; 56453947Smccanne if (d->bd_hbuf) 56548932Smccanne n += d->bd_hlen; 56647584Smccanne splx(s); 56747584Smccanne 56847584Smccanne *(int *)addr = n; 56947584Smccanne break; 57047584Smccanne } 57147584Smccanne 57247584Smccanne case SIOCGIFADDR: 57347584Smccanne { 57447584Smccanne struct ifnet *ifp; 57547584Smccanne 57647584Smccanne if (d->bd_bif == 0) 57747584Smccanne error = EINVAL; 57847584Smccanne else { 57947584Smccanne ifp = d->bd_bif->bif_ifp; 58053947Smccanne error = (*ifp->if_ioctl)(ifp, cmd, addr); 58147584Smccanne } 58247584Smccanne break; 58347584Smccanne } 58447584Smccanne 58547584Smccanne /* 58647584Smccanne * Get buffer len [for read()]. 58747584Smccanne */ 58847584Smccanne case BIOCGBLEN: 58948932Smccanne *(u_int *)addr = d->bd_bufsize; 59047584Smccanne break; 59147584Smccanne 59247584Smccanne /* 59353947Smccanne * Set buffer length. 59453947Smccanne */ 59553947Smccanne case BIOCSBLEN: 59653947Smccanne #if BSD < 199103 59753947Smccanne error = EINVAL; 59853947Smccanne #else 59953947Smccanne if (d->bd_bif != 0) 60053947Smccanne error = EINVAL; 60153947Smccanne else { 60253947Smccanne register u_int size = *(u_int *)addr; 60353947Smccanne 60453947Smccanne if (size > BPF_MAXBUFSIZE) 60553947Smccanne *(u_int *)addr = size = BPF_MAXBUFSIZE; 60653947Smccanne else if (size < BPF_MINBUFSIZE) 60753947Smccanne *(u_int *)addr = size = BPF_MINBUFSIZE; 60853947Smccanne d->bd_bufsize = size; 60953947Smccanne } 61053947Smccanne #endif 61153947Smccanne break; 61253947Smccanne 61353947Smccanne /* 61451425Smccanne * Set link layer read filter. 61547584Smccanne */ 61653947Smccanne case BIOCSETF: 61747584Smccanne error = bpf_setf(d, (struct bpf_program *)addr); 61847584Smccanne break; 61947584Smccanne 62047584Smccanne /* 62147584Smccanne * Flush read packet buffer. 62247584Smccanne */ 62347584Smccanne case BIOCFLUSH: 62447584Smccanne s = splimp(); 62547584Smccanne reset_d(d); 62647584Smccanne splx(s); 62747584Smccanne break; 62847584Smccanne 62947584Smccanne /* 63047584Smccanne * Put interface into promiscuous mode. 63147584Smccanne */ 63247584Smccanne case BIOCPROMISC: 63347584Smccanne if (d->bd_bif == 0) { 63447584Smccanne /* 63547584Smccanne * No interface attached yet. 63647584Smccanne */ 63747584Smccanne error = EINVAL; 63847584Smccanne break; 63947584Smccanne } 64047584Smccanne s = splimp(); 64147584Smccanne if (d->bd_promisc == 0) { 64247584Smccanne error = ifpromisc(d->bd_bif->bif_ifp, 1); 64351425Smccanne if (error == 0) 64451425Smccanne d->bd_promisc = 1; 64547584Smccanne } 64647584Smccanne splx(s); 64747584Smccanne break; 64847584Smccanne 64947584Smccanne /* 65047584Smccanne * Get device parameters. 65147584Smccanne */ 65249202Smccanne case BIOCGDLT: 65347584Smccanne if (d->bd_bif == 0) 65447584Smccanne error = EINVAL; 65547584Smccanne else 65649202Smccanne *(u_int *)addr = d->bd_bif->bif_dlt; 65747584Smccanne break; 65847584Smccanne 65947584Smccanne /* 66047584Smccanne * Set interface name. 66147584Smccanne */ 66247584Smccanne case BIOCGETIF: 66347584Smccanne if (d->bd_bif == 0) 66447584Smccanne error = EINVAL; 66547584Smccanne else 66647584Smccanne bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr); 66747584Smccanne break; 66847584Smccanne 66947584Smccanne /* 67047584Smccanne * Set interface. 67147584Smccanne */ 67247584Smccanne case BIOCSETIF: 67347584Smccanne error = bpf_setif(d, (struct ifreq *)addr); 67447584Smccanne break; 67547584Smccanne 67647584Smccanne /* 67747584Smccanne * Set read timeout. 67847584Smccanne */ 67953947Smccanne case BIOCSRTIMEOUT: 68047584Smccanne { 68147584Smccanne struct timeval *tv = (struct timeval *)addr; 68247584Smccanne u_long msec; 68347584Smccanne 68447584Smccanne /* Compute number of milliseconds. */ 68547584Smccanne msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; 68647584Smccanne /* Scale milliseconds to ticks. Assume hard 68747584Smccanne clock has millisecond or greater resolution 68847584Smccanne (i.e. tick >= 1000). For 10ms hardclock, 68947584Smccanne tick/1000 = 10, so rtout<-msec/10. */ 69047584Smccanne d->bd_rtout = msec / (tick / 1000); 69147584Smccanne break; 69247584Smccanne } 69347584Smccanne 69447584Smccanne /* 69547584Smccanne * Get read timeout. 69647584Smccanne */ 69753947Smccanne case BIOCGRTIMEOUT: 69847584Smccanne { 69947584Smccanne struct timeval *tv = (struct timeval *)addr; 70047584Smccanne u_long msec = d->bd_rtout; 70147584Smccanne 70247584Smccanne msec *= tick / 1000; 70347584Smccanne tv->tv_sec = msec / 1000; 70447584Smccanne tv->tv_usec = msec % 1000; 70547584Smccanne break; 70647584Smccanne } 70747584Smccanne 70847584Smccanne /* 70947584Smccanne * Get packet stats. 71047584Smccanne */ 71147584Smccanne case BIOCGSTATS: 71247584Smccanne { 71347584Smccanne struct bpf_stat *bs = (struct bpf_stat *)addr; 71447584Smccanne 71547584Smccanne bs->bs_recv = d->bd_rcount; 71647584Smccanne bs->bs_drop = d->bd_dcount; 71747584Smccanne break; 71847584Smccanne } 71947584Smccanne 72047584Smccanne /* 72147584Smccanne * Set immediate mode. 72247584Smccanne */ 72347584Smccanne case BIOCIMMEDIATE: 72447584Smccanne d->bd_immediate = *(u_int *)addr; 72547584Smccanne break; 72653947Smccanne 72753947Smccanne case BIOCVERSION: 72853947Smccanne { 72953947Smccanne struct bpf_version *bv = (struct bpf_version *)addr; 73053947Smccanne 73153947Smccanne bv->bv_major = BPF_MAJOR_VERSION; 73253947Smccanne bv->bv_minor = BPF_MINOR_VERSION; 73353947Smccanne break; 73453947Smccanne } 73547584Smccanne } 73648932Smccanne return (error); 73747584Smccanne } 73847584Smccanne 73953947Smccanne /* 74051425Smccanne * Set d's packet filter program to fp. If this file already has a filter, 74148932Smccanne * free it and replace it. Returns EINVAL for bogus requests. 74247584Smccanne */ 74347584Smccanne int 74447584Smccanne bpf_setf(d, fp) 74547584Smccanne struct bpf_d *d; 74647584Smccanne struct bpf_program *fp; 74747584Smccanne { 74848932Smccanne struct bpf_insn *fcode, *old; 74947584Smccanne u_int flen, size; 75047584Smccanne int s; 75147584Smccanne 75248932Smccanne old = d->bd_filter; 75347584Smccanne if (fp->bf_insns == 0) { 75447584Smccanne if (fp->bf_len != 0) 75548932Smccanne return (EINVAL); 75648932Smccanne s = splimp(); 75748967Smccanne d->bd_filter = 0; 75847584Smccanne reset_d(d); 75947584Smccanne splx(s); 76048967Smccanne if (old != 0) 76148932Smccanne free((caddr_t)old, M_DEVBUF); 76248932Smccanne return (0); 76347584Smccanne } 76447584Smccanne flen = fp->bf_len; 76548932Smccanne if (flen > BPF_MAXINSNS) 76648932Smccanne return (EINVAL); 76748932Smccanne 76847584Smccanne size = flen * sizeof(*fp->bf_insns); 76948932Smccanne fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK); 77050417Smccanne if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 && 77150417Smccanne bpf_validate(fcode, (int)flen)) { 77248967Smccanne s = splimp(); 77348932Smccanne d->bd_filter = fcode; 77447584Smccanne reset_d(d); 77547584Smccanne splx(s); 77648967Smccanne if (old != 0) 77748932Smccanne free((caddr_t)old, M_DEVBUF); 77847584Smccanne 77948932Smccanne return (0); 78047584Smccanne } 78148932Smccanne free((caddr_t)fcode, M_DEVBUF); 78248932Smccanne return (EINVAL); 78347584Smccanne } 78447584Smccanne 78547584Smccanne /* 78653947Smccanne * Detach a file from its current interface (if attached at all) and attach 78753947Smccanne * to the interface indicated by the name stored in ifr. 78851425Smccanne * Return an errno or 0. 78947584Smccanne */ 79047584Smccanne static int 79147584Smccanne bpf_setif(d, ifr) 79247584Smccanne struct bpf_d *d; 79347584Smccanne struct ifreq *ifr; 79447584Smccanne { 79547584Smccanne struct bpf_if *bp; 79647584Smccanne char *cp; 79753947Smccanne int unit, s, error; 79847584Smccanne 79947584Smccanne /* 80047584Smccanne * Separate string into name part and unit number. Put a null 80153947Smccanne * byte at the end of the name part, and compute the number. 80247584Smccanne * If the a unit number is unspecified, the default is 0, 80348932Smccanne * as initialized above. XXX This should be common code. 80447584Smccanne */ 80547584Smccanne unit = 0; 80647584Smccanne cp = ifr->ifr_name; 80747584Smccanne cp[sizeof(ifr->ifr_name) - 1] = '\0'; 80847584Smccanne while (*cp++) { 80947584Smccanne if (*cp >= '0' && *cp <= '9') { 81047584Smccanne unit = *cp - '0'; 81147584Smccanne *cp++ = '\0'; 81247584Smccanne while (*cp) 81347584Smccanne unit = 10 * unit + *cp++ - '0'; 81447584Smccanne break; 81547584Smccanne } 81647584Smccanne } 81747584Smccanne /* 81847584Smccanne * Look through attached interfaces for the named one. 81947584Smccanne */ 82049202Smccanne for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) { 82147584Smccanne struct ifnet *ifp = bp->bif_ifp; 82247584Smccanne 82353947Smccanne if (ifp == 0 || unit != ifp->if_unit 82447584Smccanne || strcmp(ifp->if_name, ifr->ifr_name) != 0) 82547584Smccanne continue; 82647584Smccanne /* 82753947Smccanne * We found the requested interface. 82847584Smccanne * If it's not up, return an error. 82953947Smccanne * Allocate the packet buffers if we need to. 83053947Smccanne * If we're already attached to requested interface, 83153947Smccanne * just flush the buffer. 83247584Smccanne */ 83347584Smccanne if ((ifp->if_flags & IFF_UP) == 0) 83448932Smccanne return (ENETDOWN); 83553947Smccanne 83653947Smccanne if (d->bd_sbuf == 0) { 83753947Smccanne error = bpf_allocbufs(d); 83853947Smccanne if (error != 0) 83953947Smccanne return (error); 84053947Smccanne } 84147584Smccanne s = splimp(); 84247584Smccanne if (bp != d->bd_bif) { 84347584Smccanne if (d->bd_bif) 84453947Smccanne /* 84548932Smccanne * Detach if attached to something else. 84647584Smccanne */ 84747584Smccanne bpf_detachd(d); 84847584Smccanne 84947584Smccanne bpf_attachd(d, bp); 85047584Smccanne } 85147584Smccanne reset_d(d); 85247584Smccanne splx(s); 85348932Smccanne return (0); 85447584Smccanne } 85547584Smccanne /* Not found. */ 85648932Smccanne return (ENXIO); 85747584Smccanne } 85847584Smccanne 85947584Smccanne /* 86051425Smccanne * Convert an interface name plus unit number of an ifp to a single 86151425Smccanne * name which is returned in the ifr. 86247584Smccanne */ 86347584Smccanne static void 86447584Smccanne bpf_ifname(ifp, ifr) 86547584Smccanne struct ifnet *ifp; 86647584Smccanne struct ifreq *ifr; 86747584Smccanne { 86847584Smccanne char *s = ifp->if_name; 86947584Smccanne char *d = ifr->ifr_name; 87047584Smccanne 87147584Smccanne while (*d++ = *s++) 87253947Smccanne continue; 87348932Smccanne /* XXX Assume that unit number is less than 10. */ 87447584Smccanne *d++ = ifp->if_unit + '0'; 87547584Smccanne *d = '\0'; 87647584Smccanne } 87747584Smccanne 87847584Smccanne /* 87951425Smccanne * The new select interface passes down the proc pointer; the old select 88051425Smccanne * stubs had to grab it out of the user struct. This glue allows either case. 88151425Smccanne */ 88251425Smccanne #if BSD >= 199103 88351425Smccanne #define bpf_select bpfselect 88451425Smccanne #else 88551425Smccanne int 88651425Smccanne bpfselect(dev, rw) 88751425Smccanne register dev_t dev; 88851425Smccanne int rw; 88951425Smccanne { 89053947Smccanne return (bpf_select(dev, rw, u.u_procp)); 89151425Smccanne } 89251425Smccanne #endif 89351425Smccanne 89451425Smccanne /* 89547584Smccanne * Support for select() system call 89647584Smccanne * Inspired by the code in tty.c for the same purpose. 89747584Smccanne * 89853947Smccanne * Return true iff the specific operation will not block indefinitely. 89953947Smccanne * Otherwise, return false but make a note that a selwakeup() must be done. 90047584Smccanne */ 90147584Smccanne int 90251425Smccanne bpf_select(dev, rw, p) 90347584Smccanne register dev_t dev; 90447584Smccanne int rw; 90548932Smccanne struct proc *p; 90647584Smccanne { 90747584Smccanne register struct bpf_d *d; 90847584Smccanne register int s; 90953947Smccanne 91047584Smccanne if (rw != FREAD) 91148932Smccanne return (0); 91247584Smccanne /* 91347584Smccanne * An imitation of the FIONREAD ioctl code. 91447584Smccanne */ 91547584Smccanne d = &bpf_dtab[minor(dev)]; 91653947Smccanne 91747584Smccanne s = splimp(); 91849723Smccanne if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) { 91947584Smccanne /* 92047584Smccanne * There is data waiting. 92147584Smccanne */ 92247584Smccanne splx(s); 92348932Smccanne return (1); 92447584Smccanne } 92553947Smccanne #if BSD >= 199103 92653947Smccanne selrecord(p, &d->bd_sel); 92753947Smccanne #else 92847584Smccanne /* 92947584Smccanne * No data ready. If there's already a select() waiting on this 93053947Smccanne * minor device then this is a collision. This shouldn't happen 93147584Smccanne * because minors really should not be shared, but if a process 93247584Smccanne * forks while one of these is open, it is possible that both 93347584Smccanne * processes could select on the same descriptor. 93447584Smccanne */ 93553947Smccanne if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait) 93653947Smccanne d->bd_selcoll = 1; 93753947Smccanne else 93853947Smccanne d->bd_selproc = p; 93953947Smccanne #endif 94053947Smccanne splx(s); 94148932Smccanne return (0); 94247584Smccanne } 94347584Smccanne 94447584Smccanne /* 94553947Smccanne * Incoming linkage from device drivers. Process the packet pkt, of length 94653947Smccanne * pktlen, which is stored in a contiguous buffer. The packet is parsed 94753947Smccanne * by each process' filter, and if accepted, stashed into the corresponding 94853947Smccanne * buffer. 94947584Smccanne */ 95047584Smccanne void 95148932Smccanne bpf_tap(arg, pkt, pktlen) 95247584Smccanne caddr_t arg; 95348932Smccanne register u_char *pkt; 95448932Smccanne register u_int pktlen; 95547584Smccanne { 95647584Smccanne struct bpf_if *bp; 95747584Smccanne register struct bpf_d *d; 95847584Smccanne register u_int slen; 95947584Smccanne /* 96047584Smccanne * Note that the ipl does not have to be raised at this point. 96147584Smccanne * The only problem that could arise here is that if two different 96247584Smccanne * interfaces shared any data. This is not the case. 96347584Smccanne */ 96447584Smccanne bp = (struct bpf_if *)arg; 96547584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 96647584Smccanne ++d->bd_rcount; 96749202Smccanne slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen); 96847584Smccanne if (slen != 0) 96949202Smccanne catchpacket(d, pkt, pktlen, slen, bcopy); 97047584Smccanne } 97147584Smccanne } 97247584Smccanne 97347584Smccanne /* 97447584Smccanne * Copy data from an mbuf chain into a buffer. This code is derived 97547584Smccanne * from m_copydata in sys/uipc_mbuf.c. 97647584Smccanne */ 97747584Smccanne static void 97849202Smccanne bpf_mcopy(src, dst, len) 97947584Smccanne u_char *src; 98047584Smccanne u_char *dst; 98147584Smccanne register int len; 98247584Smccanne { 98347584Smccanne register struct mbuf *m = (struct mbuf *)src; 98447584Smccanne register unsigned count; 98547584Smccanne 98647584Smccanne while (len > 0) { 98747584Smccanne if (m == 0) 98849202Smccanne panic("bpf_mcopy"); 989*55065Spendry count = min(m->m_len, len); 99049202Smccanne bcopy(mtod(m, caddr_t), (caddr_t)dst, count); 99149202Smccanne m = m->m_next; 99249202Smccanne dst += count; 99347584Smccanne len -= count; 99447584Smccanne } 99547584Smccanne } 99647584Smccanne 99747584Smccanne /* 99853947Smccanne * Incoming linkage from device drivers, when packet is in an mbuf chain. 99947584Smccanne */ 100047584Smccanne void 100149202Smccanne bpf_mtap(arg, m) 100247584Smccanne caddr_t arg; 100349202Smccanne struct mbuf *m; 100447584Smccanne { 100547584Smccanne struct bpf_if *bp = (struct bpf_if *)arg; 100647584Smccanne struct bpf_d *d; 100749202Smccanne u_int pktlen, slen; 100849202Smccanne struct mbuf *m0; 100947584Smccanne 101048932Smccanne pktlen = 0; 101151425Smccanne for (m0 = m; m0 != 0; m0 = m0->m_next) 101249202Smccanne pktlen += m0->m_len; 101349723Smccanne 101447584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 101547584Smccanne ++d->bd_rcount; 101649202Smccanne slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0); 101747584Smccanne if (slen != 0) 101849202Smccanne catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy); 101947584Smccanne } 102047584Smccanne } 102147584Smccanne 102247584Smccanne /* 102349202Smccanne * Move the packet data from interface memory (pkt) into the 102447584Smccanne * store buffer. Return 1 if it's time to wakeup a listener (buffer full), 102553947Smccanne * otherwise 0. "copy" is the routine called to do the actual data 102651425Smccanne * transfer. bcopy is passed in to copy contiguous chunks, while 102751425Smccanne * bpf_mcopy is passed in to copy mbuf chains. In the latter case, 102851425Smccanne * pkt is really an mbuf. 102947584Smccanne */ 103047584Smccanne static void 103148932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn) 103248932Smccanne register struct bpf_d *d; 103348932Smccanne register u_char *pkt; 103448932Smccanne register u_int pktlen, snaplen; 103548932Smccanne register void (*cpfn)(); 103647584Smccanne { 103748932Smccanne register struct bpf_hdr *hp; 103848932Smccanne register int totlen, curlen; 103948932Smccanne register int hdrlen = d->bd_bif->bif_hdrlen; 104047584Smccanne /* 104147584Smccanne * Figure out how many bytes to move. If the packet is 104247584Smccanne * greater or equal to the snapshot length, transfer that 104347584Smccanne * much. Otherwise, transfer the whole packet (unless 104448932Smccanne * we hit the buffer size limit). 104547584Smccanne */ 1046*55065Spendry totlen = hdrlen + min(snaplen, pktlen); 104750082Smccanne if (totlen > d->bd_bufsize) 104850082Smccanne totlen = d->bd_bufsize; 104947584Smccanne 105047584Smccanne /* 105147584Smccanne * Round up the end of the previous packet to the next longword. 105247584Smccanne */ 105348932Smccanne curlen = BPF_WORDALIGN(d->bd_slen); 105448932Smccanne if (curlen + totlen > d->bd_bufsize) { 105547584Smccanne /* 105647584Smccanne * This packet will overflow the storage buffer. 105748932Smccanne * Rotate the buffers if we can, then wakeup any 105848932Smccanne * pending reads. 105947584Smccanne */ 106047584Smccanne if (d->bd_fbuf == 0) { 106153947Smccanne /* 106253947Smccanne * We haven't completed the previous read yet, 106348932Smccanne * so drop the packet. 106447584Smccanne */ 106547584Smccanne ++d->bd_dcount; 106647584Smccanne return; 106747584Smccanne } 106848932Smccanne ROTATE_BUFFERS(d); 106947584Smccanne bpf_wakeup(d); 107048932Smccanne curlen = 0; 107147584Smccanne } 107253947Smccanne else if (d->bd_immediate) 107347584Smccanne /* 107447584Smccanne * Immediate mode is set. A packet arrived so any 107547584Smccanne * reads should be woken up. 107647584Smccanne */ 107747584Smccanne bpf_wakeup(d); 107848932Smccanne 107947584Smccanne /* 108047584Smccanne * Append the bpf header. 108147584Smccanne */ 108248932Smccanne hp = (struct bpf_hdr *)(d->bd_sbuf + curlen); 108351425Smccanne #if BSD >= 199103 108447584Smccanne microtime(&hp->bh_tstamp); 108553947Smccanne #elif defined(sun) 108653947Smccanne uniqtime(&hp->bh_tstamp); 108747584Smccanne #else 108847584Smccanne hp->bh_tstamp = time; 108947584Smccanne #endif 109048932Smccanne hp->bh_datalen = pktlen; 109147584Smccanne hp->bh_hdrlen = hdrlen; 109247584Smccanne /* 109348932Smccanne * Copy the packet data into the store buffer and update its length. 109447584Smccanne */ 109548932Smccanne (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen)); 109648932Smccanne d->bd_slen = curlen + totlen; 109747584Smccanne } 109847584Smccanne 109953947Smccanne /* 110047584Smccanne * Initialize all nonzero fields of a descriptor. 110147584Smccanne */ 110247584Smccanne static int 110353947Smccanne bpf_allocbufs(d) 110447584Smccanne register struct bpf_d *d; 110547584Smccanne { 110648932Smccanne d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 110748932Smccanne if (d->bd_fbuf == 0) 110848932Smccanne return (ENOBUFS); 110947584Smccanne 111048932Smccanne d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 111148932Smccanne if (d->bd_sbuf == 0) { 111248932Smccanne free(d->bd_fbuf, M_DEVBUF); 111348932Smccanne return (ENOBUFS); 111447584Smccanne } 111548932Smccanne d->bd_slen = 0; 111648932Smccanne d->bd_hlen = 0; 111748932Smccanne return (0); 111847584Smccanne } 111947584Smccanne 112047584Smccanne /* 112151425Smccanne * Free buffers currently in use by a descriptor. 112251425Smccanne * Called on close. 112347584Smccanne */ 112453947Smccanne static void 112551425Smccanne bpf_freed(d) 112651425Smccanne register struct bpf_d *d; 112751425Smccanne { 112851425Smccanne /* 112951425Smccanne * We don't need to lock out interrupts since this descriptor has 113053947Smccanne * been detached from its interface and it yet hasn't been marked 113151425Smccanne * free. 113251425Smccanne */ 113353947Smccanne if (d->bd_sbuf != 0) { 113453947Smccanne free(d->bd_sbuf, M_DEVBUF); 113553947Smccanne if (d->bd_hbuf != 0) 113653947Smccanne free(d->bd_hbuf, M_DEVBUF); 113753947Smccanne if (d->bd_fbuf != 0) 113853947Smccanne free(d->bd_fbuf, M_DEVBUF); 113953947Smccanne } 114051425Smccanne if (d->bd_filter) 114151425Smccanne free((caddr_t)d->bd_filter, M_DEVBUF); 114253947Smccanne 114351425Smccanne D_MARKFREE(d); 114451425Smccanne } 114551425Smccanne 114651425Smccanne /* 114751425Smccanne * Attach an interface to bpf. driverp is a pointer to a (struct bpf_if *) 114851425Smccanne * in the driver's softc; dlt is the link layer type; hdrlen is the fixed 114951425Smccanne * size of the link header (variable length headers not yet supported). 115051425Smccanne */ 115147584Smccanne void 115249202Smccanne bpfattach(driverp, ifp, dlt, hdrlen) 115347584Smccanne caddr_t *driverp; 115447584Smccanne struct ifnet *ifp; 115549202Smccanne u_int dlt, hdrlen; 115647584Smccanne { 115747584Smccanne struct bpf_if *bp; 115847584Smccanne int i; 115951425Smccanne #if BSD < 199103 116051425Smccanne static struct bpf_if bpf_ifs[NBPFILTER]; 116151425Smccanne static int bpfifno; 116247584Smccanne 116351425Smccanne bp = (bpfifno < NBPFILTER) ? &bpf_ifs[bpfifno++] : 0; 116451425Smccanne #else 116549202Smccanne bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT); 116651425Smccanne #endif 116749202Smccanne if (bp == 0) 116849202Smccanne panic("bpfattach"); 116947584Smccanne 117047584Smccanne bp->bif_dlist = 0; 117147584Smccanne bp->bif_driverp = (struct bpf_if **)driverp; 117247584Smccanne bp->bif_ifp = ifp; 117349202Smccanne bp->bif_dlt = dlt; 117447584Smccanne 117549202Smccanne bp->bif_next = bpf_iflist; 117649202Smccanne bpf_iflist = bp; 117749202Smccanne 117848932Smccanne *bp->bif_driverp = 0; 117948932Smccanne 118047584Smccanne /* 118147584Smccanne * Compute the length of the bpf header. This is not necessarily 118253947Smccanne * equal to SIZEOF_BPF_HDR because we want to insert spacing such 118353947Smccanne * that the network layer header begins on a longword boundary (for 118447584Smccanne * performance reasons and to alleviate alignment restrictions). 118547584Smccanne */ 118649202Smccanne bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen; 118747584Smccanne 118847584Smccanne /* 118947584Smccanne * Mark all the descriptors free if this hasn't been done. 119047584Smccanne */ 119147584Smccanne if (!D_ISFREE(&bpf_dtab[0])) 119247584Smccanne for (i = 0; i < NBPFILTER; ++i) 119347584Smccanne D_MARKFREE(&bpf_dtab[i]); 119447584Smccanne 119547584Smccanne printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit); 119647584Smccanne } 119747584Smccanne 119851425Smccanne #if BSD >= 199103 119948967Smccanne /* XXX This routine belongs in net/if.c. */ 120048932Smccanne /* 120153947Smccanne * Set/clear promiscuous mode on interface ifp based on the truth value 120248932Smccanne * of pswitch. The calls are reference counted so that only the first 120353947Smccanne * "on" request actually has an effect, as does the final "off" request. 120453947Smccanne * Results are undefined if the "off" and "on" requests are not matched. 120548932Smccanne */ 120648932Smccanne int 120748932Smccanne ifpromisc(ifp, pswitch) 120848932Smccanne struct ifnet *ifp; 120948932Smccanne int pswitch; 121048932Smccanne { 121149726Smccanne struct ifreq ifr; 121253947Smccanne /* 121348932Smccanne * If the device is not configured up, we cannot put it in 121448932Smccanne * promiscuous mode. 121548932Smccanne */ 121648932Smccanne if ((ifp->if_flags & IFF_UP) == 0) 121748932Smccanne return (ENETDOWN); 121848932Smccanne 121948932Smccanne if (pswitch) { 122048932Smccanne if (ifp->if_pcount++ != 0) 122148932Smccanne return (0); 122248932Smccanne ifp->if_flags |= IFF_PROMISC; 122348932Smccanne } else { 122448932Smccanne if (--ifp->if_pcount > 0) 122548932Smccanne return (0); 122648932Smccanne ifp->if_flags &= ~IFF_PROMISC; 122748932Smccanne } 122849726Smccanne ifr.ifr_flags = ifp->if_flags; 122949726Smccanne return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); 123048932Smccanne } 123151425Smccanne #endif 123248932Smccanne 123351425Smccanne #if BSD < 199103 123451425Smccanne /* 123551425Smccanne * Allocate some memory for bpf. This is temporary SunOS support, and 123653947Smccanne * is admittedly a hack. 123751425Smccanne * If resources unavaiable, return 0. 123851425Smccanne */ 123951425Smccanne static caddr_t 124051425Smccanne bpf_alloc(size, canwait) 124151425Smccanne register int size; 124251425Smccanne register int canwait; 124351425Smccanne { 124451425Smccanne register struct mbuf *m; 124551425Smccanne 124651425Smccanne if ((unsigned)size > (MCLBYTES-8)) 124751425Smccanne return 0; 124851425Smccanne 124951425Smccanne MGET(m, canwait, MT_DATA); 125051425Smccanne if (m == 0) 125151425Smccanne return 0; 125251425Smccanne if ((unsigned)size > (MLEN-8)) { 125351425Smccanne MCLGET(m); 125451425Smccanne if (m->m_len != MCLBYTES) { 125551425Smccanne m_freem(m); 125651425Smccanne return 0; 125751425Smccanne } 125851425Smccanne } 125951425Smccanne *mtod(m, struct mbuf **) = m; 126051425Smccanne return mtod(m, caddr_t) + 8; 126151425Smccanne } 126251425Smccanne #endif 126351425Smccanne #endif 1264