Annotation of XNU/bsd/net/bpf.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * The contents of this file constitute Original Code as defined in and
        !             7:  * are subject to the Apple Public Source License Version 1.1 (the
        !             8:  * "License").  You may not use this file except in compliance with the
        !             9:  * License.  Please obtain a copy of the License at
        !            10:  * http://www.apple.com/publicsource and read it before using this file.
        !            11:  * 
        !            12:  * This Original Code and all software distributed under the License are
        !            13:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            14:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            15:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            16:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            17:  * License for the specific language governing rights and limitations
        !            18:  * under the License.
        !            19:  * 
        !            20:  * @APPLE_LICENSE_HEADER_END@
        !            21:  */
        !            22: /*
        !            23:  * Copyright (c) 1990, 1991, 1993
        !            24:  *     The Regents of the University of California.  All rights reserved.
        !            25:  *
        !            26:  * This code is derived from the Stanford/CMU enet packet filter,
        !            27:  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
        !            28:  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
        !            29:  * Berkeley Laboratory.
        !            30:  *
        !            31:  * Redistribution and use in source and binary forms, with or without
        !            32:  * modification, are permitted provided that the following conditions
        !            33:  * are met:
        !            34:  * 1. Redistributions of source code must retain the above copyright
        !            35:  *    notice, this list of conditions and the following disclaimer.
        !            36:  * 2. Redistributions in binary form must reproduce the above copyright
        !            37:  *    notice, this list of conditions and the following disclaimer in the
        !            38:  *    documentation and/or other materials provided with the distribution.
        !            39:  * 3. All advertising materials mentioning features or use of this software
        !            40:  *    must display the following acknowledgement:
        !            41:  *     This product includes software developed by the University of
        !            42:  *     California, Berkeley and its contributors.
        !            43:  * 4. Neither the name of the University nor the names of its contributors
        !            44:  *    may be used to endorse or promote products derived from this software
        !            45:  *    without specific prior written permission.
        !            46:  *
        !            47:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
        !            48:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
        !            49:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
        !            50:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
        !            51:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
        !            52:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
        !            53:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
        !            54:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
        !            55:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
        !            56:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
        !            57:  * SUCH DAMAGE.
        !            58:  *
        !            59:  *      @(#)bpf.c      8.2 (Berkeley) 3/28/94
        !            60:  *
        !            61:  */
        !            62: 
        !            63: #include "bpfilter.h"
        !            64: 
        !            65: #if NBPFILTER > 0
        !            66: 
        !            67: #ifndef __GNUC__
        !            68: #define inline
        !            69: #else
        !            70: #define inline __inline
        !            71: #endif
        !            72: 
        !            73: #include <sys/param.h>
        !            74: #include <sys/systm.h>
        !            75: #include <sys/conf.h>
        !            76: #include <sys/malloc.h>
        !            77: #include <sys/mbuf.h>
        !            78: #include <sys/time.h>
        !            79: #include <sys/proc.h>
        !            80: 
        !            81: 
        !            82: #include <sys/poll.h>
        !            83: 
        !            84: 
        !            85: #include <sys/signalvar.h>
        !            86: #include <sys/filio.h>
        !            87: #include <sys/sockio.h>
        !            88: #include <sys/ttycom.h>
        !            89: #include <sys/filedesc.h>
        !            90: 
        !            91: #include <sys/socket.h>
        !            92: #include <sys/vnode.h>
        !            93: 
        !            94: #include <net/if.h>
        !            95: #include <net/bpf.h>
        !            96: #include <net/bpfdesc.h>
        !            97: 
        !            98: #include <netinet/in.h>
        !            99: #include <netinet/if_ether.h>
        !           100: #include <sys/kernel.h>
        !           101: #include <sys/sysctl.h>
        !           102: 
        !           103: 
        !           104: #include <miscfs/devfs/devfs.h>
        !           105: #include <net/dlil.h>
        !           106: 
        !           107: /*
        !           108:  * Older BSDs don't have kernel malloc.
        !           109:  */
        !           110: #if BSD < 199103
        !           111: extern bcopy();
        !           112: static caddr_t bpf_alloc();
        !           113: 
        !           114: #define BPF_BUFSIZE (MCLBYTES-8)
        !           115: #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, code, uio)
        !           116: #else
        !           117: #define BPF_BUFSIZE 4096
        !           118: #define UIOMOVE(cp, len, code, uio) uiomove(cp, len, uio)
        !           119: #endif
        !           120: 
        !           121: #define PRINET  26                     /* interruptible */
        !           122: 
        !           123: /*
        !           124:  * The default read buffer size is patchable.
        !           125:  */
        !           126: static int bpf_bufsize = BPF_BUFSIZE;
        !           127: 
        !           128: 
        !           129: 
        !           130: SYSCTL_INT(_debug, OID_AUTO, bpf_bufsize, CTLFLAG_RW, 
        !           131:        &bpf_bufsize, 0, "");
        !           132: 
        !           133: 
        !           134: /*
        !           135:  *  bpf_iflist is the list of interfaces; each corresponds to an ifnet
        !           136:  *  bpf_dtab holds the descriptors, indexed by minor device #
        !           137:  */
        !           138: static struct bpf_if   *bpf_iflist;
        !           139: static struct bpf_d    bpf_dtab[NBPFILTER];
        !           140: static int             bpf_dtab_init;
        !           141: static int             nbpfilter = NBPFILTER;
        !           142: 
        !           143: static int     bpf_allocbufs __P((struct bpf_d *));
        !           144: static void    bpf_attachd __P((struct bpf_d *d, struct bpf_if *bp));
        !           145: static void    bpf_detachd __P((struct bpf_d *d));
        !           146: static void    bpf_freed __P((struct bpf_d *));
        !           147: static void    bpf_ifname __P((struct ifnet *, struct ifreq *));
        !           148: static void    bpf_mcopy __P((const void *, void *, size_t));
        !           149: static int     bpf_movein __P((struct uio *, int,
        !           150:                    struct mbuf **, struct sockaddr *, int *));
        !           151: static int     bpf_setif __P((struct bpf_d *, struct ifreq *));
        !           152: static inline void
        !           153:                bpf_wakeup __P((struct bpf_d *));
        !           154: static void    catchpacket __P((struct bpf_d *, u_char *, u_int,
        !           155:                    u_int, void (*)(const void *, void *, size_t)));
        !           156: static void    reset_d __P((struct bpf_d *));
        !           157: static int      bpf_setf __P((struct bpf_d *, struct bpf_program *));
        !           158: 
        !           159:        d_open_t        bpfopen;
        !           160:        d_close_t       bpfclose;
        !           161:        d_read_t        bpfread;
        !           162:        d_write_t       bpfwrite;
        !           163:        d_ioctl_t       bpfioctl;
        !           164: 
        !           165: 
        !           166: #define BPF_MAJOR      7
        !           167: 
        !           168: void bpf_mtap(struct ifnet *, struct mbuf *);
        !           169: 
        !           170: int    bpfopen(), bpfclose(), bpfread(), bpfwrite(), bpfioctl(),
        !           171:                bpfpoll();
        !           172: 
        !           173: 
        !           174: static struct cdevsw bpf_cdevsw = {
        !           175:     bpfopen,   bpfclose,       bpfread,        bpfwrite,
        !           176:     bpfioctl,  nulldev,        nulldev,        NULL,           bpfpoll,
        !           177:     eno_mmap,  eno_strat,      eno_getc,       eno_putc,       0
        !           178: };
        !           179: 
        !           180: static int
        !           181: bpf_movein(uio, linktype, mp, sockp, datlen)
        !           182:        register struct uio *uio;
        !           183:        int linktype, *datlen;
        !           184:        register struct mbuf **mp;
        !           185:        register struct sockaddr *sockp;
        !           186: {
        !           187:        struct mbuf *m;
        !           188:        int error;
        !           189:        int len;
        !           190:        int hlen;
        !           191: 
        !           192:        /*
        !           193:         * Build a sockaddr based on the data link layer type.
        !           194:         * We do this at this level because the ethernet header
        !           195:         * is copied directly into the data field of the sockaddr.
        !           196:         * In the case of SLIP, there is no header and the packet
        !           197:         * is forwarded as is.
        !           198:         * Also, we are careful to leave room at the front of the mbuf
        !           199:         * for the link level header.
        !           200:         */
        !           201:        switch (linktype) {
        !           202: 
        !           203:        case DLT_SLIP:
        !           204:                sockp->sa_family = AF_INET;
        !           205:                hlen = 0;
        !           206:                break;
        !           207: 
        !           208:        case DLT_EN10MB:
        !           209:                sockp->sa_family = AF_UNSPEC;
        !           210:                /* XXX Would MAXLINKHDR be better? */
        !           211:                hlen = sizeof(struct ether_header);
        !           212:                break;
        !           213: 
        !           214:        case DLT_FDDI:
        !           215: #if defined(__FreeBSD__) || defined(__bsdi__)
        !           216:                sockp->sa_family = AF_IMPLINK;
        !           217:                hlen = 0;
        !           218: #else
        !           219:                sockp->sa_family = AF_UNSPEC;
        !           220:                /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
        !           221:                hlen = 24;
        !           222: #endif
        !           223:                break;
        !           224: 
        !           225:        case DLT_RAW:
        !           226:        case DLT_NULL:
        !           227:                sockp->sa_family = AF_UNSPEC;
        !           228:                hlen = 0;
        !           229:                break;
        !           230: 
        !           231: #ifdef __FreeBSD__
        !           232:        case DLT_ATM_RFC1483:
        !           233:                /*
        !           234:                 * en atm driver requires 4-byte atm pseudo header.
        !           235:                 * though it isn't standard, vpi:vci needs to be
        !           236:                 * specified anyway.
        !           237:                 */
        !           238:                sockp->sa_family = AF_UNSPEC;
        !           239:                hlen = 12;      /* XXX 4(ATM_PH) + 3(LLC) + 5(SNAP) */
        !           240:                break;
        !           241: #endif
        !           242: 
        !           243:        default:
        !           244:                return (EIO);
        !           245:        }
        !           246: 
        !           247:        len = uio->uio_resid;
        !           248:        *datlen = len - hlen;
        !           249:        if ((unsigned)len > MCLBYTES)
        !           250:                return (EIO);
        !           251: 
        !           252:        MGETHDR(m, M_WAIT, MT_DATA);
        !           253:        if (m == 0)
        !           254:                return (ENOBUFS);
        !           255:        if (len > MHLEN) {
        !           256: #if BSD >= 199103
        !           257:                MCLGET(m, M_WAIT);
        !           258:                if ((m->m_flags & M_EXT) == 0) {
        !           259: #else
        !           260:                MCLGET(m);
        !           261:                if (m->m_len != MCLBYTES) {
        !           262: #endif
        !           263:                        error = ENOBUFS;
        !           264:                        goto bad;
        !           265:                }
        !           266:        }
        !           267:        m->m_pkthdr.len = m->m_len = len;
        !           268:        m->m_pkthdr.rcvif = NULL;
        !           269:        *mp = m;
        !           270:        /*
        !           271:         * Make room for link header.
        !           272:         */
        !           273:        if (hlen != 0) {
        !           274:                m->m_pkthdr.len -= hlen;
        !           275:                m->m_len -= hlen;
        !           276: #if BSD >= 199103
        !           277:                m->m_data += hlen; /* XXX */
        !           278: #else
        !           279:                m->m_off += hlen;
        !           280: #endif
        !           281:                error = UIOMOVE((caddr_t)sockp->sa_data, hlen, UIO_WRITE, uio);
        !           282:                if (error)
        !           283:                        goto bad;
        !           284:        }
        !           285:        error = UIOMOVE(mtod(m, caddr_t), len - hlen, UIO_WRITE, uio);
        !           286:        if (!error)
        !           287:                return (0);
        !           288:  bad:
        !           289:        m_freem(m);
        !           290:        return (error);
        !           291: }
        !           292: 
        !           293: int bpf_tap_callback(struct ifnet *ifp, struct mbuf *m)
        !           294: {
        !           295:        bpf_mtap(ifp, m);
        !           296:        return 0;
        !           297: }
        !           298: 
        !           299: 
        !           300: /*
        !           301:  * Attach file to the bpf interface, i.e. make d listen on bp.
        !           302:  * Must be called at splimp.
        !           303:  */
        !           304: static void
        !           305: bpf_attachd(d, bp)
        !           306:        struct bpf_d *d;
        !           307:        struct bpf_if *bp;
        !           308: {
        !           309:        struct ifnet *ifp;
        !           310: 
        !           311:        /*
        !           312:         * Point d at bp, and add d to the interface's list of listeners.
        !           313:         * Finally, point the driver's bpf cookie at the interface so
        !           314:         * it will divert packets to bpf.
        !           315:         */
        !           316:        d->bd_bif = bp;
        !           317:        d->bd_next = bp->bif_dlist;
        !           318:        bp->bif_dlist = d;
        !           319: 
        !           320:        bp->bif_ifp->if_bpf = bp;
        !           321:        ifp = bp->bif_ifp;
        !           322: 
        !           323:        if (ifp->if_set_bpf_tap)
        !           324:                (*ifp->if_set_bpf_tap)(ifp, BPF_TAP_INPUT_OUTPUT, bpf_tap_callback);
        !           325: }
        !           326: 
        !           327: /*
        !           328:  * Detach a file from its interface.
        !           329:  */
        !           330: static void
        !           331: bpf_detachd(d)
        !           332:        struct bpf_d *d;
        !           333: {
        !           334:        struct bpf_d **p;
        !           335:        struct bpf_if *bp;
        !           336:        struct ifnet  *ifp;
        !           337: 
        !           338:        ifp = d->bd_bif->bif_ifp;
        !           339:        if (ifp->if_set_bpf_tap)
        !           340:                (*ifp->if_set_bpf_tap)(ifp, BPF_TAP_DISABLE, 0);
        !           341: 
        !           342:        bp = d->bd_bif;
        !           343:        /*
        !           344:         * Check if this descriptor had requested promiscuous mode.
        !           345:         * If so, turn it off.
        !           346:         */
        !           347:        if (d->bd_promisc) {
        !           348:                d->bd_promisc = 0;
        !           349:                if (ifpromisc(bp->bif_ifp, 0))
        !           350:                        /*
        !           351:                         * Something is really wrong if we were able to put
        !           352:                         * the driver into promiscuous mode, but can't
        !           353:                         * take it out.
        !           354:                         */
        !           355:                        panic("bpf: ifpromisc failed");
        !           356:        }
        !           357:        /* Remove d from the interface's descriptor list. */
        !           358:        p = &bp->bif_dlist;
        !           359:        while (*p != d) {
        !           360:                p = &(*p)->bd_next;
        !           361:                if (*p == 0)
        !           362:                        panic("bpf_detachd: descriptor not in list");
        !           363:        }
        !           364:        *p = (*p)->bd_next;
        !           365:        if (bp->bif_dlist == 0)
        !           366:                /*
        !           367:                 * Let the driver know that there are no more listeners.
        !           368:                 */
        !           369:                d->bd_bif->bif_ifp->if_bpf = 0;
        !           370:        d->bd_bif = 0;
        !           371: }
        !           372: 
        !           373: 
        !           374: /*
        !           375:  * Mark a descriptor free by making it point to itself.
        !           376:  * This is probably cheaper than marking with a constant since
        !           377:  * the address should be in a register anyway.
        !           378:  */
        !           379: #define D_ISFREE(d) ((d) == (d)->bd_next)
        !           380: #define D_MARKFREE(d) ((d)->bd_next = (d))
        !           381: #define D_MARKUSED(d) ((d)->bd_next = 0)
        !           382: 
        !           383: /*
        !           384:  * Open ethernet device.  Returns ENXIO for illegal minor device number,
        !           385:  * EBUSY if file is open by another process.
        !           386:  */
        !           387: /* ARGSUSED */
        !           388:        int
        !           389: bpfopen(dev, flags, fmt, p)
        !           390:        dev_t dev;
        !           391:        int flags;
        !           392:        int fmt;
        !           393:        struct proc *p;
        !           394: {
        !           395:        register struct bpf_d *d;
        !           396: 
        !           397:        if (minor(dev) >= nbpfilter)
        !           398:                return (ENXIO);
        !           399:        /*
        !           400:         * Each minor can be opened by only one process.  If the requested
        !           401:         * minor is in use, return EBUSY.
        !           402:         */
        !           403:        d = &bpf_dtab[minor(dev)];
        !           404:        if (!D_ISFREE(d))
        !           405:                return (EBUSY);
        !           406: 
        !           407:        /* Mark "free" and do most initialization. */
        !           408:        bzero((char *)d, sizeof(*d));
        !           409:        d->bd_bufsize = bpf_bufsize;
        !           410:        d->bd_sig = SIGIO;
        !           411: 
        !           412:        return (0);
        !           413: }
        !           414: 
        !           415: /*
        !           416:  * Close the descriptor by detaching it from its interface,
        !           417:  * deallocating its buffers, and marking it free.
        !           418:  */
        !           419: /* ARGSUSED */
        !           420:        int
        !           421: bpfclose(dev, flags, fmt, p)
        !           422:        dev_t dev;
        !           423:        int flags;
        !           424:        int fmt;
        !           425:        struct proc *p;
        !           426: {
        !           427:        register struct bpf_d *d = &bpf_dtab[minor(dev)];
        !           428:        register int s;
        !           429: 
        !           430: #if ISFB31
        !           431:        funsetown(d->bd_sigio);
        !           432: #endif
        !           433:        s = splimp();
        !           434:        if (d->bd_bif)
        !           435:                bpf_detachd(d);
        !           436:        splx(s);
        !           437:        bpf_freed(d);
        !           438: 
        !           439:        return (0);
        !           440: }
        !           441: 
        !           442: /*
        !           443:  * Support for SunOS, which does not have tsleep.
        !           444:  */
        !           445: #if BSD < 199103
        !           446: static
        !           447: bpf_timeout(arg)
        !           448:        caddr_t arg;
        !           449: {
        !           450:        struct bpf_d *d = (struct bpf_d *)arg;
        !           451:        d->bd_timedout = 1;
        !           452:        wakeup(arg);
        !           453: }
        !           454: 
        !           455: #define BPF_SLEEP(chan, pri, s, t) bpf_sleep((struct bpf_d *)chan)
        !           456: 
        !           457: int
        !           458: bpf_sleep(d)
        !           459:        register struct bpf_d *d;
        !           460: {
        !           461:        register int rto = d->bd_rtout;
        !           462:        register int st;
        !           463: 
        !           464:        if (rto != 0) {
        !           465:                d->bd_timedout = 0;
        !           466:                timeout(bpf_timeout, (caddr_t)d, rto);
        !           467:        }
        !           468:        st = sleep((caddr_t)d, PRINET|PCATCH);
        !           469:        if (rto != 0) {
        !           470:                if (d->bd_timedout == 0)
        !           471:                        untimeout(bpf_timeout, (caddr_t)d);
        !           472:                else if (st == 0)
        !           473:                        return EWOULDBLOCK;
        !           474:        }
        !           475:        return (st != 0) ? EINTR : 0;
        !           476: }
        !           477: #else
        !           478: #define BPF_SLEEP tsleep
        !           479: #endif
        !           480: 
        !           481: /*
        !           482:  * Rotate the packet buffers in descriptor d.  Move the store buffer
        !           483:  * into the hold slot, and the free buffer into the store slot.
        !           484:  * Zero the length of the new store buffer.
        !           485:  */
        !           486: #define ROTATE_BUFFERS(d) \
        !           487:        (d)->bd_hbuf = (d)->bd_sbuf; \
        !           488:        (d)->bd_hlen = (d)->bd_slen; \
        !           489:        (d)->bd_sbuf = (d)->bd_fbuf; \
        !           490:        (d)->bd_slen = 0; \
        !           491:        (d)->bd_fbuf = 0;
        !           492: /*
        !           493:  *  bpfread - read next chunk of packets from buffers
        !           494:  */
        !           495:        int
        !           496: bpfread(dev, uio, ioflag)
        !           497:        dev_t dev;
        !           498:        register struct uio *uio;
        !           499:        int ioflag;
        !           500: {
        !           501:        register struct bpf_d *d = &bpf_dtab[minor(dev)];
        !           502:        int error;
        !           503:        int s;
        !           504: 
        !           505:        /*
        !           506:         * Restrict application to use a buffer the same size as
        !           507:         * as kernel buffers.
        !           508:         */
        !           509:        if (uio->uio_resid != d->bd_bufsize)
        !           510:                return (EINVAL);
        !           511: 
        !           512:        s = splimp();
        !           513:        /*
        !           514:         * If the hold buffer is empty, then do a timed sleep, which
        !           515:         * ends when the timeout expires or when enough packets
        !           516:         * have arrived to fill the store buffer.
        !           517:         */
        !           518:        while (d->bd_hbuf == 0) {
        !           519:                if (d->bd_immediate && d->bd_slen != 0) {
        !           520:                        /*
        !           521:                         * A packet(s) either arrived since the previous
        !           522:                         * read or arrived while we were asleep.
        !           523:                         * Rotate the buffers and return what's here.
        !           524:                         */
        !           525:                        ROTATE_BUFFERS(d);
        !           526:                        break;
        !           527:                }
        !           528:                if (ioflag & IO_NDELAY)
        !           529:                        error = EWOULDBLOCK;
        !           530:                else
        !           531:                        error = BPF_SLEEP((caddr_t)d, PRINET|PCATCH, "bpf",
        !           532:                                          d->bd_rtout);
        !           533:                if (error == EINTR || error == ERESTART) {
        !           534:                        splx(s);
        !           535:                        return (error);
        !           536:                }
        !           537:                if (error == EWOULDBLOCK) {
        !           538:                        /*
        !           539:                         * On a timeout, return what's in the buffer,
        !           540:                         * which may be nothing.  If there is something
        !           541:                         * in the store buffer, we can rotate the buffers.
        !           542:                         */
        !           543:                        if (d->bd_hbuf)
        !           544:                                /*
        !           545:                                 * We filled up the buffer in between
        !           546:                                 * getting the timeout and arriving
        !           547:                                 * here, so we don't need to rotate.
        !           548:                                 */
        !           549:                                break;
        !           550: 
        !           551:                        if (d->bd_slen == 0) {
        !           552:                                splx(s);
        !           553:                                return (0);
        !           554:                        }
        !           555:                        ROTATE_BUFFERS(d);
        !           556:                        break;
        !           557:                }
        !           558:        }
        !           559:        /*
        !           560:         * At this point, we know we have something in the hold slot.
        !           561:         */
        !           562:        splx(s);
        !           563: 
        !           564:        /*
        !           565:         * Move data from hold buffer into user space.
        !           566:         * We know the entire buffer is transferred since
        !           567:         * we checked above that the read buffer is bpf_bufsize bytes.
        !           568:         */
        !           569:        error = UIOMOVE(d->bd_hbuf, d->bd_hlen, UIO_READ, uio);
        !           570: 
        !           571:        s = splimp();
        !           572:        d->bd_fbuf = d->bd_hbuf;
        !           573:        d->bd_hbuf = 0;
        !           574:        d->bd_hlen = 0;
        !           575:        splx(s);
        !           576: 
        !           577:        return (error);
        !           578: }
        !           579: 
        !           580: 
        !           581: /*
        !           582:  * If there are processes sleeping on this descriptor, wake them up.
        !           583:  */
        !           584: static inline void
        !           585: bpf_wakeup(d)
        !           586:        register struct bpf_d *d;
        !           587: {
        !           588:        wakeup((caddr_t)d);
        !           589:        if (d->bd_async && d->bd_sig && d->bd_sigio)
        !           590:                pgsigio(d->bd_sigio, d->bd_sig, 0);
        !           591: 
        !           592: #if BSD >= 199103
        !           593:        selwakeup(&d->bd_sel);
        !           594:        /* XXX */
        !           595:        d->bd_sel.si_thread = 0;
        !           596: #else
        !           597:        if (d->bd_selproc) {
        !           598:                selwakeup(d->bd_selproc, (int)d->bd_selcoll);
        !           599:                d->bd_selcoll = 0;
        !           600:                d->bd_selproc = 0;
        !           601:        }
        !           602: #endif
        !           603: }
        !           604: 
        !           605:        int
        !           606: bpfwrite(dev, uio, ioflag)
        !           607:        dev_t dev;
        !           608:        struct uio *uio;
        !           609:        int ioflag;
        !           610: {
        !           611:        register struct bpf_d *d = &bpf_dtab[minor(dev)];
        !           612:        struct ifnet *ifp;
        !           613:        struct mbuf *m;
        !           614:        int error, s;
        !           615:        static struct sockaddr dst;
        !           616:        int datlen;
        !           617: 
        !           618:        if (d->bd_bif == 0)
        !           619:                return (ENXIO);
        !           620: 
        !           621:        ifp = d->bd_bif->bif_ifp;
        !           622: 
        !           623:        if (uio->uio_resid == 0)
        !           624:                return (0);
        !           625: 
        !           626:        error = bpf_movein(uio, (int)d->bd_bif->bif_dlt, &m, &dst, &datlen);
        !           627:        if (error)
        !           628:                return (error);
        !           629: 
        !           630:        if (datlen > ifp->if_mtu)
        !           631:                return (EMSGSIZE);
        !           632: 
        !           633:        s = splnet();
        !           634: 
        !           635:        error = dlil_output((u_long) ifp, m, 
        !           636:                            (caddr_t) 0, &dst, 0);
        !           637: 
        !           638:        /*
        !           639:        error = dlil_inject_if_output(m, DLIL_NULL_FILTER);
        !           640:        */
        !           641: 
        !           642:        splx(s);
        !           643:        /*
        !           644:         * The driver frees the mbuf.
        !           645:         */
        !           646:        return (error);
        !           647: }
        !           648: 
        !           649: /*
        !           650:  * Reset a descriptor by flushing its packet buffer and clearing the
        !           651:  * receive and drop counts.  Should be called at splimp.
        !           652:  */
        !           653: static void
        !           654: reset_d(d)
        !           655:        struct bpf_d *d;
        !           656: {
        !           657:        if (d->bd_hbuf) {
        !           658:                /* Free the hold buffer. */
        !           659:                d->bd_fbuf = d->bd_hbuf;
        !           660:                d->bd_hbuf = 0;
        !           661:        }
        !           662:        d->bd_slen = 0;
        !           663:        d->bd_hlen = 0;
        !           664:        d->bd_rcount = 0;
        !           665:        d->bd_dcount = 0;
        !           666: }
        !           667: 
        !           668: /*
        !           669:  *  FIONREAD           Check for read packet available.
        !           670:  *  SIOCGIFADDR                Get interface address - convenient hook to driver.
        !           671:  *  BIOCGBLEN          Get buffer len [for read()].
        !           672:  *  BIOCSETF           Set ethernet read filter.
        !           673:  *  BIOCFLUSH          Flush read packet buffer.
        !           674:  *  BIOCPROMISC                Put interface into promiscuous mode.
        !           675:  *  BIOCGDLT           Get link layer type.
        !           676:  *  BIOCGETIF          Get interface name.
        !           677:  *  BIOCSETIF          Set interface.
        !           678:  *  BIOCSRTIMEOUT      Set read timeout.
        !           679:  *  BIOCGRTIMEOUT      Get read timeout.
        !           680:  *  BIOCGSTATS         Get packet stats.
        !           681:  *  BIOCIMMEDIATE      Set immediate mode.
        !           682:  *  BIOCVERSION                Get filter language version.
        !           683:  */
        !           684: /* ARGSUSED */
        !           685:        int
        !           686: bpfioctl(dev, cmd, addr, flags, p)
        !           687:        dev_t dev;
        !           688:        u_long cmd;
        !           689:        caddr_t addr;
        !           690:        int flags;
        !           691:        struct proc *p;
        !           692: {
        !           693:        register struct bpf_d *d = &bpf_dtab[minor(dev)];
        !           694:        int s, error = 0;
        !           695: 
        !           696:        switch (cmd) {
        !           697: 
        !           698:        default:
        !           699:                error = EINVAL;
        !           700:                break;
        !           701: 
        !           702:        /*
        !           703:         * Check for read packet available.
        !           704:         */
        !           705:        case FIONREAD:
        !           706:                {
        !           707:                        int n;
        !           708: 
        !           709:                        s = splimp();
        !           710:                        n = d->bd_slen;
        !           711:                        if (d->bd_hbuf)
        !           712:                                n += d->bd_hlen;
        !           713:                        splx(s);
        !           714: 
        !           715:                        *(int *)addr = n;
        !           716:                        break;
        !           717:                }
        !           718: 
        !           719:        case SIOCGIFADDR:
        !           720:                {
        !           721:                        struct ifnet *ifp;
        !           722: 
        !           723:                        if (d->bd_bif == 0)
        !           724:                                error = EINVAL;
        !           725:                        else {
        !           726:                                ifp = d->bd_bif->bif_ifp;
        !           727:                                error = (*ifp->if_ioctl)(ifp, cmd, addr);
        !           728:                        }
        !           729:                        break;
        !           730:                }
        !           731: 
        !           732:        /*
        !           733:         * Get buffer len [for read()].
        !           734:         */
        !           735:        case BIOCGBLEN:
        !           736:                *(u_int *)addr = d->bd_bufsize;
        !           737:                break;
        !           738: 
        !           739:        /*
        !           740:         * Set buffer length.
        !           741:         */
        !           742:        case BIOCSBLEN:
        !           743: #if BSD < 199103
        !           744:                error = EINVAL;
        !           745: #else
        !           746:                if (d->bd_bif != 0)
        !           747:                        error = EINVAL;
        !           748:                else {
        !           749:                        register u_int size = *(u_int *)addr;
        !           750: 
        !           751:                        if (size > BPF_MAXBUFSIZE)
        !           752:                                *(u_int *)addr = size = BPF_MAXBUFSIZE;
        !           753:                        else if (size < BPF_MINBUFSIZE)
        !           754:                                *(u_int *)addr = size = BPF_MINBUFSIZE;
        !           755:                        d->bd_bufsize = size;
        !           756:                }
        !           757: #endif
        !           758:                break;
        !           759: 
        !           760:        /*
        !           761:         * Set link layer read filter.
        !           762:         */
        !           763:        case BIOCSETF:
        !           764:                error = bpf_setf(d, (struct bpf_program *)addr);
        !           765:                break;
        !           766: 
        !           767:        /*
        !           768:         * Flush read packet buffer.
        !           769:         */
        !           770:        case BIOCFLUSH:
        !           771:                s = splimp();
        !           772:                reset_d(d);
        !           773:                splx(s);
        !           774:                break;
        !           775: 
        !           776:        /*
        !           777:         * Put interface into promiscuous mode.
        !           778:         */
        !           779:        case BIOCPROMISC:
        !           780:                if (d->bd_bif == 0) {
        !           781:                        /*
        !           782:                         * No interface attached yet.
        !           783:                         */
        !           784:                        error = EINVAL;
        !           785:                        break;
        !           786:                }
        !           787:                s = splimp();
        !           788:                if (d->bd_promisc == 0) {
        !           789:                        error = ifpromisc(d->bd_bif->bif_ifp, 1);
        !           790:                        if (error == 0)
        !           791:                                d->bd_promisc = 1;
        !           792:                }
        !           793:                splx(s);
        !           794:                break;
        !           795: 
        !           796:        /*
        !           797:         * Get device parameters.
        !           798:         */
        !           799:        case BIOCGDLT:
        !           800:                if (d->bd_bif == 0)
        !           801:                        error = EINVAL;
        !           802:                else
        !           803:                        *(u_int *)addr = d->bd_bif->bif_dlt;
        !           804:                break;
        !           805: 
        !           806:        /*
        !           807:         * Set interface name.
        !           808:         */
        !           809:        case BIOCGETIF:
        !           810:                if (d->bd_bif == 0)
        !           811:                        error = EINVAL;
        !           812:                else
        !           813:                        bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
        !           814:                break;
        !           815: 
        !           816:        /*
        !           817:         * Set interface.
        !           818:         */
        !           819:        case BIOCSETIF:
        !           820:                error = bpf_setif(d, (struct ifreq *)addr);
        !           821:                break;
        !           822: 
        !           823:        /*
        !           824:         * Set read timeout.
        !           825:         */
        !           826:        case BIOCSRTIMEOUT:
        !           827:                {
        !           828:                        struct timeval *tv = (struct timeval *)addr;
        !           829: 
        !           830:                        /*
        !           831:                         * Subtract 1 tick from tvtohz() since this isn't
        !           832:                         * a one-shot timer.
        !           833:                         */
        !           834:                        if ((error = itimerfix(tv)) == 0)
        !           835:                                d->bd_rtout = tvtohz(tv) - 1;
        !           836:                        break;
        !           837:                }
        !           838: 
        !           839:        /*
        !           840:         * Get read timeout.
        !           841:         */
        !           842:        case BIOCGRTIMEOUT:
        !           843:                {
        !           844:                        struct timeval *tv = (struct timeval *)addr;
        !           845: 
        !           846:                        tv->tv_sec = d->bd_rtout / hz;
        !           847:                        tv->tv_usec = (d->bd_rtout % hz) * tick;
        !           848:                        break;
        !           849:                }
        !           850: 
        !           851:        /*
        !           852:         * Get packet stats.
        !           853:         */
        !           854:        case BIOCGSTATS:
        !           855:                {
        !           856:                        struct bpf_stat *bs = (struct bpf_stat *)addr;
        !           857: 
        !           858:                        bs->bs_recv = d->bd_rcount;
        !           859:                        bs->bs_drop = d->bd_dcount;
        !           860:                        break;
        !           861:                }
        !           862: 
        !           863:        /*
        !           864:         * Set immediate mode.
        !           865:         */
        !           866:        case BIOCIMMEDIATE:
        !           867:                d->bd_immediate = *(u_int *)addr;
        !           868:                break;
        !           869: 
        !           870:        case BIOCVERSION:
        !           871:                {
        !           872:                        struct bpf_version *bv = (struct bpf_version *)addr;
        !           873: 
        !           874:                        bv->bv_major = BPF_MAJOR_VERSION;
        !           875:                        bv->bv_minor = BPF_MINOR_VERSION;
        !           876:                        break;
        !           877:                }
        !           878: 
        !           879:        case FIONBIO:           /* Non-blocking I/O */
        !           880:                break;
        !           881: 
        !           882:        case FIOASYNC:          /* Send signal on receive packets */
        !           883:                d->bd_async = *(int *)addr;
        !           884:                break;
        !           885: #if ISFB31
        !           886:        case FIOSETOWN:
        !           887:                error = fsetown(*(int *)addr, &d->bd_sigio);
        !           888:                break;
        !           889: 
        !           890:        case FIOGETOWN:
        !           891:                *(int *)addr = fgetown(d->bd_sigio);
        !           892:                break;
        !           893: 
        !           894:        /* This is deprecated, FIOSETOWN should be used instead. */
        !           895:        case TIOCSPGRP:
        !           896:                error = fsetown(-(*(int *)addr), &d->bd_sigio);
        !           897:                break;
        !           898: 
        !           899:        /* This is deprecated, FIOGETOWN should be used instead. */
        !           900:        case TIOCGPGRP:
        !           901:                *(int *)addr = -fgetown(d->bd_sigio);
        !           902:                break;
        !           903: #endif
        !           904:        case BIOCSRSIG:         /* Set receive signal */
        !           905:                {
        !           906:                        u_int sig;
        !           907: 
        !           908:                        sig = *(u_int *)addr;
        !           909: 
        !           910:                        if (sig >= NSIG)
        !           911:                                error = EINVAL;
        !           912:                        else
        !           913:                                d->bd_sig = sig;
        !           914:                        break;
        !           915:                }
        !           916:        case BIOCGRSIG:
        !           917:                *(u_int *)addr = d->bd_sig;
        !           918:                break;
        !           919:        }
        !           920:        return (error);
        !           921: }
        !           922: 
        !           923: /*
        !           924:  * Set d's packet filter program to fp.  If this file already has a filter,
        !           925:  * free it and replace it.  Returns EINVAL for bogus requests.
        !           926:  */
        !           927: static int
        !           928: bpf_setf(d, fp)
        !           929:        struct bpf_d *d;
        !           930:        struct bpf_program *fp;
        !           931: {
        !           932:        struct bpf_insn *fcode, *old;
        !           933:        u_int flen, size;
        !           934:        int s;
        !           935: 
        !           936:        old = d->bd_filter;
        !           937:        if (fp->bf_insns == 0) {
        !           938:                if (fp->bf_len != 0)
        !           939:                        return (EINVAL);
        !           940:                s = splimp();
        !           941:                d->bd_filter = 0;
        !           942:                reset_d(d);
        !           943:                splx(s);
        !           944:                if (old != 0)
        !           945:                        FREE((caddr_t)old, M_DEVBUF);
        !           946:                return (0);
        !           947:        }
        !           948:        flen = fp->bf_len;
        !           949:        if (flen > BPF_MAXINSNS)
        !           950:                return (EINVAL);
        !           951: 
        !           952:        size = flen * sizeof(*fp->bf_insns);
        !           953:        fcode = (struct bpf_insn *) _MALLOC(size, M_DEVBUF, M_WAIT);
        !           954:        if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
        !           955:            bpf_validate(fcode, (int)flen)) {
        !           956:                s = splimp();
        !           957:                d->bd_filter = fcode;
        !           958:                reset_d(d);
        !           959:                splx(s);
        !           960:                if (old != 0)
        !           961:                        FREE((caddr_t)old, M_DEVBUF);
        !           962: 
        !           963:                return (0);
        !           964:        }
        !           965:        FREE((caddr_t)fcode, M_DEVBUF);
        !           966:        return (EINVAL);
        !           967: }
        !           968: 
        !           969: /*
        !           970:  * Detach a file from its current interface (if attached at all) and attach
        !           971:  * to the interface indicated by the name stored in ifr.
        !           972:  * Return an errno or 0.
        !           973:  */
        !           974: static int
        !           975: bpf_setif(d, ifr)
        !           976:        struct bpf_d *d;
        !           977:        struct ifreq *ifr;
        !           978: {
        !           979:        struct bpf_if *bp;
        !           980:        int s, error;
        !           981:        struct ifnet *theywant;
        !           982: 
        !           983:        theywant = ifunit(ifr->ifr_name);
        !           984:        if (theywant == 0)
        !           985:                return ENXIO;
        !           986: 
        !           987:        /*
        !           988:         * Look through attached interfaces for the named one.
        !           989:         */
        !           990:        for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
        !           991:                struct ifnet *ifp = bp->bif_ifp;
        !           992: 
        !           993:                if (ifp == 0 || ifp != theywant)
        !           994:                        continue;
        !           995:                /*
        !           996:                 * We found the requested interface.
        !           997:                 * If it's not up, return an error.
        !           998:                 * Allocate the packet buffers if we need to.
        !           999:                 * If we're already attached to requested interface,
        !          1000:                 * just flush the buffer.
        !          1001:                 */
        !          1002:                if ((ifp->if_flags & IFF_UP) == 0)
        !          1003:                        return (ENETDOWN);
        !          1004: 
        !          1005:                if (d->bd_sbuf == 0) {
        !          1006:                        error = bpf_allocbufs(d);
        !          1007:                        if (error != 0)
        !          1008:                                return (error);
        !          1009:                }
        !          1010:                s = splimp();
        !          1011:                if (bp != d->bd_bif) {
        !          1012:                        if (d->bd_bif)
        !          1013:                                /*
        !          1014:                                 * Detach if attached to something else.
        !          1015:                                 */
        !          1016:                                bpf_detachd(d);
        !          1017: 
        !          1018:                        bpf_attachd(d, bp);
        !          1019:                }
        !          1020:                reset_d(d);
        !          1021:                splx(s);
        !          1022:                return (0);
        !          1023:        }
        !          1024:        /* Not found. */
        !          1025:        return (ENXIO);
        !          1026: }
        !          1027: 
        !          1028: /*
        !          1029:  * Convert an interface name plus unit number of an ifp to a single
        !          1030:  * name which is returned in the ifr.
        !          1031:  */
        !          1032: static void
        !          1033: bpf_ifname(ifp, ifr)
        !          1034:        struct ifnet *ifp;
        !          1035:        struct ifreq *ifr;
        !          1036: {
        !          1037:        char *s = ifp->if_name;
        !          1038:        char *d = ifr->ifr_name;
        !          1039: 
        !          1040:        while (*d++ = *s++)
        !          1041:                continue;
        !          1042:        d--; /* back to the null */
        !          1043:        /* XXX Assume that unit number is less than 10. */
        !          1044:        *d++ = ifp->if_unit + '0';
        !          1045:        *d = '\0';
        !          1046: }
        !          1047: 
        !          1048: 
        !          1049: 
        !          1050: /*
        !          1051:  * Support for select() and poll() system calls
        !          1052:  *
        !          1053:  * Return true iff the specific operation will not block indefinitely.
        !          1054:  * Otherwise, return false but make a note that a selwakeup() must be done.
        !          1055:  */
        !          1056: int
        !          1057: bpfpoll(dev, events, p)
        !          1058:        register dev_t dev;
        !          1059:        int events;
        !          1060:        struct proc *p;
        !          1061: {
        !          1062:        register struct bpf_d *d;
        !          1063:        register int s;
        !          1064:        int revents = 0;
        !          1065: 
        !          1066:        /*
        !          1067:         * An imitation of the FIONREAD ioctl code.
        !          1068:         */
        !          1069:        d = &bpf_dtab[minor(dev)];
        !          1070: 
        !          1071:        s = splimp();
        !          1072:        if (events & (POLLIN | POLLRDNORM))
        !          1073:                if (d->bd_hlen != 0 || (d->bd_immediate && d->bd_slen != 0))
        !          1074:                        revents |= events & (POLLIN | POLLRDNORM);
        !          1075:                else
        !          1076:                        selrecord(p, &d->bd_sel);
        !          1077: 
        !          1078:        splx(s);
        !          1079:        return (revents);
        !          1080: }
        !          1081: 
        !          1082: /*
        !          1083:  * Incoming linkage from device drivers.  Process the packet pkt, of length
        !          1084:  * pktlen, which is stored in a contiguous buffer.  The packet is parsed
        !          1085:  * by each process' filter, and if accepted, stashed into the corresponding
        !          1086:  * buffer.
        !          1087:  */
        !          1088: void
        !          1089: bpf_tap(ifp, pkt, pktlen)
        !          1090:        struct ifnet *ifp;
        !          1091:        register u_char *pkt;
        !          1092:        register u_int pktlen;
        !          1093: {
        !          1094:        struct bpf_if *bp;
        !          1095:        register struct bpf_d *d;
        !          1096:        register u_int slen;
        !          1097:        /*
        !          1098:         * Note that the ipl does not have to be raised at this point.
        !          1099:         * The only problem that could arise here is that if two different
        !          1100:         * interfaces shared any data.  This is not the case.
        !          1101:         */
        !          1102:        bp = ifp->if_bpf;
        !          1103:        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
        !          1104:                ++d->bd_rcount;
        !          1105:                slen = bpf_filter(d->bd_filter, pkt, pktlen, pktlen);
        !          1106:                if (slen != 0)
        !          1107:                        catchpacket(d, pkt, pktlen, slen, bcopy);
        !          1108:        }
        !          1109: }
        !          1110: 
        !          1111: /*
        !          1112:  * Copy data from an mbuf chain into a buffer.  This code is derived
        !          1113:  * from m_copydata in sys/uipc_mbuf.c.
        !          1114:  */
        !          1115: static void
        !          1116: bpf_mcopy(src_arg, dst_arg, len)
        !          1117:        const void *src_arg;
        !          1118:        void *dst_arg;
        !          1119:        register size_t len;
        !          1120: {
        !          1121:        register const struct mbuf *m;
        !          1122:        register u_int count;
        !          1123:        u_char *dst;
        !          1124: 
        !          1125:        m = src_arg;
        !          1126:        dst = dst_arg;
        !          1127:        while (len > 0) {
        !          1128:                if (m == 0)
        !          1129:                        panic("bpf_mcopy");
        !          1130:                count = min(m->m_len, len);
        !          1131:                bcopy(mtod(m, void *), dst, count);
        !          1132:                m = m->m_next;
        !          1133:                dst += count;
        !          1134:                len -= count;
        !          1135:        }
        !          1136: }
        !          1137: 
        !          1138: /*
        !          1139:  * Incoming linkage from device drivers, when packet is in an mbuf chain.
        !          1140:  */
        !          1141: void
        !          1142: bpf_mtap(ifp, m)
        !          1143:        struct ifnet *ifp;
        !          1144:        struct mbuf *m;
        !          1145: {
        !          1146:        struct bpf_if *bp = ifp->if_bpf;
        !          1147:        struct bpf_d *d;
        !          1148:        u_int pktlen, slen;
        !          1149:        struct mbuf *m0;
        !          1150: 
        !          1151:        pktlen = 0;
        !          1152:        for (m0 = m; m0 != 0; m0 = m0->m_next)
        !          1153:                pktlen += m0->m_len;
        !          1154: 
        !          1155:        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
        !          1156:                ++d->bd_rcount;
        !          1157:                slen = bpf_filter(d->bd_filter, (u_char *)m, pktlen, 0);
        !          1158:                if (slen != 0)
        !          1159:                        catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
        !          1160:        }
        !          1161: }
        !          1162: 
        !          1163: /*
        !          1164:  * Move the packet data from interface memory (pkt) into the
        !          1165:  * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
        !          1166:  * otherwise 0.  "copy" is the routine called to do the actual data
        !          1167:  * transfer.  bcopy is passed in to copy contiguous chunks, while
        !          1168:  * bpf_mcopy is passed in to copy mbuf chains.  In the latter case,
        !          1169:  * pkt is really an mbuf.
        !          1170:  */
        !          1171: static void
        !          1172: catchpacket(d, pkt, pktlen, snaplen, cpfn)
        !          1173:        register struct bpf_d *d;
        !          1174:        register u_char *pkt;
        !          1175:        register u_int pktlen, snaplen;
        !          1176:        register void (*cpfn) __P((const void *, void *, size_t));
        !          1177: {
        !          1178:        register struct bpf_hdr *hp;
        !          1179:        register int totlen, curlen;
        !          1180:        register int hdrlen = d->bd_bif->bif_hdrlen;
        !          1181:        /*
        !          1182:         * Figure out how many bytes to move.  If the packet is
        !          1183:         * greater or equal to the snapshot length, transfer that
        !          1184:         * much.  Otherwise, transfer the whole packet (unless
        !          1185:         * we hit the buffer size limit).
        !          1186:         */
        !          1187:        totlen = hdrlen + min(snaplen, pktlen);
        !          1188:        if (totlen > d->bd_bufsize)
        !          1189:                totlen = d->bd_bufsize;
        !          1190: 
        !          1191:        /*
        !          1192:         * Round up the end of the previous packet to the next longword.
        !          1193:         */
        !          1194:        curlen = BPF_WORDALIGN(d->bd_slen);
        !          1195:        if (curlen + totlen > d->bd_bufsize) {
        !          1196:                /*
        !          1197:                 * This packet will overflow the storage buffer.
        !          1198:                 * Rotate the buffers if we can, then wakeup any
        !          1199:                 * pending reads.
        !          1200:                 */
        !          1201:                if (d->bd_fbuf == 0) {
        !          1202:                        /*
        !          1203:                         * We haven't completed the previous read yet,
        !          1204:                         * so drop the packet.
        !          1205:                         */
        !          1206:                        ++d->bd_dcount;
        !          1207:                        return;
        !          1208:                }
        !          1209:                ROTATE_BUFFERS(d);
        !          1210:                bpf_wakeup(d);
        !          1211:                curlen = 0;
        !          1212:        }
        !          1213:        else if (d->bd_immediate)
        !          1214:                /*
        !          1215:                 * Immediate mode is set.  A packet arrived so any
        !          1216:                 * reads should be woken up.
        !          1217:                 */
        !          1218:                bpf_wakeup(d);
        !          1219: 
        !          1220:        /*
        !          1221:         * Append the bpf header.
        !          1222:         */
        !          1223:        hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
        !          1224: #if BSD >= 199103
        !          1225:        microtime(&hp->bh_tstamp);
        !          1226: #elif defined(sun)
        !          1227:        uniqtime(&hp->bh_tstamp);
        !          1228: #else
        !          1229:        hp->bh_tstamp = time;
        !          1230: #endif
        !          1231:        hp->bh_datalen = pktlen;
        !          1232:        hp->bh_hdrlen = hdrlen;
        !          1233:        /*
        !          1234:         * Copy the packet data into the store buffer and update its length.
        !          1235:         */
        !          1236:        (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
        !          1237:        d->bd_slen = curlen + totlen;
        !          1238: }
        !          1239: 
        !          1240: /*
        !          1241:  * Initialize all nonzero fields of a descriptor.
        !          1242:  */
        !          1243: static int
        !          1244: bpf_allocbufs(d)
        !          1245:        register struct bpf_d *d;
        !          1246: {
        !          1247:        d->bd_fbuf = (caddr_t) _MALLOC(d->bd_bufsize, M_DEVBUF, M_WAIT);
        !          1248:        if (d->bd_fbuf == 0)
        !          1249:                return (ENOBUFS);
        !          1250: 
        !          1251:        d->bd_sbuf = (caddr_t) _MALLOC(d->bd_bufsize, M_DEVBUF, M_WAIT);
        !          1252:        if (d->bd_sbuf == 0) {
        !          1253:                FREE(d->bd_fbuf, M_DEVBUF);
        !          1254:                return (ENOBUFS);
        !          1255:        }
        !          1256:        d->bd_slen = 0;
        !          1257:        d->bd_hlen = 0;
        !          1258:        return (0);
        !          1259: }
        !          1260: 
        !          1261: /*
        !          1262:  * Free buffers currently in use by a descriptor.
        !          1263:  * Called on close.
        !          1264:  */
        !          1265: static void
        !          1266: bpf_freed(d)
        !          1267:        register struct bpf_d *d;
        !          1268: {
        !          1269:        /*
        !          1270:         * We don't need to lock out interrupts since this descriptor has
        !          1271:         * been detached from its interface and it yet hasn't been marked
        !          1272:         * free.
        !          1273:         */
        !          1274:        if (d->bd_sbuf != 0) {
        !          1275:                FREE(d->bd_sbuf, M_DEVBUF);
        !          1276:                if (d->bd_hbuf != 0)
        !          1277:                        FREE(d->bd_hbuf, M_DEVBUF);
        !          1278:                if (d->bd_fbuf != 0)
        !          1279:                        FREE(d->bd_fbuf, M_DEVBUF);
        !          1280:        }
        !          1281:        if (d->bd_filter)
        !          1282:                FREE((caddr_t)d->bd_filter, M_DEVBUF);
        !          1283: 
        !          1284:        D_MARKFREE(d);
        !          1285: }
        !          1286: 
        !          1287: /*
        !          1288:  * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if *)
        !          1289:  * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
        !          1290:  * size of the link header (variable length headers not yet supported).
        !          1291:  */
        !          1292: void
        !          1293: bpfattach(ifp, dlt, hdrlen)
        !          1294:        struct ifnet *ifp;
        !          1295:        u_int dlt, hdrlen;
        !          1296: {
        !          1297:        struct bpf_if *bp;
        !          1298:        int i;
        !          1299:        bp = (struct bpf_if *) _MALLOC(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
        !          1300:        if (bp == 0)
        !          1301:                panic("bpfattach");
        !          1302: 
        !          1303:        bp->bif_dlist = 0;
        !          1304:        bp->bif_ifp = ifp;
        !          1305:        bp->bif_dlt = dlt;
        !          1306: 
        !          1307:        bp->bif_next = bpf_iflist;
        !          1308:        bpf_iflist = bp;
        !          1309: 
        !          1310:        bp->bif_ifp->if_bpf = 0;
        !          1311: 
        !          1312:        /*
        !          1313:         * Compute the length of the bpf header.  This is not necessarily
        !          1314:         * equal to SIZEOF_BPF_HDR because we want to insert spacing such
        !          1315:         * that the network layer header begins on a longword boundary (for
        !          1316:         * performance reasons and to alleviate alignment restrictions).
        !          1317:         */
        !          1318:        bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
        !          1319: 
        !          1320:        /*
        !          1321:         * Mark all the descriptors free if this hasn't been done.
        !          1322:         */
        !          1323:        if (!bpf_dtab_init) {
        !          1324:                for (i = 0; i < nbpfilter; ++i)
        !          1325:                        D_MARKFREE(&bpf_dtab[i]);
        !          1326:                bpf_dtab_init = 1;
        !          1327:        }
        !          1328: #if 0
        !          1329:        if (bootverbose)
        !          1330:                printf("bpf: %s%d attached\n", ifp->if_name, ifp->if_unit);
        !          1331: #endif
        !          1332: }
        !          1333: 
        !          1334: static void *bpf_devfs_token[NBPFILTER];
        !          1335: 
        !          1336: static int bpf_devsw_installed;
        !          1337: 
        !          1338: void bpf_init __P((void *unused));
        !          1339: void
        !          1340: bpf_init(unused)
        !          1341:        void *unused;
        !          1342: {
        !          1343:        int     i;
        !          1344:        int     maj;
        !          1345: 
        !          1346:        if (!bpf_devsw_installed ) {
        !          1347:            bpf_devsw_installed = 1;
        !          1348:            maj = cdevsw_add(BPF_MAJOR, &bpf_cdevsw);
        !          1349:            if (maj == -1) {
        !          1350:                printf("bpf_init: failed to allocate a major number!\n");
        !          1351:                nbpfilter = 0;
        !          1352:                return;
        !          1353:            }
        !          1354:            for (i = 0 ; i < nbpfilter; i++) {
        !          1355:                bpf_devfs_token[i]  = devfs_make_node(makedev(maj, i), 
        !          1356:                                                      DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0600, 
        !          1357:                                                      "bpf%x", i);
        !          1358: 
        !          1359:            }
        !          1360:        }
        !          1361: }
        !          1362: 
        !          1363: /*
        !          1364: SYSINIT(bpfdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,bpf_drvinit,NULL)
        !          1365: */
        !          1366: 
        !          1367: #endif

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.