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: }

Defined functions

rpctest_service defined in line 456; used 2 times
svc_find defined in line 183; used 3 times
svc_getreq defined in line 341; used 4 times
svc_run defined in line 430; used 2 times
svc_unregister defined in line 158; used 1 times
svcerr_auth defined in line 275; used 2 times
svcerr_noproc defined in line 227; used 3 times
svcerr_noprog defined in line 303; used 1 times
svcerr_progvers defined in line 319; used 1 times
svcerr_systemerr defined in line 259; used 1 times
svcerr_weakauth defined in line 292; used 1 times

Defined variables

sccsid defined in line 30; never used
svc_fds defined in line 58; used 4 times
svc_head defined in line 77; used 5 times

Defined struct's

svc_callout defined in line 72; used 26 times

Defined macros

NOFILE defined in line 55; used 3 times
NULL_SVC defined in line 62; used 8 times
Last modified: 1985-04-19
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1273
Valid CSS Valid XHTML 1.0 Strict