OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems/] [c/] [src/] [librpc/] [src/] [rpc/] [svc_tcp.c] - Blame information for rev 1771

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 158 chris
/*
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
 
30
#if defined(LIBC_SCCS) && !defined(lint)
31
/*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
32
/*static char *sccsid = "from: @(#)svc_tcp.c    2.2 88/08/01 4.0 RPCSRC";*/
33
static char *rcsid = "$FreeBSD: src/lib/libc/rpc/svc_tcp.c,v 1.18 2000/01/27 23:06:41 jasone Exp $";
34
#endif
35
 
36
/*
37
 * svc_tcp.c, Server side for TCP/IP based RPC.
38
 *
39
 * Copyright (C) 1984, Sun Microsystems, Inc.
40
 *
41
 * Actually implements two flavors of transporter -
42
 * a tcp rendezvouser (a listner and connection establisher)
43
 * and a record/tcp stream.
44
 */
45
 
46
#include <stdio.h>
47
#include <stdlib.h>
48
#include <unistd.h>
49
#include <string.h>
50
#include <rpc/rpc.h>
51
#include <sys/socket.h>
52
#include <sys/ioctl.h>
53
#include <errno.h>
54
 
55
/*
56
 * Ops vector for TCP/IP based rpc service handle
57
 */
58
static bool_t           svctcp_recv();
59
static enum xprt_stat   svctcp_stat();
60
static bool_t           svctcp_getargs();
61
static bool_t           svctcp_reply();
62
static bool_t           svctcp_freeargs();
63
static void             svctcp_destroy();
64
 
65
static struct xp_ops svctcp_op = {
66
        svctcp_recv,
67
        svctcp_stat,
68
        svctcp_getargs,
69
        svctcp_reply,
70
        svctcp_freeargs,
71
        svctcp_destroy
72
};
73
 
74
/*
75
 * Ops vector for TCP/IP rendezvous handler
76
 */
77
static bool_t           rendezvous_request();
78
static enum xprt_stat   rendezvous_stat();
79
 
80
static struct xp_ops svctcp_rendezvous_op = {
81
        rendezvous_request,
82
        rendezvous_stat,
83
        (bool_t (*)())abort,
84
        (bool_t (*)())abort,
85
        (bool_t (*)())abort,
86
        svctcp_destroy
87
};
88
 
89
static int readtcp(), writetcp();
90
static SVCXPRT *makefd_xprt();
91
 
92
struct tcp_rendezvous { /* kept in xprt->xp_p1 */
93
        u_int sendsize;
94
        u_int recvsize;
95
};
96
 
97
struct tcp_conn {  /* kept in xprt->xp_p1 */
98
        enum xprt_stat strm_stat;
99
        u_long x_id;
100
        XDR xdrs;
101
        char verf_body[MAX_AUTH_BYTES];
102
};
103
 
104
/*
105
 * Usage:
106
 *      xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
107
 *
108
 * Creates, registers, and returns a (rpc) tcp based transporter.
109
 * Once *xprt is initialized, it is registered as a transporter
110
 * see (svc.h, xprt_register).  This routine returns
111
 * a NULL if a problem occurred.
112
 *
113
 * If sock<0 then a socket is created, else sock is used.
114
 * If the socket, sock is not bound to a port then svctcp_create
115
 * binds it to an arbitrary port.  The routine then starts a tcp
116
 * listener on the socket's associated port.  In any (successful) case,
117
 * xprt->xp_sock is the registered socket number and xprt->xp_port is the
118
 * associated port number.
119
 *
120
 * Since tcp streams do buffered io similar to stdio, the caller can specify
121
 * how big the send and receive buffers are via the second and third parms;
122
 * 0 => use the system default.
123
 */
124
SVCXPRT *
125
svctcp_create(sock, sendsize, recvsize)
126
        register int sock;
127
        u_int sendsize;
128
        u_int recvsize;
129
{
130
        bool_t madesock = FALSE;
131
        register SVCXPRT *xprt;
132
        register struct tcp_rendezvous *r;
133
        struct sockaddr_in addr;
134
        int len = sizeof(struct sockaddr_in);
135
        int on;
136
 
137
        if (sock == RPC_ANYSOCK) {
138
                if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
139
                        perror("svctcp_.c - udp socket creation problem");
140
                        return ((SVCXPRT *)NULL);
141
                }
142
                madesock = TRUE;
143
        }
144
        on = 1;
145
        if (ioctl(sock, FIONBIO, &on) < 0) {
146
                perror("svc_tcp.c - cannot turn on non-blocking mode");
147
                if (madesock)
148
                       (void)_close(sock);
149
                return ((SVCXPRT *)NULL);
150
        }
151
        memset(&addr, 0, sizeof (addr));
152
        addr.sin_len = sizeof(struct sockaddr_in);
153
        addr.sin_family = AF_INET;
154
        if (bindresvport(sock, &addr)) {
155
                addr.sin_port = 0;
156
                (void)bind(sock, (struct sockaddr *)&addr, len);
157
        }
158
        if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0)  ||
159
            (listen(sock, 2) != 0)) {
160
                perror("svctcp_.c - cannot getsockname or listen");
161
                if (madesock)
162
                       (void)_close(sock);
163
                return ((SVCXPRT *)NULL);
164
        }
165
        r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
166
        if (r == NULL) {
167
                (void) fprintf(stderr, "svctcp_create: out of memory\n");
168
                return (NULL);
169
        }
170
        r->sendsize = sendsize;
171
        r->recvsize = recvsize;
172
        xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
173
        if (xprt == NULL) {
174
                (void) fprintf(stderr, "svctcp_create: out of memory\n");
175
                return (NULL);
176
        }
177
        xprt->xp_p2 = NULL;
178
        xprt->xp_p1 = (caddr_t)r;
179
        xprt->xp_verf = _null_auth;
180
        xprt->xp_ops = &svctcp_rendezvous_op;
181
        xprt->xp_port = ntohs(addr.sin_port);
182
        xprt->xp_sock = sock;
183
        xprt_register(xprt);
184
        return (xprt);
185
}
186
 
187
/*
188
 * Like svtcp_create(), except the routine takes any *open* UNIX file
189
 * descriptor as its first input.
190
 */
191
SVCXPRT *
192
svcfd_create(fd, sendsize, recvsize)
193
        int fd;
194
        u_int sendsize;
195
        u_int recvsize;
196
{
197
 
198
        return (makefd_xprt(fd, sendsize, recvsize));
199
}
200
 
201
static SVCXPRT *
202
makefd_xprt(fd, sendsize, recvsize)
203
        int fd;
204
        u_int sendsize;
205
        u_int recvsize;
206
{
207
        register SVCXPRT *xprt;
208
        register struct tcp_conn *cd;
209
 
210
        xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
211
        if (xprt == (SVCXPRT *)NULL) {
212
                (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
213
                goto done;
214
        }
215
        cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
216
        if (cd == (struct tcp_conn *)NULL) {
217
                (void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
218
                mem_free((char *) xprt, sizeof(SVCXPRT));
219
                xprt = (SVCXPRT *)NULL;
220
                goto done;
221
        }
222
        cd->strm_stat = XPRT_IDLE;
223
        xdrrec_create(&(cd->xdrs), sendsize, recvsize,
224
            (caddr_t)xprt, readtcp, writetcp);
225
        xprt->xp_p2 = NULL;
226
        xprt->xp_p1 = (caddr_t)cd;
227
        xprt->xp_verf.oa_base = cd->verf_body;
228
        xprt->xp_addrlen = 0;
229
        xprt->xp_ops = &svctcp_op;  /* truely deals with calls */
230
        xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */
231
        xprt->xp_sock = fd;
232
        xprt_register(xprt);
233
    done:
234
        return (xprt);
235
}
236
 
237
static bool_t
238
rendezvous_request(xprt)
239
        register SVCXPRT *xprt;
240
{
241
        int sock;
242
        struct tcp_rendezvous *r;
243
        struct sockaddr_in addr;
244
        int len;
245
        int off;
246
 
247
        r = (struct tcp_rendezvous *)xprt->xp_p1;
248
    again:
249
        len = sizeof(struct sockaddr_in);
250
        if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
251
            &len)) < 0) {
252
                if (errno == EINTR)
253
                        goto again;
254
               return (FALSE);
255
        }
256
        /*
257
         * Guard against FTP bounce attacks.
258
         */
259
        if (addr.sin_port == htons(20)) {
260
                _close(sock);
261
                return (FALSE);
262
        }
263
        /*
264
         * The listening socket is in FIONBIO mode and we inherit it.
265
         */
266
        off = 0;
267
        if (ioctl(sock, FIONBIO, &off) < 0) {
268
                _close(sock);
269
                return (FALSE);
270
        }
271
        /*
272
         * make a new transporter (re-uses xprt)
273
         */
274
        xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
275
        xprt->xp_raddr = addr;
276
        xprt->xp_addrlen = len;
277
        return (FALSE); /* there is never an rpc msg to be processed */
278
}
279
 
280
static enum xprt_stat
281
rendezvous_stat()
282
{
283
 
284
        return (XPRT_IDLE);
285
}
286
 
287
static void
288
svctcp_destroy(xprt)
289
        register SVCXPRT *xprt;
290
{
291
        register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
292
 
293
        xprt_unregister(xprt);
294
        (void)_close(xprt->xp_sock);
295
        if (xprt->xp_port != 0) {
296
                /* a rendezvouser socket */
297
                xprt->xp_port = 0;
298
        } else {
299
                /* an actual connection socket */
300
                XDR_DESTROY(&(cd->xdrs));
301
        }
302
        mem_free((caddr_t)cd, sizeof(struct tcp_conn));
303
        mem_free((caddr_t)xprt, sizeof(SVCXPRT));
304
}
305
 
306
/*
307
 * All read operations timeout after 35 seconds.
308
 * A timeout is fatal for the connection.
309
 */
310
static struct timeval wait_per_try = { 35, 0 };
311
 
312
/*
313
 * reads data from the tcp conection.
314
 * any error is fatal and the connection is closed.
315
 * (And a read of zero bytes is a half closed stream => error.)
316
 *
317
 * Note: we have to be careful here not to allow ourselves to become
318
 * blocked too long in this routine. While we're waiting for data from one
319
 * client, another client may be trying to connect. To avoid this situation,
320
 * some code from svc_run() is transplanted here: the select() loop checks
321
 * all RPC descriptors including the one we want and calls svc_getreqset2()
322
 * to handle new requests if any are detected.
323
 */
324
static int
325
readtcp(xprt, buf, len)
326
        register SVCXPRT *xprt;
327
        caddr_t buf;
328
        register int len;
329
{
330
        register int sock = xprt->xp_sock;
331
        struct timeval start, delta, tv;
332
        struct timeval tmp1, tmp2;
333
        fd_set *fds;
334
 
335
        delta = wait_per_try;
336
        fds = NULL;
337
        gettimeofday(&start, NULL);
338
        do {
339
                int bytes = sizeof (fd_set);
340
                if (fds != NULL)
341
                        free(fds);
342
                fds = (fd_set *)malloc(bytes);
343
                if (fds == NULL)
344
                        goto fatal_err;
345
                memcpy(fds, __svc_fdset, bytes);
346
 
347
                /* XXX we know the other bits are still clear */
348
                FD_SET(sock, fds);
349
                tv = delta;     /* in case select() implements writeback */
350
                switch (select(svc_maxfd + 1, fds, NULL, NULL, &tv)) {
351
                case -1:
352
                        if (errno != EINTR)
353
                                goto fatal_err;
354
                        gettimeofday(&tmp1, NULL);
355
                        timersub(&tmp1, &start, &tmp2);
356
                        timersub(&wait_per_try, &tmp2, &tmp1);
357
                        if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
358
                                goto fatal_err;
359
                        delta = tmp1;
360
                        continue;
361
                case 0:
362
                        goto fatal_err;
363
                default:
364
                        if (!FD_ISSET(sock, fds)) {
365
                                svc_getreqset2(fds, svc_maxfd + 1);
366
                                gettimeofday(&tmp1, NULL);
367
                                timersub(&tmp1, &start, &tmp2);
368
                                timersub(&wait_per_try, &tmp2, &tmp1);
369
                                if (tmp1.tv_sec < 0 || !timerisset(&tmp1))
370
                                        goto fatal_err;
371
                                delta = tmp1;
372
                                continue;
373
                        }
374
                }
375
        } while (!FD_ISSET(sock, fds));
376
        if ((len = _read(sock, buf, len)) > 0) {
377
                if (fds != NULL)
378
                        free(fds);
379
                return (len);
380
        }
381
fatal_err:
382
        ((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
383
        if (fds != NULL)
384
                free(fds);
385
        return (-1);
386
}
387
 
388
/*
389
 * writes data to the tcp connection.
390
 * Any error is fatal and the connection is closed.
391
 */
392
static int
393
writetcp(xprt, buf, len)
394
        register SVCXPRT *xprt;
395
        caddr_t buf;
396
        int len;
397
{
398
        register int i, cnt;
399
 
400
        for (cnt = len; cnt > 0; cnt -= i, buf += i) {
401
                if ((i = _write(xprt->xp_sock, buf, cnt)) < 0) {
402
                        ((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
403
                            XPRT_DIED;
404
                        return (-1);
405
                }
406
        }
407
        return (len);
408
}
409
 
410
static enum xprt_stat
411
svctcp_stat(xprt)
412
        SVCXPRT *xprt;
413
{
414
        register struct tcp_conn *cd =
415
            (struct tcp_conn *)(xprt->xp_p1);
416
 
417
        if (cd->strm_stat == XPRT_DIED)
418
                return (XPRT_DIED);
419
        if (! xdrrec_eof(&(cd->xdrs)))
420
                return (XPRT_MOREREQS);
421
        return (XPRT_IDLE);
422
}
423
 
424
static bool_t
425
svctcp_recv(xprt, msg)
426
        SVCXPRT *xprt;
427
        register struct rpc_msg *msg;
428
{
429
        register struct tcp_conn *cd =
430
            (struct tcp_conn *)(xprt->xp_p1);
431
        register XDR *xdrs = &(cd->xdrs);
432
 
433
        xdrs->x_op = XDR_DECODE;
434
        (void)xdrrec_skiprecord(xdrs);
435
        if (xdr_callmsg(xdrs, msg)) {
436
                cd->x_id = msg->rm_xid;
437
                return (TRUE);
438
        }
439
        cd->strm_stat = XPRT_DIED;      /* XXXX */
440
        return (FALSE);
441
}
442
 
443
static bool_t
444
svctcp_getargs(xprt, xdr_args, args_ptr)
445
        SVCXPRT *xprt;
446
        xdrproc_t xdr_args;
447
        caddr_t args_ptr;
448
{
449
 
450
        return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
451
}
452
 
453
static bool_t
454
svctcp_freeargs(xprt, xdr_args, args_ptr)
455
        SVCXPRT *xprt;
456
        xdrproc_t xdr_args;
457
        caddr_t args_ptr;
458
{
459
        register XDR *xdrs =
460
            &(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
461
 
462
        xdrs->x_op = XDR_FREE;
463
        return ((*xdr_args)(xdrs, args_ptr));
464
}
465
 
466
static bool_t
467
svctcp_reply(xprt, msg)
468
        SVCXPRT *xprt;
469
        register struct rpc_msg *msg;
470
{
471
        register struct tcp_conn *cd =
472
            (struct tcp_conn *)(xprt->xp_p1);
473
        register XDR *xdrs = &(cd->xdrs);
474
        register bool_t stat;
475
 
476
        xdrs->x_op = XDR_ENCODE;
477
        msg->rm_xid = cd->x_id;
478
        stat = xdr_replymsg(xdrs, msg);
479
        (void)xdrrec_endofrecord(xdrs, TRUE);
480
        return (stat);
481
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.