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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [rtems-20020807/] [cpukit/] [librpc/] [src/] [rpc/] [svc_unix.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

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