Annotation of XNU/bsd/netat/aurp_aurpd.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: /*
                     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.