Annotation of kernel/bsd/net/ndrv.c, revision 1.1

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:  *     @(#)ndrv.c      1.1 (Rhapsody) 6/10/97
        !            28:  * Justin Walker, 970604
        !            29:  *   AF_NDRV support
        !            30:  * 980130 - Cleanup, reorg, performance improvemements
        !            31:  */
        !            32: 
        !            33: #include <sys/param.h>
        !            34: #include <sys/systm.h>
        !            35: #include <sys/kernel.h>
        !            36: #include <sys/malloc.h>
        !            37: #include <sys/mbuf.h>
        !            38: #include <sys/protosw.h>
        !            39: #include <sys/domain.h>
        !            40: #include <sys/socket.h>
        !            41: #include <sys/socketvar.h>
        !            42: #include <sys/ioctl.h>
        !            43: #include <sys/errno.h>
        !            44: #include <sys/syslog.h>
        !            45: #include <sys/proc.h>
        !            46: 
        !            47: #include <net/if.h>
        !            48: #include <net/netisr.h>
        !            49: #include <net/route.h>
        !            50: #include <net/if_llc.h>
        !            51: #include <net/if_dl.h>
        !            52: #include <net/if_types.h>
        !            53: #include "if_blue.h"
        !            54: #include "ndrv.h"
        !            55: 
        !            56: #if INET
        !            57: #include <netinet/in.h>
        !            58: #include <netinet/in_var.h>
        !            59: #endif
        !            60: #include <netinet/if_ether.h>
        !            61: 
        !            62: #if NS
        !            63: #include <netns/ns.h>
        !            64: #include <netns/ns_if.h>
        !            65: #endif
        !            66: 
        !            67: #if ISO
        !            68: #include <netiso/argo_debug.h>
        !            69: #include <netiso/iso.h>
        !            70: #include <netiso/iso_var.h>
        !            71: #include <netiso/iso_snpac.h>
        !            72: #endif
        !            73: 
        !            74: #if LLC
        !            75: #include <netccitt/dll.h>
        !            76: #include <netccitt/llc_var.h>
        !            77: #endif
        !            78: 
        !            79: #include <machine/spl.h>
        !            80: 
        !            81: extern void ndrv_ctlinput(), ndrv_init(), ndrv_drain();
        !            82: extern int ndrv_ctloutput(), ndrv_usrreq(), ndrv_output(), ndrv_sysctl();
        !            83: 
        !            84: int ndrv_attach(struct socket *, int);
        !            85: int ndrv_detach(struct ndrv_cb *);
        !            86: int ndrv_bind(struct socket *, struct mbuf *);
        !            87: int ndrv_disconnect(struct ndrv_cb *);
        !            88: 
        !            89: extern struct domain ndrvdomain; /* That silly forward reference stuff */
        !            90: 
        !            91: struct protosw ndrvsw[] =
        !            92: {      {       SOCK_RAW, &ndrvdomain, 0, PR_ATOMIC|PR_ADDR,
        !            93:                0, ndrv_output, ndrv_ctlinput, ndrv_ctloutput,
        !            94:                ndrv_usrreq, ndrv_init, NULL, NULL,
        !            95:                ndrv_drain, ndrv_sysctl
        !            96:        }
        !            97: };
        !            98: 
        !            99: void ndrv_dinit(void);
        !           100: 
        !           101: struct domain ndrvdomain =
        !           102: {      AF_NDRV, "NetDriver", NULL, NULL, NULL,
        !           103:        ndrvsw, &ndrvsw[sizeof(ndrvsw)/sizeof(ndrvsw[0])],
        !           104:        NULL, NULL, 0, 0
        !           105: };
        !           106: 
        !           107: unsigned long  ndrv_sendspace = NDRVSNDQ;
        !           108: unsigned long  ndrv_recvspace = NDRVRCVQ;
        !           109: struct ndrv_cb ndrvl;          /* Head of controlblock list */
        !           110: 
        !           111: #define BLUEQMAXLEN    50
        !           112: int blueqmaxlen = BLUEQMAXLEN; /* Default */
        !           113: 
        !           114: /* Domain init function for AF_NDRV - noop */
        !           115: void
        !           116: ndrv_dinit(void)
        !           117: {
        !           118: }
        !           119: 
        !           120: /*
        !           121:  * Protocol init function for NDRV protocol
        !           122:  * Init the control block list.
        !           123:  */
        !           124: void
        !           125: ndrv_init()
        !           126: {      ndrvl.nd_next = ndrvl.nd_prev = &ndrvl;
        !           127:        blueq.ifq_maxlen = blueqmaxlen;
        !           128: }
        !           129: 
        !           130: /*
        !           131:  * Protocol output - Called from, e.g., the Blue Box
        !           132:  * Just use the driver.  If we're splitting, loop it back.
        !           133:  */
        !           134: int
        !           135: ndrv_output(register struct mbuf *m,
        !           136:            register struct socket *so)
        !           137: {      register struct ndrv_cb *np = sotondrvcb(so);
        !           138:        register struct ifnet *ifp = np->nd_if;
        !           139:        int s, error;
        !           140:        extern struct ifnet_blue *blue_if;
        !           141:        extern void kprintf(const char *, ...);
        !           142:        extern int Filter_check(struct mbuf **);
        !           143: #define senderr(e) { error = (e); goto bad;}
        !           144: 
        !           145: #if 0
        !           146:        kprintf("NDRV output: %x, %x, %x\n", m, so, np);
        !           147: #endif
        !           148: 
        !           149:        /*
        !           150:         * No header is a format error
        !           151:         */
        !           152:        if ((m->m_flags&M_PKTHDR) == 0)
        !           153:                return(ENOBUFS); /* EINVAL??? */
        !           154: 
        !           155:        /* If we're splitting,  */
        !           156:        if (ifp->if_flags&IFF_SPLITTER) /* Splitter is turned on */
        !           157:        {       register struct mbuf *m0;
        !           158:                struct mbuf *m1;
        !           159:                register int rv;
        !           160:                extern struct mbuf *m_dup(struct mbuf *, int);
        !           161: #if 0
        !           162:                kprintf("NDRV_OUTPUT: m0 = %x\n", m0);
        !           163: #endif
        !           164:                
        !           165:                m1 = m;
        !           166:                rv = Filter_check(&m1);
        !           167:                m = m1;
        !           168:                /*
        !           169:                 * -1 => Not For Rhapsody
        !           170:                 * 0 => For Both
        !           171:                 * 1 => For Rhapsody
        !           172:                 */
        !           173:                if (rv >= 0)
        !           174:                {       register struct ether_header *eh;
        !           175: 
        !           176:                        if (rv == 0)
        !           177:                        {       if ((m0 = m_dup(m, M_WAIT)) == NULL)
        !           178:                                        ((struct ifnet_blue *)ifp->if_Y)->no_bufs2++;
        !           179:                        } else
        !           180:                        {       m0 = m;
        !           181:                                m = NULL;
        !           182:                        }
        !           183:                        /* Hack alert! */
        !           184:                        eh = mtod(m0, struct ether_header *);
        !           185:                        m0->m_data += sizeof(struct ether_header);
        !           186:                        m0->m_len -= sizeof (struct ether_header);
        !           187:                        m0->m_pkthdr.len -= sizeof(struct ether_header);
        !           188:                        m0->m_flags |= 0x80;
        !           189:                        ether_input((struct ifnet *)blue_if, eh, m0);
        !           190:                        if (!m)
        !           191:                                return(0);
        !           192:                }
        !           193:        }
        !           194: 
        !           195:        /*
        !           196:         * Output to real device.  Here if rv==0.
        !           197:         * Cribbed from ether_output() XXX
        !           198:         *
        !           199:         * Can't do multicast accounting because we don't know
        !           200:         *  (a) if our interface does multicast; and
        !           201:         *  (b) what a multicast address looks like
        !           202:         */
        !           203:        s = splimp();
        !           204:        /*
        !           205:         * Queue message on interface, and start output
        !           206:         *  Can't check for already active, since that's a race.
        !           207:         */
        !           208:        if (IF_QFULL(&ifp->if_snd)) {
        !           209:                IF_DROP(&ifp->if_snd);
        !           210:                splx(s);
        !           211:                senderr(ENOBUFS);
        !           212:        }
        !           213:        IF_ENQUEUE(&ifp->if_snd, m);
        !           214:         (*ifp->if_start)(ifp);
        !           215:        splx(s);
        !           216:        ifp->if_obytes += m->m_len; /* MP alert! */
        !           217:        blue_if->pkts_out++;
        !           218:        return (0);
        !           219: bad:
        !           220:        if (m)
        !           221:                m_freem(m);
        !           222:        return (error);
        !           223: }
        !           224: 
        !           225: /* The meat of the protocol handler */
        !           226: int
        !           227: ndrv_usrreq(register struct socket *so,
        !           228:            register int req,
        !           229:            register struct mbuf *m,
        !           230:            register struct mbuf *nam,
        !           231:            register struct mbuf *control)
        !           232: {      register struct ndrv_cb *np = sotondrvcb(so);
        !           233:        register int error = 0;
        !           234:        int len;
        !           235:        extern int splitter_ctl(struct socket *, int, caddr_t, struct ifnet *);
        !           236: 
        !           237: #if 0
        !           238:        kprintf("NDRV usrreq: %x, %x, %x\n", so, req, np);
        !           239: #endif
        !           240:        if (req == PRU_CONTROL)
        !           241:                return (splitter_ctl(so, (int)m, (caddr_t)nam,
        !           242:                                     (struct ifnet *)control));
        !           243:        if (control && control->m_len) {
        !           244:                error = EOPNOTSUPP;
        !           245:                goto release;
        !           246:        }
        !           247:        if (req != PRU_ATTACH && np == 0) {
        !           248:                error = EINVAL;
        !           249:                goto release;
        !           250:        }
        !           251: 
        !           252:        switch (req) {
        !           253: 
        !           254:                /*
        !           255:                 * Allocate a control block and fill in the
        !           256:                 * necessary info to allow packets to be routed to
        !           257:                 * the appropriate device driver routine.
        !           258:                 */
        !           259:                case PRU_ATTACH:
        !           260:                        error = ndrv_attach(so, (int)nam);
        !           261:                        break;
        !           262: 
        !           263:                /*
        !           264:                 * Destroy state just before socket deallocation.
        !           265:                 * Flush data or not depending on the options.
        !           266:                 */
        !           267:                case PRU_DETACH:
        !           268:                        ndrv_detach((struct ndrv_cb *)np);
        !           269:                        break;
        !           270: 
        !           271:                /*
        !           272:                 * If a socket isn't bound to a single address,
        !           273:                 * the ndrv input routine will hand it anything
        !           274:                 * within that protocol family (assuming there's
        !           275:                 * nothing else around it should go to).
        !           276:                 *
        !           277:                 * Don't expect this to be used.
        !           278:                 */
        !           279:                case PRU_CONNECT:
        !           280:                        if (np->nd_faddr) {
        !           281:                                error = EISCONN;
        !           282:                                break;
        !           283:                        }
        !           284:                        nam = m_copym(nam, 0, M_COPYALL, M_WAIT);
        !           285:                        np->nd_faddr = mtod(nam, struct sockaddr_ndrv *);
        !           286:                        soisconnected(so);
        !           287:                        break;
        !           288: 
        !           289:                /*
        !           290:                 * This is the "driver open" hook - we 'bind' to the
        !           291:                 *  named driver.
        !           292:                 */
        !           293:                case PRU_BIND:
        !           294:                        if (np->nd_laddr) {
        !           295:                                error = EINVAL;                 /* XXX */
        !           296:                                break;
        !           297:                        }
        !           298:                        error = ndrv_bind(so, nam);
        !           299:                        break;
        !           300: 
        !           301:                case PRU_CONNECT2:
        !           302:                        error = EOPNOTSUPP;
        !           303:                        goto release;
        !           304: 
        !           305:                case PRU_DISCONNECT:
        !           306:                        if (np->nd_faddr == 0) {
        !           307:                                error = ENOTCONN;
        !           308:                                break;
        !           309:                        }
        !           310:                        ndrv_disconnect((struct ndrv_cb *)np);
        !           311:                        soisdisconnected(so);
        !           312:                        break;
        !           313: 
        !           314:                /*
        !           315:                 * Mark the connection as being incapable of further input.
        !           316:                 */
        !           317:                case PRU_SHUTDOWN:
        !           318:                        socantsendmore(so);
        !           319:                        break;
        !           320: 
        !           321:                /*
        !           322:                 * Ship a packet out.  The ndrv output will pass it
        !           323:                 *  to the appropriate driver.  The really tricky part
        !           324:                 *  is the destination address...
        !           325:                 */
        !           326:                case PRU_SEND:
        !           327:                        error = ndrv_output(m, so);
        !           328:                        m = NULL;
        !           329:                        break;
        !           330: 
        !           331:                case PRU_ABORT:
        !           332:                        ndrv_disconnect((struct ndrv_cb *)np);
        !           333:                        sofree(so);
        !           334:                        soisdisconnected(so);
        !           335:                        break;
        !           336: 
        !           337:                case PRU_SENSE:
        !           338:                        /*
        !           339:                         * stat: don't bother with a blocksize.
        !           340:                         */
        !           341:                        return (0);
        !           342: 
        !           343:                /*
        !           344:                 * Not supported.
        !           345:                 */
        !           346:                case PRU_RCVOOB:
        !           347:                case PRU_RCVD:
        !           348:                        return(EOPNOTSUPP);
        !           349: 
        !           350:                case PRU_LISTEN:
        !           351:                case PRU_ACCEPT:
        !           352:                case PRU_SENDOOB:
        !           353:                case PRU_SLOWTIMO:
        !           354:                case PRU_FASTTIMO:
        !           355:                case PRU_PROTORCV:
        !           356:                case PRU_PROTOSEND:
        !           357:                        error = EOPNOTSUPP;
        !           358:                        break;
        !           359: 
        !           360:                case PRU_SOCKADDR:
        !           361:                        if (np->nd_laddr == 0) {
        !           362:                                error = EINVAL;
        !           363:                                break;
        !           364:                        }
        !           365:                        len = np->nd_laddr->snd_len;
        !           366:                        bcopy((caddr_t)np->nd_laddr, mtod(nam, caddr_t),
        !           367:                              (unsigned)len);
        !           368:                        nam->m_len = len;
        !           369:                        break;
        !           370: 
        !           371:                case PRU_PEERADDR:
        !           372:                        if (np->nd_faddr == 0) {
        !           373:                                error = ENOTCONN;
        !           374:                                break;
        !           375:                        }
        !           376:                        len = np->nd_faddr->snd_len;
        !           377:                        bcopy((caddr_t)np->nd_faddr, mtod(nam, caddr_t),
        !           378:                              (unsigned)len);
        !           379:                        nam->m_len = len;
        !           380:                        break;
        !           381: 
        !           382:                default:
        !           383:                        panic("ndrv_usrreq");
        !           384:        }
        !           385: release:
        !           386:        if (m != NULL)
        !           387:                m_freem(m);
        !           388:        return (error);
        !           389: }
        !           390: 
        !           391: /* Control input */
        !           392: void
        !           393: ndrv_ctlinput()
        !           394: {}
        !           395: 
        !           396: /* Control output */
        !           397: int
        !           398: ndrv_ctloutput()
        !           399: {
        !           400:        return(0);
        !           401: }
        !           402: 
        !           403: /* Drain the queues */
        !           404: void
        !           405: ndrv_drain()
        !           406: {}
        !           407: 
        !           408: /* Sysctl hook for NDRV */
        !           409: int
        !           410: ndrv_sysctl()
        !           411: {
        !           412:        return(0);
        !           413: }
        !           414: 
        !           415: /*
        !           416:  * Allocate an ndrv control block and some buffer space for the socket
        !           417:  */
        !           418: int
        !           419: ndrv_attach(register struct socket *so,
        !           420:            register int proto)
        !           421: {      int error;
        !           422:        register struct ndrv_cb *np = sotondrvcb(so);
        !           423: 
        !           424: #if 0
        !           425:        kprintf("NDRV attach: %x, %x, %x\n", so, proto, np);
        !           426: #endif
        !           427:        MALLOC(np, struct ndrv_cb *, sizeof(*np), M_PCB, M_WAITOK);
        !           428: #if 0
        !           429:        kprintf("NDRV attach: %x, %x, %x\n", so, proto, np);
        !           430: #endif
        !           431:        if ((so->so_pcb = (caddr_t)np))
        !           432:                bzero(np, sizeof(*np));
        !           433:        else
        !           434:                return(ENOBUFS);
        !           435:        if ((error = soreserve(so, ndrv_sendspace, ndrv_recvspace)))
        !           436:                return(error);
        !           437:        np->nd_signature = NDRV_SIGNATURE;
        !           438:        np->nd_socket = so;
        !           439:        np->nd_proto.sp_family = so->so_proto->pr_domain->dom_family;
        !           440:        np->nd_proto.sp_protocol = proto;
        !           441:        insque((queue_t)np, (queue_t)&ndrvl);
        !           442:        return(0);
        !           443: }
        !           444: 
        !           445: int
        !           446: ndrv_detach(register struct ndrv_cb *np)
        !           447: {      register struct socket *so = np->nd_socket;
        !           448:        extern struct ifnet_blue *blue_if;
        !           449:        extern void splitter_close(struct ndrv_cb *);
        !           450: 
        !           451: #if 0
        !           452:        kprintf("NDRV detach: %x, %x\n", so, np);
        !           453: #endif
        !           454:        if (blue_if)
        !           455:                splitter_close(np); /* 'np' is freed within */
        !           456:        so->so_pcb = 0;
        !           457:        sofree(so);
        !           458:        return(0);
        !           459: }
        !           460: 
        !           461: int
        !           462: ndrv_disconnect(register struct ndrv_cb *np)
        !           463: {
        !           464: #if 0
        !           465:        kprintf("NDRV disconnect: %x\n", np);
        !           466: #endif
        !           467:        if (np->nd_faddr)
        !           468:        {       m_freem(dtom(np->nd_faddr));
        !           469:                np->nd_faddr = 0;
        !           470:        }
        !           471:        if (np->nd_socket->so_state & SS_NOFDREF)
        !           472:                ndrv_detach(np);
        !           473:        return(0);
        !           474: }
        !           475: 
        !           476: /*
        !           477:  * Here's where we latch onto the driver and make it ours.
        !           478:  */
        !           479: int
        !           480: ndrv_bind(register struct socket *so,
        !           481:          register struct mbuf *nam)
        !           482: {      register char *dname;
        !           483:        register struct sockaddr_ndrv *sa;
        !           484:        register struct ndrv_cb *np;
        !           485:        register struct ifnet *ifp;
        !           486:        extern int name_cmp(struct ifnet *, char *);
        !           487: 
        !           488:        if (ifnet == 0)
        !           489:                return(EADDRNOTAVAIL); /* Quick sanity check */
        !           490:        np = sotondrvcb(so);
        !           491:        /* I think we just latch onto a copy here; the caller frees */
        !           492:        nam = m_copym(nam, 0, M_COPYALL, M_WAITOK);
        !           493:        sa = mtod(nam, struct sockaddr_ndrv *);
        !           494:        np->nd_laddr = sa;
        !           495:        dname = sa->snd_name;
        !           496:        if (dname == NULL)
        !           497:                return(EINVAL);
        !           498: #if 0
        !           499:        kprintf("NDRV bind: %x, %x, %s\n", so, np, dname);
        !           500: #endif
        !           501:        /* Track down the driver and its ifnet structure.
        !           502:         * There's no internal call for this so we have to dup the code
        !           503:         *  in if.c/ifconf()
        !           504:         */
        !           505:        for (ifp = ifnet; ifp; ifp = ifp->if_next)
        !           506:                if (name_cmp(ifp, dname) == 0)
        !           507:                        break;
        !           508:        if (ifp == NULL)
        !           509:                return(EADDRNOTAVAIL);
        !           510:        /*
        !           511:         * Now, at this point, we should force open the driver and somehow
        !           512:         *  register ourselves to receive packets (a la the bpf).
        !           513:         * However, we have this groaty hack in place that makes it
        !           514:         *  not necessary for blue box purposes (the 'splitter' trick).
        !           515:         * If we want this to be a full-fledged AF, we have to force the
        !           516:         *  open and implement a filter mechanism.
        !           517:         */
        !           518:        np->nd_if = ifp;
        !           519:        return(0);
        !           520: }
        !           521: 
        !           522: /*
        !           523:  * Try to compare a device name (q) with one of the funky ifnet
        !           524:  *  device names (ifp).
        !           525:  */
        !           526: int name_cmp(register struct ifnet *ifp, register char *q)
        !           527: {      register char *r;
        !           528:        register int len;
        !           529:        char buf[IFNAMSIZ];
        !           530:        static char *sprint_d();
        !           531: 
        !           532:        r = buf;
        !           533:        len = strlen(ifp->if_name);
        !           534:        strncpy(r, ifp->if_name, IFNAMSIZ);
        !           535:        r += len;
        !           536:        (void)sprint_d(ifp->if_unit, r, r-buf);
        !           537: #if 0
        !           538:        kprintf("Comparing %s, %s\n", buf, q);
        !           539: #endif
        !           540:        return(strncmp(buf, q, IFNAMSIZ));
        !           541: }
        !           542: 
        !           543: /* Hackery - return a string version of a decimal number */
        !           544: static char *
        !           545: sprint_d(n, buf, buflen)
        !           546:         u_int n;
        !           547:         char *buf;
        !           548:         int buflen;
        !           549: {
        !           550:         register char *cp = buf + buflen - 1;
        !           551: 
        !           552:         *cp = 0;
        !           553:         do {
        !           554:                 cp--;
        !           555:                 *cp = "0123456789"[n % 10];
        !           556:                 n /= 10;
        !           557:         } while (n != 0);
        !           558:         return (cp);
        !           559: }
        !           560: 
        !           561: /*
        !           562:  * When closing, dump any enqueued mbufs.
        !           563:  */
        !           564: void
        !           565: ndrv_flushq(register struct ifqueue *q)
        !           566: {      register struct mbuf *m;
        !           567:        register int s;
        !           568:        for (;;)
        !           569:        {       s = splimp();
        !           570:                IF_DEQUEUE(q, m);
        !           571:                if (m == NULL)
        !           572:                        break;
        !           573:                IF_DROP(q);
        !           574:                splx(s);
        !           575:                if (m)
        !           576:                        m_freem(m);
        !           577:        }
        !           578:        splx(s);
        !           579: }

unix.superglobalmegacorp.com

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