[BACK]Return to bpf.c CVS log [TXT][DIR] Up to [local] / sys / net

Annotation of sys/net/bpf.c, Revision 1.1

1.1     ! nbrk        1: /*     $OpenBSD: bpf.c,v 1.66 2007/07/25 23:11:53 art Exp $    */
        !             2: /*     $NetBSD: bpf.c,v 1.33 1997/02/21 23:59:35 thorpej Exp $ */
        !             3:
        !             4: /*
        !             5:  * Copyright (c) 1990, 1991, 1993
        !             6:  *     The Regents of the University of California.  All rights reserved.
        !             7:  *
        !             8:  * This code is derived from the Stanford/CMU enet packet filter,
        !             9:  * (net/enet.c) distributed as part of 4.3BSD, and code contributed
        !            10:  * to Berkeley by Steven McCanne and Van Jacobson both of Lawrence
        !            11:  * Berkeley Laboratory.
        !            12:  *
        !            13:  * Redistribution and use in source and binary forms, with or without
        !            14:  * modification, are permitted provided that the following conditions
        !            15:  * are met:
        !            16:  * 1. Redistributions of source code must retain the above copyright
        !            17:  *    notice, this list of conditions and the following disclaimer.
        !            18:  * 2. Redistributions in binary form must reproduce the above copyright
        !            19:  *    notice, this list of conditions and the following disclaimer in the
        !            20:  *    documentation and/or other materials provided with the distribution.
        !            21:  * 3. 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       8.2 (Berkeley) 3/28/94
        !            38:  */
        !            39:
        !            40: #include "bpfilter.h"
        !            41:
        !            42: #include <sys/param.h>
        !            43: #include <sys/mbuf.h>
        !            44: #include <sys/proc.h>
        !            45: #include <sys/signalvar.h>
        !            46: #include <sys/ioctl.h>
        !            47: #include <sys/conf.h>
        !            48: #include <sys/vnode.h>
        !            49: #include <sys/file.h>
        !            50: #include <sys/socket.h>
        !            51: #include <sys/poll.h>
        !            52: #include <sys/kernel.h>
        !            53: #include <sys/sysctl.h>
        !            54:
        !            55: #include <net/if.h>
        !            56: #include <net/bpf.h>
        !            57: #include <net/bpfdesc.h>
        !            58:
        !            59: #include <netinet/in.h>
        !            60: #include <netinet/if_ether.h>
        !            61:
        !            62: #define BPF_BUFSIZE 32768
        !            63:
        !            64: #define PRINET  26                     /* interruptible */
        !            65:
        !            66: /*
        !            67:  * The default read buffer size is patchable.
        !            68:  */
        !            69: int bpf_bufsize = BPF_BUFSIZE;
        !            70: int bpf_maxbufsize = BPF_MAXBUFSIZE;
        !            71:
        !            72: /*
        !            73:  *  bpf_iflist is the list of interfaces; each corresponds to an ifnet
        !            74:  *  bpf_d_list is the list of descriptors
        !            75:  */
        !            76: struct bpf_if  *bpf_iflist;
        !            77: LIST_HEAD(, bpf_d) bpf_d_list;
        !            78:
        !            79: int    bpf_allocbufs(struct bpf_d *);
        !            80: void   bpf_freed(struct bpf_d *);
        !            81: void   bpf_ifname(struct ifnet *, struct ifreq *);
        !            82: void   bpf_mcopy(const void *, void *, size_t);
        !            83: int    bpf_movein(struct uio *, u_int, struct mbuf **,
        !            84:            struct sockaddr *, struct bpf_insn *);
        !            85: void   bpf_attachd(struct bpf_d *, struct bpf_if *);
        !            86: void   bpf_detachd(struct bpf_d *);
        !            87: int    bpf_setif(struct bpf_d *, struct ifreq *);
        !            88: int    bpfpoll(dev_t, int, struct proc *);
        !            89: int    bpfkqfilter(dev_t, struct knote *);
        !            90: static __inline void bpf_wakeup(struct bpf_d *);
        !            91: void   bpf_catchpacket(struct bpf_d *, u_char *, size_t, size_t,
        !            92:            void (*)(const void *, void *, size_t));
        !            93: void   bpf_reset_d(struct bpf_d *);
        !            94: int    bpf_getdltlist(struct bpf_d *, struct bpf_dltlist *);
        !            95: int    bpf_setdlt(struct bpf_d *, u_int);
        !            96:
        !            97: void   filt_bpfrdetach(struct knote *);
        !            98: int    filt_bpfread(struct knote *, long);
        !            99:
        !           100: struct bpf_d *bpfilter_lookup(int);
        !           101: struct bpf_d *bpfilter_create(int);
        !           102: void bpfilter_destroy(struct bpf_d *);
        !           103:
        !           104: int
        !           105: bpf_movein(struct uio *uio, u_int linktype, struct mbuf **mp,
        !           106:     struct sockaddr *sockp, struct bpf_insn *filter)
        !           107: {
        !           108:        struct mbuf *m;
        !           109:        struct m_tag *mtag;
        !           110:        int error;
        !           111:        u_int hlen;
        !           112:        u_int len;
        !           113:        u_int slen;
        !           114:
        !           115:        /*
        !           116:         * Build a sockaddr based on the data link layer type.
        !           117:         * We do this at this level because the ethernet header
        !           118:         * is copied directly into the data field of the sockaddr.
        !           119:         * In the case of SLIP, there is no header and the packet
        !           120:         * is forwarded as is.
        !           121:         * Also, we are careful to leave room at the front of the mbuf
        !           122:         * for the link level header.
        !           123:         */
        !           124:        switch (linktype) {
        !           125:
        !           126:        case DLT_SLIP:
        !           127:                sockp->sa_family = AF_INET;
        !           128:                hlen = 0;
        !           129:                break;
        !           130:
        !           131:        case DLT_PPP:
        !           132:                sockp->sa_family = AF_UNSPEC;
        !           133:                hlen = 0;
        !           134:                break;
        !           135:
        !           136:        case DLT_EN10MB:
        !           137:                sockp->sa_family = AF_UNSPEC;
        !           138:                /* XXX Would MAXLINKHDR be better? */
        !           139:                hlen = ETHER_HDR_LEN;
        !           140:                break;
        !           141:
        !           142:        case DLT_FDDI:
        !           143:                sockp->sa_family = AF_UNSPEC;
        !           144:                /* XXX 4(FORMAC)+6(dst)+6(src)+3(LLC)+5(SNAP) */
        !           145:                hlen = 24;
        !           146:                break;
        !           147:
        !           148:        case DLT_IEEE802_11:
        !           149:        case DLT_IEEE802_11_RADIO:
        !           150:                sockp->sa_family = AF_UNSPEC;
        !           151:                hlen = 0;
        !           152:                break;
        !           153:
        !           154:        case DLT_RAW:
        !           155:        case DLT_NULL:
        !           156:                sockp->sa_family = AF_UNSPEC;
        !           157:                hlen = 0;
        !           158:                break;
        !           159:
        !           160:        case DLT_ATM_RFC1483:
        !           161:                /*
        !           162:                 * en atm driver requires 4-byte atm pseudo header.
        !           163:                 * though it isn't standard, vpi:vci needs to be
        !           164:                 * specified anyway.
        !           165:                 */
        !           166:                sockp->sa_family = AF_UNSPEC;
        !           167:                hlen = 12;      /* XXX 4(ATM_PH) + 3(LLC) + 5(SNAP) */
        !           168:                break;
        !           169:
        !           170:        default:
        !           171:                return (EIO);
        !           172:        }
        !           173:
        !           174:        len = uio->uio_resid;
        !           175:        if (len > MCLBYTES)
        !           176:                return (EIO);
        !           177:
        !           178:        MGETHDR(m, M_WAIT, MT_DATA);
        !           179:        m->m_pkthdr.rcvif = 0;
        !           180:        m->m_pkthdr.len = len - hlen;
        !           181:
        !           182:        if (len > MHLEN) {
        !           183:                MCLGET(m, M_WAIT);
        !           184:                if ((m->m_flags & M_EXT) == 0) {
        !           185:                        error = ENOBUFS;
        !           186:                        goto bad;
        !           187:                }
        !           188:        }
        !           189:        m->m_len = len;
        !           190:        *mp = m;
        !           191:
        !           192:        error = uiomove(mtod(m, caddr_t), len, uio);
        !           193:        if (error)
        !           194:                goto bad;
        !           195:
        !           196:        slen = bpf_filter(filter, mtod(m, u_char *), len, len);
        !           197:        if (slen < len) {
        !           198:                error = EPERM;
        !           199:                goto bad;
        !           200:        }
        !           201:
        !           202:        if (m->m_len < hlen) {
        !           203:                error = EPERM;
        !           204:                goto bad;
        !           205:        }
        !           206:        /*
        !           207:         * Make room for link header, and copy it to sockaddr
        !           208:         */
        !           209:        if (hlen != 0) {
        !           210:                bcopy(m->m_data, sockp->sa_data, hlen);
        !           211:                m->m_len -= hlen;
        !           212:                m->m_data += hlen; /* XXX */
        !           213:        }
        !           214:
        !           215:        /*
        !           216:         * Prepend the data link type as a mbuf tag
        !           217:         */
        !           218:        mtag = m_tag_get(PACKET_TAG_DLT, sizeof(u_int), M_NOWAIT);
        !           219:        if (mtag == NULL)
        !           220:                return (ENOMEM);
        !           221:        *(u_int *)(mtag + 1) = linktype;
        !           222:        m_tag_prepend(m, mtag);
        !           223:
        !           224:        return (0);
        !           225:  bad:
        !           226:        m_freem(m);
        !           227:        return (error);
        !           228: }
        !           229:
        !           230: /*
        !           231:  * Attach file to the bpf interface, i.e. make d listen on bp.
        !           232:  * Must be called at splnet.
        !           233:  */
        !           234: void
        !           235: bpf_attachd(struct bpf_d *d, struct bpf_if *bp)
        !           236: {
        !           237:        /*
        !           238:         * Point d at bp, and add d to the interface's list of listeners.
        !           239:         * Finally, point the driver's bpf cookie at the interface so
        !           240:         * it will divert packets to bpf.
        !           241:         */
        !           242:        d->bd_bif = bp;
        !           243:        d->bd_next = bp->bif_dlist;
        !           244:        bp->bif_dlist = d;
        !           245:
        !           246:        *bp->bif_driverp = bp;
        !           247: }
        !           248:
        !           249: /*
        !           250:  * Detach a file from its interface.
        !           251:  */
        !           252: void
        !           253: bpf_detachd(struct bpf_d *d)
        !           254: {
        !           255:        struct bpf_d **p;
        !           256:        struct bpf_if *bp;
        !           257:
        !           258:        bp = d->bd_bif;
        !           259:        /*
        !           260:         * Check if this descriptor had requested promiscuous mode.
        !           261:         * If so, turn it off.
        !           262:         */
        !           263:        if (d->bd_promisc) {
        !           264:                int error;
        !           265:
        !           266:                d->bd_promisc = 0;
        !           267:                error = ifpromisc(bp->bif_ifp, 0);
        !           268:                if (error && !(error == EINVAL || error == ENODEV))
        !           269:                        /*
        !           270:                         * Something is really wrong if we were able to put
        !           271:                         * the driver into promiscuous mode, but can't
        !           272:                         * take it out.
        !           273:                         */
        !           274:                        panic("bpf: ifpromisc failed");
        !           275:        }
        !           276:        /* Remove d from the interface's descriptor list. */
        !           277:        p = &bp->bif_dlist;
        !           278:        while (*p != d) {
        !           279:                p = &(*p)->bd_next;
        !           280:                if (*p == 0)
        !           281:                        panic("bpf_detachd: descriptor not in list");
        !           282:        }
        !           283:        *p = (*p)->bd_next;
        !           284:        if (bp->bif_dlist == 0)
        !           285:                /*
        !           286:                 * Let the driver know that there are no more listeners.
        !           287:                 */
        !           288:                *d->bd_bif->bif_driverp = 0;
        !           289:        d->bd_bif = 0;
        !           290: }
        !           291:
        !           292: /*
        !           293:  * Reference count access to descriptor buffers
        !           294:  */
        !           295: #define D_GET(d) ((d)->bd_ref++)
        !           296: #define D_PUT(d) bpf_freed(d)
        !           297:
        !           298: /*
        !           299:  * bpfilterattach() is called at boot time in new systems.  We do
        !           300:  * nothing here since old systems will not call this.
        !           301:  */
        !           302: /* ARGSUSED */
        !           303: void
        !           304: bpfilterattach(int n)
        !           305: {
        !           306:        LIST_INIT(&bpf_d_list);
        !           307: }
        !           308:
        !           309: /*
        !           310:  * Open ethernet device.  Returns ENXIO for illegal minor device number,
        !           311:  * EBUSY if file is open by another process.
        !           312:  */
        !           313: /* ARGSUSED */
        !           314: int
        !           315: bpfopen(dev_t dev, int flag, int mode, struct proc *p)
        !           316: {
        !           317:        struct bpf_d *d;
        !           318:
        !           319:        /* create on demand */
        !           320:        if ((d = bpfilter_create(minor(dev))) == NULL)
        !           321:                return (EBUSY);
        !           322:
        !           323:        /* Mark "free" and do most initialization. */
        !           324:        d->bd_bufsize = bpf_bufsize;
        !           325:        d->bd_sig = SIGIO;
        !           326:
        !           327:        D_GET(d);
        !           328:
        !           329:        return (0);
        !           330: }
        !           331:
        !           332: /*
        !           333:  * Close the descriptor by detaching it from its interface,
        !           334:  * deallocating its buffers, and marking it free.
        !           335:  */
        !           336: /* ARGSUSED */
        !           337: int
        !           338: bpfclose(dev_t dev, int flag, int mode, struct proc *p)
        !           339: {
        !           340:        struct bpf_d *d;
        !           341:        int s;
        !           342:
        !           343:        d = bpfilter_lookup(minor(dev));
        !           344:        s = splnet();
        !           345:        if (d->bd_bif)
        !           346:                bpf_detachd(d);
        !           347:        bpf_wakeup(d);
        !           348:        D_PUT(d);
        !           349:        splx(s);
        !           350:
        !           351:        return (0);
        !           352: }
        !           353:
        !           354: /*
        !           355:  * Rotate the packet buffers in descriptor d.  Move the store buffer
        !           356:  * into the hold slot, and the free buffer into the store slot.
        !           357:  * Zero the length of the new store buffer.
        !           358:  */
        !           359: #define ROTATE_BUFFERS(d) \
        !           360:        (d)->bd_hbuf = (d)->bd_sbuf; \
        !           361:        (d)->bd_hlen = (d)->bd_slen; \
        !           362:        (d)->bd_sbuf = (d)->bd_fbuf; \
        !           363:        (d)->bd_slen = 0; \
        !           364:        (d)->bd_fbuf = 0;
        !           365: /*
        !           366:  *  bpfread - read next chunk of packets from buffers
        !           367:  */
        !           368: int
        !           369: bpfread(dev_t dev, struct uio *uio, int ioflag)
        !           370: {
        !           371:        struct bpf_d *d;
        !           372:        int error;
        !           373:        int s;
        !           374:
        !           375:        d = bpfilter_lookup(minor(dev));
        !           376:        if (d->bd_bif == 0)
        !           377:                return (ENXIO);
        !           378:
        !           379:        /*
        !           380:         * Restrict application to use a buffer the same size as
        !           381:         * as kernel buffers.
        !           382:         */
        !           383:        if (uio->uio_resid != d->bd_bufsize)
        !           384:                return (EINVAL);
        !           385:
        !           386:        s = splnet();
        !           387:
        !           388:        D_GET(d);
        !           389:
        !           390:        /*
        !           391:         * bd_rdStart is tagged when we start the read, iff there's a timeout.
        !           392:         * we can then figure out when we're done reading.
        !           393:         */
        !           394:        if (d->bd_rtout != -1 && d->bd_rdStart == 0)
        !           395:                d->bd_rdStart = ticks;
        !           396:        else
        !           397:                d->bd_rdStart = 0;
        !           398:
        !           399:        /*
        !           400:         * If the hold buffer is empty, then do a timed sleep, which
        !           401:         * ends when the timeout expires or when enough packets
        !           402:         * have arrived to fill the store buffer.
        !           403:         */
        !           404:        while (d->bd_hbuf == 0) {
        !           405:                if (d->bd_bif == NULL) {
        !           406:                        /* interface is gone */
        !           407:                        if (d->bd_slen == 0) {
        !           408:                                D_PUT(d);
        !           409:                                splx(s);
        !           410:                                return (EIO);
        !           411:                        }
        !           412:                        ROTATE_BUFFERS(d);
        !           413:                        break;
        !           414:                }
        !           415:                if (d->bd_immediate && d->bd_slen != 0) {
        !           416:                        /*
        !           417:                         * A packet(s) either arrived since the previous
        !           418:                         * read or arrived while we were asleep.
        !           419:                         * Rotate the buffers and return what's here.
        !           420:                         */
        !           421:                        ROTATE_BUFFERS(d);
        !           422:                        break;
        !           423:                }
        !           424:                if ((d->bd_rtout != -1) ||
        !           425:                    (d->bd_rdStart + d->bd_rtout) < ticks) {
        !           426:                        error = tsleep((caddr_t)d, PRINET|PCATCH, "bpf",
        !           427:                            d->bd_rtout);
        !           428:                } else {
        !           429:                        if (d->bd_rtout == -1) {
        !           430:                                /* User requested non-blocking I/O */
        !           431:                                error = EWOULDBLOCK;
        !           432:                        } else
        !           433:                                error = 0;
        !           434:                }
        !           435:                if (error == EINTR || error == ERESTART) {
        !           436:                        D_PUT(d);
        !           437:                        splx(s);
        !           438:                        return (error);
        !           439:                }
        !           440:                if (error == EWOULDBLOCK) {
        !           441:                        /*
        !           442:                         * On a timeout, return what's in the buffer,
        !           443:                         * which may be nothing.  If there is something
        !           444:                         * in the store buffer, we can rotate the buffers.
        !           445:                         */
        !           446:                        if (d->bd_hbuf)
        !           447:                                /*
        !           448:                                 * We filled up the buffer in between
        !           449:                                 * getting the timeout and arriving
        !           450:                                 * here, so we don't need to rotate.
        !           451:                                 */
        !           452:                                break;
        !           453:
        !           454:                        if (d->bd_slen == 0) {
        !           455:                                D_PUT(d);
        !           456:                                splx(s);
        !           457:                                return (0);
        !           458:                        }
        !           459:                        ROTATE_BUFFERS(d);
        !           460:                        break;
        !           461:                }
        !           462:        }
        !           463:        /*
        !           464:         * At this point, we know we have something in the hold slot.
        !           465:         */
        !           466:        splx(s);
        !           467:
        !           468:        /*
        !           469:         * Move data from hold buffer into user space.
        !           470:         * We know the entire buffer is transferred since
        !           471:         * we checked above that the read buffer is bpf_bufsize bytes.
        !           472:         */
        !           473:        error = uiomove(d->bd_hbuf, d->bd_hlen, uio);
        !           474:
        !           475:        s = splnet();
        !           476:        d->bd_fbuf = d->bd_hbuf;
        !           477:        d->bd_hbuf = 0;
        !           478:        d->bd_hlen = 0;
        !           479:
        !           480:        D_PUT(d);
        !           481:        splx(s);
        !           482:
        !           483:        return (error);
        !           484: }
        !           485:
        !           486:
        !           487: /*
        !           488:  * If there are processes sleeping on this descriptor, wake them up.
        !           489:  */
        !           490: static __inline void
        !           491: bpf_wakeup(struct bpf_d *d)
        !           492: {
        !           493:        wakeup((caddr_t)d);
        !           494:        if (d->bd_async && d->bd_sig)
        !           495:                csignal(d->bd_pgid, d->bd_sig,
        !           496:                    d->bd_siguid, d->bd_sigeuid);
        !           497:
        !           498:        selwakeup(&d->bd_sel);
        !           499:        /* XXX */
        !           500:        d->bd_sel.si_selpid = 0;
        !           501:        KNOTE(&d->bd_sel.si_note, 0);
        !           502: }
        !           503:
        !           504: int
        !           505: bpfwrite(dev_t dev, struct uio *uio, int ioflag)
        !           506: {
        !           507:        struct bpf_d *d;
        !           508:        struct ifnet *ifp;
        !           509:        struct mbuf *m;
        !           510:        int error, s;
        !           511:        struct sockaddr_storage dst;
        !           512:
        !           513:        d = bpfilter_lookup(minor(dev));
        !           514:        if (d->bd_bif == 0)
        !           515:                return (ENXIO);
        !           516:
        !           517:        ifp = d->bd_bif->bif_ifp;
        !           518:
        !           519:        if ((ifp->if_flags & IFF_UP) == 0)
        !           520:                return (ENETDOWN);
        !           521:
        !           522:        if (uio->uio_resid == 0)
        !           523:                return (0);
        !           524:
        !           525:        error = bpf_movein(uio, d->bd_bif->bif_dlt, &m,
        !           526:            (struct sockaddr *)&dst, d->bd_wfilter);
        !           527:        if (error)
        !           528:                return (error);
        !           529:
        !           530:        if (m->m_pkthdr.len > ifp->if_mtu) {
        !           531:                m_freem(m);
        !           532:                return (EMSGSIZE);
        !           533:        }
        !           534:
        !           535:        if (d->bd_hdrcmplt)
        !           536:                dst.ss_family = pseudo_AF_HDRCMPLT;
        !           537:
        !           538:        s = splsoftnet();
        !           539:        error = (*ifp->if_output)(ifp, m, (struct sockaddr *)&dst,
        !           540:            (struct rtentry *)0);
        !           541:        splx(s);
        !           542:        /*
        !           543:         * The driver frees the mbuf.
        !           544:         */
        !           545:        return (error);
        !           546: }
        !           547:
        !           548: /*
        !           549:  * Reset a descriptor by flushing its packet buffer and clearing the
        !           550:  * receive and drop counts.  Should be called at splnet.
        !           551:  */
        !           552: void
        !           553: bpf_reset_d(struct bpf_d *d)
        !           554: {
        !           555:        if (d->bd_hbuf) {
        !           556:                /* Free the hold buffer. */
        !           557:                d->bd_fbuf = d->bd_hbuf;
        !           558:                d->bd_hbuf = 0;
        !           559:        }
        !           560:        d->bd_slen = 0;
        !           561:        d->bd_hlen = 0;
        !           562:        d->bd_rcount = 0;
        !           563:        d->bd_dcount = 0;
        !           564: }
        !           565:
        !           566: /*
        !           567:  *  FIONREAD           Check for read packet available.
        !           568:  *  BIOCGBLEN          Get buffer len [for read()].
        !           569:  *  BIOCSETF           Set ethernet read filter.
        !           570:  *  BIOCFLUSH          Flush read packet buffer.
        !           571:  *  BIOCPROMISC                Put interface into promiscuous mode.
        !           572:  *  BIOCGDLTLIST       Get supported link layer types.
        !           573:  *  BIOCGDLT           Get link layer type.
        !           574:  *  BIOCSDLT           Set link layer type.
        !           575:  *  BIOCGETIF          Get interface name.
        !           576:  *  BIOCSETIF          Set interface.
        !           577:  *  BIOCSRTIMEOUT      Set read timeout.
        !           578:  *  BIOCGRTIMEOUT      Get read timeout.
        !           579:  *  BIOCGSTATS         Get packet stats.
        !           580:  *  BIOCIMMEDIATE      Set immediate mode.
        !           581:  *  BIOCVERSION                Get filter language version.
        !           582:  *  BIOCGHDRCMPLT      Get "header already complete" flag
        !           583:  *  BIOCSHDRCMPLT      Set "header already complete" flag
        !           584:  */
        !           585: /* ARGSUSED */
        !           586: int
        !           587: bpfioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
        !           588: {
        !           589:        struct bpf_d *d;
        !           590:        int s, error = 0;
        !           591:
        !           592:        d = bpfilter_lookup(minor(dev));
        !           593:        if (d->bd_locked && suser(p, 0) != 0) {
        !           594:                /* list of allowed ioctls when locked and not root */
        !           595:                switch (cmd) {
        !           596:                case BIOCGBLEN:
        !           597:                case BIOCFLUSH:
        !           598:                case BIOCGDLT:
        !           599:                case BIOCGDLTLIST:
        !           600:                case BIOCGETIF:
        !           601:                case BIOCGRTIMEOUT:
        !           602:                case BIOCGSTATS:
        !           603:                case BIOCVERSION:
        !           604:                case BIOCGRSIG:
        !           605:                case BIOCGHDRCMPLT:
        !           606:                case FIONREAD:
        !           607:                case BIOCLOCK:
        !           608:                case BIOCSRTIMEOUT:
        !           609:                case BIOCIMMEDIATE:
        !           610:                case TIOCGPGRP:
        !           611:                case BIOCGDIRFILT:
        !           612:                        break;
        !           613:                default:
        !           614:                        return (EPERM);
        !           615:                }
        !           616:        }
        !           617:
        !           618:        switch (cmd) {
        !           619:
        !           620:        default:
        !           621:                error = EINVAL;
        !           622:                break;
        !           623:
        !           624:        /*
        !           625:         * Check for read packet available.
        !           626:         */
        !           627:        case FIONREAD:
        !           628:                {
        !           629:                        int n;
        !           630:
        !           631:                        s = splnet();
        !           632:                        n = d->bd_slen;
        !           633:                        if (d->bd_hbuf)
        !           634:                                n += d->bd_hlen;
        !           635:                        splx(s);
        !           636:
        !           637:                        *(int *)addr = n;
        !           638:                        break;
        !           639:                }
        !           640:
        !           641:        /*
        !           642:         * Get buffer len [for read()].
        !           643:         */
        !           644:        case BIOCGBLEN:
        !           645:                *(u_int *)addr = d->bd_bufsize;
        !           646:                break;
        !           647:
        !           648:        /*
        !           649:         * Set buffer length.
        !           650:         */
        !           651:        case BIOCSBLEN:
        !           652:                if (d->bd_bif != 0)
        !           653:                        error = EINVAL;
        !           654:                else {
        !           655:                        u_int size = *(u_int *)addr;
        !           656:
        !           657:                        if (size > bpf_maxbufsize)
        !           658:                                *(u_int *)addr = size = bpf_maxbufsize;
        !           659:                        else if (size < BPF_MINBUFSIZE)
        !           660:                                *(u_int *)addr = size = BPF_MINBUFSIZE;
        !           661:                        d->bd_bufsize = size;
        !           662:                }
        !           663:                break;
        !           664:
        !           665:        /*
        !           666:         * Set link layer read filter.
        !           667:         */
        !           668:        case BIOCSETF:
        !           669:                error = bpf_setf(d, (struct bpf_program *)addr, 0);
        !           670:                break;
        !           671:
        !           672:        /*
        !           673:         * Set link layer write filter.
        !           674:         */
        !           675:        case BIOCSETWF:
        !           676:                error = bpf_setf(d, (struct bpf_program *)addr, 1);
        !           677:                break;
        !           678:
        !           679:        /*
        !           680:         * Flush read packet buffer.
        !           681:         */
        !           682:        case BIOCFLUSH:
        !           683:                s = splnet();
        !           684:                bpf_reset_d(d);
        !           685:                splx(s);
        !           686:                break;
        !           687:
        !           688:        /*
        !           689:         * Put interface into promiscuous mode.
        !           690:         */
        !           691:        case BIOCPROMISC:
        !           692:                if (d->bd_bif == 0) {
        !           693:                        /*
        !           694:                         * No interface attached yet.
        !           695:                         */
        !           696:                        error = EINVAL;
        !           697:                        break;
        !           698:                }
        !           699:                s = splnet();
        !           700:                if (d->bd_promisc == 0) {
        !           701:                        error = ifpromisc(d->bd_bif->bif_ifp, 1);
        !           702:                        if (error == 0)
        !           703:                                d->bd_promisc = 1;
        !           704:                }
        !           705:                splx(s);
        !           706:                break;
        !           707:
        !           708:        /*
        !           709:         * Get a list of supported device parameters.
        !           710:         */
        !           711:        case BIOCGDLTLIST:
        !           712:                if (d->bd_bif == NULL)
        !           713:                        error = EINVAL;
        !           714:                else
        !           715:                        error = bpf_getdltlist(d, (struct bpf_dltlist *)addr);
        !           716:                break;
        !           717:
        !           718:        /*
        !           719:         * Get device parameters.
        !           720:         */
        !           721:        case BIOCGDLT:
        !           722:                if (d->bd_bif == 0)
        !           723:                        error = EINVAL;
        !           724:                else
        !           725:                        *(u_int *)addr = d->bd_bif->bif_dlt;
        !           726:                break;
        !           727:
        !           728:        /*
        !           729:         * Set device parameters.
        !           730:         */
        !           731:        case BIOCSDLT:
        !           732:                if (d->bd_bif == NULL)
        !           733:                        error = EINVAL;
        !           734:                else
        !           735:                        error = bpf_setdlt(d, *(u_int *)addr);
        !           736:                break;
        !           737:
        !           738:        /*
        !           739:         * Set interface name.
        !           740:         */
        !           741:        case BIOCGETIF:
        !           742:                if (d->bd_bif == 0)
        !           743:                        error = EINVAL;
        !           744:                else
        !           745:                        bpf_ifname(d->bd_bif->bif_ifp, (struct ifreq *)addr);
        !           746:                break;
        !           747:
        !           748:        /*
        !           749:         * Set interface.
        !           750:         */
        !           751:        case BIOCSETIF:
        !           752:                error = bpf_setif(d, (struct ifreq *)addr);
        !           753:                break;
        !           754:
        !           755:        /*
        !           756:         * Set read timeout.
        !           757:         */
        !           758:        case BIOCSRTIMEOUT:
        !           759:                {
        !           760:                        struct timeval *tv = (struct timeval *)addr;
        !           761:
        !           762:                        /* Compute number of ticks. */
        !           763:                        d->bd_rtout = tv->tv_sec * hz + tv->tv_usec / tick;
        !           764:                        if (d->bd_rtout == 0 && tv->tv_usec != 0)
        !           765:                                d->bd_rtout = 1;
        !           766:                        break;
        !           767:                }
        !           768:
        !           769:        /*
        !           770:         * Get read timeout.
        !           771:         */
        !           772:        case BIOCGRTIMEOUT:
        !           773:                {
        !           774:                        struct timeval *tv = (struct timeval *)addr;
        !           775:
        !           776:                        tv->tv_sec = d->bd_rtout / hz;
        !           777:                        tv->tv_usec = (d->bd_rtout % hz) * tick;
        !           778:                        break;
        !           779:                }
        !           780:
        !           781:        /*
        !           782:         * Get packet stats.
        !           783:         */
        !           784:        case BIOCGSTATS:
        !           785:                {
        !           786:                        struct bpf_stat *bs = (struct bpf_stat *)addr;
        !           787:
        !           788:                        bs->bs_recv = d->bd_rcount;
        !           789:                        bs->bs_drop = d->bd_dcount;
        !           790:                        break;
        !           791:                }
        !           792:
        !           793:        /*
        !           794:         * Set immediate mode.
        !           795:         */
        !           796:        case BIOCIMMEDIATE:
        !           797:                d->bd_immediate = *(u_int *)addr;
        !           798:                break;
        !           799:
        !           800:        case BIOCVERSION:
        !           801:                {
        !           802:                        struct bpf_version *bv = (struct bpf_version *)addr;
        !           803:
        !           804:                        bv->bv_major = BPF_MAJOR_VERSION;
        !           805:                        bv->bv_minor = BPF_MINOR_VERSION;
        !           806:                        break;
        !           807:                }
        !           808:
        !           809:        case BIOCGHDRCMPLT:     /* get "header already complete" flag */
        !           810:                *(u_int *)addr = d->bd_hdrcmplt;
        !           811:                break;
        !           812:
        !           813:        case BIOCSHDRCMPLT:     /* set "header already complete" flag */
        !           814:                d->bd_hdrcmplt = *(u_int *)addr ? 1 : 0;
        !           815:                break;
        !           816:
        !           817:        case BIOCLOCK:          /* set "locked" flag (no reset) */
        !           818:                d->bd_locked = 1;
        !           819:                break;
        !           820:
        !           821:        case BIOCGFILDROP:      /* get "filter-drop" flag */
        !           822:                *(u_int *)addr = d->bd_fildrop;
        !           823:                break;
        !           824:
        !           825:        case BIOCSFILDROP:      /* set "filter-drop" flag */
        !           826:                d->bd_fildrop = *(u_int *)addr ? 1 : 0;
        !           827:                break;
        !           828:
        !           829:        case BIOCGDIRFILT:      /* get direction filter */
        !           830:                *(u_int *)addr = d->bd_dirfilt;
        !           831:                break;
        !           832:
        !           833:        case BIOCSDIRFILT:      /* set direction filter */
        !           834:                d->bd_dirfilt = (*(u_int *)addr) &
        !           835:                    (BPF_DIRECTION_IN|BPF_DIRECTION_OUT);
        !           836:                break;
        !           837:
        !           838:        case FIONBIO:           /* Non-blocking I/O */
        !           839:                if (*(int *)addr)
        !           840:                        d->bd_rtout = -1;
        !           841:                else
        !           842:                        d->bd_rtout = 0;
        !           843:                break;
        !           844:
        !           845:        case FIOASYNC:          /* Send signal on receive packets */
        !           846:                d->bd_async = *(int *)addr;
        !           847:                break;
        !           848:
        !           849:        /*
        !           850:         * N.B.  ioctl (FIOSETOWN) and fcntl (F_SETOWN) both end up doing
        !           851:         * the equivalent of a TIOCSPGRP and hence end up here.  *However*
        !           852:         * TIOCSPGRP's arg is a process group if it's positive and a process
        !           853:         * id if it's negative.  This is exactly the opposite of what the
        !           854:         * other two functions want!  Therefore there is code in ioctl and
        !           855:         * fcntl to negate the arg before calling here.
        !           856:         */
        !           857:        case TIOCSPGRP:         /* Process or group to send signals to */
        !           858:                d->bd_pgid = *(int *)addr;
        !           859:                d->bd_siguid = p->p_cred->p_ruid;
        !           860:                d->bd_sigeuid = p->p_ucred->cr_uid;
        !           861:                break;
        !           862:
        !           863:        case TIOCGPGRP:
        !           864:                *(int *)addr = d->bd_pgid;
        !           865:                break;
        !           866:
        !           867:        case BIOCSRSIG:         /* Set receive signal */
        !           868:                {
        !           869:                        u_int sig;
        !           870:
        !           871:                        sig = *(u_int *)addr;
        !           872:
        !           873:                        if (sig >= NSIG)
        !           874:                                error = EINVAL;
        !           875:                        else
        !           876:                                d->bd_sig = sig;
        !           877:                        break;
        !           878:                }
        !           879:        case BIOCGRSIG:
        !           880:                *(u_int *)addr = d->bd_sig;
        !           881:                break;
        !           882:        }
        !           883:        return (error);
        !           884: }
        !           885:
        !           886: /*
        !           887:  * Set d's packet filter program to fp.  If this file already has a filter,
        !           888:  * free it and replace it.  Returns EINVAL for bogus requests.
        !           889:  */
        !           890: int
        !           891: bpf_setf(struct bpf_d *d, struct bpf_program *fp, int wf)
        !           892: {
        !           893:        struct bpf_insn *fcode, *old;
        !           894:        u_int flen, size;
        !           895:        int s;
        !           896:
        !           897:        old = wf ? d->bd_wfilter : d->bd_rfilter;
        !           898:        if (fp->bf_insns == 0) {
        !           899:                if (fp->bf_len != 0)
        !           900:                        return (EINVAL);
        !           901:                s = splnet();
        !           902:                if (wf)
        !           903:                        d->bd_wfilter = 0;
        !           904:                else
        !           905:                        d->bd_rfilter = 0;
        !           906:                bpf_reset_d(d);
        !           907:                splx(s);
        !           908:                if (old != 0)
        !           909:                        free((caddr_t)old, M_DEVBUF);
        !           910:                return (0);
        !           911:        }
        !           912:        flen = fp->bf_len;
        !           913:        if (flen > BPF_MAXINSNS)
        !           914:                return (EINVAL);
        !           915:
        !           916:        size = flen * sizeof(*fp->bf_insns);
        !           917:        fcode = (struct bpf_insn *)malloc(size, M_DEVBUF, M_WAITOK);
        !           918:        if (copyin((caddr_t)fp->bf_insns, (caddr_t)fcode, size) == 0 &&
        !           919:            bpf_validate(fcode, (int)flen)) {
        !           920:                s = splnet();
        !           921:                if (wf)
        !           922:                        d->bd_wfilter = fcode;
        !           923:                else
        !           924:                        d->bd_rfilter = fcode;
        !           925:                bpf_reset_d(d);
        !           926:                splx(s);
        !           927:                if (old != 0)
        !           928:                        free((caddr_t)old, M_DEVBUF);
        !           929:
        !           930:                return (0);
        !           931:        }
        !           932:        free((caddr_t)fcode, M_DEVBUF);
        !           933:        return (EINVAL);
        !           934: }
        !           935:
        !           936: /*
        !           937:  * Detach a file from its current interface (if attached at all) and attach
        !           938:  * to the interface indicated by the name stored in ifr.
        !           939:  * Return an errno or 0.
        !           940:  */
        !           941: int
        !           942: bpf_setif(struct bpf_d *d, struct ifreq *ifr)
        !           943: {
        !           944:        struct bpf_if *bp, *candidate = NULL;
        !           945:        int s, error;
        !           946:
        !           947:        /*
        !           948:         * Look through attached interfaces for the named one.
        !           949:         */
        !           950:        for (bp = bpf_iflist; bp != 0; bp = bp->bif_next) {
        !           951:                struct ifnet *ifp = bp->bif_ifp;
        !           952:
        !           953:                if (ifp == 0 ||
        !           954:                    strcmp(ifp->if_xname, ifr->ifr_name) != 0)
        !           955:                        continue;
        !           956:
        !           957:                /*
        !           958:                 * We found the requested interface.
        !           959:                 */
        !           960:                if (candidate == NULL || candidate->bif_dlt > bp->bif_dlt)
        !           961:                        candidate = bp;
        !           962:        }
        !           963:
        !           964:        if (candidate != NULL) {
        !           965:                /*
        !           966:                 * Allocate the packet buffers if we need to.
        !           967:                 * If we're already attached to requested interface,
        !           968:                 * just flush the buffer.
        !           969:                 */
        !           970:                if (d->bd_sbuf == 0) {
        !           971:                        error = bpf_allocbufs(d);
        !           972:                        if (error != 0)
        !           973:                                return (error);
        !           974:                }
        !           975:                s = splnet();
        !           976:                if (candidate != d->bd_bif) {
        !           977:                        if (d->bd_bif)
        !           978:                                /*
        !           979:                                 * Detach if attached to something else.
        !           980:                                 */
        !           981:                                bpf_detachd(d);
        !           982:
        !           983:                        bpf_attachd(d, candidate);
        !           984:                }
        !           985:                bpf_reset_d(d);
        !           986:                splx(s);
        !           987:                return (0);
        !           988:        }
        !           989:        /* Not found. */
        !           990:        return (ENXIO);
        !           991: }
        !           992:
        !           993: /*
        !           994:  * Copy the interface name to the ifreq.
        !           995:  */
        !           996: void
        !           997: bpf_ifname(struct ifnet *ifp, struct ifreq *ifr)
        !           998: {
        !           999:        bcopy(ifp->if_xname, ifr->ifr_name, IFNAMSIZ);
        !          1000: }
        !          1001:
        !          1002: /*
        !          1003:  * Support for poll() system call
        !          1004:  */
        !          1005: int
        !          1006: bpfpoll(dev_t dev, int events, struct proc *p)
        !          1007: {
        !          1008:        struct bpf_d *d;
        !          1009:        int s, revents;
        !          1010:
        !          1011:        revents = events & (POLLIN | POLLRDNORM);
        !          1012:        if (revents == 0)
        !          1013:                return (0);             /* only support reading */
        !          1014:
        !          1015:        /*
        !          1016:         * An imitation of the FIONREAD ioctl code.
        !          1017:         */
        !          1018:        d = bpfilter_lookup(minor(dev));
        !          1019:        s = splnet();
        !          1020:        if (d->bd_hlen == 0 && (!d->bd_immediate || d->bd_slen == 0)) {
        !          1021:                revents = 0;            /* no data waiting */
        !          1022:                /*
        !          1023:                 * if there's a timeout, mark the time we started waiting.
        !          1024:                 */
        !          1025:                if (d->bd_rtout != -1 && d->bd_rdStart == 0)
        !          1026:                        d->bd_rdStart = ticks;
        !          1027:                selrecord(p, &d->bd_sel);
        !          1028:        }
        !          1029:        splx(s);
        !          1030:        return (revents);
        !          1031: }
        !          1032:
        !          1033: struct filterops bpfread_filtops =
        !          1034:        { 1, NULL, filt_bpfrdetach, filt_bpfread };
        !          1035:
        !          1036: int
        !          1037: bpfkqfilter(dev_t dev, struct knote *kn)
        !          1038: {
        !          1039:        struct bpf_d *d;
        !          1040:        struct klist *klist;
        !          1041:        int s;
        !          1042:
        !          1043:        d = bpfilter_lookup(minor(dev));
        !          1044:        switch (kn->kn_filter) {
        !          1045:        case EVFILT_READ:
        !          1046:                klist = &d->bd_sel.si_note;
        !          1047:                kn->kn_fop = &bpfread_filtops;
        !          1048:                break;
        !          1049:        default:
        !          1050:                return (1);
        !          1051:        }
        !          1052:
        !          1053:        kn->kn_hook = (caddr_t)((u_long)dev);
        !          1054:
        !          1055:        s = splnet();
        !          1056:        SLIST_INSERT_HEAD(klist, kn, kn_selnext);
        !          1057:        splx(s);
        !          1058:
        !          1059:        return (0);
        !          1060: }
        !          1061:
        !          1062: void
        !          1063: filt_bpfrdetach(struct knote *kn)
        !          1064: {
        !          1065:        dev_t dev = (dev_t)((u_long)kn->kn_hook);
        !          1066:        struct bpf_d *d;
        !          1067:        int s;
        !          1068:
        !          1069:        d = bpfilter_lookup(minor(dev));
        !          1070:        s = splnet();
        !          1071:        SLIST_REMOVE(&d->bd_sel.si_note, kn, knote, kn_selnext);
        !          1072:        splx(s);
        !          1073: }
        !          1074:
        !          1075: int
        !          1076: filt_bpfread(struct knote *kn, long hint)
        !          1077: {
        !          1078:        dev_t dev = (dev_t)((u_long)kn->kn_hook);
        !          1079:        struct bpf_d *d;
        !          1080:
        !          1081:        d = bpfilter_lookup(minor(dev));
        !          1082:        kn->kn_data = d->bd_hlen;
        !          1083:        if (d->bd_immediate)
        !          1084:                kn->kn_data += d->bd_slen;
        !          1085:        return (kn->kn_data > 0);
        !          1086: }
        !          1087:
        !          1088: /*
        !          1089:  * Incoming linkage from device drivers.  Process the packet pkt, of length
        !          1090:  * pktlen, which is stored in a contiguous buffer.  The packet is parsed
        !          1091:  * by each process' filter, and if accepted, stashed into the corresponding
        !          1092:  * buffer.
        !          1093:  */
        !          1094: int
        !          1095: bpf_tap(caddr_t arg, u_char *pkt, u_int pktlen, u_int direction)
        !          1096: {
        !          1097:        struct bpf_if *bp;
        !          1098:        struct bpf_d *d;
        !          1099:        size_t slen;
        !          1100:        int drop = 0;
        !          1101:
        !          1102:        /*
        !          1103:         * Note that the ipl does not have to be raised at this point.
        !          1104:         * The only problem that could arise here is that if two different
        !          1105:         * interfaces shared any data.  This is not the case.
        !          1106:         */
        !          1107:        bp = (struct bpf_if *)arg;
        !          1108:        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
        !          1109:                ++d->bd_rcount;
        !          1110:                if ((direction & d->bd_dirfilt) != 0)
        !          1111:                        slen = 0;
        !          1112:                else
        !          1113:                        slen = bpf_filter(d->bd_rfilter, pkt, pktlen, pktlen);
        !          1114:                if (slen != 0) {
        !          1115:                        bpf_catchpacket(d, pkt, pktlen, slen, bcopy);
        !          1116:                        if (d->bd_fildrop)
        !          1117:                                drop++;
        !          1118:                }
        !          1119:        }
        !          1120:
        !          1121:        return (drop);
        !          1122: }
        !          1123:
        !          1124: /*
        !          1125:  * Copy data from an mbuf chain into a buffer.  This code is derived
        !          1126:  * from m_copydata in sys/uipc_mbuf.c.
        !          1127:  */
        !          1128: void
        !          1129: bpf_mcopy(const void *src_arg, void *dst_arg, size_t len)
        !          1130: {
        !          1131:        const struct mbuf *m;
        !          1132:        u_int count;
        !          1133:        u_char *dst;
        !          1134:
        !          1135:        m = src_arg;
        !          1136:        dst = dst_arg;
        !          1137:        while (len > 0) {
        !          1138:                if (m == 0)
        !          1139:                        panic("bpf_mcopy");
        !          1140:                count = min(m->m_len, len);
        !          1141:                bcopy(mtod(m, caddr_t), (caddr_t)dst, count);
        !          1142:                m = m->m_next;
        !          1143:                dst += count;
        !          1144:                len -= count;
        !          1145:        }
        !          1146: }
        !          1147:
        !          1148: /*
        !          1149:  * Incoming linkage from device drivers, when packet is in an mbuf chain.
        !          1150:  */
        !          1151: void
        !          1152: bpf_mtap(caddr_t arg, struct mbuf *m, u_int direction)
        !          1153: {
        !          1154:        struct bpf_if *bp = (struct bpf_if *)arg;
        !          1155:        struct bpf_d *d;
        !          1156:        size_t pktlen, slen;
        !          1157:        struct mbuf *m0;
        !          1158:
        !          1159:        if (m == NULL)
        !          1160:                return;
        !          1161:
        !          1162:        pktlen = 0;
        !          1163:        for (m0 = m; m0 != 0; m0 = m0->m_next)
        !          1164:                pktlen += m0->m_len;
        !          1165:
        !          1166:        for (d = bp->bif_dlist; d != 0; d = d->bd_next) {
        !          1167:                ++d->bd_rcount;
        !          1168:                if ((direction & d->bd_dirfilt) != 0)
        !          1169:                        slen = 0;
        !          1170:                else
        !          1171:                        slen = bpf_filter(d->bd_rfilter, (u_char *)m,
        !          1172:                            pktlen, 0);
        !          1173:
        !          1174:                if (slen == 0)
        !          1175:                    continue;
        !          1176:
        !          1177:                bpf_catchpacket(d, (u_char *)m, pktlen, slen, bpf_mcopy);
        !          1178:                if (d->bd_fildrop)
        !          1179:                        m->m_flags |= M_FILDROP;
        !          1180:        }
        !          1181: }
        !          1182:
        !          1183: /*
        !          1184:  * Incoming linkage from device drivers, where we have a mbuf chain
        !          1185:  * but need to prepend some arbitrary header from a linear buffer.
        !          1186:  *
        !          1187:  * Con up a minimal dummy header to pacify bpf.  Allocate (only) a
        !          1188:  * struct m_hdr on the stack.  This is safe as bpf only reads from the
        !          1189:  * fields in this header that we initialize, and will not try to free
        !          1190:  * it or keep a pointer to it.
        !          1191:  */
        !          1192: void
        !          1193: bpf_mtap_hdr(caddr_t arg, caddr_t data, u_int dlen, struct mbuf *m,
        !          1194:     u_int direction)
        !          1195: {
        !          1196:        struct m_hdr mh;
        !          1197:
        !          1198:        mh.mh_flags = 0;
        !          1199:        mh.mh_next = m;
        !          1200:        mh.mh_len = dlen;
        !          1201:        mh.mh_data = data;
        !          1202:
        !          1203:        bpf_mtap(arg, (struct mbuf *) &mh, direction);
        !          1204:        m->m_flags |= mh.mh_flags & M_FILDROP;
        !          1205: }
        !          1206:
        !          1207: /*
        !          1208:  * Incoming linkage from device drivers, where we have a mbuf chain
        !          1209:  * but need to prepend the address family.
        !          1210:  *
        !          1211:  * Con up a minimal dummy header to pacify bpf.  We allocate (only) a
        !          1212:  * struct m_hdr on the stack.  This is safe as bpf only reads from the
        !          1213:  * fields in this header that we initialize, and will not try to free
        !          1214:  * it or keep a pointer to it.
        !          1215:  */
        !          1216: void
        !          1217: bpf_mtap_af(caddr_t arg, u_int32_t af, struct mbuf *m, u_int direction)
        !          1218: {
        !          1219:        struct m_hdr mh;
        !          1220:
        !          1221:        mh.mh_flags = 0;
        !          1222:        mh.mh_next = m;
        !          1223:        mh.mh_len = 4;
        !          1224:        mh.mh_data = (caddr_t)&af;
        !          1225:
        !          1226:        bpf_mtap(arg, (struct mbuf *) &mh, direction);
        !          1227:        m->m_flags |= mh.mh_flags & M_FILDROP;
        !          1228: }
        !          1229:
        !          1230: /*
        !          1231:  * Move the packet data from interface memory (pkt) into the
        !          1232:  * store buffer.  Return 1 if it's time to wakeup a listener (buffer full),
        !          1233:  * otherwise 0.  "copy" is the routine called to do the actual data
        !          1234:  * transfer.  bcopy is passed in to copy contiguous chunks, while
        !          1235:  * bpf_mcopy is passed in to copy mbuf chains.  In the latter case,
        !          1236:  * pkt is really an mbuf.
        !          1237:  */
        !          1238: void
        !          1239: bpf_catchpacket(struct bpf_d *d, u_char *pkt, size_t pktlen, size_t snaplen,
        !          1240:     void (*cpfn)(const void *, void *, size_t))
        !          1241: {
        !          1242:        struct bpf_hdr *hp;
        !          1243:        int totlen, curlen;
        !          1244:        int hdrlen = d->bd_bif->bif_hdrlen;
        !          1245:        struct timeval tv;
        !          1246:
        !          1247:        /*
        !          1248:         * Figure out how many bytes to move.  If the packet is
        !          1249:         * greater or equal to the snapshot length, transfer that
        !          1250:         * much.  Otherwise, transfer the whole packet (unless
        !          1251:         * we hit the buffer size limit).
        !          1252:         */
        !          1253:        totlen = hdrlen + min(snaplen, pktlen);
        !          1254:        if (totlen > d->bd_bufsize)
        !          1255:                totlen = d->bd_bufsize;
        !          1256:
        !          1257:        /*
        !          1258:         * Round up the end of the previous packet to the next longword.
        !          1259:         */
        !          1260:        curlen = BPF_WORDALIGN(d->bd_slen);
        !          1261:        if (curlen + totlen > d->bd_bufsize) {
        !          1262:                /*
        !          1263:                 * This packet will overflow the storage buffer.
        !          1264:                 * Rotate the buffers if we can, then wakeup any
        !          1265:                 * pending reads.
        !          1266:                 */
        !          1267:                if (d->bd_fbuf == 0) {
        !          1268:                        /*
        !          1269:                         * We haven't completed the previous read yet,
        !          1270:                         * so drop the packet.
        !          1271:                         */
        !          1272:                        ++d->bd_dcount;
        !          1273:                        return;
        !          1274:                }
        !          1275:                ROTATE_BUFFERS(d);
        !          1276:                bpf_wakeup(d);
        !          1277:                curlen = 0;
        !          1278:        }
        !          1279:
        !          1280:        /*
        !          1281:         * Append the bpf header.
        !          1282:         */
        !          1283:        hp = (struct bpf_hdr *)(d->bd_sbuf + curlen);
        !          1284:        microtime(&tv);
        !          1285:        hp->bh_tstamp.tv_sec = tv.tv_sec;
        !          1286:        hp->bh_tstamp.tv_usec = tv.tv_usec;
        !          1287:        hp->bh_datalen = pktlen;
        !          1288:        hp->bh_hdrlen = hdrlen;
        !          1289:        /*
        !          1290:         * Copy the packet data into the store buffer and update its length.
        !          1291:         */
        !          1292:        (*cpfn)(pkt, (u_char *)hp + hdrlen, (hp->bh_caplen = totlen - hdrlen));
        !          1293:        d->bd_slen = curlen + totlen;
        !          1294:
        !          1295:        if (d->bd_immediate) {
        !          1296:                /*
        !          1297:                 * Immediate mode is set.  A packet arrived so any
        !          1298:                 * reads should be woken up.
        !          1299:                 */
        !          1300:                bpf_wakeup(d);
        !          1301:        }
        !          1302:
        !          1303:        if (d->bd_rdStart && (d->bd_rtout + d->bd_rdStart < ticks)) {
        !          1304:                /*
        !          1305:                 * we could be selecting on the bpf, and we
        !          1306:                 * may have timeouts set.  We got here by getting
        !          1307:                 * a packet, so wake up the reader.
        !          1308:                 */
        !          1309:                if (d->bd_fbuf) {
        !          1310:                        d->bd_rdStart = 0;
        !          1311:                        ROTATE_BUFFERS(d);
        !          1312:                        bpf_wakeup(d);
        !          1313:                        curlen = 0;
        !          1314:                }
        !          1315:        }
        !          1316: }
        !          1317:
        !          1318: /*
        !          1319:  * Initialize all nonzero fields of a descriptor.
        !          1320:  */
        !          1321: int
        !          1322: bpf_allocbufs(struct bpf_d *d)
        !          1323: {
        !          1324:        d->bd_fbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT);
        !          1325:        if (d->bd_fbuf == NULL)
        !          1326:                return (ENOBUFS);
        !          1327:        d->bd_sbuf = (caddr_t)malloc(d->bd_bufsize, M_DEVBUF, M_NOWAIT);
        !          1328:        if (d->bd_sbuf == NULL) {
        !          1329:                free(d->bd_fbuf, M_DEVBUF);
        !          1330:                return (ENOBUFS);
        !          1331:        }
        !          1332:        d->bd_slen = 0;
        !          1333:        d->bd_hlen = 0;
        !          1334:        return (0);
        !          1335: }
        !          1336:
        !          1337: /*
        !          1338:  * Free buffers currently in use by a descriptor
        !          1339:  * when the reference count drops to zero.
        !          1340:  */
        !          1341: void
        !          1342: bpf_freed(struct bpf_d *d)
        !          1343: {
        !          1344:        if (--d->bd_ref > 0)
        !          1345:                return;
        !          1346:
        !          1347:        if (d->bd_sbuf != 0) {
        !          1348:                free(d->bd_sbuf, M_DEVBUF);
        !          1349:                if (d->bd_hbuf != 0)
        !          1350:                        free(d->bd_hbuf, M_DEVBUF);
        !          1351:                if (d->bd_fbuf != 0)
        !          1352:                        free(d->bd_fbuf, M_DEVBUF);
        !          1353:        }
        !          1354:        if (d->bd_rfilter)
        !          1355:                free((caddr_t)d->bd_rfilter, M_DEVBUF);
        !          1356:        if (d->bd_wfilter)
        !          1357:                free((caddr_t)d->bd_wfilter, M_DEVBUF);
        !          1358:
        !          1359:        bpfilter_destroy(d);
        !          1360: }
        !          1361:
        !          1362: /*
        !          1363:  * Attach an interface to bpf.  driverp is a pointer to a (struct bpf_if *)
        !          1364:  * in the driver's softc; dlt is the link layer type; hdrlen is the fixed
        !          1365:  * size of the link header (variable length headers not yet supported).
        !          1366:  */
        !          1367: void
        !          1368: bpfattach(caddr_t *driverp, struct ifnet *ifp, u_int dlt, u_int hdrlen)
        !          1369: {
        !          1370:        struct bpf_if *bp;
        !          1371:        bp = (struct bpf_if *)malloc(sizeof(*bp), M_DEVBUF, M_DONTWAIT);
        !          1372:
        !          1373:        if (bp == 0)
        !          1374:                panic("bpfattach");
        !          1375:
        !          1376:        bp->bif_dlist = 0;
        !          1377:        bp->bif_driverp = (struct bpf_if **)driverp;
        !          1378:        bp->bif_ifp = ifp;
        !          1379:        bp->bif_dlt = dlt;
        !          1380:
        !          1381:        bp->bif_next = bpf_iflist;
        !          1382:        bpf_iflist = bp;
        !          1383:
        !          1384:        *bp->bif_driverp = NULL;
        !          1385:
        !          1386:        /*
        !          1387:         * Compute the length of the bpf header.  This is not necessarily
        !          1388:         * equal to SIZEOF_BPF_HDR because we want to insert spacing such
        !          1389:         * that the network layer header begins on a longword boundary (for
        !          1390:         * performance reasons and to alleviate alignment restrictions).
        !          1391:         */
        !          1392:        bp->bif_hdrlen = BPF_WORDALIGN(hdrlen + SIZEOF_BPF_HDR) - hdrlen;
        !          1393: }
        !          1394:
        !          1395: /* Detach an interface from its attached bpf device.  */
        !          1396: void
        !          1397: bpfdetach(struct ifnet *ifp)
        !          1398: {
        !          1399:        struct bpf_if *bp, *nbp, **pbp = &bpf_iflist;
        !          1400:        struct bpf_d *bd;
        !          1401:        int maj;
        !          1402:
        !          1403:        for (bp = bpf_iflist; bp; bp = nbp) {
        !          1404:                nbp= bp->bif_next;
        !          1405:                if (bp->bif_ifp == ifp) {
        !          1406:                        *pbp = nbp;
        !          1407:
        !          1408:                        /* Locate the major number. */
        !          1409:                        for (maj = 0; maj < nchrdev; maj++)
        !          1410:                                if (cdevsw[maj].d_open == bpfopen)
        !          1411:                                        break;
        !          1412:
        !          1413:                        for (bd = bp->bif_dlist; bd; bd = bp->bif_dlist) {
        !          1414:                                struct bpf_d *d;
        !          1415:
        !          1416:                                /*
        !          1417:                                 * Locate the minor number and nuke the vnode
        !          1418:                                 * for any open instance.
        !          1419:                                 */
        !          1420:                                LIST_FOREACH(d, &bpf_d_list, bd_list)
        !          1421:                                        if (d == bd) {
        !          1422:                                                vdevgone(maj, d->bd_unit,
        !          1423:                                                    d->bd_unit, VCHR);
        !          1424:                                                break;
        !          1425:                                        }
        !          1426:                        }
        !          1427:
        !          1428:                        free(bp, M_DEVBUF);
        !          1429:                } else
        !          1430:                        pbp = &bp->bif_next;
        !          1431:        }
        !          1432:        ifp->if_bpf = NULL;
        !          1433: }
        !          1434:
        !          1435: int
        !          1436: bpf_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
        !          1437:     size_t newlen)
        !          1438: {
        !          1439:        int newval;
        !          1440:        int error;
        !          1441:
        !          1442:        if (namelen != 1)
        !          1443:                return (ENOTDIR);
        !          1444:
        !          1445:        switch (name[0]) {
        !          1446:        case NET_BPF_BUFSIZE:
        !          1447:                newval = bpf_bufsize;
        !          1448:                error = sysctl_int(oldp, oldlenp, newp, newlen, &newval);
        !          1449:                if (error)
        !          1450:                        return (error);
        !          1451:                if (newval < BPF_MINBUFSIZE || newval > bpf_maxbufsize)
        !          1452:                        return (EINVAL);
        !          1453:                bpf_bufsize = newval;
        !          1454:                break;
        !          1455:        case NET_BPF_MAXBUFSIZE:
        !          1456:                newval = bpf_maxbufsize;
        !          1457:                error = sysctl_int(oldp, oldlenp, newp, newlen, &newval);
        !          1458:                if (error)
        !          1459:                        return (error);
        !          1460:                if (newval < BPF_MINBUFSIZE)
        !          1461:                        return (EINVAL);
        !          1462:                bpf_maxbufsize = newval;
        !          1463:                break;
        !          1464:        default:
        !          1465:                return (EOPNOTSUPP);
        !          1466:        }
        !          1467:        return (0);
        !          1468: }
        !          1469:
        !          1470: struct bpf_d *
        !          1471: bpfilter_lookup(int unit)
        !          1472: {
        !          1473:        struct bpf_d *bd;
        !          1474:
        !          1475:        LIST_FOREACH(bd, &bpf_d_list, bd_list)
        !          1476:                if (bd->bd_unit == unit)
        !          1477:                        return (bd);
        !          1478:        return (NULL);
        !          1479: }
        !          1480:
        !          1481: struct bpf_d *
        !          1482: bpfilter_create(int unit)
        !          1483: {
        !          1484:        struct bpf_d *bd;
        !          1485:
        !          1486:        if ((bd = bpfilter_lookup(unit)) != NULL)
        !          1487:                return (NULL);
        !          1488:        if ((bd = malloc(sizeof(*bd), M_DEVBUF, M_NOWAIT)) != NULL) {
        !          1489:                bzero(bd, sizeof(*bd));
        !          1490:                bd->bd_unit = unit;
        !          1491:                LIST_INSERT_HEAD(&bpf_d_list, bd, bd_list);
        !          1492:        }
        !          1493:        return (bd);
        !          1494: }
        !          1495:
        !          1496: void
        !          1497: bpfilter_destroy(struct bpf_d *bd)
        !          1498: {
        !          1499:        LIST_REMOVE(bd, bd_list);
        !          1500:        free(bd, M_DEVBUF);
        !          1501: }
        !          1502:
        !          1503: /*
        !          1504:  * Get a list of available data link type of the interface.
        !          1505:  */
        !          1506: int
        !          1507: bpf_getdltlist(struct bpf_d *d, struct bpf_dltlist *bfl)
        !          1508: {
        !          1509:        int n, error;
        !          1510:        struct ifnet *ifp;
        !          1511:        struct bpf_if *bp;
        !          1512:
        !          1513:        ifp = d->bd_bif->bif_ifp;
        !          1514:        n = 0;
        !          1515:        error = 0;
        !          1516:        for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
        !          1517:                if (bp->bif_ifp != ifp)
        !          1518:                        continue;
        !          1519:                if (bfl->bfl_list != NULL) {
        !          1520:                        if (n >= bfl->bfl_len)
        !          1521:                                return (ENOMEM);
        !          1522:                        error = copyout(&bp->bif_dlt,
        !          1523:                            bfl->bfl_list + n, sizeof(u_int));
        !          1524:                        if (error)
        !          1525:                                break;
        !          1526:                }
        !          1527:                n++;
        !          1528:        }
        !          1529:
        !          1530:        bfl->bfl_len = n;
        !          1531:        return (error);
        !          1532: }
        !          1533:
        !          1534: /*
        !          1535:  * Set the data link type of a BPF instance.
        !          1536:  */
        !          1537: int
        !          1538: bpf_setdlt(struct bpf_d *d, u_int dlt)
        !          1539: {
        !          1540:        int s;
        !          1541:        struct ifnet *ifp;
        !          1542:        struct bpf_if *bp;
        !          1543:
        !          1544:        if (d->bd_bif->bif_dlt == dlt)
        !          1545:                return (0);
        !          1546:        ifp = d->bd_bif->bif_ifp;
        !          1547:        for (bp = bpf_iflist; bp != NULL; bp = bp->bif_next) {
        !          1548:                if (bp->bif_ifp == ifp && bp->bif_dlt == dlt)
        !          1549:                        break;
        !          1550:        }
        !          1551:        if (bp == NULL)
        !          1552:                return (EINVAL);
        !          1553:        s = splnet();
        !          1554:        bpf_detachd(d);
        !          1555:        bpf_attachd(d, bp);
        !          1556:        bpf_reset_d(d);
        !          1557:        splx(s);
        !          1558:        return (0);
        !          1559: }

CVSweb