Annotation of kernel/bsd/net/ndrv.c, revision 1.1.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.