1 /*********************************************************************
2 * RPC for the Windows NT Operating System
3 * 1993 by Martin F. Gergeleit
4 * Users may use, copy or modify Sun RPC for the Windows NT Operating
5 * System according to the Sun copyright below.
7 * RPC for the Windows NT Operating System COMES WITH ABSOLUTELY NO
8 * WARRANTY, NOR WILL I BE LIABLE FOR ANY DAMAGES INCURRED FROM THE
9 * USE OF. USE ENTIRELY AT YOUR OWN RISK!!!
10 *********************************************************************/
12 /* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
14 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
15 * unrestricted use provided that this legend is included on all tape
16 * media and as a part of the software program in whole or part. Users
17 * may copy or modify Sun RPC without charge, but are not authorized
18 * to license or distribute it to anyone else except as part of a product or
19 * program developed by the user.
21 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
22 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
23 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
25 * Sun RPC is provided with no support and without any obligation on the
26 * part of Sun Microsystems, Inc. to assist in its use, correction,
27 * modification or enhancement.
29 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
30 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
31 * OR ANY PART THEREOF.
33 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
34 * or profits or other special, indirect and consequential damages, even if
35 * Sun has been advised of the possibility of such damages.
37 * Sun Microsystems, Inc.
39 * Mountain View, California 94043
41 #if !defined(lint) && defined(SCCSIDS)
42 static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
46 * svc.c, Server-side remote procedure call interface.
48 * There are two sets of procedures here. The xprt routines are
49 * for handling transport handles. The svc routines handle the
50 * list of service routines.
52 * Copyright (C) 1984, Sun Microsystems, Inc.
57 #include <rpc/pmap_clnt.h>
60 #include <sys/errno.h>
62 #include <rpc/pmap_clnt.h>
65 pthread_mutex_t __thr_mutex = PTHREAD_MUTEX_INITIALIZER;
71 static SVCXPRT **xports;
73 static int sizeof_xports = FD_SETSIZE;
78 static SVCXPRT *xports[NOFILE];
79 #endif /* def FD_SETSIZE */
81 #define NULL_SVC ((struct svc_callout *)0)
82 #define RQCRED_SIZE 400 /* this size is excessive */
86 * Each entry represents a set of procedures (an rpc program).
87 * The dispatch routine takes request structs and runs the
88 * apropriate procedure.
90 static struct svc_callout {
91 struct svc_callout *sc_next;
94 void (*sc_dispatch)();
97 static struct svc_callout *svc_find();
99 /* *************** SVCXPRT related stuff **************** */
102 * Activate a transport handle.
108 register int sock = xprt->xp_sock;
110 EnterCriticalSection(&__thr_mutex);
112 pthread_mutex_lock(&__thr_mutex);
116 if (xports == NULL) {
117 xports = (SVCXPRT **)
118 mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
121 while (sock >= sizeof_xports) {
122 SVCXPRT **old_xports;
125 xports = (SVCXPRT **)
126 mem_alloc(2 * sizeof_xports * sizeof(SVCXPRT *));
127 bcopy(old_xports, xports, sizeof_xports * sizeof(SVCXPRT *));
128 sizeof_xports = 2 * sizeof_xports;
132 if (svc_fdset.fd_count < FD_SETSIZE) {
134 FD_SET(sock, &svc_fdset);
138 sprintf(str, "too many connections (%d), compilation constant FD_SETSIZE was only %d", sock, FD_SETSIZE);
142 if (sock < FD_SETSIZE) {
144 FD_SET(sock, &svc_fdset);
150 svc_fds |= (1 << sock);
152 #endif /* def FD_SETSIZE */
155 LeaveCriticalSection(&__thr_mutex);
157 pthread_mutex_unlock(&__thr_mutex);
162 * De-activate a transport handle.
165 xprt_unregister(xprt)
168 register int sock = xprt->xp_sock;
170 EnterCriticalSection(&__thr_mutex);
172 pthread_mutex_lock(&__thr_mutex);
177 if ((xports[sock] == xprt)) {
178 xports[sock] = (SVCXPRT *)0;
179 FD_CLR((unsigned)sock, &svc_fdset);
181 if ((sock < FD_SETSIZE) && (xports[sock] == xprt)) {
182 xports[sock] = (SVCXPRT *)0;
183 FD_CLR(sock, &svc_fdset);
187 if ((sock < NOFILE) && (xports[sock] == xprt)) {
188 xports[sock] = (SVCXPRT *)0;
189 svc_fds &= ~(1 << sock);
191 #endif /* def FD_SETSIZE */
194 LeaveCriticalSection(&__thr_mutex);
196 pthread_mutex_unlock(&__thr_mutex);
201 /* ********************** CALLOUT list related stuff ************* */
204 * Add a service program to the callout list.
205 * The dispatch routine will be called when a rpc request for this
206 * program number comes in.
209 svc_register(xprt, prog, vers, dispatch, protocol)
216 struct svc_callout *prev;
217 register struct svc_callout *s;
219 if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
220 if (s->sc_dispatch == dispatch)
221 goto pmap_it; /* he is registering another xptr */
224 s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
225 if (s == (struct svc_callout *)0) {
230 s->sc_dispatch = dispatch;
231 s->sc_next = svc_head;
234 /* now register the information with the local binder service */
236 return (pmap_set(prog, vers, protocol, xprt->xp_port));
242 * Remove a service program from the callout list.
245 svc_unregister(prog, vers)
249 struct svc_callout *prev;
250 register struct svc_callout *s;
252 if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
254 if (prev == NULL_SVC) {
255 svc_head = s->sc_next;
257 prev->sc_next = s->sc_next;
259 s->sc_next = NULL_SVC;
260 mem_free((char *) s, (u_int) sizeof(struct svc_callout));
261 /* now unregister the information with the local binder service */
262 (void)pmap_unset(prog, vers);
266 * Search the callout list for a program number, return the callout
269 static struct svc_callout *
270 svc_find(prog, vers, prev)
273 struct svc_callout **prev;
275 register struct svc_callout *s, *p;
278 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
279 if ((s->sc_prog == prog) && (s->sc_vers == vers))
288 /* ******************* REPLY GENERATION ROUTINES ************ */
291 * Send a reply to an rpc request
294 svc_sendreply(xprt, xdr_results, xdr_location)
295 register SVCXPRT *xprt;
296 xdrproc_t xdr_results;
297 caddr_t xdr_location;
301 rply.rm_direction = REPLY;
302 rply.rm_reply.rp_stat = MSG_ACCEPTED;
303 rply.acpted_rply.ar_verf = xprt->xp_verf;
304 rply.acpted_rply.ar_stat = SUCCESS;
305 rply.acpted_rply.ar_results.where = xdr_location;
306 rply.acpted_rply.ar_results.proc = xdr_results;
307 return (SVC_REPLY(xprt, &rply));
311 * No procedure error reply
315 register SVCXPRT *xprt;
319 rply.rm_direction = REPLY;
320 rply.rm_reply.rp_stat = MSG_ACCEPTED;
321 rply.acpted_rply.ar_verf = xprt->xp_verf;
322 rply.acpted_rply.ar_stat = PROC_UNAVAIL;
323 SVC_REPLY(xprt, &rply);
327 * Can't decode args error reply
331 register SVCXPRT *xprt;
335 rply.rm_direction = REPLY;
336 rply.rm_reply.rp_stat = MSG_ACCEPTED;
337 rply.acpted_rply.ar_verf = xprt->xp_verf;
338 rply.acpted_rply.ar_stat = GARBAGE_ARGS;
339 SVC_REPLY(xprt, &rply);
346 svcerr_systemerr(xprt)
347 register SVCXPRT *xprt;
351 rply.rm_direction = REPLY;
352 rply.rm_reply.rp_stat = MSG_ACCEPTED;
353 rply.acpted_rply.ar_verf = xprt->xp_verf;
354 rply.acpted_rply.ar_stat = SYSTEM_ERR;
355 SVC_REPLY(xprt, &rply);
359 * Authentication error reply
362 svcerr_auth(xprt, why)
368 rply.rm_direction = REPLY;
369 rply.rm_reply.rp_stat = MSG_DENIED;
370 rply.rjcted_rply.rj_stat = AUTH_ERROR;
371 rply.rjcted_rply.rj_why = why;
372 SVC_REPLY(xprt, &rply);
376 * Auth too weak error reply
379 svcerr_weakauth(xprt)
383 svcerr_auth(xprt, AUTH_TOOWEAK);
387 * Program unavailable error reply
391 register SVCXPRT *xprt;
395 rply.rm_direction = REPLY;
396 rply.rm_reply.rp_stat = MSG_ACCEPTED;
397 rply.acpted_rply.ar_verf = xprt->xp_verf;
398 rply.acpted_rply.ar_stat = PROG_UNAVAIL;
399 SVC_REPLY(xprt, &rply);
403 * Program version mismatch error reply
406 svcerr_progvers(xprt, low_vers, high_vers)
407 register SVCXPRT *xprt;
413 rply.rm_direction = REPLY;
414 rply.rm_reply.rp_stat = MSG_ACCEPTED;
415 rply.acpted_rply.ar_verf = xprt->xp_verf;
416 rply.acpted_rply.ar_stat = PROG_MISMATCH;
417 rply.acpted_rply.ar_vers.low = low_vers;
418 rply.acpted_rply.ar_vers.high = high_vers;
419 SVC_REPLY(xprt, &rply);
422 /* ******************* SERVER INPUT STUFF ******************* */
425 * Get server side input from some transport.
427 * Statement of authentication parameters management:
428 * This function owns and manages all authentication parameters, specifically
429 * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
430 * the "cooked" credentials (rqst->rq_clntcred).
431 * However, this function does not know the structure of the cooked
432 * credentials, so it make the following assumptions:
433 * a) the structure is contiguous (no pointers), and
434 * b) the cred structure size does not exceed RQCRED_SIZE bytes.
435 * In all events, all three parameters are freed upon exit from this routine.
436 * The storage is trivially management on the call stack in user land, but
437 * is mallocated in kernel land.
461 readfds.fds_bits[0] = rdfds;
463 svc_getreqset(&readfds);
465 int readfds = rdfds & svc_fds;
467 svc_getreqset(&readfds);
468 #endif /* def FD_SETSIZE */
472 svc_getreqset(readfds)
479 int readfds_local = *readfds;
480 #endif /* def FD_SETSIZE */
487 register SVCXPRT *xprt;
488 register u_long mask;
490 register u_long *maskp;
491 register int setsize;
493 char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
496 msg.rm_call.cb_cred.oa_base = cred_area;
497 msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
498 r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
502 /* Loop through the sockets that have input ready */
503 for ( i=0; i<readfds->fd_count; i++ ) {
504 sock = readfds->fd_array[i];
505 /* sock has input waiting */
506 EnterCriticalSection(&__thr_mutex);
508 LeaveCriticalSection(&__thr_mutex);
510 setsize = FD_SETSIZE;
511 maskp = (u_long *)readfds->fds_bits;
512 for (sock = 0; sock < setsize; sock += NFDBITS) {
513 for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) {
514 /* sock has input waiting */
515 pthread_mutex_lock(&__thr_mutex);
516 xprt = xports[sock + bit - 1];
517 pthread_mutex_unlock(&__thr_mutex);
520 for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
521 if ((readfds_local & 1) != 0) {
522 /* sock has input waiting */
523 pthread_mutex_lock(&__thr_mutex);
525 pthread_mutex_unlock(&__thr_mutex);
526 #endif /* def FD_SETSIZE */
527 /* now receive msgs from xprtprt (support batch calls) */
529 if (SVC_RECV(xprt, &msg)) {
531 /* now find the exported program and call it */
532 register struct svc_callout *s;
536 r.rq_prog = msg.rm_call.cb_prog;
537 r.rq_vers = msg.rm_call.cb_vers;
538 r.rq_proc = msg.rm_call.cb_proc;
539 r.rq_cred = msg.rm_call.cb_cred;
540 /* first authenticate the message */
541 if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
542 svcerr_auth(xprt, why);
545 /* now match message with a registered service*/
549 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
550 if (s->sc_prog == r.rq_prog) {
551 if (s->sc_vers == r.rq_vers) {
552 (*s->sc_dispatch)(&r, xprt);
554 } /* found correct version */
556 if (s->sc_vers < low_vers)
557 low_vers = s->sc_vers;
558 if (s->sc_vers > high_vers)
559 high_vers = s->sc_vers;
560 } /* found correct program */
563 * if we got here, the program or version
567 svcerr_progvers(xprt,
568 low_vers, high_vers);
571 /* Fall through to ... */
574 if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
578 } while (stat == XPRT_MOREREQS);
581 #if !defined(FD_SETSIZE) || !defined(WIN32)