147584Smccanne /* 247584Smccanne * Copyright (c) 1990 The Regents of the University of California. 347584Smccanne * All rights reserved. 447584Smccanne * 547584Smccanne * Redistribution and use in source and binary forms, with or without 647584Smccanne * modification, are permitted provided that: (1) source code distributions 747584Smccanne * retain the above copyright notice and this paragraph in its entirety, (2) 847584Smccanne * distributions including binary code include the above copyright notice and 947584Smccanne * this paragraph in its entirety in the documentation or other materials 1047584Smccanne * provided with the distribution, and (3) all advertising materials mentioning 1147584Smccanne * features or use of this software display the following acknowledgement: 1247584Smccanne * ``This product includes software developed by the University of California, 1347584Smccanne * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of 1447584Smccanne * the University nor the names of its contributors may be used to endorse 1547584Smccanne * or promote products derived from this software without specific prior 1647584Smccanne * written permission. 1747584Smccanne * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED 1847584Smccanne * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF 1947584Smccanne * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 2047584Smccanne * 2147584Smccanne * This code is derived from the Stanford/CMU enet packet filter, 2247584Smccanne * (net/enet.c) distributed in 4.3BSD Unix. 2347584Smccanne */ 2447584Smccanne #ifndef lint 2547584Smccanne static char rcsid[] = 2647584Smccanne "$Header: bpf.c,v 1.23 91/01/30 18:22:13 mccanne Exp $"; 2747584Smccanne #endif 2847584Smccanne 2947584Smccanne #include "bpfilter.h" 3047584Smccanne 3147584Smccanne #if (NBPFILTER > 0) 3247584Smccanne 3347584Smccanne #ifndef __GNUC__ 3447584Smccanne #define inline 3547584Smccanne #endif 3647584Smccanne 3747584Smccanne #include <sys/param.h> 3847584Smccanne #include <sys/systm.h> 3947584Smccanne #include <sys/mbuf.h> 4047584Smccanne #include <sys/buf.h> 4147584Smccanne #include <sys/dir.h> 4248932Smccanne #include <sys/proc.h> 4347584Smccanne #include <sys/user.h> 4447584Smccanne #include <sys/ioctl.h> 4547584Smccanne #include <sys/map.h> 4647584Smccanne 4747584Smccanne #include <sys/file.h> 4847584Smccanne #ifdef sparc 4947584Smccanne #include <sys/stream.h> 5047584Smccanne #endif 5147584Smccanne #include <sys/tty.h> 5247584Smccanne #include <sys/uio.h> 5347584Smccanne 5447584Smccanne #include <sys/protosw.h> 5547584Smccanne #include <sys/socket.h> 5647584Smccanne #include <net/if.h> 5747584Smccanne 5847584Smccanne #include <net/bpf.h> 5947584Smccanne #include <net/bpfdesc.h> 6047584Smccanne 6147584Smccanne #include <sys/errno.h> 6247584Smccanne 6347584Smccanne #include <netinet/in.h> 6447584Smccanne #include <netinet/if_ether.h> 6547584Smccanne #include <sys/kernel.h> 6647584Smccanne 6747584Smccanne #define PRINET 26 /* interruptible */ 6847584Smccanne 6947584Smccanne /* 7048932Smccanne * The default read buffer size is patchable. 7148932Smccanne */ 7248932Smccanne int bpf_bufsize = MCLBYTES; 7348932Smccanne 7448932Smccanne /* 7547584Smccanne * 'bpf_iftab' is the driver state table per logical unit number 7647584Smccanne * 'bpf_dtab' holds the descriptors, indexed by minor device # 7747584Smccanne * 'bpf_units' is the number of attached units 7847584Smccanne * 7947584Smccanne * We really don't need NBPFILTER bpf_if entries, but this eliminates 8047584Smccanne * the need to account for all possible drivers here. 8147584Smccanne * This problem will go away when these structures are allocated dynamically. 8247584Smccanne */ 8347584Smccanne static struct bpf_if bpf_iftab[NBPFILTER]; 8447584Smccanne static struct bpf_d bpf_dtab[NBPFILTER]; 8547584Smccanne static u_int bpf_units = 0; 8647584Smccanne 8747584Smccanne static void bpf_ifname(); 8847584Smccanne static void catchpacket(); 8947584Smccanne static int bpf_setif(); 9047584Smccanne static int bpf_initd(); 9147584Smccanne 9247584Smccanne static int 9347584Smccanne bpf_movein(uio, linktype, mp, sockp) 9447584Smccanne register struct uio *uio; 9547584Smccanne int linktype; 9647584Smccanne register struct mbuf **mp; 9747584Smccanne register struct sockaddr *sockp; 9847584Smccanne { 9947584Smccanne struct mbuf *m; 10047584Smccanne int error; 10147584Smccanne int len; 10247584Smccanne int hlen; 10347584Smccanne 10447584Smccanne /* 10547584Smccanne * Build a sockaddr based on the data link layer type. 10647584Smccanne * We do this at this level because the ethernet header 10747584Smccanne * is copied directly into the data field of the sockaddr. 10847584Smccanne * In the case of SLIP, there is no header and the packet 10947584Smccanne * is forwarded as is. 11047584Smccanne * Also, we are careful to leave room at the front of the mbuf 11147584Smccanne * for the link level header. 11247584Smccanne */ 11347584Smccanne switch (linktype) { 11447584Smccanne case DLT_SLIP: 11547584Smccanne sockp->sa_family = AF_INET; 11647584Smccanne hlen = 0; 11747584Smccanne break; 11847584Smccanne 11947584Smccanne case DLT_EN10MB: 12047584Smccanne sockp->sa_family = AF_UNSPEC; 12147584Smccanne /* XXX Would MAXLINKHDR be better? */ 12247584Smccanne hlen = sizeof(struct ether_header); 12347584Smccanne break; 12447584Smccanne 12547584Smccanne case DLT_FDDI: 12647584Smccanne sockp->sa_family = AF_UNSPEC; 12747584Smccanne /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */ 12847584Smccanne hlen = 24; 12947584Smccanne break; 13047584Smccanne 13147584Smccanne default: 13248932Smccanne return (EIO); 13347584Smccanne } 13447584Smccanne 13547584Smccanne len = uio->uio_resid; 13647584Smccanne if ((unsigned)len > MCLBYTES) 13748932Smccanne return (EIO); 13847584Smccanne 13947584Smccanne MGET(m, M_WAIT, MT_DATA); 14047584Smccanne if (m == 0) 14148932Smccanne return (ENOBUFS); 14247584Smccanne if (len > MLEN) { 14348932Smccanne MCLGET(m, M_WAIT); 14448932Smccanne if ((m->m_flags & M_EXT) == 0) { 14547584Smccanne error = ENOBUFS; 14647584Smccanne goto bad; 14747584Smccanne } 14847584Smccanne } 14947584Smccanne m->m_len = len; 15047584Smccanne *mp = m; 15147584Smccanne /* 15247584Smccanne * Make room for link header. 15347584Smccanne */ 15447584Smccanne if (hlen) { 15547584Smccanne m->m_len -= hlen; 15648932Smccanne m->m_data += hlen; /* XXX */ 15747584Smccanne 15848932Smccanne error = uiomove((caddr_t)sockp->sa_data, hlen, uio); 15947584Smccanne if (error) 16047584Smccanne goto bad; 16147584Smccanne } 16248932Smccanne error = uiomove(mtod(m, caddr_t), len - hlen, uio); 16347584Smccanne if (!error) 16448932Smccanne return (0); 16547584Smccanne bad: 16647584Smccanne m_freem(m); 16748932Smccanne return (error); 16847584Smccanne } 16947584Smccanne 17047584Smccanne /* 17147584Smccanne * Attach 'd' to the bpf interface 'bp', i.e. make 'd' listen on 'bp'. 17247584Smccanne * Must be called at splimp. 17347584Smccanne */ 17447584Smccanne static void 17547584Smccanne bpf_attachd(d, bp) 17647584Smccanne struct bpf_d *d; 17747584Smccanne struct bpf_if *bp; 17847584Smccanne { 17948932Smccanne /* Point d at bp. */ 18047584Smccanne d->bd_bif = bp; 18147584Smccanne 18248932Smccanne /* Add d to bp's list of listeners. */ 18347584Smccanne d->bd_next = bp->bif_dlist; 18447584Smccanne bp->bif_dlist = d; 18547584Smccanne 18647584Smccanne /* 18747584Smccanne * Let the driver know we're here (if it doesn't already). 18847584Smccanne */ 18947584Smccanne *bp->bif_driverp = bp; 19047584Smccanne } 19147584Smccanne 19247584Smccanne static void 19347584Smccanne bpf_detachd(d) 19447584Smccanne struct bpf_d *d; 19547584Smccanne { 19647584Smccanne struct bpf_d **p; 19747584Smccanne struct bpf_if *bp; 19847584Smccanne 19947584Smccanne bp = d->bd_bif; 20047584Smccanne /* 20147584Smccanne * Check if this descriptor had requested promiscuous mode. 20247584Smccanne * If so, turn it off. 20347584Smccanne */ 20447584Smccanne if (d->bd_promisc) { 20547584Smccanne d->bd_promisc = 0; 20647584Smccanne if (ifpromisc(bp->bif_ifp, 0)) 20747584Smccanne /* 20847584Smccanne * Something is really wrong if we were able to put 20947584Smccanne * the driver into promiscuous mode, but can't 21047584Smccanne * take it out. 21147584Smccanne */ 21248932Smccanne panic("bpf_detachd: ifpromisc failed"); 21347584Smccanne } 21447584Smccanne /* Remove 'd' from the interface's descriptor list. */ 21547584Smccanne p = &bp->bif_dlist; 21647584Smccanne while (*p != d) { 21747584Smccanne p = &(*p)->bd_next; 21847584Smccanne if (*p == 0) 21947584Smccanne panic("bpf_detachd: descriptor not in list"); 22047584Smccanne } 22147584Smccanne *p = (*p)->bd_next; 22247584Smccanne if (bp->bif_dlist == 0) 22347584Smccanne /* 22447584Smccanne * Let the driver know that there are no more listeners. 22547584Smccanne */ 22647584Smccanne *d->bd_bif->bif_driverp = 0; 22747584Smccanne d->bd_bif = 0; 22847584Smccanne } 22947584Smccanne 23047584Smccanne 23147584Smccanne /* 23247584Smccanne * Mark a descriptor free by making it point to itself. 23347584Smccanne * This is probably cheaper than marking with a constant since 23447584Smccanne * the address should be in a register anyway. 23547584Smccanne */ 23647584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next) 23747584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d)) 23847584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0) 23947584Smccanne 24047584Smccanne /* 24147584Smccanne * bpfopen - open ethernet device 24247584Smccanne * 24347584Smccanne * Errors: ENXIO - illegal minor device number 24447584Smccanne * EBUSY - too many files open 24547584Smccanne */ 24647584Smccanne /* ARGSUSED */ 24747584Smccanne int 24847584Smccanne bpfopen(dev, flag) 24947584Smccanne dev_t dev; 25047584Smccanne int flag; 25147584Smccanne { 25247584Smccanne int error, s; 25347584Smccanne register struct bpf_d *d; 25447584Smccanne 25547584Smccanne if (minor(dev) >= NBPFILTER) 25648932Smccanne return (ENXIO); 25747584Smccanne 25847584Smccanne /* 25947584Smccanne * Each minor can be opened by only one process. If the requested 26047584Smccanne * minor is in use, return EBUSY. 26147584Smccanne */ 26247584Smccanne s = splimp(); 26347584Smccanne d = &bpf_dtab[minor(dev)]; 26447584Smccanne if (!D_ISFREE(d)) { 26547584Smccanne splx(s); 26648932Smccanne return (EBUSY); 26747584Smccanne } else 26847584Smccanne /* Mark "free" and do most initialization. */ 26947584Smccanne bzero((char *)d, sizeof(*d)); 27047584Smccanne splx(s); 27147584Smccanne 27247584Smccanne error = bpf_initd(d); 27347584Smccanne if (error) { 27447584Smccanne D_MARKFREE(d); 27548932Smccanne return (error); 27647584Smccanne } 27748932Smccanne return (0); 27847584Smccanne } 27947584Smccanne 28047584Smccanne /* 28147584Smccanne * Close the descriptor by detaching it from its interface, 28247584Smccanne * deallocating its buffers, and marking it free. 28347584Smccanne */ 28447584Smccanne /* ARGSUSED */ 28547584Smccanne bpfclose(dev, flag) 28647584Smccanne dev_t dev; 28747584Smccanne int flag; 28847584Smccanne { 28947584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 29047584Smccanne int s; 29147584Smccanne 29247584Smccanne s = splimp(); 29347584Smccanne if (d->bd_bif) 29447584Smccanne bpf_detachd(d); 29547584Smccanne splx(s); 29647584Smccanne 29748932Smccanne /* Free the buffer space. */ 29848932Smccanne if (d->bd_hbuf) 29948932Smccanne free(d->bd_hbuf, M_DEVBUF); 30048932Smccanne if (d->bd_fbuf) 30148932Smccanne free(d->bd_fbuf, M_DEVBUF); 30248932Smccanne free(d->bd_sbuf, M_DEVBUF); 303*48967Smccanne if (d->bd_filter) 30448932Smccanne free((caddr_t)d->bd_filter, M_DEVBUF); 30547584Smccanne 30647584Smccanne D_MARKFREE(d); 30747584Smccanne } 30847584Smccanne 30947584Smccanne /* 31048932Smccanne * Rotate the packet buffers in descriptor d. Move the store buffer 31148932Smccanne * into the hold slot, and the free buffer into the store slot. 31248932Smccanne * Zero the length of the new store buffer. 31348932Smccanne */ 31448932Smccanne #define ROTATE_BUFFERS(d) \ 31548932Smccanne (d)->bd_hbuf = (d)->bd_sbuf; \ 31648932Smccanne (d)->bd_hlen = (d)->bd_slen; \ 31748932Smccanne (d)->bd_sbuf = (d)->bd_fbuf; \ 31848932Smccanne (d)->bd_slen = 0; \ 31948932Smccanne (d)->bd_fbuf = 0; 32048932Smccanne /* 32147584Smccanne * bpfread - read next chunk of packets from buffers 32247584Smccanne */ 32347584Smccanne int 32447584Smccanne bpfread(dev, uio) 32547584Smccanne dev_t dev; 32647584Smccanne register struct uio *uio; 32747584Smccanne { 32847584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 32947584Smccanne int error; 33047584Smccanne int s; 33147584Smccanne 33247584Smccanne /* 33347584Smccanne * Restrict application to use a buffer the same size as 33447584Smccanne * as kernel buffers. 33547584Smccanne */ 33648932Smccanne if (uio->uio_resid != d->bd_bufsize) 33748932Smccanne return (EIO); 33847584Smccanne 33947584Smccanne s = splimp(); 34047584Smccanne /* 34147584Smccanne * If the hold buffer is empty, then set a timer and sleep 34247584Smccanne * until either the timeout has occurred or enough packets have 34347584Smccanne * arrived to fill the store buffer. 34447584Smccanne */ 34547584Smccanne while (d->bd_hbuf == 0) { 34648932Smccanne if (d->bd_immediate && d->bd_slen != 0) { 34747584Smccanne /* 34847584Smccanne * A packet(s) either arrived since the previous 34947584Smccanne * read or arrived while we were asleep. 35047584Smccanne * Rotate the buffers and return what's here. 35147584Smccanne */ 35248932Smccanne ROTATE_BUFFERS(d); 35347584Smccanne break; 35447584Smccanne } 35548932Smccanne error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf", d->bd_rtout); 35648932Smccanne if (error == EINTR || error == ERESTART) { 35748932Smccanne splx(s); 35848932Smccanne return (error); 35947584Smccanne } 36048932Smccanne if (error == EWOULDBLOCK) { 36147584Smccanne /* 36247584Smccanne * On a timeout, return what's in the buffer, 36348932Smccanne * which may be nothing. If there is something 36448932Smccanne * in the store buffer, we can rotate the buffers. 36547584Smccanne */ 36647584Smccanne if (d->bd_hbuf) 36747584Smccanne /* 36847584Smccanne * We filled up the buffer in between 36947584Smccanne * getting the timeout and arriving 37047584Smccanne * here, so we don't need to rotate. 37147584Smccanne */ 37247584Smccanne break; 37347584Smccanne 37448932Smccanne if (d->bd_slen == 0) { 37547584Smccanne splx(s); 37648932Smccanne return (0); 37747584Smccanne } 37848932Smccanne ROTATE_BUFFERS(d); 37947584Smccanne break; 38047584Smccanne } 38147584Smccanne } 38247584Smccanne /* 38347584Smccanne * At this point, we know we have something in the hold slot. 38447584Smccanne */ 38547584Smccanne splx(s); 38647584Smccanne 38747584Smccanne /* 38847584Smccanne * Move data from hold buffer into user space. 38947584Smccanne * We know the entire buffer is transferred since 39048932Smccanne * we checked above that the read buffer is bpf_bufsize bytes. 39147584Smccanne */ 39248932Smccanne error = uiomove(d->bd_hbuf, d->bd_hlen, uio); 39347584Smccanne 39447584Smccanne s = splimp(); 39548932Smccanne d->bd_fbuf = d->bd_hbuf; 39648932Smccanne d->bd_hbuf = 0; 39747584Smccanne splx(s); 39847584Smccanne 39948932Smccanne return (error); 40047584Smccanne } 40147584Smccanne 40247584Smccanne 40347584Smccanne /* 40448932Smccanne * If there are processes sleeping on this descriptor, wake them up. 40547584Smccanne */ 40647584Smccanne static inline void 40747584Smccanne bpf_wakeup(d) 40847584Smccanne register struct bpf_d *d; 40947584Smccanne { 41048932Smccanne wakeup((caddr_t)d); 41148932Smccanne if (d->bd_selproc) { 41248932Smccanne selwakeup(d->bd_selproc, (int)d->bd_selcoll); 41348932Smccanne d->bd_selcoll = 0; 41448932Smccanne d->bd_selproc = 0; 41547584Smccanne } 41647584Smccanne } 41747584Smccanne 41847584Smccanne int 41947584Smccanne bpfwrite(dev, uio) 42047584Smccanne dev_t dev; 42147584Smccanne struct uio *uio; 42247584Smccanne { 42347584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 42447584Smccanne struct ifnet *ifp; 42547584Smccanne struct mbuf *m; 42647584Smccanne int error, s; 42747584Smccanne static struct sockaddr dst; 42847584Smccanne 42947584Smccanne if (d->bd_bif == 0) 43048932Smccanne return (ENXIO); 43147584Smccanne 43247584Smccanne ifp = d->bd_bif->bif_ifp; 43347584Smccanne 43447584Smccanne if (uio->uio_resid == 0) 43548932Smccanne return (0); 43647584Smccanne if (uio->uio_resid > ifp->if_mtu) 43748932Smccanne return (EMSGSIZE); 43847584Smccanne 43947584Smccanne error = bpf_movein(uio, (int)d->bd_bif->bif_devp.bdev_type, &m, &dst); 44047584Smccanne if (error) 44148932Smccanne return (error); 44247584Smccanne 44347584Smccanne s = splnet(); 44447584Smccanne error = (*ifp->if_output)(ifp, m, &dst); 44547584Smccanne splx(s); 44647584Smccanne /* 44747584Smccanne * The driver frees the mbuf. 44847584Smccanne */ 44948932Smccanne return (error); 45047584Smccanne } 45147584Smccanne 45247584Smccanne /* 45348932Smccanne * Reset a descriptor by flushing its packet bufferand clearing the receive 45448932Smccanne * and drop counts. Should be called at splimp. 45547584Smccanne */ 45647584Smccanne static void 45747584Smccanne reset_d(d) 45847584Smccanne struct bpf_d *d; 45947584Smccanne { 46047584Smccanne if (d->bd_hbuf) { 46147584Smccanne /* Free the hold buffer. */ 46247584Smccanne d->bd_fbuf = d->bd_hbuf; 46347584Smccanne d->bd_hbuf = 0; 46447584Smccanne } 46548932Smccanne d->bd_slen = 0; 46647584Smccanne d->bd_rcount = 0; 46747584Smccanne d->bd_dcount = 0; 46847584Smccanne } 46947584Smccanne 47047584Smccanne /* 47147584Smccanne * bpfioctl - packet filter control 47247584Smccanne * 47347584Smccanne * FIONREAD Check for read packet available. 47447584Smccanne * SIOCGIFADDR Get interface address - convenient hook to driver. 47547584Smccanne * BIOCGFLEN Get max filter len. 47647584Smccanne * BIOCGBLEN Get buffer len [for read()]. 47747584Smccanne * BIOCSETF Set ethernet read filter. 47847584Smccanne * BIOCFLUSH Flush read packet buffer. 47947584Smccanne * BIOCPROMISC Put interface into promiscuous mode. 48047584Smccanne * BIOCDEVP Get device parameters. 48147584Smccanne * BIOCGETIF Get interface name. 48247584Smccanne * BIOCSETIF Set interface. 48347584Smccanne * BIOCSRTIMEOUT Set read timeout. 48447584Smccanne * BIOCGRTIMEOUT Get read timeout. 48547584Smccanne * BIOCGSTATS Get packet stats. 48647584Smccanne * BIOCIMMEDIATE Set immediate mode. 48747584Smccanne */ 48847584Smccanne /* ARGSUSED */ 48947584Smccanne int 49047584Smccanne bpfioctl(dev, cmd, addr, flag) 49147584Smccanne dev_t dev; 49247584Smccanne int cmd; 49347584Smccanne caddr_t addr; 49447584Smccanne int flag; 49547584Smccanne { 49647584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 49747584Smccanne int s, error = 0; 49847584Smccanne 49947584Smccanne switch (cmd) { 50047584Smccanne 50147584Smccanne default: 50247584Smccanne error = EINVAL; 50347584Smccanne break; 50447584Smccanne 50547584Smccanne /* 50647584Smccanne * Check for read packet available. 50747584Smccanne */ 50847584Smccanne case FIONREAD: 50947584Smccanne { 51047584Smccanne int n; 51147584Smccanne 51247584Smccanne s = splimp(); 51348932Smccanne n = d->bd_slen; 51447584Smccanne if (d->bd_hbuf) 51548932Smccanne n += d->bd_hlen; 51647584Smccanne splx(s); 51747584Smccanne 51847584Smccanne *(int *)addr = n; 51947584Smccanne break; 52047584Smccanne } 52147584Smccanne 52247584Smccanne case SIOCGIFADDR: 52347584Smccanne { 52447584Smccanne struct ifnet *ifp; 52547584Smccanne 52647584Smccanne if (d->bd_bif == 0) 52747584Smccanne error = EINVAL; 52847584Smccanne else { 52947584Smccanne ifp = d->bd_bif->bif_ifp; 53047584Smccanne error = (*ifp->if_ioctl)(ifp, cmd, addr); 53147584Smccanne } 53247584Smccanne break; 53347584Smccanne } 53447584Smccanne 53547584Smccanne /* 53647584Smccanne * Get max filter len. 53747584Smccanne */ 53847584Smccanne case BIOCGFLEN: 53948932Smccanne *(u_int *)addr = BPF_MAXINSNS; 54047584Smccanne break; 54147584Smccanne /* 54247584Smccanne * Get buffer len [for read()]. 54347584Smccanne */ 54447584Smccanne case BIOCGBLEN: 54548932Smccanne *(u_int *)addr = d->bd_bufsize; 54647584Smccanne break; 54747584Smccanne 54847584Smccanne /* 54947584Smccanne * Set ethernet read filter. 55047584Smccanne */ 55147584Smccanne case BIOCSETF: 55247584Smccanne error = bpf_setf(d, (struct bpf_program *)addr); 55347584Smccanne break; 55447584Smccanne 55547584Smccanne /* 55647584Smccanne * Flush read packet buffer. 55747584Smccanne */ 55847584Smccanne case BIOCFLUSH: 55947584Smccanne s = splimp(); 56047584Smccanne reset_d(d); 56147584Smccanne splx(s); 56247584Smccanne break; 56347584Smccanne 56447584Smccanne /* 56547584Smccanne * Put interface into promiscuous mode. 56647584Smccanne */ 56747584Smccanne case BIOCPROMISC: 56847584Smccanne if (d->bd_bif == 0) { 56947584Smccanne /* 57047584Smccanne * No interface attached yet. 57147584Smccanne */ 57247584Smccanne error = EINVAL; 57347584Smccanne break; 57447584Smccanne } 57547584Smccanne s = splimp(); 57647584Smccanne if (d->bd_promisc == 0) { 57747584Smccanne d->bd_promisc = 1; 57847584Smccanne error = ifpromisc(d->bd_bif->bif_ifp, 1); 57947584Smccanne } 58047584Smccanne splx(s); 58147584Smccanne break; 58247584Smccanne 58347584Smccanne /* 58447584Smccanne * Get device parameters. 58547584Smccanne */ 58647584Smccanne case BIOCDEVP: 58747584Smccanne if (d->bd_bif == 0) 58847584Smccanne error = EINVAL; 58947584Smccanne else 59047584Smccanne *(struct bpf_devp *)addr = d->bd_bif->bif_devp; 59147584Smccanne break; 59247584Smccanne 59347584Smccanne /* 59447584Smccanne * Set interface name. 59547584Smccanne */ 59647584Smccanne case BIOCGETIF: 59747584Smccanne if (d->bd_bif == 0) 59847584Smccanne error = EINVAL; 59947584Smccanne else 60047584Smccanne bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr); 60147584Smccanne break; 60247584Smccanne 60347584Smccanne /* 60447584Smccanne * Set interface. 60547584Smccanne */ 60647584Smccanne case BIOCSETIF: 60747584Smccanne error = bpf_setif(d, (struct ifreq *)addr); 60847584Smccanne break; 60947584Smccanne 61047584Smccanne /* 61147584Smccanne * Set read timeout. 61247584Smccanne */ 61347584Smccanne case BIOCSRTIMEOUT: 61447584Smccanne { 61547584Smccanne struct timeval *tv = (struct timeval *)addr; 61647584Smccanne u_long msec; 61747584Smccanne 61847584Smccanne /* Compute number of milliseconds. */ 61947584Smccanne msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; 62047584Smccanne /* Scale milliseconds to ticks. Assume hard 62147584Smccanne clock has millisecond or greater resolution 62247584Smccanne (i.e. tick >= 1000). For 10ms hardclock, 62347584Smccanne tick/1000 = 10, so rtout<-msec/10. */ 62447584Smccanne d->bd_rtout = msec / (tick / 1000); 62547584Smccanne break; 62647584Smccanne } 62747584Smccanne 62847584Smccanne /* 62947584Smccanne * Get read timeout. 63047584Smccanne */ 63147584Smccanne case BIOCGRTIMEOUT: 63247584Smccanne { 63347584Smccanne struct timeval *tv = (struct timeval *)addr; 63447584Smccanne u_long msec = d->bd_rtout; 63547584Smccanne 63647584Smccanne msec *= tick / 1000; 63747584Smccanne tv->tv_sec = msec / 1000; 63847584Smccanne tv->tv_usec = msec % 1000; 63947584Smccanne break; 64047584Smccanne } 64147584Smccanne 64247584Smccanne /* 64347584Smccanne * Get packet stats. 64447584Smccanne */ 64547584Smccanne case BIOCGSTATS: 64647584Smccanne { 64747584Smccanne struct bpf_stat *bs = (struct bpf_stat *)addr; 64847584Smccanne 64947584Smccanne bs->bs_recv = d->bd_rcount; 65047584Smccanne bs->bs_drop = d->bd_dcount; 65147584Smccanne break; 65247584Smccanne } 65347584Smccanne 65447584Smccanne /* 65547584Smccanne * Set immediate mode. 65647584Smccanne */ 65747584Smccanne case BIOCIMMEDIATE: 65847584Smccanne d->bd_immediate = *(u_int *)addr; 65947584Smccanne break; 66047584Smccanne } 66148932Smccanne return (error); 66247584Smccanne } 66347584Smccanne 66447584Smccanne /* 66547584Smccanne * Set d's packet filter program to 'fp'. If 'd' already has a filter, 66648932Smccanne * free it and replace it. Returns EINVAL for bogus requests. 66747584Smccanne */ 66847584Smccanne int 66947584Smccanne bpf_setf(d, fp) 67047584Smccanne struct bpf_d *d; 67147584Smccanne struct bpf_program *fp; 67247584Smccanne { 67348932Smccanne struct bpf_insn *fcode, *old; 67447584Smccanne u_int flen, size; 67547584Smccanne int s; 67647584Smccanne 67748932Smccanne old = d->bd_filter; 67847584Smccanne if (fp->bf_insns == 0) { 67947584Smccanne if (fp->bf_len != 0) 68048932Smccanne return (EINVAL); 68148932Smccanne s = splimp(); 682*48967Smccanne d->bd_filter = 0; 68347584Smccanne reset_d(d); 68447584Smccanne splx(s); 685*48967Smccanne if (old != 0) 68648932Smccanne free((caddr_t)old, M_DEVBUF); 68748932Smccanne return (0); 68847584Smccanne } 68947584Smccanne flen = fp->bf_len; 69048932Smccanne if (flen > BPF_MAXINSNS) 69148932Smccanne return (EINVAL); 69248932Smccanne 69347584Smccanne size = flen * sizeof(*fp->bf_insns); 69448932Smccanne fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK); 69548932Smccanne if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size)) 69648932Smccanne return (EINVAL); 69747584Smccanne 69847584Smccanne if (bpf_validate(fcode, (int)flen)) { 699*48967Smccanne s = splimp(); 70048932Smccanne d->bd_filter = fcode; 70147584Smccanne reset_d(d); 70247584Smccanne splx(s); 703*48967Smccanne if (old != 0) 70448932Smccanne free((caddr_t)old, M_DEVBUF); 70547584Smccanne 70648932Smccanne return (0); 70747584Smccanne } 70848932Smccanne free((caddr_t)fcode, M_DEVBUF); 70948932Smccanne return (EINVAL); 71047584Smccanne } 71147584Smccanne 71247584Smccanne /* 71347584Smccanne * Detach 'd' from its current interface (if attached at all) and attach to 71447584Smccanne * the interface named 'name'. Return ioctl error code or 0. 71547584Smccanne */ 71647584Smccanne static int 71747584Smccanne bpf_setif(d, ifr) 71847584Smccanne struct bpf_d *d; 71947584Smccanne struct ifreq *ifr; 72047584Smccanne { 72147584Smccanne struct bpf_if *bp; 72247584Smccanne char *cp; 72347584Smccanne int unit, i, s; 72447584Smccanne 72547584Smccanne /* 72647584Smccanne * Separate string into name part and unit number. Put a null 72747584Smccanne * byte at the end of the name part, and compute the number. 72847584Smccanne * If the a unit number is unspecified, the default is 0, 72948932Smccanne * as initialized above. XXX This should be common code. 73047584Smccanne */ 73147584Smccanne unit = 0; 73247584Smccanne cp = ifr->ifr_name; 73347584Smccanne cp[sizeof(ifr->ifr_name) - 1] = '\0'; 73447584Smccanne while (*cp++) { 73547584Smccanne if (*cp >= '0' && *cp <= '9') { 73647584Smccanne unit = *cp - '0'; 73747584Smccanne *cp++ = '\0'; 73847584Smccanne while (*cp) 73947584Smccanne unit = 10 * unit + *cp++ - '0'; 74047584Smccanne break; 74147584Smccanne } 74247584Smccanne } 74347584Smccanne /* 74447584Smccanne * Look through attached interfaces for the named one. 74547584Smccanne */ 74647584Smccanne bp = bpf_iftab; 74747584Smccanne for (i = 0; i < NBPFILTER; ++bp, ++i) { 74847584Smccanne struct ifnet *ifp = bp->bif_ifp; 74947584Smccanne 75047584Smccanne if (ifp == 0 || unit != ifp->if_unit 75147584Smccanne || strcmp(ifp->if_name, ifr->ifr_name) != 0) 75247584Smccanne continue; 75347584Smccanne /* 75447584Smccanne * We found the requested interface. If we're 75547584Smccanne * already attached to it, just flush the buffer. 75647584Smccanne * If it's not up, return an error. 75747584Smccanne */ 75847584Smccanne if ((ifp->if_flags & IFF_UP) == 0) 75948932Smccanne return (ENETDOWN); 76047584Smccanne s = splimp(); 76147584Smccanne if (bp != d->bd_bif) { 76247584Smccanne if (d->bd_bif) 76347584Smccanne /* 76448932Smccanne * Detach if attached to something else. 76547584Smccanne */ 76647584Smccanne bpf_detachd(d); 76747584Smccanne 76847584Smccanne bpf_attachd(d, bp); 76947584Smccanne } 77047584Smccanne reset_d(d); 77147584Smccanne splx(s); 77248932Smccanne return (0); 77347584Smccanne } 77447584Smccanne /* Not found. */ 77548932Smccanne return (ENXIO); 77647584Smccanne } 77747584Smccanne 77847584Smccanne /* 77947584Smccanne * Lookup the name of the 'ifp' interface and return it in 'ifr->ifr_name'. 78047584Smccanne * We augment the ifp's base name with its unit number. 78147584Smccanne */ 78247584Smccanne static void 78347584Smccanne bpf_ifname(ifp, ifr) 78447584Smccanne struct ifnet *ifp; 78547584Smccanne struct ifreq *ifr; 78647584Smccanne { 78747584Smccanne char *s = ifp->if_name; 78847584Smccanne char *d = ifr->ifr_name; 78947584Smccanne 79047584Smccanne while (*d++ = *s++) 79147584Smccanne ; 79248932Smccanne /* XXX Assume that unit number is less than 10. */ 79347584Smccanne *d++ = ifp->if_unit + '0'; 79447584Smccanne *d = '\0'; 79547584Smccanne } 79647584Smccanne 79747584Smccanne /* 79847584Smccanne * Support for select() system call 79947584Smccanne * Inspired by the code in tty.c for the same purpose. 80047584Smccanne * 80147584Smccanne * bpfselect - returns true iff the specific operation 80247584Smccanne * will not block indefinitely. Otherwise, return 80347584Smccanne * false but make a note that a selwakeup() must be done. 80447584Smccanne */ 80547584Smccanne int 80648932Smccanne bpfselect(dev, rw, p) 80747584Smccanne register dev_t dev; 80847584Smccanne int rw; 80948932Smccanne struct proc *p; 81047584Smccanne { 81147584Smccanne register struct bpf_d *d; 81247584Smccanne register int s; 81347584Smccanne 81447584Smccanne if (rw != FREAD) 81548932Smccanne return (0); 81647584Smccanne /* 81747584Smccanne * An imitation of the FIONREAD ioctl code. 81847584Smccanne */ 81947584Smccanne d = &bpf_dtab[minor(dev)]; 82047584Smccanne 82147584Smccanne s = splimp(); 82248932Smccanne if (d->bd_slen != 0 || d->bd_hbuf && d->bd_hlen != 0) { 82347584Smccanne /* 82447584Smccanne * There is data waiting. 82547584Smccanne */ 82647584Smccanne splx(s); 82748932Smccanne return (1); 82847584Smccanne } 82947584Smccanne /* 83047584Smccanne * No data ready. If there's already a select() waiting on this 83147584Smccanne * minor device then this is a collision. This shouldn't happen 83247584Smccanne * because minors really should not be shared, but if a process 83347584Smccanne * forks while one of these is open, it is possible that both 83447584Smccanne * processes could select on the same descriptor. 83547584Smccanne */ 83648932Smccanne if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait) 83748932Smccanne d->bd_selcoll = 1; 83847584Smccanne else 83948932Smccanne d->bd_selproc = p; 84048932Smccanne 84147584Smccanne splx(s); 84248932Smccanne return (0); 84347584Smccanne } 84447584Smccanne 84547584Smccanne /* 84647584Smccanne * bpf_tap - incoming linkage from device drivers 84747584Smccanne */ 84847584Smccanne void 84948932Smccanne bpf_tap(arg, pkt, pktlen) 85047584Smccanne caddr_t arg; 85148932Smccanne register u_char *pkt; 85248932Smccanne register u_int pktlen; 85347584Smccanne { 85447584Smccanne struct bpf_if *bp; 85547584Smccanne register struct bpf_d *d; 85647584Smccanne register u_int slen; 85747584Smccanne extern bcopy(); 85847584Smccanne /* 85947584Smccanne * Note that the ipl does not have to be raised at this point. 86047584Smccanne * The only problem that could arise here is that if two different 86147584Smccanne * interfaces shared any data. This is not the case. 86247584Smccanne */ 86347584Smccanne bp = (struct bpf_if *)arg; 86447584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 86547584Smccanne ++d->bd_rcount; 866*48967Smccanne if (d->bd_filter) 867*48967Smccanne slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen); 868*48967Smccanne else 869*48967Smccanne slen = (u_int)-1; 870*48967Smccanne 87147584Smccanne if (slen != 0) 87248932Smccanne catchpacket(d, pkt, pktlen, slen, (void (*)())bcopy); 87347584Smccanne } 87447584Smccanne } 87547584Smccanne 87647584Smccanne /* 87747584Smccanne * Copy data from an mbuf chain into a buffer. This code is derived 87847584Smccanne * from m_copydata in sys/uipc_mbuf.c. 87947584Smccanne */ 88047584Smccanne static void 88147584Smccanne bpf_m_copydata(src, dst, len) 88247584Smccanne u_char *src; 88347584Smccanne u_char *dst; 88447584Smccanne register int len; 88547584Smccanne { 88647584Smccanne register struct mbuf *m = (struct mbuf *)src; 88747584Smccanne register unsigned count; 88847584Smccanne 88947584Smccanne while (len > 0) { 89047584Smccanne if (m == 0) 89147584Smccanne panic("bpf_m_copydata"); 89247584Smccanne count = MIN(m->m_len, len); 89347584Smccanne (void)bcopy(mtod(m, caddr_t), (caddr_t)dst, count); 89447584Smccanne len -= count; 89547584Smccanne dst += count; 89647584Smccanne m = m->m_next; 89747584Smccanne } 89847584Smccanne } 89947584Smccanne 90047584Smccanne /* 90148932Smccanne * Length of ethernet and TCP/IP header with no IP options. 90247584Smccanne */ 90347584Smccanne #define BPF_MIN_SNAPLEN 50 90447584Smccanne 90547584Smccanne /* 90647584Smccanne * bpf_mtap - incoming linkage from device drivers, when packet 90747584Smccanne * is in an mbuf chain 90847584Smccanne */ 90947584Smccanne void 91047584Smccanne bpf_mtap(arg, m0) 91147584Smccanne caddr_t arg; 91247584Smccanne struct mbuf *m0; 91347584Smccanne { 91447584Smccanne struct bpf_if *bp = (struct bpf_if *)arg; 91547584Smccanne struct bpf_d *d; 91647584Smccanne u_char *cp; 91748932Smccanne u_int slen, pktlen; 91847584Smccanne int nbytes; 91947584Smccanne struct mbuf *m; 92048932Smccanne static u_char buf[BPF_MIN_SNAPLEN]; 92147584Smccanne 92247584Smccanne if (m0->m_len >= BPF_MIN_SNAPLEN) { 92347584Smccanne slen = m0->m_len; 92447584Smccanne cp = mtod(m0, u_char *); 92547584Smccanne } 92647584Smccanne else { 92747584Smccanne nbytes = BPF_MIN_SNAPLEN; 92847584Smccanne cp = buf; 92947584Smccanne m = m0; 93047584Smccanne while (m && nbytes > 0) { 93147584Smccanne slen = MIN(m->m_len, nbytes); 93247584Smccanne bcopy(mtod(m, char *), (char *)cp, slen); 93347584Smccanne cp += slen; 93447584Smccanne nbytes -= slen; 93547584Smccanne m = m->m_next; 93647584Smccanne } 93747584Smccanne if (nbytes > 0) 93847584Smccanne /* Packet too small? */ 93947584Smccanne return; 94047584Smccanne 94147584Smccanne slen = BPF_MIN_SNAPLEN; 94247584Smccanne cp = buf; 94347584Smccanne } 94448932Smccanne pktlen = 0; 94547584Smccanne m = m0; 94647584Smccanne while (m) { 94748932Smccanne pktlen += m->m_len; 94847584Smccanne m = m->m_next; 94947584Smccanne } 95047584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 95147584Smccanne ++d->bd_rcount; 952*48967Smccanne if (d->bd_filter) 953*48967Smccanne slen = bpf_filter(d->bd_filter, cp, pktlen, slen); 954*48967Smccanne else 955*48967Smccanne slen = (u_int)-1; 95647584Smccanne if (slen != 0) 95748932Smccanne catchpacket(d, (u_char *)m0, pktlen, slen, 95847584Smccanne bpf_m_copydata); 95947584Smccanne } 96047584Smccanne } 96147584Smccanne 96247584Smccanne /* 96348932Smccanne * Move the packet data from interface memory ('pkt') into the 96447584Smccanne * store buffer. Return 1 if it's time to wakeup a listener (buffer full), 96547584Smccanne * otherwise 0. 'copy' is the routine called to do the actual data 96647584Smccanne * transfer. 'bcopy' is passed in to copy contiguous chunks, while 96747584Smccanne * 'bpf_m_copydata' is passed in to copy mbuf chains. In the latter 96848932Smccanne * case, 'pkt' is really an mbuf. 96947584Smccanne */ 97047584Smccanne static void 97148932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn) 97248932Smccanne register struct bpf_d *d; 97348932Smccanne register u_char *pkt; 97448932Smccanne register u_int pktlen, snaplen; 97548932Smccanne register void (*cpfn)(); 97647584Smccanne { 97748932Smccanne register struct bpf_hdr *hp; 97848932Smccanne register int totlen, curlen; 97948932Smccanne register int hdrlen = d->bd_bif->bif_hdrlen; 98047584Smccanne /* 98147584Smccanne * Figure out how many bytes to move. If the packet is 98247584Smccanne * greater or equal to the snapshot length, transfer that 98347584Smccanne * much. Otherwise, transfer the whole packet (unless 98448932Smccanne * we hit the buffer size limit). 98547584Smccanne */ 98648932Smccanne if (snaplen <= pktlen) 98747584Smccanne totlen = snaplen + hdrlen; 98847584Smccanne else { 98948932Smccanne totlen = pktlen + hdrlen; 99048932Smccanne if (totlen > d->bd_bufsize) 99148932Smccanne totlen = d->bd_bufsize; 99247584Smccanne } 99347584Smccanne 99447584Smccanne /* 99547584Smccanne * Round up the end of the previous packet to the next longword. 99647584Smccanne */ 99748932Smccanne curlen = BPF_WORDALIGN(d->bd_slen); 99848932Smccanne if (curlen + totlen > d->bd_bufsize) { 99947584Smccanne /* 100047584Smccanne * This packet will overflow the storage buffer. 100148932Smccanne * Rotate the buffers if we can, then wakeup any 100248932Smccanne * pending reads. 100347584Smccanne */ 100447584Smccanne if (d->bd_fbuf == 0) { 100547584Smccanne /* 100648932Smccanne * We haven't completed the previous read yet, 100748932Smccanne * so drop the packet. 100847584Smccanne */ 100947584Smccanne ++d->bd_dcount; 101047584Smccanne return; 101147584Smccanne } 101248932Smccanne ROTATE_BUFFERS(d); 101347584Smccanne bpf_wakeup(d); 101448932Smccanne curlen = 0; 101547584Smccanne } 101648932Smccanne else if (d->bd_immediate) 101747584Smccanne /* 101847584Smccanne * Immediate mode is set. A packet arrived so any 101947584Smccanne * reads should be woken up. 102047584Smccanne */ 102147584Smccanne bpf_wakeup(d); 102248932Smccanne 102347584Smccanne /* 102447584Smccanne * Append the bpf header. 102547584Smccanne */ 102648932Smccanne hp = (struct bpf_hdr *)(d->bd_sbuf + curlen); 102747584Smccanne #ifdef sun 102847584Smccanne uniqtime(&hp->bh_tstamp); 102947584Smccanne #else 103047584Smccanne #ifdef hp300 103147584Smccanne microtime(&hp->bh_tstamp); 103247584Smccanne #else 103347584Smccanne hp->bh_tstamp = time; 103447584Smccanne #endif 103547584Smccanne #endif 103648932Smccanne hp->bh_datalen = pktlen; 103747584Smccanne hp->bh_hdrlen = hdrlen; 103847584Smccanne /* 103948932Smccanne * Copy the packet data into the store buffer and update its length. 104047584Smccanne */ 104148932Smccanne (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen)); 104248932Smccanne d->bd_slen = curlen + totlen; 104347584Smccanne } 104447584Smccanne 104547584Smccanne /* 104647584Smccanne * Initialize all nonzero fields of a descriptor. 104747584Smccanne */ 104847584Smccanne static int 104947584Smccanne bpf_initd(d) 105047584Smccanne register struct bpf_d *d; 105147584Smccanne { 105248932Smccanne d->bd_bufsize = bpf_bufsize; 105348932Smccanne d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 105448932Smccanne if (d->bd_fbuf == 0) 105548932Smccanne return (ENOBUFS); 105647584Smccanne 105748932Smccanne d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 105848932Smccanne if (d->bd_sbuf == 0) { 105948932Smccanne free(d->bd_fbuf, M_DEVBUF); 106048932Smccanne return (ENOBUFS); 106147584Smccanne } 106248932Smccanne d->bd_slen = 0; 106348932Smccanne d->bd_hlen = 0; 106448932Smccanne return (0); 106547584Smccanne } 106647584Smccanne 106747584Smccanne /* 106847584Smccanne * Register 'ifp' with bpf. 'devp' is the link-level device descriptor 106947584Smccanne * and 'driverp' is a pointer to the 'struct bpf_if *' in the driver's softc. 107047584Smccanne */ 107147584Smccanne void 107247584Smccanne bpfattach(driverp, ifp, devp) 107347584Smccanne caddr_t *driverp; 107447584Smccanne struct ifnet *ifp; 107547584Smccanne struct bpf_devp *devp; 107647584Smccanne { 107747584Smccanne struct bpf_if *bp; 107847584Smccanne int i; 107947584Smccanne 108047584Smccanne if (bpf_units >= NBPFILTER) { 108147584Smccanne printf("bpf: too many interfaces: %s%d not attached\n", 108247584Smccanne ifp->if_name, ifp->if_unit); 108347584Smccanne return; 108447584Smccanne } 108547584Smccanne bp = &bpf_iftab[bpf_units++]; 108647584Smccanne 108747584Smccanne bp->bif_dlist = 0; 108847584Smccanne bp->bif_driverp = (struct bpf_if **)driverp; 108947584Smccanne bp->bif_ifp = ifp; 109047584Smccanne bp->bif_devp = *devp; 109147584Smccanne 109248932Smccanne *bp->bif_driverp = 0; 109348932Smccanne 109447584Smccanne /* 109547584Smccanne * Compute the length of the bpf header. This is not necessarily 109647584Smccanne * equal to SIZEOF_BPF_HDR because we want to insert spacing such 109747584Smccanne * that the network layer header begins on a longword boundary (for 109847584Smccanne * performance reasons and to alleviate alignment restrictions). 109947584Smccanne */ 110047584Smccanne i = devp->bdev_hdrlen; 110147584Smccanne bp->bif_hdrlen = BPF_WORDALIGN(i + SIZEOF_BPF_HDR) - i; 110247584Smccanne 110347584Smccanne /* 110447584Smccanne * Mark all the descriptors free if this hasn't been done. 110547584Smccanne */ 110647584Smccanne if (!D_ISFREE(&bpf_dtab[0])) 110747584Smccanne for (i = 0; i < NBPFILTER; ++i) 110847584Smccanne D_MARKFREE(&bpf_dtab[i]); 110947584Smccanne 111047584Smccanne printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit); 111147584Smccanne } 111247584Smccanne 1113*48967Smccanne /* XXX This routine belongs in net/if.c. */ 111448932Smccanne /* 111548932Smccanne * Set/clear promiscuous mode on interface ifp based on the truth value` 111648932Smccanne * of pswitch. The calls are reference counted so that only the first 111748932Smccanne * on request actually has an effect, as does the final off request. 111848932Smccanne * Results are undefined if the off and on requests are not matched. 111948932Smccanne */ 112048932Smccanne int 112148932Smccanne ifpromisc(ifp, pswitch) 112248932Smccanne struct ifnet *ifp; 112348932Smccanne int pswitch; 112448932Smccanne { 112548932Smccanne /* 112648932Smccanne * If the device is not configured up, we cannot put it in 112748932Smccanne * promiscuous mode. 112848932Smccanne */ 112948932Smccanne if ((ifp->if_flags & IFF_UP) == 0) 113048932Smccanne return (ENETDOWN); 113148932Smccanne 113248932Smccanne if (pswitch) { 113348932Smccanne if (ifp->if_pcount++ != 0) 113448932Smccanne return (0); 113548932Smccanne ifp->if_flags |= IFF_PROMISC; 113648932Smccanne } else { 113748932Smccanne if (--ifp->if_pcount > 0) 113848932Smccanne return (0); 113948932Smccanne ifp->if_flags &= ~IFF_PROMISC; 114048932Smccanne } 114148932Smccanne return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)0)); 114248932Smccanne } 114348932Smccanne 114447584Smccanne #endif (NBPFILTER > 0) 1145