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: }

Defined functions

readtcp defined in line 262; used 2 times
rendezvous_request defined in line 178; used 2 times
rendezvous_stat defined in line 225; used 2 times
svctcp_create defined in line 126; used 2 times
svctcp_destroy defined in line 232; used 3 times
svctcp_freeargs defined in line 351; used 2 times
svctcp_getargs defined in line 341; used 2 times
svctcp_recv defined in line 323; used 2 times
svctcp_reply defined in line 364; used 2 times
svctcp_stat defined in line 309; used 2 times
writetcp defined in line 291; used 2 times

Defined variables

sccsid defined in line 30; never used
svctcp_op defined in line 68; used 1 times
svctcp_rendezvous_op defined in line 83; used 1 times
wait_per_try defined in line 255; used 1 times

Defined struct's

tcp_conn defined in line 99; used 32 times
tcp_rendezvous defined in line 94; used 8 times
Last modified: 1985-04-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1531
Valid CSS Valid XHTML 1.0 Strict