aboutsummaryrefslogtreecommitdiff
path: root/lib/libc/rpc
diff options
context:
space:
mode:
authorsvn2git <svn2git@FreeBSD.org>1994-05-01 08:00:00 +0000
committersvn2git <svn2git@FreeBSD.org>1994-05-01 08:00:00 +0000
commita16f65c7d117419bd266c28a1901ef129a337569 (patch)
tree2626602f66dc3551e7a7c7bc9ad763c3bc7ab40a /lib/libc/rpc
parent8503f4f13f77abf7adc8f7e329c6f9c1d52b6a20 (diff)
Diffstat (limited to 'lib/libc/rpc')
-rw-r--r--lib/libc/rpc/DISCLAIMER28
-rw-r--r--lib/libc/rpc/Makefile.inc39
-rw-r--r--lib/libc/rpc/README233
-rw-r--r--lib/libc/rpc/auth.h178
-rw-r--r--lib/libc/rpc/auth_none.c135
-rw-r--r--lib/libc/rpc/auth_unix.c322
-rw-r--r--lib/libc/rpc/auth_unix.h82
-rw-r--r--lib/libc/rpc/authunix_prot.c68
-rw-r--r--lib/libc/rpc/bindresvport.327
-rw-r--r--lib/libc/rpc/bindresvport.c84
-rw-r--r--lib/libc/rpc/clnt.h358
-rw-r--r--lib/libc/rpc/clnt_generic.c113
-rw-r--r--lib/libc/rpc/clnt_perror.c303
-rw-r--r--lib/libc/rpc/clnt_raw.c240
-rw-r--r--lib/libc/rpc/clnt_simple.c115
-rw-r--r--lib/libc/rpc/clnt_tcp.c468
-rw-r--r--lib/libc/rpc/clnt_udp.c444
-rw-r--r--lib/libc/rpc/get_myaddress.c99
-rw-r--r--lib/libc/rpc/getrpcent.3109
-rw-r--r--lib/libc/rpc/getrpcent.c298
-rw-r--r--lib/libc/rpc/getrpcport.331
-rw-r--r--lib/libc/rpc/getrpcport.c57
-rw-r--r--lib/libc/rpc/pmap_clnt.c117
-rw-r--r--lib/libc/rpc/pmap_clnt.h84
-rw-r--r--lib/libc/rpc/pmap_getmaps.c86
-rw-r--r--lib/libc/rpc/pmap_getport.c89
-rw-r--r--lib/libc/rpc/pmap_prot.c59
-rw-r--r--lib/libc/rpc/pmap_prot.h104
-rw-r--r--lib/libc/rpc/pmap_prot2.c118
-rw-r--r--lib/libc/rpc/pmap_rmt.c397
-rw-r--r--lib/libc/rpc/pmap_rmt.h63
-rw-r--r--lib/libc/rpc/rpc.31729
-rw-r--r--lib/libc/rpc/rpc.571
-rw-r--r--lib/libc/rpc/rpc.h89
-rw-r--r--lib/libc/rpc/rpc_callmsg.c192
-rw-r--r--lib/libc/rpc/rpc_commondata.c46
-rw-r--r--lib/libc/rpc/rpc_dtablesize.c48
-rw-r--r--lib/libc/rpc/rpc_msg.h195
-rw-r--r--lib/libc/rpc/rpc_prot.c291
-rw-r--r--lib/libc/rpc/rstat.157
-rw-r--r--lib/libc/rpc/rstat_svc.821
-rw-r--r--lib/libc/rpc/svc.c481
-rw-r--r--lib/libc/rpc/svc.h302
-rw-r--r--lib/libc/rpc/svc_auth.c117
-rw-r--r--lib/libc/rpc/svc_auth.h50
-rw-r--r--lib/libc/rpc/svc_auth_unix.c136
-rw-r--r--lib/libc/rpc/svc_raw.c168
-rw-r--r--lib/libc/rpc/svc_run.c73
-rw-r--r--lib/libc/rpc/svc_simple.c145
-rw-r--r--lib/libc/rpc/svc_tcp.c421
-rw-r--r--lib/libc/rpc/svc_udp.c480
-rw-r--r--lib/libc/rpc/types.h66
-rw-r--r--lib/libc/rpc/xdr.3823
-rw-r--r--lib/libc/rpc/xdr.c578
-rw-r--r--lib/libc/rpc/xdr.h291
-rw-r--r--lib/libc/rpc/xdr_array.c155
-rw-r--r--lib/libc/rpc/xdr_float.c283
-rw-r--r--lib/libc/rpc/xdr_mem.c186
-rw-r--r--lib/libc/rpc/xdr_rec.c586
-rw-r--r--lib/libc/rpc/xdr_reference.c134
-rw-r--r--lib/libc/rpc/xdr_stdio.c191
61 files changed, 13353 insertions, 0 deletions
diff --git a/lib/libc/rpc/DISCLAIMER b/lib/libc/rpc/DISCLAIMER
new file mode 100644
index 000000000000..1a66d5f4c9cd
--- /dev/null
+++ b/lib/libc/rpc/DISCLAIMER
@@ -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
+ */
diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc
new file mode 100644
index 000000000000..8776d9d8eee9
--- /dev/null
+++ b/lib/libc/rpc/Makefile.inc
@@ -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
diff --git a/lib/libc/rpc/README b/lib/libc/rpc/README
new file mode 100644
index 000000000000..ad9d70f99056
--- /dev/null
+++ b/lib/libc/rpc/README
@@ -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".
diff --git a/lib/libc/rpc/auth.h b/lib/libc/rpc/auth.h
new file mode 100644
index 000000000000..e7db1d01fcb4
--- /dev/null
+++ b/lib/libc/rpc/auth.h
@@ -0,0 +1,178 @@
+/*
+ * 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
+ *
+ * from: @(#)auth.h 1.17 88/02/08 SMI
+ * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC
+ * $Id: auth.h,v 1.1 1993/10/27 05:40:09 paul Exp $
+ */
+
+/*
+ * auth.h, Authentication interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The data structures are completely opaque to the client. The client
+ * is required to pass a AUTH * to routines that create rpc
+ * "sessions".
+ */
+
+#ifndef _RPC_AUTH_H
+#define _RPC_AUTH_H
+#include <sys/cdefs.h>
+
+#define MAX_AUTH_BYTES 400
+#define MAXNETNAMELEN 255 /* maximum length of network user's name */
+
+/*
+ * Status returned from authentication check
+ */
+enum auth_stat {
+ AUTH_OK=0,
+ /*
+ * failed at remote end
+ */
+ AUTH_BADCRED=1, /* bogus credentials (seal broken) */
+ AUTH_REJECTEDCRED=2, /* client should begin new session */
+ AUTH_BADVERF=3, /* bogus verifier (seal broken) */
+ AUTH_REJECTEDVERF=4, /* verifier expired or was replayed */
+ AUTH_TOOWEAK=5, /* rejected due to security reasons */
+ /*
+ * failed locally
+ */
+ AUTH_INVALIDRESP=6, /* bogus response verifier */
+ AUTH_FAILED=7 /* some unknown reason */
+};
+
+#if (mc68000 || sparc || vax || i386 || tahoe || hp300)
+typedef u_long u_int32; /* 32-bit unsigned integers */
+#endif
+
+union des_block {
+ struct {
+ u_int32 high;
+ u_int32 low;
+ } key;
+ char c[8];
+};
+typedef union des_block des_block;
+__BEGIN_DECLS
+extern bool_t xdr_des_block __P((XDR *, des_block *));
+__END_DECLS
+
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
+};
+
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct {
+ struct opaque_auth ah_cred;
+ struct opaque_auth ah_verf;
+ union des_block ah_key;
+ struct auth_ops {
+ void (*ah_nextverf)();
+ int (*ah_marshal)(); /* nextverf & serialize */
+ int (*ah_validate)(); /* validate varifier */
+ int (*ah_refresh)(); /* refresh credentials */
+ void (*ah_destroy)(); /* destroy this structure */
+ } *ah_ops;
+ caddr_t ah_private;
+} AUTH;
+
+
+/*
+ * Authentication ops.
+ * The ops and the auth handle provide the interface to the authenticators.
+ *
+ * AUTH *auth;
+ * XDR *xdrs;
+ * struct opaque_auth verf;
+ */
+#define AUTH_NEXTVERF(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+#define auth_nextverf(auth) \
+ ((*((auth)->ah_ops->ah_nextverf))(auth))
+
+#define AUTH_MARSHALL(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+#define auth_marshall(auth, xdrs) \
+ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs))
+
+#define AUTH_VALIDATE(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+#define auth_validate(auth, verfp) \
+ ((*((auth)->ah_ops->ah_validate))((auth), verfp))
+
+#define AUTH_REFRESH(auth) \
+ ((*((auth)->ah_ops->ah_refresh))(auth))
+#define auth_refresh(auth) \
+ ((*((auth)->ah_ops->ah_refresh))(auth))
+
+#define AUTH_DESTROY(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+#define auth_destroy(auth) \
+ ((*((auth)->ah_ops->ah_destroy))(auth))
+
+
+extern struct opaque_auth _null_auth;
+
+
+/*
+ * These are the various implementations of client side authenticators.
+ */
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ * char *machname;
+ * int uid;
+ * int gid;
+ * int len;
+ * int *aup_gids;
+ */
+__BEGIN_DECLS
+extern AUTH *authunix_create __P((char *, int, int, int, int *));
+extern AUTH *authunix_create_default __P((void));
+extern AUTH *authnone_create __P((void));
+extern AUTH *authdes_create();
+__END_DECLS
+
+#define AUTH_NONE 0 /* no authentication */
+#define AUTH_NULL 0 /* backward compatibility */
+#define AUTH_UNIX 1 /* unix style (uid, gids) */
+#define AUTH_SHORT 2 /* short hand unix style */
+#define AUTH_DES 3 /* des style (encrypted timestamps) */
+
+#endif /* !_RPC_AUTH_H */
diff --git a/lib/libc/rpc/auth_none.c b/lib/libc/rpc/auth_none.c
new file mode 100644
index 000000000000..9c5a664795f6
--- /dev/null
+++ b/lib/libc/rpc/auth_none.c
@@ -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()
+{
+}
diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c
new file mode 100644
index 000000000000..334dc56c265a
--- /dev/null
+++ b/lib/libc/rpc/auth_unix.c
@@ -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);
+}
diff --git a/lib/libc/rpc/auth_unix.h b/lib/libc/rpc/auth_unix.h
new file mode 100644
index 000000000000..e9da2644c7d8
--- /dev/null
+++ b/lib/libc/rpc/auth_unix.h
@@ -0,0 +1,82 @@
+/*
+ * 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
+ *
+ * from: @(#)auth_unix.h 1.8 88/02/08 SMI
+ * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC
+ * $Id: auth_unix.h,v 1.1 1993/10/27 05:40:12 paul Exp $
+ */
+
+/*
+ * auth_unix.h, Protocol for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * The system is very weak. The client uses no encryption for it
+ * 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.
+ */
+
+#ifndef _RPC_AUTH_UNIX_H
+#define _RPC_AUTH_UNIX_H
+#include <sys/cdefs.h>
+
+/* The machine name is part of a credential; it may not exceed 255 bytes */
+#define MAX_MACHINE_NAME 255
+
+/* gids compose part of a credential; there may not be more than 16 of them */
+#define NGRPS 16
+
+/*
+ * Unix style credentials.
+ */
+struct authunix_parms {
+ u_long aup_time;
+ char *aup_machname;
+ int aup_uid;
+ int aup_gid;
+ u_int aup_len;
+ int *aup_gids;
+};
+
+__BEGIN_DECLS
+extern bool_t xdr_authunix_parms __P((XDR *, struct authunix_parms *));
+__END_DECLS
+
+/*
+ * If a response verifier has flavor AUTH_SHORT,
+ * then the body of the response verifier encapsulates the following structure;
+ * again it is serialized in the obvious fashion.
+ */
+struct short_hand_verf {
+ struct opaque_auth new_cred;
+};
+
+#endif /* !_RPC_AUTH_UNIX_H */
diff --git a/lib/libc/rpc/authunix_prot.c b/lib/libc/rpc/authunix_prot.c
new file mode 100644
index 000000000000..15faf184cfb5
--- /dev/null
+++ b/lib/libc/rpc/authunix_prot.c
@@ -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);
+}
+
diff --git a/lib/libc/rpc/bindresvport.3 b/lib/libc/rpc/bindresvport.3
new file mode 100644
index 000000000000..1fb1f9a30600
--- /dev/null
+++ b/lib/libc/rpc/bindresvport.3
@@ -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.
diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c
new file mode 100644
index 000000000000..a085c910c3c3
--- /dev/null
+++ b/lib/libc/rpc/bindresvport.c
@@ -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);
+}
diff --git a/lib/libc/rpc/clnt.h b/lib/libc/rpc/clnt.h
new file mode 100644
index 000000000000..71d36bc97fdb
--- /dev/null
+++ b/lib/libc/rpc/clnt.h
@@ -0,0 +1,358 @@
+/*
+ * 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
+ *
+ * from: @(#)clnt.h 1.31 88/02/08 SMI
+ * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC
+ * $Id: clnt.h,v 1.1 1993/10/27 05:40:18 paul Exp $
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_CLNT_H_
+#define _RPC_CLNT_H_
+#include <sys/cdefs.h>
+
+/*
+ * Rpc calls return an enum clnt_stat. This should be looked at more,
+ * since each implementation is required to live with this (implementation
+ * independent) list of errors.
+ */
+enum clnt_stat {
+ RPC_SUCCESS=0, /* call succeeded */
+ /*
+ * local errors
+ */
+ RPC_CANTENCODEARGS=1, /* can't encode arguments */
+ RPC_CANTDECODERES=2, /* can't decode results */
+ RPC_CANTSEND=3, /* failure in sending call */
+ RPC_CANTRECV=4, /* failure in receiving result */
+ RPC_TIMEDOUT=5, /* call timed out */
+ /*
+ * remote errors
+ */
+ RPC_VERSMISMATCH=6, /* rpc versions not compatible */
+ RPC_AUTHERROR=7, /* authentication error */
+ RPC_PROGUNAVAIL=8, /* program not available */
+ RPC_PROGVERSMISMATCH=9, /* program version mismatched */
+ RPC_PROCUNAVAIL=10, /* procedure unavailable */
+ RPC_CANTDECODEARGS=11, /* decode arguments error */
+ RPC_SYSTEMERROR=12, /* generic "other problem" */
+
+ /*
+ * callrpc & clnt_create errors
+ */
+ RPC_UNKNOWNHOST=13, /* unknown host name */
+ RPC_UNKNOWNPROTO=17, /* unkown protocol */
+
+ /*
+ * _ create errors
+ */
+ RPC_PMAPFAILURE=14, /* the pmapper failed in its call */
+ RPC_PROGNOTREGISTERED=15, /* remote program is not registered */
+ /*
+ * unspecified error
+ */
+ RPC_FAILED=16
+};
+
+
+/*
+ * Error info.
+ */
+struct rpc_err {
+ enum clnt_stat re_status;
+ union {
+ int RE_errno; /* realated system error */
+ enum auth_stat RE_why; /* why the auth error occurred */
+ struct {
+ u_long low; /* lowest verion supported */
+ u_long high; /* highest verion supported */
+ } RE_vers;
+ struct { /* maybe meaningful if RPC_FAILED */
+ long s1;
+ long s2;
+ } RE_lb; /* life boot & debugging only */
+ } ru;
+#define re_errno ru.RE_errno
+#define re_why ru.RE_why
+#define re_vers ru.RE_vers
+#define re_lb ru.RE_lb
+};
+
+
+/*
+ * Client rpc handle.
+ * Created by individual implementations, see e.g. rpc_udp.c.
+ * Client is responsible for initializing auth, see e.g. auth_none.c.
+ */
+typedef struct {
+ AUTH *cl_auth; /* authenticator */
+ struct clnt_ops {
+ enum clnt_stat (*cl_call)(); /* call remote procedure */
+ void (*cl_abort)(); /* abort a call */
+ void (*cl_geterr)(); /* get specific error code */
+ bool_t (*cl_freeres)(); /* frees results */
+ void (*cl_destroy)();/* destroy this structure */
+ bool_t (*cl_control)();/* the ioctl() of rpc */
+ } *cl_ops;
+ caddr_t cl_private; /* private stuff */
+} CLIENT;
+
+
+/*
+ * client side rpc interface ops
+ *
+ * Parameter types are:
+ *
+ */
+
+/*
+ * enum clnt_stat
+ * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout)
+ * CLIENT *rh;
+ * u_long proc;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ * struct timeval timeout;
+ */
+#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \
+ ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs))
+
+/*
+ * void
+ * CLNT_ABORT(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh))
+
+/*
+ * struct rpc_err
+ * CLNT_GETERR(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp))
+
+
+/*
+ * bool_t
+ * CLNT_FREERES(rh, xres, resp);
+ * CLIENT *rh;
+ * xdrproc_t xres;
+ * caddr_t resp;
+ */
+#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp))
+
+/*
+ * bool_t
+ * CLNT_CONTROL(cl, request, info)
+ * CLIENT *cl;
+ * u_int request;
+ * char *info;
+ */
+#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in))
+
+/*
+ * control operations that apply to both udp and tcp transports
+ */
+#define CLSET_TIMEOUT 1 /* set timeout (timeval) */
+#define CLGET_TIMEOUT 2 /* get timeout (timeval) */
+#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */
+/*
+ * udp only control operations
+ */
+#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */
+#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */
+
+/*
+ * void
+ * CLNT_DESTROY(rh);
+ * CLIENT *rh;
+ */
+#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh))
+
+
+/*
+ * RPCTEST is a test program which is accessable on every rpc
+ * transport/port. It is used for testing, performance evaluation,
+ * and network administration.
+ */
+
+#define RPCTEST_PROGRAM ((u_long)1)
+#define RPCTEST_VERSION ((u_long)1)
+#define RPCTEST_NULL_PROC ((u_long)2)
+#define RPCTEST_NULL_BATCH_PROC ((u_long)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((u_long)0)
+
+/*
+ * Below are the client handle creation routines for the various
+ * implementations of client side rpc. They can return NULL if a
+ * creation failure occurs.
+ */
+
+/*
+ * Memory based rpc (for speed check and testing)
+ * CLIENT *
+ * clntraw_create(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntraw_create __P((u_long, u_long));
+__END_DECLS
+
+
+/*
+ * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ * CLIENT *
+ * clnt_create(host, prog, vers, prot);
+ * char *host; -- hostname
+ * u_long prog; -- program number
+ * u_long vers; -- version number
+ * char *prot; -- protocol
+ */
+__BEGIN_DECLS
+extern CLIENT *clnt_create __P((char *, u_long, u_long, char *));
+__END_DECLS
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long prog;
+ * u_long version;
+ * register int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clnttcp_create __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ *
+ * Same as above, but you specify max packet sizes.
+ * CLIENT *
+ * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * u_long program;
+ * u_long version;
+ * struct timeval wait;
+ * int *sockp;
+ * u_int sendsz;
+ * u_int recvsz;
+ */
+__BEGIN_DECLS
+extern CLIENT *clntudp_create __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ struct timeval,
+ int *));
+extern CLIENT *clntudp_bufcreate __P((struct sockaddr_in *,
+ u_long,
+ u_long,
+ struct timeval,
+ int *,
+ u_int,
+ u_int));
+__END_DECLS
+
+
+/*
+ * Print why creation failed
+ */
+__BEGIN_DECLS
+extern void clnt_pcreateerror __P((char *)); /* stderr */
+extern char *clnt_spcreateerror __P((char *)); /* string */
+__END_DECLS
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */
+__BEGIN_DECLS
+extern void clnt_perrno __P((enum clnt_stat)); /* stderr */
+extern char *clnt_sperrno __P((enum clnt_stat)); /* string */
+__END_DECLS
+
+/*
+ * Print an English error message, given the client error code
+ */
+__BEGIN_DECLS
+extern void clnt_perror __P((CLIENT *, char *)); /* stderr */
+extern char *clnt_sperror __P((CLIENT *, char *)); /* string */
+__END_DECLS
+
+
+/*
+ * If a creation fails, the following allows the user to figure out why.
+ */
+struct rpc_createerr {
+ enum clnt_stat cf_stat;
+ struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */
+};
+
+extern struct rpc_createerr rpc_createerr;
+
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+#endif /* !_RPC_CLNT_H */
diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c
new file mode 100644
index 000000000000..ad9c22bb7191
--- /dev/null
+++ b/lib/libc/rpc/clnt_generic.c
@@ -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);
+}
diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c
new file mode 100644
index 000000000000..9a7d76cbc200
--- /dev/null
+++ b/lib/libc/rpc/clnt_perror.c
@@ -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);
+}
diff --git a/lib/libc/rpc/clnt_raw.c b/lib/libc/rpc/clnt_raw.c
new file mode 100644
index 000000000000..9ee87b225701
--- /dev/null
+++ b/lib/libc/rpc/clnt_raw.c
@@ -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()
+{
+}
diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c
new file mode 100644
index 000000000000..671e2eb61a93
--- /dev/null
+++ b/lib/libc/rpc/clnt_simple.c
@@ -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);
+}
diff --git a/lib/libc/rpc/clnt_tcp.c b/lib/libc/rpc/clnt_tcp.c
new file mode 100644
index 000000000000..efc041ab8db3
--- /dev/null
+++ b/lib/libc/rpc/clnt_tcp.c
@@ -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);
+}
diff --git a/lib/libc/rpc/clnt_udp.c b/lib/libc/rpc/clnt_udp.c
new file mode 100644
index 000000000000..4df4631079a7
--- /dev/null
+++ b/lib/libc/rpc/clnt_udp.c
@@ -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));
+}
diff --git a/lib/libc/rpc/get_myaddress.c b/lib/libc/rpc/get_myaddress.c
new file mode 100644
index 000000000000..2b0b20d96f0e
--- /dev/null
+++ b/lib/libc/rpc/get_myaddress.c
@@ -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);
+}
diff --git a/lib/libc/rpc/getrpcent.3 b/lib/libc/rpc/getrpcent.3
new file mode 100644
index 000000000000..f500c01b075f
--- /dev/null
+++ b/lib/libc/rpc/getrpcent.3
@@ -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.
diff --git a/lib/libc/rpc/getrpcent.c b/lib/libc/rpc/getrpcent.c
new file mode 100644
index 000000000000..a495278f8d27
--- /dev/null
+++ b/lib/libc/rpc/getrpcent.c
@@ -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);
+}
+
diff --git a/lib/libc/rpc/getrpcport.3 b/lib/libc/rpc/getrpcport.3
new file mode 100644
index 000000000000..0323d34a07c8
--- /dev/null
+++ b/lib/libc/rpc/getrpcport.3
@@ -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.
diff --git a/lib/libc/rpc/getrpcport.c b/lib/libc/rpc/getrpcport.c
new file mode 100644
index 000000000000..f1d58f9eb718
--- /dev/null
+++ b/lib/libc/rpc/getrpcport.c
@@ -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));
+}
diff --git a/lib/libc/rpc/pmap_clnt.c b/lib/libc/rpc/pmap_clnt.c
new file mode 100644
index 000000000000..4ef44ec3144c
--- /dev/null
+++ b/lib/libc/rpc/pmap_clnt.c
@@ -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);
+}
diff --git a/lib/libc/rpc/pmap_clnt.h b/lib/libc/rpc/pmap_clnt.h
new file mode 100644
index 000000000000..f080ec50956f
--- /dev/null
+++ b/lib/libc/rpc/pmap_clnt.h
@@ -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
+ *
+ * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI
+ * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC
+ * $Id: pmap_clnt.h,v 1.1 1993/10/27 05:40:33 paul Exp $
+ */
+
+/*
+ * pmap_clnt.h
+ * Supplies C routines to get to portmap services.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Usage:
+ * success = pmap_set(program, version, protocol, port);
+ * success = pmap_unset(program, version);
+ * port = pmap_getport(address, program, version, protocol);
+ * head = pmap_getmaps(address);
+ * clnt_stat = pmap_rmtcall(address, program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, tout, port_ptr)
+ * (works for udp only.)
+ * clnt_stat = clnt_broadcast(program, version, procedure,
+ * xdrargs, argsp, xdrres, resp, eachresult)
+ * (like pmap_rmtcall, except the call is broadcasted to all
+ * locally connected nets. For each valid response received,
+ * the procedure eachresult is called. Its form is:
+ * done = eachresult(resp, raddr)
+ * bool_t done;
+ * caddr_t resp;
+ * struct sockaddr_in raddr;
+ * where resp points to the results of the call and raddr is the
+ * address if the responder to the broadcast.
+ */
+
+#ifndef _RPC_PMAPCLNT_H
+#define _RPC_PMAPCLNT_H
+#include <sys/cdefs.h>
+
+__BEGIN_DECLS
+extern bool_t pmap_set __P((u_long, u_long, int, int));
+extern bool_t pmap_unset __P((u_long, u_long));
+extern struct pmaplist *pmap_getmaps __P((struct sockaddr_in *));
+extern enum clnt_stat pmap_rmtcall __P((struct sockaddr_in *,
+ u_long, u_long, u_long,
+ xdrproc_t, caddr_t,
+ xdrproc_t, caddr_t,
+ struct timeval, u_long *));
+extern enum clnt_stat clnt_broadcast __P((u_long, u_long, u_long,
+ xdrproc_t, char *,
+ xdrproc_t, char *,
+ bool_t (*)()));
+extern u_short pmap_getport __P((struct sockaddr_in *,
+ u_long, u_long, u_int));
+__END_DECLS
+
+#endif /* !_RPC_PMAPCLNT_H */
diff --git a/lib/libc/rpc/pmap_getmaps.c b/lib/libc/rpc/pmap_getmaps.c
new file mode 100644
index 000000000000..5af52106454b
--- /dev/null
+++ b/lib/libc/rpc/pmap_getmaps.c
@@ -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);
+}
diff --git a/lib/libc/rpc/pmap_getport.c b/lib/libc/rpc/pmap_getport.c
new file mode 100644
index 000000000000..06ed4d409fbb
--- /dev/null
+++ b/lib/libc/rpc/pmap_getport.c
@@ -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);
+}
diff --git a/lib/libc/rpc/pmap_prot.c b/lib/libc/rpc/pmap_prot.c
new file mode 100644
index 000000000000..ea0a20dfb144
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot.c
@@ -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);
+}
diff --git a/lib/libc/rpc/pmap_prot.h b/lib/libc/rpc/pmap_prot.h
new file mode 100644
index 000000000000..1c10c368d187
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot.h
@@ -0,0 +1,104 @@
+/*
+ * 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
+ *
+ * from: @(#)pmap_prot.h 1.14 88/02/08 SMI
+ * from: @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC
+ * $Id: pmap_prot.h,v 1.1 1993/10/27 05:40:38 paul Exp $
+ */
+
+/*
+ * pmap_prot.h
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The following procedures are supported by the protocol:
+ *
+ * PMAPPROC_NULL() returns ()
+ * takes nothing, returns nothing
+ *
+ * PMAPPROC_SET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Registers the tuple
+ * [prog, vers, prot, port].
+ *
+ * PMAPPROC_UNSET(struct pmap) returns (bool_t)
+ * TRUE is success, FALSE is failure. Un-registers pair
+ * [prog, vers]. prot and port are ignored.
+ *
+ * PMAPPROC_GETPORT(struct pmap) returns (long unsigned).
+ * 0 is failure. Otherwise returns the port number where the pair
+ * [prog, vers] is registered. It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+ * RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * Calls the procedure on the local machine. If it is not registered,
+ * this procedure is quite; ie it does not return error information!!!
+ * This procedure only is supported on rpc/udp and calls via
+ * rpc/udp. This routine only passes null authentication parameters.
+ * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#ifndef _RPC_PMAPPROT_H
+#define _RPC_PMAPPROT_H
+#include <sys/cdefs.h>
+
+#define PMAPPORT ((u_short)111)
+#define PMAPPROG ((u_long)100000)
+#define PMAPVERS ((u_long)2)
+#define PMAPVERS_PROTO ((u_long)2)
+#define PMAPVERS_ORIG ((u_long)1)
+#define PMAPPROC_NULL ((u_long)0)
+#define PMAPPROC_SET ((u_long)1)
+#define PMAPPROC_UNSET ((u_long)2)
+#define PMAPPROC_GETPORT ((u_long)3)
+#define PMAPPROC_DUMP ((u_long)4)
+#define PMAPPROC_CALLIT ((u_long)5)
+
+struct pmap {
+ long unsigned pm_prog;
+ long unsigned pm_vers;
+ long unsigned pm_prot;
+ long unsigned pm_port;
+};
+
+struct pmaplist {
+ struct pmap pml_map;
+ struct pmaplist *pml_next;
+};
+
+__BEGIN_DECLS
+extern bool_t xdr_pmap __P((XDR *, struct pmap *));
+extern bool_t xdr_pmaplist __P((XDR *, struct pmaplist **));
+__END_DECLS
+
+#endif /* !_RPC_PMAPPROT_H */
diff --git a/lib/libc/rpc/pmap_prot2.c b/lib/libc/rpc/pmap_prot2.c
new file mode 100644
index 000000000000..71ab21a7103b
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot2.c
@@ -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);
+ }
+}
diff --git a/lib/libc/rpc/pmap_rmt.c b/lib/libc/rpc/pmap_rmt.c
new file mode 100644
index 000000000000..339860c2c153
--- /dev/null
+++ b/lib/libc/rpc/pmap_rmt.c
@@ -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);
+}
+
diff --git a/lib/libc/rpc/pmap_rmt.h b/lib/libc/rpc/pmap_rmt.h
new file mode 100644
index 000000000000..c8c06ecb584d
--- /dev/null
+++ b/lib/libc/rpc/pmap_rmt.h
@@ -0,0 +1,63 @@
+/*
+ * 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
+ *
+ * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI
+ * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC
+ * $Id: pmap_rmt.h,v 1.1 1993/10/27 05:40:41 paul Exp $
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_PMAPRMT_H
+#define _RPC_PMAPRMT_H
+#include <sys/cdefs.h>
+
+struct rmtcallargs {
+ u_long prog, vers, proc, arglen;
+ caddr_t args_ptr;
+ xdrproc_t xdr_args;
+};
+
+struct rmtcallres {
+ u_long *port_ptr;
+ u_long resultslen;
+ caddr_t results_ptr;
+ xdrproc_t xdr_results;
+};
+
+__BEGIN_DECLS
+extern bool_t xdr_rmtcall_args __P((XDR *, struct rmtcallargs *));
+extern bool_t xdr_rmtcallres __P((XDR *, struct rmtcallres *));
+__END_DECLS
+
+#endif /* !_RPC_PMAPRMT_H */
diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3
new file mode 100644
index 000000000000..b5a2b92fce76
--- /dev/null
+++ b/lib/libc/rpc/rpc.3
@@ -0,0 +1,1729 @@
+.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.TH RPC 3N "16 February 1988"
+.SH NAME
+rpc \- library routines for remote procedure calls
+.SH SYNOPSIS AND DESCRIPTION
+These routines allow C programs to make procedure
+calls on other machines across the network.
+First, the client calls a procedure to send a
+data packet to the server.
+Upon receipt of the packet, the server calls a dispatch routine
+to perform the requested service, and then sends back a
+reply.
+Finally, the procedure call returns to the client.
+.LP
+Routines that are used for Secure RPC (DES authentication) are described in
+.BR rpc_secure (3N).
+Secure RPC can be used only if DES encryption is available.
+.LP
+.ft B
+.nf
+.sp .5
+#include <rpc/rpc.h>
+.fi
+.ft R
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+auth_destroy(auth)
+\s-1AUTH\s0 *auth;
+.fi
+.ft R
+.IP
+A macro that destroys the authentication information associated with
+.IR auth .
+Destruction usually involves deallocation of private data
+structures. The use of
+.I auth
+is undefined after calling
+.BR auth_destroy(\|) .
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authnone_create(\|)
+.fi
+.ft R
+.IP
+Create and returns an
+.SM RPC
+authentication handle that passes nonusable authentication
+information with each remote procedure call. This is the
+default authentication used by
+.SM RPC.
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create(host, uid, gid, len, aup_gids)
+char *host;
+int uid, gid, len, *aup.gids;
+.fi
+.ft R
+.IP
+Create and return an
+.SM RPC
+authentication handle that contains
+.UX
+authentication information.
+The parameter
+.I host
+is the name of the machine on which the information was
+created;
+.I uid
+is the user's user
+.SM ID ;
+.I gid
+is the user's current group
+.SM ID ;
+.I len
+and
+.I aup_gids
+refer to a counted array of groups to which the user belongs.
+It is easy to impersonate a user.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+\s-1AUTH\s0 *
+authunix_create_default(\|)
+.fi
+.ft R
+.IP
+Calls
+.B authunix_create(\|)
+with the appropriate parameters.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+char *host;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Call the remote procedure associated with
+.IR prognum ,
+.IR versnum ,
+and
+.I procnum
+on the machine,
+.IR host .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results.
+This routine returns zero if it succeeds, or the value of
+.B "enum clnt_stat"
+cast to an integer if it fails.
+The routine
+.B clnt_perrno(\|)
+is handy for translating failure statuses into messages.
+.IP
+Warning: calling remote procedures with this routine
+uses
+.SM UDP/IP
+as a transport; see
+.B clntudp_create(\|)
+for restrictions.
+You do not have control of timeouts or authentication using
+this routine.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_broadcast(prognum, versnum, procnum, inproc, in, outproc, out, eachresult)
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+resultproc_t eachresult;
+.fi
+.ft R
+.IP
+Like
+.BR callrpc(\|) ,
+except the call message is broadcast to all locally
+connected broadcast nets. Each time it receives a
+response, this routine calls
+.BR eachresult(\|) ,
+whose form is:
+.IP
+.RS 1i
+.ft B
+.nf
+eachresult(out, addr)
+char *out;
+struct sockaddr_in *addr;
+.ft R
+.fi
+.RE
+.IP
+where
+.I out
+is the same as
+.I out
+passed to
+.BR clnt_broadcast(\|) ,
+except that the remote procedure's output is decoded there;
+.I addr
+points to the address of the machine that sent the results.
+If
+.B eachresult(\|)
+returns zero,
+.B clnt_broadcast(\|)
+waits for more replies; otherwise it returns with appropriate
+status.
+.IP
+Warning: broadcast sockets are limited in size to the
+maximum transfer unit of the data link. For ethernet,
+this value is 1500 bytes.
+.br
+.if t .ne 13
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+clnt_call(clnt, procnum, inproc, in, outproc, out, tout)
+\s-1CLIENT\s0 *clnt;
+u_long
+procnum;
+xdrproc_t inproc, outproc;
+char *in, *out;
+struct timeval tout;
+.fi
+.ft R
+.IP
+A macro that calls the remote procedure
+.I procnum
+associated with the client handle,
+.IR clnt ,
+which is obtained with an
+.SM RPC
+client creation routine such as
+.BR clnt_create(\|) .
+The parameter
+.I in
+is the address of the procedure's argument(s), and
+.I out
+is the address of where to place the result(s);
+.I inproc
+is used to encode the procedure's parameters, and
+.I outproc
+is used to decode the procedure's results;
+.I tout
+is the time allowed for results to come back.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+clnt_destroy(clnt)
+\s-1CLIENT\s0 *clnt;
+.fi
+.ft R
+.IP
+A macro that destroys the client's
+.SM RPC
+handle. Destruction usually involves deallocation
+of private data structures, including
+.I clnt
+itself. Use of
+.I clnt
+is undefined after calling
+.BR clnt_destroy(\|) .
+If the
+.SM RPC
+library opened the associated socket, it will close it also.
+Otherwise, the socket remains open.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnt_create(host, prog, vers, proto)
+char *host;
+u_long prog, vers;
+char *proto;
+.fi
+.ft R
+.IP
+Generic client creation routine.
+.I host
+identifies the name of the remote host where the server
+is located.
+.I proto
+indicates which kind of transport protocol to use. The
+currently supported values for this field are \(lqudp\(rq
+and \(lqtcp\(rq.
+Default timeouts are set, but can be modified using
+.BR clnt_control(\|) .
+.IP
+Warning: Using
+.SM UDP
+has its shortcomings. Since
+.SM UDP\s0-based
+.SM RPC
+messages can only hold up to 8 Kbytes of encoded data,
+this transport cannot be used for procedures that take
+large arguments or return huge results.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+bool_t
+clnt_control(cl, req, info)
+\s-1CLIENT\s0 *cl;
+char *info;
+.fi
+.ft R
+.IP
+A macro used to change or retrieve various information
+about a client object.
+.I req
+indicates the type of operation, and
+.I info
+is a pointer to the information. For both
+.SM UDP
+and
+.SM TCP\s0,
+the supported values of
+.I req
+and their argument types and what they do are:
+.IP
+.nf
+.ta +2.0i +2.0i +2.0i
+.SM CLSET_TIMEOUT\s0 struct timeval set total timeout
+.SM CLGET_TIMEOUT\s0 struct timeval get total timeout
+.fi
+.IP
+Note: if you set the timeout using
+.BR clnt_control(\|) ,
+the timeout parameter passed to
+.B clnt_call(\|)
+will be ignored in all future calls.
+.IP
+.nf
+.SM CLGET_SERVER_ADDR\s0 struct sockaddr_in get server's address
+.fi
+.br
+.IP
+The following operations are valid for
+.SM UDP
+only:
+.IP
+.nf
+.ta +2.0i ; +2.0i ; +2.0i
+.SM CLSET_RETRY_TIMEOUT\s0 struct timeval set the retry timeout
+.SM CLGET_RETRY_TIMEOUT\s0 struct timeval get the retry timeout
+.fi
+.br
+.IP
+The retry timeout is the time that
+.SM "UDP RPC"
+waits for the server to reply before
+retransmitting the request.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+clnt_freeres(clnt, outproc, out)
+\s-1CLIENT\s0 *clnt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the results of an
+.SM RPC
+call. The
+parameter
+.I out
+is the address of the results, and
+.I outproc
+is the
+.SM XDR
+routine describing the results.
+This routine returns one if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_geterr(clnt, errp)
+\s-1CLIENT\s0 *clnt;
+struct rpc_err *errp;
+.fi
+.ft R
+.IP
+A macro that copies the error structure out of the client
+handle
+to the structure at address
+.IR errp .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_pcreateerror(s)
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating
+why a client
+.SM RPC
+handle could not be created.
+The message is prepended with string
+.I s
+and a colon.
+Used when a
+.BR clnt_create(\|) ,
+.BR clntraw_create(\|) ,
+.BR clnttcp_create(\|) ,
+or
+.B clntudp_create(\|)
+call fails.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+clnt_perrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Print a message to standard error corresponding
+to the condition indicated by
+.IR stat .
+Used after
+.BR callrpc(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+clnt_perror(clnt, s)
+\s-1CLIENT\s0 *clnt;
+char *s;
+.fi
+.ft R
+.IP
+Print a message to standard error indicating why an
+.SM RPC
+call failed;
+.I clnt
+is the handle used to do the call.
+The message is prepended with string
+.I s
+and a colon.
+Used after
+.BR clnt_call(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_spcreateerror
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_pcreateerror(\|) ,
+except that it returns a string
+instead of printing to the standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperrno(stat)
+enum clnt_stat stat;
+.fi
+.ft R
+.IP
+Take the same arguments as
+.BR clnt_perrno(\|) ,
+but instead of sending a message to the standard error
+indicating why an
+.SM RPC
+call failed, return a pointer to a string which contains
+the message. The string ends with a
+.SM NEWLINE\s0.
+.IP
+.B clnt_sperrno(\|)
+is used instead of
+.B clnt_perrno(\|)
+if the program does not have a standard error (as a program
+running as a server quite likely does not), or if the
+programmer
+does not want the message to be output with
+.BR printf ,
+or if a message format different than that supported by
+.B clnt_perrno(\|)
+is to be used.
+Note: unlike
+.B clnt_sperror(\|)
+and
+.BR clnt_spcreaterror(\|) ,
+.B clnt_sperrno(\|)
+returns pointer to static data, but the
+result will not get overwritten on each call.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+char *
+clnt_sperror(rpch, s)
+\s-1CLIENT\s0 *rpch;
+char *s;
+.fi
+.ft R
+.IP
+Like
+.BR clnt_perror(\|) ,
+except that (like
+.BR clnt_sperrno(\|) )
+it returns a string instead of printing to standard error.
+.IP
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntraw_create(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum .
+The transport used to pass messages to the service is
+actually a buffer within the process's address space, so the
+corresponding
+.SM RPC
+server should live in the same address space; see
+.BR svcraw_create(\|) .
+This allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads, such as round trip times, without any
+kernel interference. This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clnttcp_create(addr, prognum, versnum, sockp, sendsz, recvsz)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+int *sockp;
+u_int sendsz, recvsz;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses
+.SM TCP/IP
+as a transport. The remote program is located at Internet
+address
+.IR *addr .
+If
+.\"The following in-line font conversion is necessary for the hyphen indicator
+\fB\%addr\->sin_port\fR
+is zero, then it is set to the actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+the user may specify the size of the send and receive buffers
+with the parameters
+.I sendsz
+and
+.IR recvsz ;
+values of zero choose suitable defaults.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_create(addr, prognum, versnum, wait, sockp)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+version
+.IR versnum ;
+the client uses use
+.SM UDP/IP
+as a transport. The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.IR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.BR clnt_call(\|) .
+.IP
+Warning: since
+.SM UDP\s0-based
+.SM RPC
+messages can only hold up to 8 Kbytes
+of encoded data, this transport cannot be used for procedures
+that take large arguments or return huge results.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+\s-1CLIENT\s0 *
+clntudp_bufcreate(addr, prognum, versnum, wait, sockp, sendsize, recosize)
+struct sockaddr_in *addr;
+u_long prognum, versnum;
+struct timeval wait;
+int *sockp;
+unsigned int sendsize;
+unsigned int recosize;
+.fi
+.ft R
+.IP
+This routine creates an
+.SM RPC
+client for the remote program
+.IR prognum ,
+on
+.IR versnum ;
+the client uses use
+.SM UDP/IP
+as a transport. The remote program is located at Internet
+address
+.IR addr .
+If
+\fB\%addr\->sin_port\fR
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.B portmap
+service is consulted for this information). The parameter
+.I sockp
+is a socket; if it is
+.BR \s-1RPC_ANYSOCK\s0 ,
+then this routine opens a new one and sets
+.BR sockp .
+The
+.SM UDP
+transport resends the call message in intervals of
+.B wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.BR clnt_call(\|) .
+.IP
+This allows the user to specify the maximun packet size for sending and receiving
+.SM UDP\s0-based
+.SM RPC
+messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+get_myaddress(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+Stuff the machine's
+.SM IP
+address into
+.IR *addr ,
+without consulting the library routines that deal with
+.BR /etc/hosts .
+The port number is always set to
+.BR htons(\s-1PMAPPORT\s0) .
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+struct pmaplist *
+pmap_getmaps(addr)
+struct sockaddr_in *addr;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns a list of the current
+.SM RPC
+program-to-port mappings
+on the host located at
+.SM IP
+address
+.IR *addr .
+This routine can return
+.SM NULL .
+The command
+.RB ` "rpcinfo \-p" '
+uses this routine.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+u_short
+pmap_getport(addr, prognum, versnum, protocol)
+struct sockaddr_in *addr;
+u_long prognum, versnum, protocol;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which returns the port number
+on which waits a service that supports program number
+.IR prognum ,
+version
+.IR versnum ,
+and speaks the transport protocol associated with
+.IR protocol .
+The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+A return value of zero means that the mapping does not exist
+or that
+the
+.SM RPC
+system failured to contact the remote
+.B portmap
+service. In the latter case, the global variable
+.B rpc_createerr(\|)
+contains the
+.SM RPC
+status.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+enum clnt_stat
+pmap_rmtcall(addr, prognum, versnum, procnum, inproc, in, outproc, out, tout, portp)
+struct sockaddr_in *addr;
+u_long prognum, versnum, procnum;
+char *in, *out;
+xdrproc_t inproc, outproc;
+struct timeval tout;
+u_long *portp;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which instructs
+.B portmap
+on the host at
+.SM IP
+address
+.I *addr
+to make an
+.SM RPC
+call on your behalf to a procedure on that host.
+The parameter
+.I *portp
+will be modified to the program's port number if the
+procedure
+succeeds. The definitions of other parameters are discussed
+in
+.B callrpc(\|)
+and
+.BR clnt_call(\|) .
+This procedure should be used for a \(lqping\(rq and nothing
+else.
+See also
+.BR clnt_broadcast(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+pmap_set(prognum, versnum, protocol, port)
+u_long prognum, versnum, protocol;
+u_short port;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which establishes a mapping between the triple
+.RI [ prognum , versnum , protocol\fR]
+and
+.I port
+on the machine's
+.B portmap
+service. The value of
+.I protocol
+is most likely
+.B
+.SM IPPROTO_UDP
+or
+.BR \s-1IPPROTO_TCP\s0 .
+This routine returns one if it succeeds, zero otherwise.
+Automatically done by
+.BR svc_register(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+pmap_unset(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+A user interface to the
+.B portmap
+service, which destroys all mapping between the triple
+.RI [ prognum , versnum , *\fR]
+and
+.B ports
+on the machine's
+.B portmap
+service. This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+registerrpc(prognum, versnum, procnum, procname, inproc, outproc)
+u_long prognum, versnum, procnum;
+char *(*procname) (\|) ;
+xdrproc_t inproc, outproc;
+.fi
+.ft R
+.IP
+Register procedure
+.I procname
+with the
+.SM RPC
+service package. If a request arrives for program
+.IR prognum ,
+version
+.IR versnum ,
+and procedure
+.IR procnum ,
+.I procname
+is called with a pointer to its parameter(s);
+.I progname
+should return a pointer to its static result(s);
+.I inproc
+is used to decode the parameters while
+.I outproc
+is used to encode the results.
+This routine returns zero if the registration succeeded, \-1
+otherwise.
+.IP
+Warning: remote procedures registered in this form
+are accessed using the
+.SM UDP/IP
+transport; see
+.B svcudp_create(\|)
+for restrictions.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+struct rpc_createerr rpc_createerr;
+.fi
+.ft R
+.IP
+A global variable whose value is set by any
+.SM RPC
+client creation routine
+that does not succeed. Use the routine
+.B clnt_pcreateerror(\|)
+to print the reason why.
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+svc_destroy(xprt)
+\s-1SVCXPRT\s0 *
+xprt;
+.fi
+.ft R
+.IP
+A macro that destroys the
+.SM RPC
+service transport handle,
+.IR xprt .
+Destruction usually involves deallocation
+of private data structures, including
+.I xprt
+itself. Use of
+.I xprt
+is undefined after calling this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+fd_set svc_fdset;
+.fi
+.ft R
+.IP
+A global variable reflecting the
+.SM RPC
+service side's
+read file descriptor bit mask; it is suitable as a parameter
+to the
+.B select
+system call. This is only of interest
+if a service implementor does not call
+.BR svc_run(\|) ,
+but rather does his own asynchronous event processing.
+This variable is read-only (do not pass its address to
+.BR select !),
+yet it may change after calls to
+.B svc_getreqset(\|)
+or any creation routines.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+int svc_fds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_fedset(\|) ,
+but limited to 32 descriptors. This
+interface is obsoleted by
+.BR svc_fdset(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_freeargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that frees any data allocated by the
+.SM RPC/XDR
+system when it decoded the arguments to a service procedure
+using
+.BR svc_getargs(\|) .
+This routine returns 1 if the results were successfully
+freed,
+and zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+svc_getargs(xprt, inproc, in)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t inproc;
+char *in;
+.fi
+.ft R
+.IP
+A macro that decodes the arguments of an
+.SM RPC
+request
+associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+The parameter
+.I in
+is the address where the arguments will be placed;
+.I inproc
+is the
+.SM XDR
+routine used to decode the arguments.
+This routine returns one if decoding succeeds, and zero
+otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+struct sockaddr_in *
+svc_getcaller(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+The approved way of getting the network address of the caller
+of a procedure associated with the
+.SM RPC
+service transport handle,
+.IR xprt .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreqset(rdfds)
+fd_set *rdfds;
+.fi
+.ft R
+.IP
+This routine is only of interest if a service implementor
+does not call
+.BR svc_run(\|) ,
+but instead implements custom asynchronous event processing.
+It is called when the
+.B select
+system call has determined that an
+.SM RPC
+request has arrived on some
+.SM RPC
+.B socket(s) ;
+.I rdfds
+is the resultant read file descriptor bit mask.
+The routine returns when all sockets associated with the
+value of
+.I rdfds
+have been serviced.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_getreq(rdfds)
+int rdfds;
+.fi
+.ft R
+.IP
+Similar to
+.BR svc_getreqset(\|) ,
+but limited to 32 descriptors. This interface is obsoleted by
+.BR svc_getreqset(\|) .
+.br
+.if t .ne 17
+.LP
+.ft B
+.nf
+.sp .5
+svc_register(xprt, prognum, versnum, dispatch, protocol)
+\s-1SVCXPRT\s0 *xprt;
+u_long prognum, versnum;
+void (*dispatch) (\|);
+u_long protocol;
+.fi
+.ft R
+.IP
+Associates
+.I prognum
+and
+.I versnum
+with the service dispatch procedure,
+.IR dispatch .
+If
+.I protocol
+is zero, the service is not registered with the
+.B portmap
+service. If
+.I protocol
+is non-zero, then a mapping of the triple
+.RI [ prognum , versnum , protocol\fR]
+to
+\fB\%xprt\->xp_port\fR
+is established with the local
+.B portmap
+service (generally
+.I protocol
+is zero,
+.B
+.SM IPPROTO_UDP
+or
+.B
+.SM IPPROTO_TCP
+).
+The procedure
+.I dispatch
+has the following form:
+.RS 1i
+.ft B
+.nf
+dispatch(request, xprt)
+struct svc_req *request;
+\s-1SVCXPRT\s0 *xprt;
+.ft R
+.fi
+.RE
+.IP
+The
+.B svc_register(\|)
+routine returns one if it succeeds, and zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+svc_run(\|)
+.fi
+.ft R
+.IP
+This routine never returns. It waits for
+.SM RPC
+requests to arrive, and calls the appropriate service
+procedure using
+.B svc_getreq(\|)
+when one arrives. This procedure is usually waiting for a
+.B select(\|)
+system call to return.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+svc_sendreply(xprt, outproc, out)
+\s-1SVCXPRT\s0 *xprt;
+xdrproc_t outproc;
+char *out;
+.fi
+.ft R
+.IP
+Called by an
+.SM RPC
+service's dispatch routine to send the results of a
+remote procedure call. The parameter
+.I xprt
+is the request's associated transport handle;
+.I outproc
+is the
+.SM XDR
+routine which is used to encode the results; and
+.I out
+is the address of the results.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svc_unregister(prognum, versnum)
+u_long prognum, versnum;
+.fi
+.ft R
+.IP
+Remove all mapping of the double
+.RI [ prognum , versnum ]
+to dispatch routines, and of the triple
+.RI [ prognum , versnum , *\fR]
+to port number.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_auth(xprt, why)
+\s-1SVCXPRT\s0 *xprt;
+enum auth_stat why;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to an authentication error.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_decode(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that cannot successfully
+decode its parameters. See also
+.BR svc_getargs(\|) .
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noproc(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that does not implement
+the procedure number that the caller requests.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_noprog(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired program is not registered with the
+.SM RPC
+package. Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_progvers(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called when the desired version of a program is not registered
+with the
+.SM RPC
+package. Service implementors usually do not need this routine.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_systemerr(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine when it detects a system
+error
+not covered by any particular protocol.
+For example, if a service can no longer allocate storage,
+it may call this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+svcerr_weakauth(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to insufficient
+authentication parameters. The routine calls
+.BR "svcerr_auth(xprt, \s-1AUTH_TOOWEAK\s0)" .
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcraw_create(\|)
+.fi
+.ft R
+.IP
+This routine creates a toy
+.SM RPC
+service transport, to which it returns a pointer. The
+transport
+is really a buffer within the process's address space,
+so the corresponding
+.SM RPC
+client should live in the same
+address space;
+see
+.BR clntraw_create(\|) .
+This routine allows simulation of
+.SM RPC
+and acquisition of
+.SM RPC
+overheads (such as round trip times), without any kernel
+interference.
+This routine returns
+.SM NULL
+if it fails.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svctcp_create(sock, send_buf_size, recv_buf_size)
+int sock;
+u_int send_buf_size, recv_buf_size;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM TCP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.BR \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM TCP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails. Since
+.SM TCP\s0-based
+.SM RPC
+uses buffered
+.SM I/O ,
+users may specify the size of buffers; values of zero
+choose suitable defaults.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcfd_create(fd, sendsize, recvsize)
+int fd;
+u_int sendsize;
+u_int recvsize;
+.fi
+.ft R
+.IP
+Create a service on top of any open descriptor. Typically,
+this
+descriptor is a connected socket for a stream protocol such
+as
+.SM TCP\s0.
+.I sendsize
+and
+.I recvsize
+indicate sizes for the send and receive buffers. If they are
+zero, a reasonable default is chosen.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+\s-1SVCXPRT\s0 *
+svcudp_bufcreate(sock, sendsize, recosize)
+int sock;
+.fi
+.ft R
+.IP
+This routine creates a
+.SM UDP/IP\s0-based
+.SM RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.IR sock ,
+which may be
+.B \s-1RPC_ANYSOCK\s0 ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.SM UDP
+port, then this routine binds it to an arbitrary port. Upon
+completion,
+\fB\%xprt\->xp_sock\fR
+is the transport's socket descriptor, and
+\fB\%xprt\->xp_port\fR
+is the transport's port number.
+This routine returns
+.SM NULL
+if it fails.
+.IP
+This allows the user to specify the maximun packet size for sending and
+receiving
+.SM UDP\s0-based
+.SM RPC messages.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_accepted_reply(xdrs, ar)
+\s-1XDR\s0 *xdrs;
+struct accepted_reply *ar;
+.fi
+.ft R
+.IP
+Used for encoding
+.SM RPC
+reply messages. This routine is useful for users who
+wish to generate
+\s-1RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_authunix_parms(xdrs, aupp)
+\s-1XDR\s0 *xdrs;
+struct authunix_parms *aupp;
+.fi
+.ft R
+.IP
+Used for describing
+.SM UNIX
+credentials. This routine is useful for users
+who wish to generate these credentials without using the
+.SM RPC
+authentication package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_callhdr(xdrs, chdr)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *chdr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call header messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_callmsg(xdrs, cmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *cmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+call messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque_auth(xdrs, ap)
+\s-1XDR\s0 *xdrs;
+struct opaque_auth *ap;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+authentication information messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmap(xdrs, regs)
+\s-1XDR\s0 *xdrs;
+struct pmap *regs;
+.fi
+.ft R
+.IP
+Used for describing parameters to various
+.B portmap
+procedures, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pmaplist(xdrs, rp)
+\s-1XDR\s0 *xdrs;
+struct pmaplist **rp;
+.fi
+.ft R
+.IP
+Used for describing a list of port mappings, externally.
+This routine is useful for users who wish to generate
+these parameters without using the
+.B pmap
+interface.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_rejected_reply(xdrs, rr)
+\s-1XDR\s0 *xdrs;
+struct rejected_reply *rr;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC\s0-style
+messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_replymsg(xdrs, rmsg)
+\s-1XDR\s0 *xdrs;
+struct rpc_msg *rmsg;
+.fi
+.ft R
+.IP
+Used for describing
+.SM RPC
+reply messages.
+This routine is useful for users who wish to generate
+.SM RPC
+style messages without using the
+.SM RPC
+package.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_register(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+After
+.SM RPC
+service transport handles are created,
+they should register themselves with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xprt_unregister(xprt)
+\s-1SVCXPRT\s0 *xprt;
+.fi
+.ft R
+.IP
+Before an
+.SM RPC
+service transport handle is destroyed,
+it should unregister itself with the
+.SM RPC
+service package.
+This routine modifies the global variable
+.BR svc_fds(\|) .
+Service implementors usually do not need this routine.
+.SH SEE ALSO
+.BR rpc_secure (3N),
+.BR xdr (3N)
+.br
+The following manuals:
+.RS
+.ft I
+Remote Procedure Calls: Protocol Specification
+.br
+Remote Procedure Call Programming Guide
+.br
+rpcgen Programming Guide
+.br
+.ft R
+.RE
+.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" ,
+.SM RFC1050, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
+
diff --git a/lib/libc/rpc/rpc.5 b/lib/libc/rpc/rpc.5
new file mode 100644
index 000000000000..324ecb153a83
--- /dev/null
+++ b/lib/libc/rpc/rpc.5
@@ -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)
diff --git a/lib/libc/rpc/rpc.h b/lib/libc/rpc/rpc.h
new file mode 100644
index 000000000000..5f8d23ea3d6e
--- /dev/null
+++ b/lib/libc/rpc/rpc.h
@@ -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
+ *
+ * from: @(#)rpc.h 1.9 88/02/08 SMI
+ * from: @(#)rpc.h 2.4 89/07/11 4.0 RPCSRC
+ * $Id: rpc.h,v 1.1 1993/10/27 05:40:45 paul Exp $
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef _RPC_RPC_H
+#define _RPC_RPC_H
+
+#include <rpc/types.h> /* some typedefs */
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <rpc/xdr.h> /* generic (de)serializer */
+
+/* Client side only authentication */
+#include <rpc/auth.h> /* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <rpc/clnt.h> /* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <rpc/rpc_msg.h> /* protocol for rpc messages */
+#include <rpc/auth_unix.h> /* protocol for unix style cred */
+/*
+ * Uncomment-out the next line if you are building the rpc library with
+ * DES Authentication (see the README file in the secure_rpc/ directory).
+ */
+/*#include <rpc/auth_des.h> /* protocol for des style cred */
+
+/* Server side only remote procedure callee */
+#include <rpc/svc.h> /* service manager and multiplexer */
+#include <rpc/svc_auth.h> /* service side authenticator */
+
+/*
+ * COMMENT OUT THE NEXT INCLUDE (or add to the #ifndef) IF RUNNING ON
+ * A VERSION OF UNIX THAT USES SUN'S NFS SOURCE. These systems will
+ * already have the structures defined by <rpc/netdb.h> included in <netdb.h>.
+ */
+/* routines for parsing /etc/rpc */
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+__BEGIN_DECLS
+extern struct rpcent *getrpcbyname __P((char *));
+extern struct rpcent *getrpcbynumber __P((int));
+extern struct rpcent *getrpcent __P((void));
+extern void setrpcent __P((int));
+extern void endrpcent __P((void));
+__END_DECLS
+
+#endif /* !_RPC_RPC_H */
diff --git a/lib/libc/rpc/rpc_callmsg.c b/lib/libc/rpc/rpc_callmsg.c
new file mode 100644
index 000000000000..4ec59dbc7855
--- /dev/null
+++ b/lib/libc/rpc/rpc_callmsg.c
@@ -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);
+}
+
diff --git a/lib/libc/rpc/rpc_commondata.c b/lib/libc/rpc/rpc_commondata.c
new file mode 100644
index 000000000000..e870ab8dde7c
--- /dev/null
+++ b/lib/libc/rpc/rpc_commondata.c
@@ -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;
diff --git a/lib/libc/rpc/rpc_dtablesize.c b/lib/libc/rpc/rpc_dtablesize.c
new file mode 100644
index 000000000000..c4a2ac411b33
--- /dev/null
+++ b/lib/libc/rpc/rpc_dtablesize.c
@@ -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);
+}
diff --git a/lib/libc/rpc/rpc_msg.h b/lib/libc/rpc/rpc_msg.h
new file mode 100644
index 000000000000..f3697fa8a02f
--- /dev/null
+++ b/lib/libc/rpc/rpc_msg.h
@@ -0,0 +1,195 @@
+/*
+ * 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
+ *
+ * from: @(#)rpc_msg.h 1.7 86/07/16 SMI
+ * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC
+ * $Id: rpc_msg.h,v 1.1 1993/10/27 05:40:49 paul Exp $
+ */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_RPCMSG_H
+#define _RPC_RPCMSG_H
+
+#define RPC_MSG_VERSION ((u_long) 2)
+#define RPC_SERVICE_PORT ((u_short) 2048)
+
+/*
+ * Bottom up definition of an rpc message.
+ * NOTE: call and reply use the same overall stuct but
+ * different parts of unions within it.
+ */
+
+enum msg_type {
+ CALL=0,
+ REPLY=1
+};
+
+enum reply_stat {
+ MSG_ACCEPTED=0,
+ MSG_DENIED=1
+};
+
+enum accept_stat {
+ SUCCESS=0,
+ PROG_UNAVAIL=1,
+ PROG_MISMATCH=2,
+ PROC_UNAVAIL=3,
+ GARBAGE_ARGS=4,
+ SYSTEM_ERR=5
+};
+
+enum reject_stat {
+ RPC_MISMATCH=0,
+ AUTH_ERROR=1
+};
+
+/*
+ * Reply part of an rpc exchange
+ */
+
+/*
+ * Reply to an rpc request that was accepted by the server.
+ * Note: there could be an error even though the request was
+ * accepted.
+ */
+struct accepted_reply {
+ struct opaque_auth ar_verf;
+ enum accept_stat ar_stat;
+ union {
+ struct {
+ u_long low;
+ u_long high;
+ } AR_versions;
+ struct {
+ caddr_t where;
+ xdrproc_t proc;
+ } AR_results;
+ /* and many other null cases */
+ } ru;
+#define ar_results ru.AR_results
+#define ar_vers ru.AR_versions
+};
+
+/*
+ * Reply to an rpc request that was rejected by the server.
+ */
+struct rejected_reply {
+ enum reject_stat rj_stat;
+ union {
+ struct {
+ u_long low;
+ u_long high;
+ } RJ_versions;
+ enum auth_stat RJ_why; /* why authentication did not work */
+ } ru;
+#define rj_vers ru.RJ_versions
+#define rj_why ru.RJ_why
+};
+
+/*
+ * Body of a reply to an rpc request.
+ */
+struct reply_body {
+ enum reply_stat rp_stat;
+ union {
+ struct accepted_reply RP_ar;
+ struct rejected_reply RP_dr;
+ } ru;
+#define rp_acpt ru.RP_ar
+#define rp_rjct ru.RP_dr
+};
+
+/*
+ * Body of an rpc request call.
+ */
+struct call_body {
+ u_long cb_rpcvers; /* must be equal to two */
+ u_long cb_prog;
+ u_long cb_vers;
+ u_long cb_proc;
+ struct opaque_auth cb_cred;
+ struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+ u_long rm_xid;
+ enum msg_type rm_direction;
+ union {
+ struct call_body RM_cmb;
+ struct reply_body RM_rmb;
+ } ru;
+#define rm_call ru.RM_cmb
+#define rm_reply ru.RM_rmb
+};
+#define acpted_rply ru.RM_rmb.ru.RP_ar
+#define rjcted_rply ru.RM_rmb.ru.RP_dr
+
+__BEGIN_DECLS
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callmsg __P((XDR *, struct rpc_msg *));
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callhdr __P((XDR *, struct rpc_msg *));
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *rmsg;
+ */
+extern bool_t xdr_replymsg __P((XDR *, struct rpc_msg *));
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * struct rpc_msg *msg;
+ * struct rpc_err *error;
+ */
+extern void _seterr_reply __P((struct rpc_msg *, struct rpc_err *));
+__END_DECLS
+
+#endif /* !_RPC_RPCMSG_H */
diff --git a/lib/libc/rpc/rpc_prot.c b/lib/libc/rpc/rpc_prot.c
new file mode 100644
index 000000000000..7fbb36fd7557
--- /dev/null
+++ b/lib/libc/rpc/rpc_prot.c
@@ -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;
+ }
+}
diff --git a/lib/libc/rpc/rstat.1 b/lib/libc/rpc/rstat.1
new file mode 100644
index 000000000000..61d9999116f8
--- /dev/null
+++ b/lib/libc/rpc/rstat.1
@@ -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)
diff --git a/lib/libc/rpc/rstat_svc.8 b/lib/libc/rpc/rstat_svc.8
new file mode 100644
index 000000000000..a10b71dbacad
--- /dev/null
+++ b/lib/libc/rpc/rstat_svc.8
@@ -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),
diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c
new file mode 100644
index 000000000000..55ad25e92ad0
--- /dev/null
+++ b/lib/libc/rpc/svc.c
@@ -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);
+ }
+ }
+}
diff --git a/lib/libc/rpc/svc.h b/lib/libc/rpc/svc.h
new file mode 100644
index 000000000000..b525d8232dea
--- /dev/null
+++ b/lib/libc/rpc/svc.h
@@ -0,0 +1,302 @@
+/*
+ * 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
+ *
+ * from: @(#)svc.h 1.20 88/02/08 SMI
+ * from: @(#)svc.h 2.2 88/07/29 4.0 RPCSRC
+ * $Id: svc.h,v 1.1 1993/10/27 05:40:55 paul Exp $
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_SVC_H
+#define _RPC_SVC_H
+#include <sys/cdefs.h>
+
+/*
+ * This interface must manage two items concerning remote procedure calling:
+ *
+ * 1) An arbitrary number of transport connections upon which rpc requests
+ * are received. The two most notable transports are TCP and UDP; they are
+ * created and registered by routines in svc_tcp.c and svc_udp.c, respectively;
+ * they in turn call xprt_register and xprt_unregister.
+ *
+ * 2) An arbitrary number of locally registered services. Services are
+ * described by the following four data: program number, version number,
+ * "service dispatch" function, a transport handle, and a boolean that
+ * indicates whether or not the exported program should be registered with a
+ * local binder service; if true the program's number and version and the
+ * port number from the transport handle are registered with the binder.
+ * These data are registered with the rpc svc system via svc_register.
+ *
+ * A service's dispatch function is called whenever an rpc request comes in
+ * on a transport. The request's program and version numbers must match
+ * those of the registered service. The dispatch function is passed two
+ * parameters, struct svc_req * and SVCXPRT *, defined below.
+ */
+
+enum xprt_stat {
+ XPRT_DIED,
+ XPRT_MOREREQS,
+ XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct {
+ int xp_sock;
+ u_short xp_port; /* associated port number */
+ struct xp_ops {
+ bool_t (*xp_recv)(); /* receive incomming requests */
+ enum xprt_stat (*xp_stat)(); /* get transport status */
+ bool_t (*xp_getargs)(); /* get arguments */
+ bool_t (*xp_reply)(); /* send reply */
+ bool_t (*xp_freeargs)();/* free mem allocated for args */
+ void (*xp_destroy)(); /* destroy this struct */
+ } *xp_ops;
+ int xp_addrlen; /* length of remote address */
+ struct sockaddr_in xp_raddr; /* remote address */
+ struct opaque_auth xp_verf; /* raw response verifier */
+ caddr_t xp_p1; /* private */
+ caddr_t xp_p2; /* private */
+} SVCXPRT;
+
+/*
+ * Approved way of getting address of caller
+ */
+#define svc_getcaller(x) (&(x)->xp_raddr)
+
+/*
+ * Operations defined on an SVCXPRT handle
+ *
+ * SVCXPRT *xprt;
+ * struct rpc_msg *msg;
+ * xdrproc_t xargs;
+ * caddr_t argsp;
+ */
+#define SVC_RECV(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+#define svc_recv(xprt, msg) \
+ (*(xprt)->xp_ops->xp_recv)((xprt), (msg))
+
+#define SVC_STAT(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+#define svc_stat(xprt) \
+ (*(xprt)->xp_ops->xp_stat)(xprt)
+
+#define SVC_GETARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+#define svc_getargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp))
+
+#define SVC_REPLY(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+#define svc_reply(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply) ((xprt), (msg))
+
+#define SVC_FREEARGS(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+#define svc_freeargs(xprt, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp))
+
+#define SVC_DESTROY(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+#define svc_destroy(xprt) \
+ (*(xprt)->xp_ops->xp_destroy)(xprt)
+
+
+/*
+ * Service request
+ */
+struct svc_req {
+ u_long rq_prog; /* service program number */
+ u_long rq_vers; /* service protocol version */
+ u_long rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ caddr_t rq_clntcred; /* read only cooked cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * u_long prog;
+ * u_long vers;
+ * void (*dispatch)();
+ * int protocol; /* like TCP or UDP, zero means do not register
+ */
+__BEGIN_DECLS
+extern bool_t svc_register __P((SVCXPRT *, u_long, u_long, void (*)(), int));
+__END_DECLS
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * u_long prog;
+ * u_long vers;
+ */
+__BEGIN_DECLS
+extern void svc_unregister __P((u_long, u_long));
+__END_DECLS
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ * SVCXPRT *xprt;
+ */
+__BEGIN_DECLS
+extern void xprt_register __P((SVCXPRT *));
+__END_DECLS
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ * SVCXPRT *xprt;
+ */
+__BEGIN_DECLS
+extern void xprt_unregister __P((SVCXPRT *));
+__END_DECLS
+
+
+
+
+/*
+ * When the service routine is called, it must first check to see if it
+ * knows about the procedure; if not, it should call svcerr_noproc
+ * and return. If so, it should deserialize its arguments via
+ * SVC_GETARGS (defined above). If the deserialization does not work,
+ * svcerr_decode should be called followed by a return. Successful
+ * decoding of the arguments should be followed the execution of the
+ * procedure's code and a call to svc_sendreply.
+ *
+ * Also, if the service refuses to execute the procedure due to too-
+ * weak authentication parameters, svcerr_weakauth should be called.
+ * Note: do not confuse access-control failure with weak authentication!
+ *
+ * NB: In pure implementations of rpc, the caller always waits for a reply
+ * msg. This message is sent when svc_sendreply is called.
+ * Therefore pure service implementations should always call
+ * svc_sendreply even if the function logically returns void; use
+ * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows
+ * for the abuse of pure rpc via batched calling or pipelining. In the
+ * case of a batched call, svc_sendreply should NOT be called since
+ * this would send a return message, which is what batching tries to avoid.
+ * It is the service/protocol writer's responsibility to know which calls are
+ * batched and which are not. Warning: responding to batch calls may
+ * deadlock the caller and server processes!
+ */
+
+__BEGIN_DECLS
+extern bool_t svc_sendreply __P((SVCXPRT *, xdrproc_t, char *));
+extern void svcerr_decode __P((SVCXPRT *));
+extern void svcerr_weakauth __P((SVCXPRT *));
+extern void svcerr_noproc __P((SVCXPRT *));
+extern void svcerr_progvers __P((SVCXPRT *, u_long, u_long));
+extern void svcerr_auth __P((SVCXPRT *, enum auth_stat));
+extern void svcerr_noprog __P((SVCXPRT *));
+extern void svcerr_systemerr __P((SVCXPRT *));
+__END_DECLS
+
+/*
+ * Lowest level dispatching -OR- who owns this process anyway.
+ * Somebody has to wait for incoming requests and then call the correct
+ * service routine. The routine svc_run does infinite waiting; i.e.,
+ * svc_run never returns.
+ * Since another (co-existant) package may wish to selectively wait for
+ * incoming calls or other events outside of the rpc architecture, the
+ * routine svc_getreq is provided. It must be passed readfds, the
+ * "in-place" results of a select system call (see select, section 2).
+ */
+
+/*
+ * Global keeper of rpc service descriptors in use
+ * dynamic; must be inspected before each call to select
+ */
+#ifdef FD_SETSIZE
+extern fd_set svc_fdset;
+#define svc_fds svc_fdset.fds_bits[0] /* compatibility */
+#else
+extern int svc_fds;
+#endif /* def FD_SETSIZE */
+
+/*
+ * a small program implemented by the svc_rpc implementation itself;
+ * also see clnt.h for protocol numbers.
+ */
+extern void rpctest_service();
+
+__BEGIN_DECLS
+extern void svc_getreq __P((int));
+extern void svc_getreqset __P((fd_set *));
+extern void svc_run __P((void));
+__END_DECLS
+
+/*
+ * Socket to use on svcxxx_create call to get default socket
+ */
+#define RPC_ANYSOCK -1
+
+/*
+ * These are the existing service side transport implementations
+ */
+
+/*
+ * Memory based rpc for testing and timing.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcraw_create __P((void));
+__END_DECLS
+
+
+/*
+ * Udp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svcudp_create __P((int));
+extern SVCXPRT *svcudp_bufcreate __P((int, u_int, u_int));
+__END_DECLS
+
+
+/*
+ * Tcp based rpc.
+ */
+__BEGIN_DECLS
+extern SVCXPRT *svctcp_create __P((int, u_int, u_int));
+__END_DECLS
+
+#endif /* !_RPC_SVC_H */
diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c
new file mode 100644
index 000000000000..0a9f2765bf6a
--- /dev/null
+++ b/lib/libc/rpc/svc_auth.c
@@ -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);
+}
diff --git a/lib/libc/rpc/svc_auth.h b/lib/libc/rpc/svc_auth.h
new file mode 100644
index 000000000000..c6db4404e25d
--- /dev/null
+++ b/lib/libc/rpc/svc_auth.h
@@ -0,0 +1,50 @@
+/*
+ * 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
+ *
+ * from: @(#)svc_auth.h 1.6 86/07/16 SMI
+ * from: @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC
+ * $Id: svc_auth.h,v 1.1 1993/10/27 05:40:57 paul Exp $
+ */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_SVCAUTH_H
+#define _RPC_SVCAUTH_H
+
+/*
+ * Server side authenticator
+ */
+__BEGIN_DECLS
+extern enum auth_stat _authenticate __P((struct svc_req *, struct rpc_msg *));
+__END_DECLS
+
+#endif /* !_RPC_SVCAUTH_H */
diff --git a/lib/libc/rpc/svc_auth_unix.c b/lib/libc/rpc/svc_auth_unix.c
new file mode 100644
index 000000000000..5cf825f6f8ab
--- /dev/null
+++ b/lib/libc/rpc/svc_auth_unix.c
@@ -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);
+}
diff --git a/lib/libc/rpc/svc_raw.c b/lib/libc/rpc/svc_raw.c
new file mode 100644
index 000000000000..e34ea9e32608
--- /dev/null
+++ b/lib/libc/rpc/svc_raw.c
@@ -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()
+{
+}
diff --git a/lib/libc/rpc/svc_run.c b/lib/libc/rpc/svc_run.c
new file mode 100644
index 000000000000..52fddf226382
--- /dev/null
+++ b/lib/libc/rpc/svc_run.c
@@ -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);
+ }
+ }
+}
diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c
new file mode 100644
index 000000000000..eacf859f5ca9
--- /dev/null
+++ b/lib/libc/rpc/svc_simple.c
@@ -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);
+}
+
diff --git a/lib/libc/rpc/svc_tcp.c b/lib/libc/rpc/svc_tcp.c
new file mode 100644
index 000000000000..9d19504858fb
--- /dev/null
+++ b/lib/libc/rpc/svc_tcp.c
@@ -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);
+}
diff --git a/lib/libc/rpc/svc_udp.c b/lib/libc/rpc/svc_udp.c
new file mode 100644
index 000000000000..d7c7bb2dd825
--- /dev/null
+++ b/lib/libc/rpc/svc_udp.c
@@ -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);
+}
+
diff --git a/lib/libc/rpc/types.h b/lib/libc/rpc/types.h
new file mode 100644
index 000000000000..b12221d0d3b2
--- /dev/null
+++ b/lib/libc/rpc/types.h
@@ -0,0 +1,66 @@
+/*
+ * 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
+ *
+ * from: @(#)types.h 1.18 87/07/24 SMI
+ * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC
+ * $Id: types.h,v 1.1 1993/10/27 05:41:04 paul Exp $
+ */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef _RPC_TYPES_H
+#define _RPC_TYPES_H
+
+#define bool_t int
+#define enum_t int
+#define __dontcare__ -1
+
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (1)
+#endif
+#ifndef NULL
+# define NULL 0
+#endif
+
+#define mem_alloc(bsize) malloc(bsize)
+#define mem_free(ptr, bsize) free(ptr)
+
+#ifndef makedev /* ie, we haven't already included it */
+#include <sys/types.h>
+#endif
+#include <sys/time.h>
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (u_long)0x7F000001
+#endif
+
+#endif /* !_RPC_TYPES_H */
diff --git a/lib/libc/rpc/xdr.3 b/lib/libc/rpc/xdr.3
new file mode 100644
index 000000000000..b656ea804da8
--- /dev/null
+++ b/lib/libc/rpc/xdr.3
@@ -0,0 +1,823 @@
+.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI
+.TH XDR 3N "16 February 1988"
+.SH NAME
+xdr \- library routines for external data representation
+.SH SYNOPSIS AND DESCRIPTION
+.LP
+These routines allow C programmers to describe
+arbitrary data structures in a machine-independent fashion.
+Data for remote procedure calls are transmitted using these
+routines.
+.LP
+.ft B
+.nf
+.sp .5
+xdr_array(xdrs, arrp, sizep, maxsize, elsize, elproc)
+\s-1XDR\s0 *xdrs;
+char **arrp;
+u_int *sizep, maxsize, elsize;
+xdrproc_t elproc;
+.fi
+.ft R
+.IP
+A filter primitive that translates between variable-length
+arrays
+and their corresponding external representations. The
+parameter
+.I arrp
+is the address of the pointer to the array, while
+.I sizep
+is the address of the element count of the array;
+this element count cannot exceed
+.IR maxsize .
+The parameter
+.I elsize
+is the
+.I sizeof
+each of the array's elements, and
+.I elproc
+is an
+.SM XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_bool(xdrs, bp)
+\s-1XDR\s0 *xdrs;
+bool_t *bp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between booleans (C
+integers)
+and their external representations. When encoding data, this
+filter produces values of either one or zero.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_bytes(xdrs, sp, sizep, maxsize)
+\s-1XDR\s0 *xdrs;
+char **sp;
+u_int *sizep, maxsize;
+.fi
+.ft R
+.IP
+A filter primitive that translates between counted byte
+strings and their external representations.
+The parameter
+.I sp
+is the address of the string pointer. The length of the
+string is located at address
+.IR sizep ;
+strings cannot be longer than
+.IR maxsize .
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_char(xdrs, cp)
+\s-1XDR\s0 *xdrs;
+char *cp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C characters
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+Note: encoded characters are not packed, and occupy 4 bytes
+each. For arrays of characters, it is worthwhile to
+consider
+.BR xdr_bytes(\|) ,
+.B xdr_opaque(\|)
+or
+.BR xdr_string(\|) .
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_destroy(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+A macro that invokes the destroy routine associated with the
+.SM XDR
+stream,
+.IR xdrs .
+Destruction usually involves freeing private data structures
+associated with the stream. Using
+.I xdrs
+after invoking
+.B xdr_destroy(\|)
+is undefined.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_double(xdrs, dp)
+\s-1XDR\s0 *xdrs;
+double *dp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B double
+precision numbers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_enum(xdrs, ep)
+\s-1XDR\s0 *xdrs;
+enum_t *ep;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.BR enum s
+(actually integers) and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_float(xdrs, fp)
+\s-1XDR\s0 *xdrs;
+float *fp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.BR float s
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdr_free(proc, objp)
+xdrproc_t proc;
+char *objp;
+.fi
+.ft R
+.IP
+Generic freeing routine. The first argument is the
+.SM XDR
+routine for the object being freed. The second argument
+is a pointer to the object itself. Note: the pointer passed
+to this routine is
+.I not
+freed, but what it points to
+.I is
+freed (recursively).
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+u_int
+xdr_getpos(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+A macro that invokes the get-position routine
+associated with the
+.SM XDR
+stream,
+.IR xdrs .
+The routine returns an unsigned integer,
+which indicates the position of the
+.SM XDR
+byte stream.
+A desirable feature of
+.SM XDR
+streams is that simple arithmetic works with this number,
+although the
+.SM XDR
+stream instances need not guarantee this.
+.br
+.if t .ne 4
+.LP
+.ft B
+.nf
+.sp .5
+.br
+long *
+xdr_inline(xdrs, len)
+\s-1XDR\s0 *xdrs;
+int len;
+.fi
+.ft R
+.IP
+A macro that invokes the in-line routine associated with the
+.SM XDR
+stream,
+.IR xdrs .
+The routine returns a pointer
+to a contiguous piece of the stream's buffer;
+.I len
+is the byte length of the desired buffer.
+Note: pointer is cast to
+.BR "long *" .
+.IP
+Warning:
+.B xdr_inline(\|)
+may return
+.SM NULL
+(0)
+if it cannot allocate a contiguous piece of a buffer.
+Therefore the behavior may vary among stream instances;
+it exists for the sake of efficiency.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_int(xdrs, ip)
+\s-1XDR\s0 *xdrs;
+int *ip;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C integers
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_long(xdrs, lp)
+\s-1XDR\s0 *xdrs;
+long *lp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B long
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 12
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrmem_create(xdrs, addr, size, op)
+\s-1XDR\s0 *xdrs;
+char *addr;
+u_int size;
+enum xdr_op op;
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The stream's data is written to, or read from,
+a chunk of memory at location
+.I addr
+whose length is no more than
+.I size
+bytes long. The
+.I op
+determines the direction of the
+.SM XDR
+stream
+(either
+.BR \s-1XDR_ENCODE\s0 ,
+.BR \s-1XDR_DECODE\s0 ,
+or
+.BR \s-1XDR_FREE\s0 ).
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_opaque(xdrs, cp, cnt)
+\s-1XDR\s0 *xdrs;
+char *cp;
+u_int cnt;
+.fi
+.ft R
+.IP
+A filter primitive that translates between fixed size opaque
+data
+and its external representation.
+The parameter
+.I cp
+is the address of the opaque object, and
+.I cnt
+is its size in bytes.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_pointer(xdrs, objpp, objsize, xdrobj)
+\s-1XDR\s0 *xdrs;
+char **objpp;
+u_int objsize;
+xdrproc_t xdrobj;
+.fi
+.ft R
+.IP
+Like
+.B xdr_reference(\|)
+execpt that it serializes
+.SM NULL
+pointers, whereas
+.B xdr_reference(\|)
+does not. Thus,
+.B xdr_pointer(\|)
+can represent
+recursive data structures, such as binary trees or
+linked lists.
+.br
+.if t .ne 15
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrrec_create(xdrs, sendsize, recvsize, handle, readit, writeit)
+\s-1XDR\s0 *xdrs;
+u_int sendsize, recvsize;
+char *handle;
+int (*readit) (\|), (*writeit) (\|);
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The stream's data is written to a buffer of size
+.IR sendsize ;
+a value of zero indicates the system should use a suitable
+default. The stream's data is read from a buffer of size
+.IR recvsize ;
+it too can be set to a suitable default by passing a zero
+value.
+When a stream's output buffer is full,
+.I writeit
+is called. Similarly, when a stream's input buffer is empty,
+.I readit
+is called. The behavior of these two routines is similar to
+the
+system calls
+.B read
+and
+.BR write ,
+except that
+.I handle
+is passed to the former routines as the first parameter.
+Note: the
+.SM XDR
+stream's
+.I op
+field must be set by the caller.
+.IP
+Warning: this
+.SM XDR
+stream implements an intermediate record stream.
+Therefore there are additional bytes in the stream
+to provide record boundary information.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_endofrecord(xdrs, sendnow)
+\s-1XDR\s0 *xdrs;
+int sendnow;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+The data in the output buffer is marked as a completed
+record,
+and the output buffer is optionally written out if
+.I sendnow
+is non-zero. This routine returns one if it succeeds, zero
+otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_eof(xdrs)
+\s-1XDR\s0 *xdrs;
+int empty;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+After consuming the rest of the current record in the stream,
+this routine returns one if the stream has no more input,
+zero otherwise.
+.br
+.if t .ne 3
+.LP
+.ft B
+.nf
+.sp .5
+xdrrec_skiprecord(xdrs)
+\s-1XDR\s0 *xdrs;
+.fi
+.ft R
+.IP
+This routine can be invoked only on
+streams created by
+.BR xdrrec_create(\|) .
+It tells the
+.SM XDR
+implementation that the rest of the current record
+in the stream's input buffer should be discarded.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 11
+.LP
+.ft B
+.nf
+.sp .5
+xdr_reference(xdrs, pp, size, proc)
+\s-1XDR\s0 *xdrs;
+char **pp;
+u_int size;
+xdrproc_t proc;
+.fi
+.ft R
+.IP
+A primitive that provides pointer chasing within structures.
+The parameter
+.I pp
+is the address of the pointer;
+.I size
+is the
+.I sizeof
+the structure that
+.I *pp
+points to; and
+.I proc
+is an
+.SM XDR
+procedure that filters the structure
+between its C form and its external representation.
+This routine returns one if it succeeds, zero otherwise.
+.IP
+Warning: this routine does not understand
+.SM NULL
+pointers. Use
+.B xdr_pointer(\|)
+instead.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_setpos(xdrs, pos)
+\s-1XDR\s0 *xdrs;
+u_int pos;
+.fi
+.ft R
+.IP
+A macro that invokes the set position routine associated with
+the
+.SM XDR
+stream
+.IR xdrs .
+The parameter
+.I pos
+is a position value obtained from
+.BR xdr_getpos(\|) .
+This routine returns one if the
+.SM XDR
+stream could be repositioned,
+and zero otherwise.
+.IP
+Warning: it is difficult to reposition some types of
+.SM XDR
+streams, so this routine may fail with one
+type of stream and succeed with another.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_short(xdrs, sp)
+\s-1XDR\s0 *xdrs;
+short *sp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B short
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+void
+xdrstdio_create(xdrs, file, op)
+\s-1XDR\s0 *xdrs;
+\s-1FILE\s0 *file;
+enum xdr_op op;
+.fi
+.ft R
+.IP
+This routine initializes the
+.SM XDR
+stream object pointed to by
+.IR xdrs .
+The
+.SM XDR
+stream data is written to, or read from, the Standard
+.B I/O
+stream
+.IR file .
+The parameter
+.I op
+determines the direction of the
+.SM XDR
+stream (either
+.BR \s-1XDR_ENCODE\s0 ,
+.BR \s-1XDR_DECODE\s0 ,
+or
+.BR \s-1XDR_FREE\s0 ).
+.IP
+Warning: the destroy routine associated with such
+.SM XDR
+streams calls
+.B fflush(\|)
+on the
+.I file
+stream, but never
+.BR fclose(\|) .
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdr_string(xdrs, sp, maxsize)
+\s-1XDR\s0
+*xdrs;
+char **sp;
+u_int maxsize;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C strings and
+their
+corresponding external representations.
+Strings cannot be longer than
+.IR maxsize .
+Note:
+.I sp
+is the address of the string's pointer.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 8
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_char(xdrs, ucp)
+\s-1XDR\s0 *xdrs;
+unsigned char *ucp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between
+.B unsigned
+C characters and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 9
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_int(xdrs, up)
+\s-1XDR\s0 *xdrs;
+unsigned *up;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B unsigned
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_long(xdrs, ulp)
+\s-1XDR\s0 *xdrs;
+unsigned long *ulp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B "unsigned long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 7
+.LP
+.ft B
+.nf
+.sp .5
+xdr_u_short(xdrs, usp)
+\s-1XDR\s0 *xdrs;
+unsigned short *usp;
+.fi
+.ft R
+.IP
+A filter primitive that translates between C
+.B "unsigned short"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 16
+.LP
+.ft B
+.nf
+.sp .5
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+\s-1XDR\s0 *xdrs;
+int *dscmp;
+char *unp;
+struct xdr_discrim *choices;
+bool_t (*defaultarm) (\|); /* may equal \s-1NULL\s0 */
+.fi
+.ft R
+.IP
+A filter primitive that translates between a discriminated C
+.B union
+and its corresponding external representation. It first
+translates the discriminant of the union located at
+.IR dscmp .
+This discriminant is always an
+.BR enum_t .
+Next the union located at
+.I unp
+is translated. The parameter
+.I choices
+is a pointer to an array of
+.B xdr_discrim(\|)
+structures. Each structure contains an ordered pair of
+.RI [ value , proc ].
+If the union's discriminant is equal to the associated
+.IR value ,
+then the
+.I proc
+is called to translate the union. The end of the
+.B xdr_discrim(\|)
+structure array is denoted by a routine of value
+.SM NULL\s0.
+If the discriminant is not found in the
+.I choices
+array, then the
+.I defaultarm
+procedure is called (if it is not
+.SM NULL\s0).
+Returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 6
+.LP
+.ft B
+.nf
+.sp .5
+xdr_vector(xdrs, arrp, size, elsize, elproc)
+\s-1XDR\s0 *xdrs;
+char *arrp;
+u_int size, elsize;
+xdrproc_t elproc;
+.fi
+.ft R
+.IP
+A filter primitive that translates between fixed-length
+arrays
+and their corresponding external representations. The
+parameter
+.I arrp
+is the address of the pointer to the array, while
+.I size
+is is the element count of the array. The parameter
+.I elsize
+is the
+.I sizeof
+each of the array's elements, and
+.I elproc
+is an
+.SM XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.br
+.if t .ne 5
+.LP
+.ft B
+.nf
+.sp .5
+xdr_void(\|)
+.fi
+.ft R
+.IP
+This routine always returns one.
+It may be passed to
+.SM RPC
+routines that require a function parameter,
+where nothing is to be done.
+.br
+.if t .ne 10
+.LP
+.ft B
+.nf
+.sp .5
+xdr_wrapstring(xdrs, sp)
+\s-1XDR\s0 *xdrs;
+char **sp;
+.fi
+.ft R
+.IP
+A primitive that calls
+.B "xdr_string(xdrs, sp,\s-1MAXUN.UNSIGNED\s0 );"
+where
+.B
+.SM MAXUN.UNSIGNED
+is the maximum value of an unsigned integer.
+.B xdr_wrapstring(\|)
+is handy because the
+.SM RPC
+package passes a maximum of two
+.SM XDR
+routines as parameters, and
+.BR xdr_string(\|) ,
+one of the most frequently used primitives, requires three.
+Returns one if it succeeds, zero otherwise.
+.SH SEE ALSO
+.BR rpc (3N)
+.LP
+The following manuals:
+.RS
+.ft I
+eXternal Data Representation Standard: Protocol Specification
+.br
+eXternal Data Representation: Sun Technical Notes
+.ft R
+.br
+.IR "\s-1XDR\s0: External Data Representation Standard" ,
+.SM RFC1014, Sun Microsystems, Inc.,
+.SM USC-ISI\s0.
diff --git a/lib/libc/rpc/xdr.c b/lib/libc/rpc/xdr.c
new file mode 100644
index 000000000000..9f402047aa5a
--- /dev/null
+++ b/lib/libc/rpc/xdr.c
@@ -0,0 +1,578 @@
+/*
+ * 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: @(#)xdr.c 1.35 87/08/12";*/
+/*static char *sccsid = "from: @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr.c,v 1.1 1993/10/27 05:41:06 paul Exp $";
+#endif
+
+/*
+ * xdr.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ *
+ * These are the "generic" xdr routines used to serialize and de-serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE ((long) 0)
+#define XDR_TRUE ((long) 1)
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * for unit alignment
+ */
+static char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+
+/*
+ * Free a data structure using XDR
+ * Not a filter, but a convenient utility nonetheless
+ */
+void
+xdr_free(proc, objp)
+ xdrproc_t proc;
+ char *objp;
+{
+ XDR x;
+
+ x.x_op = XDR_FREE;
+ (*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(/* xdrs, addr */)
+ /* XDR *xdrs; */
+ /* caddr_t addr; */
+{
+
+ return (TRUE);
+}
+
+/*
+ * XDR integers
+ */
+bool_t
+xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+{
+
+#ifdef lint
+ (void) (xdr_short(xdrs, (short *)ip));
+ return (xdr_long(xdrs, (long *)ip));
+#else
+ if (sizeof (int) == sizeof (long)) {
+ return (xdr_long(xdrs, (long *)ip));
+ } else {
+ return (xdr_short(xdrs, (short *)ip));
+ }
+#endif
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ u_int *up;
+{
+
+#ifdef lint
+ (void) (xdr_short(xdrs, (short *)up));
+ return (xdr_u_long(xdrs, (u_long *)up));
+#else
+ if (sizeof (u_int) == sizeof (u_long)) {
+ return (xdr_u_long(xdrs, (u_long *)up));
+ } else {
+ return (xdr_short(xdrs, (short *)up));
+ }
+#endif
+}
+
+/*
+ * XDR long integers
+ * same as xdr_u_long - open coded to save a proc call!
+ */
+bool_t
+xdr_long(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if (xdrs->x_op == XDR_ENCODE)
+ return (XDR_PUTLONG(xdrs, lp));
+
+ if (xdrs->x_op == XDR_DECODE)
+ return (XDR_GETLONG(xdrs, lp));
+
+ if (xdrs->x_op == XDR_FREE)
+ return (TRUE);
+
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ * same as xdr_long - open coded to save a proc call!
+ */
+bool_t
+xdr_u_long(xdrs, ulp)
+ register XDR *xdrs;
+ u_long *ulp;
+{
+
+ if (xdrs->x_op == XDR_DECODE)
+ return (XDR_GETLONG(xdrs, (long *)ulp));
+ if (xdrs->x_op == XDR_ENCODE)
+ return (XDR_PUTLONG(xdrs, (long *)ulp));
+ if (xdrs->x_op == XDR_FREE)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(xdrs, sp)
+ register XDR *xdrs;
+ short *sp;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *sp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *sp = (short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(xdrs, usp)
+ register XDR *xdrs;
+ u_short *usp;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *usp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *usp = (u_short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+
+/*
+ * XDR a char
+ */
+bool_t
+xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+{
+ int i;
+
+ i = (*cp);
+ if (!xdr_int(xdrs, &i)) {
+ return (FALSE);
+ }
+ *cp = i;
+ return (TRUE);
+}
+
+/*
+ * XDR an unsigned char
+ */
+bool_t
+xdr_u_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+{
+ u_int u;
+
+ u = (*cp);
+ if (!xdr_u_int(xdrs, &u)) {
+ return (FALSE);
+ }
+ *cp = u;
+ return (TRUE);
+}
+
+/*
+ * XDR booleans
+ */
+bool_t
+xdr_bool(xdrs, bp)
+ register XDR *xdrs;
+ bool_t *bp;
+{
+ long lb;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ lb = *bp ? XDR_TRUE : XDR_FALSE;
+ return (XDR_PUTLONG(xdrs, &lb));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &lb)) {
+ return (FALSE);
+ }
+ *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+{
+#ifndef lint
+ enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
+
+ /*
+ * enums are treated as ints
+ */
+ if (sizeof (enum sizecheck) == sizeof (long)) {
+ return (xdr_long(xdrs, (long *)ep));
+ } else if (sizeof (enum sizecheck) == sizeof (short)) {
+ return (xdr_short(xdrs, (short *)ep));
+ } else {
+ return (FALSE);
+ }
+#else
+ (void) (xdr_short(xdrs, (short *)ep));
+ return (xdr_long(xdrs, (long *)ep));
+#endif
+}
+
+/*
+ * XDR opaque data
+ * Allows the specification of a fixed size sequence of opaque bytes.
+ * cp points to the opaque object and cnt gives the byte length.
+ */
+bool_t
+xdr_opaque(xdrs, cp, cnt)
+ register XDR *xdrs;
+ caddr_t cp;
+ register u_int cnt;
+{
+ register u_int rndup;
+ static crud[BYTES_PER_XDR_UNIT];
+
+ /*
+ * if no data we are done
+ */
+ if (cnt == 0)
+ return (TRUE);
+
+ /*
+ * round byte count to full xdr units
+ */
+ rndup = cnt % BYTES_PER_XDR_UNIT;
+ if (rndup > 0)
+ rndup = BYTES_PER_XDR_UNIT - rndup;
+
+ if (xdrs->x_op == XDR_DECODE) {
+ if (!XDR_GETBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_GETBYTES(xdrs, crud, rndup));
+ }
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+ }
+
+ if (xdrs->x_op == XDR_FREE) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * XDR counted bytes
+ * *cpp is a pointer to the bytes, *sizep is the count.
+ * If *cpp is NULL maxsize bytes are allocated
+ */
+bool_t
+xdr_bytes(xdrs, cpp, sizep, maxsize)
+ register XDR *xdrs;
+ char **cpp;
+ register u_int *sizep;
+ u_int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ register u_int nodesize;
+
+ /*
+ * first deal with the length since xdr bytes are counted
+ */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ nodesize = *sizep;
+ if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL) {
+ *cpp = sp = (char *)mem_alloc(nodesize);
+ }
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_bytes: out of memory\n");
+ return (FALSE);
+ }
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, nodesize));
+
+ case XDR_FREE:
+ if (sp != NULL) {
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ }
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * Implemented here due to commonality of the object.
+ */
+bool_t
+xdr_netobj(xdrs, np)
+ XDR *xdrs;
+ struct netobj *np;
+{
+
+ return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+}
+
+/*
+ * XDR a descriminated union
+ * Support routine for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer. The routine gets
+ * the discriminant value and then searches the array of xdrdiscrims
+ * looking for that value. It calls the procedure given in the xdrdiscrim
+ * to handle the discriminant. If there is no specific routine a default
+ * routine may be called.
+ * If there is no specific or default routine an error is returned.
+ */
+bool_t
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+ register XDR *xdrs;
+ enum_t *dscmp; /* enum to decide which arm to work on */
+ char *unp; /* the union itself */
+ struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
+ xdrproc_t dfault; /* default xdr routine */
+{
+ register enum_t dscm;
+
+ /*
+ * we deal with the discriminator; it's an enum
+ */
+ if (! xdr_enum(xdrs, dscmp)) {
+ return (FALSE);
+ }
+ dscm = *dscmp;
+
+ /*
+ * search choices for a value that matches the discriminator.
+ * if we find one, execute the xdr routine for that value.
+ */
+ for (; choices->proc != NULL_xdrproc_t; choices++) {
+ if (choices->value == dscm)
+ return ((*(choices->proc))(xdrs, unp, LASTUNSIGNED));
+ }
+
+ /*
+ * no match - execute the default xdr routine if there is one
+ */
+ return ((dfault == NULL_xdrproc_t) ? FALSE :
+ (*dfault)(xdrs, unp, LASTUNSIGNED));
+}
+
+
+/*
+ * Non-portable xdr primitives.
+ * Care should be taken when moving these routines to new architectures.
+ */
+
+
+/*
+ * XDR null terminated ASCII strings
+ * xdr_string deals with "C strings" - arrays of bytes that are
+ * terminated by a NULL character. The parameter cpp references a
+ * pointer to storage; If the pointer is null, then the necessary
+ * storage is allocated. The last parameter is the max allowed length
+ * of the string as specified by a protocol.
+ */
+bool_t
+xdr_string(xdrs, cpp, maxsize)
+ register XDR *xdrs;
+ char **cpp;
+ u_int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ u_int size;
+ u_int nodesize;
+
+ /*
+ * first deal with the length since xdr strings are counted-strings
+ */
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ if (sp == NULL) {
+ return(TRUE); /* already free */
+ }
+ /* fall through... */
+ case XDR_ENCODE:
+ size = strlen(sp);
+ break;
+ }
+ if (! xdr_u_int(xdrs, &size)) {
+ return (FALSE);
+ }
+ if (size > maxsize) {
+ return (FALSE);
+ }
+ nodesize = size + 1;
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL)
+ *cpp = sp = (char *)mem_alloc(nodesize);
+ if (sp == NULL) {
+ (void) fprintf(stderr, "xdr_string: out of memory\n");
+ return (FALSE);
+ }
+ sp[size] = 0;
+ /* fall into ... */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, size));
+
+ case XDR_FREE:
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * Wrapper for xdr_string that can be called directly from
+ * routines like clnt_call
+ */
+bool_t
+xdr_wrapstring(xdrs, cpp)
+ XDR *xdrs;
+ char **cpp;
+{
+ if (xdr_string(xdrs, cpp, LASTUNSIGNED)) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/lib/libc/rpc/xdr.h b/lib/libc/rpc/xdr.h
new file mode 100644
index 000000000000..c29cc4816c22
--- /dev/null
+++ b/lib/libc/rpc/xdr.h
@@ -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
+ *
+ * from: @(#)xdr.h 1.19 87/04/22 SMI
+ * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC
+ * $Id: xdr.h,v 1.1 1993/10/27 05:41:07 paul Exp $
+ */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _RPC_XDR_H
+#define _RPC_XDR_H
+#include <sys/cdefs.h>
+
+/*
+ * XDR provides a conventional way for converting between C data
+ * types and an external bit-string representation. Library supplied
+ * routines provide for the conversion on built-in C data types. These
+ * routines and utility routines defined here are used to help implement
+ * a type encode/decode routine for each user-defined type.
+ *
+ * Each data type provides a single procedure which takes two arguments:
+ *
+ * bool_t
+ * xdrproc(xdrs, argresp)
+ * XDR *xdrs;
+ * <type> *argresp;
+ *
+ * xdrs is an instance of a XDR handle, to which or from which the data
+ * type is to be converted. argresp is a pointer to the structure to be
+ * converted. The XDR handle contains an operation field which indicates
+ * which of the operations (ENCODE, DECODE * or FREE) is to be performed.
+ *
+ * XDR_DECODE may allocate space if the pointer argresp is null. This
+ * data can be freed with the XDR_FREE operation.
+ *
+ * We write only one procedure per data type to make it easy
+ * to keep the encode and decode procedures for a data type consistent.
+ * In many cases the same code performs all operations on a user defined type,
+ * because all the hard work is done in the component type routines.
+ * decode as a series of calls on the nested data types.
+ */
+
+/*
+ * Xdr operations. XDR_ENCODE causes the type to be encoded into the
+ * stream. XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+ XDR_ENCODE=0,
+ XDR_DECODE=1,
+ XDR_FREE=2
+};
+
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT (4)
+#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \
+ * BYTES_PER_XDR_UNIT)
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or decoded.
+ *
+ * The second argument to the xdrproc_t is a pointer to an opaque pointer.
+ * The opaque pointer generally points to a structure of the data type
+ * to be decoded. If this pointer is 0, then the type routines should
+ * allocate dynamic storage of the appropriate size and return it.
+ * bool_t (*xdrproc_t)(XDR *, caddr_t *);
+ */
+typedef bool_t (*xdrproc_t)();
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the paticular implementation (e.g. see xdr_mem.c),
+ * and two private fields for the use of the particular impelementation.
+ */
+typedef struct {
+ enum xdr_op x_op; /* operation; fast additional param */
+ struct xdr_ops {
+ bool_t (*x_getlong)(); /* get a long from underlying stream */
+ bool_t (*x_putlong)(); /* put a long to " */
+ bool_t (*x_getbytes)();/* get some bytes from " */
+ bool_t (*x_putbytes)();/* put some bytes to " */
+ u_int (*x_getpostn)();/* returns bytes off from beginning */
+ bool_t (*x_setpostn)();/* lets you reposition the stream */
+ long * (*x_inline)(); /* buf quick ptr to buffered data */
+ void (*x_destroy)(); /* free privates of this xdr_stream */
+ } *x_ops;
+ caddr_t x_public; /* users' data */
+ caddr_t x_private; /* pointer to private data */
+ caddr_t x_base; /* private used for position info */
+ int x_handy; /* extra private word */
+} XDR;
+
+/*
+ * Operations defined on a XDR handle
+ *
+ * XDR *xdrs;
+ * long *longp;
+ * caddr_t addr;
+ * u_int len;
+ * u_int pos;
+ */
+#define XDR_GETLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+#define xdr_getlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_getlong)(xdrs, longp)
+
+#define XDR_PUTLONG(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+#define xdr_putlong(xdrs, longp) \
+ (*(xdrs)->x_ops->x_putlong)(xdrs, longp)
+
+#define XDR_GETBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+#define xdr_getbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len)
+
+#define XDR_PUTBYTES(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+#define xdr_putbytes(xdrs, addr, len) \
+ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len)
+
+#define XDR_GETPOS(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+#define xdr_getpos(xdrs) \
+ (*(xdrs)->x_ops->x_getpostn)(xdrs)
+
+#define XDR_SETPOS(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+#define xdr_setpos(xdrs, pos) \
+ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos)
+
+#define XDR_INLINE(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+#define xdr_inline(xdrs, len) \
+ (*(xdrs)->x_ops->x_inline)(xdrs, len)
+
+#define XDR_DESTROY(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+#define xdr_destroy(xdrs) \
+ if ((xdrs)->x_ops->x_destroy) \
+ (*(xdrs)->x_ops->x_destroy)(xdrs)
+
+/*
+ * Support struct for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * a entry with a null procedure pointer. The xdr_union routine gets
+ * the discriminant value and then searches the array of structures
+ * for a matching value. If a match is found the associated xdr routine
+ * is called to handle that part of the union. If there is
+ * no match, then a default routine may be called.
+ * If there is no match and no default routine it is an error.
+ */
+#define NULL_xdrproc_t ((xdrproc_t)0)
+struct xdr_discrim {
+ int value;
+ xdrproc_t proc;
+};
+
+/*
+ * In-line routines for fast encode/decode of primitve data types.
+ * Caveat emptor: these use single memory cycles to get the
+ * data from the underlying buffer, and will fail to operate
+ * properly if the data is not aligned. The standard way to use these
+ * is to say:
+ * if ((buf = XDR_INLINE(xdrs, count)) == NULL)
+ * return (FALSE);
+ * <<< macro calls >>>
+ * where ``count'' is the number of bytes of data occupied
+ * by the primitive data types.
+ *
+ * N.B. and frozen for all time: each data type here uses 4 bytes
+ * of external representation.
+ */
+#define IXDR_GET_LONG(buf) ((long)ntohl((u_long)*(buf)++))
+#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (long)htonl((u_long)v))
+
+#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf))
+#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf))
+#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf))
+
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((long)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+__BEGIN_DECLS
+extern bool_t xdr_void __P((void));
+extern bool_t xdr_int __P((XDR *, int *));
+extern bool_t xdr_u_int __P((XDR *, u_int *));
+extern bool_t xdr_long __P((XDR *, long *));
+extern bool_t xdr_u_long __P((XDR *, u_long *));
+extern bool_t xdr_short __P((XDR *, short *));
+extern bool_t xdr_u_short __P((XDR *, u_short *));
+extern bool_t xdr_bool __P((XDR *, bool_t *));
+extern bool_t xdr_enum __P((XDR *, enum_t *));
+extern bool_t xdr_array __P((XDR *, char **, u_int *, u_int, u_int, xdrproc_t));
+extern bool_t xdr_bytes __P((XDR *, char **, u_int *, u_int));
+extern bool_t xdr_opaque __P((XDR *, caddr_t, u_int));
+extern bool_t xdr_string __P((XDR *, char **, u_int));
+extern bool_t xdr_union __P((XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t));
+extern bool_t xdr_char __P((XDR *, char *));
+extern bool_t xdr_u_char __P((XDR *, char *));
+extern bool_t xdr_vector __P((XDR *, char *, u_int, u_int, xdrproc_t));
+extern bool_t xdr_float __P((XDR *, float *));
+extern bool_t xdr_double __P((XDR *, double *));
+extern bool_t xdr_reference __P((XDR *, caddr_t *, u_int, xdrproc_t));
+extern bool_t xdr_pointer __P((XDR *, caddr_t *, u_int, xdrproc_t));
+extern bool_t xdr_wrapstring __P((XDR *, char **));
+extern void xdr_free __P((xdrproc_t, char *));
+__END_DECLS
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 1024
+struct netobj {
+ u_int n_len;
+ char *n_bytes;
+};
+typedef struct netobj netobj;
+extern bool_t xdr_netobj();
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+__BEGIN_DECLS
+/* XDR using memory buffers */
+extern void xdrmem_create __P((XDR *, char *, u_int, enum xdr_op));
+
+#ifdef _STDIO_H_
+/* XDR using stdio library */
+extern void xdrstdio_create __P((XDR *, FILE *, enum xdr_op));
+#endif
+
+/* XDR pseudo records for tcp */
+extern void xdrrec_create __P((XDR *, u_int, u_int, char *, int (*)(), int (*)()));
+
+/* make end of xdr record */
+extern bool_t xdrrec_endofrecord __P((XDR *, int));
+
+/* move to beginning of next record */
+extern bool_t xdrrec_skiprecord __P((XDR *));
+
+/* true if no more input */
+extern bool_t xdrrec_eof __P((XDR *));
+__END_DECLS
+
+#endif /* !_RPC_XDR_H */
diff --git a/lib/libc/rpc/xdr_array.c b/lib/libc/rpc/xdr_array.c
new file mode 100644
index 000000000000..a17b534a92e7
--- /dev/null
+++ b/lib/libc/rpc/xdr_array.c
@@ -0,0 +1,155 @@
+/*
+ * 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: @(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_array.c,v 1.1 1993/10/27 05:41:09 paul Exp $";
+#endif
+
+/*
+ * xdr_array.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * arrays. See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((u_int)0-1)
+
+
+/*
+ * XDR an array of arbitrary elements
+ * *addrp is a pointer to the array, *sizep is the number of elements.
+ * If addrp is NULL (*sizep * elsize) bytes are allocated.
+ * elsize is the size (in bytes) of each element, and elproc is the
+ * xdr procedure to call to handle each element of the array.
+ */
+bool_t
+xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
+ register XDR *xdrs;
+ caddr_t *addrp; /* array pointer */
+ u_int *sizep; /* number of elements */
+ u_int maxsize; /* max numberof elements */
+ u_int elsize; /* size in bytes of each element */
+ xdrproc_t elproc; /* xdr routine to handle each element */
+{
+ register u_int i;
+ register caddr_t target = *addrp;
+ register u_int c; /* the actual element count */
+ register bool_t stat = TRUE;
+ register u_int nodesize;
+
+ /* like strings, arrays are really counted arrays */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ c = *sizep;
+ if ((c > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+ nodesize = c * elsize;
+
+ /*
+ * if we are deserializing, we may need to allocate an array.
+ * We also save time by checking for a null array if we are freeing.
+ */
+ if (target == NULL)
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (c == 0)
+ return (TRUE);
+ *addrp = target = mem_alloc(nodesize);
+ if (target == NULL) {
+ (void) fprintf(stderr,
+ "xdr_array: out of memory\n");
+ return (FALSE);
+ }
+ bzero(target, nodesize);
+ break;
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+
+ /*
+ * now we xdr each element of array
+ */
+ for (i = 0; (i < c) && stat; i++) {
+ stat = (*elproc)(xdrs, target, LASTUNSIGNED);
+ target += elsize;
+ }
+
+ /*
+ * the array may need freeing
+ */
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(*addrp, nodesize);
+ *addrp = NULL;
+ }
+ return (stat);
+}
+
+/*
+ * xdr_vector():
+ *
+ * XDR a fixed length array. Unlike variable-length arrays,
+ * the storage of fixed length arrays is static and unfreeable.
+ * > basep: base of the array
+ * > size: size of the array
+ * > elemsize: size of each element
+ * > xdr_elem: routine to XDR each element
+ */
+bool_t
+xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
+ register XDR *xdrs;
+ register char *basep;
+ register u_int nelem;
+ register u_int elemsize;
+ register xdrproc_t xdr_elem;
+{
+ register u_int i;
+ register char *elptr;
+
+ elptr = basep;
+ for (i = 0; i < nelem; i++) {
+ if (! (*xdr_elem)(xdrs, elptr, LASTUNSIGNED)) {
+ return(FALSE);
+ }
+ elptr += elemsize;
+ }
+ return(TRUE);
+}
+
diff --git a/lib/libc/rpc/xdr_float.c b/lib/libc/rpc/xdr_float.c
new file mode 100644
index 000000000000..fae0c8b7f8e3
--- /dev/null
+++ b/lib/libc/rpc/xdr_float.c
@@ -0,0 +1,283 @@
+/*
+ * 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: @(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_float.c,v 1.1 1993/10/27 05:41:10 paul Exp $";
+#endif
+
+/*
+ * xdr_float.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "floating point" xdr routines used to (de)serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * NB: Not portable.
+ * This routine works on Suns (Sky / 68000's), i386's, MIPS, NS32k and Vaxen.
+ */
+
+#if defined(mc68000)||defined(sparc)||defined(i386)||defined(mips)||defined(ns32000)
+#define IEEEFP
+#endif
+
+#ifdef vax
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct ieee_single {
+ unsigned int mantissa: 23;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+};
+
+/* Vax single precision floating point */
+struct vax_single {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS 0x81
+#define IEEE_SNG_BIAS 0x7f
+
+static struct sgl_limits {
+ struct vax_single s;
+ struct ieee_single ieee;
+} sgl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
+ { 0x0, 0xff, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
+ { 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+#endif /* vax */
+
+bool_t
+xdr_float(xdrs, fp)
+ register XDR *xdrs;
+ register float *fp;
+{
+#ifndef IEEEFP
+ struct ieee_single is;
+ struct vax_single vs, *vsp;
+ struct sgl_limits *lim;
+ int i;
+#endif
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ return (XDR_PUTLONG(xdrs, (long *)fp));
+#else
+ vs = *((struct vax_single *)fp);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((vs.mantissa2 == lim->s.mantissa2) &&
+ (vs.exp == lim->s.exp) &&
+ (vs.mantissa1 == lim->s.mantissa1)) {
+ is = lim->ieee;
+ goto shipit;
+ }
+ }
+ is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+ is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
+ shipit:
+ is.sign = vs.sign;
+ return (XDR_PUTLONG(xdrs, (long *)&is));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ return (XDR_GETLONG(xdrs, (long *)fp));
+#else
+ vsp = (struct vax_single *)fp;
+ if (!XDR_GETLONG(xdrs, (long *)&is))
+ return (FALSE);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((is.exp == lim->ieee.exp) &&
+ (is.mantissa == lim->ieee.mantissa)) {
+ *vsp = lim->s;
+ goto doneit;
+ }
+ }
+ vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+ vsp->mantissa2 = is.mantissa;
+ vsp->mantissa1 = (is.mantissa >> 16);
+ doneit:
+ vsp->sign = is.sign;
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * This routine works on Suns (Sky / 68000's), i386's, MIPS and Vaxen.
+ */
+
+#ifdef vax
+/* What IEEE double precision floating point looks like on a Vax */
+struct ieee_double {
+ unsigned int mantissa1 : 20;
+ unsigned int exp : 11;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 32;
+};
+
+/* Vax double precision floating point */
+struct vax_double {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+ unsigned int mantissa3 : 16;
+ unsigned int mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS 0x81
+#define IEEE_DBL_BIAS 0x3ff
+#define MASK(nbits) ((1 << nbits) - 1)
+
+static struct dbl_limits {
+ struct vax_double d;
+ struct ieee_double ieee;
+} dbl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
+ { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
+ { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+
+#endif /* vax */
+
+
+bool_t
+xdr_double(xdrs, dp)
+ register XDR *xdrs;
+ double *dp;
+{
+ register long *lp;
+#ifndef IEEEFP
+ struct ieee_double id;
+ struct vax_double vd;
+ register struct dbl_limits *lim;
+ int i;
+#endif
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ lp = (long *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#else
+ return (XDR_PUTLONG(xdrs, lp+1) && XDR_PUTLONG(xdrs, lp));
+#endif
+#else
+ vd = *((struct vax_double *)dp);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((vd.mantissa4 == lim->d.mantissa4) &&
+ (vd.mantissa3 == lim->d.mantissa3) &&
+ (vd.mantissa2 == lim->d.mantissa2) &&
+ (vd.mantissa1 == lim->d.mantissa1) &&
+ (vd.exp == lim->d.exp)) {
+ id = lim->ieee;
+ goto shipit;
+ }
+ }
+ id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+ id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
+ id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
+ (vd.mantissa3 << 13) |
+ ((vd.mantissa4 >> 3) & MASK(13));
+ shipit:
+ id.sign = vd.sign;
+ lp = (long *)&id;
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ lp = (long *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
+#else
+ return (XDR_GETLONG(xdrs, lp+1) && XDR_GETLONG(xdrs, lp));
+#endif
+#else
+ lp = (long *)&id;
+ if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp))
+ return (FALSE);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((id.mantissa2 == lim->ieee.mantissa2) &&
+ (id.mantissa1 == lim->ieee.mantissa1) &&
+ (id.exp == lim->ieee.exp)) {
+ vd = lim->d;
+ goto doneit;
+ }
+ }
+ vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+ vd.mantissa1 = (id.mantissa1 >> 13);
+ vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
+ (id.mantissa2 >> 29);
+ vd.mantissa3 = (id.mantissa2 >> 13);
+ vd.mantissa4 = (id.mantissa2 << 3);
+ doneit:
+ vd.sign = id.sign;
+ *dp = *((double *)&vd);
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/lib/libc/rpc/xdr_mem.c b/lib/libc/rpc/xdr_mem.c
new file mode 100644
index 000000000000..3909edda4ee8
--- /dev/null
+++ b/lib/libc/rpc/xdr_mem.c
@@ -0,0 +1,186 @@
+/*
+ * 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: @(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_mem.c,v 1.1 1993/10/27 05:41:11 paul Exp $";
+#endif
+
+/*
+ * xdr_mem.h, XDR implementation using memory buffers.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * If you have some data to be interpreted as external data representation
+ * or to be converted to external data representation in a memory buffer,
+ * then this is the package for you.
+ *
+ */
+
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+static bool_t xdrmem_getlong();
+static bool_t xdrmem_putlong();
+static bool_t xdrmem_getbytes();
+static bool_t xdrmem_putbytes();
+static u_int xdrmem_getpos();
+static bool_t xdrmem_setpos();
+static long * xdrmem_inline();
+static void xdrmem_destroy();
+
+static struct xdr_ops xdrmem_ops = {
+ xdrmem_getlong,
+ xdrmem_putlong,
+ xdrmem_getbytes,
+ xdrmem_putbytes,
+ xdrmem_getpos,
+ xdrmem_setpos,
+ xdrmem_inline,
+ xdrmem_destroy
+};
+
+/*
+ * The procedure xdrmem_create initializes a stream descriptor for a
+ * memory buffer.
+ */
+void
+xdrmem_create(xdrs, addr, size, op)
+ register XDR *xdrs;
+ caddr_t addr;
+ u_int size;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrmem_ops;
+ xdrs->x_private = xdrs->x_base = addr;
+ xdrs->x_handy = size;
+}
+
+static void
+xdrmem_destroy(/*xdrs*/)
+ /*XDR *xdrs;*/
+{
+}
+
+static bool_t
+xdrmem_getlong(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(long)) < 0)
+ return (FALSE);
+ *lp = (long)ntohl((u_long)(*((long *)(xdrs->x_private))));
+ xdrs->x_private += sizeof(long);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(long)) < 0)
+ return (FALSE);
+ *(long *)xdrs->x_private = (long)htonl((u_long)(*lp));
+ xdrs->x_private += sizeof(long);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register u_int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ bcopy(xdrs->x_private, addr, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register u_int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ bcopy(addr, xdrs->x_private, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static u_int
+xdrmem_getpos(xdrs)
+ register XDR *xdrs;
+{
+
+ return ((u_int)xdrs->x_private - (u_int)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(xdrs, pos)
+ register XDR *xdrs;
+ u_int pos;
+{
+ register caddr_t newaddr = xdrs->x_base + pos;
+ register caddr_t lastaddr = xdrs->x_private + xdrs->x_handy;
+
+ if ((long)newaddr > (long)lastaddr)
+ return (FALSE);
+ xdrs->x_private = newaddr;
+ xdrs->x_handy = (int)lastaddr - (int)newaddr;
+ return (TRUE);
+}
+
+static long *
+xdrmem_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ long *buf = 0;
+
+ if (xdrs->x_handy >= len) {
+ xdrs->x_handy -= len;
+ buf = (long *) xdrs->x_private;
+ xdrs->x_private += len;
+ }
+ return (buf);
+}
diff --git a/lib/libc/rpc/xdr_rec.c b/lib/libc/rpc/xdr_rec.c
new file mode 100644
index 000000000000..f2559d4b4f6b
--- /dev/null
+++ b/lib/libc/rpc/xdr_rec.c
@@ -0,0 +1,586 @@
+/*
+ * 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: @(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_rec.c,v 1.1 1993/10/27 05:41:12 paul Exp $";
+#endif
+
+/*
+ * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
+ * layer above tcp (for rpc's use).
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These routines interface XDRSTREAMS to a tcp/ip connection.
+ * There is a record marking layer between the xdr stream
+ * and the tcp transport level. A record is composed on one or more
+ * record fragments. A record fragment is a thirty-two bit header followed
+ * by n bytes of data, where n is contained in the header. The header
+ * is represented as a htonl(u_long). Thegh order bit encodes
+ * whether or not the fragment is the last fragment of the record
+ * (1 => fragment is last, 0 => more fragments to follow.
+ * The other 31 bits encode the byte length of the fragment.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+extern long lseek();
+
+static u_int fix_buf_size();
+static bool_t flush_out();
+static bool_t get_input_bytes();
+static bool_t set_input_fragment();
+static bool_t skip_input_bytes();
+
+static bool_t xdrrec_getlong();
+static bool_t xdrrec_putlong();
+static bool_t xdrrec_getbytes();
+static bool_t xdrrec_putbytes();
+static u_int xdrrec_getpos();
+static bool_t xdrrec_setpos();
+static long * xdrrec_inline();
+static void xdrrec_destroy();
+
+static struct xdr_ops xdrrec_ops = {
+ xdrrec_getlong,
+ xdrrec_putlong,
+ xdrrec_getbytes,
+ xdrrec_putbytes,
+ xdrrec_getpos,
+ xdrrec_setpos,
+ xdrrec_inline,
+ xdrrec_destroy
+};
+
+/*
+ * A record is composed of one or more record fragments.
+ * A record fragment is a two-byte header followed by zero to
+ * 2**32-1 bytes. The header is treated as a long unsigned and is
+ * encode/decoded to the network via htonl/ntohl. The low order 31 bits
+ * are a byte count of the fragment. The highest order bit is a boolean:
+ * 1 => this fragment is the last fragment of the record,
+ * 0 => this fragment is followed by more fragment(s).
+ *
+ * The fragment/record machinery is not general; it is constructed to
+ * meet the needs of xdr and rpc based on tcp.
+ */
+
+#define LAST_FRAG ((u_long)(1 << 31))
+
+typedef struct rec_strm {
+ caddr_t tcp_handle;
+ caddr_t the_buffer;
+ /*
+ * out-goung bits
+ */
+ int (*writeit)();
+ caddr_t out_base; /* output buffer (points to frag header) */
+ caddr_t out_finger; /* next output position */
+ caddr_t out_boundry; /* data cannot up to this address */
+ u_long *frag_header; /* beginning of curren fragment */
+ bool_t frag_sent; /* true if buffer sent in middle of record */
+ /*
+ * in-coming bits
+ */
+ int (*readit)();
+ u_long in_size; /* fixed size of the input buffer */
+ caddr_t in_base;
+ caddr_t in_finger; /* location of next byte to be had */
+ caddr_t in_boundry; /* can read up to this location */
+ long fbtbc; /* fragment bytes to be consumed */
+ bool_t last_frag;
+ u_int sendsize;
+ u_int recvsize;
+} RECSTREAM;
+
+
+/*
+ * Create an xdr handle for xdrrec
+ * xdrrec_create fills in xdrs. Sendsize and recvsize are
+ * send and recv buffer sizes (0 => use default).
+ * tcp_handle is an opaque handle that is passed as the first parameter to
+ * the procedures readit and writeit. Readit and writeit are read and
+ * write respectively. They are like the system
+ * calls expect that they take an opaque handle rather than an fd.
+ */
+void
+xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
+ register XDR *xdrs;
+ register u_int sendsize;
+ register u_int recvsize;
+ caddr_t tcp_handle;
+ int (*readit)(); /* like read, but pass it a tcp_handle, not sock */
+ int (*writeit)(); /* like write, but pass it a tcp_handle, not sock */
+{
+ register RECSTREAM *rstrm =
+ (RECSTREAM *)mem_alloc(sizeof(RECSTREAM));
+
+ if (rstrm == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ /*
+ * This is bad. Should rework xdrrec_create to
+ * return a handle, and in this case return NULL
+ */
+ return;
+ }
+ /*
+ * adjust sizes and allocate buffer quad byte aligned
+ */
+ rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+ rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+ rstrm->the_buffer = mem_alloc(sendsize + recvsize + BYTES_PER_XDR_UNIT);
+ if (rstrm->the_buffer == NULL) {
+ (void)fprintf(stderr, "xdrrec_create: out of memory\n");
+ return;
+ }
+ for (rstrm->out_base = rstrm->the_buffer;
+ (u_int)rstrm->out_base % BYTES_PER_XDR_UNIT != 0;
+ rstrm->out_base++);
+ rstrm->in_base = rstrm->out_base + sendsize;
+ /*
+ * now the rest ...
+ */
+ xdrs->x_ops = &xdrrec_ops;
+ xdrs->x_private = (caddr_t)rstrm;
+ rstrm->tcp_handle = tcp_handle;
+ rstrm->readit = readit;
+ rstrm->writeit = writeit;
+ rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+ rstrm->frag_header = (u_long *)rstrm->out_base;
+ rstrm->out_finger += sizeof(u_long);
+ rstrm->out_boundry += sendsize;
+ rstrm->frag_sent = FALSE;
+ rstrm->in_size = recvsize;
+ rstrm->in_boundry = rstrm->in_base;
+ rstrm->in_finger = (rstrm->in_boundry += recvsize);
+ rstrm->fbtbc = 0;
+ rstrm->last_frag = TRUE;
+}
+
+
+/*
+ * The reoutines defined below are the xdr ops which will go into the
+ * xdr handle filled in by xdrrec_create.
+ */
+
+static bool_t
+xdrrec_getlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register long *buflp = (long *)(rstrm->in_finger);
+ long mylong;
+
+ /* first try the inline, fast case */
+ if ((rstrm->fbtbc >= sizeof(long)) &&
+ (((int)rstrm->in_boundry - (int)buflp) >= sizeof(long))) {
+ *lp = (long)ntohl((u_long)(*buflp));
+ rstrm->fbtbc -= sizeof(long);
+ rstrm->in_finger += sizeof(long);
+ } else {
+ if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(long)))
+ return (FALSE);
+ *lp = (long)ntohl((u_long)mylong);
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register long *dest_lp = ((long *)(rstrm->out_finger));
+
+ if ((rstrm->out_finger += sizeof(long)) > rstrm->out_boundry) {
+ /*
+ * this case should almost never happen so the code is
+ * inefficient
+ */
+ rstrm->out_finger -= sizeof(long);
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ dest_lp = ((long *)(rstrm->out_finger));
+ rstrm->out_finger += sizeof(long);
+ }
+ *dest_lp = (long)htonl((u_long)(*lp));
+ return (TRUE);
+}
+
+static bool_t /* must manage buffers, fragments, and records */
+xdrrec_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register u_int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = rstrm->fbtbc;
+ if (current == 0) {
+ if (rstrm->last_frag)
+ return (FALSE);
+ if (! set_input_fragment(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ if (! get_input_bytes(rstrm, addr, current))
+ return (FALSE);
+ addr += current;
+ rstrm->fbtbc -= current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register u_int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = (u_int)rstrm->out_boundry - (u_int)rstrm->out_finger;
+ current = (len < current) ? len : current;
+ bcopy(addr, rstrm->out_finger, current);
+ rstrm->out_finger += current;
+ addr += current;
+ len -= current;
+ if (rstrm->out_finger == rstrm->out_boundry) {
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+static u_int
+xdrrec_getpos(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ register long pos;
+
+ pos = lseek((int)rstrm->tcp_handle, (long) 0, 1);
+ if (pos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ pos += rstrm->out_finger - rstrm->out_base;
+ break;
+
+ case XDR_DECODE:
+ pos -= rstrm->in_boundry - rstrm->in_finger;
+ break;
+
+ default:
+ pos = (u_int) -1;
+ break;
+ }
+ return ((u_int) pos);
+}
+
+static bool_t
+xdrrec_setpos(xdrs, pos)
+ register XDR *xdrs;
+ u_int pos;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ u_int currpos = xdrrec_getpos(xdrs);
+ int delta = currpos - pos;
+ caddr_t newpos;
+
+ if ((int)currpos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ newpos = rstrm->out_finger - delta;
+ if ((newpos > (caddr_t)(rstrm->frag_header)) &&
+ (newpos < rstrm->out_boundry)) {
+ rstrm->out_finger = newpos;
+ return (TRUE);
+ }
+ break;
+
+ case XDR_DECODE:
+ newpos = rstrm->in_finger - delta;
+ if ((delta < (int)(rstrm->fbtbc)) &&
+ (newpos <= rstrm->in_boundry) &&
+ (newpos >= rstrm->in_base)) {
+ rstrm->in_finger = newpos;
+ rstrm->fbtbc -= delta;
+ return (TRUE);
+ }
+ break;
+ }
+ return (FALSE);
+}
+
+static long *
+xdrrec_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ long * buf = NULL;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
+ buf = (long *) rstrm->out_finger;
+ rstrm->out_finger += len;
+ }
+ break;
+
+ case XDR_DECODE:
+ if ((len <= rstrm->fbtbc) &&
+ ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
+ buf = (long *) rstrm->in_finger;
+ rstrm->fbtbc -= len;
+ rstrm->in_finger += len;
+ }
+ break;
+ }
+ return (buf);
+}
+
+static void
+xdrrec_destroy(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+ mem_free(rstrm->the_buffer,
+ rstrm->sendsize + rstrm->recvsize + BYTES_PER_XDR_UNIT);
+ mem_free((caddr_t)rstrm, sizeof(RECSTREAM));
+}
+
+
+/*
+ * Exported routines to manage xdr records
+ */
+
+/*
+ * Before reading (deserializing from the stream, one should always call
+ * this procedure to guarantee proper record alignment.
+ */
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (FALSE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (FALSE);
+ }
+ rstrm->last_frag = FALSE;
+ return (TRUE);
+}
+
+/*
+ * Look ahead fuction.
+ * Returns TRUE iff there is no more input in the buffer
+ * after consuming the rest of the current record.
+ */
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (TRUE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (TRUE);
+ }
+ if (rstrm->in_finger == rstrm->in_boundry)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * The client must tell the package when an end-of-record has occurred.
+ * The second paraemters tells whether the record should be flushed to the
+ * (output) tcp stream. (This let's the package support batched or
+ * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
+ */
+bool_t
+xdrrec_endofrecord(xdrs, sendnow)
+ XDR *xdrs;
+ bool_t sendnow;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register u_long len; /* fragment length */
+
+ if (sendnow || rstrm->frag_sent ||
+ ((u_long)rstrm->out_finger + sizeof(u_long) >=
+ (u_long)rstrm->out_boundry)) {
+ rstrm->frag_sent = FALSE;
+ return (flush_out(rstrm, TRUE));
+ }
+ len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
+ sizeof(u_long);
+ *(rstrm->frag_header) = htonl((u_long)len | LAST_FRAG);
+ rstrm->frag_header = (u_long *)rstrm->out_finger;
+ rstrm->out_finger += sizeof(u_long);
+ return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(rstrm, eor)
+ register RECSTREAM *rstrm;
+ bool_t eor;
+{
+ register u_long eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ register u_long len = (u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->frag_header) - sizeof(u_long);
+
+ *(rstrm->frag_header) = htonl(len | eormask);
+ len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->out_base);
+ if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+ != (int)len)
+ return (FALSE);
+ rstrm->frag_header = (u_long *)rstrm->out_base;
+ rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(u_long);
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+fill_input_buf(rstrm)
+ register RECSTREAM *rstrm;
+{
+ register caddr_t where;
+ u_int i;
+ register int len;
+
+ where = rstrm->in_base;
+ i = (u_int)rstrm->in_boundry % BYTES_PER_XDR_UNIT;
+ where += i;
+ len = rstrm->in_size - i;
+ if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
+ return (FALSE);
+ rstrm->in_finger = where;
+ where += len;
+ rstrm->in_boundry = where;
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+get_input_bytes(rstrm, addr, len)
+ register RECSTREAM *rstrm;
+ register caddr_t addr;
+ register int len;
+{
+ register int current;
+
+ while (len > 0) {
+ current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ bcopy(rstrm->in_finger, addr, current);
+ rstrm->in_finger += current;
+ addr += current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t /* next two bytes of the input stream are treated as a header */
+set_input_fragment(rstrm)
+ register RECSTREAM *rstrm;
+{
+ u_long header;
+
+ if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+ return (FALSE);
+ header = (long)ntohl(header);
+ rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+ rstrm->fbtbc = header & (~LAST_FRAG);
+ return (TRUE);
+}
+
+static bool_t /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(rstrm, cnt)
+ register RECSTREAM *rstrm;
+ long cnt;
+{
+ register int current;
+
+ while (cnt > 0) {
+ current = (int)rstrm->in_boundry - (int)rstrm->in_finger;
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (cnt < current) ? cnt : current;
+ rstrm->in_finger += current;
+ cnt -= current;
+ }
+ return (TRUE);
+}
+
+static u_int
+fix_buf_size(s)
+ register u_int s;
+{
+
+ if (s < 100)
+ s = 4000;
+ return (RNDUP(s));
+}
diff --git a/lib/libc/rpc/xdr_reference.c b/lib/libc/rpc/xdr_reference.c
new file mode 100644
index 000000000000..c955f8820256
--- /dev/null
+++ b/lib/libc/rpc/xdr_reference.c
@@ -0,0 +1,134 @@
+/*
+ * 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: @(#)xdr_reference.c 1.11 87/08/11 SMI";*/
+/*static char *sccsid = "from: @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_reference.c,v 1.1 1993/10/27 05:41:13 paul Exp $";
+#endif
+
+/*
+ * xdr_reference.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * "pointers". See xdr.h for more info on the interface to xdr.
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((u_int)0-1)
+
+/*
+ * XDR an indirect pointer
+ * xdr_reference is for recursively translating a structure that is
+ * referenced by a pointer inside the structure that is currently being
+ * translated. pp references a pointer to storage. If *pp is null
+ * the necessary storage is allocated.
+ * size is the sizeof the referneced structure.
+ * proc is the routine to handle the referenced structure.
+ */
+bool_t
+xdr_reference(xdrs, pp, size, proc)
+ register XDR *xdrs;
+ caddr_t *pp; /* the pointer to work on */
+ u_int size; /* size of the object pointed to */
+ xdrproc_t proc; /* xdr routine to handle the object */
+{
+ register caddr_t loc = *pp;
+ register bool_t stat;
+
+ if (loc == NULL)
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ return (TRUE);
+
+ case XDR_DECODE:
+ *pp = loc = (caddr_t) mem_alloc(size);
+ if (loc == NULL) {
+ (void) fprintf(stderr,
+ "xdr_reference: out of memory\n");
+ return (FALSE);
+ }
+ bzero(loc, (int)size);
+ break;
+ }
+
+ stat = (*proc)(xdrs, loc, LASTUNSIGNED);
+
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(loc, size);
+ *pp = NULL;
+ }
+ return (stat);
+}
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ * What's sent is actually a union:
+ *
+ * union object_pointer switch (boolean b) {
+ * case TRUE: object_data data;
+ * case FALSE: void nothing;
+ * }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
+ register XDR *xdrs;
+ char **objpp;
+ u_int obj_size;
+ xdrproc_t xdr_obj;
+{
+
+ bool_t more_data;
+
+ more_data = (*objpp != NULL);
+ if (! xdr_bool(xdrs,&more_data)) {
+ return (FALSE);
+ }
+ if (! more_data) {
+ *objpp = NULL;
+ return (TRUE);
+ }
+ return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
diff --git a/lib/libc/rpc/xdr_stdio.c b/lib/libc/rpc/xdr_stdio.c
new file mode 100644
index 000000000000..9761b13d5f2a
--- /dev/null
+++ b/lib/libc/rpc/xdr_stdio.c
@@ -0,0 +1,191 @@
+/*
+ * 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: @(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";*/
+/*static char *sccsid = "from: @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";*/
+static char *rcsid = "$Id: xdr_stdio.c,v 1.1 1993/10/27 05:41:14 paul Exp $";
+#endif
+
+/*
+ * xdr_stdio.c, XDR implementation on standard i/o file.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements a XDR on a stdio stream.
+ * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
+ * from the stream.
+ */
+
+#include <rpc/types.h>
+#include <stdio.h>
+#include <rpc/xdr.h>
+
+static bool_t xdrstdio_getlong();
+static bool_t xdrstdio_putlong();
+static bool_t xdrstdio_getbytes();
+static bool_t xdrstdio_putbytes();
+static u_int xdrstdio_getpos();
+static bool_t xdrstdio_setpos();
+static long * xdrstdio_inline();
+static void xdrstdio_destroy();
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static struct xdr_ops xdrstdio_ops = {
+ xdrstdio_getlong, /* deseraialize a long int */
+ xdrstdio_putlong, /* seraialize a long int */
+ xdrstdio_getbytes, /* deserialize counted bytes */
+ xdrstdio_putbytes, /* serialize counted bytes */
+ xdrstdio_getpos, /* get offset in the stream */
+ xdrstdio_setpos, /* set offset in the stream */
+ xdrstdio_inline, /* prime stream for inline macros */
+ xdrstdio_destroy /* destroy stream */
+};
+
+/*
+ * Initialize a stdio xdr stream.
+ * Sets the xdr stream handle xdrs for use on the stream file.
+ * Operation flag is set to op.
+ */
+void
+xdrstdio_create(xdrs, file, op)
+ register XDR *xdrs;
+ FILE *file;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrstdio_ops;
+ xdrs->x_private = (caddr_t)file;
+ xdrs->x_handy = 0;
+ xdrs->x_base = 0;
+}
+
+/*
+ * Destroy a stdio xdr stream.
+ * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
+ */
+static void
+xdrstdio_destroy(xdrs)
+ register XDR *xdrs;
+{
+ (void)fflush((FILE *)xdrs->x_private);
+ /* xx should we close the file ?? */
+};
+
+static bool_t
+xdrstdio_getlong(xdrs, lp)
+ XDR *xdrs;
+ register long *lp;
+{
+
+ if (fread((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+#ifndef mc68000
+ *lp = ntohl(*lp);
+#endif
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+
+#ifndef mc68000
+ long mycopy = htonl(*lp);
+ lp = &mycopy;
+#endif
+ if (fwrite((caddr_t)lp, sizeof(long), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fread(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static u_int
+xdrstdio_getpos(xdrs)
+ XDR *xdrs;
+{
+
+ return ((u_int) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+
+ return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
+ FALSE : TRUE);
+}
+
+static long *
+xdrstdio_inline(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+
+ /*
+ * Must do some work to implement this: must insure
+ * enough data in the underlying stdio buffer,
+ * that the buffer is aligned so that we can indirect through a
+ * long *, and stuff this pointer in xdrs->x_buf. Doing
+ * a fread or fwrite to a scratch buffer would defeat
+ * most of the gains to be had here and require storage
+ * management on this buffer, so we don't do this.
+ */
+ return (NULL);
+}