rsalz@bbn.com (Rich Salz) (03/03/88)
Submitted-by: Stephen X. Nahm <sxn@Sun.COM> Posting-number: Volume 13, Issue 80 Archive-name: rpc3.9/part03 #! /bin/sh # This is a shell archive. To extract, remove the header and type "sh filename" # cd rpc echo x - pmap_prot.h cat > pmap_prot.h <<'Funky_Stuff' /* @(#)pmap_prot.h 1.1 87/11/04 3.9 RPCSRC */ /* * 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 */ /* @(#)pmap_prot.h 1.13 86/07/16 SMI */ /* * pmap_prot.h * Protocol for the local binder service, or pmap. * * Copyright (C) 1984, Sun Microsystems, Inc. * * The following procedures are supported by the protocol: * * PMAPPROC_NULL() returns () * takes nothing, returns nothing * * PMAPPROC_SET(struct pmap) returns (bool_t) * TRUE is success, FALSE is failure. Registers the tuple * [prog, vers, prot, port]. * * PMAPPROC_UNSET(struct pmap) returns (bool_t) * TRUE is success, FALSE is failure. Un-registers pair * [prog, vers]. prot and port are ignored. * * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). * 0 is failure. Otherwise returns the port number where the pair * [prog, vers] is registered. It may lie! * * PMAPPROC_DUMP() RETURNS (struct pmaplist *) * * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) * RETURNS (port, string<>); * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); * Calls the procedure on the local machine. If it is not registered, * this procedure is quite; ie it does not return error information!!! * This procedure only is supported on rpc/udp and calls via * rpc/udp. This routine only passes null authentication parameters. * This file has no interface to xdr routines for PMAPPROC_CALLIT. * * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. */ #define PMAPPORT ((u_short)111) #define PMAPPROG ((u_long)100000) #define PMAPVERS ((u_long)2) #define PMAPVERS_PROTO ((u_long)2) #define PMAPVERS_ORIG ((u_long)1) #define PMAPPROC_NULL ((u_long)0) #define PMAPPROC_SET ((u_long)1) #define PMAPPROC_UNSET ((u_long)2) #define PMAPPROC_GETPORT ((u_long)3) #define PMAPPROC_DUMP ((u_long)4) #define PMAPPROC_CALLIT ((u_long)5) struct pmap { long unsigned pm_prog; long unsigned pm_vers; long unsigned pm_prot; long unsigned pm_port; }; extern bool_t xdr_pmap(); struct pmaplist { struct pmap pml_map; struct pmaplist *pml_next; }; extern bool_t xdr_pmaplist(); Funky_Stuff len=`wc -c < pmap_prot.h` if [ $len != 3349 ] ; then echo error: pmap_prot.h was $len bytes long, should have been 3349 fi echo x - pmap_prot2.c cat > pmap_prot2.c <<'Funky_Stuff' /* @(#)pmap_prot2.c 1.1 87/11/04 3.9 RPCSRC */ /* * 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[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro"; #endif /* * pmap_prot2.c * Protocol for the local binder service, or pmap. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <rpc/types.h> #include <rpc/xdr.h> #include <rpc/pmap_prot.h> /* * What is going on with linked lists? (!) * First recall the link list declaration from pmap_prot.h: * * struct pmaplist { * struct pmap pml_map; * struct pmaplist *pml_map; * }; * * Compare that declaration with a corresponding xdr declaration that * is (a) pointer-less, and (b) recursive: * * typedef union switch (bool_t) { * * case TRUE: struct { * struct pmap; * pmaplist_t foo; * }; * * case FALSE: struct {}; * } pmaplist_t; * * Notice that the xdr declaration has no nxt pointer while * the C declaration has no bool_t variable. The bool_t can be * interpreted as ``more data follows me''; if FALSE then nothing * follows this bool_t; if TRUE then the bool_t is followed by * an actual struct pmap, and then (recursively) by the * xdr union, pamplist_t. * * This could be implemented via the xdr_union primitive, though this * would cause a one recursive call per element in the list. Rather than do * that we can ``unwind'' the recursion * into a while loop and do the union arms in-place. * * The head of the list is what the C programmer wishes to past around * the net, yet is the data that the pointer points to which is interesting; * this sounds like a job for xdr_reference! */ bool_t xdr_pmaplist(xdrs, rp) register XDR *xdrs; register struct pmaplist **rp; { /* * more_elements is pre-computed in case the direction is * XDR_ENCODE or XDR_FREE. more_elements is overwritten by * xdr_bool when the direction is XDR_DECODE. */ bool_t more_elements; register int freeing = (xdrs->x_op == XDR_FREE); register struct pmaplist **next; while (TRUE) { more_elements = (bool_t)(*rp != NULL); if (! xdr_bool(xdrs, &more_elements)) return (FALSE); if (! more_elements) return (TRUE); /* we are done */ /* * the unfortunate side effect of non-recursion is that in * the case of freeing we must remember the next object * before we free the current object ... */ if (freeing) next = &((*rp)->pml_next); if (! xdr_reference(xdrs, (caddr_t *)rp, (u_int)sizeof(struct pmaplist), xdr_pmap)) return (FALSE); rp = (freeing) ? next : &((*rp)->pml_next); } } Funky_Stuff len=`wc -c < pmap_prot2.c` if [ $len != 3809 ] ; then echo error: pmap_prot2.c was $len bytes long, should have been 3809 fi echo x - pmap_rmt.c cat > pmap_rmt.c <<'Funky_Stuff' /* @(#)pmap_rmt.c 1.4 87/11/30 3.9 RPCSRC */ /* * 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[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro"; #endif /* * pmap_rmt.c * Client interface to pmap rpc service. * remote call and broadcast service * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include <rpc/rpc.h> #include <rpc/pmap_prot.h> #include <rpc/pmap_clnt.h> #include <rpc/pmap_rmt.h> #include <sys/socket.h> #include <sys/time.h> #include <stdio.h> #include <errno.h> #include <net/if.h> #include <sys/ioctl.h> #include <arpa/inet.h> #define MAX_BROADCAST_SIZE 1400 extern int errno; static struct timeval timeout = { 3, 0 }; /* * pmapper remote-call-service interface. * This routine is used to call the pmapper remote call service * which will look up a service program in the port maps, and then * remotely call that routine with the given parameters. This allows * programs to do a lookup and call in one step. */ enum clnt_stat pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_ptr) struct sockaddr_in *addr; u_long prog, vers, proc; xdrproc_t xdrargs, xdrres; caddr_t argsp, resp; struct timeval tout; u_long *port_ptr; { int socket = -1; register CLIENT *client; struct rmtcallargs a; struct rmtcallres r; enum clnt_stat stat; addr->sin_port = htons(PMAPPORT); client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &socket); if (client != (CLIENT *)NULL) { a.prog = prog; a.vers = vers; a.proc = proc; a.args_ptr = argsp; a.xdr_args = xdrargs; r.port_ptr = port_ptr; r.results_ptr = resp; r.xdr_results = xdrres; stat = CLNT_CALL(client, PMAPPROC_CALLIT, xdr_rmtcall_args, &a, xdr_rmtcallres, &r, tout); CLNT_DESTROY(client); } else { stat = RPC_FAILED; } (void)close(socket); addr->sin_port = 0; return (stat); } /* * XDR remote call arguments * written for XDR_ENCODE direction only */ bool_t xdr_rmtcall_args(xdrs, cap) register XDR *xdrs; register struct rmtcallargs *cap; { u_int lenposition, argposition, position; if (xdr_u_long(xdrs, &(cap->prog)) && xdr_u_long(xdrs, &(cap->vers)) && xdr_u_long(xdrs, &(cap->proc))) { lenposition = XDR_GETPOS(xdrs); if (! xdr_u_long(xdrs, &(cap->arglen))) return (FALSE); argposition = XDR_GETPOS(xdrs); if (! (*(cap->xdr_args))(xdrs, cap->args_ptr)) return (FALSE); position = XDR_GETPOS(xdrs); cap->arglen = (u_long)position - (u_long)argposition; XDR_SETPOS(xdrs, lenposition); if (! xdr_u_long(xdrs, &(cap->arglen))) return (FALSE); XDR_SETPOS(xdrs, position); return (TRUE); } return (FALSE); } /* * XDR remote call results * written for XDR_DECODE direction only */ bool_t xdr_rmtcallres(xdrs, crp) register XDR *xdrs; register struct rmtcallres *crp; { caddr_t port_ptr; port_ptr = (caddr_t)crp->port_ptr; if (xdr_reference(xdrs, &port_ptr, sizeof (u_long), xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) { crp->port_ptr = (u_long *)port_ptr; return ((*(crp->xdr_results))(xdrs, crp->results_ptr)); } return (FALSE); } /* * The following is kludged-up support for simple rpc broadcasts. * Someday a large, complicated system will replace these trivial * routines which only support udp/ip . */ static int getbroadcastnets(addrs, sock, buf) struct in_addr *addrs; int sock; /* any valid socket will do */ char *buf; /* why allocxate more when we can use existing... */ { struct ifconf ifc; struct ifreq ifreq, *ifr; struct sockaddr_in *sin; int n, i; ifc.ifc_len = UDPMSGSIZE; ifc.ifc_buf = buf; if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) { perror("broadcast: ioctl (get interface configuration)"); return (0); } ifr = ifc.ifc_req; for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) { ifreq = *ifr; if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) { perror("broadcast: ioctl (get interface flags)"); continue; } if ((ifreq.ifr_flags & IFF_BROADCAST) && (ifreq.ifr_flags & IFF_UP) && ifr->ifr_addr.sa_family == AF_INET) { sin = (struct sockaddr_in *)&ifr->ifr_addr; #ifdef SIOCGIFBRDADDR /* 4.3BSD */ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { addrs[i++] = inet_makeaddr(inet_netof (sin->sin_addr.s_addr), INADDR_ANY); } else { addrs[i++] = ((struct sockaddr_in*) &ifreq.ifr_addr)->sin_addr; } #else /* 4.2 BSD */ addrs[i++] = inet_makeaddr(inet_netof (sin->sin_addr.s_addr), INADDR_ANY); #endif } } return (i); } typedef bool_t (*resultproc_t)(); enum clnt_stat clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult) u_long prog; /* program number */ u_long vers; /* version number */ u_long proc; /* procedure number */ xdrproc_t xargs; /* xdr routine for args */ caddr_t argsp; /* pointer to args */ xdrproc_t xresults; /* xdr routine for results */ caddr_t resultsp; /* pointer to results */ resultproc_t eachresult; /* call with each result obtained */ { enum clnt_stat stat; AUTH *unix_auth = authunix_create_default(); XDR xdr_stream; register XDR *xdrs = &xdr_stream; int outlen, inlen, fromlen, nets; register int sock; #ifdef FD_SETSIZE fd_set mask; fd_set readfds; #else int readfds; register int mask; #endif /* def FD_SETSIZE */ register int i; bool_t done = FALSE; register u_long xid; u_long port; struct in_addr addrs[20]; struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ struct rmtcallargs a; struct rmtcallres r; struct rpc_msg msg; struct timeval t; char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; /* * initialization: create a socket, a broadcast address, and * preserialize the arguments into a send buffer. */ if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) { perror("Cannot create socket for broadcast rpc"); stat = RPC_CANTSEND; goto done_broad; } #ifdef FD_SETSIZE FD_ZERO(&mask); FD_SET(sock, &mask); #else mask = (1 << sock); #endif /* def FD_SETSIZE */ nets = getbroadcastnets(addrs, sock, inbuf); bzero((char *)&baddr, sizeof (baddr)); baddr.sin_family = AF_INET; baddr.sin_port = htons(PMAPPORT); baddr.sin_addr.s_addr = htonl(INADDR_ANY); /* baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */ (void)gettimeofday(&t, (struct timezone *)0); msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec; t.tv_usec = 0; msg.rm_direction = CALL; msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; msg.rm_call.cb_prog = PMAPPROG; msg.rm_call.cb_vers = PMAPVERS; msg.rm_call.cb_proc = PMAPPROC_CALLIT; msg.rm_call.cb_cred = unix_auth->ah_cred; msg.rm_call.cb_verf = unix_auth->ah_verf; a.prog = prog; a.vers = vers; a.proc = proc; a.xdr_args = xargs; a.args_ptr = argsp; r.port_ptr = &port; r.xdr_results = xresults; r.results_ptr = resultsp; xdrmem_create(xdrs, outbuf, MAX_BROADCAST_SIZE, XDR_ENCODE); if ((! xdr_callmsg(xdrs, &msg)) || (! xdr_rmtcall_args(xdrs, &a))) { stat = RPC_CANTENCODEARGS; goto done_broad; } outlen = (int)xdr_getpos(xdrs); xdr_destroy(xdrs); /* * Basic loop: broadcast a packet and wait a while for response(s). * The response timeout grows larger per iteration. */ for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) { for (i = 0; i < nets; i++) { baddr.sin_addr = addrs[i]; if (sendto(sock, outbuf, outlen, 0, (struct sockaddr *)&baddr, sizeof (struct sockaddr)) != outlen) { perror("Cannot send broadcast packet"); stat = RPC_CANTSEND; goto done_broad; } } if (eachresult == NULL) { stat = RPC_SUCCESS; goto done_broad; } recv_again: msg.acpted_rply.ar_verf = _null_auth; msg.acpted_rply.ar_results.where = (caddr_t)&r; msg.acpted_rply.ar_results.proc = xdr_rmtcallres; readfds = mask; switch (select(_rpc_dtablesize(), &readfds, (int *)NULL, (int *)NULL, &t)) { case 0: /* timed out */ stat = RPC_TIMEDOUT; continue; case -1: /* some kind of error */ if (errno == EINTR) goto recv_again; perror("Broadcast select problem"); stat = RPC_CANTRECV; goto done_broad; } /* end of select results switch */ try_again: fromlen = sizeof(struct sockaddr); inlen = recvfrom(sock, inbuf, UDPMSGSIZE, 0, (struct sockaddr *)&raddr, &fromlen); if (inlen < 0) { if (errno == EINTR) goto try_again; perror("Cannot receive reply to broadcast"); stat = RPC_CANTRECV; goto done_broad; } if (inlen < sizeof(u_long)) goto recv_again; /* * see if reply transaction id matches sent id. * If so, decode the results. */ xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE); if (xdr_replymsg(xdrs, &msg)) { if ((msg.rm_xid == xid) && (msg.rm_reply.rp_stat == MSG_ACCEPTED) && (msg.acpted_rply.ar_stat == SUCCESS)) { raddr.sin_port = htons((u_short)port); done = (*eachresult)(resultsp, &raddr); } /* otherwise, we just ignore the errors ... */ } else { #ifdef notdef /* some kind of deserialization problem ... */ if (msg.rm_xid == xid) fprintf(stderr, "Broadcast deserialization problem"); /* otherwise, just random garbage */ #endif } xdrs->x_op = XDR_FREE; msg.acpted_rply.ar_results.proc = xdr_void; (void)xdr_replymsg(xdrs, &msg); (void)(*xresults)(xdrs, resultsp); xdr_destroy(xdrs); if (done) { stat = RPC_SUCCESS; goto done_broad; } else { goto recv_again; } } done_broad: (void)close(sock); AUTH_DESTROY(unix_auth); return (stat); } Funky_Stuff len=`wc -c < pmap_rmt.c` if [ $len != 10900 ] ; then echo error: pmap_rmt.c was $len bytes long, should have been 10900 fi echo x - pmap_rmt.h cat > pmap_rmt.h <<'Funky_Stuff' /* @(#)pmap_rmt.h 1.1 87/11/04 3.9 RPCSRC */ /* * 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 */ /* @(#)pmap_rmt.h 1.1 87/01/13 SMI */ /* * Structures and XDR routines for parameters to and replies from * the portmapper remote-call-service. * * Copyright (C) 1986, Sun Microsystems, Inc. */ struct rmtcallargs { u_long prog, vers, proc, arglen; caddr_t args_ptr; xdrproc_t xdr_args; }; bool_t xdr_rmtcall_args(); struct rmtcallres { u_long *port_ptr; u_long resultslen; caddr_t results_ptr; xdrproc_t xdr_results; }; bool_t xdr_rmtcallres(); Funky_Stuff len=`wc -c < pmap_rmt.h` if [ $len != 1776 ] ; then echo error: pmap_rmt.h was $len bytes long, should have been 1776 fi echo x - rpc.h cat > rpc.h <<'Funky_Stuff' /* @(#)rpc.h 1.2 87/11/13 3.9 RPCSRC */ /* * 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 */ /* @(#)rpc.h 1.8 87/07/24 SMI */ /* * rpc.h, Just includes the billions of rpc header files necessary to * do remote procedure calling. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef __RPC_HEADER__ #define __RPC_HEADER__ #include <rpc/types.h> /* some typedefs */ #include <netinet/in.h> /* external data representation interfaces */ #include <rpc/xdr.h> /* generic (de)serializer */ /* Client side only authentication */ #include <rpc/auth.h> /* generic authenticator (client side) */ /* Client side (mostly) remote procedure call */ #include <rpc/clnt.h> /* generic rpc stuff */ /* semi-private protocol headers */ #include <rpc/rpc_msg.h> /* protocol for rpc messages */ #include <rpc/auth_unix.h> /* protocol for unix style cred */ /* Server side only remote procedure callee */ #include <rpc/svc.h> /* service manager and multiplexer */ #include <rpc/svc_auth.h> /* service side authenticator */ /* REMOVE NEXT INCLUDE IF RUNNING ON SUN OS */ /* routines for parsing /etc/rpc */ #include <rpc/netdb.h> /* structures and routines to parse /etc/rpc */ #endif /* ndef __RPC_HEADER__ */ Funky_Stuff len=`wc -c < rpc.h` if [ $len != 2427 ] ; then echo error: rpc.h was $len bytes long, should have been 2427 fi echo x - rpc_callmsg.c cat > rpc_callmsg.c <<'Funky_Stuff' /* @(#)rpc_callmsg.c 1.2 87/11/23 3.9 RPCSRC */ /* * 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[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro"; #endif /* * rpc_callmsg.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include <sys/param.h> #include <rpc/rpc.h> /* * XDR a call message */ bool_t xdr_callmsg(xdrs, cmsg) register XDR *xdrs; register struct rpc_msg *cmsg; { register long *buf; register struct opaque_auth *oa; if (xdrs->x_op == XDR_ENCODE) { if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { return (FALSE); } buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_cred.oa_length) + 2 * BYTES_PER_XDR_UNIT + RNDUP(cmsg->rm_call.cb_verf.oa_length)); if (buf != NULL) { IXDR_PUT_LONG(buf, cmsg->rm_xid); IXDR_PUT_ENUM(buf, cmsg->rm_direction); if (cmsg->rm_direction != CALL) { return (FALSE); } IXDR_PUT_LONG(buf, cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } IXDR_PUT_LONG(buf, cmsg->rm_call.cb_prog); IXDR_PUT_LONG(buf, cmsg->rm_call.cb_vers); IXDR_PUT_LONG(buf, cmsg->rm_call.cb_proc); oa = &cmsg->rm_call.cb_cred; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof (long); } oa = &cmsg->rm_call.cb_verf; IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (long); */ } return (TRUE); } } if (xdrs->x_op == XDR_DECODE) { buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT); if (buf != NULL) { cmsg->rm_xid = IXDR_GET_LONG(buf); cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); if (cmsg->rm_direction != CALL) { return (FALSE); } cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG(buf); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { return (FALSE); } cmsg->rm_call.cb_prog = IXDR_GET_LONG(buf); cmsg->rm_call.cb_vers = IXDR_GET_LONG(buf); cmsg->rm_call.cb_proc = IXDR_GET_LONG(buf); oa = &cmsg->rm_call.cb_cred; oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_LONG(buf); if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (caddr_t) mem_alloc(oa->oa_length); } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { return (FALSE); } } else { bcopy((caddr_t)buf, oa->oa_base, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (long); */ } } oa = &cmsg->rm_call.cb_verf; buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf == NULL) { if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE || xdr_u_int(xdrs, &oa->oa_length) == FALSE) { return (FALSE); } } else { oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = IXDR_GET_LONG(buf); } if (oa->oa_length) { if (oa->oa_length > MAX_AUTH_BYTES) { return (FALSE); } if (oa->oa_base == NULL) { oa->oa_base = (caddr_t) mem_alloc(oa->oa_length); } buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length)); if (buf == NULL) { if (xdr_opaque(xdrs, oa->oa_base, oa->oa_length) == FALSE) { return (FALSE); } } else { bcopy((caddr_t)buf, oa->oa_base, oa->oa_length); /* no real need... buf += RNDUP(oa->oa_length) / sizeof (long); */ } } return (TRUE); } } if ( xdr_u_long(xdrs, &(cmsg->rm_xid)) && xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && (cmsg->rm_direction == CALL) && xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) && xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) && xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) && xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) ) return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf))); return (FALSE); } Funky_Stuff len=`wc -c < rpc_callmsg.c` if [ $len != 5703 ] ; then echo error: rpc_callmsg.c was $len bytes long, should have been 5703 fi echo x - rpc_commondata.c cat > rpc_commondata.c <<'Funky_Stuff' /* @(#)rpc_commondata.c 1.2 87/11/09 3.9 RPCSRC */ /* * 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 */ #include <rpc/rpc.h> /* * This file should only contain common data (global data) that is exported * by public interfaces */ struct opaque_auth _null_auth; #ifdef FD_SETSIZE fd_set svc_fdset; #else int svc_fds; #endif /* def FD_SETSIZE */ struct rpc_createerr rpc_createerr; Funky_Stuff len=`wc -c < rpc_commondata.c` if [ $len != 1599 ] ; then echo error: rpc_commondata.c was $len bytes long, should have been 1599 fi echo x - rpc_dtablesize.c cat > rpc_dtablesize.c <<'Funky_Stuff' /* @(#)rpc_dtablesize.c 1.1 87/11/04 3.9 RPCSRC */ /* * 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[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro"; #endif /* * Cache the result of getdtablesize(), so we don't have to do an * expensive system call every time. */ _rpc_dtablesize() { static int size; if (size == 0) { size = getdtablesize(); } return (size); } Funky_Stuff len=`wc -c < rpc_dtablesize.c` if [ $len != 1663 ] ; then echo error: rpc_dtablesize.c was $len bytes long, should have been 1663 fi echo x - rpc_msg.h cat > rpc_msg.h <<'Funky_Stuff' /* @(#)rpc_msg.h 1.1 87/11/04 3.9 RPCSRC */ /* * 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 */ /* @(#)rpc_msg.h 1.7 86/07/16 SMI */ /* * rpc_msg.h * rpc message definition * * Copyright (C) 1984, Sun Microsystems, Inc. */ #define RPC_MSG_VERSION ((u_long) 2) #define RPC_SERVICE_PORT ((u_short) 2048) /* * Bottom up definition of an rpc message. * NOTE: call and reply use the same overall stuct but * different parts of unions within it. */ enum msg_type { CALL=0, REPLY=1 }; enum reply_stat { MSG_ACCEPTED=0, MSG_DENIED=1 }; enum accept_stat { SUCCESS=0, PROG_UNAVAIL=1, PROG_MISMATCH=2, PROC_UNAVAIL=3, GARBAGE_ARGS=4, SYSTEM_ERR=5 }; enum reject_stat { RPC_MISMATCH=0, AUTH_ERROR=1 }; /* * Reply part of an rpc exchange */ /* * Reply to an rpc request that was accepted by the server. * Note: there could be an error even though the request was * accepted. */ struct accepted_reply { struct opaque_auth ar_verf; enum accept_stat ar_stat; union { struct { u_long low; u_long high; } AR_versions; struct { caddr_t where; xdrproc_t proc; } AR_results; /* and many other null cases */ } ru; #define ar_results ru.AR_results #define ar_vers ru.AR_versions }; /* * Reply to an rpc request that was rejected by the server. */ struct rejected_reply { enum reject_stat rj_stat; union { struct { u_long low; u_long high; } RJ_versions; enum auth_stat RJ_why; /* why authentication did not work */ } ru; #define rj_vers ru.RJ_versions #define rj_why ru.RJ_why }; /* * Body of a reply to an rpc request. */ struct reply_body { enum reply_stat rp_stat; union { struct accepted_reply RP_ar; struct rejected_reply RP_dr; } ru; #define rp_acpt ru.RP_ar #define rp_rjct ru.RP_dr }; /* * Body of an rpc request call. */ struct call_body { u_long cb_rpcvers; /* must be equal to two */ u_long cb_prog; u_long cb_vers; u_long cb_proc; struct opaque_auth cb_cred; struct opaque_auth cb_verf; /* protocol specific - provided by client */ }; /* * The rpc message */ struct rpc_msg { u_long rm_xid; enum msg_type rm_direction; union { struct call_body RM_cmb; struct reply_body RM_rmb; } ru; #define rm_call ru.RM_cmb #define rm_reply ru.RM_rmb }; #define acpted_rply ru.RM_rmb.ru.RP_ar #define rjcted_rply ru.RM_rmb.ru.RP_dr /* * XDR routine to handle a rpc message. * xdr_callmsg(xdrs, cmsg) * XDR *xdrs; * struct rpc_msg *cmsg; */ extern bool_t xdr_callmsg(); /* * XDR routine to pre-serialize the static part of a rpc message. * xdr_callhdr(xdrs, cmsg) * XDR *xdrs; * struct rpc_msg *cmsg; */ extern bool_t xdr_callhdr(); /* * XDR routine to handle a rpc reply. * xdr_replymsg(xdrs, rmsg) * XDR *xdrs; * struct rpc_msg *rmsg; */ extern bool_t xdr_replymsg(); /* * Fills in the error part of a reply message. * _seterr_reply(msg, error) * struct rpc_msg *msg; * struct rpc_err *error; */ extern void _seterr_reply(); Funky_Stuff len=`wc -c < rpc_msg.h` if [ $len != 4178 ] ; then echo error: rpc_msg.h was $len bytes long, should have been 4178 fi echo x - rpc_prot.c cat > rpc_prot.c <<'Funky_Stuff' /* @(#)rpc_prot.c 1.2 87/11/23 3.9 RPCSRC */ /* * 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[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro"; #endif /* * rpc_prot.c * * Copyright (C) 1984, Sun Microsystems, Inc. * * This set of routines implements the rpc message definition, * its serializer and some common rpc utility routines. * The routines are meant for various implementations of rpc - * they are NOT for the rpc client or rpc service implementations! * Because authentication stuff is easy and is part of rpc, the opaque * routines are also in this program. */ #include <sys/param.h> #include <rpc/rpc.h> /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ struct opaque_auth _null_auth; /* * XDR an opaque authentication struct * (see auth.h) */ bool_t xdr_opaque_auth(xdrs, ap) register XDR *xdrs; register struct opaque_auth *ap; { if (xdr_enum(xdrs, &(ap->oa_flavor))) return (xdr_bytes(xdrs, &ap->oa_base, &ap->oa_length, MAX_AUTH_BYTES)); return (FALSE); } /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ /* * XDR the MSG_ACCEPTED part of a reply message union */ bool_t xdr_accepted_reply(xdrs, ar) register XDR *xdrs; register struct accepted_reply *ar; { /* personalized union, rather than calling xdr_union */ if (! xdr_opaque_auth(xdrs, &(ar->ar_verf))) return (FALSE); if (! xdr_enum(xdrs, (enum_t *)&(ar->ar_stat))) return (FALSE); switch (ar->ar_stat) { case SUCCESS: return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); case PROG_MISMATCH: if (! xdr_u_long(xdrs, &(ar->ar_vers.low))) return (FALSE); return (xdr_u_long(xdrs, &(ar->ar_vers.high))); } return (TRUE); /* TRUE => open ended set of problems */ } /* * XDR the MSG_DENIED part of a reply message union */ bool_t xdr_rejected_reply(xdrs, rr) register XDR *xdrs; register struct rejected_reply *rr; { /* personalized union, rather than calling xdr_union */ if (! xdr_enum(xdrs, (enum_t *)&(rr->rj_stat))) return (FALSE); switch (rr->rj_stat) { case RPC_MISMATCH: if (! xdr_u_long(xdrs, &(rr->rj_vers.low))) return (FALSE); return (xdr_u_long(xdrs, &(rr->rj_vers.high))); case AUTH_ERROR: return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); } return (FALSE); } static struct xdr_discrim reply_dscrm[3] = { { (int)MSG_ACCEPTED, xdr_accepted_reply }, { (int)MSG_DENIED, xdr_rejected_reply }, { __dontcare__, NULL_xdrproc_t } }; /* * XDR a reply message */ bool_t xdr_replymsg(xdrs, rmsg) register XDR *xdrs; register struct rpc_msg *rmsg; { if ( xdr_u_long(xdrs, &(rmsg->rm_xid)) && xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) && (rmsg->rm_direction == REPLY) ) return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), (caddr_t)&(rmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); return (FALSE); } /* * Serializes the "static part" of a call message header. * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers. * The rm_xid is not really static, but the user can easily munge on the fly. */ bool_t xdr_callhdr(xdrs, cmsg) register XDR *xdrs; register struct rpc_msg *cmsg; { cmsg->rm_direction = CALL; cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; if ( (xdrs->x_op == XDR_ENCODE) && xdr_u_long(xdrs, &(cmsg->rm_xid)) && xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) ) return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers))); return (FALSE); } /* ************************** Client utility routine ************* */ static void accepted(acpt_stat, error) register enum accept_stat acpt_stat; register struct rpc_err *error; { switch (acpt_stat) { case PROG_UNAVAIL: error->re_status = RPC_PROGUNAVAIL; return; case PROG_MISMATCH: error->re_status = RPC_PROGVERSMISMATCH; return; case PROC_UNAVAIL: error->re_status = RPC_PROCUNAVAIL; return; case GARBAGE_ARGS: error->re_status = RPC_CANTDECODEARGS; return; case SYSTEM_ERR: error->re_status = RPC_SYSTEMERROR; return; case SUCCESS: error->re_status = RPC_SUCCESS; return; } /* something's wrong, but we don't know what ... */ error->re_status = RPC_FAILED; error->re_lb.s1 = (long)MSG_ACCEPTED; error->re_lb.s2 = (long)acpt_stat; } static void rejected(rjct_stat, error) register enum reject_stat rjct_stat; register struct rpc_err *error; { switch (rjct_stat) { case RPC_VERSMISMATCH: error->re_status = RPC_VERSMISMATCH; return; case AUTH_ERROR: error->re_status = RPC_AUTHERROR; return; } /* something's wrong, but we don't know what ... */ error->re_status = RPC_FAILED; error->re_lb.s1 = (long)MSG_DENIED; error->re_lb.s2 = (long)rjct_stat; } /* * given a reply message, fills in the error */ void _seterr_reply(msg, error) register struct rpc_msg *msg; register struct rpc_err *error; { /* optimized for normal, SUCCESSful case */ switch (msg->rm_reply.rp_stat) { case MSG_ACCEPTED: if (msg->acpted_rply.ar_stat == SUCCESS) { error->re_status = RPC_SUCCESS; return; }; accepted(msg->acpted_rply.ar_stat, error); break; case MSG_DENIED: rejected(msg->rjcted_rply.rj_stat, error); break; default: error->re_status = RPC_FAILED; error->re_lb.s1 = (long)(msg->rm_reply.rp_stat); break; } switch (error->re_status) { case RPC_VERSMISMATCH: error->re_vers.low = msg->rjcted_rply.rj_vers.low; error->re_vers.high = msg->rjcted_rply.rj_vers.high; break; case RPC_AUTHERROR: error->re_why = msg->rjcted_rply.rj_why; break; case RPC_PROGVERSMISMATCH: error->re_vers.low = msg->acpted_rply.ar_vers.low; error->re_vers.high = msg->acpted_rply.ar_vers.high; break; } } Funky_Stuff len=`wc -c < rpc_prot.c` if [ $len != 7053 ] ; then echo error: rpc_prot.c was $len bytes long, should have been 7053 fi echo x - svc.c cat > svc.c <<'Funky_Stuff' /* @(#)svc.c 1.4 87/11/16 3.9 RPCSRC */ /* * 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 <sys/errno.h> #include <sys/time.h> #include <rpc/rpc.h> #include <rpc/pmap_clnt.h> extern int errno; #ifdef FD_SETSIZE static SVCXPRT **xports; #else #define NOFILE 32 static SVCXPRT *xports[NOFILE]; #endif /* def FD_SETSIZE */ #define NULL_SVC ((struct svc_callout *)0) #define RQCRED_SIZE 400 /* this size is excessive */ /* * The services list * Each entry represents a set of procedures (an rpc program). * The dispatch routine takes request structs and runs the * apropriate procedure. */ static struct svc_callout { struct svc_callout *sc_next; u_long sc_prog; u_long sc_vers; void (*sc_dispatch)(); } *svc_head; static struct svc_callout *svc_find(); /* *************** SVCXPRT related stuff **************** */ /* * Activate a transport handle. */ void xprt_register(xprt) SVCXPRT *xprt; { register int sock = xprt->xp_sock; #ifdef FD_SETSIZE if (xports == NULL) { xports = (SVCXPRT **) mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); } if (sock < _rpc_dtablesize()) { xports[sock] = xprt; FD_SET(sock, &svc_fdset); } #else if (sock < NOFILE) { xports[sock] = xprt; svc_fds |= (1 << sock); } #endif /* def FD_SETSIZE */ } /* * De-activate a transport handle. */ void xprt_unregister(xprt) SVCXPRT *xprt; { register int sock = xprt->xp_sock; #ifdef FD_SETSIZE if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) { xports[sock] = (SVCXPRT *)0; FD_CLR(sock, &svc_fdset); } #else if ((sock < NOFILE) && (xports[sock] == xprt)) { xports[sock] = (SVCXPRT *)0; svc_fds &= ~(1 << sock); } #endif /* def FD_SETSIZE */ } /* ********************** CALLOUT list related stuff ************* */ /* * Add a service program to the callout list. * The dispatch routine will be called when a rpc request for this * program number comes in. */ bool_t svc_register(xprt, prog, vers, dispatch, protocol) SVCXPRT *xprt; u_long prog; u_long vers; void (*dispatch)(); int protocol; { struct svc_callout *prev; register struct svc_callout *s; if ((s = svc_find(prog, vers, &prev)) != NULL_SVC) { if (s->sc_dispatch == dispatch) goto pmap_it; /* he is registering another xptr */ return (FALSE); } s = (struct svc_callout *)mem_alloc(sizeof(struct svc_callout)); if (s == (struct svc_callout *)0) { return (FALSE); } s->sc_prog = prog; s->sc_vers = vers; s->sc_dispatch = dispatch; s->sc_next = svc_head; svc_head = s; pmap_it: /* now register the information with the local binder service */ if (protocol) { return (pmap_set(prog, vers, protocol, xprt->xp_port)); } return (TRUE); } /* * Remove a service program from the callout list. */ void svc_unregister(prog, vers) u_long prog; u_long vers; { struct svc_callout *prev; register struct svc_callout *s; if ((s = svc_find(prog, vers, &prev)) == NULL_SVC) return; if (prev == NULL_SVC) { svc_head = s->sc_next; } else { prev->sc_next = s->sc_next; } s->sc_next = NULL_SVC; mem_free((char *) s, (u_int) sizeof(struct svc_callout)); /* now unregister the information with the local binder service */ (void)pmap_unset(prog, vers); } /* * Search the callout list for a program number, return the callout * struct. */ static struct svc_callout * svc_find(prog, vers, prev) u_long prog; u_long vers; struct svc_callout **prev; { register struct svc_callout *s, *p; p = NULL_SVC; for (s = svc_head; s != NULL_SVC; s = s->sc_next) { if ((s->sc_prog == prog) && (s->sc_vers == vers)) goto done; p = s; } done: *prev = p; return (s); } /* ******************* 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); } /* ******************* SERVER INPUT STUFF ******************* */ /* * Get server side input from some transport. * * Statement of authentication parameters management: * This function owns and manages all authentication parameters, specifically * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and * the "cooked" credentials (rqst->rq_clntcred). * However, this function does not know the structure of the cooked * credentials, so it make the following assumptions: * a) the structure is contiguous (no pointers), and * b) the cred structure size does not exceed RQCRED_SIZE bytes. * In all events, all three parameters are freed upon exit from this routine. * The storage is trivially management on the call stack in user land, but * is mallocated in kernel land. */ void svc_getreq(rdfds) int rdfds; { #ifdef FD_SETSIZE fd_set readfds; FD_ZERO(&readfds); readfds.fds_bits[0] = rdfds; svc_getreqset(&readfds); #else int readfds = rdfds & svc_fds; svc_getreqset(&readfds); #endif /* def FD_SETSIZE */ } void svc_getreqset(readfds) #ifdef FD_SETSIZE fd_set *readfds; { #else int *readfds; { int readfds_local = *readfds; #endif /* def FD_SETSIZE */ register enum xprt_stat stat; struct rpc_msg msg; int prog_found; int u_long low_vers; u_long high_vers; struct svc_req r; register int sock; register SVCXPRT *xprt; char cred_area[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]); #ifdef FD_SETSIZE for (sock = 0; sock < FD_SETSIZE; sock++) { if (FD_ISSET(sock, readfds) && FD_ISSET(sock, &svc_fdset)) { #else for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) { if ((readfds_local & 1) != 0) { #endif /* def FD_SETSIZE */ /* sock has input waiting */ xprt = xports[sock]; /* now receive msgs from xprtprt (support batch calls) */ do { 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); goto call_done; } /* now match message with a registered service*/ prog_found = FALSE; low_vers = 0 - 1; high_vers = 0; for (s = svc_head; s != NULL_SVC; s = s->sc_next) { if (s->sc_prog == r.rq_prog) { if (s->sc_vers == r.rq_vers) { (*s->sc_dispatch)(&r, xprt); goto call_done; } /* found correct version */ prog_found = TRUE; if (s->sc_vers < low_vers) low_vers = s->sc_vers; if (s->sc_vers > high_vers) high_vers = s->sc_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); /* Fall through to ... */ } call_done: if ((stat = SVC_STAT(xprt)) == XPRT_DIED){ SVC_DESTROY(xprt); break; } } while (stat == XPRT_MOREREQS); } } } Funky_Stuff len=`wc -c < svc.c` if [ $len != 11186 ] ; then echo error: svc.c was $len bytes long, should have been 11186 fi cd .. echo more files to follow exit -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.