Annotation of XNU/bsd/net/ndrv.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:  *     @(#)ndrv.c      1.1 (MacOSX) 6/10/43
                     25:  * Justin Walker, 970604
                     26:  *   AF_NDRV support
                     27:  * 980130 - Cleanup, reorg, performance improvemements
                     28:  */
                     29: 
                     30: /*
                     31:  * PF_NDRV allows raw access to a specified network device, directly
                     32:  *  with a socket.  Expected use involves a socket option to request
                     33:  *  protocol packets.  This lets ndrv_output() call dlil_output(), and
                     34:  *  lets DLIL find the proper recipient for incoming packets.
                     35:  *  The purpose here is for user-mode protocol implementation.
                     36:  * Note that "pure raw access" will still be accomplished with BPF.
                     37:  *
                     38:  * In addition to the former use, when combined with socket NKEs,
                     39:  * PF_NDRV permits a fairly flexible mechanism for implementing
                     40:  * strange protocol support.  One of the main ones will be the
                     41:  * BlueBox/Classic Shared IP Address support.
                     42:  *
                     43:  * TODO: Add user access to protocol registration
                     44:  */
                     45: 
                     46: #include <sys/param.h>
                     47: #include <sys/systm.h>
                     48: #include <sys/kernel.h>
                     49: #include <sys/malloc.h>
                     50: #include <sys/mbuf.h>
                     51: #include <sys/protosw.h>
                     52: #include <sys/domain.h>
                     53: #include <sys/socket.h>
                     54: #include <sys/socketvar.h>
                     55: #include <sys/ioctl.h>
                     56: #include <sys/errno.h>
                     57: #include <sys/syslog.h>
                     58: #include <sys/proc.h>
                     59: 
                     60: #include <kern/queue.h>
                     61: 
                     62: #include <net/if.h>
                     63: #include <net/netisr.h>
                     64: #include <net/route.h>
                     65: #include <net/if_llc.h>
                     66: #include <net/if_dl.h>
                     67: #include <net/if_types.h>
                     68: #include "if_blue.h"           /* TEMP!  Until BB gets in synch */
                     69: #include "ndrv.h"
                     70: 
                     71: #if INET
                     72: #include <netinet/in.h>
                     73: #include <netinet/in_var.h>
                     74: #endif
                     75: #include <netinet/if_ether.h>
                     76: 
                     77: #if NS
                     78: #include <netns/ns.h>
                     79: #include <netns/ns_if.h>
                     80: #endif
                     81: 
                     82: #if ISO
                     83: #include <netiso/argo_debug.h>
                     84: #include <netiso/iso.h>
                     85: #include <netiso/iso_var.h>
                     86: #include <netiso/iso_snpac.h>
                     87: #endif
                     88: 
                     89: #if LLC
                     90: #include <netccitt/dll.h>
                     91: #include <netccitt/llc_var.h>
                     92: #endif
                     93: 
                     94: #include <machine/spl.h>
                     95: 
                     96: int local_ndrv_attach(struct socket *, int);
                     97: int local_ndrv_detach(struct ndrv_cb *);
                     98: int local_ndrv_bind(struct socket *, struct sockaddr_ndrv *);
                     99: int local_ndrv_disconnect(struct ndrv_cb *);
                    100: 
                    101: extern int splitter_ctl(struct socket *, int, caddr_t, struct ifnet *);
                    102: 
                    103: void local_ndrv_dinit(void);
                    104: 
                    105: unsigned long  ndrv_sendspace = NDRVSNDQ;
                    106: unsigned long  ndrv_recvspace = NDRVRCVQ;
                    107: struct ndrv_cb ndrvl;          /* Head of controlblock list */
                    108: 
                    109: #define BLUEQMAXLEN    50
                    110: int blueqmaxlen = BLUEQMAXLEN; /* Default */
                    111: 
                    112: /* Domain init function for AF_NDRV - noop */
                    113: void
                    114: local_ndrv_dinit(void)
                    115: {
                    116: }
                    117: 
                    118: /*
                    119:  * Protocol init function for NDRV protocol
                    120:  * Init the control block list.
                    121:  */
                    122: void
                    123: ndrv_init()
                    124: {      ndrvl.nd_next = ndrvl.nd_prev = &ndrvl;
                    125:        blueq.ifq_maxlen = blueqmaxlen;
                    126: }
                    127: 
                    128: /*
                    129:  * Protocol output - Called to output a raw network packet directly
                    130:  *  to the driver.  If we're splitting, maybe loop it back.
                    131:  */
                    132: int
                    133: ndrv_output(register struct mbuf *m,
                    134:            register struct socket *so)
                    135: {      register struct ndrv_cb *np = sotondrvcb(so);
                    136:        register struct ifnet *ifp = np->nd_if;
                    137:        int s, error;
                    138:        extern struct ifnet_blue *blue_if;
                    139:        extern void kprintf(const char *, ...);
                    140:        extern int Filter_check(struct mbuf **);
                    141: #define senderr(e) { error = (e); goto bad;}
                    142: 
                    143: #if NDRV_DEBUG
                    144:        kprintf("NDRV output: %x, %x, %x\n", m, so, np);
                    145: #endif
                    146: 
                    147:        /*
                    148:         * No header is a format error
                    149:         */
                    150:        if ((m->m_flags&M_PKTHDR) == 0)
                    151:                return(ENOBUFS); /* EINVAL??? */
                    152: 
                    153:        /* If we're splitting,  */
                    154:        if (ifp->if_flags&IFF_SPLITTER) /* Splitter is turned on */
                    155:        {       register struct mbuf *m0;
                    156:                struct mbuf *m1;
                    157:                register int rv;
                    158:                extern struct mbuf *m_dup(struct mbuf *, int);
                    159: #if 0
                    160:                kprintf("NDRV_OUTPUT: m0 = %x\n", m0);
                    161: #endif
                    162:                
                    163:                m1 = m;
                    164:                rv = Filter_check(&m1);
                    165:                m = m1;
                    166:                /*
                    167:                 * -1 => Not For MacOSX
                    168:                 * 0 => For Both
                    169:                 * 1 => For MacOSX
                    170:                 */
                    171:                if (rv >= 0)
                    172:                {       register struct ether_header *eh;
                    173: 
                    174:                        if (rv == 0)
                    175:                        {       if ((m0 = m_dup(m, M_WAIT)) == NULL)
                    176:                                        ((struct ifnet_blue *)ifp->if_Y)->no_bufs2++;
                    177:                        } else
                    178:                        {       m0 = m;
                    179:                                m = NULL;
                    180:                        }
                    181:                        /* Hack alert! */
                    182:                        eh = mtod(m0, struct ether_header *);
                    183:                        m0->m_data += sizeof(struct ether_header);
                    184:                        m0->m_len -= sizeof (struct ether_header);
                    185:                        m0->m_pkthdr.len -= sizeof(struct ether_header);
                    186:                        m0->m_flags |= 0x80;
                    187: #if NDRV_DEBUG
                    188:                        kprintf("NDRV_OUTPUT: m0 = %x\n", m0);
                    189: #endif
                    190:                        new_ether_input(m0, eh, (struct ifnet *)blue_if, 0, 1);
                    191:                        if (!m)
                    192:                                return(0);
                    193:                }
                    194:        }
                    195: 
                    196:        /*
                    197:         * Output to real device.
                    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:        /*
                    206:         * Can't call DLIL to do the job - we don't have a tag
                    207:         *  and we aren't really a protocol
                    208:         */
                    209: 
                    210:         (*ifp->if_output)(ifp, m);
                    211:        splx(s);
                    212:        ifp->if_obytes += m->m_len; /* MP alert! */
                    213:        blue_if->pkts_out++;
                    214:        return (0);
                    215: bad:
                    216:        if (m)
                    217:                m_freem(m);
                    218:        return (error);
                    219: }
                    220: 
                    221: 
                    222: 
                    223: 
                    224: 
                    225: int ndrv_control(struct socket *so, u_long cmd, caddr_t data,
                    226:                  struct ifnet *ifp, struct proc *p) 
                    227: {
                    228:                return (splitter_ctl(so, (int)cmd, data,
                    229:                                     ifp));
                    230: }
                    231: 
                    232: int ndrv_attach(struct socket *so, int proto,
                    233:                    struct proc *p)
                    234: {
                    235: 
                    236:        return local_ndrv_attach(so, proto);
                    237: }
                    238: 
                    239: 
                    240: 
                    241: /*
                    242:  * Destroy state just before socket deallocation.
                    243:  * Flush data or not depending on the options.
                    244:  */
                    245: 
                    246: int    ndrv_detach(struct socket *so) 
                    247: {
                    248:        register struct ndrv_cb *np = sotondrvcb(so);
                    249: 
                    250:        if (np == 0) 
                    251:                return EINVAL;
                    252:        return local_ndrv_detach(np);
                    253: }
                    254: 
                    255: 
                    256: /*
                    257:  * If a socket isn't bound to a single address,
                    258:  * the ndrv input routine will hand it anything
                    259:  * within that protocol family (assuming there's
                    260:  * nothing else around it should go to).
                    261:  *
                    262:  * Don't expect this to be used.
                    263:  */
                    264: 
                    265: int ndrv_connect(struct socket *so, struct sockaddr *nam,
                    266:                            struct proc *p)
                    267: {
                    268:        register struct ndrv_cb *np = sotondrvcb(so);
                    269: 
                    270:        if (np == 0) 
                    271:                return EINVAL;
                    272: 
                    273:        if (np->nd_faddr) 
                    274:                return EISCONN;
                    275:        
                    276:        bcopy((caddr_t) nam, (caddr_t) np->nd_faddr, sizeof(struct sockaddr_ndrv));
                    277:        soisconnected(so);
                    278:        return 0;
                    279: }
                    280: 
                    281: /*
                    282:  * This is the "driver open" hook - we 'bind' to the
                    283:  *  named driver.
                    284:  */
                    285: int    ndrv_bind(struct socket *so, struct sockaddr *nam,
                    286:                  struct proc *p)
                    287: {
                    288:        register struct ndrv_cb *np = sotondrvcb(so);
                    289: 
                    290:        if (np == 0) 
                    291:                return EINVAL;
                    292: 
                    293:        if (np->nd_laddr) 
                    294:                return EINVAL;                  /* XXX */
                    295: 
                    296:        return local_ndrv_bind(so, (struct sockaddr_ndrv *) nam);
                    297: }
                    298: 
                    299: 
                    300: 
                    301: 
                    302: int    ndrv_disconnect(struct socket *so)
                    303: {
                    304:        register struct ndrv_cb *np = sotondrvcb(so);
                    305: 
                    306:        if (np == 0) 
                    307:                return EINVAL;
                    308: 
                    309:        if (np->nd_faddr == 0)
                    310:                return ENOTCONN;
                    311: 
                    312:        local_ndrv_disconnect(np);
                    313:        soisdisconnected(so);
                    314:        return 0;
                    315: }
                    316: 
                    317: /*
                    318:  * Mark the connection as being incapable of further input.
                    319:  */
                    320: int    ndrv_shutdown(struct socket *so)
                    321: {
                    322:        socantsendmore(so);
                    323:        return 0;
                    324: }
                    325: 
                    326: /*
                    327:  * Ship a packet out.  The ndrv output will pass it
                    328:  *  to the appropriate driver.  The really tricky part
                    329:  *  is the destination address...
                    330:  */
                    331: int    ndrv_send(struct socket *so, int flags, struct mbuf *m, 
                    332:                  struct sockaddr *addr, struct mbuf *control,
                    333:                  struct proc *p)
                    334: {
                    335:        int error;
                    336: 
                    337:        if (control) 
                    338:                return EOPNOTSUPP;
                    339: 
                    340:        error = ndrv_output(m, so);
                    341:        m = NULL;
                    342:        return error;
                    343: }
                    344: 
                    345: 
                    346: int    ndrv_abort(struct socket *so)
                    347: {
                    348:        register struct ndrv_cb *np = sotondrvcb(so);
                    349: 
                    350:        if (np == 0) 
                    351:                return EINVAL;
                    352: 
                    353:        local_ndrv_disconnect(np);
                    354:        sofree(so);
                    355:        soisdisconnected(so);
                    356:        return 0;
                    357: }
                    358: 
                    359: int    ndrv_sense(struct socket *so, struct stat *sb)
                    360: {
                    361:        /*
                    362:         * stat: don't bother with a blocksize.
                    363:         */
                    364:        return (0);
                    365: }
                    366: 
                    367: int    ndrv_sockaddr(struct socket *so, 
                    368:                       struct sockaddr **nam)
                    369: {
                    370:        register struct ndrv_cb *np = sotondrvcb(so);
                    371:        int len;
                    372: 
                    373:        if (np == 0) 
                    374:                return EINVAL;
                    375: 
                    376:        if (np->nd_laddr == 0) 
                    377:                return EINVAL;
                    378: 
                    379:        len = np->nd_laddr->snd_len;
                    380:        bcopy((caddr_t)np->nd_laddr, *nam,
                    381:              (unsigned)len);
                    382:        return 0;
                    383: }
                    384: 
                    385: 
                    386: int    ndrv_peeraddr(struct socket *so, 
                    387:                       struct sockaddr **nam)
                    388: {
                    389:        register struct ndrv_cb *np = sotondrvcb(so);
                    390:        int len;
                    391: 
                    392:        if (np == 0) 
                    393:                return EINVAL;
                    394: 
                    395:        if (np->nd_faddr == 0) 
                    396:                return ENOTCONN;
                    397: 
                    398:        len = np->nd_faddr->snd_len;
                    399:        bcopy((caddr_t)np->nd_faddr, *nam,
                    400:              (unsigned)len);
                    401:        return 0;
                    402: }
                    403: 
                    404: 
                    405: /* Control input */
                    406: 
                    407: void   ndrv_ctlinput(int dummy1, struct sockaddr *dummy2, void *dummy3)
                    408: 
                    409: {
                    410: }
                    411: 
                    412: /* Control output */
                    413: 
                    414: int    ndrv_ctloutput(struct socket *dummy1, struct sockopt *dummy2)
                    415: {
                    416:        return(0);
                    417: }
                    418: 
                    419: /* Drain the queues */
                    420: void
                    421: ndrv_drain()
                    422: {
                    423: }
                    424: 
                    425: /* Sysctl hook for NDRV */
                    426: int
                    427: ndrv_sysctl()
                    428: {
                    429:        return(0);
                    430: }
                    431: 
                    432: /*
                    433:  * Allocate an ndrv control block and some buffer space for the socket
                    434:  */
                    435: int
                    436: local_ndrv_attach(register struct socket *so,
                    437:            register int proto)
                    438: {      int error;
                    439:        register struct ndrv_cb *np = sotondrvcb(so);
                    440: 
                    441:        if ((so->so_state & SS_PRIV) == 0)
                    442:                return(EPERM);
                    443: 
                    444: #if NDRV_DEBUG
                    445:        kprintf("NDRV attach: %x, %x, %x\n", so, proto, np);
                    446: #endif
                    447:        MALLOC(np, struct ndrv_cb *, sizeof(*np), M_PCB, M_WAITOK);
                    448: #if NDRV_DEBUG
                    449:        kprintf("NDRV attach: %x, %x, %x\n", so, proto, np);
                    450: #endif
                    451:        if ((so->so_pcb = (caddr_t)np))
                    452:                bzero(np, sizeof(*np));
                    453:        else
                    454:                return(ENOBUFS);
                    455:        if ((error = soreserve(so, ndrv_sendspace, ndrv_recvspace)))
                    456:                return(error);
                    457:        np->nd_signature = NDRV_SIGNATURE;
                    458:        np->nd_socket = so;
                    459:        np->nd_proto.sp_family = so->so_proto->pr_domain->dom_family;
                    460:        np->nd_proto.sp_protocol = proto;
                    461:        insque((queue_t)np, (queue_t)&ndrvl);
                    462: //##### eeccckkk added here to get the kext filter "attached"... TEMP 
                    463: //     sfilter_init(so);
                    464:        return(0);
                    465: }
                    466: 
                    467: int
                    468: local_ndrv_detach(register struct ndrv_cb *np)
                    469: {      register struct socket *so = np->nd_socket;
                    470:        extern struct ifnet_blue *blue_if;
                    471:        extern void splitter_close(struct ndrv_cb *);
                    472: 
                    473: #if NDRV_DEBUG
                    474:        kprintf("NDRV detach: %x, %x\n", so, np);
                    475: #endif
                    476:        if (blue_if)
                    477:                splitter_close(np); /* 'np' is freed within */
                    478:        so->so_pcb = 0;
                    479:        sofree(so);
                    480:        return(0);
                    481: }
                    482: 
                    483: int
                    484: local_ndrv_disconnect(register struct ndrv_cb *np)
                    485: {
                    486: #if NDRV_DEBUG
                    487:        kprintf("NDRV disconnect: %x\n", np);
                    488: #endif
                    489:        if (np->nd_faddr)
                    490:        {       m_freem(dtom(np->nd_faddr));
                    491:                np->nd_faddr = 0;
                    492:        }
                    493:        if (np->nd_socket->so_state & SS_NOFDREF)
                    494:                local_ndrv_detach(np);
                    495:        return(0);
                    496: }
                    497: 
                    498: /*
                    499:  * Here's where we latch onto the driver and make it ours.
                    500:  */
                    501: int
                    502: local_ndrv_bind(register struct socket *so,
                    503:          register struct sockaddr_ndrv *sa)
                    504: {      register char *dname;
                    505:        register struct ndrv_cb *np;
                    506:        register struct ifnet *ifp;
                    507:        extern int name_cmp(struct ifnet *, char *);
                    508: 
                    509:        if TAILQ_EMPTY(&ifnet)
                    510:                return(EADDRNOTAVAIL); /* Quick sanity check */
                    511:        np = sotondrvcb(so);
                    512: 
                    513:        /* I think we just latch onto a copy here; the caller frees */
                    514: 
                    515:        
                    516:        np->nd_laddr = _MALLOC(sizeof(struct sockaddr_ndrv), M_IFADDR, M_WAITOK);
                    517:        bcopy((caddr_t) sa, (caddr_t) np->nd_laddr, sizeof(struct sockaddr_ndrv));
                    518:        dname = sa->snd_name;
                    519:        if (dname == NULL)
                    520:                return(EINVAL);
                    521: #if NDRV_DEBUG
                    522:        kprintf("NDRV bind: %x, %x, %s\n", so, np, dname);
                    523: #endif
                    524:        /* Track down the driver and its ifnet structure.
                    525:         * There's no internal call for this so we have to dup the code
                    526:         *  in if.c/ifconf()
                    527:         */
                    528:        TAILQ_FOREACH(ifp, &ifnet, if_link) {
                    529:                if (name_cmp(ifp, dname) == 0)
                    530:                        break;
                    531:        }
                    532: 
                    533:        if (ifp == NULL)
                    534:                return(EADDRNOTAVAIL);
                    535:        /*
                    536:         * Now, at this point, we should force open the driver and somehow
                    537:         *  register ourselves to receive packets (a la the bpf).
                    538:         * However, we have this groaty hack in place that makes it
                    539:         *  not necessary for blue box purposes (the 'splitter' trick).
                    540:         * If we want this to be a full-fledged AF, we have to force the
                    541:         *  open and implement a filter mechanism.
                    542:         */
                    543:        np->nd_if = ifp;
                    544:        return(0);
                    545: }
                    546: 
                    547: /*
                    548:  * Try to compare a device name (q) with one of the funky ifnet
                    549:  *  device names (ifp).
                    550:  */
                    551: int name_cmp(register struct ifnet *ifp, register char *q)
                    552: {      register char *r;
                    553:        register int len;
                    554:        char buf[IFNAMSIZ];
                    555:        static char *sprint_d();
                    556: 
                    557:        r = buf;
                    558:        len = strlen(ifp->if_name);
                    559:        strncpy(r, ifp->if_name, IFNAMSIZ);
                    560:        r += len;
                    561:        (void)sprint_d(ifp->if_unit, r, r-buf);
                    562: #if NDRV_DEBUG
                    563:        kprintf("Comparing %s, %s\n", buf, q);
                    564: #endif
                    565:        return(strncmp(buf, q, IFNAMSIZ));
                    566: }
                    567: 
                    568: /* Hackery - return a string version of a decimal number */
                    569: static char *
                    570: sprint_d(n, buf, buflen)
                    571:         u_int n;
                    572:         char *buf;
                    573:         int buflen;
                    574: {
                    575:         register char *cp = buf + buflen - 1;
                    576: 
                    577:         *cp = 0;
                    578:         do {
                    579:                 cp--;
                    580:                 *cp = "0123456789"[n % 10];
                    581:                 n /= 10;
                    582:         } while (n != 0);
                    583:         return (cp);
                    584: }
                    585: 
                    586: /*
                    587:  * When closing, dump any enqueued mbufs.
                    588:  */
                    589: void
                    590: ndrv_flushq(register struct ifqueue *q)
                    591: {      register struct mbuf *m;
                    592:        register int s;
                    593:        for (;;)
                    594:        {       s = splimp();
                    595:                IF_DEQUEUE(q, m);
                    596:                if (m == NULL)
                    597:                        break;
                    598:                IF_DROP(q);
                    599:                splx(s);
                    600:                if (m)
                    601:                        m_freem(m);
                    602:        }
                    603:        splx(s);
                    604: }
                    605: 
                    606: 
                    607: struct pr_usrreqs ndrv_usrreqs = {
                    608:        ndrv_abort, pru_accept_notsupp, ndrv_attach, ndrv_bind,
                    609:        ndrv_connect, pru_connect2_notsupp, ndrv_control, ndrv_detach,
                    610:        ndrv_disconnect, pru_listen_notsupp, ndrv_peeraddr, pru_rcvd_notsupp,
                    611:        pru_rcvoob_notsupp, ndrv_send, ndrv_sense, ndrv_shutdown,
                    612:        ndrv_sockaddr, sosend, soreceive, sopoll
                    613: };
                    614: 
                    615: struct domain ndrvdomain;
                    616: 
                    617: struct protosw ndrvsw[] =
                    618: {      {       SOCK_RAW, &ndrvdomain, 0, PR_ATOMIC|PR_ADDR,
                    619:                0, ndrv_output, ndrv_ctlinput, ndrv_ctloutput,
                    620:                0, ndrv_init, 0, 0,
                    621:                ndrv_drain, ndrv_sysctl, &ndrv_usrreqs
                    622:        }
                    623: };
                    624: 
                    625: 
                    626: struct domain ndrvdomain =
                    627: {      AF_NDRV, "NetDriver", NULL, NULL, NULL,
                    628:        ndrvsw,
                    629:        NULL, NULL, 0, 0, 0, 0
                    630: };

unix.superglobalmegacorp.com

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