|
|
1.1 root 1: /*
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: #ifndef lint
30: static char sccsid[] = "@(#)svc.c 1.7 85/03/20 Copyr 1984 Sun Micro";
31: #endif
32:
33: /*
34: * svc.c, Server-side remote procedure call interface.
35: *
36: * There are two sets of procedures here. The xprt routines are
37: * for handling transport handles. The svc routines handle the
38: * list of service routines.
39: *
40: * Copyright (C) 1984, Sun Microsystems, Inc.
41: */
42:
43: #include <stdio.h>
44: #include "types.h"
45: #include <sys/errno.h>
46: #include <netinet/in.h>
47: #include "xdr.h"
48: #include "auth.h"
49: #include "clnt.h"
50: #include "rpc_msg.h"
51: #include "svc.h"
52: #include "svc_auth.h"
53: #include "pmap_clnt.h" /* <make kernel depend happy> */
54:
55: #define NOFILE 32
56:
57: static SVCXPRT *xports[NOFILE];
58: int svc_fds = 0;
59: extern errno;
60: char *malloc();
61:
62: #define NULL_SVC ((struct svc_callout *)0)
63:
64: void rpctest_service();
65:
66: /*
67: * The services list
68: * Each entry represents a set of procedures (an rpc program).
69: * The dispatch routine takes request structs and runs the
70: * apropriate procedure.
71: */
72: static struct svc_callout {
73: struct svc_callout *sc_next;
74: u_long sc_prog;
75: u_long sc_vers;
76: void (*sc_dispatch)();
77: } *svc_head = NULL_SVC;
78:
79: static struct svc_callout *svc_find();
80:
81: /* *************** SVCXPRT related stuff **************** */
82:
83: /*
84: * Activate a transport handle.
85: */
86: void
87: xprt_register(xprt)
88: SVCXPRT *xprt;
89: {
90: register int sock = xprt->xp_sock;
91:
92: if (sock < NOFILE) {
93: xports[sock] = xprt;
94: svc_fds |= (1 << sock);
95: }
96: }
97:
98: /*
99: * De-activate a transport handle.
100: */
101: void
102: xprt_unregister(xprt)
103: SVCXPRT *xprt;
104: {
105: register int sock = xprt->xp_sock;
106:
107: if ((sock < NOFILE) && (xports[sock] == xprt)) {
108: xports[sock] = (SVCXPRT *)NULL;
109: svc_fds &= ~(1 << sock);
110: }
111: }
112:
113:
114: /* ********************** CALLOUT list related stuff ************* */
115:
116: /*
117: * Add a service program to the callout list.
118: * The dispatch routine will be called when a rpc request for this
119: * program number comes in.
120: */
121: bool_t
122: svc_register(xprt, prog, vers, dispatch, protocol)
123: SVCXPRT *xprt;
124: u_long prog;
125: u_long vers;
126: void (*dispatch)();
127: int protocol;
128: {
129: struct svc_callout *prev;
130: register struct svc_callout *s;
131:
132: if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) {
133: if (s->sc_dispatch == dispatch)
134: goto pmap_it; /* he is registering another xptr */
135: return (FALSE);
136: }
137: s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout));
138: if (s == NULL) {
139: fprintf(stderr, "svc_register: out of memory\n");
140: return (FALSE);
141: }
142: s->sc_prog = prog;
143: s->sc_vers = vers;
144: s->sc_dispatch = dispatch;
145: s->sc_next = svc_head;
146: svc_head = s;
147: pmap_it:
148: /* now register the information with the local binder service */
149: if (protocol) {
150: return (pmap_set(prog, vers, protocol, xprt->xp_port));
151: }
152: return (TRUE);
153: }
154:
155: /*
156: * Remove a service program from the callout list.
157: */
158: void
159: svc_unregister(prog, vers)
160: u_long prog;
161: u_long vers;
162: {
163: struct svc_callout *prev;
164: register struct svc_callout *s;
165:
166: if ((s = svc_find(prog, vers, &prev)) == NULL_SVC)
167: return;
168: if (prev == NULL_SVC) {
169: svc_head = s->sc_next;
170: } else {
171: prev->sc_next = s->sc_next;
172: }
173: s->sc_next = NULL_SVC;
174: mem_free(s, sizeof(struct svc_callout));
175: /* now unregister the information with the local binder service */
176: (void)pmap_unset(prog, vers);
177: }
178:
179: /*
180: * Search the callout list for a program number, return the callout
181: * struct.
182: */
183: static struct svc_callout *
184: svc_find(prog, vers, prev)
185: u_long prog;
186: u_long vers;
187: struct svc_callout **prev;
188: {
189: register struct svc_callout *s, *p;
190:
191: p = NULL_SVC;
192: for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
193: if ((s->sc_prog == prog) && (s->sc_vers == vers))
194: goto done;
195: p = s;
196: }
197: done:
198: *prev = p;
199: return (s);
200: }
201:
202: /* ******************* REPLY GENERATION ROUTINES ************ */
203:
204: /*
205: * Send a reply to an rpc request
206: */
207: bool_t
208: svc_sendreply(xprt, xdr_results, xdr_location)
209: register SVCXPRT *xprt;
210: xdrproc_t xdr_results;
211: caddr_t xdr_location;
212: {
213: struct rpc_msg rply;
214:
215: rply.rm_direction = REPLY;
216: rply.rm_reply.rp_stat = MSG_ACCEPTED;
217: rply.acpted_rply.ar_verf = xprt->xp_verf;
218: rply.acpted_rply.ar_stat = SUCCESS;
219: rply.acpted_rply.ar_results.where = xdr_location;
220: rply.acpted_rply.ar_results.proc = xdr_results;
221: return (SVC_REPLY(xprt, &rply));
222: }
223:
224: /*
225: * No procedure error reply
226: */
227: void
228: svcerr_noproc(xprt)
229: register SVCXPRT *xprt;
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 = PROC_UNAVAIL;
237: SVC_REPLY(xprt, &rply);
238: }
239:
240: /*
241: * Can't decode args error reply
242: */
243: void
244: svcerr_decode(xprt)
245: 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 = GARBAGE_ARGS;
253: SVC_REPLY(xprt, &rply);
254: }
255:
256: /*
257: * Some system error
258: */
259: void
260: svcerr_systemerr(xprt)
261: register SVCXPRT *xprt;
262: {
263: struct rpc_msg rply;
264:
265: rply.rm_direction = REPLY;
266: rply.rm_reply.rp_stat = MSG_ACCEPTED;
267: rply.acpted_rply.ar_verf = xprt->xp_verf;
268: rply.acpted_rply.ar_stat = SYSTEM_ERR;
269: SVC_REPLY(xprt, &rply);
270: }
271:
272: /*
273: * Authentication error reply
274: */
275: void
276: svcerr_auth(xprt, why)
277: SVCXPRT *xprt;
278: enum auth_stat why;
279: {
280: struct rpc_msg rply;
281:
282: rply.rm_direction = REPLY;
283: rply.rm_reply.rp_stat = MSG_DENIED;
284: rply.rjcted_rply.rj_stat = AUTH_ERROR;
285: rply.rjcted_rply.rj_why = why;
286: SVC_REPLY(xprt, &rply);
287: }
288:
289: /*
290: * Auth too weak error reply
291: */
292: void
293: svcerr_weakauth(xprt)
294: SVCXPRT *xprt;
295: {
296:
297: svcerr_auth(xprt, AUTH_TOOWEAK);
298: }
299:
300: /*
301: * Program unavailable error reply
302: */
303: void
304: svcerr_noprog(xprt)
305: register SVCXPRT *xprt;
306: {
307: struct rpc_msg rply;
308:
309: rply.rm_direction = REPLY;
310: rply.rm_reply.rp_stat = MSG_ACCEPTED;
311: rply.acpted_rply.ar_verf = xprt->xp_verf;
312: rply.acpted_rply.ar_stat = PROG_UNAVAIL;
313: SVC_REPLY(xprt, &rply);
314: }
315:
316: /*
317: * Program version mismatch error reply
318: */
319: void
320: svcerr_progvers(xprt, low_vers, high_vers)
321: register SVCXPRT *xprt;
322: u_long low_vers;
323: u_long high_vers;
324: {
325: struct rpc_msg rply;
326:
327: rply.rm_direction = REPLY;
328: rply.rm_reply.rp_stat = MSG_ACCEPTED;
329: rply.acpted_rply.ar_verf = xprt->xp_verf;
330: rply.acpted_rply.ar_stat = PROG_MISMATCH;
331: rply.acpted_rply.ar_vers.low = low_vers;
332: rply.acpted_rply.ar_vers.high = high_vers;
333: SVC_REPLY(xprt, &rply);
334: }
335:
336: /* ******************* SERVER INPUT STUFF ******************* */
337:
338: /*
339: * Get server side input from some transport
340: */
341: void
342: svc_getreq(rdfds)
343: int rdfds;
344: {
345: register int sock;
346: register int readfds = rdfds & svc_fds;
347: register SVCXPRT *xprt;
348: register enum xprt_stat stat;
349: struct rpc_msg msg;
350: /*char cred_body[MAX_AUTH_BYTES], verf_body[MAX_AUTH_BYTES];*/
351: char *cred_body;
352: int prog_found;
353: u_long low_vers;
354: u_long high_vers;
355:
356: cred_body = (char *)mem_alloc(2 * MAX_AUTH_BYTES);
357: if (cred_body == NULL) {
358: fprintf(stderr, "svc_getreq: out of memory\n");
359: svcerr_systemerr(xprt);
360: goto call_done;
361: }
362: msg.rm_call.cb_cred.oa_base = cred_body;
363: msg.rm_call.cb_verf.oa_base = &(cred_body[MAX_AUTH_BYTES]);
364: for (sock = 0; readfds != 0; sock++, readfds >>= 1) {
365: if ((readfds & 1) != 0) {
366: /* sock has input waiting */
367: xprt = xports[sock];
368: /* now receive msgs from xprtprt (support batch calls) */
369: do {
370: if (SVC_RECV(xprt, &msg)) {
371:
372: /* now find the exported program and call it */
373: register struct svc_callout *s;
374: enum auth_stat why;
375: struct svc_req r;
376:
377: r.rq_xprt = xprt;
378: r.rq_prog = msg.rm_call.cb_prog;
379: r.rq_vers = msg.rm_call.cb_vers;
380: r.rq_proc = msg.rm_call.cb_proc;
381: r.rq_cred = msg.rm_call.cb_cred;
382: /* first authenticate the message */
383: if ((why= _authenticate(&r, &msg)) != AUTH_OK) {
384: svcerr_auth(xprt, why);
385: goto call_done;
386: }
387: /* now match message with a registered service*/
388: prog_found = FALSE;
389: low_vers = 0 - 1;
390: high_vers = 0;
391: for (s = svc_head; s != NULL_SVC; s = s->sc_next) {
392: if (s->sc_prog == r.rq_prog) {
393: if (s->sc_vers == r.rq_vers) {
394: (*s->sc_dispatch)(&r, xprt);
395: goto call_done;
396: } /* found correct version */
397: prog_found = TRUE;
398: if (s->sc_vers < low_vers)
399: low_vers = s->sc_vers;
400: if (s->sc_vers > high_vers)
401: high_vers = s->sc_vers;
402: } /* found correct program */
403: }
404: /*
405: * if we got here, the program or version
406: * is not served ...
407: */
408: if (prog_found)
409: svcerr_progvers(xprt,
410: low_vers, high_vers);
411: else
412: svcerr_noprog(xprt);
413: /* Fall through to ... */
414: }
415: call_done:
416: if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
417: SVC_DESTROY(xprt);
418: break;
419: }
420: } while (stat == XPRT_MOREREQS);
421: }
422: }
423: mem_free(cred_body, 2 * MAX_AUTH_BYTES);
424: }
425:
426: /*
427: * This is the rpc server side idle loop
428: * Wait for input, call server program.
429: */
430: void
431: svc_run()
432: {
433: int readfds;
434:
435: while (TRUE) {
436: readfds = svc_fds;
437: switch (select(32, &readfds, (int *)NULL, (int *)NULL,
438: (struct timeval *)NULL)) {
439:
440: case -1:
441: if (errno == EINTR)
442: continue;
443: else {
444: perror("svc.c: - Select failed");
445: return;
446: }
447: case 0:
448: continue;
449: default:
450: svc_getreq(readfds);
451: }
452: }
453: }
454:
455: /* *************************** BUILTIN TEST SERVICE **************** */
456: void
457: rpctest_service(reqst, xprt)
458: struct svc_req *reqst;
459: register SVCXPRT *xprt;
460: {
461:
462: switch (reqst->rq_proc) {
463:
464: case RPCTEST_NULL_PROC:
465: /* get nullp parameters, return null results */
466: if (SVC_GETARGS(xprt, xdr_void, NULL)) {
467: svc_sendreply(xprt, (xdrproc_t)xdr_void, (caddr_t)NULL);
468: } else {
469: svcerr_decode(xprt);
470: }
471: return;
472:
473: case RPCTEST_NULL_BATCH_PROC: /* nothing !! */
474: return;
475:
476: default:
477: svcerr_noproc(xprt);
478: return;
479: }
480: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.