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