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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [inet/] [rpc/] [svc_unix.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1325 phoenix
/*
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
/*
31
 * svc_unix.c, Server side for TCP/IP based RPC.
32
 *
33
 * Copyright (C) 1984, Sun Microsystems, Inc.
34
 *
35
 * Actually implements two flavors of transporter -
36
 * a unix rendezvouser (a listener and connection establisher)
37
 * and a record/unix stream.
38
 */
39
 
40
#define __FORCE_GLIBC
41
#include <features.h>
42
 
43
#include <stdio.h>
44
#include <unistd.h>
45
#include <string.h>
46
#include <rpc/rpc.h>
47
#include <rpc/svc.h>
48
#include <sys/socket.h>
49
#include <sys/uio.h>
50
#include <sys/poll.h>
51
#include <errno.h>
52
#include <stdlib.h>
53
 
54
#ifdef USE_IN_LIBIO
55
# include <wchar.h>
56
#endif
57
 
58
/*
59
 * Ops vector for AF_UNIX based rpc service handle
60
 */
61
static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *);
62
static enum xprt_stat svcunix_stat (SVCXPRT *);
63
static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t);
64
static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *);
65
static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t);
66
static void svcunix_destroy (SVCXPRT *);
67
 
68
static const struct xp_ops svcunix_op =
69
{
70
  svcunix_recv,
71
  svcunix_stat,
72
  svcunix_getargs,
73
  svcunix_reply,
74
  svcunix_freeargs,
75
  svcunix_destroy
76
};
77
 
78
/*
79
 * Ops vector for AF_UNIX rendezvous handler
80
 */
81
static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *);
82
static enum xprt_stat rendezvous_stat (SVCXPRT *);
83
static void svcunix_rendezvous_abort (void);
84
 
85
/* This function makes sure abort() relocation goes through PLT
86
   and thus can be lazy bound.  */
87
static void
88
svcunix_rendezvous_abort (void)
89
{
90
  abort ();
91
};
92
 
93
static const struct xp_ops svcunix_rendezvous_op =
94
{
95
  rendezvous_request,
96
  rendezvous_stat,
97
  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
98
  (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort,
99
  (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort,
100
  svcunix_destroy
101
};
102
 
103
static int readunix (char*, char *, int);
104
static int writeunix (char *, char *, int);
105
static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function;
106
 
107
struct unix_rendezvous {        /* kept in xprt->xp_p1 */
108
  u_int sendsize;
109
  u_int recvsize;
110
};
111
 
112
struct unix_conn {              /* kept in xprt->xp_p1 */
113
  enum xprt_stat strm_stat;
114
  u_long x_id;
115
  XDR xdrs;
116
  char verf_body[MAX_AUTH_BYTES];
117
};
118
 
119
/*
120
 * Usage:
121
 *      xprt = svcunix_create(sock, send_buf_size, recv_buf_size);
122
 *
123
 * Creates, registers, and returns a (rpc) unix based transporter.
124
 * Once *xprt is initialized, it is registered as a transporter
125
 * see (svc.h, xprt_register).  This routine returns
126
 * a NULL if a problem occurred.
127
 *
128
 * If sock<0 then a socket is created, else sock is used.
129
 * If the socket, sock is not bound to a port then svcunix_create
130
 * binds it to an arbitrary port.  The routine then starts a unix
131
 * listener on the socket's associated port.  In any (successful) case,
132
 * xprt->xp_sock is the registered socket number and xprt->xp_port is the
133
 * associated port number.
134
 *
135
 * Since unix streams do buffered io similar to stdio, the caller can specify
136
 * how big the send and receive buffers are via the second and third parms;
137
 * 0 => use the system default.
138
 */
139
SVCXPRT *
140
svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
141
{
142
  bool_t madesock = FALSE;
143
  SVCXPRT *xprt;
144
  struct unix_rendezvous *r;
145
  struct sockaddr_un addr;
146
  socklen_t len = sizeof (struct sockaddr_in);
147
 
148
  if (sock == RPC_ANYSOCK)
149
    {
150
      if ((sock = socket (AF_UNIX, SOCK_STREAM, 0)) < 0)
151
        {
152
          perror (_("svc_unix.c - AF_UNIX socket creation problem"));
153
          return (SVCXPRT *) NULL;
154
        }
155
      madesock = TRUE;
156
    }
157
  memset (&addr, '\0', sizeof (addr));
158
  addr.sun_family = AF_UNIX;
159
  len = strlen (path) + 1;
160
  memcpy (addr.sun_path, path, len);
161
  len += sizeof (addr.sun_family);
162
 
163
  bind (sock, (struct sockaddr *) &addr, len);
164
 
165
  if (getsockname (sock, (struct sockaddr *) &addr, &len) != 0
166
      || listen (sock, 2) != 0)
167
    {
168
      perror (_("svc_unix.c - cannot getsockname or listen"));
169
      if (madesock)
170
        close (sock);
171
      return (SVCXPRT *) NULL;
172
    }
173
 
174
  r = (struct unix_rendezvous *) mem_alloc (sizeof (*r));
175
  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
176
  if (r == NULL || xprt == NULL)
177
    {
178
#ifdef USE_IN_LIBIO
179
      if (_IO_fwide (stderr, 0) > 0)
180
        __fwprintf (stderr, L"%s", _("svcunix_create: out of memory\n"));
181
      else
182
#endif
183
        fputs (_("svcunix_create: out of memory\n"), stderr);
184
      mem_free (r, sizeof (*r));
185
      mem_free (xprt, sizeof (SVCXPRT));
186
      return NULL;
187
    }
188
  r->sendsize = sendsize;
189
  r->recvsize = recvsize;
190
  xprt->xp_p2 = NULL;
191
  xprt->xp_p1 = (caddr_t) r;
192
  xprt->xp_verf = _null_auth;
193
  xprt->xp_ops = &svcunix_rendezvous_op;
194
  xprt->xp_port = -1;
195
  xprt->xp_sock = sock;
196
  xprt_register (xprt);
197
  return xprt;
198
}
199
 
200
/*
201
 * Like svunix_create(), except the routine takes any *open* UNIX file
202
 * descriptor as its first input.
203
 */
204
SVCXPRT *
205
svcunixfd_create (int fd, u_int sendsize, u_int recvsize)
206
{
207
  return makefd_xprt (fd, sendsize, recvsize);
208
}
209
 
210
static SVCXPRT *
211
internal_function
212
makefd_xprt (int fd, u_int sendsize, u_int recvsize)
213
{
214
  SVCXPRT *xprt;
215
  struct unix_conn *cd;
216
 
217
  xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT));
218
  cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn));
219
  if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL)
220
    {
221
#ifdef USE_IN_LIBIO
222
      if (_IO_fwide (stderr, 0) > 0)
223
        (void) __fwprintf (stderr, L"%s",
224
                           _("svc_unix: makefd_xprt: out of memory\n"));
225
      else
226
#endif
227
        (void) fputs (_("svc_unix: makefd_xprt: out of memory\n"), stderr);
228
      mem_free (xprt, sizeof (SVCXPRT));
229
      mem_free (cd, sizeof (struct unix_conn));
230
      return NULL;
231
    }
232
  cd->strm_stat = XPRT_IDLE;
233
  xdrrec_create (&(cd->xdrs), sendsize, recvsize,
234
                 (caddr_t) xprt, readunix, writeunix);
235
  xprt->xp_p2 = NULL;
236
  xprt->xp_p1 = (caddr_t) cd;
237
  xprt->xp_verf.oa_base = cd->verf_body;
238
  xprt->xp_addrlen = 0;
239
  xprt->xp_ops = &svcunix_op;   /* truly deals with calls */
240
  xprt->xp_port = 0;             /* this is a connection, not a rendezvouser */
241
  xprt->xp_sock = fd;
242
  xprt_register (xprt);
243
  return xprt;
244
}
245
 
246
static bool_t
247
rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg)
248
{
249
  int sock;
250
  struct unix_rendezvous *r;
251
  struct sockaddr_un addr;
252
  struct sockaddr_in in_addr;
253
  socklen_t len;
254
 
255
  r = (struct unix_rendezvous *) xprt->xp_p1;
256
again:
257
  len = sizeof (struct sockaddr_un);
258
  if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0)
259
    {
260
      if (errno == EINTR)
261
        goto again;
262
      return FALSE;
263
    }
264
  /*
265
   * make a new transporter (re-uses xprt)
266
   */
267
  memset (&in_addr, '\0', sizeof (in_addr));
268
  in_addr.sin_family = AF_UNIX;
269
  xprt = makefd_xprt (sock, r->sendsize, r->recvsize);
270
  memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr));
271
  xprt->xp_addrlen = len;
272
  return FALSE;         /* there is never an rpc msg to be processed */
273
}
274
 
275
static enum xprt_stat
276
rendezvous_stat (SVCXPRT *xprt)
277
{
278
  return XPRT_IDLE;
279
}
280
 
281
static void
282
svcunix_destroy (SVCXPRT *xprt)
283
{
284
  struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1;
285
 
286
  xprt_unregister (xprt);
287
  close (xprt->xp_sock);
288
  if (xprt->xp_port != 0)
289
    {
290
      /* a rendezvouser socket */
291
      xprt->xp_port = 0;
292
    }
293
  else
294
    {
295
      /* an actual connection socket */
296
      XDR_DESTROY (&(cd->xdrs));
297
    }
298
  mem_free ((caddr_t) cd, sizeof (struct unix_conn));
299
  mem_free ((caddr_t) xprt, sizeof (SVCXPRT));
300
}
301
 
302
#ifdef SCM_CREDENTIALS
303
struct cmessage {
304
  struct cmsghdr cmsg;
305
  struct ucred cmcred;
306
  /* hack to make sure we have enough memory */
307
  char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))];
308
};
309
 
310
/* XXX This is not thread safe, but since the main functions in svc.c
311
   and the rpcgen generated *_svc functions for the daemon are also not
312
   thread safe and uses static global variables, it doesn't matter. */
313
static struct cmessage cm;
314
#endif
315
 
316
static int
317
__msgread (int sock, void *data, size_t cnt)
318
{
319
  struct iovec iov;
320
  struct msghdr msg;
321
  int len;
322
 
323
  iov.iov_base = data;
324
  iov.iov_len = cnt;
325
 
326
  msg.msg_iov = &iov;
327
  msg.msg_iovlen = 1;
328
  msg.msg_name = NULL;
329
  msg.msg_namelen = 0;
330
#ifdef SCM_CREDENTIALS
331
  msg.msg_control = (caddr_t) &cm;
332
  msg.msg_controllen = sizeof (struct cmessage);
333
#endif
334
  msg.msg_flags = 0;
335
 
336
#ifdef SO_PASSCRED
337
  {
338
    int on = 1;
339
    if (setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on)))
340
      return -1;
341
  }
342
#endif
343
 
344
 restart:
345
  len = recvmsg (sock, &msg, 0);
346
  if (len >= 0)
347
    {
348
      if (msg.msg_flags & MSG_CTRUNC || len == 0)
349
        return 0;
350
      else
351
        return len;
352
    }
353
  if (errno == EINTR)
354
    goto restart;
355
  return -1;
356
}
357
 
358
static int
359
__msgwrite (int sock, void *data, size_t cnt)
360
{
361
#ifndef SCM_CREDENTIALS
362
  /* We cannot implement this reliably.  */
363
  __set_errno (ENOSYS);
364
  return -1;
365
#else
366
  struct iovec iov;
367
  struct msghdr msg;
368
  struct cmsghdr *cmsg = &cm.cmsg;
369
  struct ucred cred;
370
  int len;
371
 
372
  /* XXX I'm not sure, if gete?id() is always correct, or if we should use
373
     get?id(). But since keyserv needs geteuid(), we have no other chance.
374
     It would be much better, if the kernel could pass both to the server. */
375
  cred.pid = getpid ();
376
  cred.uid = geteuid ();
377
  cred.gid = getegid ();
378
 
379
  memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred));
380
  cmsg->cmsg_level = SOL_SOCKET;
381
  cmsg->cmsg_type = SCM_CREDENTIALS;
382
  cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred);
383
 
384
  iov.iov_base = data;
385
  iov.iov_len = cnt;
386
 
387
  msg.msg_iov = &iov;
388
  msg.msg_iovlen = 1;
389
  msg.msg_name = NULL;
390
  msg.msg_namelen = 0;
391
  msg.msg_control = cmsg;
392
  msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len);
393
  msg.msg_flags = 0;
394
 
395
 restart:
396
  len = sendmsg (sock, &msg, 0);
397
  if (len >= 0)
398
    return len;
399
  if (errno == EINTR)
400
    goto restart;
401
  return -1;
402
 
403
#endif
404
}
405
 
406
/*
407
 * reads data from the unix connection.
408
 * any error is fatal and the connection is closed.
409
 * (And a read of zero bytes is a half closed stream => error.)
410
 */
411
static int
412
readunix (char *xprtptr, char *buf, int len)
413
{
414
  SVCXPRT *xprt = (SVCXPRT *) xprtptr;
415
  int sock = xprt->xp_sock;
416
  int milliseconds = 35 * 1000;
417
  struct pollfd pollfd;
418
 
419
  do
420
    {
421
      pollfd.fd = sock;
422
      pollfd.events = POLLIN;
423
      switch (poll (&pollfd, 1, milliseconds))
424
        {
425
        case -1:
426
          if (errno == EINTR)
427
            continue;
428
          /*FALLTHROUGH*/
429
        case 0:
430
          goto fatal_err;
431
        default:
432
          if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP)
433
              || (pollfd.revents & POLLNVAL))
434
            goto fatal_err;
435
          break;
436
        }
437
    }
438
  while ((pollfd.revents & POLLIN) == 0);
439
 
440
  if ((len = __msgread (sock, buf, len)) > 0)
441
    return len;
442
 
443
 fatal_err:
444
  ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
445
  return -1;
446
}
447
 
448
/*
449
 * writes data to the unix connection.
450
 * Any error is fatal and the connection is closed.
451
 */
452
static int
453
writeunix (char *xprtptr, char * buf, int len)
454
{
455
  SVCXPRT *xprt = (SVCXPRT *) xprtptr;
456
  int i, cnt;
457
 
458
  for (cnt = len; cnt > 0; cnt -= i, buf += i)
459
    {
460
      if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0)
461
        {
462
          ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED;
463
          return -1;
464
        }
465
    }
466
  return len;
467
}
468
 
469
static enum xprt_stat
470
svcunix_stat (SVCXPRT *xprt)
471
{
472
  struct unix_conn *cd =
473
  (struct unix_conn *) (xprt->xp_p1);
474
 
475
  if (cd->strm_stat == XPRT_DIED)
476
    return XPRT_DIED;
477
  if (!xdrrec_eof (&(cd->xdrs)))
478
    return XPRT_MOREREQS;
479
  return XPRT_IDLE;
480
}
481
 
482
static bool_t
483
svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg)
484
{
485
  struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
486
  XDR *xdrs = &(cd->xdrs);
487
 
488
  xdrs->x_op = XDR_DECODE;
489
  xdrrec_skiprecord (xdrs);
490
  if (xdr_callmsg (xdrs, msg))
491
    {
492
      cd->x_id = msg->rm_xid;
493
      /* set up verifiers */
494
#ifdef SCM_CREDENTIALS
495
      msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX;
496
      msg->rm_call.cb_verf.oa_base = (caddr_t) &cm;
497
      msg->rm_call.cb_verf.oa_length = sizeof (cm);
498
#endif
499
      return TRUE;
500
    }
501
  cd->strm_stat = XPRT_DIED;    /* XXXX */
502
  return FALSE;
503
}
504
 
505
static bool_t
506
svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
507
{
508
  return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs),
509
                      args_ptr);
510
}
511
 
512
static bool_t
513
svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr)
514
{
515
  XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs);
516
 
517
  xdrs->x_op = XDR_FREE;
518
  return (*xdr_args) (xdrs, args_ptr);
519
}
520
 
521
static bool_t
522
svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg)
523
{
524
  struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1);
525
  XDR *xdrs = &(cd->xdrs);
526
  bool_t stat;
527
 
528
  xdrs->x_op = XDR_ENCODE;
529
  msg->rm_xid = cd->x_id;
530
  stat = xdr_replymsg (xdrs, msg);
531
  (void) xdrrec_endofrecord (xdrs, TRUE);
532
  return stat;
533
}

powered by: WebSVN 2.1.0

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