2 static char sfs_svc_c_id[] = "@(#)svc.c 2.1 97/10/23";
4 /* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
6 * Copyright (c) 1992-1997,2001 by Standard Performance Evaluation Corporation
8 * Standard Performance Evaluation Corporation (SPEC)
9 * 6585 Merchant Place, Suite 100
12 * This product contains benchmarks acquired from several sources who
13 * understand and agree with SPEC's goal of creating fair and objective
14 * benchmarks to measure computer performance.
16 * This copyright notice is placed here only to protect SPEC in the
17 * event the source is misused in any manner that is contrary to the
18 * spirit, the goals and the intent of SPEC.
20 * The source code is provided to the user or company under the license
21 * agreement for the SPEC Benchmark Suite for this product.
24 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
25 * unrestricted use provided that this legend is included on all tape
26 * media and as a part of the software program in whole or part. Users
27 * may copy or modify Sun RPC without charge, but are not authorized
28 * to license or distribute it to anyone else except as part of a product or
29 * program developed by the user.
31 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
32 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
33 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
35 * Sun RPC is provided with no support and without any obligation on the
36 * part of Sun Microsystems, Inc. to assist in its use, correction,
37 * modification or enhancement.
39 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
40 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
41 * OR ANY PART THEREOF.
43 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
44 * or profits or other special, indirect and consequential damages, even if
45 * Sun has been advised of the possibility of such damages.
47 * Sun Microsystems, Inc.
49 * Mountain View, California 94043
51 #if !defined(lint) && defined(SCCSIDS)
52 static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
56 * svc.c, Server-side remote procedure call interface.
58 * There are two sets of procedures here. The xprt routines are
59 * for handling transport handles. The svc routines handle the
60 * list of service routines.
62 * Copyright (C) 1984, Sun Microsystems, Inc.
71 #include "rpc/pmap_clnt.h"
74 static SVCXPRT **xports;
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 int sock = xprt->xp_sock;
111 if (xports == NULL) {
112 xports = (SVCXPRT **)
113 mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
115 if (sock < _rpc_dtablesize()) {
117 FD_SET(sock, &svc_fdset);
122 svc_fds |= (1 << sock);
124 #endif /* def FD_SETSIZE */
129 * De-activate a transport handle.
135 int sock = xprt->xp_sock;
138 if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) {
139 xports[sock] = (SVCXPRT *)0;
140 FD_CLR(sock, &svc_fdset);
143 if ((sock < NOFILE) && (xports[sock] == xprt)) {
144 xports[sock] = (SVCXPRT *)0;
145 svc_fds &= ~(1 << sock);
147 #endif /* def FD_SETSIZE */
151 /* ********************** CALLOUT list related stuff ************* */
154 * Add a service program to the callout list.
155 * The dispatch routine will be called when a rpc request for this
156 * program number comes in.
166 struct svc_callout *prev;
167 struct svc_callout *s;
169 if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
170 if (s->sc_dispatch == dispatch)
171 goto pmap_it; /* he is registering another xptr */
174 s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
175 if (s == (struct svc_callout *)0) {
180 s->sc_dispatch = dispatch;
181 s->sc_next = svc_head;
184 /* now register the information with the local binder service */
186 return (pmap_set(prog, vers, protocol, xprt->xp_port));
192 * Remove a service program from the callout list.
199 struct svc_callout *prev;
200 struct svc_callout *s;
202 if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
204 if (prev == NULL_SVC) {
205 svc_head = s->sc_next;
207 prev->sc_next = s->sc_next;
209 s->sc_next = NULL_SVC;
210 mem_free((char *) s, (uint_t) sizeof(struct svc_callout));
211 /* now unregister the information with the local binder service */
212 (void)pmap_unset(prog, vers);
216 * Search the callout list for a program number, return the callout
219 static struct svc_callout *
223 struct svc_callout **prev)
225 struct svc_callout *s, *p;
228 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
229 if ((s->sc_prog == prog) && (s->sc_vers == vers))
238 /* ******************* REPLY GENERATION ROUTINES ************ */
241 * Send a reply to an rpc request
246 xdrproc_t xdr_results,
251 rply.rm_direction = REPLY;
252 rply.rm_reply.rp_stat = MSG_ACCEPTED;
253 rply.acpted_rply.ar_verf = xprt->xp_verf;
254 rply.acpted_rply.ar_stat = SUCCESS;
255 rply.acpted_rply.ar_results.where = xdr_location;
256 rply.acpted_rply.ar_results.proc = xdr_results;
257 return (SVC_REPLY(xprt, &rply));
261 * No procedure error reply
269 rply.rm_direction = REPLY;
270 rply.rm_reply.rp_stat = MSG_ACCEPTED;
271 rply.acpted_rply.ar_verf = xprt->xp_verf;
272 rply.acpted_rply.ar_stat = PROC_UNAVAIL;
273 SVC_REPLY(xprt, &rply);
277 * Can't decode args error reply
285 rply.rm_direction = REPLY;
286 rply.rm_reply.rp_stat = MSG_ACCEPTED;
287 rply.acpted_rply.ar_verf = xprt->xp_verf;
288 rply.acpted_rply.ar_stat = GARBAGE_ARGS;
289 SVC_REPLY(xprt, &rply);
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 = SYSTEM_ERR;
305 SVC_REPLY(xprt, &rply);
309 * Authentication error reply
318 rply.rm_direction = REPLY;
319 rply.rm_reply.rp_stat = MSG_DENIED;
320 rply.rjcted_rply.rj_stat = AUTH_ERROR;
321 rply.rjcted_rply.rj_why = why;
322 SVC_REPLY(xprt, &rply);
326 * Auth too weak error reply
333 svcerr_auth(xprt, AUTH_TOOWEAK);
337 * Program unavailable error reply
345 rply.rm_direction = REPLY;
346 rply.rm_reply.rp_stat = MSG_ACCEPTED;
347 rply.acpted_rply.ar_verf = xprt->xp_verf;
348 rply.acpted_rply.ar_stat = PROG_UNAVAIL;
349 SVC_REPLY(xprt, &rply);
353 * Program version mismatch error reply
363 rply.rm_direction = REPLY;
364 rply.rm_reply.rp_stat = MSG_ACCEPTED;
365 rply.acpted_rply.ar_verf = xprt->xp_verf;
366 rply.acpted_rply.ar_stat = PROG_MISMATCH;
367 rply.acpted_rply.ar_vers.low = low_vers;
368 rply.acpted_rply.ar_vers.high = high_vers;
369 SVC_REPLY(xprt, &rply);
372 /* ******************* SERVER INPUT STUFF ******************* */
375 * Get server side input from some transport.
377 * Statement of authentication parameters management:
378 * This function owns and manages all authentication parameters, specifically
379 * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
380 * the "cooked" credentials (rqst->rq_clntcred).
381 * However, this function does not know the structure of the cooked
382 * credentials, so it make the following assumptions:
383 * a) the structure is contiguous (no pointers), and
384 * b) the cred structure size does not exceed RQCRED_SIZE bytes.
385 * In all events, all three parameters are freed upon exit from this routine.
386 * The storage is trivially management on the call stack in user land, but
387 * is mallocated in kernel land.
398 int readfds_local = *readfds;
399 #endif /* def FD_SETSIZE */
409 char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
410 msg.rm_call.cb_cred.oa_base = cred_area;
411 msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
412 r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
416 setsize = _rpc_dtablesize();
417 for (sock = 0; sock < setsize; sock++) {
418 if (FD_ISSET(sock, readfds)) {
420 for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
421 if ((readfds_local & 1) != 0) {
422 #endif /* def FD_SETSIZE */
423 /* sock has input waiting */
425 /* now receive msgs from xprtprt (support batch calls) */
427 if (SVC_RECV(xprt, &msg)) {
429 /* now find the exported program and call it */
430 struct svc_callout *s;
434 r.rq_prog = msg.rm_call.cb_prog;
435 r.rq_vers = msg.rm_call.cb_vers;
436 r.rq_proc = msg.rm_call.cb_proc;
437 r.rq_cred = msg.rm_call.cb_cred;
438 /* first authenticate the message */
439 if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
440 svcerr_auth(xprt, why);
443 /* now match message with a registered service*/
447 for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
448 if (s->sc_prog == r.rq_prog) {
449 if (s->sc_vers == r.rq_vers) {
450 (*s->sc_dispatch)(&r, xprt);
452 } /* found correct version */
454 if (s->sc_vers < low_vers)
455 low_vers = s->sc_vers;
456 if (s->sc_vers > high_vers)
457 high_vers = s->sc_vers;
458 } /* found correct program */
461 * if we got here, the program or version
465 svcerr_progvers(xprt,
466 low_vers, high_vers);
469 /* Fall through to ... */
472 if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
476 } while (stat == XPRT_MOREREQS);