|
|
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.