|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.