Annotation of XNU/bsd/netat/aurp_aurpd.c, revision 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: /*
        !            23:  *     Copyright (c) 1996 Apple Computer, Inc. 
        !            24:  *
        !            25:  *             Created April 25, 1996, by Justin C. Walker
        !            26:  *   Modified, March 17, 1997 by Tuyen Nguyen for MacOSX.
        !            27:  *
        !            28:  *     File: aurpd.c
        !            29:  */
        !            30: 
        !            31: /*
        !            32:  * Kernel process to implement the AURP daemon:
        !            33:  *  manage tunnels to remote AURP servers across IP networks
        !            34:  */
        !            35: 
        !            36: #include <sys/errno.h>
        !            37: #include <sys/types.h>
        !            38: #include <sys/param.h>
        !            39: #include <machine/spl.h>
        !            40: #include <sys/systm.h>
        !            41: #include <sys/kernel.h>
        !            42: #include <sys/proc.h>
        !            43: #include <sys/filedesc.h>
        !            44: #include <sys/fcntl.h>
        !            45: #include <sys/mbuf.h>
        !            46: #include <sys/socket.h>
        !            47: #include <sys/socketvar.h>
        !            48: #include <sys/protosw.h>
        !            49: #include <sys/malloc.h>
        !            50: #include <sys/proc.h>
        !            51: #include <netinet/in.h>
        !            52: #include <net/if.h>
        !            53: 
        !            54: #include <netat/sysglue.h>
        !            55: #include <netat/appletalk.h>
        !            56: #include <netat/at_var.h>
        !            57: #include <netat/routing_tables.h>
        !            58: #include <netat/at_pcb.h>
        !            59: #include <netat/aurp.h>
        !            60: #include <netat/debug.h>
        !            61: 
        !            62: #define M_RCVBUF (64 * 1024)
        !            63: #define M_SNDBUF (64 * 1024)
        !            64: 
        !            65: static int ip_to_atalk(struct sockaddr_in *fp, register gbuf_t *p_mbuf);
        !            66: static int aurp_bindrp(struct socket *so);
        !            67: 
        !            68: struct aurp_global_t aurp_global;
        !            69: 
        !            70: /*
        !            71:  * Initialize the aurp pipe -
        !            72:  * -Create, initialize, and start the aurpd kernel process; we need
        !            73:  *  a process to permit queueing between the socket and the stream,
        !            74:  *  which is necessary for orderly access to the socket structure.
        !            75:  * -The user process (aurpd) is there to 'build' the AURP
        !            76:  *  stream, act as a 'logging agent' (:-}), and hold open the stream
        !            77:  *  during its use.
        !            78:  * -Data and AURP packets from the DDP stream will be fed into the
        !            79:  *  UDP tunnel (AURPsend())
        !            80:  * -Data and AURP packets from the UDP tunnel will be fed into the
        !            81:  *  DDP stream (ip_to_atalk(), via the kernel process).
        !            82:  */
        !            83: int
        !            84: aurpd_start()
        !            85: {
        !            86:        register int error;
        !            87:        register struct socket *so;
        !            88:        struct mbuf *m;
        !            89:        int maxbuf;
        !            90:        struct sockopt sopt;
        !            91: 
        !            92:        if (suser(current_proc()->p_ucred, &current_proc()->p_acflag) != 0 )
        !            93:                return(EPERM);
        !            94: 
        !            95:        /*
        !            96:         * Set up state prior to starting kernel process so we can back out
        !            97:         *  (error return) if something goes wrong.
        !            98:         */
        !            99:        bzero((char *)&aurp_global.tunnel, sizeof(aurp_global.tunnel));
        !           100:        /*lock_alloc(&aurp_global.glock, LOCK_ALLOC_PIN, AURP_EVNT_LOCK, -1);*/
        !           101:        ATLOCKINIT(aurp_global.glock);
        !           102:        ATEVENTINIT(aurp_global.event_anchor);
        !           103: 
        !           104:        /* open udp socket */
        !           105:        if (aurp_global.udp_port == 0)
        !           106:                aurp_global.udp_port = AURP_SOCKNUM;
        !           107:        error = socreate(AF_INET, &aurp_global.tunnel, SOCK_DGRAM,
        !           108:                         IPPROTO_UDP);
        !           109:        if (error)
        !           110:        {       dPrintf(D_M_AURP, D_L_FATAL, ("AURP: Can't get socket (%d)\n",
        !           111:                        error));
        !           112:                return(error);
        !           113:        }
        !           114: 
        !           115:        so = aurp_global.tunnel;
        !           116: 
        !           117:        if ((error = aurp_bindrp(so)) != 0)
        !           118:        {       dPrintf(D_M_AURP, D_L_FATAL,
        !           119:                        ("AURP: Can't bind to port %d (error %d)\n",
        !           120:                        aurp_global.udp_port, error));
        !           121:                soclose(so);
        !           122:                return(error);
        !           123:        }
        !           124: 
        !           125:        sblock(&so->so_rcv, M_WAIT);
        !           126:        sblock(&so->so_snd, M_WAIT);
        !           127: 
        !           128:        /*
        !           129:         * Set socket Receive buffer size
        !           130:         */
        !           131:        m = m_get(M_WAIT, MT_SOOPTS);
        !           132:        if (m == NULL) {
        !           133:                error = ENOBUFS;
        !           134:                goto out;
        !           135:        } else {
        !           136:                maxbuf = M_RCVBUF;
        !           137:                sopt.sopt_val     = &maxbuf;
        !           138:                sopt.sopt_valsize = sizeof(maxbuf);
        !           139:                sopt.sopt_level   = SOL_SOCKET;
        !           140:                sopt.sopt_name    = SO_RCVBUF;
        !           141:                sopt.sopt_dir     = SOPT_SET;
        !           142:                if ((error = sosetopt(so, &sopt)) != 0)
        !           143:                        goto out;
        !           144:        }
        !           145: 
        !           146:        /*
        !           147:         * Set socket Send buffer size
        !           148:         */
        !           149:        m = m_get(M_WAIT, MT_SOOPTS);
        !           150:        if (m == NULL) {
        !           151:                error = ENOBUFS;
        !           152:                goto out;
        !           153:        } else {
        !           154: 
        !           155:                maxbuf = M_SNDBUF;
        !           156:                sopt.sopt_val     = &maxbuf;
        !           157:                sopt.sopt_valsize = sizeof(maxbuf);
        !           158:                sopt.sopt_level   = SOL_SOCKET;
        !           159:                sopt.sopt_name    = SO_SNDBUF;
        !           160:                sopt.sopt_dir     = SOPT_SET;
        !           161:                if ((error = sosetopt(so, &sopt)) != 0)
        !           162:                        goto out;
        !           163:        }
        !           164: 
        !           165:        so->so_upcall = aurp_wakeup;
        !           166:        so->so_upcallarg = (caddr_t)AE_UDPIP; /* Yuck */
        !           167:        so->so_state |= SS_NBIO;
        !           168:        so->so_rcv.sb_flags |=(SB_SEL|SB_NOINTR);
        !           169:        so->so_snd.sb_flags |=(SB_SEL|SB_NOINTR);
        !           170: 
        !           171: out:
        !           172:        sbunlock(&so->so_snd);
        !           173:        sbunlock(&so->so_rcv);
        !           174: 
        !           175:        return(error);
        !           176: }
        !           177: 
        !           178: int
        !           179: AURPgetmsg(err)
        !           180:        int *err;
        !           181: {      register struct socket *so;
        !           182:        register int s, events;
        !           183: 
        !           184:        so = aurp_global.tunnel;
        !           185:        *err = 0;
        !           186: 
        !           187:        for (;;)
        !           188:        {       gbuf_t *from, *p_mbuf;
        !           189:                int flags = MSG_DONTWAIT;
        !           190:                struct uio auio;
        !           191: 
        !           192:                /*
        !           193:                 * Wait for a package to arrive.  This will be from the
        !           194:                 * IP side - sowakeup() calls aurp_wakeup()
        !           195:                 *           when a packet arrives
        !           196:                 */
        !           197: 
        !           198:                ATDISABLE(s, aurp_global.glock);
        !           199:                events = aurp_global.event;
        !           200:                if (((*err == 0) || (*err == EWOULDBLOCK)) && events == 0)
        !           201:                  {
        !           202:                    *err = tsleep(&aurp_global.event_anchor, PSOCK | PCATCH, "AURPgetmsg", 0);
        !           203:                    events = aurp_global.event;
        !           204:                    aurp_global.event = 0;
        !           205:                  }     
        !           206:                ATENABLE(s, aurp_global.glock);  
        !           207: 
        !           208:                /*
        !           209:                 * Shut down if we have the AE_SHUTDOWN event or if we got
        !           210:                 * a system error other than EWOULDBLOCK, such as EINTR.
        !           211:                 */
        !           212:                if (((*err != EWOULDBLOCK) && (*err != 0)) || events & AE_SHUTDOWN)
        !           213:                  {     
        !           214:                    dPrintf(D_M_AURP, D_L_SHUTDN_INFO,
        !           215:                        ("AURPgetmsg: AE_SHUTDOWN detected--starting shutdown sequence\n"));
        !           216:                    aurp_global.shutdown = 1;
        !           217:                    while (aurp_global.running)
        !           218:                        ;
        !           219:                    /*lock_free(&aurp_global.glock);*/
        !           220:                    aurp_global.tunnel = 0;
        !           221:                    aurp_global.event = 0;
        !           222:                    aurp_global.shutdown = 0;
        !           223:                    soclose(so);
        !           224:                    if (*err == 0)
        !           225:                    *err = ESHUTDOWN;
        !           226:                    dPrintf(D_M_AURP, D_L_SHUTDN_INFO,
        !           227:                        ("AURPgetmsg: shutdown completed\n"));
        !           228:                    return -1;
        !           229:                  }
        !           230: 
        !           231: 
        !           232: 
        !           233:                /*
        !           234:                 * Set up the nominal uio structure -
        !           235:                 *  give it no iov's, point off to non-existant user space,
        !           236:                 *  but make sure the 'resid' count means somehting.
        !           237:                 */
        !           238: 
        !           239:                auio.uio_iov = NULL;
        !           240:                auio.uio_iovcnt = 0;
        !           241:                auio.uio_segflg = UIO_SYSSPACE;
        !           242:                auio.uio_offset = 0;                    /* XXX */
        !           243: 
        !           244:                /* Keep up an even flow... */
        !           245:                for (;;)
        !           246:                {
        !           247: /*
        !           248:  * This should be large enough to encompass a full DDP packet plus
        !           249:  *  domain header.
        !           250:  */
        !           251: #define A_LARGE_SIZE 700
        !           252: 
        !           253:                        flags = MSG_DONTWAIT;
        !           254:                        auio.uio_resid = A_LARGE_SIZE;
        !           255:                        *err = soreceive(so, (struct sockaddr **)&from, &auio, &p_mbuf, 0, &flags);
        !           256:                        dPrintf(D_M_AURP, D_L_VERBOSE,
        !           257:                                ("AURPgetmsg: soreceive returned %d, aurp_global.event==0x%x\n", *err, events));
        !           258:                        /* soreceive() sets *mp to zero! at start */
        !           259:                        if (p_mbuf)
        !           260:                                ip_to_atalk(from, p_mbuf);
        !           261:                        if (*err || (p_mbuf == NULL)) {
        !           262:                                /*
        !           263:                                 * An error occurred in soreceive(),
        !           264:                                 * so clear the data input event flag
        !           265:                                 * and break out of this inner loop.
        !           266:                                 *
        !           267:                                 * XXX Note that clearing AE_UDPIP here could
        !           268:                                 * cause us to lose an AE_UDPIP event that
        !           269:                                 * was posted in aurp_global.event between
        !           270:                                 * the soreceive() above and the code here.
        !           271:                                 * The protocol should recover from this
        !           272:                                 * lost event, though, since the next
        !           273:                                 * request (a tickle, for example) from
        !           274:                                 * the other end of the tunnel will cause
        !           275:                                 * another AE_UDPIP event to be posted,
        !           276:                                 * which will wake us from the sleep at
        !           277:                                 * the top of the outer loop.
        !           278:                                 */
        !           279:                                int s;
        !           280:                                ATDISABLE(s, aurp_global.glock);
        !           281:                                aurp_global.event &= ~AE_UDPIP;
        !           282:                                ATENABLE(s, aurp_global.glock);
        !           283:                                dPrintf(D_M_AURP, D_L_WARNING, ("AURPgetmsg: spurious soreceive, err==%d, p_mbuf==0x%x\n", *err, (unsigned int) p_mbuf));
        !           284:                          break;
        !           285:                }
        !           286:        }
        !           287:        }
        !           288:        return -1;
        !           289: }
        !           290: 
        !           291: /*
        !           292:  * Wakeup the sleeping giant - we've put a message on his queue(s).
        !           293:  * The arg indicates what queue has been updated.
        !           294:  *
        !           295:  * This conforms to the so_upcall function pointer member of struct sockbuf.
        !           296:  */
        !           297: void aurp_wakeup(struct socket *so, register caddr_t p, int state)
        !           298: {
        !           299:        register int s;
        !           300:        register int bit;
        !           301: 
        !           302:        bit = (int) p;
        !           303:        ATDISABLE(s, aurp_global.glock);
        !           304:        aurp_global.event |= bit;
        !           305:        ATENABLE(s, aurp_global.glock);
        !           306: 
        !           307:        dPrintf(D_M_AURP, D_L_STATE_CHG,
        !           308:                ("aurp_wakeup: bit 0x%x, aurp_global.event now 0x%x\n",
        !           309:                bit, aurp_global.event));
        !           310: 
        !           311:        thread_wakeup(&aurp_global.event_anchor);
        !           312: }
        !           313: 
        !           314: /*
        !           315:  * Try to bind to the specified reserved port.
        !           316:  * Sort of like sobind(), but no suser() check.
        !           317:  */
        !           318: static int
        !           319: aurp_bindrp(struct socket *so)
        !           320: {
        !           321:        struct sockaddr_in sin;
        !           322:        struct proc *p = current_proc();
        !           323:        gbuf_t *m;
        !           324:        int error;
        !           325: 
        !           326: 
        !           327:        bzero(&sin, sizeof(sin));
        !           328:        sin.sin_family      = AF_INET;
        !           329:        sin.sin_addr.s_addr = htons(aurp_global.src_addr);
        !           330:        sin.sin_port        = htons(aurp_global.udp_port);
        !           331:        sin.sin_len         = sizeof(struct sockaddr_in);
        !           332: 
        !           333:        sblock(&so->so_rcv, M_WAIT);
        !           334:        sblock(&so->so_snd, M_WAIT);
        !           335:        so->so_state |= SS_PRIV;
        !           336:        error = (*so->so_proto->pr_usrreqs->pru_bind)(so, (struct sockaddr *) &sin, p);
        !           337:        sbunlock(&so->so_snd);
        !           338:        sbunlock(&so->so_rcv);
        !           339: 
        !           340:        return (error);
        !           341: }
        !           342: 
        !           343: /*
        !           344:  * receive from UDP
        !           345:  * fp is the 'source address' mbuf; p_mbuf is the data mbuf.
        !           346:  * Use the source address to find the 'node number' (index of the address),
        !           347:  *  and pass that to the next stage.
        !           348:  */
        !           349: int ip_to_atalk(register struct sockaddr_in *rem_addr, register gbuf_t *p_mbuf)
        !           350: {      
        !           351:        register aurp_domain_t *domain;
        !           352:        unsigned char node;
        !           353: 
        !           354: 
        !           355:        /* determine the node where the packet came from */
        !           356:        for (node=1; node <= dst_addr_cnt; node++) {
        !           357:                if (aurp_global.dst_addr[node] == *(long *)&rem_addr->sin_addr)
        !           358:                        break;
        !           359:        }
        !           360:        if (node > dst_addr_cnt) {
        !           361:                dPrintf(D_M_AURP, D_L_WARNING,
        !           362:                        ("AURPrecv: invalid node, %d.%lx\n",
        !           363:                        rem_addr->sin_port,
        !           364:                        rem_addr->sin_addr.s_addr));
        !           365:                
        !           366:                gbuf_freem(p_mbuf);
        !           367:                FREE(rem_addr, M_SONAME);
        !           368:                return -1;
        !           369:        }
        !           370: 
        !           371:        /* validate the domain */
        !           372:        domain = (aurp_domain_t *)gbuf_rptr(p_mbuf);
        !           373:        if ( (domain->dst_length != IP_LENGTH) ||
        !           374:            (domain->dst_authority != IP_AUTHORITY) ||
        !           375:            (domain->version != AUD_Version) ||
        !           376:            ((domain->type != AUD_Atalk) && (domain->type != AUD_AURP)) ) {
        !           377:                dPrintf(D_M_AURP, D_L_WARNING,
        !           378:                        ("AURPrecv: invalid domain, %d.%lx\n",
        !           379:                        rem_addr->sin_port,
        !           380:                        rem_addr->sin_addr.s_addr));
        !           381:                
        !           382:                gbuf_freem(p_mbuf);
        !           383:                FREE(rem_addr, M_SONAME);
        !           384:                return -1;
        !           385:        }
        !           386: 
        !           387:        /* Remove domain header */
        !           388:        p_mbuf->m_pkthdr.len -= IP_DOMAINSIZE;
        !           389:        gbuf_rinc(p_mbuf,IP_DOMAINSIZE);
        !           390:        gbuf_set_type(p_mbuf, MSG_DATA);
        !           391: 
        !           392:        /* forward the packet to the local AppleTalk stack */
        !           393: 
        !           394:        at_insert(p_mbuf, domain->type, node);
        !           395:        FREE(rem_addr, M_SONAME);
        !           396:        return 0;
        !           397: }
        !           398: 
        !           399: /*
        !           400:  * send to UDP
        !           401:  * The real work has been done already.         Here, we just cobble together
        !           402:  *  a sockaddr for the destination and call sosend().
        !           403:  */
        !           404: void
        !           405: atalk_to_ip(register gbuf_t *m)
        !           406: {      register aurp_domain_t *domain;
        !           407:        int error;
        !           408:        int flags = MSG_DONTWAIT;
        !           409:        struct sockaddr_in rem_addr;
        !           410:        int s;
        !           411: 
        !           412:        m->m_type = MT_HEADER;
        !           413:        m->m_pkthdr.len = gbuf_msgsize(m);
        !           414:        m->m_pkthdr.rcvif = 0;
        !           415: 
        !           416:        bzero((char *) &rem_addr, sizeof(rem_addr));
        !           417:        rem_addr.sin_family = PF_INET;
        !           418:        rem_addr.sin_port = aurp_global.udp_port;
        !           419:        rem_addr.sin_len  = sizeof (struct sockaddr_in);
        !           420:        domain = (aurp_domain_t *)gbuf_rptr(m);
        !           421:        *(long *) &rem_addr.sin_addr = domain->dst_address;
        !           422: 
        !           423:        ATDISABLE(s, aurp_global.glock);
        !           424:        aurp_global.running++;
        !           425:        ATENABLE(s, aurp_global.glock);
        !           426:        if (aurp_global.shutdown) {
        !           427:                gbuf_freem(m);
        !           428:                        ATDISABLE(s, aurp_global.glock);
        !           429:                aurp_global.running--;
        !           430:                ATENABLE(s, aurp_global.glock);
        !           431:                dPrintf(D_M_AURP, D_L_SHUTDN_INFO,
        !           432:                        ("atalk_to_ip: detected aurp_global.shutdown state\n"));
        !           433:                return;
        !           434:        }
        !           435:        dPrintf(D_M_AURP, D_L_VERBOSE, ("atalk_to_ip: calling sosend\n"));
        !           436:        error = sosend(aurp_global.tunnel, (struct sockaddr *) &rem_addr, NULL, m, NULL, flags);
        !           437:        if (error)
        !           438:        {       /*log error*/
        !           439:          dPrintf(D_M_AURP, D_L_ERROR, ("AURP: sosend error (%d)\n",
        !           440:                  error));
        !           441:        }
        !           442: 
        !           443:        ATDISABLE(s, aurp_global.glock);
        !           444:        aurp_global.running--;
        !           445:        ATENABLE(s, aurp_global.glock);
        !           446:        return;
        !           447: }
        !           448: 

unix.superglobalmegacorp.com

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