Annotation of 43BSDReno/lib/librpc/svc_tcp.c, revision 1.1.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.