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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [uClibc/] [libc/] [inet/] [rpc/] [svc.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
 * svc.c, Server-side remote procedure call interface.
31
 *
32
 * There are two sets of procedures here.  The xprt routines are
33
 * for handling transport handles.  The svc routines handle the
34
 * list of service routines.
35
 *
36
 * Copyright (C) 1984, Sun Microsystems, Inc.
37
 */
38
 
39
#define __FORCE_GLIBC
40
#define _GNU_SOURCE
41
#include <features.h>
42
 
43
#include <errno.h>
44
#include <unistd.h>
45
#include "rpc_private.h"
46
#include <rpc/svc.h>
47
#include <rpc/pmap_clnt.h>
48
#include <sys/poll.h>
49
 
50
#ifdef __UCLIBC_HAS_THREADS__
51
#define xports ((SVCXPRT **)RPC_THREAD_VARIABLE(svc_xports_s))
52
#else
53
static SVCXPRT **xports;
54
#endif
55
 
56
#define NULL_SVC ((struct svc_callout *)0)
57
#define RQCRED_SIZE     400     /* this size is excessive */
58
 
59
/* The services list
60
   Each entry represents a set of procedures (an rpc program).
61
   The dispatch routine takes request structs and runs the
62
   appropriate procedure. */
63
struct svc_callout {
64
  struct svc_callout *sc_next;
65
  rpcprog_t sc_prog;
66
  rpcvers_t sc_vers;
67
  void (*sc_dispatch) (struct svc_req *, SVCXPRT *);
68
};
69
#ifdef __UCLIBC_HAS_THREADS__
70
#define svc_head ((struct svc_callout *)RPC_THREAD_VARIABLE(svc_head_s))
71
#else
72
static struct svc_callout *svc_head;
73
#endif
74
 
75
/* ***************  SVCXPRT related stuff **************** */
76
 
77
/* Activate a transport handle. */
78
void
79
xprt_register (SVCXPRT *xprt)
80
{
81
  register int sock = xprt->xp_sock;
82
  register int i;
83
 
84
  if (xports == NULL)
85
    {
86
      xports = (SVCXPRT **) malloc (_rpc_dtablesize () * sizeof (SVCXPRT *));
87
      if (xports == NULL) /* Don´t add handle */
88
        return;
89
    }
90
 
91
  if (sock < _rpc_dtablesize ())
92
    {
93
      xports[sock] = xprt;
94
      if (sock < FD_SETSIZE)
95
        FD_SET (sock, &svc_fdset);
96
 
97
      /* Check if we have an empty slot */
98
      for (i = 0; i < svc_max_pollfd; ++i)
99
        if (svc_pollfd[i].fd == -1)
100
          {
101
            svc_pollfd[i].fd = sock;
102
            svc_pollfd[i].events = (POLLIN | POLLPRI |
103
                                    POLLRDNORM | POLLRDBAND);
104
            return;
105
          }
106
 
107
      ++svc_max_pollfd;
108
      svc_pollfd = realloc (svc_pollfd,
109
                            sizeof (struct pollfd) * svc_max_pollfd);
110
      if (svc_pollfd == NULL) /* Out of memory */
111
        return;
112
 
113
      svc_pollfd[svc_max_pollfd - 1].fd = sock;
114
      svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI |
115
                                               POLLRDNORM | POLLRDBAND);
116
    }
117
}
118
 
119
/* De-activate a transport handle. */
120
void
121
xprt_unregister (SVCXPRT *xprt)
122
{
123
  register int sock = xprt->xp_sock;
124
  register int i;
125
 
126
  if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt))
127
    {
128
      xports[sock] = (SVCXPRT *) 0;
129
 
130
      if (sock < FD_SETSIZE)
131
        FD_CLR (sock, &svc_fdset);
132
 
133
      for (i = 0; i < svc_max_pollfd; ++i)
134
        if (svc_pollfd[i].fd == sock)
135
          svc_pollfd[i].fd = -1;
136
    }
137
}
138
 
139
 
140
/* ********************** CALLOUT list related stuff ************* */
141
 
142
/* Search the callout list for a program number, return the callout
143
   struct. */
144
static struct svc_callout *
145
svc_find (rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev)
146
{
147
  register struct svc_callout *s, *p;
148
 
149
  p = NULL_SVC;
150
  for (s = svc_head; s != NULL_SVC; s = s->sc_next)
151
    {
152
      if ((s->sc_prog == prog) && (s->sc_vers == vers))
153
        goto done;
154
      p = s;
155
    }
156
done:
157
  *prev = p;
158
  return s;
159
}
160
 
161
/* Add a service program to the callout list.
162
   The dispatch routine will be called when a rpc request for this
163
   program number comes in. */
164
bool_t
165
svc_register (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers,
166
              void (*dispatch) (struct svc_req *, SVCXPRT *),
167
              rpcproc_t protocol)
168
{
169
  struct svc_callout *prev;
170
  register struct svc_callout *s;
171
 
172
  if ((s = svc_find (prog, vers, &prev)) != NULL_SVC)
173
    {
174
      if (s->sc_dispatch == dispatch)
175
        goto pmap_it;           /* he is registering another xptr */
176
      return FALSE;
177
    }
178
  s = (struct svc_callout *) mem_alloc (sizeof (struct svc_callout));
179
  if (s == (struct svc_callout *) 0)
180
    return FALSE;
181
 
182
  s->sc_prog = prog;
183
  s->sc_vers = vers;
184
  s->sc_dispatch = dispatch;
185
  s->sc_next = svc_head;
186
  svc_head = s;
187
 
188
pmap_it:
189
  /* now register the information with the local binder service */
190
  if (protocol)
191
    return pmap_set (prog, vers, protocol, xprt->xp_port);
192
 
193
  return TRUE;
194
}
195
 
196
/* Remove a service program from the callout list. */
197
void
198
svc_unregister (rpcprog_t prog, rpcvers_t vers)
199
{
200
  struct svc_callout *prev;
201
  register struct svc_callout *s;
202
 
203
  if ((s = svc_find (prog, vers, &prev)) == NULL_SVC)
204
    return;
205
 
206
  if (prev == NULL_SVC)
207
    svc_head = s->sc_next;
208
  else
209
    prev->sc_next = s->sc_next;
210
 
211
  s->sc_next = NULL_SVC;
212
  mem_free ((char *) s, (u_int) sizeof (struct svc_callout));
213
  /* now unregister the information with the local binder service */
214
  pmap_unset (prog, vers);
215
}
216
 
217
/* ******************* REPLY GENERATION ROUTINES  ************ */
218
 
219
/* Send a reply to an rpc request */
220
bool_t
221
svc_sendreply (register SVCXPRT *xprt, xdrproc_t xdr_results,
222
               caddr_t xdr_location)
223
{
224
  struct rpc_msg rply;
225
 
226
  rply.rm_direction = REPLY;
227
  rply.rm_reply.rp_stat = MSG_ACCEPTED;
228
  rply.acpted_rply.ar_verf = xprt->xp_verf;
229
  rply.acpted_rply.ar_stat = SUCCESS;
230
  rply.acpted_rply.ar_results.where = xdr_location;
231
  rply.acpted_rply.ar_results.proc = xdr_results;
232
  return SVC_REPLY (xprt, &rply);
233
}
234
 
235
/* No procedure error reply */
236
void
237
svcerr_noproc (register SVCXPRT *xprt)
238
{
239
  struct rpc_msg rply;
240
 
241
  rply.rm_direction = REPLY;
242
  rply.rm_reply.rp_stat = MSG_ACCEPTED;
243
  rply.acpted_rply.ar_verf = xprt->xp_verf;
244
  rply.acpted_rply.ar_stat = PROC_UNAVAIL;
245
  SVC_REPLY (xprt, &rply);
246
}
247
 
248
/* Can't decode args error reply */
249
void
250
svcerr_decode (register SVCXPRT *xprt)
251
{
252
  struct rpc_msg rply;
253
 
254
  rply.rm_direction = REPLY;
255
  rply.rm_reply.rp_stat = MSG_ACCEPTED;
256
  rply.acpted_rply.ar_verf = xprt->xp_verf;
257
  rply.acpted_rply.ar_stat = GARBAGE_ARGS;
258
  SVC_REPLY (xprt, &rply);
259
}
260
 
261
/* Some system error */
262
void
263
svcerr_systemerr (register SVCXPRT *xprt)
264
{
265
  struct rpc_msg rply;
266
 
267
  rply.rm_direction = REPLY;
268
  rply.rm_reply.rp_stat = MSG_ACCEPTED;
269
  rply.acpted_rply.ar_verf = xprt->xp_verf;
270
  rply.acpted_rply.ar_stat = SYSTEM_ERR;
271
  SVC_REPLY (xprt, &rply);
272
}
273
 
274
/* Authentication error reply */
275
void
276
svcerr_auth (SVCXPRT *xprt, enum auth_stat why)
277
{
278
  struct rpc_msg rply;
279
 
280
  rply.rm_direction = REPLY;
281
  rply.rm_reply.rp_stat = MSG_DENIED;
282
  rply.rjcted_rply.rj_stat = AUTH_ERROR;
283
  rply.rjcted_rply.rj_why = why;
284
  SVC_REPLY (xprt, &rply);
285
}
286
 
287
/* Auth too weak error reply */
288
void
289
svcerr_weakauth (SVCXPRT *xprt)
290
{
291
  svcerr_auth (xprt, AUTH_TOOWEAK);
292
}
293
 
294
/* Program unavailable error reply */
295
void
296
svcerr_noprog (register SVCXPRT *xprt)
297
{
298
  struct rpc_msg rply;
299
 
300
  rply.rm_direction = REPLY;
301
  rply.rm_reply.rp_stat = MSG_ACCEPTED;
302
  rply.acpted_rply.ar_verf = xprt->xp_verf;
303
  rply.acpted_rply.ar_stat = PROG_UNAVAIL;
304
  SVC_REPLY (xprt, &rply);
305
}
306
 
307
/* Program version mismatch error reply */
308
void
309
svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers,
310
                 rpcvers_t high_vers)
311
{
312
  struct rpc_msg rply;
313
 
314
  rply.rm_direction = REPLY;
315
  rply.rm_reply.rp_stat = MSG_ACCEPTED;
316
  rply.acpted_rply.ar_verf = xprt->xp_verf;
317
  rply.acpted_rply.ar_stat = PROG_MISMATCH;
318
  rply.acpted_rply.ar_vers.low = low_vers;
319
  rply.acpted_rply.ar_vers.high = high_vers;
320
  SVC_REPLY (xprt, &rply);
321
}
322
 
323
/* ******************* SERVER INPUT STUFF ******************* */
324
 
325
/*
326
 * Get server side input from some transport.
327
 *
328
 * Statement of authentication parameters management:
329
 * This function owns and manages all authentication parameters, specifically
330
 * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
331
 * the "cooked" credentials (rqst->rq_clntcred).
332
 * However, this function does not know the structure of the cooked
333
 * credentials, so it make the following assumptions:
334
 *   a) the structure is contiguous (no pointers), and
335
 *   b) the cred structure size does not exceed RQCRED_SIZE bytes.
336
 * In all events, all three parameters are freed upon exit from this routine.
337
 * The storage is trivially management on the call stack in user land, but
338
 * is mallocated in kernel land.
339
 */
340
 
341
void
342
svc_getreq (int rdfds)
343
{
344
  fd_set readfds;
345
 
346
  FD_ZERO (&readfds);
347
  readfds.fds_bits[0] = rdfds;
348
  svc_getreqset (&readfds);
349
}
350
 
351
void
352
svc_getreqset (fd_set *readfds)
353
{
354
  register u_int32_t mask;
355
  register u_int32_t *maskp;
356
  register int setsize;
357
  register int sock;
358
  register int bit;
359
 
360
  setsize = _rpc_dtablesize ();
361
  maskp = (u_int32_t *) readfds->fds_bits;
362
  for (sock = 0; sock < setsize; sock += 32)
363
    for (mask = *maskp++; (bit = ffs (mask)); mask ^= (1 << (bit - 1)))
364
      svc_getreq_common (sock + bit - 1);
365
}
366
 
367
void
368
svc_getreq_poll (struct pollfd *pfdp, int pollretval)
369
{
370
  register int i;
371
  register int fds_found;
372
 
373
  for (i = fds_found = 0; i < svc_max_pollfd && fds_found < pollretval; ++i)
374
    {
375
      register struct pollfd *p = &pfdp[i];
376
 
377
      if (p->fd != -1 && p->revents)
378
        {
379
          /* fd has input waiting */
380
          ++fds_found;
381
 
382
          if (p->revents & POLLNVAL)
383
            xprt_unregister (xports[p->fd]);
384
          else
385
            svc_getreq_common (p->fd);
386
        }
387
    }
388
}
389
 
390
 
391
void
392
svc_getreq_common (const int fd)
393
{
394
  enum xprt_stat stat;
395
  struct rpc_msg msg;
396
  register SVCXPRT *xprt;
397
  char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE];
398
  msg.rm_call.cb_cred.oa_base = cred_area;
399
  msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
400
 
401
  xprt = xports[fd];
402
  /* Do we control fd? */
403
  if (xprt == NULL)
404
     return;
405
 
406
  /* now receive msgs from xprtprt (support batch calls) */
407
  do
408
    {
409
      if (SVC_RECV (xprt, &msg))
410
        {
411
          /* now find the exported program and call it */
412
          struct svc_callout *s;
413
          struct svc_req r;
414
          enum auth_stat why;
415
          rpcvers_t low_vers;
416
          rpcvers_t high_vers;
417
          int prog_found;
418
 
419
          r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]);
420
          r.rq_xprt = xprt;
421
          r.rq_prog = msg.rm_call.cb_prog;
422
          r.rq_vers = msg.rm_call.cb_vers;
423
          r.rq_proc = msg.rm_call.cb_proc;
424
          r.rq_cred = msg.rm_call.cb_cred;
425
 
426
          /* first authenticate the message */
427
          /* Check for null flavor and bypass these calls if possible */
428
 
429
          if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL)
430
            {
431
              r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
432
              r.rq_xprt->xp_verf.oa_length = 0;
433
            }
434
          else if ((why = _authenticate (&r, &msg)) != AUTH_OK)
435
            {
436
              svcerr_auth (xprt, why);
437
              goto call_done;
438
            }
439
 
440
          /* now match message with a registered service */
441
          prog_found = FALSE;
442
          low_vers = 0 - 1;
443
          high_vers = 0;
444
 
445
          for (s = svc_head; s != NULL_SVC; s = s->sc_next)
446
            {
447
              if (s->sc_prog == r.rq_prog)
448
                {
449
                  if (s->sc_vers == r.rq_vers)
450
                    {
451
                      (*s->sc_dispatch) (&r, xprt);
452
                      goto call_done;
453
                    }
454
                  /* found correct version */
455
                  prog_found = TRUE;
456
                  if (s->sc_vers < low_vers)
457
                    low_vers = s->sc_vers;
458
                  if (s->sc_vers > high_vers)
459
                    high_vers = s->sc_vers;
460
                }
461
              /* found correct program */
462
            }
463
          /* if we got here, the program or version
464
             is not served ... */
465
          if (prog_found)
466
            svcerr_progvers (xprt, low_vers, high_vers);
467
          else
468
            svcerr_noprog (xprt);
469
          /* Fall through to ... */
470
        }
471
    call_done:
472
      if ((stat = SVC_STAT (xprt)) == XPRT_DIED)
473
        {
474
          SVC_DESTROY (xprt);
475
          break;
476
        }
477
    }
478
  while (stat == XPRT_MOREREQS);
479
}
480
 
481
#ifdef __UCLIBC_HAS_THREADS__
482
 
483
void
484
__rpc_thread_svc_cleanup (void)
485
{
486
  struct svc_callout *svcp;
487
 
488
  while ((svcp = svc_head) != NULL)
489
    svc_unregister (svcp->sc_prog, svcp->sc_vers);
490
}
491
 
492
#endif /* __UCLIBC_HAS_THREADS__ */

powered by: WebSVN 2.1.0

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