Annotation of XNU/bsd/net/if_blue.c, revision 1.1.1.1

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 = &top;
                    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: }

unix.superglobalmegacorp.com

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