|
|
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.