Moving Sun RPC code into libc, part 1. Based on work done by a number of

people, including J.T. Conklin, Theo de Raadt, Paul Richards, and probably
someone else who's going to flame me as soon as they see this message.
This commit is contained in:
Garrett Wollman 1994-08-07 18:36:12 +00:00
parent e99a5be395
commit 990647991e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=1901
41 changed files with 8555 additions and 0 deletions

28
lib/libc/rpc/DISCLAIMER Normal file
View File

@ -0,0 +1,28 @@
/*
* 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
*/

39
lib/libc/rpc/Makefile.inc Normal file
View File

@ -0,0 +1,39 @@
# @(#)Makefile 5.11 (Berkeley) 9/6/90
.PATH: ${.CURDIR}/rpc ${.CURDIR}/.
CFLAGS+=-I${.CURDIR} -I${.CURDIR}/rpc
SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \
clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \
pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \
svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_mem.c \
xdr_rec.c xdr_reference.c xdr_stdio.c
#
# XXX -- rstat.1 and rstat_svc.8 shouldn't really be here
# but there's no rstat command, don't know why, so I'm
# leaving them here in case they're needed sometime later.
# Paul.
#
MAN1+= rpc/rstat.1
MAN3+= rpc/bindresvport.3 rpc/getrpcent.3 rpc/getrpcport.3 rpc/rpc.3 rpc/xdr.3
MAN5+= rpc/rpc.5
MAN8+= rpc/rstat_svc.8
UNSUPPORTED+= xdr_float.c
HDRS+= auth.h auth_unix.h clnt.h pmap_clnt.h \
pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h
beforeinstall: ${HDRS}
@-if [ ! -d ${DESTDIR}/usr/include/rpc ]; then \
mkdir ${DESTDIR}/usr/include/rpc; \
chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/include/rpc; \
chmod 755 ${DESTDIR}/usr/include/rpc; \
fi
cd ${.CURDIR}/rpc; install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${HDRS} \
${DESTDIR}/usr/include/rpc

233
lib/libc/rpc/README Normal file
View File

@ -0,0 +1,233 @@
RPCSRC 4.0 7/11/89
This distribution contains Sun Microsystem's implementation of the
RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD. Also
included is complete documentation, utilities, RPC service
specification files, and demonstration services in the format used by
the RPC protocol compiler (rpcgen). See WHAT'S NEW below for
details.
NOTE ABOUT SECURE RPC:
This release of RPCSRC contains most of the code needed to implement
Secure RPC (see "DES Authentication" in the RPC Protocol Specification,
doc/rpc.rfc.ms). Due to legal considerations, we are unable to
distribute an implementation of DES, the Data Encryption Standard, which
Secure RPC requires. For this reason, all of the files, documentation, and
programs associated with Secure RPC have been placed into a separate
directory, secure_rpc. The RPC library contained in the main body of this
release *DOES NOT* support Secure RPC. See secure_rpc/README for more
details. (A DES library was posted in Volume 18 of comp.sources.unix.)
If you wish to report bugs found in this release, send mail to:
Portable ONC/NFS
Sun Microsystems, Inc
MS 12-33
2550 Garcia Avenue
Mountain View, CA 94043
or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet).
ROADMAP
The directory hierarchy is as follows:
demo/ Various demonstration services
demo/dir Remote directory lister
demo/msg Remote console message delivery service
demo/sort Remote sort service
doc/ Documentation for RPC, XDR and NFS in "-ms" format.
etc/ Utilities (rpcinfo and portmap). portmap must be
started by root before any other RPC network services are
used. SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER.
man/ Manual pages for RPC library, rpcgen, and utilities.
rpc/ The RPC and XDR library. SEE BELOW
FOR BUGFIX TO 4.2BSD COMPILER.
rpcgen/ The RPC Language compiler (for .x files)
rpcsvc/ Service definition files for various services and the
server and client code for the Remote Status service.
secure_rpc/ The files in this directory are used to build a version of
the RPC library with DES Authentication. See the README
file in that directory for more details.
BUILD INSTRUCTIONS
Makefiles can be found in all directories except for man. The
Makefile in the top directory will cause these others to be invoked
(except for in the doc, man and demo directories), in turn building the
entire release.
WARNING! THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES
IN /usr/include, /usr/lib, /usr/bin and /etc.
The master RPC include file, rpc/rpc.h, is used by all programs and
routines that use RPC. It includes other RPC and system include files
needed by the RPC system. PLEASE NOTE: If your system has NFS, it
may have been based on Sun's NFS Source. The include files installed
by this package may duplicate include files you will find on your NFS
system. The RPCSRC 4.0 include files are upwardly compatible to all
NFS Source include files as of the date of this distribution (not
including any new definitions or declarations added by your system
vendor). HOWEVER: Please read the comments towards the end of
rpc/rpc.h regarding rpc/netdb.h. You may need to uncomment the
inclusion of that file if the structures it defines are already
defined by your system's include files.
After making any compiler fixes that are needed (see below), at
the top directory, type:
make install
For all installations, the Makefile macro DESTDIR is prepended to the
installation path. It is defined to be null in the Makefiles, so
installations are relative to root. (You will probably need root
privileges for installing the files under the default path.) To
install the files under some other tree (e.g., /usr/local), use the
command:
make install DESTDIR=/usr/local
This will place the include files in /usr/local/usr/include, the RPC
library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the
utilities in /usr/local/etc. You'll have to edit the Makefiles or
install the files by hand if you want to do anything other than this
kind of relocation of the installation tree.
The RPC library will be built and installed first. By default it is
installed in /usr/lib as "librpclib.a". The directory
/usr/include/rpc will also be created, and several header files will
be installed there. ALL RPC SERVICES INCLUDE THESE HEADER FILES.
The programs in etc/ link in routines from librpclib.a. If you change
where it is installed, be sure to edit etc/'s Makefile to reflect this.
These programs are installed in /etc. PORTMAP MUST BE RUNNING ON
YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE.
rpcgen is installed in /usr/bin. This program is required to build
the demonstration services in demo and the rstat client and server in
rpcsvc/.
The rpcsvc/ directory will install its files in the directory
/usr/include/rpcsvc. The Remote Status service (rstat_svc) will be
compiled and installed in /etc. If you wish to make this service
available, you should either start this service when needed or have
it started at boot time by invoking it in your /etc/rc.local script.
(Be sure that portmap is started first!) Sun has modified its
version of inetd to automatically start RPC services. (Use "make
LIB=" when building rstat on a Sun Workstation.) The Remote Status
client (rstat) will be installed in /usr/bin. This program queries
the rstat_svc on a remote host and prints a system status summary
similar to the one printed by "uptime".
The documentation is not built during the "make install" command.
Typing "make" in the doc directory will cause all of the manuals to
be formatted using nroff into a single file. We have had a report
that certain "troff" equivalents have trouble processing the full
manual. If you have trouble, try building the manuals individually
(see the Makefile).
The demonstration services in the demo directory are not built by the
top-level "make install" command. To build these, cd to the demo
directory and enter "make". The three services will be built.
RPCGEN MUST BE INSTALLED in a path that make can find. To run the
services, start the portmap program as root and invoke the service
(you probably will want to put it in the background). rpcinfo can be
used to check that the service succeeded in getting registered with
portmap, and to ping the service (see rpcinfo's man page). You can
then use the corresponding client program to exercise the service.
To build these services on a Sun workstation, you must prevent the
Makefile from trying to link the RPC library (as these routines are
already a part of Sun's libc). Use: "make LIB=".
BUGFIX FOR 4.3BSD COMPILER
The use of a 'void *' declaration for one of the arguments in
the reply_proc() procedure in etc/rpcinfo.c will trigger a bug
in the 4.3BSD compiler. The bug is fixed by the following change to
the compiler file mip/manifest.h:
*** manifest.h.r1.1 Thu Apr 30 13:52:25 1987
--- manifest.h.r1.2 Mon Nov 23 18:58:17 1987
***************
*** 21,27 ****
/*
* Bogus type values
*/
! #define TNULL PTR /* pointer to UNDEF */
#define TVOID FTN /* function returning UNDEF (for void) */
/*
--- 21,27 ----
/*
* Bogus type values
*/
! #define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
#define TVOID FTN /* function returning UNDEF (for void) */
/*
If you cannot fix your compiler, change the declaration in reply_proc()
from 'void *' to 'char *'.
BUGFIX FOR 4.2BSD COMPILER
Unpatched 4.2BSD compilers complain about valid C. You can make old
compilers happy by changing some voids to ints. However, the fix to
the 4.2 VAX compiler is as follows (to mip/trees.c):
*** trees.c.r1.1 Mon May 11 13:47:58 1987
--- trees.c.r1.2 Wed Jul 2 18:28:52 1986
***************
*** 1247,1253 ****
if(o==CAST && mt1==0)return(TYPL+TYMATCH);
if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
! else if( mt12 == 0 ) break;
else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
break;
--- 1261,1269 ----
if(o==CAST && mt1==0)return(TYPL+TYMATCH);
if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
! /* if right is TVOID and looks like a CALL, is not ok */
! else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL))
! break;
else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
break;
WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0
The previous release was RPCSRC 3.9. As with all previous releases,
this release is based directly on files from Sun Microsystem's
implementation.
Upgrade from RPCSRC 3.9
1) RPCSRC 4.0 upgrades RPCSRC 3.9. Improvements from SunOS 4.0 have
been integrated into this release.
Secure RPC (in the secure_rpc/ directory)
2) DES Authentication routines and programs are provided.
3) A new manual, "Secure NFS" is provided, which describes Secure RPC
and Secure NFS.
4) Skeleton routines and manual pages are provided which describe the
DES encryption procedures required by Secure RPC. HOWEVER, NO DES
ROUTINE IS PROVIDED.
New Functionality
5) rpcinfo can now be used to de-register services from the portmapper
which may have terminated abnormally.
6) A new client, rstat, is provided which queries the rstat_svc and
prints a status line similar to the one displayed by "uptime".

135
lib/libc/rpc/auth_none.c Normal file
View File

@ -0,0 +1,135 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: auth_none.c,v 1.1 1993/10/27 05:40:10 paul Exp $";
#endif
/*
* auth_none.c
* Creates a client authentication handle for passing "null"
* credentials and verifiers to remote systems.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#define MAX_MARSHEL_SIZE 20
/*
* Authenticator operations routines
*/
static void authnone_verf();
static void authnone_destroy();
static bool_t authnone_marshal();
static bool_t authnone_validate();
static bool_t authnone_refresh();
static struct auth_ops ops = {
authnone_verf,
authnone_marshal,
authnone_validate,
authnone_refresh,
authnone_destroy
};
static struct authnone_private {
AUTH no_client;
char marshalled_client[MAX_MARSHEL_SIZE];
u_int mcnt;
} *authnone_private;
AUTH *
authnone_create()
{
register struct authnone_private *ap = authnone_private;
XDR xdr_stream;
register XDR *xdrs;
if (ap == 0) {
ap = (struct authnone_private *)calloc(1, sizeof (*ap));
if (ap == 0)
return (0);
authnone_private = ap;
}
if (!ap->mcnt) {
ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
ap->no_client.ah_ops = &ops;
xdrs = &xdr_stream;
xdrmem_create(xdrs, ap->marshalled_client, (u_int)MAX_MARSHEL_SIZE,
XDR_ENCODE);
(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
(void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
ap->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
}
return (&ap->no_client);
}
/*ARGSUSED*/
static bool_t
authnone_marshal(client, xdrs)
AUTH *client;
XDR *xdrs;
{
register struct authnone_private *ap = authnone_private;
if (ap == 0)
return (0);
return ((*xdrs->x_ops->x_putbytes)(xdrs,
ap->marshalled_client, ap->mcnt));
}
static void
authnone_verf()
{
}
static bool_t
authnone_validate()
{
return (TRUE);
}
static bool_t
authnone_refresh()
{
return (FALSE);
}
static void
authnone_destroy()
{
}

322
lib/libc/rpc/auth_unix.c Normal file
View File

@ -0,0 +1,322 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: auth_unix.c,v 1.1 1993/10/27 05:40:11 paul Exp $";
#endif
/*
* auth_unix.c, Implements UNIX style authentication parameters.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* The system is very weak. The client uses no encryption for it's
* credentials and only sends null verifiers. The server sends backs
* null verifiers or optionally a verifier that suggests a new short hand
* for the credentials.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
/*
* Unix authenticator operations vector
*/
static void authunix_nextverf();
static bool_t authunix_marshal();
static bool_t authunix_validate();
static bool_t authunix_refresh();
static void authunix_destroy();
static struct auth_ops auth_unix_ops = {
authunix_nextverf,
authunix_marshal,
authunix_validate,
authunix_refresh,
authunix_destroy
};
/*
* This struct is pointed to by the ah_private field of an auth_handle.
*/
struct audata {
struct opaque_auth au_origcred; /* original credentials */
struct opaque_auth au_shcred; /* short hand cred */
u_long au_shfaults; /* short hand cache faults */
char au_marshed[MAX_AUTH_BYTES];
u_int au_mpos; /* xdr pos at end of marshed */
};
#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
static bool_t marshal_new_auth();
/*
* Create a unix style authenticator.
* Returns an auth handle with the given stuff in it.
*/
AUTH *
authunix_create(machname, uid, gid, len, aup_gids)
char *machname;
int uid;
int gid;
register int len;
int *aup_gids;
{
struct authunix_parms aup;
char mymem[MAX_AUTH_BYTES];
struct timeval now;
XDR xdrs;
register AUTH *auth;
register struct audata *au;
/*
* Allocate and set up auth handle
*/
auth = (AUTH *)mem_alloc(sizeof(*auth));
#ifndef KERNEL
if (auth == NULL) {
(void)fprintf(stderr, "authunix_create: out of memory\n");
return (NULL);
}
#endif
au = (struct audata *)mem_alloc(sizeof(*au));
#ifndef KERNEL
if (au == NULL) {
(void)fprintf(stderr, "authunix_create: out of memory\n");
return (NULL);
}
#endif
auth->ah_ops = &auth_unix_ops;
auth->ah_private = (caddr_t)au;
auth->ah_verf = au->au_shcred = _null_auth;
au->au_shfaults = 0;
/*
* fill in param struct from the given params
*/
(void)gettimeofday(&now, (struct timezone *)0);
aup.aup_time = now.tv_sec;
aup.aup_machname = machname;
aup.aup_uid = uid;
aup.aup_gid = gid;
aup.aup_len = (u_int)len;
aup.aup_gids = aup_gids;
/*
* Serialize the parameters into origcred
*/
xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
if (! xdr_authunix_parms(&xdrs, &aup))
abort();
au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
au->au_origcred.oa_flavor = AUTH_UNIX;
#ifdef KERNEL
au->au_origcred.oa_base = mem_alloc((u_int) len);
#else
if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
(void)fprintf(stderr, "authunix_create: out of memory\n");
return (NULL);
}
#endif
bcopy(mymem, au->au_origcred.oa_base, (u_int)len);
/*
* set auth handle to reflect new cred.
*/
auth->ah_cred = au->au_origcred;
marshal_new_auth(auth);
return (auth);
}
/*
* Returns an auth handle with parameters determined by doing lots of
* syscalls.
*/
AUTH *
authunix_create_default()
{
register int len;
char machname[MAX_MACHINE_NAME + 1];
register int uid;
register int gid;
int gids[NGRPS];
if (gethostname(machname, MAX_MACHINE_NAME) == -1)
abort();
machname[MAX_MACHINE_NAME] = 0;
uid = geteuid();
gid = getegid();
if ((len = getgroups(NGRPS, gids)) < 0)
abort();
return (authunix_create(machname, uid, gid, len, gids));
}
/*
* authunix operations
*/
static void
authunix_nextverf(auth)
AUTH *auth;
{
/* no action necessary */
}
static bool_t
authunix_marshal(auth, xdrs)
AUTH *auth;
XDR *xdrs;
{
register struct audata *au = AUTH_PRIVATE(auth);
return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
}
static bool_t
authunix_validate(auth, verf)
register AUTH *auth;
struct opaque_auth verf;
{
register struct audata *au;
XDR xdrs;
if (verf.oa_flavor == AUTH_SHORT) {
au = AUTH_PRIVATE(auth);
xdrmem_create(&xdrs, verf.oa_base, verf.oa_length, XDR_DECODE);
if (au->au_shcred.oa_base != NULL) {
mem_free(au->au_shcred.oa_base,
au->au_shcred.oa_length);
au->au_shcred.oa_base = NULL;
}
if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
auth->ah_cred = au->au_shcred;
} else {
xdrs.x_op = XDR_FREE;
(void)xdr_opaque_auth(&xdrs, &au->au_shcred);
au->au_shcred.oa_base = NULL;
auth->ah_cred = au->au_origcred;
}
marshal_new_auth(auth);
}
return (TRUE);
}
static bool_t
authunix_refresh(auth)
register AUTH *auth;
{
register struct audata *au = AUTH_PRIVATE(auth);
struct authunix_parms aup;
struct timeval now;
XDR xdrs;
register int stat;
if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
/* there is no hope. Punt */
return (FALSE);
}
au->au_shfaults ++;
/* first deserialize the creds back into a struct authunix_parms */
aup.aup_machname = NULL;
aup.aup_gids = (int *)NULL;
xdrmem_create(&xdrs, au->au_origcred.oa_base,
au->au_origcred.oa_length, XDR_DECODE);
stat = xdr_authunix_parms(&xdrs, &aup);
if (! stat)
goto done;
/* update the time and serialize in place */
(void)gettimeofday(&now, (struct timezone *)0);
aup.aup_time = now.tv_sec;
xdrs.x_op = XDR_ENCODE;
XDR_SETPOS(&xdrs, 0);
stat = xdr_authunix_parms(&xdrs, &aup);
if (! stat)
goto done;
auth->ah_cred = au->au_origcred;
marshal_new_auth(auth);
done:
/* free the struct authunix_parms created by deserializing */
xdrs.x_op = XDR_FREE;
(void)xdr_authunix_parms(&xdrs, &aup);
XDR_DESTROY(&xdrs);
return (stat);
}
static void
authunix_destroy(auth)
register AUTH *auth;
{
register struct audata *au = AUTH_PRIVATE(auth);
mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
if (au->au_shcred.oa_base != NULL)
mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
mem_free(auth->ah_private, sizeof(struct audata));
if (auth->ah_verf.oa_base != NULL)
mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
mem_free((caddr_t)auth, sizeof(*auth));
}
/*
* Marshals (pre-serializes) an auth struct.
* sets private data, au_marshed and au_mpos
*/
static bool_t
marshal_new_auth(auth)
register AUTH *auth;
{
XDR xdr_stream;
register XDR *xdrs = &xdr_stream;
register struct audata *au = AUTH_PRIVATE(auth);
xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
(! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) {
perror("auth_none.c - Fatal marshalling problem");
} else {
au->au_mpos = XDR_GETPOS(xdrs);
}
XDR_DESTROY(xdrs);
}

View File

@ -0,0 +1,68 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: authunix_prot.c,v 1.1 1993/10/27 05:40:15 paul Exp $";
#endif
/*
* authunix_prot.c
* XDR for UNIX style authentication parameters for RPC
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
/*
* XDR for unix authentication parameters.
*/
bool_t
xdr_authunix_parms(xdrs, p)
register XDR *xdrs;
register struct authunix_parms *p;
{
if (xdr_u_long(xdrs, &(p->aup_time))
&& xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
&& xdr_int(xdrs, &(p->aup_uid))
&& xdr_int(xdrs, &(p->aup_gid))
&& xdr_array(xdrs, (caddr_t *)&(p->aup_gids),
&(p->aup_len), NGRPS, sizeof(int), xdr_int) ) {
return (TRUE);
}
return (FALSE);
}

View File

@ -0,0 +1,27 @@
.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
.TH BINDRESVPORT 3N "22 november 1987"
.SH NAME
bindresvport \- bind a socket to a privileged IP port
.SH SYNOPSIS
.nf
.B #include <sys/types.h>
.B #include <netinet/in.h>
.LP
.B int bindresvport(sd, sin)
.B int sd;
.B struct sockaddr_in \(**sin;
.fi
.SH DESCRIPTION
.LP
.B bindresvport(\|)
is used to bind a socket descriptor to a privileged
.SM IP
port, that is, a
port number in the range 0-1023.
The routine returns 0 if it is successful,
otherwise \-1 is returned and
.B errno
set to reflect the cause of the error.
.LP
Only root can bind to a privileged port; this call will fail for any
other users.

View File

@ -0,0 +1,84 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/
/*static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: bindresvport.c,v 1.1 1993/10/27 05:40:17 paul Exp $";
#endif
/*
* Copyright (c) 1987 by Sun Microsystems, Inc.
*/
#include <sys/types.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
/*
* Bind a socket to a privileged IP port
*/
bindresvport(sd, sin)
int sd;
struct sockaddr_in *sin;
{
int res;
static short port;
struct sockaddr_in myaddr;
extern int errno;
int i;
#define STARTPORT 600
#define ENDPORT (IPPORT_RESERVED - 1)
#define NPORTS (ENDPORT - STARTPORT + 1)
if (sin == (struct sockaddr_in *)0) {
sin = &myaddr;
bzero(sin, sizeof (*sin));
sin->sin_family = AF_INET;
} else if (sin->sin_family != AF_INET) {
errno = EPFNOSUPPORT;
return (-1);
}
if (port == 0) {
port = (getpid() % NPORTS) + STARTPORT;
}
res = -1;
errno = EADDRINUSE;
for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) {
sin->sin_port = htons(port++);
if (port > ENDPORT) {
port = STARTPORT;
}
res = bind(sd,
(struct sockaddr *)sin, sizeof(struct sockaddr_in));
}
return (res);
}

113
lib/libc/rpc/clnt_generic.c Normal file
View File

@ -0,0 +1,113 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/
/*static char *sccsid = "from: @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: clnt_generic.c,v 1.1 1993/10/27 05:40:19 paul Exp $";
#endif
/*
* Copyright (C) 1987, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/errno.h>
#include <netdb.h>
/*
* Generic client creation: takes (hostname, program-number, protocol) and
* returns client handle. Default options are set, which the user can
* change using the rpc equivalent of ioctl()'s.
*/
CLIENT *
clnt_create(hostname, prog, vers, proto)
char *hostname;
u_long prog;
u_long vers;
char *proto;
{
struct hostent *h;
struct protoent *p;
struct sockaddr_in sin;
int sock;
struct timeval tv;
CLIENT *client;
h = gethostbyname(hostname);
if (h == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
return (NULL);
}
if (h->h_addrtype != AF_INET) {
/*
* Only support INET for now
*/
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;
return (NULL);
}
sin.sin_family = h->h_addrtype;
sin.sin_port = 0;
bzero(sin.sin_zero, sizeof(sin.sin_zero));
bcopy(h->h_addr, (char*)&sin.sin_addr, h->h_length);
p = getprotobyname(proto);
if (p == NULL) {
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
return (NULL);
}
sock = RPC_ANYSOCK;
switch (p->p_proto) {
case IPPROTO_UDP:
tv.tv_sec = 5;
tv.tv_usec = 0;
client = clntudp_create(&sin, prog, vers, tv, &sock);
if (client == NULL) {
return (NULL);
}
tv.tv_sec = 25;
clnt_control(client, CLSET_TIMEOUT, &tv);
break;
case IPPROTO_TCP:
client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);
if (client == NULL) {
return (NULL);
}
tv.tv_sec = 25;
tv.tv_usec = 0;
clnt_control(client, CLSET_TIMEOUT, &tv);
break;
default:
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;
return (NULL);
}
return (client);
}

303
lib/libc/rpc/clnt_perror.c Normal file
View File

@ -0,0 +1,303 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: clnt_perror.c,v 1.1 1993/10/27 05:40:20 paul Exp $";
#endif
/*
* clnt_perror.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
*/
#include <stdio.h>
#include <string.h>
#include <rpc/rpc.h>
#include <rpc/types.h>
#include <rpc/auth.h>
#include <rpc/clnt.h>
static char *auth_errmsg();
static char *buf;
static char *
_buf()
{
if (buf == 0)
buf = (char *)malloc(256);
return (buf);
}
/*
* Print reply error info
*/
char *
clnt_sperror(rpch, s)
CLIENT *rpch;
char *s;
{
struct rpc_err e;
void clnt_perrno();
char *err;
char *str = _buf();
char *strstart = str;
if (str == 0)
return (0);
CLNT_GETERR(rpch, &e);
(void) sprintf(str, "%s: ", s);
str += strlen(str);
(void) strcpy(str, clnt_sperrno(e.re_status));
str += strlen(str);
switch (e.re_status) {
case RPC_SUCCESS:
case RPC_CANTENCODEARGS:
case RPC_CANTDECODERES:
case RPC_TIMEDOUT:
case RPC_PROGUNAVAIL:
case RPC_PROCUNAVAIL:
case RPC_CANTDECODEARGS:
case RPC_SYSTEMERROR:
case RPC_UNKNOWNHOST:
case RPC_UNKNOWNPROTO:
case RPC_PMAPFAILURE:
case RPC_PROGNOTREGISTERED:
case RPC_FAILED:
break;
case RPC_CANTSEND:
case RPC_CANTRECV:
(void) sprintf(str, "; errno = %s",
strerror(e.re_errno));
str += strlen(str);
break;
case RPC_VERSMISMATCH:
(void) sprintf(str,
"; low version = %lu, high version = %lu",
e.re_vers.low, e.re_vers.high);
str += strlen(str);
break;
case RPC_AUTHERROR:
err = auth_errmsg(e.re_why);
(void) sprintf(str,"; why = ");
str += strlen(str);
if (err != NULL) {
(void) sprintf(str, "%s",err);
} else {
(void) sprintf(str,
"(unknown authentication error - %d)",
(int) e.re_why);
}
str += strlen(str);
break;
case RPC_PROGVERSMISMATCH:
(void) sprintf(str,
"; low version = %lu, high version = %lu",
e.re_vers.low, e.re_vers.high);
str += strlen(str);
break;
default: /* unknown */
(void) sprintf(str,
"; s1 = %lu, s2 = %lu",
e.re_lb.s1, e.re_lb.s2);
str += strlen(str);
break;
}
(void) sprintf(str, "\n");
return(strstart) ;
}
void
clnt_perror(rpch, s)
CLIENT *rpch;
char *s;
{
(void) fprintf(stderr,"%s",clnt_sperror(rpch,s));
}
struct rpc_errtab {
enum clnt_stat status;
char *message;
};
static struct rpc_errtab rpc_errlist[] = {
{ RPC_SUCCESS,
"RPC: Success" },
{ RPC_CANTENCODEARGS,
"RPC: Can't encode arguments" },
{ RPC_CANTDECODERES,
"RPC: Can't decode result" },
{ RPC_CANTSEND,
"RPC: Unable to send" },
{ RPC_CANTRECV,
"RPC: Unable to receive" },
{ RPC_TIMEDOUT,
"RPC: Timed out" },
{ RPC_VERSMISMATCH,
"RPC: Incompatible versions of RPC" },
{ RPC_AUTHERROR,
"RPC: Authentication error" },
{ RPC_PROGUNAVAIL,
"RPC: Program unavailable" },
{ RPC_PROGVERSMISMATCH,
"RPC: Program/version mismatch" },
{ RPC_PROCUNAVAIL,
"RPC: Procedure unavailable" },
{ RPC_CANTDECODEARGS,
"RPC: Server can't decode arguments" },
{ RPC_SYSTEMERROR,
"RPC: Remote system error" },
{ RPC_UNKNOWNHOST,
"RPC: Unknown host" },
{ RPC_UNKNOWNPROTO,
"RPC: Unknown protocol" },
{ RPC_PMAPFAILURE,
"RPC: Port mapper failure" },
{ RPC_PROGNOTREGISTERED,
"RPC: Program not registered"},
{ RPC_FAILED,
"RPC: Failed (unspecified error)"}
};
/*
* This interface for use by clntrpc
*/
char *
clnt_sperrno(stat)
enum clnt_stat stat;
{
int i;
for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) {
if (rpc_errlist[i].status == stat) {
return (rpc_errlist[i].message);
}
}
return ("RPC: (unknown error code)");
}
void
clnt_perrno(num)
enum clnt_stat num;
{
(void) fprintf(stderr,"%s",clnt_sperrno(num));
}
char *
clnt_spcreateerror(s)
char *s;
{
extern int sys_nerr;
char *str = _buf();
if (str == 0)
return(0);
(void) sprintf(str, "%s: ", s);
(void) strcat(str, clnt_sperrno(rpc_createerr.cf_stat));
switch (rpc_createerr.cf_stat) {
case RPC_PMAPFAILURE:
(void) strcat(str, " - ");
(void) strcat(str,
clnt_sperrno(rpc_createerr.cf_error.re_status));
break;
case RPC_SYSTEMERROR:
(void) strcat(str, " - ");
if (rpc_createerr.cf_error.re_errno > 0
&& rpc_createerr.cf_error.re_errno < sys_nerr)
(void) strcat(str,
strerror(rpc_createerr.cf_error.re_errno));
else
(void) sprintf(&str[strlen(str)], "Error %d",
rpc_createerr.cf_error.re_errno);
break;
}
(void) strcat(str, "\n");
return (str);
}
void
clnt_pcreateerror(s)
char *s;
{
(void) fprintf(stderr,"%s",clnt_spcreateerror(s));
}
struct auth_errtab {
enum auth_stat status;
char *message;
};
static struct auth_errtab auth_errlist[] = {
{ AUTH_OK,
"Authentication OK" },
{ AUTH_BADCRED,
"Invalid client credential" },
{ AUTH_REJECTEDCRED,
"Server rejected credential" },
{ AUTH_BADVERF,
"Invalid client verifier" },
{ AUTH_REJECTEDVERF,
"Server rejected verifier" },
{ AUTH_TOOWEAK,
"Client credential too weak" },
{ AUTH_INVALIDRESP,
"Invalid server verifier" },
{ AUTH_FAILED,
"Failed (unspecified error)" },
};
static char *
auth_errmsg(stat)
enum auth_stat stat;
{
int i;
for (i = 0; i < sizeof(auth_errlist)/sizeof(struct auth_errtab); i++) {
if (auth_errlist[i].status == stat) {
return(auth_errlist[i].message);
}
}
return(NULL);
}

240
lib/libc/rpc/clnt_raw.c Normal file
View File

@ -0,0 +1,240 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: clnt_raw.c,v 1.1 1993/10/27 05:40:22 paul Exp $";
#endif
/*
* clnt_raw.c
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Memory based rpc for simple testing and timing.
* Interface to create an rpc client and server in the same process.
* This lets us similate rpc and get round trip overhead, without
* any interference from the kernal.
*/
#include <rpc/rpc.h>
#define MCALL_MSG_SIZE 24
/*
* This is the "network" we will be moving stuff over.
*/
static struct clntraw_private {
CLIENT client_object;
XDR xdr_stream;
char _raw_buf[UDPMSGSIZE];
char mashl_callmsg[MCALL_MSG_SIZE];
u_int mcnt;
} *clntraw_private;
static enum clnt_stat clntraw_call();
static void clntraw_abort();
static void clntraw_geterr();
static bool_t clntraw_freeres();
static bool_t clntraw_control();
static void clntraw_destroy();
static struct clnt_ops client_ops = {
clntraw_call,
clntraw_abort,
clntraw_geterr,
clntraw_freeres,
clntraw_destroy,
clntraw_control
};
void svc_getreq();
/*
* Create a client handle for memory based rpc.
*/
CLIENT *
clntraw_create(prog, vers)
u_long prog;
u_long vers;
{
register struct clntraw_private *clp = clntraw_private;
struct rpc_msg call_msg;
XDR *xdrs = &clp->xdr_stream;
CLIENT *client = &clp->client_object;
if (clp == 0) {
clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
if (clp == 0)
return (0);
clntraw_private = clp;
}
/*
* pre-serialize the staic part of the call msg and stash it away
*/
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = prog;
call_msg.rm_call.cb_vers = vers;
xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
if (! xdr_callhdr(xdrs, &call_msg)) {
perror("clnt_raw.c - Fatal header serialization error.");
}
clp->mcnt = XDR_GETPOS(xdrs);
XDR_DESTROY(xdrs);
/*
* Set xdrmem for client/server shared buffer
*/
xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
/*
* create client handle
*/
client->cl_ops = &client_ops;
client->cl_auth = authnone_create();
return (client);
}
static enum clnt_stat
clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
CLIENT *h;
u_long proc;
xdrproc_t xargs;
caddr_t argsp;
xdrproc_t xresults;
caddr_t resultsp;
struct timeval timeout;
{
register struct clntraw_private *clp = clntraw_private;
register XDR *xdrs = &clp->xdr_stream;
struct rpc_msg msg;
enum clnt_stat status;
struct rpc_err error;
if (clp == 0)
return (RPC_FAILED);
call_again:
/*
* send request
*/
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, 0);
((struct rpc_msg *)clp->mashl_callmsg)->rm_xid ++ ;
if ((! XDR_PUTBYTES(xdrs, clp->mashl_callmsg, clp->mcnt)) ||
(! XDR_PUTLONG(xdrs, (long *)&proc)) ||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp))) {
return (RPC_CANTENCODEARGS);
}
(void)XDR_GETPOS(xdrs); /* called just to cause overhead */
/*
* We have to call server input routine here because this is
* all going on in one process. Yuk.
*/
svc_getreq(1);
/*
* get results
*/
xdrs->x_op = XDR_DECODE;
XDR_SETPOS(xdrs, 0);
msg.acpted_rply.ar_verf = _null_auth;
msg.acpted_rply.ar_results.where = resultsp;
msg.acpted_rply.ar_results.proc = xresults;
if (! xdr_replymsg(xdrs, &msg))
return (RPC_CANTDECODERES);
_seterr_reply(&msg, &error);
status = error.re_status;
if (status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
status = RPC_AUTHERROR;
}
} /* end successful completion */
else {
if (AUTH_REFRESH(h->cl_auth))
goto call_again;
} /* end of unsuccessful completion */
if (status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
status = RPC_AUTHERROR;
}
if (msg.acpted_rply.ar_verf.oa_base != NULL) {
xdrs->x_op = XDR_FREE;
(void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
}
}
return (status);
}
static void
clntraw_geterr()
{
}
static bool_t
clntraw_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
register struct clntraw_private *clp = clntraw_private;
register XDR *xdrs = &clp->xdr_stream;
bool_t rval;
if (clp == 0)
{
rval = (bool_t) RPC_FAILED;
return (rval);
}
xdrs->x_op = XDR_FREE;
return ((*xdr_res)(xdrs, res_ptr));
}
static void
clntraw_abort()
{
}
static bool_t
clntraw_control()
{
return (FALSE);
}
static void
clntraw_destroy()
{
}

115
lib/libc/rpc/clnt_simple.c Normal file
View File

@ -0,0 +1,115 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: clnt_simple.c,v 1.1 1993/10/27 05:40:23 paul Exp $";
#endif
/*
* clnt_simple.c
* Simplified front end to rpc.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <netdb.h>
static struct callrpc_private {
CLIENT *client;
int socket;
int oldprognum, oldversnum, valid;
char *oldhost;
} *callrpc_private;
callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
char *host;
xdrproc_t inproc, outproc;
char *in, *out;
{
register struct callrpc_private *crp = callrpc_private;
struct sockaddr_in server_addr;
enum clnt_stat clnt_stat;
struct hostent *hp;
struct timeval timeout, tottimeout;
if (crp == 0) {
crp = (struct callrpc_private *)calloc(1, sizeof (*crp));
if (crp == 0)
return (0);
callrpc_private = crp;
}
if (crp->oldhost == NULL) {
crp->oldhost = malloc(256);
crp->oldhost[0] = 0;
crp->socket = RPC_ANYSOCK;
}
if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum
&& strcmp(crp->oldhost, host) == 0) {
/* reuse old client */
} else {
crp->valid = 0;
(void)close(crp->socket);
crp->socket = RPC_ANYSOCK;
if (crp->client) {
clnt_destroy(crp->client);
crp->client = NULL;
}
if ((hp = gethostbyname(host)) == NULL)
return ((int) RPC_UNKNOWNHOST);
timeout.tv_usec = 0;
timeout.tv_sec = 5;
bcopy(hp->h_addr, (char *)&server_addr.sin_addr, hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = 0;
if ((crp->client = clntudp_create(&server_addr, (u_long)prognum,
(u_long)versnum, timeout, &crp->socket)) == NULL)
return ((int) rpc_createerr.cf_stat);
crp->valid = 1;
crp->oldprognum = prognum;
crp->oldversnum = versnum;
(void) strcpy(crp->oldhost, host);
}
tottimeout.tv_sec = 25;
tottimeout.tv_usec = 0;
clnt_stat = clnt_call(crp->client, procnum, inproc, in,
outproc, out, tottimeout);
/*
* if call failed, empty cache
*/
if (clnt_stat != RPC_SUCCESS)
crp->valid = 0;
return ((int) clnt_stat);
}

468
lib/libc/rpc/clnt_tcp.c Normal file
View File

@ -0,0 +1,468 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: clnt_tcp.c,v 1.1 1993/10/27 05:40:24 paul Exp $";
#endif
/*
* clnt_tcp.c, Implements a TCP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* TCP based RPC supports 'batched calls'.
* A sequence of calls may be batched-up in a send buffer. The rpc call
* return immediately to the client even though the call was not necessarily
* sent. The batching occurs if the results' xdr routine is NULL (0) AND
* the rpc timeout value is zero (see clnt.h, rpc).
*
* Clients should NOT casually batch calls that in fact return results; that is,
* the server side should be aware that a call is batched and not produce any
* return message. Batched calls that produce many result messages can
* deadlock (netlock) the client and the server....
*
* Now go hang yourself.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <netdb.h>
#include <errno.h>
#include <rpc/pmap_clnt.h>
#define MCALL_MSG_SIZE 24
extern int errno;
static int readtcp();
static int writetcp();
static enum clnt_stat clnttcp_call();
static void clnttcp_abort();
static void clnttcp_geterr();
static bool_t clnttcp_freeres();
static bool_t clnttcp_control();
static void clnttcp_destroy();
static struct clnt_ops tcp_ops = {
clnttcp_call,
clnttcp_abort,
clnttcp_geterr,
clnttcp_freeres,
clnttcp_destroy,
clnttcp_control
};
struct ct_data {
int ct_sock;
bool_t ct_closeit;
struct timeval ct_wait;
bool_t ct_waitset; /* wait set by clnt_control? */
struct sockaddr_in ct_addr;
struct rpc_err ct_error;
char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */
u_int ct_mpos; /* pos after marshal */
XDR ct_xdrs;
};
/*
* Create a client handle for a tcp/ip connection.
* If *sockp<0, *sockp is set to a newly created TCP socket and it is
* connected to raddr. If *sockp non-negative then
* raddr is ignored. The rpc/tcp package does buffering
* similar to stdio, so the client must pick send and receive buffer sizes,];
* 0 => use the default.
* If raddr->sin_port is 0, then a binder on the remote machine is
* consulted for the right port number.
* NB: *sockp is copied into a private area.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is set null authentication. Caller may wish to set this
* something more useful.
*/
CLIENT *
clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
struct sockaddr_in *raddr;
u_long prog;
u_long vers;
register int *sockp;
u_int sendsz;
u_int recvsz;
{
CLIENT *h;
register struct ct_data *ct;
struct timeval now;
struct rpc_msg call_msg;
h = (CLIENT *)mem_alloc(sizeof(*h));
if (h == NULL) {
(void)fprintf(stderr, "clnttcp_create: out of memory\n");
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
ct = (struct ct_data *)mem_alloc(sizeof(*ct));
if (ct == NULL) {
(void)fprintf(stderr, "clnttcp_create: out of memory\n");
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
/*
* If no port number given ask the pmap for one
*/
if (raddr->sin_port == 0) {
u_short port;
if ((port = pmap_getport(raddr, prog, vers, IPPROTO_TCP)) == 0) {
mem_free((caddr_t)ct, sizeof(struct ct_data));
mem_free((caddr_t)h, sizeof(CLIENT));
return ((CLIENT *)NULL);
}
raddr->sin_port = htons(port);
}
/*
* If no socket given, open one
*/
if (*sockp < 0) {
*sockp = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
(void)bindresvport(*sockp, (struct sockaddr_in *)0);
if ((*sockp < 0)
|| (connect(*sockp, (struct sockaddr *)raddr,
sizeof(*raddr)) < 0)) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
(void)close(*sockp);
goto fooy;
}
ct->ct_closeit = TRUE;
} else {
ct->ct_closeit = FALSE;
}
/*
* Set up private data struct
*/
ct->ct_sock = *sockp;
ct->ct_wait.tv_usec = 0;
ct->ct_waitset = FALSE;
ct->ct_addr = *raddr;
/*
* Initialize call message
*/
(void)gettimeofday(&now, (struct timezone *)0);
call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = prog;
call_msg.rm_call.cb_vers = vers;
/*
* pre-serialize the staic part of the call msg and stash it away
*/
xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,
XDR_ENCODE);
if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
if (ct->ct_closeit) {
(void)close(*sockp);
}
goto fooy;
}
ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
XDR_DESTROY(&(ct->ct_xdrs));
/*
* Create a client handle which uses xdrrec for serialization
* and authnone for authentication.
*/
xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
(caddr_t)ct, readtcp, writetcp);
h->cl_ops = &tcp_ops;
h->cl_private = (caddr_t) ct;
h->cl_auth = authnone_create();
return (h);
fooy:
/*
* Something goofed, free stuff and barf
*/
mem_free((caddr_t)ct, sizeof(struct ct_data));
mem_free((caddr_t)h, sizeof(CLIENT));
return ((CLIENT *)NULL);
}
static enum clnt_stat
clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
register CLIENT *h;
u_long proc;
xdrproc_t xdr_args;
caddr_t args_ptr;
xdrproc_t xdr_results;
caddr_t results_ptr;
struct timeval timeout;
{
register struct ct_data *ct = (struct ct_data *) h->cl_private;
register XDR *xdrs = &(ct->ct_xdrs);
struct rpc_msg reply_msg;
u_long x_id;
u_long *msg_x_id = (u_long *)(ct->ct_mcall); /* yuk */
register bool_t shipnow;
int refreshes = 2;
if (!ct->ct_waitset) {
ct->ct_wait = timeout;
}
shipnow =
(xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0
&& timeout.tv_usec == 0) ? FALSE : TRUE;
call_again:
xdrs->x_op = XDR_ENCODE;
ct->ct_error.re_status = RPC_SUCCESS;
x_id = ntohl(--(*msg_x_id));
if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) ||
(! XDR_PUTLONG(xdrs, (long *)&proc)) ||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
(! (*xdr_args)(xdrs, args_ptr))) {
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTENCODEARGS;
(void)xdrrec_endofrecord(xdrs, TRUE);
return (ct->ct_error.re_status);
}
if (! xdrrec_endofrecord(xdrs, shipnow))
return (ct->ct_error.re_status = RPC_CANTSEND);
if (! shipnow)
return (RPC_SUCCESS);
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
return(ct->ct_error.re_status = RPC_TIMEDOUT);
}
/*
* Keep receiving until we get a valid transaction id
*/
xdrs->x_op = XDR_DECODE;
while (TRUE) {
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = NULL;
reply_msg.acpted_rply.ar_results.proc = xdr_void;
if (! xdrrec_skiprecord(xdrs))
return (ct->ct_error.re_status);
/* now decode and validate the response header */
if (! xdr_replymsg(xdrs, &reply_msg)) {
if (ct->ct_error.re_status == RPC_SUCCESS)
continue;
return (ct->ct_error.re_status);
}
if (reply_msg.rm_xid == x_id)
break;
}
/*
* process header
*/
_seterr_reply(&reply_msg, &(ct->ct_error));
if (ct->ct_error.re_status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) {
ct->ct_error.re_status = RPC_AUTHERROR;
ct->ct_error.re_why = AUTH_INVALIDRESP;
} else if (! (*xdr_results)(xdrs, results_ptr)) {
if (ct->ct_error.re_status == RPC_SUCCESS)
ct->ct_error.re_status = RPC_CANTDECODERES;
}
/* free verifier ... */
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
xdrs->x_op = XDR_FREE;
(void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else {
/* maybe our credentials need to be refreshed ... */
if (refreshes-- && AUTH_REFRESH(h->cl_auth))
goto call_again;
} /* end of unsuccessful completion */
return (ct->ct_error.re_status);
}
static void
clnttcp_geterr(h, errp)
CLIENT *h;
struct rpc_err *errp;
{
register struct ct_data *ct =
(struct ct_data *) h->cl_private;
*errp = ct->ct_error;
}
static bool_t
clnttcp_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
register struct ct_data *ct = (struct ct_data *)cl->cl_private;
register XDR *xdrs = &(ct->ct_xdrs);
xdrs->x_op = XDR_FREE;
return ((*xdr_res)(xdrs, res_ptr));
}
static void
clnttcp_abort()
{
}
static bool_t
clnttcp_control(cl, request, info)
CLIENT *cl;
int request;
char *info;
{
register struct ct_data *ct = (struct ct_data *)cl->cl_private;
switch (request) {
case CLSET_TIMEOUT:
ct->ct_wait = *(struct timeval *)info;
ct->ct_waitset = TRUE;
break;
case CLGET_TIMEOUT:
*(struct timeval *)info = ct->ct_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_in *)info = ct->ct_addr;
break;
default:
return (FALSE);
}
return (TRUE);
}
static void
clnttcp_destroy(h)
CLIENT *h;
{
register struct ct_data *ct =
(struct ct_data *) h->cl_private;
if (ct->ct_closeit) {
(void)close(ct->ct_sock);
}
XDR_DESTROY(&(ct->ct_xdrs));
mem_free((caddr_t)ct, sizeof(struct ct_data));
mem_free((caddr_t)h, sizeof(CLIENT));
}
/*
* Interface between xdr serializer and tcp connection.
* Behaves like the system calls, read & write, but keeps some error state
* around for the rpc level.
*/
static int
readtcp(ct, buf, len)
register struct ct_data *ct;
caddr_t buf;
register int len;
{
#ifdef FD_SETSIZE
fd_set mask;
fd_set readfds;
if (len == 0)
return (0);
FD_ZERO(&mask);
FD_SET(ct->ct_sock, &mask);
#else
register int mask = 1 << (ct->ct_sock);
int readfds;
if (len == 0)
return (0);
#endif /* def FD_SETSIZE */
while (TRUE) {
readfds = mask;
switch (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL,
&(ct->ct_wait))) {
case 0:
ct->ct_error.re_status = RPC_TIMEDOUT;
return (-1);
case -1:
if (errno == EINTR)
continue;
ct->ct_error.re_status = RPC_CANTRECV;
ct->ct_error.re_errno = errno;
return (-1);
}
break;
}
switch (len = read(ct->ct_sock, buf, len)) {
case 0:
/* premature eof */
ct->ct_error.re_errno = ECONNRESET;
ct->ct_error.re_status = RPC_CANTRECV;
len = -1; /* it's really an error */
break;
case -1:
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTRECV;
break;
}
return (len);
}
static int
writetcp(ct, buf, len)
struct ct_data *ct;
caddr_t buf;
int len;
{
register int i, cnt;
for (cnt = len; cnt > 0; cnt -= i, buf += i) {
if ((i = write(ct->ct_sock, buf, cnt)) == -1) {
ct->ct_error.re_errno = errno;
ct->ct_error.re_status = RPC_CANTSEND;
return (-1);
}
}
return (len);
}

444
lib/libc/rpc/clnt_udp.c Normal file
View File

@ -0,0 +1,444 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: clnt_udp.c,v 1.1 1993/10/27 05:40:25 paul Exp $";
#endif
/*
* clnt_udp.c, Implements a UDP/IP based, client side RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <netdb.h>
#include <errno.h>
#include <rpc/pmap_clnt.h>
extern int errno;
/*
* UDP bases client side rpc operations
*/
static enum clnt_stat clntudp_call();
static void clntudp_abort();
static void clntudp_geterr();
static bool_t clntudp_freeres();
static bool_t clntudp_control();
static void clntudp_destroy();
static struct clnt_ops udp_ops = {
clntudp_call,
clntudp_abort,
clntudp_geterr,
clntudp_freeres,
clntudp_destroy,
clntudp_control
};
/*
* Private data kept per client handle
*/
struct cu_data {
int cu_sock;
bool_t cu_closeit;
struct sockaddr_in cu_raddr;
int cu_rlen;
struct timeval cu_wait;
struct timeval cu_total;
struct rpc_err cu_error;
XDR cu_outxdrs;
u_int cu_xdrpos;
u_int cu_sendsz;
char *cu_outbuf;
u_int cu_recvsz;
char cu_inbuf[1];
};
/*
* Create a UDP based client handle.
* If *sockp<0, *sockp is set to a newly created UPD socket.
* If raddr->sin_port is 0 a binder on the remote machine
* is consulted for the correct port number.
* NB: It is the clients responsibility to close *sockp.
* NB: The rpch->cl_auth is initialized to null authentication.
* Caller may wish to set this something more useful.
*
* wait is the amount of time used between retransmitting a call if
* no response has been heard; retransmition occurs until the actual
* rpc call times out.
*
* sendsz and recvsz are the maximum allowable packet sizes that can be
* sent and received.
*/
CLIENT *
clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
struct sockaddr_in *raddr;
u_long program;
u_long version;
struct timeval wait;
register int *sockp;
u_int sendsz;
u_int recvsz;
{
CLIENT *cl;
register struct cu_data *cu;
struct timeval now;
struct rpc_msg call_msg;
cl = (CLIENT *)mem_alloc(sizeof(CLIENT));
if (cl == NULL) {
(void) fprintf(stderr, "clntudp_create: out of memory\n");
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
sendsz = ((sendsz + 3) / 4) * 4;
recvsz = ((recvsz + 3) / 4) * 4;
cu = (struct cu_data *)mem_alloc(sizeof(*cu) + sendsz + recvsz);
if (cu == NULL) {
(void) fprintf(stderr, "clntudp_create: out of memory\n");
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
(void)gettimeofday(&now, (struct timezone *)0);
if (raddr->sin_port == 0) {
u_short port;
if ((port =
pmap_getport(raddr, program, version, IPPROTO_UDP)) == 0) {
goto fooy;
}
raddr->sin_port = htons(port);
}
cl->cl_ops = &udp_ops;
cl->cl_private = (caddr_t)cu;
cu->cu_raddr = *raddr;
cu->cu_rlen = sizeof (cu->cu_raddr);
cu->cu_wait = wait;
cu->cu_total.tv_sec = -1;
cu->cu_total.tv_usec = -1;
cu->cu_sendsz = sendsz;
cu->cu_recvsz = recvsz;
call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec;
call_msg.rm_direction = CALL;
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
call_msg.rm_call.cb_prog = program;
call_msg.rm_call.cb_vers = version;
xdrmem_create(&(cu->cu_outxdrs), cu->cu_outbuf,
sendsz, XDR_ENCODE);
if (! xdr_callhdr(&(cu->cu_outxdrs), &call_msg)) {
goto fooy;
}
cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
if (*sockp < 0) {
int dontblock = 1;
*sockp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (*sockp < 0) {
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
rpc_createerr.cf_error.re_errno = errno;
goto fooy;
}
/* attempt to bind to prov port */
(void)bindresvport(*sockp, (struct sockaddr_in *)0);
/* the sockets rpc controls are non-blocking */
(void)ioctl(*sockp, FIONBIO, (char *) &dontblock);
cu->cu_closeit = TRUE;
} else {
cu->cu_closeit = FALSE;
}
cu->cu_sock = *sockp;
cl->cl_auth = authnone_create();
return (cl);
fooy:
if (cu)
mem_free((caddr_t)cu, sizeof(*cu) + sendsz + recvsz);
if (cl)
mem_free((caddr_t)cl, sizeof(CLIENT));
return ((CLIENT *)NULL);
}
CLIENT *
clntudp_create(raddr, program, version, wait, sockp)
struct sockaddr_in *raddr;
u_long program;
u_long version;
struct timeval wait;
register int *sockp;
{
return(clntudp_bufcreate(raddr, program, version, wait, sockp,
UDPMSGSIZE, UDPMSGSIZE));
}
static enum clnt_stat
clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
register CLIENT *cl; /* client handle */
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 */
struct timeval utimeout; /* seconds to wait before giving up */
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
register XDR *xdrs;
register int outlen;
register int inlen;
int fromlen;
#ifdef FD_SETSIZE
fd_set readfds;
fd_set mask;
#else
int readfds;
register int mask;
#endif /* def FD_SETSIZE */
struct sockaddr_in from;
struct rpc_msg reply_msg;
XDR reply_xdrs;
struct timeval time_waited;
bool_t ok;
int nrefreshes = 2; /* number of times to refresh cred */
struct timeval timeout;
if (cu->cu_total.tv_usec == -1) {
timeout = utimeout; /* use supplied timeout */
} else {
timeout = cu->cu_total; /* use default timeout */
}
time_waited.tv_sec = 0;
time_waited.tv_usec = 0;
call_again:
xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, cu->cu_xdrpos);
/*
* the transaction is the first thing in the out buffer
*/
(*(u_short *)(cu->cu_outbuf))++;
if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||
(! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
(! (*xargs)(xdrs, argsp)))
return (cu->cu_error.re_status = RPC_CANTENCODEARGS);
outlen = (int)XDR_GETPOS(xdrs);
send_again:
if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0,
(struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen)
!= outlen) {
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTSEND);
}
/*
* Hack to provide rpc-based message passing
*/
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
return (cu->cu_error.re_status = RPC_TIMEDOUT);
}
/*
* sub-optimal code appears here because we have
* some clock time to spare while the packets are in flight.
* (We assume that this is actually only executed once.)
*/
reply_msg.acpted_rply.ar_verf = _null_auth;
reply_msg.acpted_rply.ar_results.where = resultsp;
reply_msg.acpted_rply.ar_results.proc = xresults;
#ifdef FD_SETSIZE
FD_ZERO(&mask);
FD_SET(cu->cu_sock, &mask);
#else
mask = 1 << cu->cu_sock;
#endif /* def FD_SETSIZE */
for (;;) {
readfds = mask;
switch (select(_rpc_dtablesize(), &readfds, (int *)NULL,
(int *)NULL, &(cu->cu_wait))) {
case 0:
time_waited.tv_sec += cu->cu_wait.tv_sec;
time_waited.tv_usec += cu->cu_wait.tv_usec;
while (time_waited.tv_usec >= 1000000) {
time_waited.tv_sec++;
time_waited.tv_usec -= 1000000;
}
if ((time_waited.tv_sec < timeout.tv_sec) ||
((time_waited.tv_sec == timeout.tv_sec) &&
(time_waited.tv_usec < timeout.tv_usec)))
goto send_again;
return (cu->cu_error.re_status = RPC_TIMEDOUT);
/*
* buggy in other cases because time_waited is not being
* updated.
*/
case -1:
if (errno == EINTR)
continue;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
do {
fromlen = sizeof(struct sockaddr);
inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,
(int) cu->cu_recvsz, 0,
(struct sockaddr *)&from, &fromlen);
} while (inlen < 0 && errno == EINTR);
if (inlen < 0) {
if (errno == EWOULDBLOCK)
continue;
cu->cu_error.re_errno = errno;
return (cu->cu_error.re_status = RPC_CANTRECV);
}
if (inlen < sizeof(u_long))
continue;
/* see if reply transaction id matches sent id */
if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf)))
continue;
/* we now assume we have the proper reply */
break;
}
/*
* now decode and validate the response
*/
xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)inlen, XDR_DECODE);
ok = xdr_replymsg(&reply_xdrs, &reply_msg);
/* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
if (ok) {
_seterr_reply(&reply_msg, &(cu->cu_error));
if (cu->cu_error.re_status == RPC_SUCCESS) {
if (! AUTH_VALIDATE(cl->cl_auth,
&reply_msg.acpted_rply.ar_verf)) {
cu->cu_error.re_status = RPC_AUTHERROR;
cu->cu_error.re_why = AUTH_INVALIDRESP;
}
if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
xdrs->x_op = XDR_FREE;
(void)xdr_opaque_auth(xdrs,
&(reply_msg.acpted_rply.ar_verf));
}
} /* end successful completion */
else {
/* maybe our credentials need to be refreshed ... */
if (nrefreshes > 0 && AUTH_REFRESH(cl->cl_auth)) {
nrefreshes--;
goto call_again;
}
} /* end of unsuccessful completion */
} /* end of valid reply message */
else {
cu->cu_error.re_status = RPC_CANTDECODERES;
}
return (cu->cu_error.re_status);
}
static void
clntudp_geterr(cl, errp)
CLIENT *cl;
struct rpc_err *errp;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
*errp = cu->cu_error;
}
static bool_t
clntudp_freeres(cl, xdr_res, res_ptr)
CLIENT *cl;
xdrproc_t xdr_res;
caddr_t res_ptr;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
register XDR *xdrs = &(cu->cu_outxdrs);
xdrs->x_op = XDR_FREE;
return ((*xdr_res)(xdrs, res_ptr));
}
static void
clntudp_abort(/*h*/)
/*CLIENT *h;*/
{
}
static bool_t
clntudp_control(cl, request, info)
CLIENT *cl;
int request;
char *info;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
switch (request) {
case CLSET_TIMEOUT:
cu->cu_total = *(struct timeval *)info;
break;
case CLGET_TIMEOUT:
*(struct timeval *)info = cu->cu_total;
break;
case CLSET_RETRY_TIMEOUT:
cu->cu_wait = *(struct timeval *)info;
break;
case CLGET_RETRY_TIMEOUT:
*(struct timeval *)info = cu->cu_wait;
break;
case CLGET_SERVER_ADDR:
*(struct sockaddr_in *)info = cu->cu_raddr;
break;
default:
return (FALSE);
}
return (TRUE);
}
static void
clntudp_destroy(cl)
CLIENT *cl;
{
register struct cu_data *cu = (struct cu_data *)cl->cl_private;
if (cu->cu_closeit) {
(void)close(cu->cu_sock);
}
XDR_DESTROY(&(cu->cu_outxdrs));
mem_free((caddr_t)cu, (sizeof(*cu) + cu->cu_sendsz + cu->cu_recvsz));
mem_free((caddr_t)cl, sizeof(CLIENT));
}

View File

@ -0,0 +1,99 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: get_myaddress.c,v 1.1 1993/10/27 05:40:27 paul Exp $";
#endif
/*
* get_myaddress.c
*
* Get client's IP address via ioctl. This avoids using the yellowpages.
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/pmap_prot.h>
#include <sys/socket.h>
#include <stdio.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* don't use gethostbyname, which would invoke yellow pages
*/
get_myaddress(addr)
struct sockaddr_in *addr;
{
int s;
char buf[BUFSIZ];
struct ifconf ifc;
struct ifreq ifreq, *ifr;
int len, slop;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("get_myaddress: socket");
exit(1);
}
ifc.ifc_len = sizeof (buf);
ifc.ifc_buf = buf;
if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) {
perror("get_myaddress: ioctl (get interface configuration)");
exit(1);
}
ifr = ifc.ifc_req;
for (len = ifc.ifc_len; len; len -= sizeof ifreq) {
ifreq = *ifr;
if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
perror("get_myaddress: ioctl");
exit(1);
}
if ((ifreq.ifr_flags & IFF_UP) &&
ifr->ifr_addr.sa_family == AF_INET) {
*addr = *((struct sockaddr_in *)&ifr->ifr_addr);
addr->sin_port = htons(PMAPPORT);
break;
}
/*
* Deal with variable length addresses
*/
slop = ifr->ifr_addr.sa_len - sizeof (struct sockaddr);
if (slop) {
ifr = (struct ifreq *) ((caddr_t)ifr + slop);
len -= slop;
}
ifr++;
}
(void) close(s);
}

109
lib/libc/rpc/getrpcent.3 Normal file
View File

@ -0,0 +1,109 @@
.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
.TH GETRPCENT 3N "14 December 1987"
.SH NAME
getrpcent, getrpcbyname, getrpcbynumber \- get RPC entry
.SH SYNOPSIS
.nf
.ft B
#include <netdb.h>
.LP
.ft B
struct rpcent *getrpcent(\|)
.LP
.ft B
struct rpcent *getrpcbyname(name)
char *name;
.LP
.ft B
struct rpcent *getrpcbynumber(number)
int number;
.LP
.ft B
setrpcent (stayopen)
int stayopen
.LP
.ft B
endrpcent (\|)
.fi
.SH DESCRIPTION
.LP
.BR getrpcent(\|) ,
.BR getrpcbyname(\|) ,
and
.B getrpcbynumber(\|)
each return a pointer to an object with the
following structure
containing the broken-out
fields of a line in the rpc program number data base,
.BR /etc/rpc .
.RS
.LP
.nf
.ft B
struct rpcent {
char *r_name; /* name of server for this rpc program */
char **r_aliases; /* alias list */
long r_number; /* rpc program number */
};
.ft R
.fi
.RE
.LP
The members of this structure are:
.RS
.PD 0
.TP 20
.B r_name
The name of the server for this rpc program.
.TP 20
.B r_aliases
A zero terminated list of alternate names for the rpc program.
.TP 20
.B r_number
The rpc program number for this service.
.PD
.RE
.LP
.B getrpcent(\|)
reads the next line of the file, opening the file if necessary.
.LP
.B getrpcent(\|)
opens and rewinds the file. If the
.I stayopen
flag is non-zero,
the net data base will not be closed after each call to
.B getrpcent(\|)
(either directly, or indirectly through one of
the other \*(lqgetrpc\*(rq calls).
.LP
.B endrpcent
closes the file.
.LP
.B getrpcbyname(\|)
and
.B getrpcbynumber(\|)
sequentially search from the beginning
of the file until a matching rpc program name or
program number is found, or until end-of-file is encountered.
.SH FILES
.PD 0
.TP 20
.B /etc/rpc
.PD
.SH "SEE ALSO"
.BR rpc (5),
.BR rpcinfo (8C),
.BR ypserv (8)
.SH DIAGNOSTICS
.LP
A
.SM NULL
pointer is returned on
.SM EOF
or error.
.SH BUGS
.LP
All information
is contained in a static area
so it must be copied if it is
to be saved.

298
lib/libc/rpc/getrpcent.c Normal file
View File

@ -0,0 +1,298 @@
/*
* 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 or with the express written consent of
* Sun Microsystems, Inc.
*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/
static char *rcsid = "$Id: getrpcent.c,v 1.1 1993/10/27 05:40:29 paul Exp $";
#endif
/*
* Copyright (c) 1984 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <rpc/rpc.h>
#ifdef YP
#include <rpcsvc/yp_prot.h>
#include <rpcsvc/ypclnt.h>
#endif
/*
* Internet version.
*/
struct rpcdata {
FILE *rpcf;
int stayopen;
#define MAXALIASES 35
char *rpc_aliases[MAXALIASES];
struct rpcent rpc;
char line[BUFSIZ+1];
#ifdef YP
char *domain;
char *current;
int currentlen;
#endif
} *rpcdata;
#ifdef YP
static int __yp_nomap = 0;
#endif /* YP */
static struct rpcent *interpret();
struct hostent *gethostent();
char *inet_ntoa();
static char RPCDB[] = "/etc/rpc";
static struct rpcdata *
_rpcdata()
{
register struct rpcdata *d = rpcdata;
if (d == 0) {
d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
rpcdata = d;
}
return (d);
}
struct rpcent *
getrpcbynumber(number)
register int number;
{
register struct rpcdata *d = _rpcdata();
register struct rpcent *p;
#ifdef YP
int reason;
char adrstr[16];
#endif
if (d == 0)
return (0);
#ifdef YP
if (!__yp_nomap && _yp_check(&d->domain)) {
sprintf(adrstr, "%d", number);
reason = yp_match(d->domain, "rpc.bynumber", adrstr, strlen(adrstr),
&d->current, &d->currentlen);
switch(reason) {
case 0:
break;
case YPERR_MAP:
__yp_nomap = 1;
goto no_yp;
break;
default:
return(0);
break;
}
d->current[d->currentlen] = '\0';
p = interpret(d->current, d->currentlen);
(void) free(d->current);
return p;
}
no_yp:
#endif /* YP */
setrpcent(0);
while (p = getrpcent()) {
if (p->r_number == number)
break;
}
endrpcent();
return (p);
}
struct rpcent *
getrpcbyname(name)
char *name;
{
struct rpcent *rpc;
char **rp;
setrpcent(0);
while (rpc = getrpcent()) {
if (strcmp(rpc->r_name, name) == 0)
return (rpc);
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
if (strcmp(*rp, name) == 0)
return (rpc);
}
}
endrpcent();
return (NULL);
}
void
setrpcent(f)
int f;
{
register struct rpcdata *d = _rpcdata();
if (d == 0)
return;
#ifdef YP
if (!__yp_nomap && _yp_check(NULL)) {
if (d->current)
free(d->current);
d->current = NULL;
d->currentlen = 0;
return;
}
__yp_nomap = 0;
#endif /* YP */
if (d->rpcf == NULL)
d->rpcf = fopen(RPCDB, "r");
else
rewind(d->rpcf);
d->stayopen |= f;
}
void
endrpcent()
{
register struct rpcdata *d = _rpcdata();
if (d == 0)
return;
#ifdef YP
if (!__yp_nomap && _yp_check(NULL)) {
if (d->current && !d->stayopen)
free(d->current);
d->current = NULL;
d->currentlen = 0;
return;
}
__yp_nomap = 0;
#endif /* YP */
if (d->rpcf && !d->stayopen) {
fclose(d->rpcf);
d->rpcf = NULL;
}
}
struct rpcent *
getrpcent()
{
struct rpcent *hp;
int reason;
register struct rpcdata *d = _rpcdata();
#ifdef YP
char *key = NULL, *val = NULL;
int keylen, vallen;
#endif
if (d == 0)
return(NULL);
#ifdef YP
if (!__yp_nomap && _yp_check(&d->domain)) {
if (d->current == NULL && d->currentlen == 0) {
reason = yp_first(d->domain, "rpc.bynumber",
&d->current, &d->currentlen,
&val, &vallen);
} else {
reason = yp_next(d->domain, "rpc.bynumber",
d->current, d->currentlen,
&d->current, &d->currentlen,
&val, &vallen);
}
switch(reason) {
case 0:
break;
case YPERR_MAP:
__yp_nomap = 1;
goto no_yp;
break;
default:
return(0);
break;
}
val[vallen] = '\0';
hp = interpret(val, vallen);
(void) free(val);
return hp;
}
no_yp:
#endif /* YP */
if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
return (NULL);
if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
return (NULL);
return (interpret(d->line, strlen(d->line)));
}
static struct rpcent *
interpret(val, len)
char *val;
int len;
{
register struct rpcdata *d = _rpcdata();
char *p;
register char *cp, **q;
if (d == 0)
return (0);
(void) strncpy(d->line, val, len);
p = d->line;
d->line[len] = '\n';
if (*p == '#')
return (getrpcent());
cp = strpbrk(p, "#\n");
if (cp == NULL)
return (getrpcent());
*cp = '\0';
cp = strpbrk(p, " \t");
if (cp == NULL)
return (getrpcent());
*cp++ = '\0';
/* THIS STUFF IS INTERNET SPECIFIC */
d->rpc.r_name = d->line;
while (*cp == ' ' || *cp == '\t')
cp++;
d->rpc.r_number = atoi(cp);
q = d->rpc.r_aliases = d->rpc_aliases;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
while (cp && *cp) {
if (*cp == ' ' || *cp == '\t') {
cp++;
continue;
}
if (q < &(d->rpc_aliases[MAXALIASES - 1]))
*q++ = cp;
cp = strpbrk(cp, " \t");
if (cp != NULL)
*cp++ = '\0';
}
*q = NULL;
return (&d->rpc);
}

31
lib/libc/rpc/getrpcport.3 Normal file
View File

@ -0,0 +1,31 @@
.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI
.TH GETRPCPORT 3R "6 October 1987"
.SH NAME
getrpcport \- get RPC port number
.SH SYNOPSIS
.ft B
.nf
int getrpcport(host, prognum, versnum, proto)
char *host;
int prognum, versnum, proto;
.fi
.SH DESCRIPTION
.IX getrpcport "" "\fLgetrpcport\fR \(em get RPC port number"
.B getrpcport(\|)
returns the port number for version
.I versnum
of the RPC program
.I prognum
running on
.I host
and using protocol
.IR proto .
It returns 0 if it cannot contact the portmapper, or if
.I prognum
is not registered. If
.I prognum
is registered but not with version
.IR versnum ,
it will still return a port number (for some version of the program)
indicating that the program is indeed registered.
The version mismatch will be detected upon the first call to the service.

57
lib/libc/rpc/getrpcport.c Normal file
View File

@ -0,0 +1,57 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/
/*static char *sccsid = "from: @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: getrpcport.c,v 1.1 1993/10/27 05:40:31 paul Exp $";
#endif
/*
* Copyright (c) 1985 by Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <netdb.h>
#include <sys/socket.h>
getrpcport(host, prognum, versnum, proto)
char *host;
{
struct sockaddr_in addr;
struct hostent *hp;
if ((hp = gethostbyname(host)) == NULL)
return (0);
bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length);
addr.sin_family = AF_INET;
addr.sin_port = 0;
return (pmap_getport(&addr, prognum, versnum, proto));
}

117
lib/libc/rpc/pmap_clnt.c Normal file
View File

@ -0,0 +1,117 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_clnt.c,v 1.1 1993/10/27 05:40:32 paul Exp $";
#endif
/*
* pmap_clnt.c
* Client interface to pmap rpc service.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
static struct timeval timeout = { 5, 0 };
static struct timeval tottimeout = { 60, 0 };
void clnt_perror();
/*
* Set a mapping between program,version and port.
* Calls the pmap service remotely to do the mapping.
*/
bool_t
pmap_set(program, version, protocol, port)
u_long program;
u_long version;
int protocol;
u_short port;
{
struct sockaddr_in myaddress;
int socket = -1;
register CLIENT *client;
struct pmap parms;
bool_t rslt;
get_myaddress(&myaddress);
client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client == (CLIENT *)NULL)
return (FALSE);
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = port;
if (CLNT_CALL(client, PMAPPROC_SET, xdr_pmap, &parms, xdr_bool, &rslt,
tottimeout) != RPC_SUCCESS) {
clnt_perror(client, "Cannot register service");
return (FALSE);
}
CLNT_DESTROY(client);
(void)close(socket);
return (rslt);
}
/*
* Remove the mapping between program,version and port.
* Calls the pmap service remotely to do the un-mapping.
*/
bool_t
pmap_unset(program, version)
u_long program;
u_long version;
{
struct sockaddr_in myaddress;
int socket = -1;
register CLIENT *client;
struct pmap parms;
bool_t rslt;
get_myaddress(&myaddress);
client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS,
timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client == (CLIENT *)NULL)
return (FALSE);
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_port = parms.pm_prot = 0;
CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,
tottimeout);
CLNT_DESTROY(client);
(void)close(socket);
return (rslt);
}

View File

@ -0,0 +1,86 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_getmaps.c,v 1.1 1993/10/27 05:40:35 paul Exp $";
#endif
/*
* pmap_getmap.c
* Client interface to pmap rpc service.
* contains pmap_getmaps, which is only tcp service involved
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include <errno.h>
#include <net/if.h>
#include <sys/ioctl.h>
#define NAMELEN 255
#define MAX_BROADCAST_SIZE 1400
extern int errno;
/*
* Get a copy of the current port maps.
* Calls the pmap service remotely to do get the maps.
*/
struct pmaplist *
pmap_getmaps(address)
struct sockaddr_in *address;
{
struct pmaplist *head = (struct pmaplist *)NULL;
int socket = -1;
struct timeval minutetimeout;
register CLIENT *client;
minutetimeout.tv_sec = 60;
minutetimeout.tv_usec = 0;
address->sin_port = htons(PMAPPORT);
client = clnttcp_create(address, PMAPPROG,
PMAPVERS, &socket, 50, 500);
if (client != (CLIENT *)NULL) {
if (CLNT_CALL(client, PMAPPROC_DUMP, xdr_void, NULL, xdr_pmaplist,
&head, minutetimeout) != RPC_SUCCESS) {
clnt_perror(client, "pmap_getmaps rpc problem");
}
CLNT_DESTROY(client);
}
(void)close(socket);
address->sin_port = 0;
return (head);
}

View File

@ -0,0 +1,89 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_getport.c,v 1.1 1993/10/27 05:40:36 paul Exp $";
#endif
/*
* pmap_getport.c
* Client interface to pmap rpc service.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <net/if.h>
static struct timeval timeout = { 5, 0 };
static struct timeval tottimeout = { 60, 0 };
/*
* Find the mapped port for program,version.
* Calls the pmap service remotely to do the lookup.
* Returns 0 if no map exists.
*/
u_short
pmap_getport(address, program, version, protocol)
struct sockaddr_in *address;
u_long program;
u_long version;
u_int protocol;
{
u_short port = 0;
int socket = -1;
register CLIENT *client;
struct pmap parms;
address->sin_port = htons(PMAPPORT);
client = clntudp_bufcreate(address, PMAPPROG,
PMAPVERS, timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
if (client != (CLIENT *)NULL) {
parms.pm_prog = program;
parms.pm_vers = version;
parms.pm_prot = protocol;
parms.pm_port = 0; /* not needed or used */
if (CLNT_CALL(client, PMAPPROC_GETPORT, xdr_pmap, &parms,
xdr_u_short, &port, tottimeout) != RPC_SUCCESS){
rpc_createerr.cf_stat = RPC_PMAPFAILURE;
clnt_geterr(client, &rpc_createerr.cf_error);
} else if (port == 0) {
rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
}
CLNT_DESTROY(client);
}
(void)close(socket);
address->sin_port = 0;
return (port);
}

59
lib/libc/rpc/pmap_prot.c Normal file
View File

@ -0,0 +1,59 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_prot.c,v 1.1 1993/10/27 05:40:37 paul Exp $";
#endif
/*
* pmap_prot.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>
bool_t
xdr_pmap(xdrs, regs)
XDR *xdrs;
struct pmap *regs;
{
if (xdr_u_long(xdrs, &regs->pm_prog) &&
xdr_u_long(xdrs, &regs->pm_vers) &&
xdr_u_long(xdrs, &regs->pm_prot))
return (xdr_u_long(xdrs, &regs->pm_port));
return (FALSE);
}

118
lib/libc/rpc/pmap_prot2.c Normal file
View File

@ -0,0 +1,118 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_prot2.c,v 1.1 1993/10/27 05:40:39 paul Exp $";
#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);
}
}

397
lib/libc/rpc/pmap_rmt.c Normal file
View File

@ -0,0 +1,397 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: pmap_rmt.c,v 1.1 1993/10/27 05:40:40 paul Exp $";
#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 <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;
char *cp, *cplim;
int n, i = 0;
ifc.ifc_len = UDPMSGSIZE;
ifc.ifc_buf = buf;
if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
perror("broadcast: ioctl (get interface configuration)");
return (0);
}
#define max(a, b) (a > b ? a : b)
#define size(p) max((p).sa_len, sizeof(p))
cplim = buf + ifc.ifc_len; /*skip over if's with big ifr_addr's */
for (cp = buf; cp < cplim;
cp += sizeof (ifr->ifr_name) + size(ifr->ifr_addr)) {
ifr = (struct ifreq *)cp;
if (ifr->ifr_addr.sa_family != AF_INET)
continue;
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)) {
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),
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),
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;
int on = 1;
#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 SO_BROADCAST
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) {
perror("Cannot set socket option SO_BROADCAST");
stat = RPC_CANTSEND;
goto done_broad;
}
#endif /* def SO_BROADCAST */
#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);
}

1729
lib/libc/rpc/rpc.3 Normal file

File diff suppressed because it is too large Load Diff

71
lib/libc/rpc/rpc.5 Normal file
View File

@ -0,0 +1,71 @@
.\" @(#)rpc.5 2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI;
.TH RPC 5 "26 September 1985"
.SH NAME
rpc \- rpc program number data base
.SH SYNOPSIS
.B /etc/rpc
.SH DESCRIPTION
The
.I rpc
file contains user readable names that
can be used in place of rpc program numbers.
Each line has the following information:
.HP 10
name of server for the rpc program
.br
.ns
.HP 10
rpc program number
.br
.ns
.HP 10
aliases
.LP
Items are separated by any number of blanks and/or
tab characters.
A ``#'' indicates the beginning of a comment; characters up to the end of
the line are not interpreted by routines which search the file.
.LP
Here is an example of the \fI/etc/rpc\fP file from the Sun RPC Source
distribution.
.nf
.ta 1.5i +0.5i +1.0i +1.0i
#
# rpc 88/08/01 4.0 RPCSRC; from 1.12 88/02/07 SMI
#
portmapper 100000 portmap sunrpc
rstatd 100001 rstat rstat_svc rup perfmeter
rusersd 100002 rusers
nfs 100003 nfsprog
ypserv 100004 ypprog
mountd 100005 mount showmount
ypbind 100007
walld 100008 rwall shutdown
yppasswdd 100009 yppasswd
etherstatd 100010 etherstat
rquotad 100011 rquotaprog quota rquota
sprayd 100012 spray
3270_mapper 100013
rje_mapper 100014
selection_svc 100015 selnsvc
database_svc 100016
rexd 100017 rex
alis 100018
sched 100019
llockmgr 100020
nlockmgr 100021
x25.inr 100022
statmon 100023
status 100024
bootparam 100026
ypupdated 100028 ypupdate
keyserv 100029 keyserver
tfsd 100037
nsed 100038
nsemntd 100039
.fi
.DT
.SH FILES
/etc/rpc
.SH "SEE ALSO"
getrpcent(3N)

192
lib/libc/rpc/rpc_callmsg.c Normal file
View File

@ -0,0 +1,192 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: rpc_callmsg.c,v 1.1 1993/10/27 05:40:46 paul Exp $";
#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);
}

View File

@ -0,0 +1,46 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: rpc_commondata.c,v 1.1 1993/10/27 05:40:47 paul Exp $";
#endif
#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;

View File

@ -0,0 +1,48 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/
/*static char *sccsid = "from: @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: rpc_dtablesize.c,v 1.1 1993/10/27 05:40:48 paul Exp $";
#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);
}

291
lib/libc/rpc/rpc_prot.c Normal file
View File

@ -0,0 +1,291 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";*/
static char *rcsid = "$Id: rpc_prot.c,v 1.1 1993/10/27 05:40:50 paul Exp $";
#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 a DES block
*/
bool_t
xdr_des_block(xdrs, blkp)
register XDR *xdrs;
register des_block *blkp;
{
return (xdr_opaque(xdrs, (caddr_t)blkp, sizeof(des_block)));
}
/* * * * * * * * * * * * * * 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;
}
}

57
lib/libc/rpc/rstat.1 Normal file
View File

@ -0,0 +1,57 @@
.\" @(#)rstat.1 2.1 88/08/03 4.0 RPCSRC
.TH RSTAT 1 "3 August 1988"
.SH NAME
rstat \- remote status display
.SH SYNOPSIS
.B rstat
.B host
.SH DESCRIPTION
.LP
.B rstat
displays a summary of the current system status of a particular
.BR host .
The output shows the current time of day, how long the system has
been up,
and the load averages.
The load average numbers give the number of jobs in the run queue
averaged over 1, 5 and 15 minutes.
.PP
The
.B rstat_svc(8c)
daemon must be running on the remote host for this command to
work.
.B rstat
uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x.
.SH EXAMPLE
.RS
.ft B
.nf
example% rstat otherhost
7:36am up 6 days, 16:45, load average: 0.20, 0.23, 0.18
example%
.ft R
.fi
.RE
.SH DIAGNOSTICS
.LP
rstat: RPC: Program not registered
.IP
The
.B rstat_svc
daemon has not been started on the remote host.
.LP
rstat: RPC: Timed out
.IP
A communication error occurred. Either the network is
excessively congested, or the
.B rstat_svc
daemon has terminated on the remote host.
.LP
rstat: RPC: Port mapper failure - RPC: Timed out
.IP
The remote host is not running the portmapper (see
.BR portmap(8c) ),
and cannot accomodate any RPC-based services. The host may be down.
.SH "SEE ALSO"
.BR portmap (8c),
.BR rstat_svc (8c)

21
lib/libc/rpc/rstat_svc.8 Normal file
View File

@ -0,0 +1,21 @@
.\" @(#)rstat_svc.8c 2.2 88/08/03 4.0 RPCSRC; from 1.10 87/09/09 SMI
.TH RSTAT_SVC 8C "24 November 1987"
.SH NAME
rstat_svc \- kernel statistics server
.SH SYNOPSIS
.B /etc/rstat_svc
.SH DESCRIPTION
.LP
.B rstat_svc
is a server which returns performance statistics
obtained from the kernel.
These statistics are graphically displayed by the Sun Microsystems program,
.BR perfmeter (1).
The
.B rstat_svc
daemon is normally invoked at boot time through /etc/rc.local.
.PP
.B rstat_svc
uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x.
.SH "SEE ALSO"
.BR rstat (1),

481
lib/libc/rpc/svc.c Normal file
View File

@ -0,0 +1,481 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc.c 2.4 88/08/11 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc.c,v 1.1 1993/10/27 05:40:54 paul Exp $";
#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 <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 */
enum xprt_stat stat;
struct rpc_msg msg;
int prog_found;
u_long low_vers;
u_long high_vers;
struct svc_req r;
register SVCXPRT *xprt;
register u_long mask;
register int bit;
register u_long *maskp;
register int setsize;
register int sock;
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
setsize = _rpc_dtablesize();
maskp = (u_long *)readfds->fds_bits;
for (sock = 0; sock < setsize; sock += NFDBITS) {
for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) {
/* sock has input waiting */
xprt = xports[sock + bit - 1];
#else
for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) {
if ((readfds_local & 1) != 0) {
/* sock has input waiting */
xprt = xports[sock];
#endif /* def FD_SETSIZE */
/* 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);
}
}
}

117
lib/libc/rpc/svc_auth.c Normal file
View File

@ -0,0 +1,117 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_auth.c 2.1 88/08/07 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_auth.c,v 1.1 1993/10/27 05:40:56 paul Exp $";
#endif
/*
* svc_auth_nodes.c, Server-side rpc authenticator interface,
* *WITHOUT* DES authentication.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
/*
* svcauthsw is the bdevsw of server side authentication.
*
* Server side authenticators are called from authenticate by
* using the client auth struct flavor field to index into svcauthsw.
* The server auth flavors must implement a routine that looks
* like:
*
* enum auth_stat
* flavorx_auth(rqst, msg)
* register struct svc_req *rqst;
* register struct rpc_msg *msg;
*
*/
enum auth_stat _svcauth_null(); /* no authentication */
enum auth_stat _svcauth_unix(); /* unix style (uid, gids) */
enum auth_stat _svcauth_short(); /* short hand unix style */
static struct {
enum auth_stat (*authenticator)();
} svcauthsw[] = {
_svcauth_null, /* AUTH_NULL */
_svcauth_unix, /* AUTH_UNIX */
_svcauth_short, /* AUTH_SHORT */
};
#define AUTH_MAX 2 /* HIGHEST AUTH NUMBER */
/*
* The call rpc message, msg has been obtained from the wire. The msg contains
* the raw form of credentials and verifiers. authenticate returns AUTH_OK
* if the msg is successfully authenticated. If AUTH_OK then the routine also
* does the following things:
* set rqst->rq_xprt->verf to the appropriate response verifier;
* sets rqst->rq_client_cred to the "cooked" form of the credentials.
*
* NB: rqst->rq_cxprt->verf must be pre-alloctaed;
* its length is set appropriately.
*
* The caller still owns and is responsible for msg->u.cmb.cred and
* msg->u.cmb.verf. The authentication system retains ownership of
* rqst->rq_client_cred, the cooked credentials.
*
* There is an assumption that any flavour less than AUTH_NULL is
* invalid.
*/
enum auth_stat
_authenticate(rqst, msg)
register struct svc_req *rqst;
struct rpc_msg *msg;
{
register int cred_flavor;
rqst->rq_cred = msg->rm_call.cb_cred;
rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
rqst->rq_xprt->xp_verf.oa_length = 0;
cred_flavor = rqst->rq_cred.oa_flavor;
if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) {
return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg));
}
return (AUTH_REJECTEDCRED);
}
enum auth_stat
_svcauth_null(/*rqst, msg*/)
/*struct svc_req *rqst;
struct rpc_msg *msg;*/
{
return (AUTH_OK);
}

View File

@ -0,0 +1,136 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_auth_unix.c,v 1.1 1993/10/27 05:40:58 paul Exp $";
#endif
/*
* svc_auth_unix.c
* Handles UNIX flavor authentication parameters on the service side of rpc.
* There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
* _svcauth_unix does full blown unix style uid,gid+gids auth,
* _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
* Note: the shorthand has been gutted for efficiency.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
/*
* Unix longhand authenticator
*/
enum auth_stat
_svcauth_unix(rqst, msg)
register struct svc_req *rqst;
register struct rpc_msg *msg;
{
register enum auth_stat stat;
XDR xdrs;
register struct authunix_parms *aup;
register long *buf;
struct area {
struct authunix_parms area_aup;
char area_machname[MAX_MACHINE_NAME+1];
int area_gids[NGRPS];
} *area;
u_int auth_len;
int str_len, gid_len;
register int i;
area = (struct area *) rqst->rq_clntcred;
aup = &area->area_aup;
aup->aup_machname = area->area_machname;
aup->aup_gids = area->area_gids;
auth_len = (u_int)msg->rm_call.cb_cred.oa_length;
xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
buf = XDR_INLINE(&xdrs, auth_len);
if (buf != NULL) {
aup->aup_time = IXDR_GET_LONG(buf);
str_len = IXDR_GET_U_LONG(buf);
if (str_len > MAX_MACHINE_NAME) {
stat = AUTH_BADCRED;
goto done;
}
bcopy((caddr_t)buf, aup->aup_machname, (u_int)str_len);
aup->aup_machname[str_len] = 0;
str_len = RNDUP(str_len);
buf += str_len / sizeof (long);
aup->aup_uid = IXDR_GET_LONG(buf);
aup->aup_gid = IXDR_GET_LONG(buf);
gid_len = IXDR_GET_U_LONG(buf);
if (gid_len > NGRPS) {
stat = AUTH_BADCRED;
goto done;
}
aup->aup_len = gid_len;
for (i = 0; i < gid_len; i++) {
aup->aup_gids[i] = IXDR_GET_LONG(buf);
}
/*
* five is the smallest unix credentials structure -
* timestamp, hostname len (0), uid, gid, and gids len (0).
*/
if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
(void) printf("bad auth_len gid %d str %d auth %d\n",
gid_len, str_len, auth_len);
stat = AUTH_BADCRED;
goto done;
}
} else if (! xdr_authunix_parms(&xdrs, aup)) {
xdrs.x_op = XDR_FREE;
(void)xdr_authunix_parms(&xdrs, aup);
stat = AUTH_BADCRED;
goto done;
}
rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
rqst->rq_xprt->xp_verf.oa_length = 0;
stat = AUTH_OK;
done:
XDR_DESTROY(&xdrs);
return (stat);
}
/*
* Shorthand unix authenticator
* Looks up longhand in a cache.
*/
/*ARGSUSED*/
enum auth_stat
_svcauth_short(rqst, msg)
struct svc_req *rqst;
struct rpc_msg *msg;
{
return (AUTH_REJECTEDCRED);
}

168
lib/libc/rpc/svc_raw.c Normal file
View File

@ -0,0 +1,168 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_raw.c,v 1.1 1993/10/27 05:40:59 paul Exp $";
#endif
/*
* svc_raw.c, This a toy for simple testing and timing.
* Interface to create an rpc client and server in the same UNIX process.
* This lets us similate rpc and get rpc (round trip) overhead, without
* any interference from the kernal.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <rpc/rpc.h>
/*
* This is the "network" that we will be moving data over
*/
static struct svcraw_private {
char _raw_buf[UDPMSGSIZE];
SVCXPRT server;
XDR xdr_stream;
char verf_body[MAX_AUTH_BYTES];
} *svcraw_private;
static bool_t svcraw_recv();
static enum xprt_stat svcraw_stat();
static bool_t svcraw_getargs();
static bool_t svcraw_reply();
static bool_t svcraw_freeargs();
static void svcraw_destroy();
static struct xp_ops server_ops = {
svcraw_recv,
svcraw_stat,
svcraw_getargs,
svcraw_reply,
svcraw_freeargs,
svcraw_destroy
};
SVCXPRT *
svcraw_create()
{
register struct svcraw_private *srp = svcraw_private;
if (srp == 0) {
srp = (struct svcraw_private *)calloc(1, sizeof (*srp));
if (srp == 0)
return (0);
}
srp->server.xp_sock = 0;
srp->server.xp_port = 0;
srp->server.xp_ops = &server_ops;
srp->server.xp_verf.oa_base = srp->verf_body;
xdrmem_create(&srp->xdr_stream, srp->_raw_buf, UDPMSGSIZE, XDR_FREE);
return (&srp->server);
}
static enum xprt_stat
svcraw_stat()
{
return (XPRT_IDLE);
}
static bool_t
svcraw_recv(xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
register struct svcraw_private *srp = svcraw_private;
register XDR *xdrs;
if (srp == 0)
return (0);
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_DECODE;
XDR_SETPOS(xdrs, 0);
if (! xdr_callmsg(xdrs, msg))
return (FALSE);
return (TRUE);
}
static bool_t
svcraw_reply(xprt, msg)
SVCXPRT *xprt;
struct rpc_msg *msg;
{
register struct svcraw_private *srp = svcraw_private;
register XDR *xdrs;
if (srp == 0)
return (FALSE);
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, 0);
if (! xdr_replymsg(xdrs, msg))
return (FALSE);
(void)XDR_GETPOS(xdrs); /* called just for overhead */
return (TRUE);
}
static bool_t
svcraw_getargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
register struct svcraw_private *srp = svcraw_private;
if (srp == 0)
return (FALSE);
return ((*xdr_args)(&srp->xdr_stream, args_ptr));
}
static bool_t
svcraw_freeargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
register struct svcraw_private *srp = svcraw_private;
register XDR *xdrs;
if (srp == 0)
return (FALSE);
xdrs = &srp->xdr_stream;
xdrs->x_op = XDR_FREE;
return ((*xdr_args)(xdrs, args_ptr));
}
static void
svcraw_destroy()
{
}

73
lib/libc/rpc/svc_run.c Normal file
View File

@ -0,0 +1,73 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_run.c,v 1.1 1993/10/27 05:41:00 paul Exp $";
#endif
/*
* This is the rpc server side idle loop
* Wait for input, call server program.
*/
#include <rpc/rpc.h>
#include <sys/errno.h>
void
svc_run()
{
#ifdef FD_SETSIZE
fd_set readfds;
#else
int readfds;
#endif /* def FD_SETSIZE */
extern int errno;
for (;;) {
#ifdef FD_SETSIZE
readfds = svc_fdset;
#else
readfds = svc_fds;
#endif /* def FD_SETSIZE */
switch (select(_rpc_dtablesize(), &readfds, (int *)0, (int *)0,
(struct timeval *)0)) {
case -1:
if (errno == EINTR) {
continue;
}
perror("svc_run: - select failed");
return;
case 0:
continue;
default:
svc_getreqset(&readfds);
}
}
}

145
lib/libc/rpc/svc_simple.c Normal file
View File

@ -0,0 +1,145 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_simple.c,v 1.1 1993/10/27 05:41:01 paul Exp $";
#endif
/*
* svc_simple.c
* Simplified front end to rpc.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <netdb.h>
static struct proglst {
char *(*p_progname)();
int p_prognum;
int p_procnum;
xdrproc_t p_inproc, p_outproc;
struct proglst *p_nxt;
} *proglst;
static void universal();
static SVCXPRT *transp;
struct proglst *pl;
registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
char *(*progname)();
xdrproc_t inproc, outproc;
{
if (procnum == NULLPROC) {
(void) fprintf(stderr,
"can't reassign procedure number %d\n", NULLPROC);
return (-1);
}
if (transp == 0) {
transp = svcudp_create(RPC_ANYSOCK);
if (transp == NULL) {
(void) fprintf(stderr, "couldn't create an rpc server\n");
return (-1);
}
}
(void) pmap_unset((u_long)prognum, (u_long)versnum);
if (!svc_register(transp, (u_long)prognum, (u_long)versnum,
universal, IPPROTO_UDP)) {
(void) fprintf(stderr, "couldn't register prog %d vers %d\n",
prognum, versnum);
return (-1);
}
pl = (struct proglst *)malloc(sizeof(struct proglst));
if (pl == NULL) {
(void) fprintf(stderr, "registerrpc: out of memory\n");
return (-1);
}
pl->p_progname = progname;
pl->p_prognum = prognum;
pl->p_procnum = procnum;
pl->p_inproc = inproc;
pl->p_outproc = outproc;
pl->p_nxt = proglst;
proglst = pl;
return (0);
}
static void
universal(rqstp, transp)
struct svc_req *rqstp;
SVCXPRT *transp;
{
int prog, proc;
char *outdata;
char xdrbuf[UDPMSGSIZE];
struct proglst *pl;
/*
* enforce "procnum 0 is echo" convention
*/
if (rqstp->rq_proc == NULLPROC) {
if (svc_sendreply(transp, xdr_void, (char *)NULL) == FALSE) {
(void) fprintf(stderr, "xxx\n");
exit(1);
}
return;
}
prog = rqstp->rq_prog;
proc = rqstp->rq_proc;
for (pl = proglst; pl != NULL; pl = pl->p_nxt)
if (pl->p_prognum == prog && pl->p_procnum == proc) {
/* decode arguments into a CLEAN buffer */
bzero(xdrbuf, sizeof(xdrbuf)); /* required ! */
if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
svcerr_decode(transp);
return;
}
outdata = (*(pl->p_progname))(xdrbuf);
if (outdata == NULL && pl->p_outproc != xdr_void)
/* there was an error */
return;
if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
(void) fprintf(stderr,
"trouble replying to prog %d\n",
pl->p_prognum);
exit(1);
}
/* free the decoded arguments */
(void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
return;
}
(void) fprintf(stderr, "never registered prog %d\n", prog);
exit(1);
}

421
lib/libc/rpc/svc_tcp.c Normal file
View File

@ -0,0 +1,421 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_tcp.c,v 1.1 1993/10/27 05:41:02 paul Exp $";
#endif
/*
* svc_tcp.c, Server side for TCP/IP based RPC.
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*
* Actually implements two flavors of transporter -
* a tcp rendezvouser (a listner and connection establisher)
* and a record/tcp stream.
*/
#include <stdio.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <errno.h>
extern bool_t abort();
extern errno;
/*
* Ops vector for TCP/IP based rpc service handle
*/
static bool_t svctcp_recv();
static enum xprt_stat svctcp_stat();
static bool_t svctcp_getargs();
static bool_t svctcp_reply();
static bool_t svctcp_freeargs();
static void svctcp_destroy();
static struct xp_ops svctcp_op = {
svctcp_recv,
svctcp_stat,
svctcp_getargs,
svctcp_reply,
svctcp_freeargs,
svctcp_destroy
};
/*
* Ops vector for TCP/IP rendezvous handler
*/
static bool_t rendezvous_request();
static enum xprt_stat rendezvous_stat();
static struct xp_ops svctcp_rendezvous_op = {
rendezvous_request,
rendezvous_stat,
abort,
abort,
abort,
svctcp_destroy
};
static int readtcp(), writetcp();
static SVCXPRT *makefd_xprt();
struct tcp_rendezvous { /* kept in xprt->xp_p1 */
u_int sendsize;
u_int recvsize;
};
struct tcp_conn { /* kept in xprt->xp_p1 */
enum xprt_stat strm_stat;
u_long x_id;
XDR xdrs;
char verf_body[MAX_AUTH_BYTES];
};
/*
* Usage:
* xprt = svctcp_create(sock, send_buf_size, recv_buf_size);
*
* Creates, registers, and returns a (rpc) tcp based transporter.
* Once *xprt is initialized, it is registered as a transporter
* see (svc.h, xprt_register). This routine returns
* a NULL if a problem occurred.
*
* If sock<0 then a socket is created, else sock is used.
* If the socket, sock is not bound to a port then svctcp_create
* binds it to an arbitrary port. The routine then starts a tcp
* listener on the socket's associated port. In any (successful) case,
* xprt->xp_sock is the registered socket number and xprt->xp_port is the
* associated port number.
*
* Since tcp streams do buffered io similar to stdio, the caller can specify
* how big the send and receive buffers are via the second and third parms;
* 0 => use the system default.
*/
SVCXPRT *
svctcp_create(sock, sendsize, recvsize)
register int sock;
u_int sendsize;
u_int recvsize;
{
bool_t madesock = FALSE;
register SVCXPRT *xprt;
register struct tcp_rendezvous *r;
struct sockaddr_in addr;
int len = sizeof(struct sockaddr_in);
if (sock == RPC_ANYSOCK) {
if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("svctcp_.c - udp socket creation problem");
return ((SVCXPRT *)NULL);
}
madesock = TRUE;
}
bzero((char *)&addr, sizeof (addr));
addr.sin_family = AF_INET;
if (bindresvport(sock, &addr)) {
addr.sin_port = 0;
(void)bind(sock, (struct sockaddr *)&addr, len);
}
if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0) ||
(listen(sock, 2) != 0)) {
perror("svctcp_.c - cannot getsockname or listen");
if (madesock)
(void)close(sock);
return ((SVCXPRT *)NULL);
}
r = (struct tcp_rendezvous *)mem_alloc(sizeof(*r));
if (r == NULL) {
(void) fprintf(stderr, "svctcp_create: out of memory\n");
return (NULL);
}
r->sendsize = sendsize;
r->recvsize = recvsize;
xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
if (xprt == NULL) {
(void) fprintf(stderr, "svctcp_create: out of memory\n");
return (NULL);
}
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t)r;
xprt->xp_verf = _null_auth;
xprt->xp_ops = &svctcp_rendezvous_op;
xprt->xp_port = ntohs(addr.sin_port);
xprt->xp_sock = sock;
xprt_register(xprt);
return (xprt);
}
/*
* Like svtcp_create(), except the routine takes any *open* UNIX file
* descriptor as its first input.
*/
SVCXPRT *
svcfd_create(fd, sendsize, recvsize)
int fd;
u_int sendsize;
u_int recvsize;
{
return (makefd_xprt(fd, sendsize, recvsize));
}
static SVCXPRT *
makefd_xprt(fd, sendsize, recvsize)
int fd;
u_int sendsize;
u_int recvsize;
{
register SVCXPRT *xprt;
register struct tcp_conn *cd;
xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
if (xprt == (SVCXPRT *)NULL) {
(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
goto done;
}
cd = (struct tcp_conn *)mem_alloc(sizeof(struct tcp_conn));
if (cd == (struct tcp_conn *)NULL) {
(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n");
mem_free((char *) xprt, sizeof(SVCXPRT));
xprt = (SVCXPRT *)NULL;
goto done;
}
cd->strm_stat = XPRT_IDLE;
xdrrec_create(&(cd->xdrs), sendsize, recvsize,
(caddr_t)xprt, readtcp, writetcp);
xprt->xp_p2 = NULL;
xprt->xp_p1 = (caddr_t)cd;
xprt->xp_verf.oa_base = cd->verf_body;
xprt->xp_addrlen = 0;
xprt->xp_ops = &svctcp_op; /* truely deals with calls */
xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
xprt->xp_sock = fd;
xprt_register(xprt);
done:
return (xprt);
}
static bool_t
rendezvous_request(xprt)
register SVCXPRT *xprt;
{
int sock;
struct tcp_rendezvous *r;
struct sockaddr_in addr;
int len;
r = (struct tcp_rendezvous *)xprt->xp_p1;
again:
len = sizeof(struct sockaddr_in);
if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr,
&len)) < 0) {
if (errno == EINTR)
goto again;
return (FALSE);
}
/*
* make a new transporter (re-uses xprt)
*/
xprt = makefd_xprt(sock, r->sendsize, r->recvsize);
xprt->xp_raddr = addr;
xprt->xp_addrlen = len;
return (FALSE); /* there is never an rpc msg to be processed */
}
static enum xprt_stat
rendezvous_stat()
{
return (XPRT_IDLE);
}
static void
svctcp_destroy(xprt)
register SVCXPRT *xprt;
{
register struct tcp_conn *cd = (struct tcp_conn *)xprt->xp_p1;
xprt_unregister(xprt);
(void)close(xprt->xp_sock);
if (xprt->xp_port != 0) {
/* a rendezvouser socket */
xprt->xp_port = 0;
} else {
/* an actual connection socket */
XDR_DESTROY(&(cd->xdrs));
}
mem_free((caddr_t)cd, sizeof(struct tcp_conn));
mem_free((caddr_t)xprt, sizeof(SVCXPRT));
}
/*
* All read operations timeout after 35 seconds.
* A timeout is fatal for the connection.
*/
static struct timeval wait_per_try = { 35, 0 };
/*
* reads data from the tcp conection.
* any error is fatal and the connection is closed.
* (And a read of zero bytes is a half closed stream => error.)
*/
static int
readtcp(xprt, buf, len)
register SVCXPRT *xprt;
caddr_t buf;
register int len;
{
register int sock = xprt->xp_sock;
#ifdef FD_SETSIZE
fd_set mask;
fd_set readfds;
FD_ZERO(&mask);
FD_SET(sock, &mask);
#else
register int mask = 1 << sock;
int readfds;
#endif /* def FD_SETSIZE */
do {
readfds = mask;
if (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL,
&wait_per_try) <= 0) {
if (errno == EINTR) {
continue;
}
goto fatal_err;
}
#ifdef FD_SETSIZE
} while (!FD_ISSET(sock, &readfds));
#else
} while (readfds != mask);
#endif /* def FD_SETSIZE */
if ((len = read(sock, buf, len)) > 0) {
return (len);
}
fatal_err:
((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
return (-1);
}
/*
* writes data to the tcp connection.
* Any error is fatal and the connection is closed.
*/
static int
writetcp(xprt, buf, len)
register SVCXPRT *xprt;
caddr_t buf;
int len;
{
register int i, cnt;
for (cnt = len; cnt > 0; cnt -= i, buf += i) {
if ((i = write(xprt->xp_sock, buf, cnt)) < 0) {
((struct tcp_conn *)(xprt->xp_p1))->strm_stat =
XPRT_DIED;
return (-1);
}
}
return (len);
}
static enum xprt_stat
svctcp_stat(xprt)
SVCXPRT *xprt;
{
register struct tcp_conn *cd =
(struct tcp_conn *)(xprt->xp_p1);
if (cd->strm_stat == XPRT_DIED)
return (XPRT_DIED);
if (! xdrrec_eof(&(cd->xdrs)))
return (XPRT_MOREREQS);
return (XPRT_IDLE);
}
static bool_t
svctcp_recv(xprt, msg)
SVCXPRT *xprt;
register struct rpc_msg *msg;
{
register struct tcp_conn *cd =
(struct tcp_conn *)(xprt->xp_p1);
register XDR *xdrs = &(cd->xdrs);
xdrs->x_op = XDR_DECODE;
(void)xdrrec_skiprecord(xdrs);
if (xdr_callmsg(xdrs, msg)) {
cd->x_id = msg->rm_xid;
return (TRUE);
}
return (FALSE);
}
static bool_t
svctcp_getargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
return ((*xdr_args)(&(((struct tcp_conn *)(xprt->xp_p1))->xdrs), args_ptr));
}
static bool_t
svctcp_freeargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
register XDR *xdrs =
&(((struct tcp_conn *)(xprt->xp_p1))->xdrs);
xdrs->x_op = XDR_FREE;
return ((*xdr_args)(xdrs, args_ptr));
}
static bool_t
svctcp_reply(xprt, msg)
SVCXPRT *xprt;
register struct rpc_msg *msg;
{
register struct tcp_conn *cd =
(struct tcp_conn *)(xprt->xp_p1);
register XDR *xdrs = &(cd->xdrs);
register bool_t stat;
xdrs->x_op = XDR_ENCODE;
msg->rm_xid = cd->x_id;
stat = xdr_replymsg(xdrs, msg);
(void)xdrrec_endofrecord(xdrs, TRUE);
return (stat);
}

480
lib/libc/rpc/svc_udp.c Normal file
View File

@ -0,0 +1,480 @@
/*
* 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(LIBC_SCCS) && !defined(lint)
/*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/
/*static char *sccsid = "from: @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC";*/
static char *rcsid = "$Id: svc_udp.c,v 1.1 1993/10/27 05:41:03 paul Exp $";
#endif
/*
* svc_udp.c,
* Server side for UDP/IP based RPC. (Does some caching in the hopes of
* achieving execute-at-most-once semantics.)
*
* Copyright (C) 1984, Sun Microsystems, Inc.
*/
#include <stdio.h>
#include <stdlib.h>
#include <rpc/rpc.h>
#include <sys/socket.h>
#include <errno.h>
#define rpc_buffer(xprt) ((xprt)->xp_p1)
#define MAX(a, b) ((a > b) ? a : b)
static bool_t svcudp_recv();
static bool_t svcudp_reply();
static enum xprt_stat svcudp_stat();
static bool_t svcudp_getargs();
static bool_t svcudp_freeargs();
static void svcudp_destroy();
static struct xp_ops svcudp_op = {
svcudp_recv,
svcudp_stat,
svcudp_getargs,
svcudp_reply,
svcudp_freeargs,
svcudp_destroy
};
extern int errno;
/*
* kept in xprt->xp_p2
*/
struct svcudp_data {
u_int su_iosz; /* byte size of send.recv buffer */
u_long su_xid; /* transaction id */
XDR su_xdrs; /* XDR handle */
char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
char * su_cache; /* cached data, NULL if no cache */
};
#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2))
/*
* Usage:
* xprt = svcudp_create(sock);
*
* If sock<0 then a socket is created, else sock is used.
* If the socket, sock is not bound to a port then svcudp_create
* binds it to an arbitrary port. In any (successful) case,
* xprt->xp_sock is the registered socket number and xprt->xp_port is the
* associated port number.
* Once *xprt is initialized, it is registered as a transporter;
* see (svc.h, xprt_register).
* The routines returns NULL if a problem occurred.
*/
SVCXPRT *
svcudp_bufcreate(sock, sendsz, recvsz)
register int sock;
u_int sendsz, recvsz;
{
bool_t madesock = FALSE;
register SVCXPRT *xprt;
register struct svcudp_data *su;
struct sockaddr_in addr;
int len = sizeof(struct sockaddr_in);
if (sock == RPC_ANYSOCK) {
if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
perror("svcudp_create: socket creation problem");
return ((SVCXPRT *)NULL);
}
madesock = TRUE;
}
bzero((char *)&addr, sizeof (addr));
addr.sin_family = AF_INET;
if (bindresvport(sock, &addr)) {
addr.sin_port = 0;
(void)bind(sock, (struct sockaddr *)&addr, len);
}
if (getsockname(sock, (struct sockaddr *)&addr, &len) != 0) {
perror("svcudp_create - cannot getsockname");
if (madesock)
(void)close(sock);
return ((SVCXPRT *)NULL);
}
xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));
if (xprt == NULL) {
(void)fprintf(stderr, "svcudp_create: out of memory\n");
return (NULL);
}
su = (struct svcudp_data *)mem_alloc(sizeof(*su));
if (su == NULL) {
(void)fprintf(stderr, "svcudp_create: out of memory\n");
return (NULL);
}
su->su_iosz = ((MAX(sendsz, recvsz) + 3) / 4) * 4;
if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL) {
(void)fprintf(stderr, "svcudp_create: out of memory\n");
return (NULL);
}
xdrmem_create(
&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE);
su->su_cache = NULL;
xprt->xp_p2 = (caddr_t)su;
xprt->xp_verf.oa_base = su->su_verfbody;
xprt->xp_ops = &svcudp_op;
xprt->xp_port = ntohs(addr.sin_port);
xprt->xp_sock = sock;
xprt_register(xprt);
return (xprt);
}
SVCXPRT *
svcudp_create(sock)
int sock;
{
return(svcudp_bufcreate(sock, UDPMSGSIZE, UDPMSGSIZE));
}
static enum xprt_stat
svcudp_stat(xprt)
SVCXPRT *xprt;
{
return (XPRT_IDLE);
}
static bool_t
svcudp_recv(xprt, msg)
register SVCXPRT *xprt;
struct rpc_msg *msg;
{
register struct svcudp_data *su = su_data(xprt);
register XDR *xdrs = &(su->su_xdrs);
register int rlen;
char *reply;
u_long replylen;
static int cache_get();
again:
xprt->xp_addrlen = sizeof(struct sockaddr_in);
rlen = recvfrom(xprt->xp_sock, rpc_buffer(xprt), (int) su->su_iosz,
0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));
if (rlen == -1 && errno == EINTR)
goto again;
if (rlen < 4*sizeof(u_long))
return (FALSE);
xdrs->x_op = XDR_DECODE;
XDR_SETPOS(xdrs, 0);
if (! xdr_callmsg(xdrs, msg))
return (FALSE);
su->su_xid = msg->rm_xid;
if (su->su_cache != NULL) {
if (cache_get(xprt, msg, &reply, &replylen)) {
(void) sendto(xprt->xp_sock, reply, (int) replylen, 0,
(struct sockaddr *) &xprt->xp_raddr, xprt->xp_addrlen);
return (TRUE);
}
}
return (TRUE);
}
static bool_t
svcudp_reply(xprt, msg)
register SVCXPRT *xprt;
struct rpc_msg *msg;
{
register struct svcudp_data *su = su_data(xprt);
register XDR *xdrs = &(su->su_xdrs);
register int slen;
register bool_t stat = FALSE;
static void cache_set();
xdrs->x_op = XDR_ENCODE;
XDR_SETPOS(xdrs, 0);
msg->rm_xid = su->su_xid;
if (xdr_replymsg(xdrs, msg)) {
slen = (int)XDR_GETPOS(xdrs);
if (sendto(xprt->xp_sock, rpc_buffer(xprt), slen, 0,
(struct sockaddr *)&(xprt->xp_raddr), xprt->xp_addrlen)
== slen) {
stat = TRUE;
if (su->su_cache && slen >= 0) {
cache_set(xprt, (u_long) slen);
}
}
}
return (stat);
}
static bool_t
svcudp_getargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
return ((*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr));
}
static bool_t
svcudp_freeargs(xprt, xdr_args, args_ptr)
SVCXPRT *xprt;
xdrproc_t xdr_args;
caddr_t args_ptr;
{
register XDR *xdrs = &(su_data(xprt)->su_xdrs);
xdrs->x_op = XDR_FREE;
return ((*xdr_args)(xdrs, args_ptr));
}
static void
svcudp_destroy(xprt)
register SVCXPRT *xprt;
{
register struct svcudp_data *su = su_data(xprt);
xprt_unregister(xprt);
(void)close(xprt->xp_sock);
XDR_DESTROY(&(su->su_xdrs));
mem_free(rpc_buffer(xprt), su->su_iosz);
mem_free((caddr_t)su, sizeof(struct svcudp_data));
mem_free((caddr_t)xprt, sizeof(SVCXPRT));
}
/***********this could be a separate file*********************/
/*
* Fifo cache for udp server
* Copies pointers to reply buffers into fifo cache
* Buffers are sent again if retransmissions are detected.
*/
#define SPARSENESS 4 /* 75% sparse */
#define CACHE_PERROR(msg) \
(void) fprintf(stderr,"%s\n", msg)
#define ALLOC(type, size) \
(type *) mem_alloc((unsigned) (sizeof(type) * (size)))
#define BZERO(addr, type, size) \
bzero((char *) addr, sizeof(type) * (int) (size))
/*
* An entry in the cache
*/
typedef struct cache_node *cache_ptr;
struct cache_node {
/*
* Index into cache is xid, proc, vers, prog and address
*/
u_long cache_xid;
u_long cache_proc;
u_long cache_vers;
u_long cache_prog;
struct sockaddr_in cache_addr;
/*
* The cached reply and length
*/
char * cache_reply;
u_long cache_replylen;
/*
* Next node on the list, if there is a collision
*/
cache_ptr cache_next;
};
/*
* The entire cache
*/
struct udp_cache {
u_long uc_size; /* size of cache */
cache_ptr *uc_entries; /* hash table of entries in cache */
cache_ptr *uc_fifo; /* fifo list of entries in cache */
u_long uc_nextvictim; /* points to next victim in fifo list */
u_long uc_prog; /* saved program number */
u_long uc_vers; /* saved version number */
u_long uc_proc; /* saved procedure number */
struct sockaddr_in uc_addr; /* saved caller's address */
};
/*
* the hashing function
*/
#define CACHE_LOC(transp, xid) \
(xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))
/*
* Enable use of the cache.
* Note: there is no disable.
*/
svcudp_enablecache(transp, size)
SVCXPRT *transp;
u_long size;
{
struct svcudp_data *su = su_data(transp);
struct udp_cache *uc;
if (su->su_cache != NULL) {
CACHE_PERROR("enablecache: cache already enabled");
return(0);
}
uc = ALLOC(struct udp_cache, 1);
if (uc == NULL) {
CACHE_PERROR("enablecache: could not allocate cache");
return(0);
}
uc->uc_size = size;
uc->uc_nextvictim = 0;
uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
if (uc->uc_entries == NULL) {
CACHE_PERROR("enablecache: could not allocate cache data");
return(0);
}
BZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
uc->uc_fifo = ALLOC(cache_ptr, size);
if (uc->uc_fifo == NULL) {
CACHE_PERROR("enablecache: could not allocate cache fifo");
return(0);
}
BZERO(uc->uc_fifo, cache_ptr, size);
su->su_cache = (char *) uc;
return(1);
}
/*
* Set an entry in the cache
*/
static void
cache_set(xprt, replylen)
SVCXPRT *xprt;
u_long replylen;
{
register cache_ptr victim;
register cache_ptr *vicp;
register struct svcudp_data *su = su_data(xprt);
struct udp_cache *uc = (struct udp_cache *) su->su_cache;
u_int loc;
char *newbuf;
/*
* Find space for the new entry, either by
* reusing an old entry, or by mallocing a new one
*/
victim = uc->uc_fifo[uc->uc_nextvictim];
if (victim != NULL) {
loc = CACHE_LOC(xprt, victim->cache_xid);
for (vicp = &uc->uc_entries[loc];
*vicp != NULL && *vicp != victim;
vicp = &(*vicp)->cache_next)
;
if (*vicp == NULL) {
CACHE_PERROR("cache_set: victim not found");
return;
}
*vicp = victim->cache_next; /* remote from cache */
newbuf = victim->cache_reply;
} else {
victim = ALLOC(struct cache_node, 1);
if (victim == NULL) {
CACHE_PERROR("cache_set: victim alloc failed");
return;
}
newbuf = mem_alloc(su->su_iosz);
if (newbuf == NULL) {
CACHE_PERROR("cache_set: could not allocate new rpc_buffer");
return;
}
}
/*
* Store it away
*/
victim->cache_replylen = replylen;
victim->cache_reply = rpc_buffer(xprt);
rpc_buffer(xprt) = newbuf;
xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_ENCODE);
victim->cache_xid = su->su_xid;
victim->cache_proc = uc->uc_proc;
victim->cache_vers = uc->uc_vers;
victim->cache_prog = uc->uc_prog;
victim->cache_addr = uc->uc_addr;
loc = CACHE_LOC(xprt, victim->cache_xid);
victim->cache_next = uc->uc_entries[loc];
uc->uc_entries[loc] = victim;
uc->uc_fifo[uc->uc_nextvictim++] = victim;
uc->uc_nextvictim %= uc->uc_size;
}
/*
* Try to get an entry from the cache
* return 1 if found, 0 if not found
*/
static
cache_get(xprt, msg, replyp, replylenp)
SVCXPRT *xprt;
struct rpc_msg *msg;
char **replyp;
u_long *replylenp;
{
u_int loc;
register cache_ptr ent;
register struct svcudp_data *su = su_data(xprt);
register struct udp_cache *uc = (struct udp_cache *) su->su_cache;
# define EQADDR(a1, a2) (bcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0)
loc = CACHE_LOC(xprt, su->su_xid);
for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
if (ent->cache_xid == su->su_xid &&
ent->cache_proc == uc->uc_proc &&
ent->cache_vers == uc->uc_vers &&
ent->cache_prog == uc->uc_prog &&
EQADDR(ent->cache_addr, uc->uc_addr)) {
*replyp = ent->cache_reply;
*replylenp = ent->cache_replylen;
return(1);
}
}
/*
* Failed to find entry
* Remember a few things so we can do a set later
*/
uc->uc_proc = msg->rm_call.cb_proc;
uc->uc_vers = msg->rm_call.cb_vers;
uc->uc_prog = msg->rm_call.cb_prog;
uc->uc_addr = xprt->xp_raddr;
return(0);
}