Annotation of Net2/net/bpf.c, revision 1.1

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

unix.superglobalmegacorp.com

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