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