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