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