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