Annotation of XNU/iokit/Drivers/network/AppleBPF/bpf.c, revision 1.1

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

unix.superglobalmegacorp.com

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