|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* Copyright (c) 1997, 1998 Apple Computer, Inc. All Rights Reserved */ ! 23: /* ! 24: * @(#)if_blue.c 1.1 (MacOSX) 6/10/43 ! 25: * Justin Walker, 9970520 ! 26: * First wave - splitter and notification support for the Blue Box ! 27: * 980130 - Second wave - Performance improvements, reorg and cleanup ! 28: */ ! 29: ! 30: #include <sys/kdebug.h> ! 31: #if KDEBUG ! 32: ! 33: #define DBG_SPLT_BFCHK DRVDBG_CODE(DBG_DRVSPLT, 0) ! 34: #define DBG_SPLT_APPND DRVDBG_CODE(DBG_DRVSPLT, 1) ! 35: #define DBG_SPLT_MBUF DRVDBG_CODE(DBG_DRVSPLT, 2) ! 36: #define DBG_SPLT_DUP DRVDBG_CODE(DBG_DRVSPLT, 3) ! 37: #define DBG_SPLT_PAD DRVDBG_CODE(DBG_DRVSPLT, 4) ! 38: ! 39: #endif ! 40: ! 41: ! 42: #include <sys/param.h> ! 43: #include <sys/systm.h> ! 44: #include <sys/kernel.h> ! 45: #include <sys/malloc.h> ! 46: #include <sys/mbuf.h> ! 47: #include <sys/protosw.h> ! 48: #include <sys/socket.h> ! 49: #include <sys/socketvar.h> ! 50: #include <sys/ioctl.h> ! 51: #include <sys/errno.h> ! 52: #include <sys/syslog.h> ! 53: #include <sys/proc.h> ! 54: #include <sys/vm.h> ! 55: ! 56: #include <kern/cpu_number.h> ! 57: ! 58: #include <net/if.h> ! 59: #include <net/netisr.h> ! 60: #include <net/route.h> ! 61: #include <net/if_llc.h> ! 62: #include <net/if_dl.h> ! 63: #include <net/if_types.h> ! 64: #include "if_blue.h" ! 65: #include "ndrv.h" ! 66: ! 67: #if INET ! 68: #include <netinet/in.h> ! 69: #include <netinet/in_var.h> ! 70: #endif ! 71: #include <netinet/if_ether.h> ! 72: ! 73: #if NS ! 74: #include <netns/ns.h> ! 75: #include <netns/ns_if.h> ! 76: #endif ! 77: ! 78: #if ISO ! 79: #include <netiso/argo_debug.h> ! 80: #include <netiso/iso.h> ! 81: #include <netiso/iso_var.h> ! 82: #include <netiso/iso_snpac.h> ! 83: #endif ! 84: ! 85: #if LLC ! 86: #include <netccitt/dll.h> ! 87: #include <netccitt/llc_var.h> ! 88: #endif ! 89: ! 90: #include <sys/systm.h> ! 91: #include <machine/spl.h> ! 92: #include <kern/thread.h> ! 93: #include <kern/queue.h> ! 94: ! 95: /* Dummy IFs to differentiate source of looped packets */ ! 96: struct ifnet rhap_if_s; ! 97: struct ifnet *rhap_if = &rhap_if_s; ! 98: struct ifnet_blue *blue_if; ! 99: struct sockaddr_dl ndrvsrc = {sizeof (struct sockaddr_dl), AF_NDRV}; ! 100: ! 101: struct ifqueue blueq; ! 102: ! 103: extern int if_register(register struct BlueFilter *f ! 104: #ifdef BF_if ! 105: , ! 106: register struct ifnet *ifp ! 107: #endif ! 108: ); ! 109: ! 110: /* ! 111: * Blue Box support: ! 112: * 1st cut: the Y splitter ! 113: * A process turns on the splitter by opening the "raw" device ! 114: * (socket() for AF_NDRV) and issuing an SIOCSSPLITTER ioctl. ! 115: * Incoming packets are routed into MacOSX as well as to the requesting ! 116: * interface. ! 117: * Outbound packets are sent, and are examined to see if they should go ! 118: * back up (loopback, sort of). Packets that are looped back include: ! 119: * broadcast ! 120: * multicast ! 121: */ ! 122: int ! 123: new_splitter(register struct socket *so) ! 124: { register struct ifnet_blue *ifb; ! 125: register struct ndrv_cb *np; ! 126: register struct ifnet *ifp; ! 127: struct BlueFilter filter; ! 128: int retval; ! 129: ! 130: if ((ifb = _MALLOC(sizeof (struct ifnet_blue), M_PCB, M_WAITOK)) ! 131: == NULL) ! 132: { ! 133: #if BLUE_DEBUG ! 134: kprintf("Can't create new splitter\n"); ! 135: #endif ! 136: return(ENOBUFS); ! 137: } ! 138: bzero(ifb, sizeof(struct ifnet_blue)); ! 139: np = (struct ndrv_cb *)so->so_pcb; ! 140: #if BLUE_DEBUG ! 141: kprintf("NEW SPLT: %x, %x\n", so, np); ! 142: if (np) ! 143: printf("SIG: %x, ifp: %x\n", np->nd_signature, np->nd_if); ! 144: #endif ! 145: if (np == NULL) ! 146: return(EINVAL); /* XXX */ ! 147: if (np->nd_signature != NDRV_SIGNATURE) ! 148: return(EINVAL); /* XXX */ ! 149: if ((ifp = np->nd_if) == NULL) ! 150: return(EINVAL); /* XXX */ ! 151: if (ifp->if_flags & IFF_SPLITTER) ! 152: return(EBUSY); ! 153: if ((ifp->if_flags&IFF_UP) == 0) ! 154: return(ENXIO); ! 155: /* ! 156: * Bump the receive sockbuf size - need a big buffer ! 157: * to offset the scheduling latencies of the system ! 158: * Try to get something if our grandiose design fails. ! 159: */ ! 160: if (sbreserve(&so->so_rcv, 131072) == 0) ! 161: { if (sbreserve(&so->so_rcv, 65536) == 0 && ! 162: sbreserve(&so->so_rcv, 32768) == 0 && ! 163: sbreserve(&so->so_rcv, 16384) == 0) ! 164: return(ENOBUFS); ! 165: } ! 166: ifp->if_flags |= IFF_SPLITTER; ! 167: /* ! 168: * Register each IP address associated with this ifnet ! 169: * This takes care of addresses registered prior to startup ! 170: * of the BlueBox. ! 171: * TODO: Appletalk sockaddrs ! 172: */ ! 173: #define IFA2IN(ifa) \ ! 174: ((struct in_addr) \ ! 175: ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr).s_addr ! 176: { struct ifaddr *ifa; ! 177: ! 178: TAILQ_FOREACH(ifa, &ifp->if_addrhead, ifa_link) ! 179: { if (ifa->ifa_addr->sa_family == AF_INET) ! 180: { filter.BF_flags = (BF_ALLOC|BF_IP); ! 181: filter.BF_address = IFA2IN(ifa); ! 182: #if BLUE_DEBUG ! 183: kprintf("[1] IP registering [%x] %x\n", ! 184: filter.BF_flags, ! 185: (unsigned int)filter.BF_address); ! 186: #endif ! 187: retval = if_register(&filter); ! 188: #if BLUE_DEBUG ! 189: if (retval) ! 190: kprintf("if_register(IP) returns %d\n", ! 191: retval); ! 192: #endif ! 193: } ! 194: } ! 195: } ! 196: ! 197: blue_if = (struct ifnet_blue *)ifb; ! 198: ifb->blue_pid = ((struct proc *)current_proc())->p_pid; ! 199: ifb->ifb_so = so; ! 200: ifp->if_Y = (void *)ifb; ! 201: return(0); ! 202: } ! 203: ! 204: /* ! 205: * Determine if destined for BlueBox or not. Called from ether_output() ! 206: * and ether_input(). ! 207: * Returns NULL if we ate the packet, otherwise, the mbuf to continue with. ! 208: */ ! 209: struct mbuf * ! 210: splitter_input(register struct mbuf *m, register struct ifnet *ifp) ! 211: { register struct ifnet_blue *ifb; ! 212: #if 0 ! 213: register int s, flags; ! 214: #else ! 215: register int flags; ! 216: #endif ! 217: int rv; ! 218: register struct mbuf *m0 = NULL; ! 219: struct mbuf *m1; ! 220: extern struct mbuf *m_dup(struct mbuf *, int); ! 221: extern int BlueFilter_check(struct mbuf **, struct ifnet_blue *); ! 222: extern void blue_notify(struct mbuf *); ! 223: extern int blue_notify1(struct mbuf *); ! 224: ! 225: if ((ifb = (struct ifnet_blue *)ifp->if_Y) == NULL) ! 226: { ifp->if_flags &= ~IFF_SPLITTER; ! 227: return(m); ! 228: } ! 229: flags = m->m_flags; ! 230: m1 = m; ! 231: /* Check filters */ ! 232: if ((rv = BlueFilter_check(&m1, ifb)) == -1) ! 233: return(m1); /* Not for BB, MacOSX will want to see it. */ ! 234: m = m1; ! 235: if (rv == 0) /* It's for both - dup the packet */ ! 236: { m0 = m_dup(m, M_DONTWAIT); ! 237: if (m0 == NULL) ! 238: { blue_if->no_bufs1++; ! 239: return(m); /* Give it to MacOSX */ ! 240: } ! 241: } else ! 242: { /* Oy, veh! The depths to which we stoop! */ ! 243: /* We'll just assume M_PKTHDR is set */ ! 244: if (m->m_next == 0 && (m->m_flags & M_EXT) ! 245: && m->m_pkthdr.len <= MHLEN) ! 246: { m0 = m_dup(m, M_DONTWAIT); ! 247: if (m0) ! 248: { m_freem(m); ! 249: m = NULL; ! 250: } else ! 251: m0 = m; ! 252: } else ! 253: m0 = m; ! 254: } ! 255: if (flags & 0x10) ! 256: blue_if->pkts_looped_r2b++; ! 257: ! 258: #if 0 ! 259: schednetisr(NETISR_BLUE); ! 260: s = splimp(); ! 261: if (IF_QFULL(&blueq)) { ! 262: IF_DROP(&blueq); ! 263: m_freem(m0); ! 264: } else ! 265: IF_ENQUEUE(&blueq, m0); ! 266: splx(s); ! 267: #else ! 268: blue_notify1(m0); ! 269: sorwakeup(blue_if->ifb_so); ! 270: blue_if->sig_sent++; ! 271: #endif ! 272: /* If we eat the packet (rv==1) return NULL */ ! 273: return(rv == 0 ? m : NULL); ! 274: } ! 275: ! 276: void ! 277: blue_notify() ! 278: { register int do_notify = 0; ! 279: register int s; ! 280: register struct mbuf *m; ! 281: extern int blue_notify1(struct mbuf *); ! 282: ! 283: /* ! 284: * Move the packets from the blue queue to the indicated socket ! 285: * If we haven't told anyone yet, send a signal. ! 286: */ ! 287: for (;;) ! 288: { s = splimp(); ! 289: IF_DEQUEUE(&blueq, m); ! 290: splx(s); ! 291: if (m == 0) ! 292: break; ! 293: ! 294: do_notify = blue_notify1(m); ! 295: } ! 296: if (do_notify) ! 297: sorwakeup(blue_if->ifb_so); /* Start by using SIGIO */ ! 298: } ! 299: ! 300: int ! 301: blue_notify1(register struct mbuf *m) ! 302: { register int rv; ! 303: ! 304: /* move packet from if queue to socket */ ! 305: /* !!!Fix this to work generically!!! */ ! 306: ndrvsrc.sdl_type = IFT_ETHER; ! 307: ndrvsrc.sdl_nlen = 0; ! 308: ndrvsrc.sdl_alen = 6; ! 309: ndrvsrc.sdl_slen = 0; ! 310: bcopy(m->m_data+6, &ndrvsrc.sdl_data, 6); ! 311: ! 312: if (sbappendaddr(&(blue_if->ifb_so->so_rcv), ! 313: (struct sockaddr *)&ndrvsrc, m, ! 314: (struct mbuf *)0) == 0) ! 315: { register struct mbuf *n; ! 316: ! 317: KERNEL_DEBUG(DBG_SPLT_APPND | DBG_FUNC_NONE, ! 318: blue_if->ifb_so->so_rcv.sb_cc, ! 319: blue_if->ifb_so->so_rcv.sb_hiwat, ! 320: blue_if->ifb_so->so_rcv.sb_mbcnt, ! 321: blue_if->ifb_so->so_rcv.sb_mbmax, ! 322: blue_if->ifb_so->so_rcv.sb_lowat ); ! 323: if (m->m_flags & M_PKTHDR) ! 324: KERNEL_DEBUG(DBG_SPLT_MBUF, 0, m->m_pkthdr.len, ! 325: m->m_flags, 0, 0); ! 326: for (n = m; n; n = n->m_next) ! 327: KERNEL_DEBUG(DBG_SPLT_MBUF, 1, ! 328: (int)n, (int)n->m_next, n->m_len, ! 329: n->m_flags); ! 330: m_freem(m); ! 331: blue_if->full_sockbuf++; ! 332: rv = 1; ! 333: } else ! 334: { register struct mbuf *n; ! 335: ! 336: KERNEL_DEBUG(DBG_SPLT_APPND | DBG_FUNC_NONE, ! 337: blue_if->ifb_so->so_rcv.sb_cc, ! 338: blue_if->ifb_so->so_rcv.sb_hiwat, ! 339: blue_if->ifb_so->so_rcv.sb_mbcnt, ! 340: blue_if->ifb_so->so_rcv.sb_mbmax, ! 341: blue_if->ifb_so->so_rcv.sb_lowat ); ! 342: if (m->m_flags & M_PKTHDR) ! 343: KERNEL_DEBUG(DBG_SPLT_MBUF, 2, m->m_pkthdr.len, ! 344: m->m_flags, 0, 0); ! 345: for (n = m; n; n = n->m_next) ! 346: KERNEL_DEBUG(DBG_SPLT_MBUF, 3, ! 347: (int)n, (int)n->m_next, n->m_len, ! 348: n->m_flags); ! 349: blue_if->pkts_up++; ! 350: rv = 0; ! 351: } ! 352: return(rv); ! 353: } ! 354: ! 355: /* ! 356: * Check the incoming packet against the registered filters ! 357: * Rules (the rules are subtly different for input to the ! 358: * y-adapter customer and the "real" stacks): ! 359: * For BB: return 1 ! 360: * For Both: return 0 ! 361: * Not For BB: return -1 ! 362: * Multicast/Broadcast => For Both ! 363: * Hack: ! 364: * if no registered filters, For Both ! 365: * Atalk filter registered ! 366: * filter matches => For BB else Not For BB ! 367: * IP filter registered ! 368: * filter matches => For BB else Not For BB ! 369: * Not For BB ! 370: * WARNING: this is a big-endian routine. ! 371: * WARNING 2: m_pullup can give you a new mbuf! ! 372: */ ! 373: int ! 374: BlueFilter_check(struct mbuf **m0, register struct ifnet_blue *ifb) ! 375: { register struct BlueFilter *bf; ! 376: register unsigned char *p; ! 377: register unsigned short *s; ! 378: register unsigned long *l; ! 379: int total, flags; ! 380: register struct mbuf *m; ! 381: extern struct mbuf *m_pullup(struct mbuf *, int); ! 382: #define FILTER_LEN 32 ! 383: ! 384: KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_START, 0, 0, 0, 0, 0 ); ! 385: ! 386: m = *m0; ! 387: if (FILTER_LEN > m->m_pkthdr.len) ! 388: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 0, 0, 0, 0, 0 ); ! 389: return(-1); ! 390: } ! 391: flags = m->m_flags; ! 392: while ((FILTER_LEN > m->m_len) && m->m_next) { ! 393: total = m->m_len + (m->m_next)->m_len; ! 394: if ((m = m_pullup(m, min(FILTER_LEN, total))) == 0) ! 395: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 1, flags, total, 0, 0); ! 396: return(-1); ! 397: } ! 398: } ! 399: *m0 = m; /* Update, just in case */ ! 400: ! 401: p = mtod(m, unsigned char *); /* Point to destination media addr */ ! 402: if (p[0] & 0x01) /* Multicast/broadcast */ ! 403: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 2, 0, 0, 0, 0 ); ! 404: return(0); ! 405: } ! 406: s = (unsigned short *)p; ! 407: bf = &ifb->filter[BFS_ATALK]; ! 408: if (!bf->BF_flags && !bf[1].BF_flags) /* Hack for Developer Release Blue Box */ ! 409: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 3, 0, 0, 0, 0 ); ! 410: return(0); ! 411: } ! 412: #if BLUE_DEBUG ! 413: kprintf("PKT: %x, %x, %x\n", s[6], s[7], s[8]); ! 414: #endif ! 415: if (bf->BF_flags) /* Filtering Appletalk */ ! 416: { l = (unsigned long *)&s[8]; ! 417: #if BLUE_DEBUG ! 418: kprintf("AT: %x, %x, %x, %x, %x, %x\n", s[6], s[7], ! 419: *l, s[10], s[13], p[30]); ! 420: #endif ! 421: if (s[6] <= ETHERMTU) ! 422: { if (s[7] == 0xaaaa) /* Could be Atalk */ ! 423: { /* Verify SNAP header */ ! 424: if (*l == 0x03080007 && s[10] == 0x809b) ! 425: { if ((bf->BF_flags&BF_VALID) == 0 || ! 426: (s[13] == bf->BF_address && ! 427: p[30] == bf->BF_node)) ! 428: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 4, ! 429: s[13], p[30], 0, 0 ); ! 430: return(1); ! 431: } ! 432: } else if (*l == 0x03000000 && s[10] == 0x80f3) ! 433: /* AARP pkts aren't net-addressed */ ! 434: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 5, 0, 0, 0, 0 ); ! 435: return(0); ! 436: } ! 437: /* Not for us */ ! 438: KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 6, s[13], p[30], 0, 0 ); ! 439: return(-1); ! 440: } else /* Not for us? */ ! 441: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 7, s[7], 0, 0, 0 ); ! 442: return(-1); ! 443: } ! 444: } /* Fall through */ ! 445: } /* Fall through */ ! 446: bf++; /* Look for IP next */ ! 447: if (bf->BF_flags) /* Filtering IP */ ! 448: { ! 449: l = (unsigned long *)&s[15]; ! 450: #if BLUE_DEBUG ! 451: kprintf("IP: %x, %x\n", s[6], *l); ! 452: #endif ! 453: if (s[6] > ETHERMTU) ! 454: { if (s[6] == 0x800) /* Is IP */ ! 455: { /* Verify IP address */ ! 456: if ((bf->BF_flags&BF_VALID) == 0 || ! 457: *l == bf->BF_address) ! 458: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 8, *l, 0, 0, 0 ); ! 459: return(1); ! 460: } else /* Not for us */ ! 461: { KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 9, *l, 0, 0, 0 ); ! 462: return(-1); ! 463: } ! 464: } else if (s[6] == 0x806) ! 465: { /* ARP pkts aren't net-addressed */ ! 466: KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 10, 0, 0, 0, 0 ); ! 467: return(0); ! 468: } ! 469: } ! 470: } ! 471: KERNEL_DEBUG(DBG_SPLT_BFCHK | DBG_FUNC_END, 11, s[6], 0, 0, 0 ); ! 472: return(-1); ! 473: } ! 474: ! 475: int ! 476: splitter_ctl(register struct socket *so, register int cmd, ! 477: register caddr_t data, register struct ifnet *ifp) ! 478: { register struct ndrv_cb *np = sotondrvcb(so); ! 479: register struct ifnet_blue *ifb; ! 480: register struct BlueFilter *bf = (struct BlueFilter *)data, *bf1; ! 481: u_long at_dl_tag; ! 482: int error=0; ! 483: ! 484: if ((ifb = np->nd_if->if_Y) == NULL) ! 485: return(ENXIO); ! 486: ! 487: if (cmd == SIOCSSPLTFILT) ! 488: { ! 489: #if BLUE_DEBUG ! 490: kprintf("Filter: %s, %x, %x, %x\n", bf->ifr_name, bf->BF_flags, bf->BF_address, ! 491: bf->BF_node); ! 492: #endif ! 493: if (bf->BF_flags & BF_ATALK) ! 494: bf1 = &ifb->filter[BFS_ATALK]; ! 495: else if (bf->BF_flags & BF_IP) ! 496: bf1 = &ifb->filter[BFS_IP]; ! 497: else ! 498: return(EINVAL); ! 499: if (bf->BF_flags&BF_ALLOC) ! 500: { if ((bf1->BF_flags&(BF_ALLOC|BF_VALID)) == ! 501: (BF_ALLOC|BF_VALID)) ! 502: return(EBUSY); ! 503: *bf1 = *bf; ! 504: bf1->BF_flags |= BF_VALID; ! 505: } else if (bf->BF_flags&BF_DEALLOC) ! 506: { if (bf1->BF_flags&BF_ALLOC) ! 507: bf1->BF_flags = 0; ! 508: else ! 509: return(EINVAL); ! 510: } ! 511: /* Register AppleTalk Tags if not registered */ ! 512: ! 513: /* Check if a tag was already registered for AppleTalk */ ! 514: error = dlil_find_dltag(ifp->if_family, ifp->if_unit, ! 515: PF_APPLETALK, &at_dl_tag); ! 516: ! 517: #if BLUE_DEBUG ! 518: kprintf("splitter_ctl: ifp=%s%u find_dltag returns=%d dl_tag=%d\n", ! 519: ifp->if_name, ifp->if_unit, error, at_dl_tag); ! 520: #endif ! 521: ! 522: if (error == EPROTONOSUPPORT) { ! 523: ether_attach_at(ifp, &at_dl_tag, ! 524: &at_dl_tag); ! 525: error = 0; ! 526: } ! 527: ! 528: } else if (cmd == SIOCZSPLTSTAT) ! 529: { ifb->pkts_up = 0; ! 530: ifb->pkts_out = 0; ! 531: ifb->pkts_looped_r2b = 0; ! 532: ifb->pkts_looped_b2r = 0; ! 533: ifb->no_bufs1 = 0; ! 534: ifb->no_bufs2 = 0; ! 535: ifb->full_sockbuf = 0; ! 536: } else if (cmd == SIOCGSPLTSTAT) ! 537: { register struct Ystats *ys = (struct Ystats *)data; ! 538: ys->YS_blue_pid = ifb->blue_pid; ! 539: ys->YS_filter[BFS_ATALK] = ifb->filter[BFS_ATALK]; ! 540: ys->YS_filter[BFS_IP] = ifb->filter[BFS_IP]; ! 541: ys->YS_pkts_up = ifb->pkts_up; ! 542: ys->YS_pkts_out = ifb->pkts_out; ! 543: ys->YS_pkts_looped_b2r = ifb->pkts_looped_b2r; ! 544: ys->YS_pkts_looped_r2b = ifb->pkts_looped_r2b; ! 545: ys->YS_no_bufs1 = ifb->no_bufs1; ! 546: ys->YS_no_bufs2 = ifb->no_bufs2; ! 547: ys->YS_full_sockbuf = ifb->full_sockbuf; ! 548: } else ! 549: return(EINVAL); ! 550: return(0); ! 551: } ! 552: ! 553: void ! 554: splitter_close(register struct ndrv_cb *np) ! 555: { extern struct ifnet_blue *blue_if; ! 556: extern void ndrv_flushq(struct ifqueue *); ! 557: ! 558: if (blue_if) ! 559: { /* If we're the guy holding the Y-adapter, clean it up */ ! 560: if (blue_if->blue_pid == ! 561: ((struct proc *)current_proc())->p_pid) ! 562: { if (np->nd_if) ! 563: { np->nd_if->if_flags &= ~IFF_SPLITTER; ! 564: np->nd_if->if_Y = 0; ! 565: } ! 566: ! 567: BFIx = 0; ! 568: /* Clean out the filter supply */ ! 569: bzero(RhapFilter, ! 570: sizeof(struct BlueFilter) * BFCount); ! 571: blue_if->ifb_so = 0; ! 572: blue_if->filter[0].BF_flags = 0; ! 573: blue_if->filter[1].BF_flags = 0; ! 574: ndrv_flushq(&blueq); ! 575: if (np->nd_laddr) ! 576: { FREE((caddr_t) np->nd_laddr, M_IFADDR); ! 577: np->nd_laddr = 0; ! 578: } ! 579: } ! 580: } ! 581: remque((queue_t)np); ! 582: FREE((caddr_t)np, M_PCB); ! 583: } ! 584: ! 585: /* ! 586: * Dup the mbuf chain passed in. The whole thing. No cute additional cruft. ! 587: * And really copy the thing. That way, we don't "precompute" checksums ! 588: * for unsuspecting consumers. ! 589: * Assumption: m->m_nextpkt == 0. ! 590: * Trick: for small packets, don't dup into a cluster. That way received ! 591: * packets don't take up too much room in the sockbuf (cf. sbspace()). ! 592: */ ! 593: int MDFail; ! 594: ! 595: struct mbuf * ! 596: m_dup(register struct mbuf *m, int how) ! 597: { register struct mbuf *n, **np; ! 598: struct mbuf *top; ! 599: int copyhdr = 0; ! 600: ! 601: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_START, m->m_flags, m->m_len, ! 602: m->m_pkthdr.len, 0, 0 ); ! 603: np = ⊤ ! 604: top = 0; ! 605: if (m->m_flags & M_PKTHDR) ! 606: copyhdr = 1; ! 607: ! 608: /* ! 609: * Quick check: if we have one mbuf and its data fits in an ! 610: * mbuf with packet header, just copy and go. ! 611: */ ! 612: if (m->m_next == NULL) ! 613: { /* Then just move the data into an mbuf and be done... */ ! 614: if (copyhdr) ! 615: { if (m->m_pkthdr.len <= MHLEN) ! 616: { if ((n = m_gethdr(how, m->m_type)) == NULL) ! 617: return(NULL); ! 618: bcopy(m->m_data, n->m_data, m->m_pkthdr.len); ! 619: n->m_pkthdr.len = m->m_pkthdr.len; ! 620: n->m_len = m->m_len; ! 621: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 2, ! 622: m->m_pkthdr.len, m->m_flags, ! 623: n->m_flags, 0 ); ! 624: return(n); ! 625: } ! 626: } else if (m->m_len <= MLEN) ! 627: { if ((n = m_get(how, m->m_type)) == NULL) ! 628: return(NULL); ! 629: bcopy(m->m_data, n->m_data, m->m_len); ! 630: n->m_len = m->m_len; ! 631: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 3, m->m_len, ! 632: m->m_flags, n->m_flags, 0 ); ! 633: return(n); ! 634: } ! 635: } ! 636: while (m) ! 637: { ! 638: #if BLUE_DEBUG ! 639: kprintf("<%x: %x, %x, %x\n", m, m->m_flags, m->m_len, ! 640: m->m_data); ! 641: #endif ! 642: if (copyhdr) ! 643: n = m_gethdr(how, m->m_type); ! 644: else ! 645: n = m_get(how, m->m_type); ! 646: if (n == 0) ! 647: goto nospace; ! 648: if (m->m_flags & M_EXT) ! 649: { MCLGET(n, how); ! 650: if ((n->m_flags & M_EXT) == 0) ! 651: goto nospace; ! 652: } ! 653: *np = n; ! 654: if (copyhdr) ! 655: { /* Don't use M_COPY_PKTHDR: preserve m_data */ ! 656: n->m_pkthdr = m->m_pkthdr; ! 657: n->m_flags |= (m->m_flags & M_COPYFLAGS); ! 658: copyhdr = 0; ! 659: if ((n->m_flags & M_EXT) == 0) ! 660: n->m_data = n->m_pktdat; ! 661: } ! 662: n->m_len = m->m_len; ! 663: /* ! 664: * Get the dup on the same bdry as the original ! 665: * Assume that the two mbufs have the same offset to data area ! 666: * (up to word bdries) ! 667: */ ! 668: bcopy(mtod(m, caddr_t), mtod(n, caddr_t), (unsigned)n->m_len); ! 669: m = m->m_next; ! 670: np = &n->m_next; ! 671: #if BLUE_DEBUG ! 672: kprintf(">%x: %x, %x, %x\n", n, n->m_flags, n->m_len, ! 673: n->m_data); ! 674: #endif ! 675: } ! 676: ! 677: if (top == 0) ! 678: MDFail++; ! 679: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 0, (int)top, 0, 0, 0 ); ! 680: return (top); ! 681: nospace: ! 682: m_freem(top); ! 683: MDFail++; ! 684: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 1, 0, 0, 0, 0 ); ! 685: return (0); ! 686: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.