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*55289Smckusick * @(#)bpf.c 7.12 (Berkeley) 07/16/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 95*55289Smckusick bpf_movein(uio, linktype, mp, sockp, datlen) 9647584Smccanne register struct uio *uio; 97*55289Smckusick int linktype, *datlen; 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; 144*55289Smckusick *datlen = len - hlen; 14547584Smccanne if ((unsigned)len > MCLBYTES) 14648932Smccanne return (EIO); 14747584Smccanne 14847584Smccanne MGET(m, M_WAIT, MT_DATA); 14947584Smccanne if (m == 0) 15048932Smccanne return (ENOBUFS); 15147584Smccanne if (len > MLEN) { 15251425Smccanne #if BSD >= 199103 15348932Smccanne MCLGET(m, M_WAIT); 15448932Smccanne if ((m->m_flags & M_EXT) == 0) { 15551425Smccanne #else 15651425Smccanne MCLGET(m); 15753947Smccanne if (m->m_len != MCLBYTES) { 15851425Smccanne #endif 15953947Smccanne error = ENOBUFS; 16047584Smccanne goto bad; 16147584Smccanne } 16247584Smccanne } 16347584Smccanne m->m_len = len; 16447584Smccanne *mp = m; 16547584Smccanne /* 16647584Smccanne * Make room for link header. 16747584Smccanne */ 16853947Smccanne if (hlen != 0) { 16947584Smccanne m->m_len -= hlen; 17051425Smccanne #if BSD >= 199103 17148932Smccanne m->m_data += hlen; /* XXX */ 17251425Smccanne #else 17351425Smccanne m->m_off += hlen; 17451425Smccanne #endif 17553947Smccanne error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio); 17647584Smccanne if (error) 17747584Smccanne goto bad; 17847584Smccanne } 17953947Smccanne error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio); 18053947Smccanne if (!error) 18148932Smccanne return (0); 18247584Smccanne bad: 18347584Smccanne m_freem(m); 18448932Smccanne return (error); 18547584Smccanne } 18647584Smccanne 18747584Smccanne /* 18851425Smccanne * Attach file to the bpf interface, i.e. make d listen on bp. 18947584Smccanne * Must be called at splimp. 19047584Smccanne */ 19147584Smccanne static void 19247584Smccanne bpf_attachd(d, bp) 19347584Smccanne struct bpf_d *d; 19447584Smccanne struct bpf_if *bp; 19547584Smccanne { 19651425Smccanne /* 19751425Smccanne * Point d at bp, and add d to the interface's list of listeners. 19851425Smccanne * Finally, point the driver's bpf cookie at the interface so 19951425Smccanne * it will divert packets to bpf. 20051425Smccanne */ 20147584Smccanne d->bd_bif = bp; 20247584Smccanne d->bd_next = bp->bif_dlist; 20347584Smccanne bp->bif_dlist = d; 20447584Smccanne 20547584Smccanne *bp->bif_driverp = bp; 20647584Smccanne } 20747584Smccanne 20851425Smccanne /* 20951425Smccanne * Detach a file from its interface. 21051425Smccanne */ 21147584Smccanne static void 21247584Smccanne bpf_detachd(d) 21347584Smccanne struct bpf_d *d; 21447584Smccanne { 21547584Smccanne struct bpf_d **p; 21647584Smccanne struct bpf_if *bp; 21747584Smccanne 21847584Smccanne bp = d->bd_bif; 21947584Smccanne /* 22047584Smccanne * Check if this descriptor had requested promiscuous mode. 22147584Smccanne * If so, turn it off. 22247584Smccanne */ 22347584Smccanne if (d->bd_promisc) { 22447584Smccanne d->bd_promisc = 0; 22547584Smccanne if (ifpromisc(bp->bif_ifp, 0)) 22647584Smccanne /* 22747584Smccanne * Something is really wrong if we were able to put 22847584Smccanne * the driver into promiscuous mode, but can't 22947584Smccanne * take it out. 23047584Smccanne */ 23151425Smccanne panic("bpf: ifpromisc failed"); 23247584Smccanne } 23351425Smccanne /* Remove d from the interface's descriptor list. */ 23447584Smccanne p = &bp->bif_dlist; 23547584Smccanne while (*p != d) { 23647584Smccanne p = &(*p)->bd_next; 23747584Smccanne if (*p == 0) 23847584Smccanne panic("bpf_detachd: descriptor not in list"); 23947584Smccanne } 24047584Smccanne *p = (*p)->bd_next; 24147584Smccanne if (bp->bif_dlist == 0) 24247584Smccanne /* 24347584Smccanne * Let the driver know that there are no more listeners. 24447584Smccanne */ 24547584Smccanne *d->bd_bif->bif_driverp = 0; 24647584Smccanne d->bd_bif = 0; 24747584Smccanne } 24847584Smccanne 24947584Smccanne 25047584Smccanne /* 25153947Smccanne * Mark a descriptor free by making it point to itself. 25247584Smccanne * This is probably cheaper than marking with a constant since 25347584Smccanne * the address should be in a register anyway. 25447584Smccanne */ 25547584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next) 25647584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d)) 25747584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0) 25847584Smccanne 25947584Smccanne /* 26053947Smccanne * Open ethernet device. Returns ENXIO for illegal minor device number, 26153947Smccanne * EBUSY if file is open by another process. 26247584Smccanne */ 26347584Smccanne /* ARGSUSED */ 26447584Smccanne int 26547584Smccanne bpfopen(dev, flag) 26647584Smccanne dev_t dev; 26747584Smccanne int flag; 26847584Smccanne { 26947584Smccanne register struct bpf_d *d; 27053947Smccanne 27147584Smccanne if (minor(dev) >= NBPFILTER) 27248932Smccanne return (ENXIO); 27347584Smccanne /* 27447584Smccanne * Each minor can be opened by only one process. If the requested 27547584Smccanne * minor is in use, return EBUSY. 27647584Smccanne */ 27747584Smccanne d = &bpf_dtab[minor(dev)]; 27853947Smccanne if (!D_ISFREE(d)) 27948932Smccanne return (EBUSY); 28047584Smccanne 28153947Smccanne /* Mark "free" and do most initialization. */ 28253947Smccanne bzero((char *)d, sizeof(*d)); 28353947Smccanne d->bd_bufsize = bpf_bufsize; 28453947Smccanne 28548932Smccanne return (0); 28647584Smccanne } 28747584Smccanne 28847584Smccanne /* 28947584Smccanne * Close the descriptor by detaching it from its interface, 29047584Smccanne * deallocating its buffers, and marking it free. 29147584Smccanne */ 29247584Smccanne /* ARGSUSED */ 29353947Smccanne int 29447584Smccanne bpfclose(dev, flag) 29547584Smccanne dev_t dev; 29647584Smccanne int flag; 29747584Smccanne { 29847584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 29953947Smccanne register int s; 30047584Smccanne 30147584Smccanne s = splimp(); 30247584Smccanne if (d->bd_bif) 30347584Smccanne bpf_detachd(d); 30447584Smccanne splx(s); 30553947Smccanne bpf_freed(d); 30647584Smccanne 30753947Smccanne return (0); 30847584Smccanne } 30947584Smccanne 31053947Smccanne /* 31153947Smccanne * Support for SunOS, which does not have tsleep. 31253947Smccanne */ 31351425Smccanne #if BSD < 199103 31451425Smccanne static 31551425Smccanne bpf_timeout(arg) 31651425Smccanne caddr_t arg; 31751425Smccanne { 31851425Smccanne struct bpf_d *d = (struct bpf_d *)arg; 31951425Smccanne d->bd_timedout = 1; 32051425Smccanne wakeup(arg); 32151425Smccanne } 32251425Smccanne 32353947Smccanne #define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan) 32453947Smccanne 32553947Smccanne int 32653947Smccanne bpf_sleep(d) 32753947Smccanne register struct bpf_d *d; 32851425Smccanne { 32953947Smccanne register int rto = d->bd_rtout; 33053947Smccanne register int st; 33151425Smccanne 33253947Smccanne if (rto != 0) { 33351425Smccanne d->bd_timedout = 0; 33453947Smccanne timeout(bpf_timeout, (caddr_t)d, rto); 33551425Smccanne } 33653947Smccanne st = sleep((caddr_t)d, PRINET|PCATCH); 33753947Smccanne if (rto != 0) { 33853947Smccanne if (d->bd_timedout == 0) 33953947Smccanne untimeout(bpf_timeout, (caddr_t)d); 34053947Smccanne else if (st == 0) 34151425Smccanne return EWOULDBLOCK; 34251425Smccanne } 34353947Smccanne return (st != 0) ? EINTR : 0; 34451425Smccanne } 34553947Smccanne #else 34653947Smccanne #define BPF_SLEEP tsleep 34751425Smccanne #endif 34851425Smccanne 34947584Smccanne /* 35048932Smccanne * Rotate the packet buffers in descriptor d. Move the store buffer 35153947Smccanne * into the hold slot, and the free buffer into the store slot. 35248932Smccanne * Zero the length of the new store buffer. 35348932Smccanne */ 35448932Smccanne #define ROTATE_BUFFERS(d) \ 35548932Smccanne (d)->bd_hbuf = (d)->bd_sbuf; \ 35648932Smccanne (d)->bd_hlen = (d)->bd_slen; \ 35748932Smccanne (d)->bd_sbuf = (d)->bd_fbuf; \ 35848932Smccanne (d)->bd_slen = 0; \ 35953947Smccanne (d)->bd_fbuf = 0; 36048932Smccanne /* 36147584Smccanne * bpfread - read next chunk of packets from buffers 36247584Smccanne */ 36347584Smccanne int 36447584Smccanne bpfread(dev, uio) 36547584Smccanne dev_t dev; 36647584Smccanne register struct uio *uio; 36747584Smccanne { 36847584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 36947584Smccanne int error; 37047584Smccanne int s; 37147584Smccanne 37247584Smccanne /* 37353947Smccanne * Restrict application to use a buffer the same size as 37447584Smccanne * as kernel buffers. 37547584Smccanne */ 37648932Smccanne if (uio->uio_resid != d->bd_bufsize) 37749202Smccanne return (EINVAL); 37847584Smccanne 37947584Smccanne s = splimp(); 38047584Smccanne /* 38153947Smccanne * If the hold buffer is empty, then do a timed sleep, which 38253947Smccanne * ends when the timeout expires or when enough packets 38353947Smccanne * have arrived to fill the store buffer. 38447584Smccanne */ 38547584Smccanne while (d->bd_hbuf == 0) { 38648932Smccanne if (d->bd_immediate && d->bd_slen != 0) { 38747584Smccanne /* 38847584Smccanne * A packet(s) either arrived since the previous 38947584Smccanne * read or arrived while we were asleep. 39047584Smccanne * Rotate the buffers and return what's here. 39147584Smccanne */ 39248932Smccanne ROTATE_BUFFERS(d); 39347584Smccanne break; 39447584Smccanne } 39553947Smccanne error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf", 39653947Smccanne d->bd_rtout); 39748932Smccanne if (error == EINTR || error == ERESTART) { 39848932Smccanne splx(s); 39948932Smccanne return (error); 40047584Smccanne } 40148932Smccanne if (error == EWOULDBLOCK) { 40247584Smccanne /* 40347584Smccanne * On a timeout, return what's in the buffer, 40448932Smccanne * which may be nothing. If there is something 40548932Smccanne * in the store buffer, we can rotate the buffers. 40647584Smccanne */ 40747584Smccanne if (d->bd_hbuf) 40847584Smccanne /* 40953947Smccanne * We filled up the buffer in between 41047584Smccanne * getting the timeout and arriving 41147584Smccanne * here, so we don't need to rotate. 41247584Smccanne */ 41347584Smccanne break; 41447584Smccanne 41548932Smccanne if (d->bd_slen == 0) { 41647584Smccanne splx(s); 41748932Smccanne return (0); 41847584Smccanne } 41948932Smccanne ROTATE_BUFFERS(d); 42047584Smccanne break; 42147584Smccanne } 42247584Smccanne } 42347584Smccanne /* 42447584Smccanne * At this point, we know we have something in the hold slot. 42547584Smccanne */ 42647584Smccanne splx(s); 42753947Smccanne 42853947Smccanne /* 42947584Smccanne * Move data from hold buffer into user space. 43047584Smccanne * We know the entire buffer is transferred since 43148932Smccanne * we checked above that the read buffer is bpf_bufsize bytes. 43247584Smccanne */ 43353947Smccanne error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio); 43453947Smccanne 43547584Smccanne s = splimp(); 43648932Smccanne d->bd_fbuf = d->bd_hbuf; 43748932Smccanne d->bd_hbuf = 0; 43853947Smccanne d->bd_hlen = 0; 43947584Smccanne splx(s); 44053947Smccanne 44148932Smccanne return (error); 44247584Smccanne } 44347584Smccanne 44447584Smccanne 44547584Smccanne /* 44653947Smccanne * If there are processes sleeping on this descriptor, wake them up. 44747584Smccanne */ 44847584Smccanne static inline void 44947584Smccanne bpf_wakeup(d) 45047584Smccanne register struct bpf_d *d; 45147584Smccanne { 45248932Smccanne wakeup((caddr_t)d); 45353947Smccanne #if BSD >= 199103 45453947Smccanne selwakeup(&d->bd_sel); 45553947Smccanne /* XXX */ 45653947Smccanne d->bd_sel.si_pid = 0; 45753947Smccanne #else 45853947Smccanne if (d->bd_selproc) { 45953947Smccanne selwakeup(d->bd_selproc, (int)d->bd_selcoll); 46053947Smccanne d->bd_selcoll = 0; 46153947Smccanne d->bd_selproc = 0; 46253947Smccanne } 46353947Smccanne #endif 46447584Smccanne } 46547584Smccanne 46647584Smccanne int 46747584Smccanne bpfwrite(dev, uio) 46847584Smccanne dev_t dev; 46947584Smccanne struct uio *uio; 47047584Smccanne { 47147584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 47247584Smccanne struct ifnet *ifp; 47347584Smccanne struct mbuf *m; 47447584Smccanne int error, s; 47547584Smccanne static struct sockaddr dst; 476*55289Smckusick int datlen; 47747584Smccanne 47847584Smccanne if (d->bd_bif == 0) 47948932Smccanne return (ENXIO); 48047584Smccanne 48147584Smccanne ifp = d->bd_bif->bif_ifp; 48247584Smccanne 48347584Smccanne if (uio->uio_resid == 0) 48448932Smccanne return (0); 48547584Smccanne 486*55289Smckusick error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen); 48747584Smccanne if (error) 48848932Smccanne return (error); 48947584Smccanne 490*55289Smckusick if (datlen > ifp->if_mtu) 491*55289Smckusick return (EMSGSIZE); 492*55289Smckusick 49347584Smccanne s = splnet(); 49451425Smccanne #if BSD >= 199103 49553947Smccanne error = (*ifp->if_output)(ifp, m, &dst, (struct rtentry *)0); 49651425Smccanne #else 49747584Smccanne error = (*ifp->if_output)(ifp, m, &dst); 49851425Smccanne #endif 49947584Smccanne splx(s); 50047584Smccanne /* 50153947Smccanne * The driver frees the mbuf. 50247584Smccanne */ 50348932Smccanne return (error); 50447584Smccanne } 50547584Smccanne 50647584Smccanne /* 50753947Smccanne * Reset a descriptor by flushing its packet buffer and clearing the 50853947Smccanne * receive and drop counts. Should be called at splimp. 50947584Smccanne */ 51047584Smccanne static void 51147584Smccanne reset_d(d) 51247584Smccanne struct bpf_d *d; 51347584Smccanne { 51447584Smccanne if (d->bd_hbuf) { 51547584Smccanne /* Free the hold buffer. */ 51647584Smccanne d->bd_fbuf = d->bd_hbuf; 51747584Smccanne d->bd_hbuf = 0; 51847584Smccanne } 51948932Smccanne d->bd_slen = 0; 52053947Smccanne d->bd_hlen = 0; 52147584Smccanne d->bd_rcount = 0; 52247584Smccanne d->bd_dcount = 0; 52347584Smccanne } 52447584Smccanne 52547584Smccanne /* 52647584Smccanne * FIONREAD Check for read packet available. 52747584Smccanne * SIOCGIFADDR Get interface address - convenient hook to driver. 52847584Smccanne * BIOCGBLEN Get buffer len [for read()]. 52947584Smccanne * BIOCSETF Set ethernet read filter. 53047584Smccanne * BIOCFLUSH Flush read packet buffer. 53147584Smccanne * BIOCPROMISC Put interface into promiscuous mode. 53249202Smccanne * BIOCGDLT Get link layer type. 53347584Smccanne * BIOCGETIF Get interface name. 53447584Smccanne * BIOCSETIF Set interface. 53547584Smccanne * BIOCSRTIMEOUT Set read timeout. 53647584Smccanne * BIOCGRTIMEOUT Get read timeout. 53747584Smccanne * BIOCGSTATS Get packet stats. 53847584Smccanne * BIOCIMMEDIATE Set immediate mode. 53953947Smccanne * BIOCVERSION Get filter language version. 54047584Smccanne */ 54147584Smccanne /* ARGSUSED */ 54247584Smccanne int 54347584Smccanne bpfioctl(dev, cmd, addr, flag) 54447584Smccanne dev_t dev; 54547584Smccanne int cmd; 54647584Smccanne caddr_t addr; 54747584Smccanne int flag; 54847584Smccanne { 54947584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 55047584Smccanne int s, error = 0; 55147584Smccanne 55247584Smccanne switch (cmd) { 55347584Smccanne 55447584Smccanne default: 55547584Smccanne error = EINVAL; 55647584Smccanne break; 55747584Smccanne 55847584Smccanne /* 55947584Smccanne * Check for read packet available. 56047584Smccanne */ 56147584Smccanne case FIONREAD: 56247584Smccanne { 56347584Smccanne int n; 56453947Smccanne 56547584Smccanne s = splimp(); 56648932Smccanne n = d->bd_slen; 56753947Smccanne if (d->bd_hbuf) 56848932Smccanne n += d->bd_hlen; 56947584Smccanne splx(s); 57047584Smccanne 57147584Smccanne *(int *)addr = n; 57247584Smccanne break; 57347584Smccanne } 57447584Smccanne 57547584Smccanne case SIOCGIFADDR: 57647584Smccanne { 57747584Smccanne struct ifnet *ifp; 57847584Smccanne 57947584Smccanne if (d->bd_bif == 0) 58047584Smccanne error = EINVAL; 58147584Smccanne else { 58247584Smccanne ifp = d->bd_bif->bif_ifp; 58353947Smccanne error = (*ifp->if_ioctl)(ifp, cmd, addr); 58447584Smccanne } 58547584Smccanne break; 58647584Smccanne } 58747584Smccanne 58847584Smccanne /* 58947584Smccanne * Get buffer len [for read()]. 59047584Smccanne */ 59147584Smccanne case BIOCGBLEN: 59248932Smccanne *(u_int *)addr = d->bd_bufsize; 59347584Smccanne break; 59447584Smccanne 59547584Smccanne /* 59653947Smccanne * Set buffer length. 59753947Smccanne */ 59853947Smccanne case BIOCSBLEN: 59953947Smccanne #if BSD < 199103 60053947Smccanne error = EINVAL; 60153947Smccanne #else 60253947Smccanne if (d->bd_bif != 0) 60353947Smccanne error = EINVAL; 60453947Smccanne else { 60553947Smccanne register u_int size = *(u_int *)addr; 60653947Smccanne 60753947Smccanne if (size > BPF_MAXBUFSIZE) 60853947Smccanne *(u_int *)addr = size = BPF_MAXBUFSIZE; 60953947Smccanne else if (size < BPF_MINBUFSIZE) 61053947Smccanne *(u_int *)addr = size = BPF_MINBUFSIZE; 61153947Smccanne d->bd_bufsize = size; 61253947Smccanne } 61353947Smccanne #endif 61453947Smccanne break; 61553947Smccanne 61653947Smccanne /* 61751425Smccanne * Set link layer read filter. 61847584Smccanne */ 61953947Smccanne case BIOCSETF: 62047584Smccanne error = bpf_setf(d, (struct bpf_program *)addr); 62147584Smccanne break; 62247584Smccanne 62347584Smccanne /* 62447584Smccanne * Flush read packet buffer. 62547584Smccanne */ 62647584Smccanne case BIOCFLUSH: 62747584Smccanne s = splimp(); 62847584Smccanne reset_d(d); 62947584Smccanne splx(s); 63047584Smccanne break; 63147584Smccanne 63247584Smccanne /* 63347584Smccanne * Put interface into promiscuous mode. 63447584Smccanne */ 63547584Smccanne case BIOCPROMISC: 63647584Smccanne if (d->bd_bif == 0) { 63747584Smccanne /* 63847584Smccanne * No interface attached yet. 63947584Smccanne */ 64047584Smccanne error = EINVAL; 64147584Smccanne break; 64247584Smccanne } 64347584Smccanne s = splimp(); 64447584Smccanne if (d->bd_promisc == 0) { 64547584Smccanne error = ifpromisc(d->bd_bif->bif_ifp, 1); 64651425Smccanne if (error == 0) 64751425Smccanne d->bd_promisc = 1; 64847584Smccanne } 64947584Smccanne splx(s); 65047584Smccanne break; 65147584Smccanne 65247584Smccanne /* 65347584Smccanne * Get device parameters. 65447584Smccanne */ 65549202Smccanne case BIOCGDLT: 65647584Smccanne if (d->bd_bif == 0) 65747584Smccanne error = EINVAL; 65847584Smccanne else 65949202Smccanne *(u_int *)addr = d->bd_bif->bif_dlt; 66047584Smccanne break; 66147584Smccanne 66247584Smccanne /* 66347584Smccanne * Set interface name. 66447584Smccanne */ 66547584Smccanne case BIOCGETIF: 66647584Smccanne if (d->bd_bif == 0) 66747584Smccanne error = EINVAL; 66847584Smccanne else 66947584Smccanne bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr); 67047584Smccanne break; 67147584Smccanne 67247584Smccanne /* 67347584Smccanne * Set interface. 67447584Smccanne */ 67547584Smccanne case BIOCSETIF: 67647584Smccanne error = bpf_setif(d, (struct ifreq *)addr); 67747584Smccanne break; 67847584Smccanne 67947584Smccanne /* 68047584Smccanne * Set read timeout. 68147584Smccanne */ 68253947Smccanne case BIOCSRTIMEOUT: 68347584Smccanne { 68447584Smccanne struct timeval *tv = (struct timeval *)addr; 68547584Smccanne u_long msec; 68647584Smccanne 68747584Smccanne /* Compute number of milliseconds. */ 68847584Smccanne msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; 68947584Smccanne /* Scale milliseconds to ticks. Assume hard 69047584Smccanne clock has millisecond or greater resolution 69147584Smccanne (i.e. tick >= 1000). For 10ms hardclock, 69247584Smccanne tick/1000 = 10, so rtout<-msec/10. */ 69347584Smccanne d->bd_rtout = msec / (tick / 1000); 69447584Smccanne break; 69547584Smccanne } 69647584Smccanne 69747584Smccanne /* 69847584Smccanne * Get read timeout. 69947584Smccanne */ 70053947Smccanne case BIOCGRTIMEOUT: 70147584Smccanne { 70247584Smccanne struct timeval *tv = (struct timeval *)addr; 70347584Smccanne u_long msec = d->bd_rtout; 70447584Smccanne 70547584Smccanne msec *= tick / 1000; 70647584Smccanne tv->tv_sec = msec / 1000; 70747584Smccanne tv->tv_usec = msec % 1000; 70847584Smccanne break; 70947584Smccanne } 71047584Smccanne 71147584Smccanne /* 71247584Smccanne * Get packet stats. 71347584Smccanne */ 71447584Smccanne case BIOCGSTATS: 71547584Smccanne { 71647584Smccanne struct bpf_stat *bs = (struct bpf_stat *)addr; 71747584Smccanne 71847584Smccanne bs->bs_recv = d->bd_rcount; 71947584Smccanne bs->bs_drop = d->bd_dcount; 72047584Smccanne break; 72147584Smccanne } 72247584Smccanne 72347584Smccanne /* 72447584Smccanne * Set immediate mode. 72547584Smccanne */ 72647584Smccanne case BIOCIMMEDIATE: 72747584Smccanne d->bd_immediate = *(u_int *)addr; 72847584Smccanne break; 72953947Smccanne 73053947Smccanne case BIOCVERSION: 73153947Smccanne { 73253947Smccanne struct bpf_version *bv = (struct bpf_version *)addr; 73353947Smccanne 73453947Smccanne bv->bv_major = BPF_MAJOR_VERSION; 73553947Smccanne bv->bv_minor = BPF_MINOR_VERSION; 73653947Smccanne break; 73753947Smccanne } 73847584Smccanne } 73948932Smccanne return (error); 74047584Smccanne } 74147584Smccanne 74253947Smccanne /* 74351425Smccanne * Set d's packet filter program to fp. If this file already has a filter, 74448932Smccanne * free it and replace it. Returns EINVAL for bogus requests. 74547584Smccanne */ 74647584Smccanne int 74747584Smccanne bpf_setf(d, fp) 74847584Smccanne struct bpf_d *d; 74947584Smccanne struct bpf_program *fp; 75047584Smccanne { 75148932Smccanne struct bpf_insn *fcode, *old; 75247584Smccanne u_int flen, size; 75347584Smccanne int s; 75447584Smccanne 75548932Smccanne old = d->bd_filter; 75647584Smccanne if (fp->bf_insns == 0) { 75747584Smccanne if (fp->bf_len != 0) 75848932Smccanne return (EINVAL); 75948932Smccanne s = splimp(); 76048967Smccanne d->bd_filter = 0; 76147584Smccanne reset_d(d); 76247584Smccanne splx(s); 76348967Smccanne if (old != 0) 76448932Smccanne free((caddr_t)old, M_DEVBUF); 76548932Smccanne return (0); 76647584Smccanne } 76747584Smccanne flen = fp->bf_len; 76848932Smccanne if (flen > BPF_MAXINSNS) 76948932Smccanne return (EINVAL); 77048932Smccanne 77147584Smccanne size = flen * sizeof(*fp->bf_insns); 77248932Smccanne fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK); 77350417Smccanne if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 && 77450417Smccanne bpf_validate(fcode, (int)flen)) { 77548967Smccanne s = splimp(); 77648932Smccanne d->bd_filter = fcode; 77747584Smccanne reset_d(d); 77847584Smccanne splx(s); 77948967Smccanne if (old != 0) 78048932Smccanne free((caddr_t)old, M_DEVBUF); 78147584Smccanne 78248932Smccanne return (0); 78347584Smccanne } 78448932Smccanne free((caddr_t)fcode, M_DEVBUF); 78548932Smccanne return (EINVAL); 78647584Smccanne } 78747584Smccanne 78847584Smccanne /* 78953947Smccanne * Detach a file from its current interface (if attached at all) and attach 79053947Smccanne * to the interface indicated by the name stored in ifr. 79151425Smccanne * Return an errno or 0. 79247584Smccanne */ 79347584Smccanne static int 79447584Smccanne bpf_setif(d, ifr) 79547584Smccanne struct bpf_d *d; 79647584Smccanne struct ifreq *ifr; 79747584Smccanne { 79847584Smccanne struct bpf_if *bp; 79947584Smccanne char *cp; 80053947Smccanne int unit, s, error; 80147584Smccanne 80247584Smccanne /* 80347584Smccanne * Separate string into name part and unit number. Put a null 80453947Smccanne * byte at the end of the name part, and compute the number. 80547584Smccanne * If the a unit number is unspecified, the default is 0, 80648932Smccanne * as initialized above. XXX This should be common code. 80747584Smccanne */ 80847584Smccanne unit = 0; 80947584Smccanne cp = ifr->ifr_name; 81047584Smccanne cp[sizeof(ifr->ifr_name) - 1] = '\0'; 81147584Smccanne while (*cp++) { 81247584Smccanne if (*cp >= '0' && *cp <= '9') { 81347584Smccanne unit = *cp - '0'; 81447584Smccanne *cp++ = '\0'; 81547584Smccanne while (*cp) 81647584Smccanne unit = 10 * unit + *cp++ - '0'; 81747584Smccanne break; 81847584Smccanne } 81947584Smccanne } 82047584Smccanne /* 82147584Smccanne * Look through attached interfaces for the named one. 82247584Smccanne */ 82349202Smccanne for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) { 82447584Smccanne struct ifnet *ifp = bp->bif_ifp; 82547584Smccanne 82653947Smccanne if (ifp == 0 || unit != ifp->if_unit 82747584Smccanne || strcmp(ifp->if_name, ifr->ifr_name) != 0) 82847584Smccanne continue; 82947584Smccanne /* 83053947Smccanne * We found the requested interface. 83147584Smccanne * If it's not up, return an error. 83253947Smccanne * Allocate the packet buffers if we need to. 83353947Smccanne * If we're already attached to requested interface, 83453947Smccanne * just flush the buffer. 83547584Smccanne */ 83647584Smccanne if ((ifp->if_flags & IFF_UP) == 0) 83748932Smccanne return (ENETDOWN); 83853947Smccanne 83953947Smccanne if (d->bd_sbuf == 0) { 84053947Smccanne error = bpf_allocbufs(d); 84153947Smccanne if (error != 0) 84253947Smccanne return (error); 84353947Smccanne } 84447584Smccanne s = splimp(); 84547584Smccanne if (bp != d->bd_bif) { 84647584Smccanne if (d->bd_bif) 84753947Smccanne /* 84848932Smccanne * Detach if attached to something else. 84947584Smccanne */ 85047584Smccanne bpf_detachd(d); 85147584Smccanne 85247584Smccanne bpf_attachd(d, bp); 85347584Smccanne } 85447584Smccanne reset_d(d); 85547584Smccanne splx(s); 85648932Smccanne return (0); 85747584Smccanne } 85847584Smccanne /* Not found. */ 85948932Smccanne return (ENXIO); 86047584Smccanne } 86147584Smccanne 86247584Smccanne /* 86351425Smccanne * Convert an interface name plus unit number of an ifp to a single 86451425Smccanne * name which is returned in the ifr. 86547584Smccanne */ 86647584Smccanne static void 86747584Smccanne bpf_ifname(ifp, ifr) 86847584Smccanne struct ifnet *ifp; 86947584Smccanne struct ifreq *ifr; 87047584Smccanne { 87147584Smccanne char *s = ifp->if_name; 87247584Smccanne char *d = ifr->ifr_name; 87347584Smccanne 87447584Smccanne while (*d++ = *s++) 87553947Smccanne continue; 87648932Smccanne /* XXX Assume that unit number is less than 10. */ 87747584Smccanne *d++ = ifp->if_unit + '0'; 87847584Smccanne *d = '\0'; 87947584Smccanne } 88047584Smccanne 88147584Smccanne /* 88251425Smccanne * The new select interface passes down the proc pointer; the old select 88351425Smccanne * stubs had to grab it out of the user struct. This glue allows either case. 88451425Smccanne */ 88551425Smccanne #if BSD >= 199103 88651425Smccanne #define bpf_select bpfselect 88751425Smccanne #else 88851425Smccanne int 88951425Smccanne bpfselect(dev, rw) 89051425Smccanne register dev_t dev; 89151425Smccanne int rw; 89251425Smccanne { 89353947Smccanne return (bpf_select(dev, rw, u.u_procp)); 89451425Smccanne } 89551425Smccanne #endif 89651425Smccanne 89751425Smccanne /* 89847584Smccanne * Support for select() system call 89947584Smccanne * Inspired by the code in tty.c for the same purpose. 90047584Smccanne * 90153947Smccanne * Return true iff the specific operation will not block indefinitely. 90253947Smccanne * Otherwise, return false but make a note that a selwakeup() must be done. 90347584Smccanne */ 90447584Smccanne int 90551425Smccanne bpf_select(dev, rw, p) 90647584Smccanne register dev_t dev; 90747584Smccanne int rw; 90848932Smccanne struct proc *p; 90947584Smccanne { 91047584Smccanne register struct bpf_d *d; 91147584Smccanne register int s; 91253947Smccanne 91347584Smccanne if (rw != FREAD) 91448932Smccanne return (0); 91547584Smccanne /* 91647584Smccanne * An imitation of the FIONREAD ioctl code. 91747584Smccanne */ 91847584Smccanne d = &bpf_dtab[minor(dev)]; 91953947Smccanne 92047584Smccanne s = splimp(); 92149723Smccanne if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0)) { 92247584Smccanne /* 92347584Smccanne * There is data waiting. 92447584Smccanne */ 92547584Smccanne splx(s); 92648932Smccanne return (1); 92747584Smccanne } 92853947Smccanne #if BSD >= 199103 92953947Smccanne selrecord(p, &d->bd_sel); 93053947Smccanne #else 93147584Smccanne /* 93247584Smccanne * No data ready. If there's already a select() waiting on this 93353947Smccanne * minor device then this is a collision. This shouldn't happen 93447584Smccanne * because minors really should not be shared, but if a process 93547584Smccanne * forks while one of these is open, it is possible that both 93647584Smccanne * processes could select on the same descriptor. 93747584Smccanne */ 93853947Smccanne if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait) 93953947Smccanne d->bd_selcoll = 1; 94053947Smccanne else 94153947Smccanne d->bd_selproc = p; 94253947Smccanne #endif 94353947Smccanne splx(s); 94448932Smccanne return (0); 94547584Smccanne } 94647584Smccanne 94747584Smccanne /* 94853947Smccanne * Incoming linkage from device drivers. Process the packet pkt, of length 94953947Smccanne * pktlen, which is stored in a contiguous buffer. The packet is parsed 95053947Smccanne * by each process' filter, and if accepted, stashed into the corresponding 95153947Smccanne * buffer. 95247584Smccanne */ 95347584Smccanne void 95448932Smccanne bpf_tap(arg, pkt, pktlen) 95547584Smccanne caddr_t arg; 95648932Smccanne register u_char *pkt; 95748932Smccanne register u_int pktlen; 95847584Smccanne { 95947584Smccanne struct bpf_if *bp; 96047584Smccanne register struct bpf_d *d; 96147584Smccanne register u_int slen; 96247584Smccanne /* 96347584Smccanne * Note that the ipl does not have to be raised at this point. 96447584Smccanne * The only problem that could arise here is that if two different 96547584Smccanne * interfaces shared any data. This is not the case. 96647584Smccanne */ 96747584Smccanne bp = (struct bpf_if *)arg; 96847584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 96947584Smccanne ++d->bd_rcount; 97049202Smccanne slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen); 97147584Smccanne if (slen != 0) 97249202Smccanne catchpacket(d, pkt, pktlen, slen, bcopy); 97347584Smccanne } 97447584Smccanne } 97547584Smccanne 97647584Smccanne /* 97747584Smccanne * Copy data from an mbuf chain into a buffer. This code is derived 97847584Smccanne * from m_copydata in sys/uipc_mbuf.c. 97947584Smccanne */ 98047584Smccanne static void 98149202Smccanne bpf_mcopy(src, dst, len) 98247584Smccanne u_char *src; 98347584Smccanne u_char *dst; 98447584Smccanne register int len; 98547584Smccanne { 98647584Smccanne register struct mbuf *m = (struct mbuf *)src; 98747584Smccanne register unsigned count; 98847584Smccanne 98947584Smccanne while (len > 0) { 99047584Smccanne if (m == 0) 99149202Smccanne panic("bpf_mcopy"); 99255065Spendry count = min(m->m_len, len); 99349202Smccanne bcopy(mtod(m, caddr_t), (caddr_t)dst, count); 99449202Smccanne m = m->m_next; 99549202Smccanne dst += count; 99647584Smccanne len -= count; 99747584Smccanne } 99847584Smccanne } 99947584Smccanne 100047584Smccanne /* 100153947Smccanne * Incoming linkage from device drivers, when packet is in an mbuf chain. 100247584Smccanne */ 100347584Smccanne void 100449202Smccanne bpf_mtap(arg, m) 100547584Smccanne caddr_t arg; 100649202Smccanne struct mbuf *m; 100747584Smccanne { 100847584Smccanne struct bpf_if *bp = (struct bpf_if *)arg; 100947584Smccanne struct bpf_d *d; 101049202Smccanne u_int pktlen, slen; 101149202Smccanne struct mbuf *m0; 101247584Smccanne 101348932Smccanne pktlen = 0; 101451425Smccanne for (m0 = m; m0 != 0; m0 = m0->m_next) 101549202Smccanne pktlen += m0->m_len; 101649723Smccanne 101747584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 101847584Smccanne ++d->bd_rcount; 101949202Smccanne slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0); 102047584Smccanne if (slen != 0) 102149202Smccanne catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy); 102247584Smccanne } 102347584Smccanne } 102447584Smccanne 102547584Smccanne /* 102649202Smccanne * Move the packet data from interface memory (pkt) into the 102747584Smccanne * store buffer. Return 1 if it's time to wakeup a listener (buffer full), 102853947Smccanne * otherwise 0. "copy" is the routine called to do the actual data 102951425Smccanne * transfer. bcopy is passed in to copy contiguous chunks, while 103051425Smccanne * bpf_mcopy is passed in to copy mbuf chains. In the latter case, 103151425Smccanne * pkt is really an mbuf. 103247584Smccanne */ 103347584Smccanne static void 103448932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn) 103548932Smccanne register struct bpf_d *d; 103648932Smccanne register u_char *pkt; 103748932Smccanne register u_int pktlen, snaplen; 103848932Smccanne register void (*cpfn)(); 103947584Smccanne { 104048932Smccanne register struct bpf_hdr *hp; 104148932Smccanne register int totlen, curlen; 104248932Smccanne register int hdrlen = d->bd_bif->bif_hdrlen; 104347584Smccanne /* 104447584Smccanne * Figure out how many bytes to move. If the packet is 104547584Smccanne * greater or equal to the snapshot length, transfer that 104647584Smccanne * much. Otherwise, transfer the whole packet (unless 104748932Smccanne * we hit the buffer size limit). 104847584Smccanne */ 104955065Spendry totlen = hdrlen + min(snaplen, pktlen); 105050082Smccanne if (totlen > d->bd_bufsize) 105150082Smccanne totlen = d->bd_bufsize; 105247584Smccanne 105347584Smccanne /* 105447584Smccanne * Round up the end of the previous packet to the next longword. 105547584Smccanne */ 105648932Smccanne curlen = BPF_WORDALIGN(d->bd_slen); 105748932Smccanne if (curlen + totlen > d->bd_bufsize) { 105847584Smccanne /* 105947584Smccanne * This packet will overflow the storage buffer. 106048932Smccanne * Rotate the buffers if we can, then wakeup any 106148932Smccanne * pending reads. 106247584Smccanne */ 106347584Smccanne if (d->bd_fbuf == 0) { 106453947Smccanne /* 106553947Smccanne * We haven't completed the previous read yet, 106648932Smccanne * so drop the packet. 106747584Smccanne */ 106847584Smccanne ++d->bd_dcount; 106947584Smccanne return; 107047584Smccanne } 107148932Smccanne ROTATE_BUFFERS(d); 107247584Smccanne bpf_wakeup(d); 107348932Smccanne curlen = 0; 107447584Smccanne } 107553947Smccanne else if (d->bd_immediate) 107647584Smccanne /* 107747584Smccanne * Immediate mode is set. A packet arrived so any 107847584Smccanne * reads should be woken up. 107947584Smccanne */ 108047584Smccanne bpf_wakeup(d); 108148932Smccanne 108247584Smccanne /* 108347584Smccanne * Append the bpf header. 108447584Smccanne */ 108548932Smccanne hp = (struct bpf_hdr *)(d->bd_sbuf + curlen); 108651425Smccanne #if BSD >= 199103 108747584Smccanne microtime(&hp->bh_tstamp); 108853947Smccanne #elif defined(sun) 108953947Smccanne uniqtime(&hp->bh_tstamp); 109047584Smccanne #else 109147584Smccanne hp->bh_tstamp = time; 109247584Smccanne #endif 109348932Smccanne hp->bh_datalen = pktlen; 109447584Smccanne hp->bh_hdrlen = hdrlen; 109547584Smccanne /* 109648932Smccanne * Copy the packet data into the store buffer and update its length. 109747584Smccanne */ 109848932Smccanne (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen)); 109948932Smccanne d->bd_slen = curlen + totlen; 110047584Smccanne } 110147584Smccanne 110253947Smccanne /* 110347584Smccanne * Initialize all nonzero fields of a descriptor. 110447584Smccanne */ 110547584Smccanne static int 110653947Smccanne bpf_allocbufs(d) 110747584Smccanne register struct bpf_d *d; 110847584Smccanne { 110948932Smccanne d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 111048932Smccanne if (d->bd_fbuf == 0) 111148932Smccanne return (ENOBUFS); 111247584Smccanne 111348932Smccanne d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 111448932Smccanne if (d->bd_sbuf == 0) { 111548932Smccanne free(d->bd_fbuf, M_DEVBUF); 111648932Smccanne return (ENOBUFS); 111747584Smccanne } 111848932Smccanne d->bd_slen = 0; 111948932Smccanne d->bd_hlen = 0; 112048932Smccanne return (0); 112147584Smccanne } 112247584Smccanne 112347584Smccanne /* 112451425Smccanne * Free buffers currently in use by a descriptor. 112551425Smccanne * Called on close. 112647584Smccanne */ 112753947Smccanne static void 112851425Smccanne bpf_freed(d) 112951425Smccanne register struct bpf_d *d; 113051425Smccanne { 113151425Smccanne /* 113251425Smccanne * We don't need to lock out interrupts since this descriptor has 113353947Smccanne * been detached from its interface and it yet hasn't been marked 113451425Smccanne * free. 113551425Smccanne */ 113653947Smccanne if (d->bd_sbuf != 0) { 113753947Smccanne free(d->bd_sbuf, M_DEVBUF); 113853947Smccanne if (d->bd_hbuf != 0) 113953947Smccanne free(d->bd_hbuf, M_DEVBUF); 114053947Smccanne if (d->bd_fbuf != 0) 114153947Smccanne free(d->bd_fbuf, M_DEVBUF); 114253947Smccanne } 114351425Smccanne if (d->bd_filter) 114451425Smccanne free((caddr_t)d->bd_filter, M_DEVBUF); 114553947Smccanne 114651425Smccanne D_MARKFREE(d); 114751425Smccanne } 114851425Smccanne 114951425Smccanne /* 115051425Smccanne * Attach an interface to bpf. driverp is a pointer to a (struct bpf_if *) 115151425Smccanne * in the driver's softc; dlt is the link layer type; hdrlen is the fixed 115251425Smccanne * size of the link header (variable length headers not yet supported). 115351425Smccanne */ 115447584Smccanne void 115549202Smccanne bpfattach(driverp, ifp, dlt, hdrlen) 115647584Smccanne caddr_t *driverp; 115747584Smccanne struct ifnet *ifp; 115849202Smccanne u_int dlt, hdrlen; 115947584Smccanne { 116047584Smccanne struct bpf_if *bp; 116147584Smccanne int i; 116251425Smccanne #if BSD < 199103 116351425Smccanne static struct bpf_if bpf_ifs[NBPFILTER]; 116451425Smccanne static int bpfifno; 116547584Smccanne 116651425Smccanne bp = (bpfifno < NBPFILTER) ? &bpf_ifs[bpfifno++] : 0; 116751425Smccanne #else 116849202Smccanne bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT); 116951425Smccanne #endif 117049202Smccanne if (bp == 0) 117149202Smccanne panic("bpfattach"); 117247584Smccanne 117347584Smccanne bp->bif_dlist = 0; 117447584Smccanne bp->bif_driverp = (struct bpf_if **)driverp; 117547584Smccanne bp->bif_ifp = ifp; 117649202Smccanne bp->bif_dlt = dlt; 117747584Smccanne 117849202Smccanne bp->bif_next = bpf_iflist; 117949202Smccanne bpf_iflist = bp; 118049202Smccanne 118148932Smccanne *bp->bif_driverp = 0; 118248932Smccanne 118347584Smccanne /* 118447584Smccanne * Compute the length of the bpf header. This is not necessarily 118553947Smccanne * equal to SIZEOF_BPF_HDR because we want to insert spacing such 118653947Smccanne * that the network layer header begins on a longword boundary (for 118747584Smccanne * performance reasons and to alleviate alignment restrictions). 118847584Smccanne */ 118949202Smccanne bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen; 119047584Smccanne 119147584Smccanne /* 119247584Smccanne * Mark all the descriptors free if this hasn't been done. 119347584Smccanne */ 119447584Smccanne if (!D_ISFREE(&bpf_dtab[0])) 119547584Smccanne for (i = 0; i < NBPFILTER; ++i) 119647584Smccanne D_MARKFREE(&bpf_dtab[i]); 119747584Smccanne 119847584Smccanne printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit); 119947584Smccanne } 120047584Smccanne 120151425Smccanne #if BSD >= 199103 120248967Smccanne /* XXX This routine belongs in net/if.c. */ 120348932Smccanne /* 120453947Smccanne * Set/clear promiscuous mode on interface ifp based on the truth value 120548932Smccanne * of pswitch. The calls are reference counted so that only the first 120653947Smccanne * "on" request actually has an effect, as does the final "off" request. 120753947Smccanne * Results are undefined if the "off" and "on" requests are not matched. 120848932Smccanne */ 120948932Smccanne int 121048932Smccanne ifpromisc(ifp, pswitch) 121148932Smccanne struct ifnet *ifp; 121248932Smccanne int pswitch; 121348932Smccanne { 121449726Smccanne struct ifreq ifr; 121553947Smccanne /* 121648932Smccanne * If the device is not configured up, we cannot put it in 121748932Smccanne * promiscuous mode. 121848932Smccanne */ 121948932Smccanne if ((ifp->if_flags & IFF_UP) == 0) 122048932Smccanne return (ENETDOWN); 122148932Smccanne 122248932Smccanne if (pswitch) { 122348932Smccanne if (ifp->if_pcount++ != 0) 122448932Smccanne return (0); 122548932Smccanne ifp->if_flags |= IFF_PROMISC; 122648932Smccanne } else { 122748932Smccanne if (--ifp->if_pcount > 0) 122848932Smccanne return (0); 122948932Smccanne ifp->if_flags &= ~IFF_PROMISC; 123048932Smccanne } 123149726Smccanne ifr.ifr_flags = ifp->if_flags; 123249726Smccanne return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)&ifr)); 123348932Smccanne } 123451425Smccanne #endif 123548932Smccanne 123651425Smccanne #if BSD < 199103 123751425Smccanne /* 123851425Smccanne * Allocate some memory for bpf. This is temporary SunOS support, and 123953947Smccanne * is admittedly a hack. 124051425Smccanne * If resources unavaiable, return 0. 124151425Smccanne */ 124251425Smccanne static caddr_t 124351425Smccanne bpf_alloc(size, canwait) 124451425Smccanne register int size; 124551425Smccanne register int canwait; 124651425Smccanne { 124751425Smccanne register struct mbuf *m; 124851425Smccanne 124951425Smccanne if ((unsigned)size > (MCLBYTES-8)) 125051425Smccanne return 0; 125151425Smccanne 125251425Smccanne MGET(m, canwait, MT_DATA); 125351425Smccanne if (m == 0) 125451425Smccanne return 0; 125551425Smccanne if ((unsigned)size > (MLEN-8)) { 125651425Smccanne MCLGET(m); 125751425Smccanne if (m->m_len != MCLBYTES) { 125851425Smccanne m_freem(m); 125951425Smccanne return 0; 126051425Smccanne } 126151425Smccanne } 126251425Smccanne *mtod(m, struct mbuf **) = m; 126351425Smccanne return mtod(m, caddr_t) + 8; 126451425Smccanne } 126551425Smccanne #endif 126651425Smccanne #endif 1267