Annotation of 43BSDTahoe/new/sunrpc/svc_tcp.c, revision 1.1

1.1     ! root        1: /*
        !             2:  * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
        !             3:  * unrestricted use provided that this legend is included on all tape
        !             4:  * media and as a part of the software program in whole or part.  Users
        !             5:  * may copy or modify Sun RPC without charge, but are not authorized
        !             6:  * to license or distribute it to anyone else except as part of a product or
        !             7:  * program developed by the user.
        !             8:  * 
        !             9:  * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
        !            10:  * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
        !            11:  * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
        !            12:  * 
        !            13:  * Sun RPC is provided with no support and without any obligation on the
        !            14:  * part of Sun Microsystems, Inc. to assist in its use, correction,
        !            15:  * modification or enhancement.
        !            16:  * 
        !            17:  * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
        !            18:  * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
        !            19:  * OR ANY PART THEREOF.
        !            20:  * 
        !            21:  * In no event will Sun Microsystems, Inc. be liable for any lost revenue
        !            22:  * or profits or other special, indirect and consequential damages, even if
        !            23:  * Sun has been advised of the possibility of such damages.
        !            24:  * 
        !            25:  * Sun Microsystems, Inc.
        !            26:  * 2550 Garcia Avenue
        !            27:  * Mountain View, California  94043
        !            28:  */
        !            29: #ifndef lint
        !            30: static char sccsid[] = "@(#)svc_tcp.c 1.5 85/03/17 Copyr 1984 Sun Micro";
        !            31: #endif
        !            32: 
        !            33: /*
        !            34:  * svc_tcp.c, Server side for TCP/IP based RPC. 
        !            35:  *
        !            36:  * Copyright (C) 1984, Sun Microsystems, Inc.
        !            37:  *
        !            38:  * Actually implements two flavors of transporter -
        !            39:  * a tcp rendezvouser (a listner and connection establisher)
        !            40:  * and a record/tcp stream.
        !            41:  */
        !            42: 
        !            43: #include <stdio.h>
        !            44: #include "types.h"
        !            45: #include <netinet/in.h>
        !            46: #include <sys/socket.h>
        !            47: #include <sys/time.h>
        !            48: #include <errno.h>
        !            49: #include "xdr.h"
        !            50: #include "auth.h"
        !            51: #include "clnt.h"
        !            52: #include "rpc_msg.h"
        !            53: #include "svc.h"
        !            54: char *mem_alloc();
        !            55: extern bool_t abort();
        !            56: extern errno;
        !            57: 
        !            58: /*
        !            59:  * Ops vector for TCP/IP based rpc service handle
        !            60:  */
        !            61: static bool_t          svctcp_recv();
        !            62: static enum xprt_stat  svctcp_stat();
        !            63: static bool_t          svctcp_getargs();
        !            64: static bool_t          svctcp_reply();
        !            65: static bool_t          svctcp_freeargs();
        !            66: static void            svctcp_destroy();
        !            67: 
        !            68: static struct xp_ops svctcp_op = {
        !            69:        svctcp_recv,
        !            70:        svctcp_stat,
        !            71:        svctcp_getargs,
        !            72:        svctcp_reply,
        !            73:        svctcp_freeargs,
        !            74:        svctcp_destroy
        !            75: };
        !            76: 
        !            77: /*
        !            78:  * Ops vector for TCP/IP rendezvous handler
        !            79:  */
        !            80: static bool_t          rendezvous_request();
        !            81: static enum xprt_stat  rendezvous_stat();
        !            82: 
        !            83: static struct xp_ops svctcp_rendezvous_op = {
        !            84:        rendezvous_request,
        !            85:        rendezvous_stat,
        !            86:        abort,
        !            87:        abort,
        !            88:        abort,
        !            89:        svctcp_destroy
        !            90: };
        !            91: 
        !            92: static int readtcp(), writetcp();
        !            93: 
        !            94: struct tcp_rendezvous { /* kept in xprt->xp_p1 */
        !            95:        u_int sendsize;
        !            96:        u_int recvsize;
        !            97: };
        !            98: 
        !            99: struct tcp_conn {  /* kept in xprt->xp_p1 */
        !           100:        enum xprt_stat strm_stat;
        !           101:        u_long x_id;
        !           102:        XDR xdrs;
        !           103:        char verf_body[MAX_AUTH_BYTES];
        !           104: };
        !           105: 
        !           106: /*
        !           107:  * Usage:
        !           108:  *     xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
        !           109:  *
        !           110:  * Creates, registers, and returns a (rpc) tcp based transporter.
        !           111:  * Once *xprt is initialized, it is registered as a transporter
        !           112:  * see (svc.h, xprt_register).  This routine returns
        !           113:  * a NULL if a problem occurred.
        !           114:  *
        !           115:  * If sock<0 then a socket is created, else sock is used.
        !           116:  * If the socket, sock is not bound to a port then svctcp_create
        !           117:  * binds it to an arbitrary port.  The routine then starts a tcp
        !           118:  * listener on the socket's associated port.  In any (successful) case,
        !           119:  * xprt->xp_sock is the registered socket number and xprt->xp_port is the
        !           120:  * associated port number.
        !           121:  *
        !           122:  * Since tcp streams do buffered io similar to stdio, the caller can specify
        !           123:  * how big the send and receive buffers are via the second and third parms;
        !           124:  * 0 => use the system default.
        !           125:  */
        !           126: SVCXPRT *
        !           127: svctcp_create(sock, sendsize, recvsize)
        !           128:        register int sock;
        !           129:        u_int sendsize;
        !           130:        u_int recvsize;
        !           131: {
        !           132:        bool_t madesock = FALSE;
        !           133:        register SVCXPRT *xprt;
        !           134:        register struct tcp_rendezvous *r;
        !           135:        struct sockaddr_in addr;
        !           136:        int len = sizeof(struct sockaddr_in);
        !           137: 
        !           138:        if (sock == RPC_ANYSOCK) {
        !           139:                if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
        !           140:                        perror("svctcp_.c - udp socket creation problem");
        !           141:                        return ((SVCXPRT *)NULL);
        !           142:                }
        !           143:                madesock = TRUE;
        !           144:        }
        !           145:        addr.sin_addr.s_addr = 0;
        !           146:        addr.sin_family = AF_INET;
        !           147:        addr.sin_port = 0;
        !           148:        (void)bind(sock, (struct sockaddr *)&addr, len);
        !           149:        if ((getsockname(sock, (caddr_t)&addr, &len) != 0)  ||
        !           150:            (listen(sock, 2) != 0)) {
        !           151:                perror("svctcp_.c - cannot getsockname or listen");
        !           152:                if (madesock)
        !           153:                       (void)close(sock);
        !           154:                return ((SVCXPRT *)NULL);
        !           155:        }
        !           156:        r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
        !           157:        if (r == NULL) {
        !           158:                fprintf(stderr, "svctcp_create: out of memory\n");
        !           159:                return (NULL);
        !           160:        }
        !           161:        r->sendsize = sendsize;
        !           162:        r->recvsize = recvsize;
        !           163:        xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
        !           164:        if (xprt == NULL) {
        !           165:                fprintf(stderr, "svctcp_create: out of memory\n");
        !           166:                return (NULL);
        !           167:        }
        !           168:        xprt->xp_p2 = NULL;
        !           169:        xprt->xp_p1 = (caddr_t)r;
        !           170:        xprt->xp_verf = _null_auth;
        !           171:        xprt->xp_ops = &svctcp_rendezvous_op;
        !           172:        xprt->xp_port = ntohs(addr.sin_port);
        !           173:        xprt->xp_sock = sock;
        !           174:        xprt_register(xprt);
        !           175:        return (xprt);
        !           176: }
        !           177: 
        !           178: static bool_t
        !           179: rendezvous_request(xprt)
        !           180:        register SVCXPRT *xprt;
        !           181: {
        !           182:        register int sock;
        !           183:        register struct tcp_rendezvous *r;
        !           184:        register struct tcp_conn *cd;
        !           185:        struct sockaddr_in addr;
        !           186:        int len;
        !           187: 
        !           188:        r = (struct tcp_rendezvous *)xprt->xp_p1;
        !           189:     again:
        !           190:        len = sizeof(struct sockaddr_in);
        !           191:        if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
        !           192:            &len)) < 0) {
        !           193:                if (errno == EINTR)
        !           194:                        goto again;
        !           195:               return (FALSE);
        !           196:        }
        !           197:        /*
        !           198:         * make a new transporter (re-uses xprt)
        !           199:         */
        !           200:        xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
        !           201:        if (xprt == NULL) {
        !           202:                fprintf(stderr, "rendezvous_request: out of memory\n");
        !           203:                return (FALSE);
        !           204:        }
        !           205:        cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
        !           206:        if (cd == NULL) {
        !           207:                fprintf(stderr, "rendezvous_request: out of memory\n");
        !           208:                return (FALSE);
        !           209:        }
        !           210:        cd->strm_stat = XPRT_IDLE;
        !           211:        xdrrec_create(&(cd->xdrs), r->sendsize, r->recvsize,
        !           212:            (caddr_t)xprt, readtcp, writetcp);
        !           213:        xprt->xp_p2 = NULL;
        !           214:        xprt->xp_p1 = (caddr_t)cd;
        !           215:        xprt->xp_verf.oa_base = cd->verf_body;
        !           216:        xprt->xp_raddr = addr;
        !           217:        xprt->xp_addrlen = len;
        !           218:        xprt->xp_ops = &svctcp_op;  /* truely deals with calls */
        !           219:        xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
        !           220:        xprt->xp_sock = sock;
        !           221:        xprt_register(xprt);
        !           222:        return (FALSE); /* there is never an rpc msg to be processed */
        !           223: }
        !           224: 
        !           225: static enum xprt_stat
        !           226: rendezvous_stat()
        !           227: {
        !           228: 
        !           229:        return (XPRT_IDLE);
        !           230: }
        !           231: 
        !           232: static void
        !           233: svctcp_destroy(xprt)
        !           234:        register SVCXPRT *xprt;
        !           235: {
        !           236:        register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
        !           237: 
        !           238:        xprt_unregister(xprt);
        !           239:        (void)close(xprt->xp_sock);
        !           240:        if (xprt->xp_port != 0) {
        !           241:                /* a rendezvouser socket */
        !           242:                xprt->xp_port = 0;
        !           243:        } else {
        !           244:                /* an actual connection socket */
        !           245:                XDR_DESTROY(&(cd->xdrs));
        !           246:        }
        !           247:        mem_free((caddr_t)cd, sizeof(struct tcp_conn));
        !           248:        mem_free((caddr_t)xprt, sizeof(SVCXPRT));
        !           249: }
        !           250: 
        !           251: /*
        !           252:  * All read operations timeout after 35 seconds.
        !           253:  * A timeout is fatal for the connection.
        !           254:  */
        !           255: static struct timeval wait_per_try = { 35, 0 };
        !           256: 
        !           257: /*
        !           258:  * reads data from the tcp conection.
        !           259:  * any error is fatal and the connection is closed.
        !           260:  * (And a read of zero bytes is a half closed stream => error.)
        !           261:  */
        !           262: static int
        !           263: readtcp(xprt, buf, len)
        !           264:        register SVCXPRT *xprt;
        !           265:        caddr_t buf;
        !           266:        register int len;
        !           267: {
        !           268:        register int sock = xprt->xp_sock;
        !           269:        register int mask = 1 << sock;
        !           270:        int readfds;
        !           271: 
        !           272:        do {
        !           273:                readfds = mask;
        !           274:                if (select(32, &readfds, NULL, NULL, &wait_per_try) <= 0) {
        !           275:                        if (errno == EINTR)
        !           276:                                continue;
        !           277:                        goto fatal_err;
        !           278:                }
        !           279:        } while (readfds != mask);
        !           280:        if ((len = read(sock, buf, len)) > 0)
        !           281:                return (len);
        !           282: fatal_err:
        !           283:        ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
        !           284:        return (-1);
        !           285: }
        !           286: 
        !           287: /*
        !           288:  * writes data to the tcp connection.
        !           289:  * Any error is fatal and the connection is closed.
        !           290:  */
        !           291: static int
        !           292: writetcp(xprt, buf, len)
        !           293:        register SVCXPRT *xprt;
        !           294:        caddr_t buf;
        !           295:        int len;
        !           296: {
        !           297:        register int i, cnt;
        !           298: 
        !           299:        for (cnt = len; cnt > 0; cnt -= i, buf += i) {
        !           300:                if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
        !           301:                        ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
        !           302:                            XPRT_DIED;
        !           303:                        return (-1);
        !           304:                }
        !           305:        }
        !           306:        return (len);
        !           307: }
        !           308: 
        !           309: static enum xprt_stat
        !           310: svctcp_stat(xprt)
        !           311:        SVCXPRT *xprt;
        !           312: {
        !           313:        register struct tcp_conn *cd =
        !           314:            (struct tcp_conn *)(xprt->xp_p1);
        !           315: 
        !           316:        if (cd->strm_stat == XPRT_DIED)
        !           317:                return (XPRT_DIED);
        !           318:        if (! xdrrec_eof(&(cd->xdrs)))
        !           319:                return (XPRT_MOREREQS);
        !           320:        return (XPRT_IDLE);
        !           321: }
        !           322: 
        !           323: static bool_t
        !           324: svctcp_recv(xprt, msg)
        !           325:        SVCXPRT *xprt;
        !           326:        register struct rpc_msg *msg;
        !           327: {
        !           328:        register struct tcp_conn *cd =
        !           329:            (struct tcp_conn *)(xprt->xp_p1);
        !           330:        register XDR *xdrs = &(cd->xdrs);
        !           331: 
        !           332:        xdrs->x_op = XDR_DECODE;
        !           333:        (void)xdrrec_skiprecord(xdrs);
        !           334:        if (xdr_callmsg(xdrs, msg)) {
        !           335:                cd->x_id = msg->rm_xid;
        !           336:                return (TRUE);
        !           337:        }
        !           338:        return (FALSE);
        !           339: }
        !           340: 
        !           341: static bool_t
        !           342: svctcp_getargs(xprt, xdr_args, args_ptr)
        !           343:        SVCXPRT *xprt;
        !           344:        xdrproc_t xdr_args;
        !           345:        caddr_t args_ptr;
        !           346: {
        !           347: 
        !           348:        return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
        !           349: }
        !           350: 
        !           351: static bool_t
        !           352: svctcp_freeargs(xprt, xdr_args, args_ptr)
        !           353:        SVCXPRT *xprt;
        !           354:        xdrproc_t xdr_args;
        !           355:        caddr_t args_ptr;
        !           356: {
        !           357:        register XDR *xdrs =
        !           358:            &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
        !           359: 
        !           360:        xdrs->x_op = XDR_FREE;
        !           361:        return ((*xdr_args)(xdrs, args_ptr));
        !           362: }
        !           363: 
        !           364: static bool_t
        !           365: svctcp_reply(xprt, msg)
        !           366:        SVCXPRT *xprt;
        !           367:        register struct rpc_msg *msg;
        !           368: {
        !           369:        register struct tcp_conn *cd =
        !           370:            (struct tcp_conn *)(xprt->xp_p1);
        !           371:        register XDR *xdrs = &(cd->xdrs);
        !           372:        register bool_t stat;
        !           373: 
        !           374:        xdrs->x_op = XDR_ENCODE;
        !           375:        msg->rm_xid = cd->x_id;
        !           376:        stat = xdr_replymsg(xdrs, msg);
        !           377:        (void)xdrrec_endofrecord(xdrs, TRUE);
        !           378:        return (stat);
        !           379: }

unix.superglobalmegacorp.com

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