|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1999 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * Portions Copyright (c) 1999 Apple Computer, Inc. All Rights ! 7: * Reserved. This file contains Original Code and/or Modifications of ! 8: * Original Code as defined in and that are subject to the Apple Public ! 9: * Source License Version 1.1 (the "License"). You may not use this file ! 10: * except in compliance with the License. Please obtain a copy of the ! 11: * License at http://www.apple.com/publicsource and read it before using ! 12: * this file. ! 13: * ! 14: * The Original Code and all software distributed under the License are ! 15: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 16: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 17: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 18: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 19: * License for the specific language governing rights and limitations ! 20: * under the License. ! 21: * ! 22: * @APPLE_LICENSE_HEADER_END@ ! 23: */ ! 24: ! 25: /* Copyright (c) 1997, 1998 Apple Computer, Inc. All Rights Reserved */ ! 26: /* ! 27: * ! 28: * @(#)if_blue.c 1.1 (Rhapsody) 6/10/97 ! 29: * Justin Walker, 9970520 ! 30: * First wave - splitter and notification support for the Blue Box ! 31: * 980130 - Second wave - Performance improvements, reorg and cleanup ! 32: */ ! 33: ! 34: #include <kern/kdebug.h> ! 35: #if KDEBUG ! 36: ! 37: #define DBG_SPLT_BFCHK DRVDBG_CODE(DBG_DRVSPLT, 0) ! 38: #define DBG_SPLT_APPND DRVDBG_CODE(DBG_DRVSPLT, 1) ! 39: #define DBG_SPLT_MBUF DRVDBG_CODE(DBG_DRVSPLT, 2) ! 40: #define DBG_SPLT_DUP DRVDBG_CODE(DBG_DRVSPLT, 3) ! 41: #define DBG_SPLT_PAD DRVDBG_CODE(DBG_DRVSPLT, 4) ! 42: ! 43: #endif ! 44: ! 45: ! 46: #include <sys/param.h> ! 47: #include <sys/systm.h> ! 48: #include <sys/kernel.h> ! 49: #include <sys/malloc.h> ! 50: #include <sys/mbuf.h> ! 51: #include <sys/protosw.h> ! 52: #include <sys/socket.h> ! 53: #include <sys/socketvar.h> ! 54: #include <sys/ioctl.h> ! 55: #include <sys/errno.h> ! 56: #include <sys/syslog.h> ! 57: #include <sys/proc.h> ! 58: ! 59: #include <machine/cpu.h> ! 60: ! 61: #include <net/if.h> ! 62: #include <net/netisr.h> ! 63: #include <net/route.h> ! 64: #include <net/if_llc.h> ! 65: #include <net/if_dl.h> ! 66: #include <net/if_types.h> ! 67: #include "if_blue.h" ! 68: #include "ndrv.h" ! 69: ! 70: #if INET ! 71: #include <netinet/in.h> ! 72: #include <netinet/in_var.h> ! 73: #endif ! 74: #include <netinet/if_ether.h> ! 75: ! 76: #if NS ! 77: #include <netns/ns.h> ! 78: #include <netns/ns_if.h> ! 79: #endif ! 80: ! 81: #if ISO ! 82: #include <netiso/argo_debug.h> ! 83: #include <netiso/iso.h> ! 84: #include <netiso/iso_var.h> ! 85: #include <netiso/iso_snpac.h> ! 86: #endif ! 87: ! 88: #if LLC ! 89: #include <netccitt/dll.h> ! 90: #include <netccitt/llc_var.h> ! 91: #endif ! 92: ! 93: #include <sys/systm.h> ! 94: #include <machine/spl.h> ! 95: ! 96: /* Dummy IFs to differentiate source of looped packets */ ! 97: struct ifnet rhap_if_s; ! 98: struct ifnet *rhap_if = &rhap_if_s; ! 99: struct ifnet_blue *blue_if; ! 100: struct sockaddr_dl ndrvsrc = {sizeof (struct sockaddr_dl), AF_NDRV}; ! 101: ! 102: struct ifqueue blueq; ! 103: ! 104: extern int if_register(register struct BlueFilter *f ! 105: #ifdef BF_if ! 106: , ! 107: register struct ifnet *ifp ! 108: #endif ! 109: ); ! 110: ! 111: /* ! 112: * Blue Box support: ! 113: * 1st cut: the Y splitter ! 114: * A process turns on the splitter by opening the "raw" device ! 115: * (socket() for AF_NDRV) and issuing an SIOCSSPLITTER ioctl. ! 116: * Incoming packets are routed into Rhapsody as well as to the requesting ! 117: * interface. ! 118: * Outbound packets are sent, and are examined to see if they should go ! 119: * back up (loopback, sort of). Packets that are looped back include: ! 120: * broadcast ! 121: * multicast ! 122: */ ! 123: int ! 124: new_splitter(register struct socket *so) ! 125: { register struct ifnet_blue *ifb; ! 126: register struct ndrv_cb *np; ! 127: register struct ifnet *ifp; ! 128: struct BlueFilter filter; ! 129: int retval; ! 130: ! 131: if ((ifb = _MALLOC(sizeof (struct ifnet_blue), M_PCB, M_WAITOK)) ! 132: == NULL) ! 133: { ! 134: #if 0 ! 135: kprintf("Can't create new splitter\n"); ! 136: #endif ! 137: return(ENOBUFS); ! 138: } ! 139: bzero(ifb, sizeof(struct ifnet_blue)); ! 140: np = (struct ndrv_cb *)so->so_pcb; ! 141: #if 0 ! 142: printf("NEW SPLT: %x, %x\n", so, np); ! 143: if (np) ! 144: printf("SIG: %x, ifp: %x\n", np->nd_signature, np->nd_if); ! 145: #endif ! 146: if (np == NULL) ! 147: return(EINVAL); /* XXX */ ! 148: if (np->nd_signature != NDRV_SIGNATURE) ! 149: return(EINVAL); /* XXX */ ! 150: if ((ifp = np->nd_if) == NULL) ! 151: return(EINVAL); /* XXX */ ! 152: if (ifp->if_flags & IFF_SPLITTER) ! 153: return(EBUSY); ! 154: if ((ifp->if_flags&IFF_UP) == 0) ! 155: return(ENXIO); ! 156: /* ! 157: * Bump the receive sockbuf size - need a big buffer ! 158: * to offset the scheduling latencies of the system ! 159: * Try to get something if our grandiose design fails. ! 160: */ ! 161: if (sbreserve(&so->so_rcv, 131072) == 0) ! 162: { if (sbreserve(&so->so_rcv, 65536) == 0 && ! 163: sbreserve(&so->so_rcv, 32768) == 0 && ! 164: sbreserve(&so->so_rcv, 16384) == 0) ! 165: return(ENOBUFS); ! 166: } ! 167: ifp->if_flags |= IFF_SPLITTER; ! 168: /* ! 169: * Register each IP address associated with this ifnet ! 170: * This takes care of addresses registered prior to startup ! 171: * of the BlueBox. ! 172: * TODO: Appletalk sockaddrs ! 173: */ ! 174: #define IFA2IN(ifa) \ ! 175: ((struct in_addr) \ ! 176: ((struct sockaddr_in *)(ifa->ifa_addr))->sin_addr).s_addr ! 177: { struct ifaddr *ifa; ! 178: for (ifa = ifp->if_addrlist; (ifa = ifa->ifa_next);) ! 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 0 ! 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 0 ! 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 = current_thread()->task->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, Rhapsody 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 Rhapsody */ ! 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 0 ! 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 0 ! 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 0 ! 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: ! 482: if ((ifb = np->nd_if->if_Y) == NULL) ! 483: return(ENXIO); ! 484: ! 485: if (cmd == SIOCSSPLTFILT) ! 486: { ! 487: #if 0 ! 488: kprintf("Filter: %s, %x, %x, %x\n", bf->ifr_name, bf->BF_flags, bf->BF_address, ! 489: bf->BF_node); ! 490: #endif ! 491: if (bf->BF_flags & BF_ATALK) ! 492: bf1 = &ifb->filter[BFS_ATALK]; ! 493: else if (bf->BF_flags & BF_IP) ! 494: bf1 = &ifb->filter[BFS_IP]; ! 495: else ! 496: return(EINVAL); ! 497: if (bf->BF_flags&BF_ALLOC) ! 498: { if ((bf1->BF_flags&(BF_ALLOC|BF_VALID)) == ! 499: (BF_ALLOC|BF_VALID)) ! 500: return(EBUSY); ! 501: *bf1 = *bf; ! 502: bf1->BF_flags |= BF_VALID; ! 503: } else if (bf->BF_flags&BF_DEALLOC) ! 504: { if (bf1->BF_flags&BF_ALLOC) ! 505: bf1->BF_flags = 0; ! 506: else ! 507: return(EINVAL); ! 508: } ! 509: } else if (cmd == SIOCZSPLTSTAT) ! 510: { ifb->pkts_up = 0; ! 511: ifb->pkts_out = 0; ! 512: ifb->pkts_looped_r2b = 0; ! 513: ifb->pkts_looped_b2r = 0; ! 514: ifb->no_bufs1 = 0; ! 515: ifb->no_bufs2 = 0; ! 516: ifb->full_sockbuf = 0; ! 517: } else if (cmd == SIOCGSPLTSTAT) ! 518: { register struct Ystats *ys = (struct Ystats *)data; ! 519: ys->YS_blue_pid = ifb->blue_pid; ! 520: ys->YS_filter[BFS_ATALK] = ifb->filter[BFS_ATALK]; ! 521: ys->YS_filter[BFS_IP] = ifb->filter[BFS_IP]; ! 522: ys->YS_pkts_up = ifb->pkts_up; ! 523: ys->YS_pkts_out = ifb->pkts_out; ! 524: ys->YS_pkts_looped_b2r = ifb->pkts_looped_b2r; ! 525: ys->YS_pkts_looped_r2b = ifb->pkts_looped_r2b; ! 526: ys->YS_no_bufs1 = ifb->no_bufs1; ! 527: ys->YS_no_bufs2 = ifb->no_bufs2; ! 528: ys->YS_full_sockbuf = ifb->full_sockbuf; ! 529: } else ! 530: return(EINVAL); ! 531: return(0); ! 532: } ! 533: ! 534: void ! 535: splitter_close(register struct ndrv_cb *np) ! 536: { extern struct ifnet_blue *blue_if; ! 537: extern void ndrv_flushq(struct ifqueue *); ! 538: ! 539: if (blue_if) ! 540: { /* If we're the guy holding the Y-adapter, clean it up */ ! 541: if (blue_if->blue_pid == current_thread()->task->proc->p_pid) ! 542: { if (np->nd_if) ! 543: { np->nd_if->if_flags &= ~IFF_SPLITTER; ! 544: np->nd_if->if_Y = 0; ! 545: } ! 546: ! 547: BFIx = 0; ! 548: /* Clean out the filter supply */ ! 549: bzero(RhapFilter, ! 550: sizeof(struct BlueFilter) * BFCount); ! 551: blue_if->ifb_so = 0; ! 552: blue_if->filter[0].BF_flags = 0; ! 553: blue_if->filter[1].BF_flags = 0; ! 554: ndrv_flushq(&blueq); ! 555: if (np->nd_laddr) ! 556: { m_freem(dtom(np->nd_laddr)); ! 557: np->nd_laddr = 0; ! 558: } ! 559: } ! 560: } ! 561: remque((queue_t)np); ! 562: _FREE((caddr_t)np, M_PCB); ! 563: } ! 564: ! 565: /* ! 566: * Dup the mbuf chain passed in. The whole thing. No cute additional cruft. ! 567: * And really copy the thing. That way, we don't "precompute" checksums ! 568: * for unsuspecting consumers. ! 569: * Assumption: m->m_nextpkt == 0. ! 570: * Trick: for small packets, don't dup into a cluster. That way received ! 571: * packets don't take up too much room in the sockbuf (cf. sbspace()). ! 572: */ ! 573: int MDFail; ! 574: ! 575: struct mbuf * ! 576: m_dup(register struct mbuf *m, int how) ! 577: { register struct mbuf *n, **np; ! 578: struct mbuf *top; ! 579: int copyhdr = 0; ! 580: ! 581: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_START, m->m_flags, m->m_len, ! 582: m->m_pkthdr.len, 0, 0 ); ! 583: np = ⊤ ! 584: top = 0; ! 585: if (m->m_flags & M_PKTHDR) ! 586: copyhdr = 1; ! 587: ! 588: /* ! 589: * Quick check: if we have one mbuf and its data fits in an ! 590: * mbuf with packet header, just copy and go. ! 591: */ ! 592: if (m->m_next == NULL) ! 593: { /* Then just move the data into an mbuf and be done... */ ! 594: if (copyhdr) ! 595: { if (m->m_pkthdr.len <= MHLEN) ! 596: { n = m_gethdr(how, m->m_type); ! 597: bcopy(m->m_data, n->m_data, m->m_pkthdr.len); ! 598: n->m_pkthdr.len = m->m_pkthdr.len; ! 599: n->m_len = m->m_len; ! 600: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 2, ! 601: m->m_pkthdr.len, m->m_flags, ! 602: n->m_flags, 0 ); ! 603: return(n); ! 604: } ! 605: } else if (m->m_len <= MLEN) ! 606: { n = m_get(how, m->m_type); ! 607: bcopy(m->m_data, n->m_data, m->m_len); ! 608: n->m_len = m->m_len; ! 609: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 3, m->m_len, ! 610: m->m_flags, n->m_flags, 0 ); ! 611: return(n); ! 612: } ! 613: } ! 614: while (m) ! 615: { ! 616: #if 0 ! 617: kprintf("<%x: %x, %x, %x\n", m, m->m_flags, m->m_len, ! 618: m->m_data); ! 619: #endif ! 620: if (copyhdr) ! 621: n = m_gethdr(how, m->m_type); ! 622: else ! 623: n = m_get(how, m->m_type); ! 624: if (n == 0) ! 625: goto nospace; ! 626: if (m->m_flags & M_EXT) ! 627: { MCLGET(n, how); ! 628: if ((n->m_flags & M_EXT) == 0) ! 629: goto nospace; ! 630: } ! 631: *np = n; ! 632: if (copyhdr) ! 633: { /* Don't use M_COPY_PKTHDR: preserve m_data */ ! 634: n->m_pkthdr = m->m_pkthdr; ! 635: n->m_flags |= (m->m_flags & M_COPYFLAGS); ! 636: copyhdr = 0; ! 637: if ((n->m_flags & M_EXT) == 0) ! 638: n->m_data = n->m_pktdat; ! 639: } ! 640: n->m_len = m->m_len; ! 641: /* ! 642: * Get the dup on the same bdry as the original ! 643: * Assume that the two mbufs have the same offset to data area ! 644: * (up to word bdries) ! 645: */ ! 646: bcopy(mtod(m, caddr_t), mtod(n, caddr_t), (unsigned)n->m_len); ! 647: m = m->m_next; ! 648: np = &n->m_next; ! 649: #if 0 ! 650: kprintf(">%x: %x, %x, %x\n", n, n->m_flags, n->m_len, ! 651: n->m_data); ! 652: #endif ! 653: } ! 654: ! 655: if (top == 0) ! 656: MDFail++; ! 657: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 0, (int)top, 0, 0, 0 ); ! 658: return (top); ! 659: nospace: ! 660: m_freem(top); ! 661: MDFail++; ! 662: KERNEL_DEBUG(DBG_SPLT_DUP | DBG_FUNC_END, 1, 0, 0, 0, 0 ); ! 663: return (0); ! 664: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.