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 /* 75*49202Smccanne * bpf_iflist is the list of interfaces; each corresponds to an ifnet 76*49202Smccanne * bpf_dtab holds the descriptors, indexed by minor device # 7747584Smccanne * 7847584Smccanne * We really don't need NBPFILTER bpf_if entries, but this eliminates 7947584Smccanne * the need to account for all possible drivers here. 8047584Smccanne * This problem will go away when these structures are allocated dynamically. 8147584Smccanne */ 82*49202Smccanne static struct bpf_if *bpf_iflist; 8347584Smccanne static struct bpf_d bpf_dtab[NBPFILTER]; 8447584Smccanne 8547584Smccanne static void bpf_ifname(); 8647584Smccanne static void catchpacket(); 8747584Smccanne static int bpf_setif(); 8847584Smccanne static int bpf_initd(); 8947584Smccanne 9047584Smccanne static int 9147584Smccanne bpf_movein(uio, linktype, mp, sockp) 9247584Smccanne register struct uio *uio; 9347584Smccanne int linktype; 9447584Smccanne register struct mbuf **mp; 9547584Smccanne register struct sockaddr *sockp; 9647584Smccanne { 9747584Smccanne struct mbuf *m; 9847584Smccanne int error; 9947584Smccanne int len; 10047584Smccanne int hlen; 10147584Smccanne 10247584Smccanne /* 10347584Smccanne * Build a sockaddr based on the data link layer type. 10447584Smccanne * We do this at this level because the ethernet header 10547584Smccanne * is copied directly into the data field of the sockaddr. 10647584Smccanne * In the case of SLIP, there is no header and the packet 10747584Smccanne * is forwarded as is. 10847584Smccanne * Also, we are careful to leave room at the front of the mbuf 10947584Smccanne * for the link level header. 11047584Smccanne */ 11147584Smccanne switch (linktype) { 11247584Smccanne case DLT_SLIP: 11347584Smccanne sockp->sa_family = AF_INET; 11447584Smccanne hlen = 0; 11547584Smccanne break; 11647584Smccanne 11747584Smccanne case DLT_EN10MB: 11847584Smccanne sockp->sa_family = AF_UNSPEC; 11947584Smccanne /* XXX Would MAXLINKHDR be better? */ 12047584Smccanne hlen = sizeof(struct ether_header); 12147584Smccanne break; 12247584Smccanne 12347584Smccanne case DLT_FDDI: 12447584Smccanne sockp->sa_family = AF_UNSPEC; 12547584Smccanne /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */ 12647584Smccanne hlen = 24; 12747584Smccanne break; 12847584Smccanne 12947584Smccanne default: 13048932Smccanne return (EIO); 13147584Smccanne } 13247584Smccanne 13347584Smccanne len = uio->uio_resid; 13447584Smccanne if ((unsigned)len > MCLBYTES) 13548932Smccanne return (EIO); 13647584Smccanne 13747584Smccanne MGET(m, M_WAIT, MT_DATA); 13847584Smccanne if (m == 0) 13948932Smccanne return (ENOBUFS); 14047584Smccanne if (len > MLEN) { 14148932Smccanne MCLGET(m, M_WAIT); 14248932Smccanne if ((m->m_flags & M_EXT) == 0) { 14347584Smccanne error = ENOBUFS; 14447584Smccanne goto bad; 14547584Smccanne } 14647584Smccanne } 14747584Smccanne m->m_len = len; 14847584Smccanne *mp = m; 14947584Smccanne /* 15047584Smccanne * Make room for link header. 15147584Smccanne */ 15247584Smccanne if (hlen) { 15347584Smccanne m->m_len -= hlen; 15448932Smccanne m->m_data += hlen; /* XXX */ 15547584Smccanne 15648932Smccanne error = uiomove((caddr_t)sockp->sa_data, hlen, uio); 15747584Smccanne if (error) 15847584Smccanne goto bad; 15947584Smccanne } 16048932Smccanne error = uiomove(mtod(m, caddr_t), len - hlen, uio); 16147584Smccanne if (!error) 16248932Smccanne return (0); 16347584Smccanne bad: 16447584Smccanne m_freem(m); 16548932Smccanne return (error); 16647584Smccanne } 16747584Smccanne 16847584Smccanne /* 16947584Smccanne * Attach 'd' to the bpf interface 'bp', i.e. make 'd' listen on 'bp'. 17047584Smccanne * Must be called at splimp. 17147584Smccanne */ 17247584Smccanne static void 17347584Smccanne bpf_attachd(d, bp) 17447584Smccanne struct bpf_d *d; 17547584Smccanne struct bpf_if *bp; 17647584Smccanne { 17748932Smccanne /* Point d at bp. */ 17847584Smccanne d->bd_bif = bp; 17947584Smccanne 18048932Smccanne /* Add d to bp's list of listeners. */ 18147584Smccanne d->bd_next = bp->bif_dlist; 18247584Smccanne bp->bif_dlist = d; 18347584Smccanne 18447584Smccanne /* 18547584Smccanne * Let the driver know we're here (if it doesn't already). 18647584Smccanne */ 18747584Smccanne *bp->bif_driverp = bp; 18847584Smccanne } 18947584Smccanne 19047584Smccanne static void 19147584Smccanne bpf_detachd(d) 19247584Smccanne struct bpf_d *d; 19347584Smccanne { 19447584Smccanne struct bpf_d **p; 19547584Smccanne struct bpf_if *bp; 19647584Smccanne 19747584Smccanne bp = d->bd_bif; 19847584Smccanne /* 19947584Smccanne * Check if this descriptor had requested promiscuous mode. 20047584Smccanne * If so, turn it off. 20147584Smccanne */ 20247584Smccanne if (d->bd_promisc) { 20347584Smccanne d->bd_promisc = 0; 20447584Smccanne if (ifpromisc(bp->bif_ifp, 0)) 20547584Smccanne /* 20647584Smccanne * Something is really wrong if we were able to put 20747584Smccanne * the driver into promiscuous mode, but can't 20847584Smccanne * take it out. 20947584Smccanne */ 21048932Smccanne panic("bpf_detachd: ifpromisc failed"); 21147584Smccanne } 21247584Smccanne /* Remove 'd' from the interface's descriptor list. */ 21347584Smccanne p = &bp->bif_dlist; 21447584Smccanne while (*p != d) { 21547584Smccanne p = &(*p)->bd_next; 21647584Smccanne if (*p == 0) 21747584Smccanne panic("bpf_detachd: descriptor not in list"); 21847584Smccanne } 21947584Smccanne *p = (*p)->bd_next; 22047584Smccanne if (bp->bif_dlist == 0) 22147584Smccanne /* 22247584Smccanne * Let the driver know that there are no more listeners. 22347584Smccanne */ 22447584Smccanne *d->bd_bif->bif_driverp = 0; 22547584Smccanne d->bd_bif = 0; 22647584Smccanne } 22747584Smccanne 22847584Smccanne 22947584Smccanne /* 23047584Smccanne * Mark a descriptor free by making it point to itself. 23147584Smccanne * This is probably cheaper than marking with a constant since 23247584Smccanne * the address should be in a register anyway. 23347584Smccanne */ 23447584Smccanne #define D_ISFREE(d) ((d) == (d)->bd_next) 23547584Smccanne #define D_MARKFREE(d) ((d)->bd_next = (d)) 23647584Smccanne #define D_MARKUSED(d) ((d)->bd_next = 0) 23747584Smccanne 23847584Smccanne /* 23947584Smccanne * bpfopen - open ethernet device 24047584Smccanne * 24147584Smccanne * Errors: ENXIO - illegal minor device number 24247584Smccanne * EBUSY - too many files open 24347584Smccanne */ 24447584Smccanne /* ARGSUSED */ 24547584Smccanne int 24647584Smccanne bpfopen(dev, flag) 24747584Smccanne dev_t dev; 24847584Smccanne int flag; 24947584Smccanne { 25047584Smccanne int error, s; 25147584Smccanne register struct bpf_d *d; 25247584Smccanne 25347584Smccanne if (minor(dev) >= NBPFILTER) 25448932Smccanne return (ENXIO); 25547584Smccanne 25647584Smccanne /* 25747584Smccanne * Each minor can be opened by only one process. If the requested 25847584Smccanne * minor is in use, return EBUSY. 25947584Smccanne */ 26047584Smccanne s = splimp(); 26147584Smccanne d = &bpf_dtab[minor(dev)]; 26247584Smccanne if (!D_ISFREE(d)) { 26347584Smccanne splx(s); 26448932Smccanne return (EBUSY); 26547584Smccanne } else 26647584Smccanne /* Mark "free" and do most initialization. */ 26747584Smccanne bzero((char *)d, sizeof(*d)); 26847584Smccanne splx(s); 26947584Smccanne 27047584Smccanne error = bpf_initd(d); 27147584Smccanne if (error) { 27247584Smccanne D_MARKFREE(d); 27348932Smccanne return (error); 27447584Smccanne } 27548932Smccanne return (0); 27647584Smccanne } 27747584Smccanne 27847584Smccanne /* 27947584Smccanne * Close the descriptor by detaching it from its interface, 28047584Smccanne * deallocating its buffers, and marking it free. 28147584Smccanne */ 28247584Smccanne /* ARGSUSED */ 28347584Smccanne bpfclose(dev, flag) 28447584Smccanne dev_t dev; 28547584Smccanne int flag; 28647584Smccanne { 28747584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 28847584Smccanne int s; 28947584Smccanne 29047584Smccanne s = splimp(); 29147584Smccanne if (d->bd_bif) 29247584Smccanne bpf_detachd(d); 29347584Smccanne splx(s); 29447584Smccanne 29548932Smccanne /* Free the buffer space. */ 29648932Smccanne if (d->bd_hbuf) 29748932Smccanne free(d->bd_hbuf, M_DEVBUF); 29848932Smccanne if (d->bd_fbuf) 29948932Smccanne free(d->bd_fbuf, M_DEVBUF); 30048932Smccanne free(d->bd_sbuf, M_DEVBUF); 30148967Smccanne if (d->bd_filter) 30248932Smccanne free((caddr_t)d->bd_filter, M_DEVBUF); 30347584Smccanne 30447584Smccanne D_MARKFREE(d); 30547584Smccanne } 30647584Smccanne 30747584Smccanne /* 30848932Smccanne * Rotate the packet buffers in descriptor d. Move the store buffer 30948932Smccanne * into the hold slot, and the free buffer into the store slot. 31048932Smccanne * Zero the length of the new store buffer. 31148932Smccanne */ 31248932Smccanne #define ROTATE_BUFFERS(d) \ 31348932Smccanne (d)->bd_hbuf = (d)->bd_sbuf; \ 31448932Smccanne (d)->bd_hlen = (d)->bd_slen; \ 31548932Smccanne (d)->bd_sbuf = (d)->bd_fbuf; \ 31648932Smccanne (d)->bd_slen = 0; \ 31748932Smccanne (d)->bd_fbuf = 0; 31848932Smccanne /* 31947584Smccanne * bpfread - read next chunk of packets from buffers 32047584Smccanne */ 32147584Smccanne int 32247584Smccanne bpfread(dev, uio) 32347584Smccanne dev_t dev; 32447584Smccanne register struct uio *uio; 32547584Smccanne { 32647584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 32747584Smccanne int error; 32847584Smccanne int s; 32947584Smccanne 33047584Smccanne /* 33147584Smccanne * Restrict application to use a buffer the same size as 33247584Smccanne * as kernel buffers. 33347584Smccanne */ 33448932Smccanne if (uio->uio_resid != d->bd_bufsize) 335*49202Smccanne return (EINVAL); 33647584Smccanne 33747584Smccanne s = splimp(); 33847584Smccanne /* 33947584Smccanne * If the hold buffer is empty, then set a timer and sleep 34047584Smccanne * until either the timeout has occurred or enough packets have 34147584Smccanne * arrived to fill the store buffer. 34247584Smccanne */ 34347584Smccanne while (d->bd_hbuf == 0) { 34448932Smccanne if (d->bd_immediate && d->bd_slen != 0) { 34547584Smccanne /* 34647584Smccanne * A packet(s) either arrived since the previous 34747584Smccanne * read or arrived while we were asleep. 34847584Smccanne * Rotate the buffers and return what's here. 34947584Smccanne */ 35048932Smccanne ROTATE_BUFFERS(d); 35147584Smccanne break; 35247584Smccanne } 35348932Smccanne error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf", d->bd_rtout); 35448932Smccanne if (error == EINTR || error == ERESTART) { 35548932Smccanne splx(s); 35648932Smccanne return (error); 35747584Smccanne } 35848932Smccanne if (error == EWOULDBLOCK) { 35947584Smccanne /* 36047584Smccanne * On a timeout, return what's in the buffer, 36148932Smccanne * which may be nothing. If there is something 36248932Smccanne * in the store buffer, we can rotate the buffers. 36347584Smccanne */ 36447584Smccanne if (d->bd_hbuf) 36547584Smccanne /* 36647584Smccanne * We filled up the buffer in between 36747584Smccanne * getting the timeout and arriving 36847584Smccanne * here, so we don't need to rotate. 36947584Smccanne */ 37047584Smccanne break; 37147584Smccanne 37248932Smccanne if (d->bd_slen == 0) { 37347584Smccanne splx(s); 37448932Smccanne return (0); 37547584Smccanne } 37648932Smccanne ROTATE_BUFFERS(d); 37747584Smccanne break; 37847584Smccanne } 37947584Smccanne } 38047584Smccanne /* 38147584Smccanne * At this point, we know we have something in the hold slot. 38247584Smccanne */ 38347584Smccanne splx(s); 38447584Smccanne 38547584Smccanne /* 38647584Smccanne * Move data from hold buffer into user space. 38747584Smccanne * We know the entire buffer is transferred since 38848932Smccanne * we checked above that the read buffer is bpf_bufsize bytes. 38947584Smccanne */ 39048932Smccanne error = uiomove(d->bd_hbuf, d->bd_hlen, uio); 39147584Smccanne 39247584Smccanne s = splimp(); 39348932Smccanne d->bd_fbuf = d->bd_hbuf; 39448932Smccanne d->bd_hbuf = 0; 39547584Smccanne splx(s); 39647584Smccanne 39748932Smccanne return (error); 39847584Smccanne } 39947584Smccanne 40047584Smccanne 40147584Smccanne /* 40248932Smccanne * If there are processes sleeping on this descriptor, wake them up. 40347584Smccanne */ 40447584Smccanne static inline void 40547584Smccanne bpf_wakeup(d) 40647584Smccanne register struct bpf_d *d; 40747584Smccanne { 40848932Smccanne wakeup((caddr_t)d); 40948932Smccanne if (d->bd_selproc) { 41048932Smccanne selwakeup(d->bd_selproc, (int)d->bd_selcoll); 41148932Smccanne d->bd_selcoll = 0; 41248932Smccanne d->bd_selproc = 0; 41347584Smccanne } 41447584Smccanne } 41547584Smccanne 41647584Smccanne int 41747584Smccanne bpfwrite(dev, uio) 41847584Smccanne dev_t dev; 41947584Smccanne struct uio *uio; 42047584Smccanne { 42147584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 42247584Smccanne struct ifnet *ifp; 42347584Smccanne struct mbuf *m; 42447584Smccanne int error, s; 42547584Smccanne static struct sockaddr dst; 42647584Smccanne 42747584Smccanne if (d->bd_bif == 0) 42848932Smccanne return (ENXIO); 42947584Smccanne 43047584Smccanne ifp = d->bd_bif->bif_ifp; 43147584Smccanne 43247584Smccanne if (uio->uio_resid == 0) 43348932Smccanne return (0); 43447584Smccanne if (uio->uio_resid > ifp->if_mtu) 43548932Smccanne return (EMSGSIZE); 43647584Smccanne 437*49202Smccanne error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst); 43847584Smccanne if (error) 43948932Smccanne return (error); 44047584Smccanne 44147584Smccanne s = splnet(); 44247584Smccanne error = (*ifp->if_output)(ifp, m, &dst); 44347584Smccanne splx(s); 44447584Smccanne /* 44547584Smccanne * The driver frees the mbuf. 44647584Smccanne */ 44748932Smccanne return (error); 44847584Smccanne } 44947584Smccanne 45047584Smccanne /* 45148932Smccanne * Reset a descriptor by flushing its packet bufferand clearing the receive 45248932Smccanne * and drop counts. Should be called at splimp. 45347584Smccanne */ 45447584Smccanne static void 45547584Smccanne reset_d(d) 45647584Smccanne struct bpf_d *d; 45747584Smccanne { 45847584Smccanne if (d->bd_hbuf) { 45947584Smccanne /* Free the hold buffer. */ 46047584Smccanne d->bd_fbuf = d->bd_hbuf; 46147584Smccanne d->bd_hbuf = 0; 46247584Smccanne } 46348932Smccanne d->bd_slen = 0; 46447584Smccanne d->bd_rcount = 0; 46547584Smccanne d->bd_dcount = 0; 46647584Smccanne } 46747584Smccanne 46847584Smccanne /* 46947584Smccanne * FIONREAD Check for read packet available. 47047584Smccanne * SIOCGIFADDR Get interface address - convenient hook to driver. 47147584Smccanne * BIOCGFLEN Get max filter len. 47247584Smccanne * BIOCGBLEN Get buffer len [for read()]. 47347584Smccanne * BIOCSETF Set ethernet read filter. 47447584Smccanne * BIOCFLUSH Flush read packet buffer. 47547584Smccanne * BIOCPROMISC Put interface into promiscuous mode. 476*49202Smccanne * BIOCGDLT Get link layer type. 47747584Smccanne * BIOCGETIF Get interface name. 47847584Smccanne * BIOCSETIF Set interface. 47947584Smccanne * BIOCSRTIMEOUT Set read timeout. 48047584Smccanne * BIOCGRTIMEOUT Get read timeout. 48147584Smccanne * BIOCGSTATS Get packet stats. 48247584Smccanne * BIOCIMMEDIATE Set immediate mode. 48347584Smccanne */ 48447584Smccanne /* ARGSUSED */ 48547584Smccanne int 48647584Smccanne bpfioctl(dev, cmd, addr, flag) 48747584Smccanne dev_t dev; 48847584Smccanne int cmd; 48947584Smccanne caddr_t addr; 49047584Smccanne int flag; 49147584Smccanne { 49247584Smccanne register struct bpf_d *d = &bpf_dtab[minor(dev)]; 49347584Smccanne int s, error = 0; 49447584Smccanne 49547584Smccanne switch (cmd) { 49647584Smccanne 49747584Smccanne default: 49847584Smccanne error = EINVAL; 49947584Smccanne break; 50047584Smccanne 50147584Smccanne /* 50247584Smccanne * Check for read packet available. 50347584Smccanne */ 50447584Smccanne case FIONREAD: 50547584Smccanne { 50647584Smccanne int n; 50747584Smccanne 50847584Smccanne s = splimp(); 50948932Smccanne n = d->bd_slen; 51047584Smccanne if (d->bd_hbuf) 51148932Smccanne n += d->bd_hlen; 51247584Smccanne splx(s); 51347584Smccanne 51447584Smccanne *(int *)addr = n; 51547584Smccanne break; 51647584Smccanne } 51747584Smccanne 51847584Smccanne case SIOCGIFADDR: 51947584Smccanne { 52047584Smccanne struct ifnet *ifp; 52147584Smccanne 52247584Smccanne if (d->bd_bif == 0) 52347584Smccanne error = EINVAL; 52447584Smccanne else { 52547584Smccanne ifp = d->bd_bif->bif_ifp; 52647584Smccanne error = (*ifp->if_ioctl)(ifp, cmd, addr); 52747584Smccanne } 52847584Smccanne break; 52947584Smccanne } 53047584Smccanne 53147584Smccanne /* 53247584Smccanne * Get max filter len. 53347584Smccanne */ 53447584Smccanne case BIOCGFLEN: 53548932Smccanne *(u_int *)addr = BPF_MAXINSNS; 53647584Smccanne break; 53747584Smccanne /* 53847584Smccanne * Get buffer len [for read()]. 53947584Smccanne */ 54047584Smccanne case BIOCGBLEN: 54148932Smccanne *(u_int *)addr = d->bd_bufsize; 54247584Smccanne break; 54347584Smccanne 54447584Smccanne /* 54547584Smccanne * Set ethernet read filter. 54647584Smccanne */ 54747584Smccanne case BIOCSETF: 54847584Smccanne error = bpf_setf(d, (struct bpf_program *)addr); 54947584Smccanne break; 55047584Smccanne 55147584Smccanne /* 55247584Smccanne * Flush read packet buffer. 55347584Smccanne */ 55447584Smccanne case BIOCFLUSH: 55547584Smccanne s = splimp(); 55647584Smccanne reset_d(d); 55747584Smccanne splx(s); 55847584Smccanne break; 55947584Smccanne 56047584Smccanne /* 56147584Smccanne * Put interface into promiscuous mode. 56247584Smccanne */ 56347584Smccanne case BIOCPROMISC: 56447584Smccanne if (d->bd_bif == 0) { 56547584Smccanne /* 56647584Smccanne * No interface attached yet. 56747584Smccanne */ 56847584Smccanne error = EINVAL; 56947584Smccanne break; 57047584Smccanne } 57147584Smccanne s = splimp(); 57247584Smccanne if (d->bd_promisc == 0) { 57347584Smccanne d->bd_promisc = 1; 57447584Smccanne error = ifpromisc(d->bd_bif->bif_ifp, 1); 57547584Smccanne } 57647584Smccanne splx(s); 57747584Smccanne break; 57847584Smccanne 57947584Smccanne /* 58047584Smccanne * Get device parameters. 58147584Smccanne */ 582*49202Smccanne case BIOCGDLT: 58347584Smccanne if (d->bd_bif == 0) 58447584Smccanne error = EINVAL; 58547584Smccanne else 586*49202Smccanne *(u_int *)addr = d->bd_bif->bif_dlt; 58747584Smccanne break; 58847584Smccanne 58947584Smccanne /* 59047584Smccanne * Set interface name. 59147584Smccanne */ 59247584Smccanne case BIOCGETIF: 59347584Smccanne if (d->bd_bif == 0) 59447584Smccanne error = EINVAL; 59547584Smccanne else 59647584Smccanne bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr); 59747584Smccanne break; 59847584Smccanne 59947584Smccanne /* 60047584Smccanne * Set interface. 60147584Smccanne */ 60247584Smccanne case BIOCSETIF: 60347584Smccanne error = bpf_setif(d, (struct ifreq *)addr); 60447584Smccanne break; 60547584Smccanne 60647584Smccanne /* 60747584Smccanne * Set read timeout. 60847584Smccanne */ 60947584Smccanne case BIOCSRTIMEOUT: 61047584Smccanne { 61147584Smccanne struct timeval *tv = (struct timeval *)addr; 61247584Smccanne u_long msec; 61347584Smccanne 61447584Smccanne /* Compute number of milliseconds. */ 61547584Smccanne msec = tv->tv_sec * 1000 + tv->tv_usec / 1000; 61647584Smccanne /* Scale milliseconds to ticks. Assume hard 61747584Smccanne clock has millisecond or greater resolution 61847584Smccanne (i.e. tick >= 1000). For 10ms hardclock, 61947584Smccanne tick/1000 = 10, so rtout<-msec/10. */ 62047584Smccanne d->bd_rtout = msec / (tick / 1000); 62147584Smccanne break; 62247584Smccanne } 62347584Smccanne 62447584Smccanne /* 62547584Smccanne * Get read timeout. 62647584Smccanne */ 62747584Smccanne case BIOCGRTIMEOUT: 62847584Smccanne { 62947584Smccanne struct timeval *tv = (struct timeval *)addr; 63047584Smccanne u_long msec = d->bd_rtout; 63147584Smccanne 63247584Smccanne msec *= tick / 1000; 63347584Smccanne tv->tv_sec = msec / 1000; 63447584Smccanne tv->tv_usec = msec % 1000; 63547584Smccanne break; 63647584Smccanne } 63747584Smccanne 63847584Smccanne /* 63947584Smccanne * Get packet stats. 64047584Smccanne */ 64147584Smccanne case BIOCGSTATS: 64247584Smccanne { 64347584Smccanne struct bpf_stat *bs = (struct bpf_stat *)addr; 64447584Smccanne 64547584Smccanne bs->bs_recv = d->bd_rcount; 64647584Smccanne bs->bs_drop = d->bd_dcount; 64747584Smccanne break; 64847584Smccanne } 64947584Smccanne 65047584Smccanne /* 65147584Smccanne * Set immediate mode. 65247584Smccanne */ 65347584Smccanne case BIOCIMMEDIATE: 65447584Smccanne d->bd_immediate = *(u_int *)addr; 65547584Smccanne break; 65647584Smccanne } 65748932Smccanne return (error); 65847584Smccanne } 65947584Smccanne 66047584Smccanne /* 66147584Smccanne * Set d's packet filter program to 'fp'. If 'd' already has a filter, 66248932Smccanne * free it and replace it. Returns EINVAL for bogus requests. 66347584Smccanne */ 66447584Smccanne int 66547584Smccanne bpf_setf(d, fp) 66647584Smccanne struct bpf_d *d; 66747584Smccanne struct bpf_program *fp; 66847584Smccanne { 66948932Smccanne struct bpf_insn *fcode, *old; 67047584Smccanne u_int flen, size; 67147584Smccanne int s; 67247584Smccanne 67348932Smccanne old = d->bd_filter; 67447584Smccanne if (fp->bf_insns == 0) { 67547584Smccanne if (fp->bf_len != 0) 67648932Smccanne return (EINVAL); 67748932Smccanne s = splimp(); 67848967Smccanne d->bd_filter = 0; 67947584Smccanne reset_d(d); 68047584Smccanne splx(s); 68148967Smccanne if (old != 0) 68248932Smccanne free((caddr_t)old, M_DEVBUF); 68348932Smccanne return (0); 68447584Smccanne } 68547584Smccanne flen = fp->bf_len; 68648932Smccanne if (flen > BPF_MAXINSNS) 68748932Smccanne return (EINVAL); 68848932Smccanne 68947584Smccanne size = flen * sizeof(*fp->bf_insns); 69048932Smccanne fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK); 69148932Smccanne if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size)) 69248932Smccanne return (EINVAL); 69347584Smccanne 69447584Smccanne if (bpf_validate(fcode, (int)flen)) { 69548967Smccanne s = splimp(); 69648932Smccanne d->bd_filter = fcode; 69747584Smccanne reset_d(d); 69847584Smccanne splx(s); 69948967Smccanne if (old != 0) 70048932Smccanne free((caddr_t)old, M_DEVBUF); 70147584Smccanne 70248932Smccanne return (0); 70347584Smccanne } 70448932Smccanne free((caddr_t)fcode, M_DEVBUF); 70548932Smccanne return (EINVAL); 70647584Smccanne } 70747584Smccanne 70847584Smccanne /* 70947584Smccanne * Detach 'd' from its current interface (if attached at all) and attach to 71047584Smccanne * the interface named 'name'. Return ioctl error code or 0. 71147584Smccanne */ 71247584Smccanne static int 71347584Smccanne bpf_setif(d, ifr) 71447584Smccanne struct bpf_d *d; 71547584Smccanne struct ifreq *ifr; 71647584Smccanne { 71747584Smccanne struct bpf_if *bp; 71847584Smccanne char *cp; 719*49202Smccanne int unit, s; 72047584Smccanne 72147584Smccanne /* 72247584Smccanne * Separate string into name part and unit number. Put a null 72347584Smccanne * byte at the end of the name part, and compute the number. 72447584Smccanne * If the a unit number is unspecified, the default is 0, 72548932Smccanne * as initialized above. XXX This should be common code. 72647584Smccanne */ 72747584Smccanne unit = 0; 72847584Smccanne cp = ifr->ifr_name; 72947584Smccanne cp[sizeof(ifr->ifr_name) - 1] = '\0'; 73047584Smccanne while (*cp++) { 73147584Smccanne if (*cp >= '0' && *cp <= '9') { 73247584Smccanne unit = *cp - '0'; 73347584Smccanne *cp++ = '\0'; 73447584Smccanne while (*cp) 73547584Smccanne unit = 10 * unit + *cp++ - '0'; 73647584Smccanne break; 73747584Smccanne } 73847584Smccanne } 73947584Smccanne /* 74047584Smccanne * Look through attached interfaces for the named one. 74147584Smccanne */ 742*49202Smccanne for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) { 74347584Smccanne struct ifnet *ifp = bp->bif_ifp; 74447584Smccanne 74547584Smccanne if (ifp == 0 || unit != ifp->if_unit 74647584Smccanne || strcmp(ifp->if_name, ifr->ifr_name) != 0) 74747584Smccanne continue; 74847584Smccanne /* 74947584Smccanne * We found the requested interface. If we're 75047584Smccanne * already attached to it, just flush the buffer. 75147584Smccanne * If it's not up, return an error. 75247584Smccanne */ 75347584Smccanne if ((ifp->if_flags & IFF_UP) == 0) 75448932Smccanne return (ENETDOWN); 75547584Smccanne s = splimp(); 75647584Smccanne if (bp != d->bd_bif) { 75747584Smccanne if (d->bd_bif) 75847584Smccanne /* 75948932Smccanne * Detach if attached to something else. 76047584Smccanne */ 76147584Smccanne bpf_detachd(d); 76247584Smccanne 76347584Smccanne bpf_attachd(d, bp); 76447584Smccanne } 76547584Smccanne reset_d(d); 76647584Smccanne splx(s); 76748932Smccanne return (0); 76847584Smccanne } 76947584Smccanne /* Not found. */ 77048932Smccanne return (ENXIO); 77147584Smccanne } 77247584Smccanne 77347584Smccanne /* 77447584Smccanne * Lookup the name of the 'ifp' interface and return it in 'ifr->ifr_name'. 77547584Smccanne * We augment the ifp's base name with its unit number. 77647584Smccanne */ 77747584Smccanne static void 77847584Smccanne bpf_ifname(ifp, ifr) 77947584Smccanne struct ifnet *ifp; 78047584Smccanne struct ifreq *ifr; 78147584Smccanne { 78247584Smccanne char *s = ifp->if_name; 78347584Smccanne char *d = ifr->ifr_name; 78447584Smccanne 78547584Smccanne while (*d++ = *s++) 78647584Smccanne ; 78748932Smccanne /* XXX Assume that unit number is less than 10. */ 78847584Smccanne *d++ = ifp->if_unit + '0'; 78947584Smccanne *d = '\0'; 79047584Smccanne } 79147584Smccanne 79247584Smccanne /* 79347584Smccanne * Support for select() system call 79447584Smccanne * Inspired by the code in tty.c for the same purpose. 79547584Smccanne * 79647584Smccanne * bpfselect - returns true iff the specific operation 79747584Smccanne * will not block indefinitely. Otherwise, return 79847584Smccanne * false but make a note that a selwakeup() must be done. 79947584Smccanne */ 80047584Smccanne int 80148932Smccanne bpfselect(dev, rw, p) 80247584Smccanne register dev_t dev; 80347584Smccanne int rw; 80448932Smccanne struct proc *p; 80547584Smccanne { 80647584Smccanne register struct bpf_d *d; 80747584Smccanne register int s; 80847584Smccanne 80947584Smccanne if (rw != FREAD) 81048932Smccanne return (0); 81147584Smccanne /* 81247584Smccanne * An imitation of the FIONREAD ioctl code. 81347584Smccanne */ 81447584Smccanne d = &bpf_dtab[minor(dev)]; 81547584Smccanne 81647584Smccanne s = splimp(); 81748932Smccanne if (d->bd_slen != 0 || d->bd_hbuf && d->bd_hlen != 0) { 81847584Smccanne /* 81947584Smccanne * There is data waiting. 82047584Smccanne */ 82147584Smccanne splx(s); 82248932Smccanne return (1); 82347584Smccanne } 82447584Smccanne /* 82547584Smccanne * No data ready. If there's already a select() waiting on this 82647584Smccanne * minor device then this is a collision. This shouldn't happen 82747584Smccanne * because minors really should not be shared, but if a process 82847584Smccanne * forks while one of these is open, it is possible that both 82947584Smccanne * processes could select on the same descriptor. 83047584Smccanne */ 83148932Smccanne if (d->bd_selproc && d->bd_selproc->p_wchan == (caddr_t)&selwait) 83248932Smccanne d->bd_selcoll = 1; 83347584Smccanne else 83448932Smccanne d->bd_selproc = p; 83548932Smccanne 83647584Smccanne splx(s); 83748932Smccanne return (0); 83847584Smccanne } 83947584Smccanne 84047584Smccanne /* 84147584Smccanne * bpf_tap - incoming linkage from device drivers 84247584Smccanne */ 84347584Smccanne void 84448932Smccanne bpf_tap(arg, pkt, pktlen) 84547584Smccanne caddr_t arg; 84648932Smccanne register u_char *pkt; 84748932Smccanne register u_int pktlen; 84847584Smccanne { 84947584Smccanne struct bpf_if *bp; 85047584Smccanne register struct bpf_d *d; 85147584Smccanne register u_int slen; 85247584Smccanne /* 85347584Smccanne * Note that the ipl does not have to be raised at this point. 85447584Smccanne * The only problem that could arise here is that if two different 85547584Smccanne * interfaces shared any data. This is not the case. 85647584Smccanne */ 85747584Smccanne bp = (struct bpf_if *)arg; 85847584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 85947584Smccanne ++d->bd_rcount; 860*49202Smccanne if (d->bd_filter == 0) { 861*49202Smccanne catchpacket(d, pkt, pktlen, (u_int)-1, bcopy); 862*49202Smccanne continue; 863*49202Smccanne } 864*49202Smccanne slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen); 86547584Smccanne if (slen != 0) 866*49202Smccanne catchpacket(d, pkt, pktlen, slen, bcopy); 86747584Smccanne } 86847584Smccanne } 86947584Smccanne 87047584Smccanne /* 87147584Smccanne * Copy data from an mbuf chain into a buffer. This code is derived 87247584Smccanne * from m_copydata in sys/uipc_mbuf.c. 87347584Smccanne */ 87447584Smccanne static void 875*49202Smccanne bpf_mcopy(src, dst, len) 87647584Smccanne u_char *src; 87747584Smccanne u_char *dst; 87847584Smccanne register int len; 87947584Smccanne { 88047584Smccanne register struct mbuf *m = (struct mbuf *)src; 88147584Smccanne register unsigned count; 88247584Smccanne 88347584Smccanne while (len > 0) { 88447584Smccanne if (m == 0) 885*49202Smccanne panic("bpf_mcopy"); 88647584Smccanne count = MIN(m->m_len, len); 887*49202Smccanne bcopy(mtod(m, caddr_t), (caddr_t)dst, count); 888*49202Smccanne m = m->m_next; 889*49202Smccanne dst += count; 89047584Smccanne len -= count; 89147584Smccanne } 89247584Smccanne } 89347584Smccanne 89447584Smccanne /* 89548932Smccanne * Length of ethernet and TCP/IP header with no IP options. 89647584Smccanne */ 89747584Smccanne #define BPF_MIN_SNAPLEN 50 89847584Smccanne 89947584Smccanne /* 90047584Smccanne * bpf_mtap - incoming linkage from device drivers, when packet 90147584Smccanne * is in an mbuf chain 90247584Smccanne */ 90347584Smccanne void 904*49202Smccanne bpf_mtap(arg, m) 90547584Smccanne caddr_t arg; 906*49202Smccanne struct mbuf *m; 90747584Smccanne { 90847584Smccanne struct bpf_if *bp = (struct bpf_if *)arg; 90947584Smccanne struct bpf_d *d; 910*49202Smccanne u_int pktlen, slen; 911*49202Smccanne struct mbuf *m0; 912*49202Smccanne #ifdef notdef 91347584Smccanne u_char *cp; 91447584Smccanne int nbytes; 91548932Smccanne static u_char buf[BPF_MIN_SNAPLEN]; 91647584Smccanne 917*49202Smccanne if (m->m_len >= BPF_MIN_SNAPLEN) { 918*49202Smccanne slen = m->m_len; 919*49202Smccanne cp = mtod(m, u_char *); 92047584Smccanne } 92147584Smccanne else { 92247584Smccanne nbytes = BPF_MIN_SNAPLEN; 92347584Smccanne cp = buf; 924*49202Smccanne m0 = m; 925*49202Smccanne while (m0 && nbytes > 0) { 926*49202Smccanne slen = MIN(m0->m_len, nbytes); 927*49202Smccanne bcopy(mtod(m0, char *), (char *)cp, slen); 92847584Smccanne cp += slen; 92947584Smccanne nbytes -= slen; 930*49202Smccanne m0 = m0->m_next; 93147584Smccanne } 93247584Smccanne if (nbytes > 0) 93347584Smccanne /* Packet too small? */ 93447584Smccanne return; 93547584Smccanne 93647584Smccanne slen = BPF_MIN_SNAPLEN; 93747584Smccanne cp = buf; 93847584Smccanne } 939*49202Smccanne #endif 94048932Smccanne pktlen = 0; 941*49202Smccanne m0 = m; 942*49202Smccanne while (m0) { 943*49202Smccanne pktlen += m0->m_len; 944*49202Smccanne m0 = m0->m_next; 94547584Smccanne } 94647584Smccanne for (d = bp->bif_dlist; d != 0; d = d->bd_next) { 94747584Smccanne ++d->bd_rcount; 948*49202Smccanne if (d->bd_filter == 0) { 949*49202Smccanne catchpacket(d, (u_char *)m, pktlen, (u_int)-1, 950*49202Smccanne bpf_mcopy); 951*49202Smccanne continue; 952*49202Smccanne } 953*49202Smccanne slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0); 95447584Smccanne if (slen != 0) 955*49202Smccanne catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy); 95647584Smccanne } 95747584Smccanne } 95847584Smccanne 95947584Smccanne /* 960*49202Smccanne * Move the packet data from interface memory (pkt) into the 96147584Smccanne * store buffer. Return 1 if it's time to wakeup a listener (buffer full), 96247584Smccanne * otherwise 0. 'copy' is the routine called to do the actual data 96347584Smccanne * transfer. 'bcopy' is passed in to copy contiguous chunks, while 964*49202Smccanne * 'bpf_mcopy' is passed in to copy mbuf chains. In the latter 96548932Smccanne * case, 'pkt' is really an mbuf. 96647584Smccanne */ 96747584Smccanne static void 96848932Smccanne catchpacket(d, pkt, pktlen, snaplen, cpfn) 96948932Smccanne register struct bpf_d *d; 97048932Smccanne register u_char *pkt; 97148932Smccanne register u_int pktlen, snaplen; 97248932Smccanne register void (*cpfn)(); 97347584Smccanne { 97448932Smccanne register struct bpf_hdr *hp; 97548932Smccanne register int totlen, curlen; 97648932Smccanne register int hdrlen = d->bd_bif->bif_hdrlen; 97747584Smccanne /* 97847584Smccanne * Figure out how many bytes to move. If the packet is 97947584Smccanne * greater or equal to the snapshot length, transfer that 98047584Smccanne * much. Otherwise, transfer the whole packet (unless 98148932Smccanne * we hit the buffer size limit). 98247584Smccanne */ 98348932Smccanne if (snaplen <= pktlen) 98447584Smccanne totlen = snaplen + hdrlen; 98547584Smccanne else { 98648932Smccanne totlen = pktlen + hdrlen; 98748932Smccanne if (totlen > d->bd_bufsize) 98848932Smccanne totlen = d->bd_bufsize; 98947584Smccanne } 99047584Smccanne 99147584Smccanne /* 99247584Smccanne * Round up the end of the previous packet to the next longword. 99347584Smccanne */ 99448932Smccanne curlen = BPF_WORDALIGN(d->bd_slen); 99548932Smccanne if (curlen + totlen > d->bd_bufsize) { 99647584Smccanne /* 99747584Smccanne * This packet will overflow the storage buffer. 99848932Smccanne * Rotate the buffers if we can, then wakeup any 99948932Smccanne * pending reads. 100047584Smccanne */ 100147584Smccanne if (d->bd_fbuf == 0) { 100247584Smccanne /* 100348932Smccanne * We haven't completed the previous read yet, 100448932Smccanne * so drop the packet. 100547584Smccanne */ 100647584Smccanne ++d->bd_dcount; 100747584Smccanne return; 100847584Smccanne } 100948932Smccanne ROTATE_BUFFERS(d); 101047584Smccanne bpf_wakeup(d); 101148932Smccanne curlen = 0; 101247584Smccanne } 101348932Smccanne else if (d->bd_immediate) 101447584Smccanne /* 101547584Smccanne * Immediate mode is set. A packet arrived so any 101647584Smccanne * reads should be woken up. 101747584Smccanne */ 101847584Smccanne bpf_wakeup(d); 101948932Smccanne 102047584Smccanne /* 102147584Smccanne * Append the bpf header. 102247584Smccanne */ 102348932Smccanne hp = (struct bpf_hdr *)(d->bd_sbuf + curlen); 102447584Smccanne #ifdef sun 102547584Smccanne uniqtime(&hp->bh_tstamp); 102647584Smccanne #else 102747584Smccanne #ifdef hp300 102847584Smccanne microtime(&hp->bh_tstamp); 102947584Smccanne #else 103047584Smccanne hp->bh_tstamp = time; 103147584Smccanne #endif 103247584Smccanne #endif 103348932Smccanne hp->bh_datalen = pktlen; 103447584Smccanne hp->bh_hdrlen = hdrlen; 103547584Smccanne /* 103648932Smccanne * Copy the packet data into the store buffer and update its length. 103747584Smccanne */ 103848932Smccanne (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen)); 103948932Smccanne d->bd_slen = curlen + totlen; 104047584Smccanne } 104147584Smccanne 104247584Smccanne /* 104347584Smccanne * Initialize all nonzero fields of a descriptor. 104447584Smccanne */ 104547584Smccanne static int 104647584Smccanne bpf_initd(d) 104747584Smccanne register struct bpf_d *d; 104847584Smccanne { 104948932Smccanne d->bd_bufsize = bpf_bufsize; 105048932Smccanne d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 105148932Smccanne if (d->bd_fbuf == 0) 105248932Smccanne return (ENOBUFS); 105347584Smccanne 105448932Smccanne d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_WAITOK); 105548932Smccanne if (d->bd_sbuf == 0) { 105648932Smccanne free(d->bd_fbuf, M_DEVBUF); 105748932Smccanne return (ENOBUFS); 105847584Smccanne } 105948932Smccanne d->bd_slen = 0; 106048932Smccanne d->bd_hlen = 0; 106148932Smccanne return (0); 106247584Smccanne } 106347584Smccanne 106447584Smccanne /* 1065*49202Smccanne * Register 'ifp' with bpf. XXX 106647584Smccanne * and 'driverp' is a pointer to the 'struct bpf_if *' in the driver's softc. 106747584Smccanne */ 106847584Smccanne void 1069*49202Smccanne bpfattach(driverp, ifp, dlt, hdrlen) 107047584Smccanne caddr_t *driverp; 107147584Smccanne struct ifnet *ifp; 1072*49202Smccanne u_int dlt, hdrlen; 107347584Smccanne { 107447584Smccanne struct bpf_if *bp; 107547584Smccanne int i; 107647584Smccanne 1077*49202Smccanne bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT); 1078*49202Smccanne if (bp == 0) 1079*49202Smccanne panic("bpfattach"); 108047584Smccanne 108147584Smccanne bp->bif_dlist = 0; 108247584Smccanne bp->bif_driverp = (struct bpf_if **)driverp; 108347584Smccanne bp->bif_ifp = ifp; 1084*49202Smccanne bp->bif_dlt = dlt; 108547584Smccanne 1086*49202Smccanne bp->bif_next = bpf_iflist; 1087*49202Smccanne bpf_iflist = bp; 1088*49202Smccanne 108948932Smccanne *bp->bif_driverp = 0; 109048932Smccanne 109147584Smccanne /* 109247584Smccanne * Compute the length of the bpf header. This is not necessarily 109347584Smccanne * equal to SIZEOF_BPF_HDR because we want to insert spacing such 109447584Smccanne * that the network layer header begins on a longword boundary (for 109547584Smccanne * performance reasons and to alleviate alignment restrictions). 109647584Smccanne */ 1097*49202Smccanne bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen; 109847584Smccanne 109947584Smccanne /* 110047584Smccanne * Mark all the descriptors free if this hasn't been done. 110147584Smccanne */ 110247584Smccanne if (!D_ISFREE(&bpf_dtab[0])) 110347584Smccanne for (i = 0; i < NBPFILTER; ++i) 110447584Smccanne D_MARKFREE(&bpf_dtab[i]); 110547584Smccanne 110647584Smccanne printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit); 110747584Smccanne } 110847584Smccanne 110948967Smccanne /* XXX This routine belongs in net/if.c. */ 111048932Smccanne /* 111148932Smccanne * Set/clear promiscuous mode on interface ifp based on the truth value` 111248932Smccanne * of pswitch. The calls are reference counted so that only the first 111348932Smccanne * on request actually has an effect, as does the final off request. 111448932Smccanne * Results are undefined if the off and on requests are not matched. 111548932Smccanne */ 111648932Smccanne int 111748932Smccanne ifpromisc(ifp, pswitch) 111848932Smccanne struct ifnet *ifp; 111948932Smccanne int pswitch; 112048932Smccanne { 112148932Smccanne /* 112248932Smccanne * If the device is not configured up, we cannot put it in 112348932Smccanne * promiscuous mode. 112448932Smccanne */ 112548932Smccanne if ((ifp->if_flags & IFF_UP) == 0) 112648932Smccanne return (ENETDOWN); 112748932Smccanne 112848932Smccanne if (pswitch) { 112948932Smccanne if (ifp->if_pcount++ != 0) 113048932Smccanne return (0); 113148932Smccanne ifp->if_flags |= IFF_PROMISC; 113248932Smccanne } else { 113348932Smccanne if (--ifp->if_pcount > 0) 113448932Smccanne return (0); 113548932Smccanne ifp->if_flags &= ~IFF_PROMISC; 113648932Smccanne } 113748932Smccanne return ((*ifp->if_ioctl)(ifp, SIOCSIFFLAGS, (caddr_t)0)); 113848932Smccanne } 113948932Smccanne 114047584Smccanne #endif (NBPFILTER > 0) 1141