Annotation of kernel/bsd/netat/aurp_aurpd.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
        !             3:  *
        !             4:  * @APPLE_LICENSE_HEADER_START@
        !             5:  * 
        !             6:  * Portions Copyright (c) 1999 Apple Computer, Inc.  All Rights
        !             7:  * Reserved.  This file contains Original Code and/or Modifications of
        !             8:  * Original Code as defined in and that are subject to the Apple Public
        !             9:  * Source License Version 1.1 (the "License").  You may not use this file
        !            10:  * except in compliance with the License.  Please obtain a copy of the
        !            11:  * License at http://www.apple.com/publicsource and read it before using
        !            12:  * this file.
        !            13:  * 
        !            14:  * The Original Code and all software distributed under the License are
        !            15:  * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
        !            16:  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
        !            17:  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
        !            18:  * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT.  Please see the
        !            19:  * License for the specific language governing rights and limitations
        !            20:  * under the License.
        !            21:  * 
        !            22:  * @APPLE_LICENSE_HEADER_END@
        !            23:  */
        !            24: 
        !            25: /*
        !            26:  *     Copyright (c) 1996 Apple Computer, Inc. 
        !            27:  *
        !            28:  *     The information contained herein is subject to change without
        !            29:  *     notice and  should not be  construed as a commitment by Apple
        !            30:  *     Computer, Inc. Apple Computer, Inc. assumes no responsibility
        !            31:  *     for any errors that may appear.
        !            32:  *
        !            33:  *     Confidential and Proprietary to Apple Computer, Inc.
        !            34:  *
        !            35:  *     File: aurpd.c
        !            36:  */
        !            37: 
        !            38: /*
        !            39:  * Kernel process to implement the AURP daemon:
        !            40:  *  manage tunnels to remote AURP servers across IP networks
        !            41:  */
        !            42: #ifdef _AIX
        !            43: #include <sys/sleep.h>
        !            44: #endif
        !            45: #include <sysglue.h>
        !            46: #ifdef _AIX
        !            47: #include <sys/atomic_op.h>
        !            48: #endif
        !            49: #include <sys/socket.h>
        !            50: #include <sys/socketvar.h>
        !            51: #include <sys/protosw.h>
        !            52: #include <sys/errno.h>
        !            53: #include <netinet/in.h>
        !            54: #include <at/appletalk.h>
        !            55: #include <lap.h>
        !            56: #include <routing_tables.h>
        !            57: #define _AURP
        !            58: #define _KERNSYS
        !            59: #include <at/aurp.h>
        !            60: #include <at_aurp.h>
        !            61: 
        !            62: 
        !            63: #undef  e_sleep_thread
        !            64: #define M_RCVBUF (64 * 1024)
        !            65: #define M_SNDBUF (64 * 1024)
        !            66: struct aurp_global_t aurp_global;
        !            67: /*
        !            68:  * Initialize the aurp pipe -
        !            69:  * -Create, initialize, and start the aurpd kernel process; we need
        !            70:  *  a process to permit queueing between the socket and the stream,
        !            71:  *  which is necessary for orderly access to the socket structure.
        !            72:  * -The user process (aurpd) is there to 'build' the AURP
        !            73:  *  stream, act as a 'logging agent' (:-}), and hold open the stream
        !            74:  *  during its use.
        !            75:  * -Data and AURP packets from the DDP stream will be fed into the
        !            76:  *  UDP tunnel (AURPsend())
        !            77:  * -Data and AURP packets from the UDP tunnel will be fed into the
        !            78:  *  DDP stream (ip_to_atalk(), via the kernel process).
        !            79:  */
        !            80: aurpd_start()
        !            81: {      register int error;
        !            82:        register struct socket *so;
        !            83:        int maxbuf;
        !            84:        extern void aurp_wakeup(caddr_t, int);
        !            85: /****### TEMPO HACK 9/26: we need more args than that for suser in bsd4.4 
        !            86:        if (!suser())
        !            87:                return(EPERM);
        !            88: */
        !            89: 
        !            90:        /*
        !            91:         * Set up state prior to starting kernel process so we can back out
        !            92:         *  (error return) if something goes wrong.
        !            93:         */
        !            94:        bzero((char *)&aurp_global.tunnel, sizeof(aurp_global.tunnel));
        !            95:        /*lock_alloc(&aurp_global.glock, LOCK_ALLOC_PIN, AURP_EVNT_LOCK, -1);*/
        !            96:        ATLOCKINIT(aurp_global.glock);
        !            97:        ATEVENTINIT(aurp_global.event_anchor);
        !            98: 
        !            99:        /* open udp socket */
        !           100:        if (aurp_global.udp_port == 0)
        !           101:                aurp_global.udp_port = AURP_SOCKNUM;
        !           102:        error = socreate(AF_INET, &aurp_global.tunnel, SOCK_DGRAM,
        !           103:                         IPPROTO_UDP);
        !           104:        if (error)
        !           105:        {       dPrintf(D_M_AURP, D_L_FATAL, ("AURP: Can't get socket (%d)\n",
        !           106:                        error));
        !           107:                return(error);
        !           108:        }
        !           109: 
        !           110:        so = aurp_global.tunnel;
        !           111: 
        !           112:        if (error = aurp_bindrp(so))
        !           113:        {       dPrintf(D_M_AURP, D_L_FATAL,
        !           114:                        ("AURP: Can't bind to port %d (%d)\n",
        !           115:                        &aurp_global.udp_port, error));
        !           116:                soclose(so);
        !           117:                return(error);
        !           118:        }
        !           119: 
        !           120: #ifdef _AIX
        !           121:        SOCKET_LOCK(so);
        !           122: #else
        !           123:        sblock(&so->so_rcv, M_WAIT);
        !           124:        sblock(&so->so_snd, M_WAIT);
        !           125: #endif
        !           126:        maxbuf = M_RCVBUF;
        !           127:        setsockopt(so,SOL_SOCKET,SO_RCVBUF,&maxbuf,sizeof(maxbuf));
        !           128:        maxbuf = M_SNDBUF;
        !           129:        setsockopt(so,SOL_SOCKET,SO_SNDBUF,&maxbuf,sizeof(maxbuf));
        !           130: #ifdef _AIX
        !           131:        so->so_snd.sb_wakeup  = 0;
        !           132:        so->so_snd.sb_wakearg = 0;
        !           133:        so->so_rcv.sb_wakeup  = aurp_wakeup;
        !           134:        so->so_rcv.sb_wakearg = (caddr_t)AE_UDPIP; /* Yuck */
        !           135:        so->so_rcv.sb_iodone  = 0;
        !           136:        so->so_rcv.sb_ioarg = 0;
        !           137: #else
        !           138:        so->so_upcall = aurp_wakeup;
        !           139:        so->so_upcallarg = (caddr_t)AE_UDPIP; /* Yuck */
        !           140: #endif
        !           141: 
        !           142:        so->so_state |= SS_NBIO;
        !           143: #ifdef _AIX
        !           144:        so->so_special |=(SP_NOUAREA|SP_EXTPRIV);
        !           145: #else
        !           146:        kprintf("aurpd: warning what do we do with so_special?");
        !           147: #endif
        !           148:        so->so_rcv.sb_flags |=(SB_SEL|SB_NOINTR);
        !           149:        so->so_snd.sb_flags |=(SB_SEL|SB_NOINTR);
        !           150: #ifdef _AIX
        !           151:        SOCKET_UNLOCK(so);
        !           152: #else
        !           153:        sbunlock(&so->so_snd);
        !           154:        sbunlock(&so->so_rcv);
        !           155: #endif
        !           156: 
        !           157:        return(0);
        !           158: }
        !           159: 
        !           160: AURPgetmsg(err)
        !           161:        int *err;
        !           162: {      register struct socket *so;
        !           163:        register int s, events;
        !           164: 
        !           165:        so = aurp_global.tunnel;
        !           166: 
        !           167:        for (;;)
        !           168:        {       gbuf_t *from, *p_mbuf;
        !           169: #ifdef _AIX
        !           170:                int flags = MSG_NONBLOCK;
        !           171: #else
        !           172:                int flags = MSG_DONTWAIT;
        !           173: #endif
        !           174:                struct uio auio;
        !           175: 
        !           176:                /*
        !           177:                 * Wait for a package to arrive.  This will be from the
        !           178:                 * IP side - sowakeup() calls aurp_wakeup()
        !           179:                 *           when a packet arrives
        !           180:                 */
        !           181: 
        !           182:                ATDISABLE(s, aurp_global.glock);
        !           183:                events = aurp_global.event;
        !           184:                if (events == 0)
        !           185:                  {
        !           186: #ifdef _AIX
        !           187:                    e_sleep_thread(&aurp_global.event_anchor,
        !           188:                                        &aurp_global.glock, LOCK_HANDLER);
        !           189: #else
        !           190:                    (void) tsleep(&aurp_global.event_anchor, PSOCK, "AURPgetmsg", 0);
        !           191: #endif
        !           192:                    events = aurp_global.event;
        !           193:                    aurp_global.event = 0;
        !           194:                  }     
        !           195:                ATENABLE(s, aurp_global.glock);  
        !           196: 
        !           197:                if (events & AE_SHUTDOWN)
        !           198:                  {     
        !           199:                    aurp_global.shutdown = 1;
        !           200:                    while (aurp_global.running)
        !           201:                        ;
        !           202:                    /*lock_free(&aurp_global.glock);*/
        !           203:                    aurp_global.tunnel = 0;
        !           204:                    aurp_global.event = 0;
        !           205:                    soclose(so);
        !           206:                    *err = ESHUTDOWN;
        !           207:                    return -1;
        !           208:                  }
        !           209: 
        !           210: 
        !           211: 
        !           212:                /*
        !           213:                 * Set up the nominal uio structure -
        !           214:                 *  give it no iov's, point off to non-existant user space,
        !           215:                 *  but make sure the 'resid' count means somehting.
        !           216:                 */
        !           217: 
        !           218:                auio.uio_iov = NULL;
        !           219:                auio.uio_iovcnt = 0;
        !           220:                auio.uio_segflg = UIO_SYSSPACE;
        !           221:                auio.uio_offset = 0;                    /* XXX */
        !           222: 
        !           223:                /* Keep up an even flow... */
        !           224:                for (;;)
        !           225:                {       register int empty = 0;
        !           226: 
        !           227: /*
        !           228:  * This should be large enough to encompass a full DDP packet plus
        !           229:  *  domain header.
        !           230:  */
        !           231: #define A_LARGE_SIZE 700
        !           232: #ifdef _AIX
        !           233:                        flags = MSG_NONBLOCK;
        !           234: #else
        !           235:                        flags = MSG_DONTWAIT;
        !           236: #endif
        !           237:                        auio.uio_resid = A_LARGE_SIZE;
        !           238:                        *err = soreceive(so, &from, &auio, &p_mbuf, 0, &flags);
        !           239:                        dPrintf(D_M_AURP, D_L_WARNING,
        !           240:                                ("aurpd: soreceive returned %d\n", *err));
        !           241:                        /* soreceive() sets *mp to zero! at start */
        !           242:                        if (p_mbuf)
        !           243:                                ip_to_atalk(from, p_mbuf);
        !           244:                        else
        !           245:                          break;
        !           246:                }
        !           247:        }
        !           248: 
        !           249:        return -1;
        !           250: }
        !           251: 
        !           252: /*
        !           253:  * Wakeup the sleeping giant - we've put a message on his queue(s).
        !           254:  * The arg indicates what queue has been updated.
        !           255:  */
        !           256: void aurp_wakeup(register caddr_t p, int state)
        !           257: {      register int s;
        !           258:        register int bit;
        !           259: 
        !           260:        bit = (int) p;
        !           261:        ATDISABLE(s, aurp_global.glock);
        !           262:        aurp_global.event |= bit;
        !           263:        ATENABLE(s, aurp_global.glock);
        !           264: #ifdef _AIX
        !           265:        e_wakeup(&aurp_global.event_anchor);
        !           266: #else
        !           267:        thread_wakeup(&aurp_global.event_anchor);
        !           268: #endif
        !           269: }
        !           270: 
        !           271: /*
        !           272:  * Try to bind to the specified reserved port.
        !           273:  * Sort of like sobind(), but no suser() check.
        !           274:  */
        !           275: aurp_bindrp(so)
        !           276:        register struct socket *so;
        !           277: {
        !           278:        struct sockaddr_in *sin;
        !           279:        gbuf_t *m;
        !           280:        u_short i;
        !           281:        int error;
        !           282:        struct ucred *savecred;
        !           283: 
        !           284:        m = (gbuf_t *)gbuf_alloc(sizeof(struct sockaddr_in));
        !           285:        if (m == NULL) {
        !           286:                dPrintf(D_M_AURP, D_L_ERROR,
        !           287:                        ("aurp_bindrp: couldn't alloc mbuf"));
        !           288:                return (ENOBUFS);
        !           289:        }
        !           290: 
        !           291:        sin = (struct sockaddr_in *)gbuf_rptr(m);
        !           292:        sin->sin_family = AF_INET;
        !           293:        sin->sin_addr.s_addr = htons(aurp_global.src_addr);
        !           294:        sin->sin_port = htons(aurp_global.udp_port);
        !           295:        gbuf_len(m) = sizeof(struct sockaddr_in);
        !           296: 
        !           297: #ifdef _AIX
        !           298:        SOCKET_LOCK(so);
        !           299: #else
        !           300:        sblock(&so->so_rcv, M_WAIT);
        !           301:        sblock(&so->so_snd, M_WAIT);
        !           302: #endif
        !           303:        so->so_state |= SS_PRIV;
        !           304:        error = (*so->so_proto->pr_usrreq)(so, PRU_BIND, 0, m, 0);
        !           305: #ifdef _AIX
        !           306:        SOCKET_UNLOCK(so);
        !           307: #else
        !           308:        sbunlock(&so->so_snd);
        !           309:        sbunlock(&so->so_rcv);
        !           310: #endif
        !           311: 
        !           312:        (void) gbuf_freeb(m);
        !           313:        return (error);
        !           314: }
        !           315: 
        !           316: /*
        !           317:  * receive from UDP
        !           318:  * fp is the 'source address' mbuf; p_mbuf is the data mbuf.
        !           319:  * Use the source address to find the 'node number' (index of the address),
        !           320:  *  and pass that to the next stage.
        !           321:  */
        !           322: int ip_to_atalk(register gbuf_t *fp, register gbuf_t *p_mbuf)
        !           323: {      register aurp_hdr_t *hdr;
        !           324:        register domain_t *domain;
        !           325:        unsigned char node;
        !           326:        register struct sockaddr_in *rem_addr;
        !           327: 
        !           328:        rem_addr = (struct sockaddr_in *)gbuf_rptr(fp);
        !           329:        /* determine the node where the packet came from */
        !           330:        for (node=1; node <= dst_addr_cnt; node++) {
        !           331:                if (aurp_global.dst_addr[node] == *(long *)&rem_addr->sin_addr)
        !           332:                        break;
        !           333:        }
        !           334:        if (node > dst_addr_cnt) {
        !           335:                dPrintf(D_M_AURP, D_L_WARNING,
        !           336:                        ("AURPrecv: invalid node, %d.%x\n",
        !           337:                        rem_addr->sin_port,
        !           338:                        *(long *)&rem_addr->sin_addr));
        !           339:                gbuf_freem(fp);
        !           340:                gbuf_freem(p_mbuf);
        !           341:                return -1;
        !           342:        }
        !           343: 
        !           344:        /* validate the domain */
        !           345:        domain = (domain_t *)gbuf_rptr(p_mbuf);
        !           346:        if ( (domain->dst_length != IP_LENGTH) ||
        !           347:            (domain->dst_authority != IP_AUTHORITY) ||
        !           348:            (domain->version != AUD_Version) ||
        !           349:            ((domain->type != AUD_Atalk) && (domain->type != AUD_AURP)) ) {
        !           350:                dPrintf(D_M_AURP, D_L_WARNING,
        !           351:                        ("AURPrecv: invalid domain, %d.%x\n",
        !           352:                        rem_addr->sin_port,
        !           353:                        *(long *)&rem_addr->sin_addr));
        !           354:                gbuf_freem(fp);
        !           355:                gbuf_freem(p_mbuf);
        !           356:                return -1;
        !           357:        }
        !           358: 
        !           359:        /* Remove domain header */
        !           360:      p_mbuf->m_pkthdr.len -= IP_DOMAINSIZE;
        !           361:        gbuf_rinc(p_mbuf,IP_DOMAINSIZE);
        !           362:        gbuf_set_type(p_mbuf, MSG_DATA);
        !           363: 
        !           364:        /* forward the packet to the local AppleTalk stack */
        !           365:        gbuf_freem(fp);
        !           366:        at_insert(p_mbuf, domain->type, node);
        !           367:        return 0;
        !           368: }
        !           369: 
        !           370: /*
        !           371:  * send to UDP
        !           372:  * The real work has been done already.         Here, we just cobble together
        !           373:  *  a sockaddr for the destination and call sosend().
        !           374:  */
        !           375: void
        !           376: atalk_to_ip(register gbuf_t *m)
        !           377: {      register domain_t *domain;
        !           378:        int error;
        !           379: #ifdef _AIX
        !           380:        int flags = MSG_NONBLOCK;
        !           381: #else
        !           382:        int flags = MSG_DONTWAIT;
        !           383: #endif
        !           384:        struct sockaddr_in *rem_addr;
        !           385:        register gbuf_t *mbp;
        !           386: 
        !           387:        m->m_type = MT_HEADER;
        !           388:        m->m_pkthdr.len = gbuf_msgsize(m);
        !           389:        m->m_pkthdr.rcvif = 0;
        !           390: 
        !           391:        /* Cons up a destination sockaddr */
        !           392:        if ((mbp = (gbuf_t *)gbuf_alloc(sizeof(struct sockaddr_in))) == NULL)
        !           393:        {
        !           394: #ifdef _AIX
        !           395:                (void)fetch_and_add((atomic_p)&aurp_global.no_mbufs, 1);
        !           396: #endif
        !           397:                gbuf_freem(m);
        !           398:                return;
        !           399:        }
        !           400: 
        !           401:        rem_addr = (struct sockaddr_in *)gbuf_rptr(mbp);
        !           402:        bzero((char *)rem_addr, sizeof(rem_addr));
        !           403:        rem_addr->sin_family = PF_INET;
        !           404:        rem_addr->sin_port = aurp_global.udp_port;
        !           405:        gbuf_len(mbp) = sizeof (struct sockaddr_in);
        !           406:        domain = (domain_t *)gbuf_rptr(m);
        !           407:        *(long *)&rem_addr->sin_addr = domain->dst_address;
        !           408: 
        !           409: #ifdef _AIX
        !           410:        (void)fetch_and_add((atomic_p)&aurp_global.running, 1);
        !           411: #endif
        !           412:        if (aurp_global.shutdown) {
        !           413:                gbuf_freem(m);
        !           414:                gbuf_freeb(mbp);
        !           415: #ifdef _AIX
        !           416:                (void)fetch_and_add((atomic_p)&aurp_global.running, -1);
        !           417: #endif
        !           418:                return;
        !           419:        }
        !           420:        error = sosend(aurp_global.tunnel, mbp, NULL, m, NULL, flags);
        !           421:        if (error)
        !           422:        {       /*log error*/
        !           423:          dPrintf(D_M_AURP, D_L_ERROR, ("AURP: sosend error (%d)\n",
        !           424:                  error));
        !           425:        }
        !           426: 
        !           427:        gbuf_freeb(mbp);
        !           428: #ifdef _AIX    
        !           429:        (void)fetch_and_add((atomic_p)&aurp_global.running, -1);
        !           430: #endif
        !           431:        return;
        !           432: }
        !           433: 
        !           434: 

unix.superglobalmegacorp.com

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