/* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */ /* * Sun RPC is a product of Sun Microsystems, Inc. and is provided for * unrestricted use provided that this legend is included on all tape * media and as a part of the software program in whole or part. Users * may copy or modify Sun RPC without charge, but are not authorized * to license or distribute it to anyone else except as part of a product or * program developed by the user. * * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. * * Sun RPC is provided with no support and without any obligation on the * part of Sun Microsystems, Inc. to assist in its use, correction, * modification or enhancement. * * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC * OR ANY PART THEREOF. * * In no event will Sun Microsystems, Inc. be liable for any lost revenue * or profits or other special, indirect and consequential damages, even if * Sun has been advised of the possibility of such damages. * * Sun Microsystems, Inc. * 2550 Garcia Avenue * Mountain View, California 94043 */ #if !defined(lint) && defined(SCCSIDS) static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro"; #endif /* * svc.c, Server-side remote procedure call interface. * * There are two sets of procedures here. The xprt routines are * for handling transport handles. The svc routines handle the * list of service routines. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #define RQCRED_SIZE 400 /* this size is excessive */ /* ******************* REPLY GENERATION ROUTINES ************ */ /* * Send a reply to an rpc request */ bool_t svc_sendreply(xprt, xdr_results, xdr_location) register SVCXPRT *xprt; xdrproc_t xdr_results; caddr_t xdr_location; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.acpted_rply.ar_verf = xprt->xp_verf; rply.acpted_rply.ar_stat = SUCCESS; rply.acpted_rply.ar_results.where = xdr_location; rply.acpted_rply.ar_results.proc = xdr_results; return (SVC_REPLY(xprt, &rply)); } /* * No procedure error reply */ void svcerr_noproc(xprt) register SVCXPRT *xprt; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.acpted_rply.ar_verf = xprt->xp_verf; rply.acpted_rply.ar_stat = PROC_UNAVAIL; SVC_REPLY(xprt, &rply); } /* * Can't decode args error reply */ void svcerr_decode(xprt) register SVCXPRT *xprt; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.acpted_rply.ar_verf = xprt->xp_verf; rply.acpted_rply.ar_stat = GARBAGE_ARGS; SVC_REPLY(xprt, &rply); } /* * Some system error */ void svcerr_systemerr(xprt) register SVCXPRT *xprt; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.acpted_rply.ar_verf = xprt->xp_verf; rply.acpted_rply.ar_stat = SYSTEM_ERR; SVC_REPLY(xprt, &rply); } /* * Authentication error reply */ void svcerr_auth(xprt, why) SVCXPRT *xprt; enum auth_stat why; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_DENIED; rply.rjcted_rply.rj_stat = AUTH_ERROR; rply.rjcted_rply.rj_why = why; SVC_REPLY(xprt, &rply); } /* * Auth too weak error reply */ void svcerr_weakauth(xprt) SVCXPRT *xprt; { svcerr_auth(xprt, AUTH_TOOWEAK); } /* * Program unavailable error reply */ void svcerr_noprog(xprt) register SVCXPRT *xprt; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.acpted_rply.ar_verf = xprt->xp_verf; rply.acpted_rply.ar_stat = PROG_UNAVAIL; SVC_REPLY(xprt, &rply); } /* * Program version mismatch error reply */ void svcerr_progvers(xprt, low_vers, high_vers) register SVCXPRT *xprt; u_long low_vers; u_long high_vers; { struct rpc_msg rply; rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.acpted_rply.ar_verf = xprt->xp_verf; rply.acpted_rply.ar_stat = PROG_MISMATCH; rply.acpted_rply.ar_vers.low = low_vers; rply.acpted_rply.ar_vers.high = high_vers; SVC_REPLY(xprt, &rply); } void svc_processrequest(xprt, prog, vers, dispatch) SVCXPRT *xprt; u_long prog; u_long vers; void (*dispatch)(); { struct rpc_msg msg; int prog_found = FALSE; u_long low_vers = 0; /* dummy init */ u_long high_vers = 0; /* dummy init */ struct svc_req r; /*static char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];*/ char *cred_area; cred_area = (char *)malloc(2*MAX_AUTH_BYTES + RQCRED_SIZE); msg.rm_call.cb_cred.oa_base = cred_area; msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); if (SVC_RECV(xprt, &msg)) { /* now find the exported program and call it */ /* register struct svc_callout *s; */ enum auth_stat why; r.rq_xprt = xprt; r.rq_prog = msg.rm_call.cb_prog; r.rq_vers = msg.rm_call.cb_vers; r.rq_proc = msg.rm_call.cb_proc; r.rq_cred = msg.rm_call.cb_cred; /* first authenticate the message */ if ((why= _authenticate(&r, &msg)) != AUTH_OK) { svcerr_auth(xprt, why); free(cred_area); return; } /* now match message with a registered service*/ prog_found = FALSE; low_vers = 0 - 1; high_vers = 0; if (prog == r.rq_prog) { if (vers == r.rq_vers) { (*dispatch)(&r, xprt); free(cred_area); return; } /* found correct version */ prog_found = TRUE; if (vers < low_vers) low_vers = vers; if (vers > high_vers) high_vers = vers; } /* found correct program */ } /* * if we got here, the program or version * is not served ... */ if (prog_found) { svcerr_progvers(xprt, low_vers, high_vers); } else { svcerr_noprog(xprt); } free(cred_area); } /* stubs for solaris rpcgen */ /*int _rpcsvccount; int _rpcsvcstate; int _SERVED; */