aboutsummaryrefslogtreecommitdiff
path: root/src/lib/rpc
diff options
context:
space:
mode:
authorMarc Horowitz <marc@mit.edu>1996-07-22 20:49:46 +0000
committerMarc Horowitz <marc@mit.edu>1996-07-22 20:49:46 +0000
commitedf8b4d8a6a665c2aa150993cd813ea6c5cf12e1 (patch)
tree6c2974a97b448c040fa4a31708ec5e02f187526c /src/lib/rpc
parent013bb1391582ed9e653ae706e398ddb8d08cfcc9 (diff)
downloadkrb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.zip
krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.gz
krb5-edf8b4d8a6a665c2aa150993cd813ea6c5cf12e1.tar.bz2
this commit includes all the changes on the OV_9510_INTEGRATION and
OV_MERGE branches. This includes, but is not limited to, the new openvision admin system, and major changes to gssapi to add functionality, and bring the implementation in line with rfc1964. before committing, the code was built and tested for netbsd and solaris. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@8774 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/rpc')
-rw-r--r--src/lib/rpc/ChangeLog20
-rw-r--r--src/lib/rpc/Makefile.in148
-rw-r--r--src/lib/rpc/Makefile.ov52
-rw-r--r--src/lib/rpc/auth.h197
-rw-r--r--src/lib/rpc/auth_any.c19
-rw-r--r--src/lib/rpc/auth_gssapi.c901
-rw-r--r--src/lib/rpc/auth_gssapi.h161
-rw-r--r--src/lib/rpc/auth_gssapi_misc.c390
-rw-r--r--src/lib/rpc/auth_none.c136
-rw-r--r--src/lib/rpc/auth_unix.c322
-rw-r--r--src/lib/rpc/auth_unix.h72
-rw-r--r--src/lib/rpc/authunix_prot.c66
-rw-r--r--src/lib/rpc/bindresvport.c79
-rw-r--r--src/lib/rpc/clnt.h335
-rw-r--r--src/lib/rpc/clnt_generic.c110
-rw-r--r--src/lib/rpc/clnt_perror.c306
-rw-r--r--src/lib/rpc/clnt_raw.c239
-rw-r--r--src/lib/rpc/clnt_simple.c112
-rw-r--r--src/lib/rpc/clnt_tcp.c476
-rw-r--r--src/lib/rpc/clnt_udp.c460
-rw-r--r--src/lib/rpc/configure.in41
-rw-r--r--src/lib/rpc/get_myaddress.c95
-rw-r--r--src/lib/rpc/getrpcent.c256
-rw-r--r--src/lib/rpc/getrpcport.c55
-rw-r--r--src/lib/rpc/netdb.h50
-rw-r--r--src/lib/rpc/pmap_clnt.c115
-rw-r--r--src/lib/rpc/pmap_clnt.h65
-rw-r--r--src/lib/rpc/pmap_getmaps.c88
-rw-r--r--src/lib/rpc/pmap_getport.c91
-rw-r--r--src/lib/rpc/pmap_prot.c57
-rw-r--r--src/lib/rpc/pmap_prot.h94
-rw-r--r--src/lib/rpc/pmap_prot2.c116
-rw-r--r--src/lib/rpc/pmap_rmt.c403
-rw-r--r--src/lib/rpc/pmap_rmt.h53
-rw-r--r--src/lib/rpc/rpc.h74
-rw-r--r--src/lib/rpc/rpc_callmsg.c195
-rw-r--r--src/lib/rpc/rpc_commondata.c41
-rw-r--r--src/lib/rpc/rpc_dtablesize.c60
-rw-r--r--src/lib/rpc/rpc_msg.h187
-rw-r--r--src/lib/rpc/rpc_prot.c287
-rw-r--r--src/lib/rpc/svc.c492
-rw-r--r--src/lib/rpc/svc.h298
-rw-r--r--src/lib/rpc/svc_auth.c119
-rw-r--r--src/lib/rpc/svc_auth.h61
-rw-r--r--src/lib/rpc/svc_auth_any.c22
-rw-r--r--src/lib/rpc/svc_auth_gssapi.c1181
-rw-r--r--src/lib/rpc/svc_auth_unix.c137
-rw-r--r--src/lib/rpc/svc_raw.c166
-rw-r--r--src/lib/rpc/svc_run.c72
-rw-r--r--src/lib/rpc/svc_simple.c143
-rw-r--r--src/lib/rpc/svc_tcp.c453
-rw-r--r--src/lib/rpc/svc_udp.c496
-rw-r--r--src/lib/rpc/types.hin90
-rw-r--r--src/lib/rpc/unit-test/Makefile97
-rw-r--r--src/lib/rpc/unit-test/client.c320
-rw-r--r--src/lib/rpc/unit-test/rpc_test.x30
-rw-r--r--src/lib/rpc/unit-test/server.c306
-rw-r--r--src/lib/rpc/unit-test/testsuite/Makefile24
-rw-r--r--src/lib/rpc/unit-test/testsuite/config/unix.exp79
-rw-r--r--src/lib/rpc/unit-test/testsuite/helpers.exp128
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp21
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp95
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp27
-rw-r--r--src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh56
-rw-r--r--src/lib/rpc/xdr.c674
-rw-r--r--src/lib/rpc/xdr.h276
-rw-r--r--src/lib/rpc/xdr_alloc.c173
-rw-r--r--src/lib/rpc/xdr_array.c153
-rw-r--r--src/lib/rpc/xdr_float.c293
-rw-r--r--src/lib/rpc/xdr_mem.c188
-rw-r--r--src/lib/rpc/xdr_rec.c596
-rw-r--r--src/lib/rpc/xdr_reference.c132
-rw-r--r--src/lib/rpc/xdr_stdio.c189
73 files changed, 14611 insertions, 0 deletions
diff --git a/src/lib/rpc/ChangeLog b/src/lib/rpc/ChangeLog
new file mode 100644
index 0000000..a78d05c
--- /dev/null
+++ b/src/lib/rpc/ChangeLog
@@ -0,0 +1,20 @@
+Fri Jul 12 15:33:50 1996 Marc Horowitz <marc@mit.edu>
+
+ * rpc_dtablesize.c (_rpc_dtablesize): put in a few checks to make
+ sure that the return value is never larger than FD_SETSIZE, since
+ this function's purpose is to be used as the first arg to
+ select().
+
+Tue Jul 9 17:56:54 1996 Marc Horowitz <marc@mit.edu>
+
+ * rpc.h, netdb.h, getrpcent.c: Our build can (and will) require
+ that the rpc header files shipped with kerberos be used if the
+ library shipped with kerberos is used. Thus, some simplifying
+ assumptions can be made, mostly having to do with the declaration
+ of struct rpcent and the related functions.
+ * clnt_perror.c: made usage of sys_errlist conditional on
+ NEED_SYS_ERRLIST
+ * configure.in (DECLARE_SYS_ERRLIST): added
+ * Makefile.in (DONE): added a few rules and variable so shared
+ library creation would work
+
diff --git a/src/lib/rpc/Makefile.in b/src/lib/rpc/Makefile.in
new file mode 100644
index 0000000..9426bb9
--- /dev/null
+++ b/src/lib/rpc/Makefile.in
@@ -0,0 +1,148 @@
+CFLAGS = $(CCOPTS) $(DEFS) -DDEBUG_GSSAPI -I$(srcdir)/..
+
+##DOSBUILDTOP = ..\..
+##DOSLIBNAME=libgssrpc.lib
+
+.c.o:
+ $(CC) $(CFLAGS) -c $(srcdir)/$*.c
+@SHARED_RULE@
+
+SRCS = $(srcdir)/auth_none.c \
+ $(srcdir)/auth_unix.c \
+ $(srcdir)/auth_any.c \
+ $(srcdir)/authunix_prot.c \
+ $(srcdir)/auth_gssapi.c \
+ $(srcdir)/auth_gssapi_misc.c \
+ $(srcdir)/bindresvport.c \
+ $(srcdir)/clnt_generic.c \
+ $(srcdir)/clnt_perror.c \
+ $(srcdir)/clnt_raw.c \
+ $(srcdir)/clnt_simple.c \
+ $(srcdir)/clnt_tcp.c \
+ $(srcdir)/clnt_udp.c \
+ $(srcdir)/rpc_dtablesize.c \
+ $(srcdir)/get_myaddress.c \
+ $(srcdir)/getrpcent.c \
+ $(srcdir)/getrpcport.c \
+ $(srcdir)/pmap_clnt.c \
+ $(srcdir)/pmap_getmaps.c \
+ $(srcdir)/pmap_getport.c \
+ $(srcdir)/pmap_prot.c \
+ $(srcdir)/pmap_prot2.c \
+ $(srcdir)/pmap_rmt.c \
+ $(srcdir)/rpc_prot.c \
+ $(srcdir)/rpc_commondata.c \
+ $(srcdir)/rpc_callmsg.c \
+ $(srcdir)/svc.c \
+ $(srcdir)/svc_auth.c \
+ $(srcdir)/svc_auth_unix.c \
+ $(srcdir)/svc_auth_any.c \
+ $(srcdir)/svc_auth_gssapi.c \
+ $(srcdir)/svc_raw.c \
+ $(srcdir)/svc_run.c \
+ $(srcdir)/svc_simple.c \
+ $(srcdir)/svc_tcp.c \
+ $(srcdir)/svc_udp.c \
+ $(srcdir)/xdr.c \
+ $(srcdir)/xdr_array.c \
+ $(srcdir)/xdr_float.c \
+ $(srcdir)/xdr_mem.c \
+ $(srcdir)/xdr_rec.c \
+ $(srcdir)/xdr_reference.c \
+ $(srcdir)/xdr_stdio.c \
+ $(srcdir)/xdr_alloc.c
+
+OBJS = auth_none.$(OBJEXT) \
+ auth_unix.$(OBJEXT) \
+ auth_any.$(OBJEXT) \
+ authunix_prot.$(OBJEXT) \
+ auth_gssapi.$(OBJEXT) \
+ auth_gssapi_misc.$(OBJEXT) \
+ bindresvport.$(OBJEXT) \
+ clnt_generic.$(OBJEXT) \
+ clnt_perror.$(OBJEXT) \
+ clnt_raw.$(OBJEXT) \
+ clnt_simple.$(OBJEXT) \
+ clnt_tcp.$(OBJEXT) \
+ clnt_udp.$(OBJEXT) \
+ rpc_dtablesize.$(OBJEXT) \
+ get_myaddress.$(OBJEXT) \
+ getrpcent.$(OBJEXT) \
+ getrpcport.$(OBJEXT) \
+ pmap_clnt.$(OBJEXT) \
+ pmap_getmaps.$(OBJEXT) \
+ pmap_getport.$(OBJEXT) \
+ pmap_prot.$(OBJEXT) \
+ pmap_prot2.$(OBJEXT) \
+ pmap_rmt.$(OBJEXT) \
+ rpc_prot.$(OBJEXT) \
+ rpc_commondata.$(OBJEXT) \
+ rpc_callmsg.$(OBJEXT) \
+ svc.$(OBJEXT) \
+ svc_auth.$(OBJEXT) \
+ svc_auth_unix.$(OBJEXT) \
+ svc_auth_any.$(OBJEXT) \
+ svc_auth_gssapi.$(OBJEXT) \
+ svc_raw.$(OBJEXT) \
+ svc_run.$(OBJEXT) \
+ svc_simple.$(OBJEXT) \
+ svc_tcp.$(OBJEXT) \
+ svc_udp.$(OBJEXT) \
+ xdr.$(OBJEXT) \
+ xdr_array.$(OBJEXT) \
+ xdr_float.$(OBJEXT) \
+ xdr_mem.$(OBJEXT) \
+ xdr_rec.$(OBJEXT) \
+ xdr_reference.$(OBJEXT) \
+ xdr_stdio.$(OBJEXT) \
+ xdr_alloc.$(OBJEXT)
+
+LIB_SUBDIRS= .
+LIBDONE= DONE
+#
+# Depends on libgssapi_krb5, libkrb5, libcrypto, libcom_err
+#
+GSSAPI_KRB5_VER=@GSSAPI_KRB5_SH_VERS@
+KRB5_VER=@KRB5_SH_VERS@
+CRYPTO_VER=@CRYPTO_SH_VERS@
+COMERR_VER=@COMERR_SH_VERS@
+DEPLIBS=$(TOPLIBD)/libgssapi_krb5.$(SHEXT).$(COMERR_VER) \
+ $(TOPLIBD)/libkrb5.$(SHEXT).$(KRB5_VER) \
+ $(TOPLIBD)/libcrypto.$(SHEXT).$(CRYPTO_VER) \
+ $(TOPLIBD)/libcom_err.$(SHEXT).$(COMERR_VER)
+
+SHLIB_LIBS=-lkrb5 -lcrypto -lcom_err -ldyn
+SHLIB_LDFLAGS= $(LDFLAGS) @SHLIB_RPATH_DIRS@
+SHLIB_LIBDIRS= @SHLIB_LIBDIRS@
+
+all-unix:: shared includes $(OBJS)
+all-mac:: $(OBJS)
+all-windows:: $(OBJS)
+
+shared:
+ mkdir shared
+
+check-windows::
+
+clean-unix::
+ $(RM) shared/*
+
+clean-mac::
+clean-windows::
+
+DONE: $(OBJS)
+ $(RM) DONE
+ echo $(OBJS) > DONE
+
+libgssrpc.$(STEXT): $(OBJS)
+ $(RM) $@
+ $(ARADD) $@ $(OBJS)
+ $(RANLIB) $@
+
+install:: libgssrpc.a
+ $(INSTALL_DATA) libgssrpc.a $(DESTDIR)$(KRB5_LIBDIR)/libgssrpc.a
+ $(RANLIB) $(DESTDIR)$(KRB5_LIBDIR)/libgssrpc.a
+
+clean::
+ $(RM) libgssrpc.$(LIBEXT) libgssrpc.bak DONE
+
diff --git a/src/lib/rpc/Makefile.ov b/src/lib/rpc/Makefile.ov
new file mode 100644
index 0000000..d64c77e
--- /dev/null
+++ b/src/lib/rpc/Makefile.ov
@@ -0,0 +1,52 @@
+#
+# Makefile for librpclib.a.
+#
+# $Id$
+# $Source$
+#
+TOP = ..
+include $(TOP)/config.mk/template
+
+SUBDIRS = unit-test
+
+SRCS = auth_none.c auth_unix.c auth_any.c authunix_prot.c \
+ auth_gssapi.c auth_gssapi_misc.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_auth_any.c svc_auth_gssapi.c \
+ svc_raw.c svc_run.c svc_simple.c \
+ svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+ xdr_rec.c xdr_reference.c xdr_stdio.c xdr_alloc.c
+
+OBJS = auth_none.o auth_unix.o auth_any.o authunix_prot.o \
+ auth_gssapi.o auth_gssapi_misc.o bindresvport.o \
+ clnt_generic.o clnt_perror.o clnt_raw.o clnt_simple.o clnt_tcp.o \
+ clnt_udp.o rpc_dtablesize.o get_myaddress.o getrpcent.o getrpcport.o \
+ pmap_clnt.o pmap_getmaps.o pmap_getport.o pmap_prot.o \
+ pmap_prot2.o pmap_rmt.o rpc_prot.o rpc_commondata.o rpc_callmsg.o \
+ svc.o svc_auth.o svc_auth_unix.o svc_auth_any.o svc_auth_gssapi.o \
+ svc_raw.o svc_run.o svc_simple.o \
+ svc_tcp.o svc_udp.o xdr.o xdr_array.o xdr_float.o xdr_mem.o \
+ xdr_rec.o xdr_reference.o xdr_stdio.o xdr_alloc.o
+
+HDRS = auth.h auth_unix.h auth_gssapi.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
+
+HDRS_DIR = rpc
+
+LIB = librpclib.a
+
+CFLAGS := -I.. $(CFLAGS) -DDEBUG_GSSAPI=0 $(D_NEEDS_RPCENT)
+
+expand StageLibrary
+
+expand StageIncludes
+
+expand Depend
+
+expand SubdirTarget
+
+expand Saber
+
diff --git a/src/lib/rpc/auth.h b/src/lib/rpc/auth.h
new file mode 100644
index 0000000..4b0a40c
--- /dev/null
+++ b/src/lib/rpc/auth.h
@@ -0,0 +1,197 @@
+/* @(#)auth.h 2.3 88/08/07 4.0 RPCSRC; from 1.17 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * 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".
+ */
+
+
+#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 */
+};
+
+union des_block {
+#if 0 /* XXX nothing uses this, anyway */
+ struct {
+ rpc_u_int32 high;
+ rpc_u_int32 low;
+ } key;
+#endif
+ char c[8];
+};
+typedef union des_block des_block;
+extern bool_t xdr_des_block();
+
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ unsigned 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 */
+ int (*ah_wrap)(); /* encode data for wire */
+ int (*ah_unwrap)(); /* decode data from wire */
+ } *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, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+#define auth_refresh(auth, msg) \
+ ((*((auth)->ah_ops->ah_refresh))(auth, msg))
+
+#define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+ xfunc, xwhere))
+#define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \
+ xfunc, xwhere))
+
+#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.
+ */
+
+/*
+ * Any style authentication. These routines can be used by any
+ * authentication style that does not use the wrap/unwrap functions.
+ */
+int authany_wrap(), authany_unwrap();
+
+/*
+ * Unix style authentication
+ * AUTH *authunix_create(machname, uid, gid, len, aup_gids)
+ * char *machname;
+ * int uid;
+ * int gid;
+ * int len;
+ * int *aup_gids;
+ */
+extern AUTH *authunix_create();
+extern AUTH *authunix_create_default(); /* takes no parameters */
+extern AUTH *authnone_create(); /* takes no parameters */
+extern AUTH *authdes_create();
+
+/*
+ * GSS-API style authentication:
+ * see <rpc/auth_gssapi.h>
+ */
+
+#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) */
+#define AUTH_GSSAPI 300001 /* GSS-API style */
+
+/*
+ * BACKWARDS COMPATIBILIY! OpenV*Secure 1.0 had AUTH_GSSAPI == 4. We
+ * need to accept this value until 1.0 is dead.
+ */
+#define AUTH_GSSAPI_COMPAT 4
diff --git a/src/lib/rpc/auth_any.c b/src/lib/rpc/auth_any.c
new file mode 100644
index 0000000..5e2a863
--- /dev/null
+++ b/src/lib/rpc/auth_any.c
@@ -0,0 +1,19 @@
+/*
+ * auth_any.c
+ * Provides default functions for authentication flavors that do not
+ * use all the fields in structauth_ops.
+ */
+
+#include <stdio.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+
+int authany_wrap(auth, xdrs, xfunc, xwhere)
+ AUTH *auth;
+ XDR *xdrs;
+ xdrproc_t xfunc;
+ caddr_t xwhere;
+{
+ return (*xfunc)(xdrs, xwhere);
+}
diff --git a/src/lib/rpc/auth_gssapi.c b/src/lib/rpc/auth_gssapi.c
new file mode 100644
index 0000000..0ffe96d
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi.c
@@ -0,0 +1,901 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.23 1996/07/22 20:39:39 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.22.4.1 1996/07/18 04:18:29 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.22.2.1 1996/06/20 23:35:31 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.22 1996/06/05 20:56:16 bjaspan
+ * memset bindings to zero before use
+ *
+ * Revision 1.21 1996/05/12 06:11:38 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.20 1995/12/13 14:02:45 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.19 1995/10/31 16:36:00 bjaspan
+ * GS reported this bug. When talking to a 1.1 server, the server will
+ * not fail indicating the version is wrong because it never checks the
+ * version; it just responds with call_res.version 1. So we have to
+ * deal. Oops.
+ *
+ * It's amazing what can fall through the cracks when most of the
+ * development team is fired..
+ *
+ * Revision 1.18 1995/10/31 16:07:06 bjaspan
+ * fix from grier
+ *
+ * Revision 1.17 1995/08/24 21:06:26 bjaspan
+ * set acceptor channel bindings
+ *
+ * Revision 1.16 1995/08/23 20:27:37 bjaspan
+ * [secure-rpc/3392] add channel bindinds to the rpc
+ *
+ * Revision 1.15 1995/05/08 22:32:01 marc
+ * change call_arg.version from 1 to 2 to indicate the new client is in use.
+ *
+ * Revision 1.14 1995/03/22 22:05:20 jik
+ * Reorder the auth_ops structure, to agree with the order of the version of
+ * this library in the GK source tree. I chose to reorder this one rather
+ * than reorder the GK tree because Barry says that the order in the GK tree
+ * makes more sense.
+ *
+ * Revision 1.13 1994/10/27 12:39:02 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * change to use GSS_ERROR &c macros; I don't think this is correct
+ * =============================================================================
+ *
+ * Revision 1.14 1994/10/26 20:03:46 bjaspan
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.13 1994/04/07 16:12:06 jik
+ * The second argument to xdr_opaque_auth is struct auth *, not struct
+ * auth.
+ *
+ * Revision 1.12 1993/12/08 21:42:43 bjaspan
+ * use AUTH_GSSAPI_DISPLAY_STATUS macro, reindent
+ *
+ * Revision 1.11 1993/12/06 21:21:03 bjaspan
+ * debugging levels
+ *
+ * Revision 1.10 1993/11/18 23:13:07 bjaspan
+ * add some function comments
+ *
+ * Revision 1.9 1993/11/15 19:50:03 bjaspan
+ * redefine AUTH_REFRESH to take the error message as an argument, and
+ * change auth_gssapi_refresh to increment the seq_num on REJECTEDVERF
+ *
+ * Revision 1.8 1993/11/12 02:31:59 bjaspan
+ * set rpc_createerr as appropriate
+ *
+ * Revision 1.7 1993/11/03 21:21:02 bjaspan
+ * fix seq_num handling in cases of errors and retransmission
+ *
+ * Revision 1.6 1993/11/01 19:55:20 bjaspan
+ * display gss_major and gss_minor, and unstatic auth_gssapi_debug
+ *
+ * Revision 1.5 1993/10/28 22:07:33 bjaspan
+ * create_default takes char *, use seq_num in args/results
+ *
+ * Revision 1.4 1993/10/26 21:11:53 bjaspan
+ * working
+ *
+ * Revision 1.3 1993/10/21 19:01:09 bjaspan
+ * added auth_gssapi_destroy, cleaned up a few things
+ *
+ * Revision 1.2 1993/10/19 03:10:58 bjaspan
+ * snapshot: GSS-API working in hacked up state, not seal/unseal
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/errno.h>
+
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+
+#include <rpc/rpc.h>
+#include <rpc/auth_gssapi.h>
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int auth_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (auth_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (auth_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+static void auth_gssapi_nextverf();
+static bool_t auth_gssapi_marshall();
+static bool_t auth_gssapi_validate();
+static bool_t auth_gssapi_refresh();
+static bool_t auth_gssapi_wrap();
+static bool_t auth_gssapi_unwrap();
+static void auth_gssapi_destroy();
+
+static bool_t marshall_new_creds();
+
+static struct auth_ops auth_gssapi_ops = {
+ auth_gssapi_nextverf,
+ auth_gssapi_marshall,
+ auth_gssapi_validate,
+ auth_gssapi_refresh,
+ auth_gssapi_destroy,
+ auth_gssapi_wrap,
+ auth_gssapi_unwrap,
+};
+
+/*
+ * the ah_private data structure for an auth_handle
+ */
+struct auth_gssapi_data {
+ bool_t established;
+ CLIENT *clnt;
+ gss_ctx_id_t context;
+ gss_buffer_desc client_handle;
+ rpc_u_int32 seq_num;
+ int def_cred;
+
+ /* pre-serialized ah_cred */
+ unsigned char cred_buf[MAX_AUTH_BYTES];
+ rpc_u_int32 cred_len;
+};
+#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
+
+extern struct rpc_createerr rpc_createerr;
+
+/*
+ * Function: auth_gssapi_create_default
+ *
+ * Purpose: Create a GSS-API style authenticator, with default
+ * options, and return the handle.
+ *
+ * Effects: See design document, section XXX.
+ */
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name)
+{
+ AUTH *auth;
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc input_name;
+ gss_name_t target_name;
+
+ input_name.value = service_name;
+ input_name.length = strlen(service_name) + 1;
+
+ gssstat = gss_import_name(&minor_stat, &input_name,
+ gss_nt_service_name, &target_name);
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("parsing name", gssstat,
+ minor_stat));
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = ENOMEM;
+ return NULL;
+ }
+
+ auth = auth_gssapi_create(clnt,
+ &gssstat,
+ &minor_stat,
+ GSS_C_NO_CREDENTIAL,
+ target_name,
+ GSS_C_NULL_OID,
+ GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG,
+ 0,
+ NULL,
+ NULL,
+ NULL);
+
+ gss_release_name(&minor_stat, &target_name);
+ return auth;
+}
+
+/*
+ * Function: auth_gssapi_create
+ *
+ * Purpose: Create a GSS-API style authenticator, with all the
+ * options, and return the handle.
+ *
+ * Effects: See design document, section XXX.
+ */
+AUTH *auth_gssapi_create(CLIENT *clnt,
+ OM_uint32 *gssstat,
+ OM_uint32 *minor_stat,
+ gss_cred_id_t claimant_cred_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ int req_flags,
+ OM_uint32 time_req,
+ gss_OID *actual_mech_type,
+ int *ret_flags,
+ OM_uint32 *time_rec)
+{
+ AUTH *auth, *save_auth;
+ struct auth_gssapi_data *pdata;
+ struct gss_channel_bindings_struct bindings, *bindp;
+ struct sockaddr_in laddr, raddr;
+ enum clnt_stat callstat;
+ struct timeval timeout;
+ int init_func;
+
+ auth_gssapi_init_arg call_arg;
+ auth_gssapi_init_res call_res;
+ gss_buffer_desc *input_token, isn_buf;
+
+ memset(&rpc_createerr, 0, sizeof(rpc_createerr));
+
+ /* this timeout is only used if clnt_control(clnt, CLSET_TIMEOUT) */
+ /* has not already been called.. therefore, we can just pick */
+ /* something reasonable-sounding.. */
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ auth = NULL;
+ pdata = NULL;
+
+ auth = (AUTH *) malloc(sizeof(*auth));
+ pdata = (struct auth_gssapi_data *) malloc(sizeof(*pdata));
+ if (auth == NULL || pdata == NULL) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = ENOMEM;
+ goto cleanup;
+ }
+ memset((char *) auth, 0, sizeof(*auth));
+ memset((char *) pdata, 0, sizeof(*pdata));
+
+ auth->ah_ops = &auth_gssapi_ops;
+ auth->ah_private = (caddr_t) pdata;
+
+ /* initial creds are auth_msg TRUE and no handle */
+ marshall_new_creds(auth, TRUE, NULL);
+
+ /* initial verifier is empty */
+ auth->ah_verf.oa_flavor = AUTH_GSSAPI;
+ auth->ah_verf.oa_base = NULL;
+ auth->ah_verf.oa_length = 0;
+
+ AUTH_PRIVATE(auth)->established = FALSE;
+ AUTH_PRIVATE(auth)->clnt = clnt;
+ AUTH_PRIVATE(auth)->def_cred = (claimant_cred_handle ==
+ GSS_C_NO_CREDENTIAL);
+
+ /* don't assume the caller will want to change clnt->cl_auth */
+ save_auth = clnt->cl_auth;
+ clnt->cl_auth = auth;
+
+ /* start by trying latest version */
+ call_arg.version = 3;
+
+try_new_version:
+ /* set state for initial call to init_sec_context */
+ input_token = GSS_C_NO_BUFFER;
+ AUTH_PRIVATE(auth)->context = GSS_C_NO_CONTEXT;
+ init_func = AUTH_GSSAPI_INIT;
+
+ if (call_arg.version == 3) {
+ if (clnt_control(clnt, CLGET_LOCAL_ADDR, &laddr) == FALSE) {
+ PRINTF(("gssapi_create: CLGET_LOCAL_ADDR failed"));
+ goto cleanup;
+ }
+ if (clnt_control(clnt, CLGET_SERVER_ADDR, &raddr) == FALSE) {
+ PRINTF(("gssapi_create: CLGET_SERVER_ADDR failed"));
+ goto cleanup;
+ }
+
+ memset(&bindings, 0, sizeof(bindings));
+ bindings.application_data.length = 0;
+ bindings.initiator_addrtype = GSS_C_AF_INET;
+ bindings.initiator_address.length = 4;
+ bindings.initiator_address.value = &laddr.sin_addr.s_addr;
+
+ bindings.acceptor_addrtype = GSS_C_AF_INET;
+ bindings.acceptor_address.length = 4;
+ bindings.acceptor_address.value = &raddr.sin_addr.s_addr;
+ bindp = &bindings;
+ } else {
+ bindp = NULL;
+ }
+
+ memset((char *) &call_res, 0, sizeof(call_res));
+
+next_token:
+ *gssstat = gss_init_sec_context(minor_stat,
+ claimant_cred_handle,
+ &AUTH_PRIVATE(auth)->context,
+ target_name,
+ mech_type,
+ req_flags,
+ time_req,
+ bindp,
+ input_token,
+ actual_mech_type,
+ &call_arg.token,
+ ret_flags,
+ time_rec);
+
+ if (*gssstat != GSS_S_COMPLETE && *gssstat != GSS_S_CONTINUE_NEEDED) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("initializing context", *gssstat,
+ *minor_stat));
+ goto cleanup;
+ }
+
+ /* if we got a token, pass it on */
+ if (call_arg.token.length != 0) {
+
+ /*
+ * sanity check: if we received a signed isn in the last
+ * response then there *cannot* be another token to send
+ */
+ if (call_res.signed_isn.length != 0) {
+ PRINTF(("gssapi_create: unexpected token from init_sec\n"));
+ goto cleanup;
+ }
+
+ PRINTF(("gssapi_create: calling GSSAPI_INIT (%d)\n", init_func));
+
+ memset((char *) &call_res, 0, sizeof(call_res));
+ callstat = clnt_call(clnt, init_func,
+ xdr_authgssapi_init_arg, &call_arg,
+ xdr_authgssapi_init_res, &call_res,
+ timeout);
+ gss_release_buffer(minor_stat, &call_arg.token);
+
+ if (callstat != RPC_SUCCESS) {
+ struct rpc_err err;
+
+ clnt_geterr(clnt, &err);
+ if (callstat == RPC_AUTHERROR &&
+ (err.re_why == AUTH_BADCRED || err.re_why == AUTH_FAILED)
+ && call_arg.version >= 1) {
+ L_PRINTF(1, ("call_arg protocol "
+ "version %d rejected, trying %d.\n",
+ call_arg.version, call_arg.version-1));
+ call_arg.version--;
+ goto try_new_version;
+ } else {
+ PRINTF(("gssapi_create: GSSAPI_INIT (%d) failed, stat %d\n",
+ init_func, callstat));
+ }
+
+ goto cleanup;
+ } else if (call_res.version != call_arg.version &&
+ !(call_arg.version == 2 && call_res.version == 1)) {
+ /*
+ * The Secure 1.1 servers always respond with version
+ * 1. Thus, if we just tried a version >=3, fall all
+ * the way back to version 1 since that is all they
+ * understand
+ */
+ if (call_arg.version > 2 && call_res.version == 1) {
+ L_PRINTF(1, ("Talking to Secure 1.1 server, "
+ "using version 1.\n"));
+ call_arg.version = 1;
+ goto try_new_version;
+ }
+
+ PRINTF(("gssapi_create: invalid call_res vers %d\n",
+ call_res.version));
+ goto cleanup;
+ } else if (call_res.gss_major != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("in response from server",
+ call_res.gss_major,
+ call_res.gss_minor));
+ goto cleanup;
+ }
+
+ PRINTF(("gssapi_create: GSSAPI_INIT (%d) succeeded\n", init_func));
+ init_func = AUTH_GSSAPI_CONTINUE_INIT;
+
+ /* check for client_handle */
+ if (AUTH_PRIVATE(auth)->client_handle.length == 0) {
+ if (call_res.client_handle.length == 0) {
+ PRINTF(("gssapi_create: expected client_handle\n"));
+ goto cleanup;
+ } else {
+ PRINTF(("gssapi_create: got client_handle %d\n",
+ *((rpc_u_int32 *)call_res.client_handle.value)));
+
+ GSS_DUP_BUFFER(AUTH_PRIVATE(auth)->client_handle,
+ call_res.client_handle);
+
+ /* auth_msg is TRUE; there may be more tokens */
+ marshall_new_creds(auth, TRUE,
+ &AUTH_PRIVATE(auth)->client_handle);
+ }
+ } else if (!GSS_BUFFERS_EQUAL(AUTH_PRIVATE(auth)->client_handle,
+ call_res.client_handle)) {
+ PRINTF(("gssapi_create: got different client_handle\n"));
+ goto cleanup;
+ }
+
+ /* check for token */
+ if (call_res.token.length==0 && *gssstat==GSS_S_CONTINUE_NEEDED) {
+ PRINTF(("gssapi_create: expected token\n"));
+ goto cleanup;
+ } else if (call_res.token.length != 0) {
+ if (*gssstat == GSS_S_COMPLETE) {
+ PRINTF(("gssapi_create: got unexpected token\n"));
+ goto cleanup;
+ } else {
+ /* assumes call_res is safe until init_sec_context */
+ input_token = &call_res.token;
+ PRINTF(("gssapi_create: got new token\n"));
+ }
+ }
+ }
+
+ /* check for isn */
+ if (*gssstat == GSS_S_COMPLETE) {
+ if (call_res.signed_isn.length == 0) {
+ PRINTF(("gssapi_created: expected signed isn\n"));
+ goto cleanup;
+ } else {
+ PRINTF(("gssapi_create: processing signed isn\n"));
+
+ /* don't check conf (integ only) or qop (accpet default) */
+ *gssstat = gss_unseal(minor_stat,
+ AUTH_PRIVATE(auth)->context,
+ &call_res.signed_isn,
+ &isn_buf, NULL, NULL);
+
+ if (*gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("unsealing isn",
+ *gssstat, *minor_stat));
+ goto cleanup;
+ } else if (isn_buf.length != sizeof(rpc_u_int32)) {
+ PRINTF(("gssapi_create: gss_unseal gave %d bytes\n",
+ isn_buf.length));
+ goto cleanup;
+ }
+
+ AUTH_PRIVATE(auth)->seq_num = (rpc_u_int32)
+ ntohl(*((rpc_u_int32*)isn_buf.value));
+ *gssstat = gss_release_buffer(minor_stat, &isn_buf);
+ if (*gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("releasing unsealed isn",
+ *gssstat, *minor_stat));
+ goto cleanup;
+ }
+
+ PRINTF(("gssapi_create: isn is %d\n",
+ AUTH_PRIVATE(auth)->seq_num));
+
+ /* we no longer need these results.. */
+ xdr_free(xdr_authgssapi_init_res, &call_res);
+ }
+ } else if (call_res.signed_isn.length != 0) {
+ PRINTF(("gssapi_create: got signed isn, can't check yet\n"));
+ }
+
+ /* results were okay.. continue if necessary */
+ if (*gssstat == GSS_S_CONTINUE_NEEDED) {
+ PRINTF(("gssapi_create: not done, continuing\n"));
+ goto next_token;
+ }
+
+ /*
+ * Done! Context is established, we have client_handle and isn.
+ */
+ AUTH_PRIVATE(auth)->established = TRUE;
+
+ marshall_new_creds(auth, FALSE,
+ &AUTH_PRIVATE(auth)->client_handle);
+
+ PRINTF(("gssapi_create: done. client_handle %#x, isn %d\n\n",
+ *((rpc_u_int32 *)AUTH_PRIVATE(auth)->client_handle.value),
+ AUTH_PRIVATE(auth)->seq_num));
+
+ /* don't assume the caller will want to change clnt->cl_auth */
+ clnt->cl_auth = save_auth;
+
+ return auth;
+
+ /******************************************************************/
+
+cleanup:
+ PRINTF(("gssapi_create: bailing\n\n"));
+
+ if (AUTH_PRIVATE(auth))
+ auth_gssapi_destroy(auth);
+ else if (auth)
+ free(auth);
+ auth = NULL;
+
+ /* don't assume the caller will want to change clnt->cl_auth */
+ clnt->cl_auth = save_auth;
+
+ if (rpc_createerr.cf_stat == 0)
+ rpc_createerr.cf_stat = RPC_AUTHERROR;
+
+ return auth;
+}
+
+/*
+ * Function: marshall_new_creds
+ *
+ * Purpose: (pre-)serialize auth_msg and client_handle fields of
+ * auth_gssapi_creds into auth->cred_buf
+ *
+ * Arguments:
+ *
+ * auth (r/w) the AUTH structure to modify
+ * auth_msg (r) the auth_msg field to serialize
+ * client_handle (r) the client_handle field to serialize, or
+ * NULL
+ *
+ * Returns: TRUE if successful, FALSE if not
+ *
+ * Requires: auth must point to a valid GSS-API auth structure, auth_msg
+ * must be TRUE or FALSE, client_handle must be a gss_buffer_t with a valid
+ * value and length field or NULL.
+ *
+ * Effects: auth->ah_cred is set to the serialized auth_gssapi_creds
+ * version 2 structure (stored in the cred_buf field of private data)
+ * containing version, auth_msg and client_handle.
+ * auth->ah_cred.oa_flavor is set to AUTH_GSSAPI. If cliend_handle is
+ * NULL, it is treated as if it had a length of 0 and a value of NULL.
+ *
+ * Modifies: auth
+ */
+static bool_t marshall_new_creds(auth, auth_msg, client_handle)
+ AUTH *auth;
+ bool_t auth_msg;
+ gss_buffer_t client_handle;
+{
+ auth_gssapi_creds creds;
+ XDR xdrs;
+
+ PRINTF(("marshall_new_creds: starting\n"));
+
+ creds.version = 2;
+
+ creds.auth_msg = auth_msg;
+ if (client_handle)
+ GSS_COPY_BUFFER(creds.client_handle, *client_handle)
+ else {
+ creds.client_handle.length = 0;
+ creds.client_handle.value = NULL;
+ }
+
+ xdrmem_create(&xdrs, AUTH_PRIVATE(auth)->cred_buf,
+ MAX_AUTH_BYTES, XDR_ENCODE);
+ if (! xdr_authgssapi_creds(&xdrs, &creds)) {
+ PRINTF(("marshall_new_creds: failed encoding auth_gssapi_creds\n"));
+ XDR_DESTROY(&xdrs);
+ return FALSE;
+ }
+ AUTH_PRIVATE(auth)->cred_len = xdr_getpos(&xdrs);
+ XDR_DESTROY(&xdrs);
+
+ PRINTF(("marshall_new_creds: auth_gssapi_creds is %d bytes\n",
+ AUTH_PRIVATE(auth)->cred_len));
+
+ auth->ah_cred.oa_flavor = AUTH_GSSAPI;
+ auth->ah_cred.oa_base = (char *) AUTH_PRIVATE(auth)->cred_buf;
+ auth->ah_cred.oa_length = AUTH_PRIVATE(auth)->cred_len;
+
+ PRINTF(("marshall_new_creds: succeeding\n"));
+
+ return TRUE;
+}
+
+
+/*
+ * Function: auth_gssapi_nextverf
+ *
+ * Purpose: None.
+ *
+ * Effects: None. Never called.
+ */
+static void auth_gssapi_nextverf(/*auth*/)
+ /*AUTH *auth;*/
+{
+}
+
+/*
+ * Function: auth_gssapi_marhsall
+ *
+ * Purpose: Marshall RPC credentials and verifier onto xdr stream.
+ *
+ * Arguments:
+ *
+ * auth (r/w) AUTH structure for client
+ * xdrs (r/w) XDR stream to marshall to
+ *
+ * Returns: boolean indicating success/failure
+ *
+ * Effects:
+ *
+ * The pre-serialized credentials in cred_buf are serialized. If the
+ * context is established, the sealed sequence number is serialized as
+ * the verifier. If the context is not established, an empty verifier
+ * is serialized. The sequence number is *not* incremented, because
+ * this function is called multiple times if retransmission is required.
+ *
+ * If this took all the header fields as arguments, it could sign
+ * them.
+ */
+static bool_t auth_gssapi_marshall(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ OM_uint32 minor_stat;
+ gss_buffer_desc out_buf;
+ rpc_u_int32 seq_num;
+
+ if (AUTH_PRIVATE(auth)->established == TRUE) {
+ PRINTF(("gssapi_marshall: starting\n"));
+
+ seq_num = AUTH_PRIVATE(auth)->seq_num + 1;
+
+ PRINTF(("gssapi_marshall: sending seq_num %d\n", seq_num));
+
+ if (auth_gssapi_seal_seq(AUTH_PRIVATE(auth)->context, seq_num,
+ &out_buf) == FALSE) {
+ PRINTF(("gssapi_marhshall: seal failed\n"));
+ }
+
+ auth->ah_verf.oa_base = out_buf.value;
+ auth->ah_verf.oa_length = out_buf.length;
+
+ if (! xdr_opaque_auth(xdrs, &auth->ah_cred) ||
+ ! xdr_opaque_auth(xdrs, &auth->ah_verf)) {
+ (void) gss_release_buffer(&minor_stat, &out_buf);
+ return FALSE;
+ }
+ (void) gss_release_buffer(&minor_stat, &out_buf);
+ } else {
+ PRINTF(("gssapi_marshall: not established, sending null verf\n"));
+
+ auth->ah_verf.oa_base = NULL;
+ auth->ah_verf.oa_length = 0;
+
+ if (! xdr_opaque_auth(xdrs, &auth->ah_cred) ||
+ ! xdr_opaque_auth(xdrs, &auth->ah_verf)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_validate
+ *
+ * Purpose: Validate RPC response verifier from server.
+ *
+ * Effects: See design document, section XXX.
+ */
+static bool_t auth_gssapi_validate(auth, verf)
+ AUTH *auth;
+ struct opaque_auth *verf;
+{
+ gss_buffer_desc in_buf;
+ rpc_u_int32 seq_num;
+
+ if (AUTH_PRIVATE(auth)->established == FALSE) {
+ PRINTF(("gssapi_validate: not established, noop\n"));
+ return TRUE;
+ }
+
+ PRINTF(("gssapi_validate: starting\n"));
+
+ in_buf.length = verf->oa_length;
+ in_buf.value = verf->oa_base;
+ if (auth_gssapi_unseal_seq(AUTH_PRIVATE(auth)->context, &in_buf,
+ &seq_num) == FALSE) {
+ PRINTF(("gssapi_validate: failed unsealing verifier\n"));
+ return FALSE;
+ }
+
+ /* we sent seq_num+1, so we should get back seq_num+2 */
+ if (AUTH_PRIVATE(auth)->seq_num+2 != seq_num) {
+ PRINTF(("gssapi_validate: expecting seq_num %d, got %d (%#x)\n",
+ AUTH_PRIVATE(auth)->seq_num + 2, seq_num, seq_num));
+ return FALSE;
+ }
+ PRINTF(("gssapi_validate: seq_num %d okay\n", seq_num));
+
+ /* +1 for successful transmission, +1 for successful validation */
+ AUTH_PRIVATE(auth)->seq_num += 2;
+
+ PRINTF(("gssapi_validate: succeeding\n"));
+
+ return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_refresh
+ *
+ * Purpose: Attempts to resyncrhonize the sequence number.
+ *
+ * Effects:
+ *
+ * When the server receives a properly authenticated RPC call, it
+ * increments the sequence number it is expecting from the client.
+ * But if the server's response is lost for any reason, the client
+ * can't know whether the server ever received it, assumes it didn't,
+ * and does *not* increment its sequence number. Thus, the client's
+ * next call will fail with AUTH_REJECTEDCRED because the server will
+ * think it is a replay attack.
+ *
+ * When an AUTH_REJECTEDCRED error arrives, this function attempts to
+ * resyncrhonize by incrementing the client's sequence number and
+ * returning TRUE. If any other error arrives, it returns FALSE.
+ */
+static bool_t auth_gssapi_refresh(auth, msg)
+ AUTH *auth;
+ struct rpc_msg *msg;
+{
+ if (msg->rm_reply.rp_rjct.rj_stat == AUTH_ERROR &&
+ msg->rm_reply.rp_rjct.rj_why == AUTH_REJECTEDVERF) {
+ PRINTF(("gssapi_refresh: rejected verifier, incrementing\n"));
+ AUTH_PRIVATE(auth)->seq_num++;
+ return TRUE;
+ } else {
+ PRINTF(("gssapi_refresh: failing\n"));
+ return FALSE;
+ }
+}
+
+/*
+ * Function: auth_gssapi_destroy
+ *
+ * Purpose: Destroy a GSS-API authentication structure.
+ *
+ * Effects: This function destroys the GSS-API authentication
+ * context, and sends a message to the server instructing it to
+ * invokte gss_process_token() and thereby destroy its corresponding
+ * context. Since the client doesn't really care whether the server
+ * gets this message, no failures are reported.
+ */
+static void auth_gssapi_destroy(auth)
+ AUTH *auth;
+{
+ struct timeval timeout;
+ OM_uint32 gssstat, minor_stat;
+ gss_cred_id_t cred;
+ int callstat;
+
+ if (AUTH_PRIVATE(auth)->client_handle.length == 0) {
+ PRINTF(("gssapi_destroy: no client_handle, not calling destroy\n"));
+ goto skip_call;
+ }
+
+ PRINTF(("gssapi_destroy: marshalling new creds\n"));
+ if (!marshall_new_creds(auth, TRUE, &AUTH_PRIVATE(auth)->client_handle)) {
+ PRINTF(("gssapi_destroy: marshall_new_creds failed\n"));
+ goto skip_call;
+ }
+
+ PRINTF(("gssapi_destroy: calling GSSAPI_DESTROY\n"));
+ timeout.tv_sec = 1;
+ timeout.tv_usec = 0;
+ callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_DESTROY,
+ xdr_void, NULL, xdr_void, NULL, timeout);
+ if (callstat != RPC_SUCCESS)
+ clnt_sperror(AUTH_PRIVATE(auth)->clnt,
+ "gssapi_destroy: GSSAPI_DESTROY failed");
+
+skip_call:
+ PRINTF(("gssapi_destroy: deleting context\n"));
+ gssstat = gss_delete_sec_context(&minor_stat,
+ &AUTH_PRIVATE(auth)->context,
+ NULL);
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
+ minor_stat));
+ if (AUTH_PRIVATE(auth)->def_cred) {
+ cred = GSS_C_NO_CREDENTIAL;
+ gssstat = gss_release_cred(&minor_stat, &cred);
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("deleting default credential",
+ gssstat, minor_stat));
+ }
+
+ if (AUTH_PRIVATE(auth)->client_handle.length != 0)
+ gss_release_buffer(&minor_stat,
+ &AUTH_PRIVATE(auth)->client_handle);
+
+#if 0
+ PRINTF(("gssapi_destroy: calling GSSAPI_EXIT\n"));
+ AUTH_PRIVATE(auth)->established = FALSE;
+ callstat = clnt_call(AUTH_PRIVATE(auth)->clnt, AUTH_GSSAPI_EXIT,
+ xdr_void, NULL, xdr_void, NULL, timeout);
+#endif
+
+ free(auth->ah_private);
+ free(auth);
+ PRINTF(("gssapi_destroy: done\n"));
+}
+
+/*
+ * Function: auth_gssapi_wrap
+ *
+ * Purpose: encrypt the serialized arguments from xdr_func applied to
+ * xdr_ptr and write the result to xdrs.
+ *
+ * Effects: See design doc, section XXX.
+ */
+static bool_t auth_gssapi_wrap(auth, out_xdrs, xdr_func, xdr_ptr)
+ AUTH *auth;
+ XDR *out_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ OM_uint32 gssstat, minor_stat;
+
+ if (! AUTH_PRIVATE(auth)->established) {
+ PRINTF(("gssapi_wrap: context not established, noop\n"));
+ return (*xdr_func)(out_xdrs, xdr_ptr);
+ } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
+ AUTH_PRIVATE(auth)->context,
+ AUTH_PRIVATE(auth)->seq_num+1,
+ out_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
+
+/*
+ * Function: auth_gssapi_unwrap
+ *
+ * Purpose: read encrypted arguments from xdrs, decrypt, and
+ * deserialize with xdr_func into xdr_ptr.
+ *
+ * Effects: See design doc, section XXX.
+ */
+static bool_t auth_gssapi_unwrap(auth, in_xdrs, xdr_func, xdr_ptr)
+ AUTH *auth;
+ XDR *in_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ OM_uint32 gssstat, minor_stat;
+
+ if (! AUTH_PRIVATE(auth)->established) {
+ PRINTF(("gssapi_unwrap: context not established, noop\n"));
+ return (*xdr_func)(in_xdrs, xdr_ptr);
+ } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
+ AUTH_PRIVATE(auth)->context,
+ AUTH_PRIVATE(auth)->seq_num,
+ in_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
diff --git a/src/lib/rpc/auth_gssapi.h b/src/lib/rpc/auth_gssapi.h
new file mode 100644
index 0000000..9092149
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi.h
@@ -0,0 +1,161 @@
+/*
+ * auth_gssapi.h, Protocol for GSS-API style authentication parameters for RPC
+ *
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.18 1996/07/22 20:39:41 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.17.4.1 1996/07/18 04:18:31 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.17.2.1 1996/06/20 23:35:44 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.17 1996/05/12 06:11:38 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.16 1996/01/31 19:16:16 grier
+ * [secure/3570]
+ * Remove (void *) casts to memcpy() args
+ *
+ * Revision 1.15 1995/12/28 17:54:34 jik
+ * Don't define DEBUG_GSSAPI here.
+ *
+ * Revision 1.14 1995/12/13 14:03:01 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.13 1995/11/07 23:15:26 grier
+ * memcpy() casts
+ *
+ * Revision 1.12 1995/05/25 18:35:59 bjaspan
+ * [secure-rpc/3103] log misc errors from RPC
+ *
+ * Revision 1.11 1994/10/27 12:39:14 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.11 1994/10/26 20:04:00 bjaspan
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.10 1993/11/12 02:32:50 bjaspan
+ * add badauth, don't use const_gss_OID
+ *
+ * Revision 1.9 1993/11/03 23:46:15 bjaspan
+ * new log_badverf format
+ *
+ * Revision 1.8 1993/11/03 21:21:38 bjaspan
+ * added log_badverf
+ *
+ * Revision 1.7 1993/11/03 01:29:56 bjaspan
+ * add const to gss_nt_*
+ *
+ */
+
+#define AUTH_GSSAPI_EXIT 0
+#define AUTH_GSSAPI_INIT 1
+#define AUTH_GSSAPI_CONTINUE_INIT 2
+#define AUTH_GSSAPI_MSG 3
+#define AUTH_GSSAPI_DESTROY 4
+
+typedef struct _auth_gssapi_name {
+ char *name;
+ gss_OID type;
+} auth_gssapi_name;
+
+typedef struct _auth_gssapi_creds {
+ rpc_u_int32 version;
+ bool_t auth_msg;
+ gss_buffer_desc client_handle;
+} auth_gssapi_creds;
+
+typedef struct _auth_gssapi_init_arg {
+ rpc_u_int32 version;
+ gss_buffer_desc token;
+} auth_gssapi_init_arg;
+
+typedef struct _auth_gssapi_init_res {
+ rpc_u_int32 version;
+ gss_buffer_desc client_handle;
+ OM_uint32 gss_major, gss_minor;
+ gss_buffer_desc token;
+ gss_buffer_desc signed_isn;
+} auth_gssapi_init_res;
+
+typedef void (*auth_gssapi_log_badauth_func)(OM_uint32 major,
+ OM_uint32 minor,
+ struct sockaddr_in *raddr,
+ caddr_t data);
+
+typedef void (*auth_gssapi_log_badverf_func)(gss_name_t client,
+ gss_name_t server,
+ struct svc_req *rqst,
+ struct rpc_msg *msg,
+ caddr_t data);
+
+typedef void (*auth_gssapi_log_miscerr_func)(struct svc_req *rqst,
+ struct rpc_msg *msg,
+ char *error,
+ caddr_t data);
+
+bool_t xdr_authgssapi_creds();
+bool_t xdr_authgssapi_init_arg();
+bool_t xdr_authgssapi_init_res();
+
+bool_t auth_gssapi_wrap_data(OM_uint32 *major, OM_uint32 *minor,
+ gss_ctx_id_t context, rpc_u_int32 seq_num, XDR
+ *out_xdrs, bool_t (*xdr_func)(), caddr_t
+ xdr_ptr);
+bool_t auth_gssapi_unwrap_data(OM_uint32 *major, OM_uint32 *minor,
+ gss_ctx_id_t context, rpc_u_int32 seq_num, XDR
+ *in_xdrs, bool_t (*xdr_func)(), caddr_t
+ xdr_ptr);
+
+AUTH *auth_gssapi_create(CLIENT *clnt,
+ OM_uint32 *major_status,
+ OM_uint32 *minor_status,
+ gss_cred_id_t claimant_cred_handle,
+ gss_name_t target_name,
+ gss_OID mech_type,
+ int req_flags,
+ OM_uint32 time_req,
+ gss_OID *actual_mech_type,
+ int *ret_flags,
+ OM_uint32 *time_rec);
+
+AUTH *auth_gssapi_create_default(CLIENT *clnt, char *service_name);
+
+void auth_gssapi_display_status(char *msg, OM_uint32 major,
+ OM_uint32 minor);
+bool_t _svcauth_gssapi_set_name(char *name, gss_OID name_type);
+
+void _svcauth_set_log_badauth_func(auth_gssapi_log_badauth_func func,
+ caddr_t data);
+void _svcauth_set_log_badverf_func(auth_gssapi_log_badverf_func func,
+ caddr_t data);
+void _svcauth_set_log_miscerr_func(auth_gssapi_log_miscerr_func func,
+ caddr_t data);
+
+#define GSS_COPY_BUFFER(dest, src) { \
+ (dest).length = (src).length; \
+ (dest).value = (src).value; }
+
+#define GSS_DUP_BUFFER(dest, src) { \
+ (dest).length = (src).length; \
+ (dest).value = (void *) malloc((dest).length); \
+ memcpy((dest).value, (src).value, (dest).length); }
+
+#define GSS_BUFFERS_EQUAL(b1, b2) (((b1).length == (b2).length) && \
+ !memcmp((b1).value,(b2).value,(b1.length)))
+
diff --git a/src/lib/rpc/auth_gssapi_misc.c b/src/lib/rpc/auth_gssapi_misc.c
new file mode 100644
index 0000000..bd7b6e5
--- /dev/null
+++ b/src/lib/rpc/auth_gssapi_misc.c
@@ -0,0 +1,390 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.14 1996/07/22 20:39:44 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.13.4.1 1996/07/18 04:18:32 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.13.2.1 1996/06/20 23:35:49 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.13 1996/05/12 06:11:38 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.12 1996/02/25 15:53:57 grier
+ * [secure/3570]
+ * OSF1 long changes
+ *
+ * Revision 1.11 1995/12/13 14:03:30 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.10 1994/10/27 12:39:23 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] back out the backwards compat hack (I only put it
+ * there in case we ever decide we want it, which we won't) and just
+ * handle the version field as if it were always there
+ *
+ * [secure-rpc/2808] add a backwards-compatible version field encoder
+ *
+ * change to use GSS_ERROR &c macros; I don't think this is correct
+ * =============================================================================
+ *
+ * Revision 1.12 1994/10/26 19:48:45 bjaspan
+ * [secure-rpc/2808] back out the backwards compat hack (I only put it
+ * there in case we ever decide we want it, which we won't) and just
+ * handle the version field as if it were always there
+ *
+ * Revision 1.11 1994/10/26 19:47:42 bjaspan
+ * [secure-rpc/2808] add a backwards-compatible version field encoder
+ *
+ * Revision 1.10 1993/12/19 22:19:40 bjaspan
+ * [secure-rpc/1077] use free instead of xdr_free(xdr_bytes,...) because
+ * xdr_bytes takes non-standard arguments
+ *
+ * Revision 1.9 1993/12/08 21:43:37 bjaspan
+ * use AUTH_GSSAPI_DISPLAY_STATUS macro, reindent
+ *
+ * Revision 1.8 1993/12/06 21:21:21 bjaspan
+ * debugging levels
+ *
+ * Revision 1.7 1993/11/03 23:46:34 bjaspan
+ * add debugging printfs showing amount of data wrapped/unwrapped
+ *
+ * Revision 1.6 1993/11/03 21:21:53 bjaspan
+ * unstatic misc_debug_gssapi
+ *
+ * Revision 1.5 1993/11/01 19:55:54 bjaspan
+ * improve display_status messages, and include gss_{major,minor}
+ *
+ * Revision 1.4 1993/10/28 22:08:21 bjaspan
+ * wrap/unwrap_data include sequence number in arg/result block
+ *
+ * Revision 1.3 1993/10/27 18:26:16 bjaspan
+ * use xdr_free instead of free(in_buf.value); doesn't actually make a
+ * difference, though
+ *
+ * Revision 1.2 1993/10/26 21:12:38 bjaspan
+ * cleaning
+ *
+ * Revision 1.1 1993/10/19 03:12:28 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/rpc.h>
+#include <stdio.h>
+
+#include <gssapi/gssapi.h>
+#include <rpc/auth_gssapi.h>
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int misc_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (misc_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (misc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+static void auth_gssapi_display_status_1(char *, OM_uint32, int, int);
+
+bool_t xdr_gss_buf(xdrs, buf)
+ XDR *xdrs;
+ gss_buffer_t buf;
+{
+ /*
+ * On decode, xdr_bytes will only allocate buf->value if the
+ * length read in is < maxsize (last arg). This is dumb, because
+ * the whole point of allocating memory is so that I don't *have*
+ * to know the maximum length. -1 effectively disables this
+ * braindamage.
+ */
+ return xdr_bytes(xdrs, (char **) &buf->value, (unsigned int *) &buf->length,
+ (xdrs->x_op == XDR_DECODE && buf->value == NULL)
+ ? (unsigned int) -1 : (unsigned int) buf->length);
+}
+
+bool_t xdr_authgssapi_creds(xdrs, creds)
+ XDR *xdrs;
+ auth_gssapi_creds *creds;
+{
+ if (! xdr_u_int32(xdrs, &creds->version) ||
+ ! xdr_bool(xdrs, &creds->auth_msg) ||
+ ! xdr_gss_buf(xdrs, &creds->client_handle))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t xdr_authgssapi_init_arg(xdrs, init_arg)
+ XDR *xdrs;
+ auth_gssapi_init_arg *init_arg;
+{
+ if (! xdr_u_int32(xdrs, &init_arg->version) ||
+ ! xdr_gss_buf(xdrs, &init_arg->token))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t xdr_authgssapi_init_res(xdrs, init_res)
+ XDR *xdrs;
+ auth_gssapi_init_res *init_res;
+{
+ if (! xdr_u_int32(xdrs, &init_res->version) ||
+ ! xdr_gss_buf(xdrs, &init_res->client_handle) ||
+ ! xdr_u_int32(xdrs, &init_res->gss_major) ||
+ ! xdr_u_int32(xdrs, &init_res->gss_minor) ||
+ ! xdr_gss_buf(xdrs, &init_res->token) ||
+ ! xdr_gss_buf(xdrs, &init_res->signed_isn))
+ return FALSE;
+ return TRUE;
+}
+
+bool_t auth_gssapi_seal_seq(context, seq_num, out_buf)
+ gss_ctx_id_t context;
+ rpc_u_int32 seq_num;
+ gss_buffer_t out_buf;
+{
+ gss_buffer_desc in_buf;
+ OM_uint32 gssstat, minor_stat;
+ rpc_u_int32 nl_seq_num;
+
+ nl_seq_num = htonl(seq_num);
+
+ in_buf.length = sizeof(rpc_u_int32);
+ in_buf.value = (char *) &nl_seq_num;
+ gssstat = gss_seal(&minor_stat, context, 0, GSS_C_QOP_DEFAULT,
+ &in_buf, NULL, out_buf);
+ if (gssstat != GSS_S_COMPLETE) {
+ PRINTF(("gssapi_seal_seq: failed\n"));
+ AUTH_GSSAPI_DISPLAY_STATUS(("sealing sequence number",
+ gssstat, minor_stat));
+ return FALSE;
+ }
+ return TRUE;
+}
+
+bool_t auth_gssapi_unseal_seq(context, in_buf, seq_num)
+ gss_ctx_id_t context;
+ gss_buffer_t in_buf;
+ rpc_u_int32 *seq_num;
+{
+ gss_buffer_desc out_buf;
+ OM_uint32 gssstat, minor_stat;
+ rpc_u_int32 nl_seq_num;
+
+ gssstat = gss_unseal(&minor_stat, context, in_buf, &out_buf,
+ NULL, NULL);
+ if (gssstat != GSS_S_COMPLETE) {
+ PRINTF(("gssapi_unseal_seq: failed\n"));
+ AUTH_GSSAPI_DISPLAY_STATUS(("unsealing sequence number",
+ gssstat, minor_stat));
+ return FALSE;
+ } else if (out_buf.length != sizeof(rpc_u_int32)) {
+ PRINTF(("gssapi_unseal_seq: unseal gave %d bytes\n",
+ out_buf.length));
+ gss_release_buffer(&minor_stat, &out_buf);
+ return FALSE;
+ }
+
+ nl_seq_num = *((rpc_u_int32 *) out_buf.value);
+ *seq_num = (rpc_u_int32) ntohl(nl_seq_num);
+ gss_release_buffer(&minor_stat, &out_buf);
+
+ return TRUE;
+}
+
+void auth_gssapi_display_status(char *msg, OM_uint32 major, OM_uint32 minor)
+{
+ auth_gssapi_display_status_1(msg, major, GSS_C_GSS_CODE, 0);
+ auth_gssapi_display_status_1(msg, minor, GSS_C_MECH_CODE, 0);
+}
+
+static void auth_gssapi_display_status_1(char *m, OM_uint32 code, int type,
+ int rec)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc msg;
+ int msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ gssstat = gss_display_status(&minor_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg);
+ if (gssstat != GSS_S_COMPLETE) {
+ if (!rec) {
+ auth_gssapi_display_status_1(m,gssstat,GSS_C_GSS_CODE,1);
+ auth_gssapi_display_status_1(m, minor_stat,
+ GSS_C_MECH_CODE, 1);
+ } else
+ fprintf(stderr,"GSS-API authentication error %s: "
+ "recursive failure!\n", msg);
+ return;
+ }
+
+ fprintf(stderr, "GSS-API authentication error %s: %s\n", m,
+ (char *)msg.value);
+ (void) gss_release_buffer(&minor_stat, &msg);
+
+ if (!msg_ctx)
+ break;
+ }
+}
+
+bool_t auth_gssapi_wrap_data(major, minor, context, seq_num, out_xdrs,
+ xdr_func, xdr_ptr)
+ OM_uint32 *major, *minor;
+ gss_ctx_id_t context;
+ rpc_u_int32 seq_num;
+ XDR *out_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ gss_buffer_desc in_buf, out_buf;
+ XDR temp_xdrs;
+ int conf_state;
+
+ PRINTF(("gssapi_wrap_data: starting\n"));
+
+ *major = GSS_S_COMPLETE;
+ *minor = 0; /* assumption */
+
+ xdralloc_create(&temp_xdrs, XDR_ENCODE);
+
+ /* serialize the sequence number into local memory */
+ PRINTF(("gssapi_wrap_data: encoding seq_num %d\n", seq_num));
+ if (! xdr_u_int32(&temp_xdrs, &seq_num)) {
+ PRINTF(("gssapi_wrap_data: serializing seq_num failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ /* serialize the arguments into local memory */
+ if (!(*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ PRINTF(("gssapi_wrap_data: serializing arguments failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ in_buf.length = xdr_getpos(&temp_xdrs);
+ in_buf.value = xdralloc_getdata(&temp_xdrs);
+
+ *major = gss_seal(minor, context, 1,
+ GSS_C_QOP_DEFAULT, &in_buf, &conf_state,
+ &out_buf);
+ if (*major != GSS_S_COMPLETE) {
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ PRINTF(("gssapi_wrap_data: %d bytes data, %d bytes sealed\n",
+ in_buf.length, out_buf.length));
+
+ /* write the token */
+ if (! xdr_bytes(out_xdrs, (char **) &out_buf.value,
+ (unsigned int *) &out_buf.length,
+ out_buf.length)) {
+ PRINTF(("gssapi_wrap_data: serializing encrypted data failed\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ *major = gss_release_buffer(minor, &out_buf);
+
+ PRINTF(("gssapi_wrap_data: succeeding\n\n"));
+ XDR_DESTROY(&temp_xdrs);
+ return TRUE;
+}
+
+bool_t auth_gssapi_unwrap_data(major, minor, context, seq_num,
+ in_xdrs, xdr_func, xdr_ptr)
+ OM_uint32 *major, *minor;
+ gss_ctx_id_t context;
+ rpc_u_int32 seq_num;
+ XDR *in_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ gss_buffer_desc in_buf, out_buf;
+ XDR temp_xdrs;
+ rpc_u_int32 verf_seq_num;
+ int conf, qop;
+
+ PRINTF(("gssapi_unwrap_data: starting\n"));
+
+ *major = GSS_S_COMPLETE;
+ *minor = 0; /* assumption */
+
+ in_buf.value = NULL;
+ out_buf.value = NULL;
+
+ if (! xdr_bytes(in_xdrs, (char **) &in_buf.value,
+ (unsigned int *) &in_buf.length, (unsigned int) -1)) {
+ PRINTF(("gssapi_unwrap_data: deserializing encrypted data failed\n"));
+ return FALSE;
+ }
+
+ *major = gss_unseal(minor, context, &in_buf, &out_buf, &conf,
+ &qop);
+ free(in_buf.value);
+ if (*major != GSS_S_COMPLETE)
+ return FALSE;
+
+ PRINTF(("gssapi_unwrap_data: %d bytes data, %d bytes sealed\n",
+ out_buf.length, in_buf.length));
+
+ xdrmem_create(&temp_xdrs, out_buf.value, out_buf.length, XDR_DECODE);
+
+ /* deserialize the sequence number */
+ if (! xdr_u_int32(&temp_xdrs, &verf_seq_num)) {
+ PRINTF(("gssapi_unwrap_data: deserializing verf_seq_num failed\n"));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+ if (verf_seq_num != seq_num) {
+ PRINTF(("gssapi_unwrap_data: seq %d specified, read %d\n",
+ seq_num, verf_seq_num));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+ PRINTF(("gssapi_unwrap_data: unwrap seq_num %d okay\n", verf_seq_num));
+
+ /* deserialize the arguments into xdr_ptr */
+ if (! (*xdr_func)(&temp_xdrs, xdr_ptr)) {
+ PRINTF(("gssapi_unwrap_data: deserializing arguments failed\n"));
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return FALSE;
+ }
+
+ PRINTF(("gssapi_unwrap_data: succeeding\n\n"));
+
+ gss_release_buffer(minor, &out_buf);
+ XDR_DESTROY(&temp_xdrs);
+ return TRUE;
+}
diff --git a/src/lib/rpc/auth_none.c b/src/lib/rpc/auth_none.c
new file mode 100644
index 0000000..90f3bb8
--- /dev/null
+++ b/src/lib/rpc/auth_none.c
@@ -0,0 +1,136 @@
+/* @(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#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>
+#include <stdlib.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,
+ authany_wrap,
+ authany_wrap,
+};
+
+static struct authnone_private {
+ AUTH no_client;
+ char marshalled_client[MAX_MARSHEL_SIZE];
+ unsigned 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, (unsigned 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/src/lib/rpc/auth_unix.c b/src/lib/rpc/auth_unix.c
new file mode 100644
index 0000000..b41e442
--- /dev/null
+++ b/src/lib/rpc/auth_unix.c
@@ -0,0 +1,322 @@
+/* @(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#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 <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,
+ authany_wrap,
+ authany_wrap,
+};
+
+/*
+ * 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 */
+ rpc_u_int32 au_shfaults; /* short hand cache faults */
+ char au_marshed[MAX_AUTH_BYTES];
+ unsigned 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 = (unsigned 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((unsigned int) len);
+#else
+ if ((au->au_origcred.oa_base = mem_alloc((unsigned int) len)) == NULL) {
+ (void)fprintf(stderr, "authunix_create: out of memory\n");
+ return (NULL);
+ }
+#endif
+ memmove(au->au_origcred.oa_base, mymem, (unsigned 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/src/lib/rpc/auth_unix.h b/src/lib/rpc/auth_unix.h
new file mode 100644
index 0000000..4b54f1d
--- /dev/null
+++ b/src/lib/rpc/auth_unix.h
@@ -0,0 +1,72 @@
+/* @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC; from 1.8 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)auth_unix.h 1.5 86/07/16 SMI */
+
+/*
+ * 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.
+ */
+
+/* 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 {
+ rpc_u_int32 aup_time;
+ char *aup_machname;
+ int aup_uid;
+ int aup_gid;
+ unsigned int aup_len;
+ int *aup_gids;
+};
+
+extern bool_t xdr_authunix_parms();
+
+/*
+ * 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;
+};
diff --git a/src/lib/rpc/authunix_prot.c b/src/lib/rpc/authunix_prot.c
new file mode 100644
index 0000000..36770f2
--- /dev/null
+++ b/src/lib/rpc/authunix_prot.c
@@ -0,0 +1,66 @@
+/* @(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#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_int32(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/src/lib/rpc/bindresvport.c b/src/lib/rpc/bindresvport.c
new file mode 100644
index 0000000..875aeef
--- /dev/null
+++ b/src/lib/rpc/bindresvport.c
@@ -0,0 +1,79 @@
+static char sccsid[] = "@(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC 1.8 88/02/08 SMI";
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * 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;
+ memset(sin, 0, 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/src/lib/rpc/clnt.h b/src/lib/rpc/clnt.h
new file mode 100644
index 0000000..442a96d
--- /dev/null
+++ b/src/lib/rpc/clnt.h
@@ -0,0 +1,335 @@
+/* @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.31 88/02/08 SMI*/
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * clnt.h - Client side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef _CLNT_
+#define _CLNT_
+
+/*
+ * 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 {
+ rpc_u_int32 low; /* lowest verion supported */
+ rpc_u_int32 high; /* highest verion supported */
+ } RE_vers;
+ struct { /* maybe meaningful if RPC_FAILED */
+ rpc_int32 s1;
+ rpc_int32 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;
+ * rpc_u_int32 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;
+ * unsigned 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) */
+/*
+ * new control operations
+ */
+#define CLGET_LOCAL_ADDR 6 /* get local address (sockaddr, getsockname)*/
+
+/*
+ * 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 ((rpc_u_int32)1)
+#define RPCTEST_VERSION ((rpc_u_int32)1)
+#define RPCTEST_NULL_PROC ((rpc_u_int32)2)
+#define RPCTEST_NULL_BATCH_PROC ((rpc_u_int32)3)
+
+/*
+ * By convention, procedure 0 takes null arguments and returns them
+ */
+
+#define NULLPROC ((rpc_u_int32)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)
+ * rpc_u_int32 prog;
+ * rpc_u_int32 vers;
+ */
+extern CLIENT *clntraw_create();
+
+
+/*
+ * Generic client creation routine. Supported protocols are "udp" and "tcp"
+ */
+extern CLIENT *
+clnt_create(/*host, prog, vers, prot*/); /*
+ char *host; -- hostname
+ rpc_u_int32 prog; -- program number
+ rpc_u_int32 vers; -- version number
+ char *prot; -- protocol
+*/
+
+
+
+
+/*
+ * TCP based rpc
+ * CLIENT *
+ * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ * struct sockaddr_in *raddr;
+ * rpc_u_int32 prog;
+ * rpc_u_int32 version;
+ * register int *sockp;
+ * unsigned int sendsz;
+ * unsigned int recvsz;
+ */
+extern CLIENT *clnttcp_create();
+
+/*
+ * UDP based rpc.
+ * CLIENT *
+ * clntudp_create(raddr, program, version, wait, sockp)
+ * struct sockaddr_in *raddr;
+ * rpc_u_int32 program;
+ * rpc_u_int32 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;
+ * rpc_u_int32 program;
+ * rpc_u_int32 version;
+ * struct timeval wait;
+ * int *sockp;
+ * unsigned int sendsz;
+ * unsigned int recvsz;
+ */
+extern CLIENT *clntudp_create();
+extern CLIENT *clntudp_bufcreate();
+
+/*
+ * Print why creation failed
+ */
+void clnt_pcreateerror(/* char *msg */); /* stderr */
+char *clnt_spcreateerror(/* char *msg */); /* string */
+
+/*
+ * Like clnt_perror(), but is more verbose in its output
+ */
+void clnt_perrno(/* enum clnt_stat num */); /* stderr */
+
+/*
+ * Print an English error message, given the client error code
+ */
+void clnt_perror(/* CLIENT *clnt, char *msg */); /* stderr */
+char *clnt_sperror(/* CLIENT *clnt, char *msg */); /* string */
+
+/*
+ * 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;
+
+
+
+/*
+ * Copy error message to buffer.
+ */
+char *clnt_sperrno(/* enum clnt_stat num */); /* string */
+
+
+
+#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */
+#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */
+
+#endif /*!_CLNT_*/
diff --git a/src/lib/rpc/clnt_generic.c b/src/lib/rpc/clnt_generic.c
new file mode 100644
index 0000000..f111c2e
--- /dev/null
+++ b/src/lib/rpc/clnt_generic.c
@@ -0,0 +1,110 @@
+/* @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
+#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;
+ unsigned prog;
+ unsigned 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;
+ memset(sin.sin_zero, 0, sizeof(sin.sin_zero));
+ memmove((char*)&sin.sin_addr, h->h_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/src/lib/rpc/clnt_perror.c b/src/lib/rpc/clnt_perror.c
new file mode 100644
index 0000000..63eef49
--- /dev/null
+++ b/src/lib/rpc/clnt_perror.c
@@ -0,0 +1,306 @@
+/* @(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include <stdio.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+
+#ifdef NEED_SYS_ERRLIST
+extern char *sys_errlist[];
+#endif
+static char *auth_errmsg();
+
+extern char *strcpy();
+
+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",
+ sys_errlist[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,
+ sys_errlist[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/src/lib/rpc/clnt_raw.c b/src/lib/rpc/clnt_raw.c
new file mode 100644
index 0000000..d05dbaa
--- /dev/null
+++ b/src/lib/rpc/clnt_raw.c
@@ -0,0 +1,239 @@
+/* @(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+#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];
+ unsigned 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)
+ rpc_u_int32 prog;
+ rpc_u_int32 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;
+ rpc_u_int32 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;
+ long procl = proc;
+
+ 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, &procl)) ||
+ (! 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);
+ sunrpc_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, &msg))
+ 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/src/lib/rpc/clnt_simple.c b/src/lib/rpc/clnt_simple.c
new file mode 100644
index 0000000..0d8f7a4
--- /dev/null
+++ b/src/lib/rpc/clnt_simple.c
@@ -0,0 +1,112 @@
+/* @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * clnt_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>
+#include <string.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 = mem_alloc(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;
+ memmove((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length);
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = 0;
+ if ((crp->client = clntudp_create(&server_addr, (rpc_u_int32)prognum,
+ (rpc_u_int32)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/src/lib/rpc/clnt_tcp.c b/src/lib/rpc/clnt_tcp.c
new file mode 100644
index 0000000..c573897
--- /dev/null
+++ b/src/lib/rpc/clnt_tcp.c
@@ -0,0 +1,476 @@
+/* @(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+#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 */
+ unsigned 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;
+ rpc_u_int32 prog;
+ rpc_u_int32 vers;
+ register int *sockp;
+ unsigned int sendsz;
+ unsigned 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) {
+ unsigned 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;
+ rpc_u_int32 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;
+ rpc_u_int32 x_id;
+ rpc_u_int32 *msg_x_id = (rpc_u_int32 *)(ct->ct_mcall); /* yuk */
+ register bool_t shipnow;
+ int refreshes = 2;
+ long procl = proc;
+
+ 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, &procl)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! AUTH_WRAP(h->cl_auth, xdrs, xdr_args, 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
+ */
+ sunrpc_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 (! AUTH_UNWRAP(h->cl_auth, xdrs,
+ xdr_results, results_ptr)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTDECODERES;
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (refreshes-- && AUTH_REFRESH(h->cl_auth, &reply_msg))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ /* free verifier ... */
+ if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (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));
+ }
+ 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;
+ int len;
+
+ 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;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(ct->ct_sock, (struct sockaddr*)info, &len) < 0)
+ return FALSE;
+ else
+ return TRUE;
+ 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, (fd_set*)NULL, (fd_set*)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/src/lib/rpc/clnt_udp.c b/src/lib/rpc/clnt_udp.c
new file mode 100644
index 0000000..000b968
--- /dev/null
+++ b/src/lib/rpc/clnt_udp.c
@@ -0,0 +1,460 @@
+/* @(#)clnt_udp.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";
+#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>
+#if defined(sparc)
+#include <sys/filio.h>
+#endif
+#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;
+ unsigned int cu_xdrpos;
+ unsigned int cu_sendsz;
+ char *cu_outbuf;
+ unsigned 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;
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ struct timeval wait;
+ register int *sockp;
+ unsigned int sendsz;
+ unsigned 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) {
+ unsigned 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;
+ rpc_u_int32 program;
+ rpc_u_int32 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 */
+ rpc_u_int32 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;
+ long procl = proc;
+
+ 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
+ */
+ (*(unsigned short *)(cu->cu_outbuf))++;
+ if ((! XDR_PUTLONG(xdrs, &procl)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! AUTH_WRAP(cl->cl_auth, xdrs, xargs, 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 = NULL;
+ reply_msg.acpted_rply.ar_results.proc = xdr_void;
+#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, (fd_set *)NULL,
+ (fd_set *)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(rpc_u_int32))
+ continue;
+ /* see if reply transaction id matches sent id */
+ if (*((rpc_u_int32 *)(cu->cu_inbuf)) != *((rpc_u_int32 *)(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, (unsigned int)inlen, XDR_DECODE);
+ ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+ /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
+ if (ok) {
+ sunrpc_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;
+ } else if (! AUTH_UNWRAP(cl->cl_auth, &reply_xdrs,
+ xresults, resultsp)) {
+ if (cu->cu_error.re_status == RPC_SUCCESS)
+ cu->cu_error.re_status = RPC_CANTDECODERES;
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (nrefreshes > 0 &&
+ AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
+ nrefreshes--;
+ goto call_again;
+ }
+ } /* end of unsuccessful completion */
+ /* free verifier */
+ if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (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 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;
+ int len;
+
+ 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;
+ case CLGET_LOCAL_ADDR:
+ len = sizeof(struct sockaddr);
+ if (getsockname(cu->cu_sock, (struct sockaddr*)info, &len) < 0)
+ return FALSE;
+ else
+ return TRUE;
+ 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/src/lib/rpc/configure.in b/src/lib/rpc/configure.in
new file mode 100644
index 0000000..6084638
--- /dev/null
+++ b/src/lib/rpc/configure.in
@@ -0,0 +1,41 @@
+AC_INIT(auth_gssapi.c)
+CONFIG_RULES
+AC_PROG_ARCHIVE
+AC_PROG_ARCHIVE_ADD
+AC_PROG_RANLIB
+AC_PROG_INSTALL
+
+AC_CHECK_SIZEOF(int)
+SIZEOF_INT=$ac_cv_sizeof_int
+AC_SUBST(SIZEOF_INT)
+AC_CHECK_SIZEOF(long)
+SIZEOF_LONG=$ac_cv_sizeof_long
+AC_SUBST(SIZEOF_LONG)
+
+DECLARE_SYS_ERRLIST
+
+V5_SHARED_LIB_OBJS
+V5_MAKE_SHARED_LIB(libgssrpc,1.0,.., ./rpc)
+GSSAPI_KRB5_SH_VERS=$krb5_cv_shlib_version_libgssapi_krb5
+AC_SUBST(GSSAPI_KRB5_SH_VERS)
+KRB5_SH_VERS=$krb5_cv_shlib_version_libkrb5
+AC_SUBST(KRB5_SH_VERS)
+CRYPTO_SH_VERS=$krb5_cv_shlib_version_libcrypto
+AC_SUBST(CRYPTO_SH_VERS)
+COMERR_SH_VERS=$krb5_cv_shlib_version_libcom_err
+AC_SUBST(COMERR_SH_VERS)
+CopySrcHeader(auth.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(auth_gssapi.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(auth_unix.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(clnt.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(netdb.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(pmap_clnt.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(pmap_prot.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(pmap_rmt.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(rpc.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(rpc_msg.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(svc.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(svc_auth.h,[$](BUILDTOP)/include/rpc)
+CopyHeader(types.h,[$](BUILDTOP)/include/rpc)
+CopySrcHeader(xdr.h,[$](BUILDTOP)/include/rpc)
+V5_AC_OUTPUT_MAKEFILE( ,types.h:types.hin)
diff --git a/src/lib/rpc/get_myaddress.c b/src/lib/rpc/get_myaddress.c
new file mode 100644
index 0000000..fa4c54e
--- /dev/null
+++ b/src/lib/rpc/get_myaddress.c
@@ -0,0 +1,95 @@
+/* @(#)get_myaddress.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#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/pmap_prot.h>
+#include <sys/socket.h>
+#if defined(sun)
+#include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#include <net/if.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <netinet/in.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;
+
+ 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;
+ }
+ ifr++;
+ }
+ (void) close(s);
+}
diff --git a/src/lib/rpc/getrpcent.c b/src/lib/rpc/getrpcent.c
new file mode 100644
index 0000000..e48d5b1
--- /dev/null
+++ b/src/lib/rpc/getrpcent.c
@@ -0,0 +1,256 @@
+/* @(#)getrpcent.c 2.2 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)getrpcent.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * 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
+ */
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/netdb.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/socket.h>
+
+/* setrpcent is declared as int-returning in netdb.h on hpux */
+/* setrpcent is declared as int-returning in rpc/rpcent.h on Solaris */
+#if !defined(hpux) && !(defined(sun) && defined(__svr4__))
+#define SETRPCENT_TYPE void
+#else
+#define SETRPCENT_TYPE int
+#endif
+
+/* endrpcent is declared as int-returning in netdb.h on hpux */
+#ifndef hpux
+#define ENDRPCENT_TYPE void
+#else
+#define ENDRPCENT_TYPE int
+#endif
+
+SETRPCENT_TYPE setrpcent(int);
+ENDRPCENT_TYPE endrpcent(void);
+
+/*
+ * Internet version.
+ */
+struct rpcdata {
+ FILE *rpcf;
+ char *current;
+ int currentlen;
+ int stayopen;
+#define MAXALIASES 35
+ char *rpc_aliases[MAXALIASES];
+ struct rpcent rpc;
+ char line[BUFSIZ+1];
+ char *domain;
+} *rpcdata;
+static struct rpcdata *_rpcdata();
+
+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;
+ int reason;
+ char adrstr[16], *val = NULL;
+ int vallen;
+
+ if (d == 0)
+ return (0);
+ setrpcent(0);
+ while (p = getrpcent()) {
+ if (p->r_number == number)
+ break;
+ }
+ endrpcent();
+ return (p);
+}
+
+struct rpcent *
+getrpcbyname(name)
+ const 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);
+}
+
+SETRPCENT_TYPE setrpcent(f)
+ int f;
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+ if (d->rpcf == NULL)
+ d->rpcf = fopen(RPCDB, "r");
+ else
+ rewind(d->rpcf);
+ if (d->current)
+ free(d->current);
+ d->current = NULL;
+ d->stayopen |= f;
+}
+
+ENDRPCENT_TYPE endrpcent()
+{
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return;
+ if (d->current && !d->stayopen) {
+ free(d->current);
+ d->current = NULL;
+ }
+ if (d->rpcf && !d->stayopen) {
+ fclose(d->rpcf);
+ d->rpcf = NULL;
+ }
+}
+
+struct rpcent *
+getrpcent()
+{
+ struct rpcent *hp;
+ int reason;
+ char *key = NULL, *val = NULL;
+ int keylen, vallen;
+ register struct rpcdata *d = _rpcdata();
+
+ if (d == 0)
+ return(NULL);
+ 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;
+{
+ register struct rpcdata *d = _rpcdata();
+ char *p;
+ register char *cp, **q;
+
+ if (d == 0)
+ return;
+ strncpy(d->line, val, len);
+ p = d->line;
+ d->line[len] = '\n';
+ if (*p == '#')
+ return (getrpcent());
+ cp = strchr(p, '#');
+ if (cp == NULL)
+ {
+ cp = strchr(p, '\n');
+ if (cp == NULL)
+ return (getrpcent());
+ }
+ *cp = '\0';
+ cp = strchr(p, ' ');
+ if (cp == NULL)
+ {
+ cp = strchr(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 = strchr(p, ' ');
+ if (cp != NULL)
+ *cp++ = '\0';
+ else
+ {
+ cp = strchr(p, '\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 = strchr(p, ' ');
+ if (cp != NULL)
+ *cp++ = '\0';
+ else
+ {
+ cp = strchr(p, '\t');
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (&d->rpc);
+}
diff --git a/src/lib/rpc/getrpcport.c b/src/lib/rpc/getrpcport.c
new file mode 100644
index 0000000..d209a15
--- /dev/null
+++ b/src/lib/rpc/getrpcport.c
@@ -0,0 +1,55 @@
+/* @(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+#endif
+/*
+ * 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
+ */
+
+/*
+ * 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);
+ memmove((char *) &addr.sin_addr, hp->h_addr, hp->h_length);
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ return (pmap_getport(&addr, prognum, versnum, proto));
+}
diff --git a/src/lib/rpc/netdb.h b/src/lib/rpc/netdb.h
new file mode 100644
index 0000000..f6b6374
--- /dev/null
+++ b/src/lib/rpc/netdb.h
@@ -0,0 +1,50 @@
+#ifndef RPC_NETDB_H
+#define RPC_NETDB_H
+
+/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)rpc.h 1.8 87/07/24 SMI */
+
+/* since the gssrpc library requires that any application using it be
+built with these header files, I am making the decision that any app
+which uses the rpcent routines must use this header file, or something
+compatible (which most <netdb.h> are) --marc */
+
+/* Really belongs in <netdb.h> */
+
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ int r_number; /* rpc program number */
+};
+
+struct rpcent *getrpcbyname(), *getrpcbynumber(), *getrpcent();
+
+#endif
diff --git a/src/lib/rpc/pmap_clnt.c b/src/lib/rpc/pmap_clnt.c
new file mode 100644
index 0000000..7218777
--- /dev/null
+++ b/src/lib/rpc/pmap_clnt.c
@@ -0,0 +1,115 @@
+/* @(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
+#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)
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ int protocol;
+ unsigned 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)
+ rpc_u_int32 program;
+ rpc_u_int32 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/src/lib/rpc/pmap_clnt.h b/src/lib/rpc/pmap_clnt.h
new file mode 100644
index 0000000..dfb00dc
--- /dev/null
+++ b/src/lib/rpc/pmap_clnt.h
@@ -0,0 +1,65 @@
+/* @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC; from 1.11 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * 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.
+ */
+
+extern bool_t pmap_set();
+extern bool_t pmap_unset();
+extern struct pmaplist *pmap_getmaps();
+enum clnt_stat pmap_rmtcall();
+enum clnt_stat clnt_broadcast();
+extern unsigned short pmap_getport();
diff --git a/src/lib/rpc/pmap_getmaps.c b/src/lib/rpc/pmap_getmaps.c
new file mode 100644
index 0000000..472b2a4
--- /dev/null
+++ b/src/lib/rpc/pmap_getmaps.c
@@ -0,0 +1,88 @@
+/* @(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#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>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#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/src/lib/rpc/pmap_getport.c b/src/lib/rpc/pmap_getport.c
new file mode 100644
index 0000000..40b7648
--- /dev/null
+++ b/src/lib/rpc/pmap_getport.c
@@ -0,0 +1,91 @@
+/* @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+#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>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#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.
+ */
+unsigned short
+pmap_getport(address, program, version, protocol)
+ struct sockaddr_in *address;
+ rpc_u_int32 program;
+ rpc_u_int32 version;
+ unsigned int protocol;
+{
+ unsigned 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/src/lib/rpc/pmap_prot.c b/src/lib/rpc/pmap_prot.c
new file mode 100644
index 0000000..1dffffe
--- /dev/null
+++ b/src/lib/rpc/pmap_prot.c
@@ -0,0 +1,57 @@
+/* @(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+#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_int32(xdrs, &regs->pm_prog) &&
+ xdr_u_int32(xdrs, &regs->pm_vers) &&
+ xdr_u_int32(xdrs, &regs->pm_prot))
+ return (xdr_u_int32(xdrs, &regs->pm_port));
+ return (FALSE);
+}
diff --git a/src/lib/rpc/pmap_prot.h b/src/lib/rpc/pmap_prot.h
new file mode 100644
index 0000000..4f76580
--- /dev/null
+++ b/src/lib/rpc/pmap_prot.h
@@ -0,0 +1,94 @@
+/* @(#)pmap_prot.h 2.1 88/07/29 4.0 RPCSRC; from 1.14 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * 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 (rpc_int32 unsigned).
+ * 0 is failure. Otherwise returns the port number where the pair
+ * [prog, vers] is registered. It may lie!
+ *
+ * PMAPPROC_DUMP() RETURNS (struct pmaplist *)
+ *
+ * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>)
+ * RETURNS (port, string<>);
+ * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs);
+ * Calls the procedure on the local machine. If it is not registered,
+ * this procedure is quite; ie it does not return error information!!!
+ * This procedure only is supported on rpc/udp and calls via
+ * rpc/udp. This routine only passes null authentication parameters.
+ * This file has no interface to xdr routines for PMAPPROC_CALLIT.
+ *
+ * The service supports remote procedure calls on udp/ip or tcp/ip socket 111.
+ */
+
+#define PMAPPORT ((unsigned short)111)
+#define PMAPPROG ((rpc_u_int32)100000)
+#define PMAPVERS ((rpc_u_int32)2)
+#define PMAPVERS_PROTO ((rpc_u_int32)2)
+#define PMAPVERS_ORIG ((rpc_u_int32)1)
+#define PMAPPROC_NULL ((rpc_u_int32)0)
+#define PMAPPROC_SET ((rpc_u_int32)1)
+#define PMAPPROC_UNSET ((rpc_u_int32)2)
+#define PMAPPROC_GETPORT ((rpc_u_int32)3)
+#define PMAPPROC_DUMP ((rpc_u_int32)4)
+#define PMAPPROC_CALLIT ((rpc_u_int32)5)
+
+struct pmap {
+ rpc_u_int32 pm_prog;
+ rpc_u_int32 pm_vers;
+ rpc_u_int32 pm_prot;
+ rpc_u_int32 pm_port;
+};
+
+extern bool_t xdr_pmap();
+
+struct pmaplist {
+ struct pmap pml_map;
+ struct pmaplist *pml_next;
+};
+
+extern bool_t xdr_pmaplist();
diff --git a/src/lib/rpc/pmap_prot2.c b/src/lib/rpc/pmap_prot2.c
new file mode 100644
index 0000000..5f48f2a
--- /dev/null
+++ b/src/lib/rpc/pmap_prot2.c
@@ -0,0 +1,116 @@
+/* @(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+
+
+/*
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ * struct pmap pml_map;
+ * struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ *
+ * case TRUE: struct {
+ * struct pmap;
+ * pmaplist_t foo;
+ * };
+ *
+ * case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable. The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the
+ * xdr union, pamplist_t.
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list. Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(xdrs, rp)
+ register XDR *xdrs;
+ register struct pmaplist **rp;
+{
+ /*
+ * more_elements is pre-computed in case the direction is
+ * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
+ * xdr_bool when the direction is XDR_DECODE.
+ */
+ bool_t more_elements;
+ register int freeing = (xdrs->x_op == XDR_FREE);
+ register struct pmaplist **next;
+
+ while (TRUE) {
+ more_elements = (bool_t)(*rp != NULL);
+ if (! xdr_bool(xdrs, &more_elements))
+ return (FALSE);
+ if (! more_elements)
+ return (TRUE); /* we are done */
+ /*
+ * the unfortunate side effect of non-recursion is that in
+ * the case of freeing we must remember the next object
+ * before we free the current object ...
+ */
+ if (freeing)
+ next = &((*rp)->pml_next);
+ if (! xdr_reference(xdrs, (caddr_t *)rp,
+ (unsigned int)sizeof(struct pmaplist), xdr_pmap))
+ return (FALSE);
+ rp = (freeing) ? next : &((*rp)->pml_next);
+ }
+}
diff --git a/src/lib/rpc/pmap_rmt.c b/src/lib/rpc/pmap_rmt.c
new file mode 100644
index 0000000..6a23767
--- /dev/null
+++ b/src/lib/rpc/pmap_rmt.c
@@ -0,0 +1,403 @@
+/* @(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#include <sys/socket.h>
+#ifdef sparc
+#include <sys/sockio.h>
+#endif
+#include <stdio.h>
+#include <errno.h>
+#ifdef OSF1
+#include <net/route.h>
+#include <sys/mbuf.h>
+#endif
+#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;
+ rpc_u_int32 prog, vers, proc;
+ xdrproc_t xdrargs, xdrres;
+ caddr_t argsp, resp;
+ struct timeval tout;
+ rpc_u_int32 *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;
+{
+ unsigned int lenposition, argposition, position;
+
+ if (xdr_u_int32(xdrs, &(cap->prog)) &&
+ xdr_u_int32(xdrs, &(cap->vers)) &&
+ xdr_u_int32(xdrs, &(cap->proc))) {
+ lenposition = XDR_GETPOS(xdrs);
+ if (! xdr_u_int32(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 = (rpc_u_int32)position - (rpc_u_int32)argposition;
+ XDR_SETPOS(xdrs, lenposition);
+ if (! xdr_u_int32(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 (rpc_u_int32),
+ xdr_u_int32) && xdr_u_int32(xdrs, &crp->resultslen)) {
+ crp->port_ptr = (rpc_u_int32 *)port_ptr;
+ return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+ }
+ return (FALSE);
+}
+
+
+/*
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these trivial
+ * routines which only support udp/ip .
+ */
+
+static int
+getbroadcastnets(addrs, sock, buf)
+ struct in_addr *addrs;
+ int sock; /* any valid socket will do */
+ char *buf; /* why allocxate more when we can use existing... */
+{
+ struct ifconf ifc;
+ struct ifreq ifreq, *ifr;
+ struct sockaddr_in *sin;
+ int n, i;
+
+ ifc.ifc_len = UDPMSGSIZE;
+ ifc.ifc_buf = buf;
+ if (ioctl(sock, SIOCGIFCONF, (char *)&ifc) < 0) {
+ perror("broadcast: ioctl (get interface configuration)");
+ return (0);
+ }
+ ifr = ifc.ifc_req;
+ for (i = 0, n = ifc.ifc_len/sizeof (struct ifreq); n > 0; n--, ifr++) {
+ ifreq = *ifr;
+ if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifreq) < 0) {
+ perror("broadcast: ioctl (get interface flags)");
+ continue;
+ }
+ if ((ifreq.ifr_flags & IFF_BROADCAST) &&
+ (ifreq.ifr_flags & IFF_UP) &&
+ ifr->ifr_addr.sa_family == AF_INET) {
+ sin = (struct sockaddr_in *)&ifr->ifr_addr;
+#ifdef SIOCGIFBRDADDR /* 4.3BSD */
+ if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) {
+ addrs[i++].s_addr = INADDR_ANY;
+#if 0 /* this is uuuuugly */
+ addrs[i++] = inet_makeaddr(inet_netof
+#if defined(hpux) || (defined(sparc) && defined(__svr4__)) || defined(linux) || (defined(__osf__) && defined(__alpha__))
+ (sin->sin_addr), INADDR_ANY);
+#else /* hpux or solaris */
+ (sin->sin_addr.s_addr), INADDR_ANY);
+#endif
+#endif
+ } else {
+ addrs[i++] = ((struct sockaddr_in*)
+ &ifreq.ifr_addr)->sin_addr;
+ }
+#else /* 4.2 BSD */
+ addrs[i++] = inet_makeaddr(inet_netof
+ (sin->sin_addr.s_addr), INADDR_ANY);
+#endif
+ }
+ }
+ return (i);
+}
+
+typedef bool_t (*resultproc_t)();
+
+enum clnt_stat
+clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
+ rpc_u_int32 prog; /* program number */
+ rpc_u_int32 vers; /* version number */
+ rpc_u_int32 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 rpc_u_int32 xid;
+ rpc_u_int32 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, (char *) &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, (fd_set *)NULL,
+ (fd_set *)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(rpc_u_int32))
+ goto recv_again;
+ /*
+ * see if reply transaction id matches sent id.
+ * If so, decode the results.
+ */
+ xdrmem_create(xdrs, inbuf, (unsigned 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((unsigned 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/src/lib/rpc/pmap_rmt.h b/src/lib/rpc/pmap_rmt.h
new file mode 100644
index 0000000..2ea2212
--- /dev/null
+++ b/src/lib/rpc/pmap_rmt.h
@@ -0,0 +1,53 @@
+/* @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC; from 1.2 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Structures and XDR routines for parameters to and replies from
+ * the portmapper remote-call-service.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+struct rmtcallargs {
+ rpc_u_int32 prog, vers, proc, arglen;
+ caddr_t args_ptr;
+ xdrproc_t xdr_args;
+};
+
+bool_t xdr_rmtcall_args();
+
+struct rmtcallres {
+ rpc_u_int32 *port_ptr;
+ rpc_u_int32 resultslen;
+ caddr_t results_ptr;
+ xdrproc_t xdr_results;
+};
+
+bool_t xdr_rmtcallres();
diff --git a/src/lib/rpc/rpc.h b/src/lib/rpc/rpc.h
new file mode 100644
index 0000000..d0280aa
--- /dev/null
+++ b/src/lib/rpc/rpc.h
@@ -0,0 +1,74 @@
+/* @(#)rpc.h 2.3 88/08/10 4.0 RPCSRC; from 1.9 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * rpc.h, Just includes the billions of rpc header files necessary to
+ * do remote procedure calling.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+#ifndef __RPC_HEADER__
+#define __RPC_HEADER__
+
+#include <rpc/types.h> /* some typedefs */
+#include <netinet/in.h>
+
+/* external data representation interfaces */
+#include <rpc/xdr.h> /* generic (de)serializer */
+
+/* Client side only authentication */
+#include <rpc/auth.h> /* generic authenticator (client side) */
+
+/* Client side (mostly) remote procedure call */
+#include <rpc/clnt.h> /* generic rpc stuff */
+
+/* semi-private protocol headers */
+#include <rpc/rpc_msg.h> /* protocol for rpc messages */
+#include <rpc/auth_unix.h> /* protocol for unix style cred */
+/*
+ * 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_auth.h> /* service side authenticator */
+#include <rpc/svc.h> /* service manager and multiplexer */
+
+/*
+ * COMMENT OUT THE NEXT INCLUDE IF RUNNING ON SUN OS OR ON A VERSION
+ * OF UNIX BASED ON NFSSRC. These systems will already have the structures
+ * defined by <rpc/netdb.h> included in <netdb.h>.
+ */
+/* routines for parsing /etc/rpc */
+#include <netdb.h>
+#include <rpc/netdb.h> /* structures and routines to parse /etc/rpc */
+
+#endif /* ndef __RPC_HEADER__ */
diff --git a/src/lib/rpc/rpc_callmsg.c b/src/lib/rpc/rpc_callmsg.c
new file mode 100644
index 0000000..370e79f
--- /dev/null
+++ b/src/lib/rpc/rpc_callmsg.c
@@ -0,0 +1,195 @@
+/* @(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include <sys/param.h>
+
+#include <rpc/rpc.h>
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(xdrs, cmsg)
+ register XDR *xdrs;
+ register struct rpc_msg *cmsg;
+{
+ register rpc_int32 *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 = (rpc_int32 *) 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) {
+ memmove((caddr_t)buf, oa->oa_base,
+ oa->oa_length);
+ buf += RNDUP(oa->oa_length) / sizeof (rpc_int32);
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_LONG(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memmove((caddr_t)buf, oa->oa_base,
+ oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) / sizeof (rpc_int32);
+ */
+ }
+ return (TRUE);
+ }
+ }
+ if (xdrs->x_op == XDR_DECODE) {
+ buf = (rpc_int32 *) 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 = (rpc_int32 *)
+ XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, (caddr_t)buf,
+ oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) /
+ sizeof (rpc_int32);
+ */
+ }
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ buf = (rpc_int32 *)
+ 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 = (rpc_int32 *)
+ XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, (caddr_t) buf,
+ oa->oa_length);
+ /* no real need...
+ buf += RNDUP(oa->oa_length) /
+ sizeof (rpc_int32);
+ */
+ }
+ }
+ return (TRUE);
+ }
+ }
+ if (
+ xdr_u_int32(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+ (cmsg->rm_direction == CALL) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_prog)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_vers)) &&
+ xdr_u_int32(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/src/lib/rpc/rpc_commondata.c b/src/lib/rpc/rpc_commondata.c
new file mode 100644
index 0000000..75cead0
--- /dev/null
+++ b/src/lib/rpc/rpc_commondata.c
@@ -0,0 +1,41 @@
+/* @(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#include <rpc/rpc.h>
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces
+ */
+struct opaque_auth _null_auth;
+#ifdef FD_SETSIZE
+fd_set svc_fdset;
+#else
+int svc_fds;
+#endif /* def FD_SETSIZE */
+struct rpc_createerr rpc_createerr;
diff --git a/src/lib/rpc/rpc_dtablesize.c b/src/lib/rpc/rpc_dtablesize.c
new file mode 100644
index 0000000..d252d6a
--- /dev/null
+++ b/src/lib/rpc/rpc_dtablesize.c
@@ -0,0 +1,60 @@
+/* @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+#endif
+
+#include <unistd.h>
+
+/*
+ * 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) {
+#ifdef _SC_OPEN_MAX
+ size = (int) sysconf(_SC_OPEN_MAX);
+#else
+ size = getdtablesize();
+#endif
+
+/* sysconf() can return a number larger than what will fit in an
+ fd_set. we can't use fd's larger than this, anyway. */
+
+#ifdef FD_SETSIZE
+ if (size >= FD_SETSIZE)
+ size = FD_SETSIZE-1;
+#endif
+ }
+ return (size);
+}
diff --git a/src/lib/rpc/rpc_msg.h b/src/lib/rpc/rpc_msg.h
new file mode 100644
index 0000000..66b10c5
--- /dev/null
+++ b/src/lib/rpc/rpc_msg.h
@@ -0,0 +1,187 @@
+/* @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)rpc_msg.h 1.7 86/07/16 SMI */
+
+/*
+ * rpc_msg.h
+ * rpc message definition
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#define RPC_MSG_VERSION ((rpc_u_int32) 2)
+#define RPC_SERVICE_PORT ((unsigned 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 {
+ rpc_u_int32 low;
+ rpc_u_int32 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 {
+ rpc_u_int32 low;
+ rpc_u_int32 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 {
+ rpc_u_int32 cb_rpcvers; /* must be equal to two */
+ rpc_u_int32 cb_prog;
+ rpc_u_int32 cb_vers;
+ rpc_u_int32 cb_proc;
+ struct opaque_auth cb_cred;
+ struct opaque_auth cb_verf; /* protocol specific - provided by client */
+};
+
+/*
+ * The rpc message
+ */
+struct rpc_msg {
+ rpc_u_int32 rm_xid;
+ enum msg_type rm_direction;
+ union {
+ struct call_body RM_cmb;
+ struct reply_body RM_rmb;
+ } ru;
+#define rm_call ru.RM_cmb
+#define rm_reply ru.RM_rmb
+};
+#define acpted_rply ru.RM_rmb.ru.RP_ar
+#define rjcted_rply ru.RM_rmb.ru.RP_dr
+
+
+/*
+ * XDR routine to handle a rpc message.
+ * xdr_callmsg(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callmsg();
+
+/*
+ * XDR routine to pre-serialize the static part of a rpc message.
+ * xdr_callhdr(xdrs, cmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *cmsg;
+ */
+extern bool_t xdr_callhdr();
+
+/*
+ * XDR routine to handle a rpc reply.
+ * xdr_replymsg(xdrs, rmsg)
+ * XDR *xdrs;
+ * struct rpc_msg *rmsg;
+ */
+extern bool_t xdr_replymsg();
+
+/*
+ * Fills in the error part of a reply message.
+ * _seterr_reply(msg, error)
+ * struct rpc_msg *msg;
+ * struct rpc_err *error;
+ */
+extern void _seterr_reply();
diff --git a/src/lib/rpc/rpc_prot.c b/src/lib/rpc/rpc_prot.c
new file mode 100644
index 0000000..6fea605
--- /dev/null
+++ b/src/lib/rpc/rpc_prot.c
@@ -0,0 +1,287 @@
+/* @(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include <sys/param.h>
+
+#include <rpc/rpc.h>
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+/*
+ * 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_int32(xdrs, &(ar->ar_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32(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_int32(xdrs, &(rr->rj_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32(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_int32(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_int32(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ xdr_u_int32(xdrs, &(cmsg->rm_call.cb_prog)) )
+ return (xdr_u_int32(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 = (rpc_int32)MSG_ACCEPTED;
+ error->re_lb.s2 = (rpc_int32)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 = (rpc_int32)MSG_DENIED;
+ error->re_lb.s2 = (rpc_int32)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+sunrpc_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 = (rpc_int32)(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/src/lib/rpc/svc.c b/src/lib/rpc/svc.c
new file mode 100644
index 0000000..cb4d877
--- /dev/null
+++ b/src/lib/rpc/svc.c
@@ -0,0 +1,492 @@
+/* @(#)svc.c 2.4 88/08/11 4.0 RPCSRC; from 1.44 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc.c 1.41 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here. The xprt routines are
+ * for handling transport handles. The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <sys/errno.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <stdio.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;
+ rpc_u_int32 sc_prog;
+ rpc_u_int32 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;
+ rpc_u_int32 prog;
+ rpc_u_int32 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)
+ rpc_u_int32 prog;
+ rpc_u_int32 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, (unsigned 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)
+ rpc_u_int32 prog;
+ rpc_u_int32 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;
+ rpc_u_int32 low_vers;
+ rpc_u_int32 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;
+ rpc_u_int32 low_vers;
+ rpc_u_int32 high_vers;
+ struct svc_req r;
+ register SVCXPRT *xprt;
+ rpc_u_int32 mask;
+ int bit;
+ rpc_u_int32 *maskp;
+ register int setsize;
+ register int sock;
+ bool_t no_dispatch;
+
+ 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 = (rpc_u_int32 *)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;
+
+ /* in case _authenticate has been replaced
+ with an old-style version */
+ r.rq_xprt->xp_auth = &svc_auth_any;
+ no_dispatch = FALSE;
+
+ /* first authenticate the message */
+ why=_authenticate(&r, &msg, &no_dispatch);
+ if (why != AUTH_OK) {
+ svcerr_auth(xprt, why);
+ goto call_done;
+ } else if (no_dispatch) {
+ 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/src/lib/rpc/svc.h b/src/lib/rpc/svc.h
new file mode 100644
index 0000000..2114d62
--- /dev/null
+++ b/src/lib/rpc/svc.h
@@ -0,0 +1,298 @@
+/* @(#)svc.h 2.2 88/07/29 4.0 RPCSRC; from 1.20 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * svc.h, Server-side remote procedure call interface.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __SVC_HEADER__
+#define __SVC_HEADER__
+
+/*
+ * 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;
+ unsigned 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 */
+ SVCAUTH *xp_auth; /* auth flavor of current req */
+ 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_GETARGS_REQ(xprt, req, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (xargs), (argsp))
+#define svc_getargs_req(xprt, req, xargs, argsp) \
+ (*(xprt)->xp_ops->xp_getargs_req)((xprt), (req), (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_REPLY_REQ(xprt, req, msg) \
+ (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (msg))
+#define svc_reply_req(xprt, msg) \
+ (*(xprt)->xp_ops->xp_reply_req) ((xprt), (req), (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 {
+ rpc_u_int32 rq_prog; /* service program number */
+ rpc_u_int32 rq_vers; /* service protocol version */
+ rpc_u_int32 rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ caddr_t rq_clntcred; /* read only cooked client cred */
+ caddr_t rq_svccred; /* read only cooked svc cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+
+ /* The request's auth flavor *should* be here, but the svc_req */
+ /* isn't passed around everywhere it is necessary. The */
+ /* transport *is* passed around, so the auth flavor it stored */
+ /* there. This means that the transport must be single */
+ /* threaded, but other parts of SunRPC already require that. */
+ /*SVCAUTH *rq_auth; associated auth flavor */
+};
+
+
+/*
+ * Service registration
+ *
+ * svc_register(xprt, prog, vers, dispatch, protocol)
+ * SVCXPRT *xprt;
+ * rpc_u_int32 prog;
+ * rpc_u_int32 vers;
+ * void (*dispatch)();
+ * int protocol; like TCP or UDP, zero means do not register
+ */
+extern bool_t svc_register();
+
+/*
+ * Service un-registration
+ *
+ * svc_unregister(prog, vers)
+ * rpc_u_int32 prog;
+ * rpc_u_int32 vers;
+ */
+extern void svc_unregister();
+
+/*
+ * Transport registration.
+ *
+ * xprt_register(xprt)
+ * SVCXPRT *xprt;
+ */
+extern void xprt_register();
+
+/*
+ * Transport un-register
+ *
+ * xprt_unregister(xprt)
+ * SVCXPRT *xprt;
+ */
+extern void xprt_unregister();
+
+
+
+
+/*
+ * 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 or the new SVC_GETARGS_REQ (both 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 or the new svc_sendreply_req.
+ *
+ * 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!
+ */
+
+extern bool_t svc_sendreply();
+extern void svcerr_decode();
+extern void svcerr_weakauth();
+extern void svcerr_noproc();
+extern void svcerr_progvers();
+extern void svcerr_auth();
+extern void svcerr_noprog();
+extern void svcerr_systemerr();
+
+/*
+ * 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();
+
+extern void svc_getreq();
+extern void svc_getreqset(); /* takes fdset instead of int */
+extern void svc_run(); /* never returns */
+
+/*
+ * 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.
+ */
+extern SVCXPRT *svcraw_create();
+
+/*
+ * Udp based rpc.
+ */
+extern SVCXPRT *svcudp_create();
+extern SVCXPRT *svcudp_bufcreate();
+
+/*
+ * Tcp based rpc.
+ */
+extern SVCXPRT *svctcp_create();
+
+#endif /* !__SVC_HEADER__ */
diff --git a/src/lib/rpc/svc_auth.c b/src/lib/rpc/svc_auth.c
new file mode 100644
index 0000000..281d7cb
--- /dev/null
+++ b/src/lib/rpc/svc_auth.c
@@ -0,0 +1,119 @@
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth.c 2.1 88/08/07 4.0 RPCSRC; from 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+/*
+ * 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
+ */
+
+/*
+ * svc_auth_nodes.c, Server-side rpc authenticator interface,
+ * *WITHOUT* DES authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include <rpc/rpc.h>
+
+/*
+ * 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 */
+enum auth_stat _svcauth_gssapi(); /* GSS-API style */
+
+static struct svcauthsw_type {
+ unsigned int flavor;
+ enum auth_stat (*authenticator)();
+} svcauthsw[] = {
+ AUTH_GSSAPI, _svcauth_gssapi, /* AUTH_GSSAPI */
+ AUTH_NONE, _svcauth_null, /* AUTH_NULL */
+ AUTH_GSSAPI_COMPAT, _svcauth_gssapi, /* AUTH_GSSAPI_COMPAT */
+ AUTH_UNIX, _svcauth_unix, /* AUTH_UNIX */
+ AUTH_SHORT, _svcauth_short, /* AUTH_SHORT */
+};
+static int svcauthnum = sizeof(svcauthsw) / sizeof(struct svcauthsw_type);
+
+/*
+ * 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.
+ */
+enum auth_stat
+_authenticate(rqst, msg, no_dispatch)
+ register struct svc_req *rqst;
+ struct rpc_msg *msg;
+ bool_t *no_dispatch;
+{
+ register int cred_flavor, i;
+
+ 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;
+ *no_dispatch = FALSE;
+ for (i = 0; i < svcauthnum; i++) {
+ if (cred_flavor == svcauthsw[i].flavor &&
+ svcauthsw[i].authenticator != NULL) {
+ return ((*(svcauthsw[i].authenticator))(rqst,
+ msg,
+ no_dispatch));
+ }
+ }
+
+ return (AUTH_REJECTEDCRED);
+}
+
+enum auth_stat
+_svcauth_null(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+ return (AUTH_OK);
+}
diff --git a/src/lib/rpc/svc_auth.h b/src/lib/rpc/svc_auth.h
new file mode 100644
index 0000000..4d59631
--- /dev/null
+++ b/src/lib/rpc/svc_auth.h
@@ -0,0 +1,61 @@
+/* @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)svc_auth.h 1.6 86/07/16 SMI */
+
+/*
+ * svc_auth.h, Service side of rpc authentication.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+/*
+ * Interface to server-side authentication flavors.
+ */
+typedef struct {
+ struct svc_auth_ops {
+ int (*svc_ah_wrap)();
+ int (*svc_ah_unwrap)();
+ } *svc_ah_ops;
+ caddr_t svc_ah_private;
+} SVCAUTH;
+
+extern SVCAUTH svc_auth_any;
+
+/*
+ * Server side authenticator
+ */
+extern enum auth_stat _authenticate();
+
+#define SVCAUTH_WRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, xdrs, xfunc, xwhere))
+#define SVCAUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \
+ ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, xdrs, xfunc, xwhere))
+
+
diff --git a/src/lib/rpc/svc_auth_any.c b/src/lib/rpc/svc_auth_any.c
new file mode 100644
index 0000000..2f0a66d
--- /dev/null
+++ b/src/lib/rpc/svc_auth_any.c
@@ -0,0 +1,22 @@
+/*
+ * svc_auth_any.c
+ * Provides default service-side functions for authentication flavors
+ * that do not use all the fields in struct svc_auth_ops.
+ *
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ */
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+
+extern int authany_wrap();
+
+struct svc_auth_ops svc_auth_any_ops = {
+ authany_wrap,
+ authany_wrap,
+};
+
+SVCAUTH svc_auth_any = {
+ &svc_auth_any_ops,
+ NULL,
+};
diff --git a/src/lib/rpc/svc_auth_gssapi.c b/src/lib/rpc/svc_auth_gssapi.c
new file mode 100644
index 0000000..07cf59a
--- /dev/null
+++ b/src/lib/rpc/svc_auth_gssapi.c
@@ -0,0 +1,1181 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.37 1996/07/22 20:41:00 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.36.4.1 1996/07/18 04:19:34 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.36.2.1 1996/06/20 23:39:22 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.36 1996/05/30 19:25:02 bjaspan
+ * zero bindings structure before using it
+ *
+ * Revision 1.35 1996/05/12 06:17:25 marc
+ * changed around the file includes, since krb5 has changed some.
+ *
+ * added conditionalization GSS_BACKWARD_HACK until and if this hack is
+ * reimplemented in the newly merged gssapi.
+ *
+ * conditionalize out the host-specific cruft for setting the local
+ * address to INADDR_ANY, since you can just assign it that way on all
+ * platforms I know of.
+ *
+ * Revision 1.34 1996/02/12 15:14:00 grier
+ * [secure/3570]
+ * restore (struct sockaddr *) cast that got mangled
+ *
+ * Revision 1.33 1996/02/07 13:09:52 jik
+ * Actually, I should have used krb5_error_code, not krb5_int32.
+ *
+ * Revision 1.32 1996/02/07 13:08:31 jik
+ * Include <krb5/krb5.h> to get the krb5_int32 typedef, which we then use
+ * in a cast when checking if the GSS-API minor status value is equal to
+ * a krb5 error code.
+ *
+ * Revision 1.31 1996/02/01 18:29:29 grier
+ * Restore use of error code definition.
+ * Return original code structure.
+ *
+ * Revision 1.30 1996/01/31 19:15:49 grier
+ * [secure/3570]
+ * Remove (void *) casts to memcpy() args
+ *
+ * Revision 1.29 1996/01/25 03:58:04 grier
+ * Remove debug code
+ *
+ * Revision 1.28 1996/01/25 03:56:50 grier
+ * secure/3570 - missed Alpha checkin
+ *
+ * Revision 1.26 1995/11/07 23:17:23 grier
+ * memcpy() cast
+ *
+ * Revision 1.25 1995/08/24 21:05:48 bjaspan
+ * set acceptor channel bindings
+ *
+ * Revision 1.24 1995/08/23 20:28:02 bjaspan
+ * [secure-rpc/3392] add channel bindinds to the rpc
+ *
+ * Revision 1.23 1995/07/10 18:49:22 bjaspan
+ * [secure-build/3377] remove use of BSD db
+ *
+ * Revision 1.22 1995/05/25 18:35:53 bjaspan
+ * [secure-rpc/3103] log misc errors from RPC
+ *
+ * Revision 1.21 1995/05/24 17:34:03 bjaspan
+ * [secure-rpc/3302] don't allow client to make server exit unless
+ * debugging is enabled
+ *
+ * Revision 1.20 1995/05/08 22:32:44 marc
+ * if a new client is in use, set the krb5 gssapi mech into
+ * backward-compatibility mode.
+ *
+ * Revision 1.19 1994/10/27 12:38:51 jik
+ * [secure-rpc/2808: add credential versioning]
+ *
+ * Sandbox:
+ *
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.22 1994/10/26 20:03:27 bjaspan
+ * [secure-rpc/2808] add version field to client creds
+ *
+ * Revision 1.21 1994/05/23 01:26:01 bjaspan
+ * [secure-rpc/1911] set rq_svccred to the context instead of the service
+ * gss name
+ *
+ * Revision 1.20 1994/05/09 17:48:39 shanzer
+ * change sys/fcntl.h to fcntl.h
+ *
+ * Revision 1.19 1994/04/08 17:21:32 bjaspan
+ * remove KRB5KTNAME hack
+ *
+ * Revision 1.18 1994/03/18 15:48:13 shanzer
+ * include sys/fcntl.h
+ *
+ * Revision 1.17 1994/03/08 00:05:56 shanzer
+ * call rand() instead random()
+ *
+ * Revision 1.16 1993/12/08 21:43:54 bjaspan
+ * gss_delete_sec_context failure is not fatal (in fact, the context
+ * will often be expired); use AUTH_GSSAPI_DISPLAY_STATUS macro
+ *
+ * Revision 1.15 1993/12/08 20:20:08 bjaspan
+ * add debugging info to expire_client, correct comment above btree->put
+ *
+ * Revision 1.14 1993/12/08 06:52:49 bjaspan
+ * *many* debugging improvements to help find secure-rpc/586, and (I hope)
+ * the fix: don't change client_data->expiration without deleting it
+ * and reinserting it into the btree
+ *
+ * Revision 1.13 1993/12/06 21:22:26 bjaspan
+ * debugging levels, #ifdef PURIFY, call abort() on impossible failures
+ *
+ * Revision 1.12 1993/11/12 02:33:14 bjaspan
+ * add badauth
+ * /
+ *
+ * Revision 1.11 1993/11/03 23:46:15 bjaspan
+ * new log_badverf format
+ *
+ * Revision 1.10 1993/11/03 21:23:30 bjaspan
+ * handle GSS_C_INDEFINITE expiration, add log_badverf, set rq_svccred
+ *
+ * Revision 1.9 1993/11/03 01:30:36 bjaspan
+ * don't include gssapi_krb5.h, it isn't needed
+ *
+ * Revision 1.8 1993/11/02 22:09:02 bjaspan
+ * support multiple service-side names via _svcauth_gssapi_set_names
+ *
+ * Revision 1.7 1993/11/01 19:56:22 bjaspan
+ * unstatic svc_debug_gssapi, and send gss_{major,minor} back if
+ * accept_sec_context fails
+ *
+ * Revision 1.6 1993/10/28 22:09:58 bjaspan
+ * fix verifier mem leak, clean_clients() first to avoid dangling ref,
+ * only include hacked kt_default_name if DEBUG_GSSAPI defined
+ *
+ * Revision 1.5 1993/10/27 18:26:51 bjaspan
+ * use xdr_free instead of gss_release_buffer; this fixes memory leaks
+ * that were probably caused by zero-length seal/unseal tokens
+ *
+ * Revision 1.4 1993/10/26 21:12:51 bjaspan
+ * fully working
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+/*
+ * svc_auth_gssapi.c
+ * Handles the GSS-API flavor authentication parameters on the service
+ * side of RPC.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+
+#include <gssapi/gssapi_generic.h>
+#include <rpc/auth_gssapi.h>
+
+#ifdef GSS_BACKWARD_HACK
+#include <gssapi/gssapi_krb5.h>
+#endif
+
+/* This is here for the krb5_error_code typedef and the
+ KRB5KRB_AP_WRONG_PRINC #define.*/
+#include <krb5.h>
+
+#include <sys/file.h>
+#include <fcntl.h>
+
+#define INITIATION_TIMEOUT 60*15 /* seconds until partially created */
+ /* context is destroed */
+#define INDEF_EXPIRE 60*60*24 /* seconds until an context with no */
+ /* expiration time is expired */
+
+#ifdef __CODECENTER__
+#define DEBUG_GSSAPI 1
+#endif
+
+#ifdef DEBUG_GSSAPI
+int svc_debug_gssapi = DEBUG_GSSAPI;
+#define L_PRINTF(l,args) if (svc_debug_gssapi >= l) printf args
+#define PRINTF(args) L_PRINTF(99, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args) \
+ if (svc_debug_gssapi) auth_gssapi_display_status args
+#else
+#define PRINTF(args)
+#define L_PRINTF(l, args)
+#define AUTH_GSSAPI_DISPLAY_STATUS(args)
+#endif
+
+typedef struct _svc_auth_gssapi_data {
+ bool_t established;
+
+ gss_ctx_id_t context;
+ gss_name_t client_name, server_name;
+ gss_cred_id_t server_creds;
+
+ rpc_u_int32 expiration;
+ rpc_u_int32 seq_num;
+ rpc_u_int32 key;
+
+ SVCAUTH svcauth;
+
+ /* kludge to free verifiers on next call */
+ gss_buffer_desc prev_verf;
+} svc_auth_gssapi_data;
+
+#define SVCAUTH_PRIVATE(auth) \
+ ((svc_auth_gssapi_data *)(auth)->svc_ah_private)
+
+static bool_t svc_auth_gssapi_wrap();
+static bool_t svc_auth_gssapi_unwrap();
+static svc_auth_gssapi_data *create_client();
+static svc_auth_gssapi_data *get_client(gss_buffer_t client_handle);
+static void destroy_client(svc_auth_gssapi_data *client_data);
+static void clean_client(), cleanup();
+static void client_expire(svc_auth_gssapi_data *client_data, rpc_u_int32 exp);
+static void dump_db(char *msg);
+
+struct svc_auth_ops svc_auth_gssapi_ops = {
+ svc_auth_gssapi_wrap,
+ svc_auth_gssapi_unwrap,
+};
+
+/*
+ * Globals! Eeek! Run for the hills!
+ */
+static gss_cred_id_t *server_creds_list = NULL;
+static gss_name_t *server_name_list = NULL;
+static int server_creds_count = 0;
+
+static auth_gssapi_log_badauth_func log_badauth = NULL;
+static caddr_t log_badauth_data = NULL;
+static auth_gssapi_log_badverf_func log_badverf = NULL;
+static caddr_t log_badverf_data = NULL;
+static auth_gssapi_log_miscerr_func log_miscerr = NULL;
+static caddr_t log_miscerr_data = NULL;
+
+#define LOG_MISCERR(arg) if (log_miscerr) \
+ (*log_miscerr)(rqst, msg, arg, log_miscerr_data)
+
+typedef struct _client_list {
+ svc_auth_gssapi_data *client;
+ struct _client_list *next;
+} client_list;
+
+static client_list *clients = NULL;
+
+extern int errno;
+
+enum auth_stat _svcauth_gssapi(rqst, msg, no_dispatch)
+ register struct svc_req *rqst;
+ register struct rpc_msg *msg;
+ bool_t *no_dispatch;
+{
+ XDR xdrs;
+ auth_gssapi_creds creds;
+ auth_gssapi_init_arg call_arg;
+ auth_gssapi_init_res call_res;
+ gss_buffer_desc output_token, in_buf, out_buf;
+ gss_cred_id_t server_creds;
+ struct gss_channel_bindings_struct bindings, *bindp;
+ struct sockaddr_in sockname;
+ OM_uint32 gssstat, minor_stat, time_rec;
+ struct opaque_auth *cred, *verf;
+ svc_auth_gssapi_data *client_data;
+ int ret_flags, ret, i;
+ rpc_u_int32 seq_num;
+ int flag;
+
+ PRINTF(("svcauth_gssapi: starting\n"));
+
+ /* clean up expired entries */
+ clean_client();
+
+ /* use AUTH_NONE until there is a client_handle */
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+
+ memset((char *) &call_res, 0, sizeof(call_res));
+
+ cred = &msg->rm_call.cb_cred;
+ verf = &msg->rm_call.cb_verf;
+
+ if (cred->oa_length == 0) {
+ PRINTF(("svcauth_gssapi: empty creds, failing\n"));
+ LOG_MISCERR("empty client credentials");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: decoding credentials\n"));
+ xdrmem_create(&xdrs, cred->oa_base, cred->oa_length, XDR_DECODE);
+ memset((char *) &creds, 0, sizeof(creds));
+ if (! xdr_authgssapi_creds(&xdrs, &creds)) {
+ PRINTF(("svcauth_gssapi: failed decoding creds\n"));
+ LOG_MISCERR("protocol error in client credentials");
+ XDR_DESTROY(&xdrs);
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+ XDR_DESTROY(&xdrs);
+
+ PRINTF(("svcauth_gssapi: got credentials, version %d, "
+ "client_handle len %d\n", creds.version,
+ creds.client_handle.length));
+
+ if (creds.version != 2) {
+ PRINTF(("svcauth_gssapi: bad credential version\n"));
+ LOG_MISCERR("unsupported client credentials version");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+#ifdef DEBUG_GSSAPI
+ if (svc_debug_gssapi) {
+ if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_EXIT) {
+ PRINTF(("svcauth_gssapi: GSSAPI_EXIT, cleaning up\n"));
+ svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+ xdr_free(xdr_authgssapi_creds, &creds);
+ cleanup();
+ exit(0);
+ }
+ }
+#endif
+
+ /*
+ * If this is an auth_msg and proc is GSSAPI_INIT, then create a
+ * client handle for this client. Otherwise, look up the
+ * existing handle.
+ */
+ if (creds.auth_msg && rqst->rq_proc == AUTH_GSSAPI_INIT) {
+ if (creds.client_handle.length != 0) {
+ PRINTF(("svcauth_gssapi: non-empty handle on GSSAPI_INIT\n"));
+ LOG_MISCERR("protocol error in client handle");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: GSSAPI_INIT, creating client.\n"));
+
+ client_data = create_client();
+ if (client_data == NULL) {
+ PRINTF(("svcauth_gssapi: create_client failed\n"));
+ LOG_MISCERR("internal error creating client record");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+ } else {
+ if (creds.client_handle.length == 0) {
+ PRINTF(("svcauth_gssapi: expected non-empty creds\n"));
+ LOG_MISCERR("protocol error in client credentials");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: incoming client_handle %d, len %d\n",
+ *((rpc_u_int32 *) creds.client_handle.value),
+ creds.client_handle.length));
+
+ client_data = get_client(&creds.client_handle);
+ if (client_data == NULL) {
+ PRINTF(("svcauth_gssapi: client_handle lookup failed\n"));
+ LOG_MISCERR("invalid client handle received");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+ PRINTF(("svcauth_gssapi: client_handle lookup succeeded\n"));
+ }
+
+ /* any response we send will use client_handle, so set it now */
+ call_res.client_handle.length = sizeof(client_data->key);
+ call_res.client_handle.value = (char *) &client_data->key;
+
+ /* mark this call as using AUTH_GSSAPI via client_data's SVCAUTH */
+ rqst->rq_xprt->xp_auth = &client_data->svcauth;
+
+ if (client_data->established == FALSE) {
+ PRINTF(("svcauth_gssapi: context is not established\n"));
+
+ if (creds.auth_msg == FALSE) {
+ PRINTF(("svcauth_gssapi: expected auth_msg TRUE\n"));
+ LOG_MISCERR("protocol error on incomplete connection");
+ ret = AUTH_REJECTEDCRED;
+ goto error;
+ }
+
+ /*
+ * If the context is not established, then only GSSAPI_INIT
+ * and _CONTINUE requests are valid.
+ */
+ if (rqst->rq_proc != AUTH_GSSAPI_INIT && rqst->rq_proc !=
+ AUTH_GSSAPI_CONTINUE_INIT) {
+ PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
+ rqst->rq_proc));
+ LOG_MISCERR("protocol error on incomplete connection");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ /* call is for us, deserialize arguments */
+ memset(&call_arg, 0, sizeof(call_arg));
+ if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
+ &call_arg)) {
+ PRINTF(("svcauth_gssapi: cannot decode args\n"));
+ LOG_MISCERR("protocol error in procedure arguments");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+ /*
+ * Process the call arg version number.
+ *
+ * Set the krb5_gss backwards-compatibility mode based on client
+ * version. This controls whether the AP_REP message is
+ * encrypted with the session key (version 2+, correct) or the
+ * session subkey (version 1, incorrect). This function can
+ * never fail, so we don't bother checking its return value.
+ */
+ switch (call_arg.version) {
+ case 1:
+ case 2:
+ LOG_MISCERR("Warning: Accepted old RPC protocol request");
+ call_res.version = 1;
+ break;
+ case 3:
+ call_res.version = call_arg.version;
+ break;
+ default:
+ PRINTF(("svcauth_gssapi: bad GSSAPI_INIT version\n"));
+ LOG_MISCERR("unsupported GSSAPI_INIT version");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+#ifdef GSS_BACKWARD_HACK
+ krb5_gss_set_backward_mode(&minor_stat, call_arg.version == 1);
+#endif
+
+ if (call_arg.version == 3) {
+ int len;
+
+ memset(&bindings, 0, sizeof(bindings));
+ bindings.application_data.length = 0;
+ bindings.initiator_addrtype = GSS_C_AF_INET;
+ bindings.initiator_address.length = 4;
+ bindings.initiator_address.value =
+ &svc_getcaller(rqst->rq_xprt)->sin_addr.s_addr;
+
+ len = sizeof(sockname);
+ if (getsockname(rqst->rq_xprt->xp_sock,
+ (struct sockaddr *) &sockname, &len) < 0) {
+ LOG_MISCERR("cannot get local address");
+ PRINTF(("svcauth_gssapi: errno %d while getting address",
+ errno));
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ bindings.acceptor_addrtype = GSS_C_AF_INET;
+ bindings.acceptor_address.length = 4;
+ bindings.acceptor_address.value = &sockname.sin_addr.s_addr;
+
+ bindp = &bindings;
+ } else {
+ bindp = GSS_C_NO_CHANNEL_BINDINGS;
+ }
+
+ /*
+ * If the client's server_creds is already set, use it.
+ * Otherwise, try each credential in server_creds_list until
+ * one of them succeedes, then set the client server_creds
+ * to that. If all fail, the client's server_creds isn't
+ * set (which is fine, because the client will be gc'ed
+ * anyway).
+ *
+ * If accept_sec_context returns something other than
+ * success and GSS_S_FAILURE, then assume different
+ * credentials won't help and stop looping.
+ *
+ * Note that there are really two cases here: (1) the client
+ * has a server_creds already, and (2) it does not. They
+ * are both written in the same loop so that there is only
+ * one textual call to gss_accept_sec_context; in fact, in
+ * case (1), the loop is executed exactly once.
+ */
+ for (i = 0; i < server_creds_count; i++) {
+ if (client_data->server_creds != NULL) {
+ PRINTF(("svcauth_gssapi: using's clients server_creds\n"));
+ server_creds = client_data->server_creds;
+ } else {
+ PRINTF(("svcauth_gssapi: trying creds %d\n", i));
+ server_creds = server_creds_list[i];
+ }
+
+ call_res.gss_major =
+ gss_accept_sec_context(&call_res.gss_minor,
+ &client_data->context,
+ server_creds,
+ &call_arg.token,
+ bindp,
+ &client_data->client_name,
+ NULL,
+ &output_token,
+ &ret_flags,
+ &time_rec,
+ NULL);
+
+ if (server_creds == client_data->server_creds)
+ break;
+
+ if (call_res.gss_major == GSS_S_COMPLETE ||
+ call_res.gss_major == GSS_S_CONTINUE_NEEDED) {
+ /* server_creds was right, set it! */
+ PRINTF(("svcauth_gssapi: creds are correct, storing\n"));
+ client_data->server_creds = server_creds;
+ client_data->server_name = server_name_list[i];
+ break;
+ } else if (call_res.gss_major != GSS_S_FAILURE ||
+ /*
+ * XXX hard-coded because there is no other
+ * way to prevent all GSS_S_FAILURES from
+ * returning a "wrong principal in request"
+ * error
+ */
+ ((krb5_error_code) call_res.gss_minor !=
+ (krb5_error_code) KRB5KRB_AP_WRONG_PRINC)) {
+ break;
+ }
+ }
+
+ gssstat = call_res.gss_major;
+ minor_stat = call_res.gss_minor;
+
+ /* done with call args */
+ xdr_free(xdr_authgssapi_init_arg, &call_arg);
+
+ PRINTF(("svcauth_gssapi: accept_sec_context returned %#x\n",
+ call_res.gss_major));
+ if (call_res.gss_major != GSS_S_COMPLETE &&
+ call_res.gss_major != GSS_S_CONTINUE_NEEDED) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("accepting context",
+ call_res.gss_major,
+ call_res.gss_minor));
+
+ if (log_badauth != NULL)
+ (*log_badauth)(call_res.gss_major,
+ call_res.gss_minor,
+ &rqst->rq_xprt->xp_raddr,
+ log_badauth_data);
+
+ svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
+ (caddr_t) &call_res);
+ *no_dispatch = TRUE;
+ ret = AUTH_OK;
+ goto error;
+ }
+
+ if (output_token.length != 0) {
+ PRINTF(("svcauth_gssapi: got new output token\n"));
+ GSS_COPY_BUFFER(call_res.token, output_token);
+ }
+
+ if (gssstat == GSS_S_COMPLETE) {
+ client_data->seq_num = rand();
+ client_expire(client_data,
+ (time_rec == GSS_C_INDEFINITE ?
+ INDEF_EXPIRE : time_rec) + time(0));
+
+ PRINTF(("svcauth_gssapi: context established, isn %d\n",
+ client_data->seq_num));
+
+ if (auth_gssapi_seal_seq(client_data->context,
+ client_data->seq_num,
+ &call_res.signed_isn) ==
+ FALSE) {
+ ret = AUTH_FAILED;
+ LOG_MISCERR("internal error sealing sequence number");
+ goto error;
+ }
+ }
+
+ PRINTF(("svcauth_gssapi: sending reply\n"));
+ svc_sendreply(rqst->rq_xprt, xdr_authgssapi_init_res,
+ (caddr_t) &call_res);
+ *no_dispatch = TRUE;
+
+ /*
+ * If appropriate, set established to TRUE *after* sending
+ * response (otherwise, the client will receive the final
+ * token encrypted)
+ */
+ if (gssstat == GSS_S_COMPLETE) {
+ gss_release_buffer(&minor_stat, &call_res.signed_isn);
+ client_data->established = TRUE;
+ }
+ gss_release_buffer(&minor_stat, &output_token);
+ } else {
+ PRINTF(("svcauth_gssapi: context is established\n"));
+
+ /* check the verifier */
+ PRINTF(("svcauth_gssapi: checking verifier, len %d\n",
+ verf->oa_length));
+
+ in_buf.length = verf->oa_length;
+ in_buf.value = verf->oa_base;
+
+ if (auth_gssapi_unseal_seq(client_data->context, &in_buf,
+ &seq_num) == FALSE) {
+ ret = AUTH_BADVERF;
+ LOG_MISCERR("internal error unsealing sequence number");
+ goto error;
+ }
+
+ if (seq_num != client_data->seq_num + 1) {
+ PRINTF(("svcauth_gssapi: expected isn %d, got %d\n",
+ client_data->seq_num + 1, seq_num));
+ if (log_badverf != NULL)
+ (*log_badverf)(client_data->client_name,
+ client_data->server_name,
+ rqst, msg, log_badverf_data);
+
+ ret = AUTH_REJECTEDVERF;
+ goto error;
+ }
+ client_data->seq_num++;
+
+ PRINTF(("svcauth_gssapi: seq_num %d okay\n", seq_num));
+
+ /* free previous response verifier, if any */
+ if (client_data->prev_verf.length != 0) {
+ gss_release_buffer(&minor_stat, &client_data->prev_verf);
+ client_data->prev_verf.length = 0;
+ }
+
+ /* prepare response verifier */
+ seq_num = client_data->seq_num + 1;
+ if (auth_gssapi_seal_seq(client_data->context, seq_num,
+ &out_buf) == FALSE) {
+ ret = AUTH_FAILED;
+ LOG_MISCERR("internal error sealing sequence number");
+ goto error;
+ }
+
+ client_data->seq_num++;
+
+ PRINTF(("svcauth_gssapi; response seq_num %d\n", seq_num));
+
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_GSSAPI;
+ rqst->rq_xprt->xp_verf.oa_base = out_buf.value;
+ rqst->rq_xprt->xp_verf.oa_length = out_buf.length;
+
+ /* save verifier so it can be freed next time */
+ client_data->prev_verf.value = out_buf.value;
+ client_data->prev_verf.length = out_buf.length;
+
+ /*
+ * Message is authentic. If auth_msg if true, process the
+ * call; otherwise, return AUTH_OK so it will be dispatched
+ * to the application server.
+ */
+
+ if (creds.auth_msg == TRUE) {
+ /*
+ * If process_token fails, then the token probably came
+ * from an attacker. No response (error or otherwise)
+ * should be returned to the client, since it won't be
+ * accepting one.
+ */
+
+ switch (rqst->rq_proc) {
+ case AUTH_GSSAPI_MSG:
+ PRINTF(("svcauth_gssapi: GSSAPI_MSG, getting args\n"));
+ memset(&call_arg, 0, sizeof(call_arg));
+ if (! svc_getargs(rqst->rq_xprt, xdr_authgssapi_init_arg,
+ &call_arg)) {
+ PRINTF(("svcauth_gssapi: cannot decode args\n"));
+ LOG_MISCERR("protocol error in call arguments");
+ ret = AUTH_BADCRED;
+ goto error;
+ }
+
+ PRINTF(("svcauth_gssapi: processing token\n"));
+ gssstat = gss_process_context_token(&minor_stat,
+ client_data->context,
+ &call_arg.token);
+
+ /* done with call args */
+ xdr_free(xdr_authgssapi_init_arg, &call_arg);
+
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("processing token",
+ gssstat, minor_stat));
+ ret = AUTH_FAILED;
+ goto error;
+ }
+
+ svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+ *no_dispatch = TRUE;
+ break;
+
+ case AUTH_GSSAPI_DESTROY:
+ PRINTF(("svcauth_gssapi: GSSAPI_DESTROY\n"));
+
+ PRINTF(("svcauth_gssapi: sending reply\n"));
+ svc_sendreply(rqst->rq_xprt, xdr_void, NULL);
+ *no_dispatch = TRUE;
+
+ destroy_client(client_data);
+ break;
+
+ default:
+ PRINTF(("svcauth_gssapi: unacceptable procedure %d\n",
+ rqst->rq_proc));
+ LOG_MISCERR("invalid call procedure number");
+ ret = AUTH_FAILED;
+ goto error;
+ }
+ } else {
+ /* set credentials for app server; comment in svc.c */
+ /* seems to imply this is incorrect, but I don't see */
+ /* any problem with it... */
+ rqst->rq_clntcred = (char *)client_data->client_name;
+ rqst->rq_svccred = (char *)client_data->context;
+ }
+ }
+
+ if (creds.client_handle.length != 0) {
+ PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
+ creds.client_handle.length));
+ xdr_free(xdr_authgssapi_creds, &creds);
+ }
+
+ PRINTF(("\n"));
+ return AUTH_OK;
+
+error:
+ if (creds.client_handle.length != 0) {
+ PRINTF(("svcauth_gssapi: freeing client_handle len %d\n",
+ creds.client_handle.length));
+ xdr_free(xdr_authgssapi_creds, &creds);
+ }
+
+ PRINTF(("\n"));
+ return ret;
+}
+
+static void cleanup()
+{
+ client_list *c, *c2;
+
+ PRINTF(("cleanup_and_exit: starting\n"));
+
+ c = clients;
+ while (c) {
+ c2 = c;
+ c = c->next;
+ destroy_client(c2->client);
+ free(c2);
+ }
+
+ exit(0);
+}
+
+/*
+ * Function: create_client
+ *
+ * Purpose: Creates an new client_data structure and stores it in the
+ * database.
+ *
+ * Returns: the new client_data structure, or NULL on failure.
+ *
+ * Effects:
+ *
+ * A new client_data is created and stored in the hash table and
+ * b-tree. A new key that is unique in the current database is
+ * chosen; this key should be used as the client's client_handle.
+ */
+static svc_auth_gssapi_data *create_client()
+{
+ client_list *c;
+ svc_auth_gssapi_data *client_data;
+ static int client_key = 1;
+ int ret;
+
+ PRINTF(("svcauth_gssapi: empty creds, creating\n"));
+
+ client_data = (svc_auth_gssapi_data *) malloc(sizeof(*client_data));
+ if (client_data == NULL)
+ return NULL;
+ memset((char *) client_data, 0, sizeof(*client_data));
+ L_PRINTF(2, ("create_client: new client_data = %#x\n", client_data));
+
+ /* set up client data structure */
+ client_data->established = 0;
+ client_data->context = GSS_C_NO_CONTEXT;
+ client_data->expiration = time(0) + INITIATION_TIMEOUT;
+
+ /* set up psycho-recursive SVCAUTH hack */
+ client_data->svcauth.svc_ah_ops = &svc_auth_gssapi_ops;
+ client_data->svcauth.svc_ah_private = (caddr_t) client_data;
+
+ client_data->key = client_key++;
+
+ c = (client_list *) malloc(sizeof(client_list));
+ if (c == NULL)
+ return NULL;
+ c->client = client_data;
+ c->next = NULL;
+
+
+ if (clients == NULL)
+ clients = c;
+ else {
+ c->next = clients;
+ clients = c;
+ }
+
+ PRINTF(("svcauth_gssapi: new handle %d\n", client_data->key));
+ L_PRINTF(2, ("create_client: done\n"));
+
+ return client_data;
+}
+
+/*
+ * Function: client_expire
+ *
+ * Purpose: change the expiration time of a client in the database
+ *
+ * Arguments:
+ *
+ * client_data (r) the client_data to expire
+ * exp (r) the new expiration time
+ *
+ * Effects:
+ *
+ * client_data->expiration = exp
+ *
+ * This function used to remove client_data from the database, change
+ * its expiration time, and re-add it, which was necessary because the
+ * database was sorted by expiration time so a simple modification
+ * would break the rep invariant. Now the database is an unsorted
+ * linked list, so it doesn't matter.
+ */
+static void client_expire(svc_auth_gssapi_data *client_data, rpc_u_int32 exp)
+{
+ client_data->expiration = exp;
+}
+
+/*
+ * Function get_client
+ *
+ * Purpose: retrieve a client_data structure from the database based
+ * on its client handle (key)
+ *
+ * Arguments:
+ *
+ * client_handle (r) the handle (key) to retrieve
+ *
+ * Effects:
+ *
+ * Searches the list and returns the client_data whose key field
+ * matches the contents of client_handle, or returns NULL if none was
+ * found.
+ */
+static svc_auth_gssapi_data *get_client(gss_buffer_t client_handle)
+{
+ client_list *c;
+ rpc_u_int32 handle;
+
+ memcpy(&handle, client_handle->value, 4);
+
+ L_PRINTF(2, ("get_client: looking for client %d\n", handle));
+
+ c = clients;
+ while (c) {
+ if (c->client->key == handle)
+ return c->client;
+ c = c->next;
+ }
+
+ L_PRINTF(2, ("get_client: client_handle lookup failed\n"));
+ return NULL;
+}
+
+/*
+ * Function: destroy_client
+ *
+ * Purpose: destroys a client entry and removes it from the database
+ *
+ * Arguments:
+ *
+ * client_data (r) the client to be destroyed
+ *
+ * Effects:
+ *
+ * client_data->context is deleted with gss_delete_sec_context.
+ * client_data's entry in the database is destroyed. client_data is
+ * freed.
+ */
+static void destroy_client(svc_auth_gssapi_data *client_data)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc out_buf;
+ client_list *c, *c2;
+ int ret;
+
+ PRINTF(("destroy_client: destroying client_data\n"));
+ L_PRINTF(2, ("destroy_client: client_data = %#x\n", client_data));
+
+#ifdef DEBUG_GSSAPI
+ if (svc_debug_gssapi >= 3)
+ dump_db("before frees");
+#endif
+
+ /* destroy client struct even if error occurs */
+
+ gssstat = gss_delete_sec_context(&minor_stat, &client_data->context,
+ &out_buf);
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("deleting context", gssstat,
+ minor_stat));
+
+ gss_release_buffer(&minor_stat, &out_buf);
+ gss_release_name(&minor_stat, &client_data->client_name);
+ if (client_data->prev_verf.length != 0)
+ gss_release_buffer(&minor_stat, &client_data->prev_verf);
+
+ if (clients == NULL) {
+ PRINTF(("destroy_client: called on empty database\n"));
+ abort();
+ } else if (clients->client == client_data) {
+ c = clients;
+ clients = clients->next;
+ free(c);
+ } else {
+ c2 = clients;
+ c = clients->next;
+ while (c) {
+ if (c->client == client_data) {
+ c2->next = c->next;
+ free(c);
+ goto done;
+ } else
+ c = c->next;
+ }
+ PRINTF(("destroy_client: client_handle delete failed\n"));
+ abort();
+ }
+
+done:
+
+ L_PRINTF(2, ("destroy_client: client %d destroyed\n", client_data->key));
+
+ free(client_data);
+
+#ifdef PURIFY
+ purify_watch_n(client_data, sizeof(*client_data), "rw");
+#endif
+}
+
+static void dump_db(char *msg)
+{
+ svc_auth_gssapi_data *client_data;
+ client_list *c;
+
+ L_PRINTF(3, ("dump_db: %s:\n", msg));
+
+ c = clients;
+ while (c) {
+ client_data = c->client;
+ L_PRINTF(3, ("\tclient_data = %#x, exp = %d\n",
+ client_data, client_data->expiration));
+ c = c->next;
+ }
+
+ L_PRINTF(3, ("\n"));
+}
+
+static void clean_client()
+{
+ svc_auth_gssapi_data *client_data;
+ client_list *c;
+
+ PRINTF(("clean_client: starting\n"));
+
+ c = clients;
+ while (c) {
+ client_data = c->client;
+
+ L_PRINTF(2, ("clean_client: client_data = %#x\n",
+ client_data));
+
+ if (client_data->expiration < time(0)) {
+ PRINTF(("clean_client: client %d expired\n",
+ client_data->key));
+ destroy_client(client_data);
+ c = clients; /* start over, just to be safe */
+ } else {
+ c = c->next;
+ }
+ }
+
+done:
+ PRINTF(("clean_client: done\n"));
+}
+
+/*
+ * Function: _svcauth_gssapi_set_name
+ *
+ * Purpose: Sets the list of service names for which incoming
+ * authentication requests should be honored.
+ *
+ * See functional specifications.
+ */
+bool_t _svcauth_gssapi_set_names(auth_gssapi_name *names, int num)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc in_buf;
+ int i;
+
+ if (num == 0)
+ for (; names[num].name != NULL; num++)
+ ;
+
+ server_creds_list = NULL;
+ server_name_list = NULL;
+
+ server_creds_list = (gss_cred_id_t *) malloc(num*sizeof(gss_cred_id_t));
+ if (server_creds_list == NULL)
+ goto fail;
+ server_name_list = (gss_name_t *) malloc(num*sizeof(gss_name_t));
+ if (server_name_list == NULL)
+ goto fail;
+
+ for (i = 0; i < num; i++) {
+ in_buf.value = names[i].name;
+ in_buf.length = strlen(in_buf.value) + 1;
+
+ gssstat = gss_import_name(&minor_stat, &in_buf, names[i].type,
+ &server_name_list[i]);
+
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("importing name", gssstat,
+ minor_stat));
+ goto fail;
+ }
+
+ gssstat = gss_acquire_cred(&minor_stat, server_name_list[i], 0,
+ GSS_C_NULL_OID_SET, GSS_C_ACCEPT,
+ &server_creds_list[i], NULL, NULL);
+ if (gssstat != GSS_S_COMPLETE) {
+ AUTH_GSSAPI_DISPLAY_STATUS(("acquiring credentials",
+ gssstat, minor_stat));
+ goto fail;
+ }
+ }
+
+ server_creds_count = num;
+
+ return TRUE;
+
+fail:
+ /* memory leak: not releasing names/creds already acquired */
+ if (server_creds_list)
+ free(server_creds_list);
+ if (server_name_list)
+ free(server_name_list);
+ return FALSE;
+}
+
+/*
+ * Function: _svcauth_gssapi_set_log_badauth_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void _svcauth_gssapi_set_log_badauth_func
+ (auth_gssapi_log_badauth_func func, caddr_t data)
+{
+ log_badauth = func;
+ log_badauth_data = data;
+}
+
+/*
+ * Function: _svcauth_gssapi_set_log_badverf_func
+ *
+ * Purpose: sets the logging function called when an invalid RPC call
+ * arrives
+ *
+ * See functional specifications.
+ */
+void _svcauth_gssapi_set_log_badverf_func
+ (auth_gssapi_log_badverf_func func, caddr_t data)
+{
+ log_badverf = func;
+ log_badverf_data = data;
+}
+
+/*
+ * Function: _svcauth_gssapi_set_log_miscerr_func
+ *
+ * Purpose: sets the logging function called when a miscellaneous
+ * AUTH_GSSAPI error occurs
+ *
+ * See functional specifications.
+ */
+void _svcauth_gssapi_set_log_miscerr_func
+ (auth_gssapi_log_miscerr_func func, caddr_t data)
+{
+ log_miscerr = func;
+ log_miscerr_data = data;
+}
+
+/*
+ * Encrypt the serialized arguments from xdr_func applied to xdr_ptr
+ * and write the result to xdrs.
+ */
+static bool_t svc_auth_gssapi_wrap(auth, out_xdrs, xdr_func, xdr_ptr)
+ SVCAUTH *auth;
+ XDR *out_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ OM_uint32 gssstat, minor_stat;
+
+ if (! SVCAUTH_PRIVATE(auth)->established) {
+ PRINTF(("svc_gssapi_wrap: not established, noop\n"));
+ return (*xdr_func)(out_xdrs, xdr_ptr);
+ } else if (! auth_gssapi_wrap_data(&gssstat, &minor_stat,
+ SVCAUTH_PRIVATE(auth)->context,
+ SVCAUTH_PRIVATE(auth)->seq_num,
+ out_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("encrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
+
+static bool_t svc_auth_gssapi_unwrap(auth, in_xdrs, xdr_func, xdr_ptr)
+ SVCAUTH *auth;
+ XDR *in_xdrs;
+ bool_t (*xdr_func)();
+ caddr_t xdr_ptr;
+{
+ svc_auth_gssapi_data *client_data = SVCAUTH_PRIVATE(auth);
+ OM_uint32 gssstat, minor_stat;
+
+ if (! client_data->established) {
+ PRINTF(("svc_gssapi_unwrap: not established, noop\n"));
+ return (*xdr_func)(in_xdrs, (auth_gssapi_init_arg *) xdr_ptr);
+ } else if (! auth_gssapi_unwrap_data(&gssstat, &minor_stat,
+ client_data->context,
+ client_data->seq_num-1,
+ in_xdrs, xdr_func, xdr_ptr)) {
+ if (gssstat != GSS_S_COMPLETE)
+ AUTH_GSSAPI_DISPLAY_STATUS(("decrypting function arguments",
+ gssstat, minor_stat));
+ return FALSE;
+ } else
+ return TRUE;
+}
diff --git a/src/lib/rpc/svc_auth_unix.c b/src/lib/rpc/svc_auth_unix.c
new file mode 100644
index 0000000..1ff2158
--- /dev/null
+++ b/src/lib/rpc/svc_auth_unix.c
@@ -0,0 +1,137 @@
+/* @(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC; from 1.28 88/02/08 SMI */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+#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 rpc_int32 *buf;
+ struct area {
+ struct authunix_parms area_aup;
+ char area_machname[MAX_MACHINE_NAME+1];
+ int area_gids[NGRPS];
+ } *area;
+ unsigned int auth_len;
+ int str_len, gid_len;
+ register int i;
+
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+
+ area = (struct area *) rqst->rq_clntcred;
+ aup = &area->area_aup;
+ aup->aup_machname = area->area_machname;
+ aup->aup_gids = area->area_gids;
+ auth_len = (unsigned int)msg->rm_call.cb_cred.oa_length;
+ xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+ buf = (rpc_int32 *) 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;
+ }
+ memmove(aup->aup_machname, (caddr_t)buf, (unsigned int)str_len);
+ aup->aup_machname[str_len] = 0;
+ str_len = RNDUP(str_len);
+ buf += str_len / sizeof (rpc_int32);
+ 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;
+{
+ rqst->rq_xprt->xp_auth = &svc_auth_any;
+ return (AUTH_REJECTEDCRED);
+}
diff --git a/src/lib/rpc/svc_raw.c b/src/lib/rpc/svc_raw.c
new file mode 100644
index 0000000..1170ece
--- /dev/null
+++ b/src/lib/rpc/svc_raw.c
@@ -0,0 +1,166 @@
+/* @(#)svc_raw.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+#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/src/lib/rpc/svc_run.c b/src/lib/rpc/svc_run.c
new file mode 100644
index 0000000..d43aa24
--- /dev/null
+++ b/src/lib/rpc/svc_run.c
@@ -0,0 +1,72 @@
+/* @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * 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
+ */
+
+/*
+ * 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, (fd_set *)0,
+ (fd_set *)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/src/lib/rpc/svc_simple.c b/src/lib/rpc/svc_simple.c
new file mode 100644
index 0000000..2a22e57
--- /dev/null
+++ b/src/lib/rpc/svc_simple.c
@@ -0,0 +1,143 @@
+/* @(#)svc_simple.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";
+#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((rpc_u_int32)prognum, (rpc_u_int32)versnum);
+ if (!svc_register(transp, (rpc_u_int32)prognum, (rpc_u_int32)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 */
+ memset(xdrbuf, 0, 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/src/lib/rpc/svc_tcp.c b/src/lib/rpc/svc_tcp.c
new file mode 100644
index 0000000..e20a29b
--- /dev/null
+++ b/src/lib/rpc/svc_tcp.c
@@ -0,0 +1,453 @@
+/* @(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#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>
+#include <stdlib.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 bool_t abortx();
+static enum xprt_stat rendezvous_stat();
+
+static struct xp_ops svctcp_rendezvous_op = {
+ rendezvous_request,
+ rendezvous_stat,
+ abortx,
+ abortx,
+ abortx,
+ svctcp_destroy
+};
+
+static int readtcp(), writetcp();
+static SVCXPRT *makefd_xprt();
+
+struct tcp_rendezvous { /* kept in xprt->xp_p1 */
+ unsigned int sendsize;
+ unsigned int recvsize;
+};
+
+struct tcp_conn { /* kept in xprt->xp_p1 */
+ enum xprt_stat strm_stat;
+ rpc_u_int32 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;
+ unsigned int sendsize;
+ unsigned 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;
+ }
+ memset((char *)&addr, 0, 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("svc_tcp.c - cannot getsockname");
+ if (madesock)
+ (void) close(sock);
+ return ((SVCXPRT *)NULL);
+ }
+ if (listen(sock, 2) != 0) {
+ perror("svctcp_.c - cannot 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;
+ unsigned int sendsize;
+ unsigned int recvsize;
+{
+
+ return (makefd_xprt(fd, sendsize, recvsize));
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ unsigned int sendsize;
+ unsigned 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, (fd_set*)NULL,
+ (fd_set*)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 (SVCAUTH_UNWRAP(xprt->xp_auth,
+ &(((struct tcp_conn *)(xprt->xp_p1))->xdrs),
+ xdr_args, 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;
+
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+ bool_t has_args;
+
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ has_args = TRUE;
+ xdr_results = msg->acpted_rply.ar_results.proc;
+ xdr_location = msg->acpted_rply.ar_results.where;
+
+ msg->acpted_rply.ar_results.proc = xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+ } else
+ has_args = FALSE;
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ stat = FALSE;
+ if (xdr_replymsg(xdrs, msg) &&
+ (!has_args ||
+ (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
+ stat = TRUE;
+ }
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ return (stat);
+}
+
+static bool_t abortx()
+{
+ abort();
+ return 1;
+}
+
diff --git a/src/lib/rpc/svc_udp.c b/src/lib/rpc/svc_udp.c
new file mode 100644
index 0000000..d44c7f5
--- /dev/null
+++ b/src/lib/rpc/svc_udp.c
@@ -0,0 +1,496 @@
+/* @(#)svc_udp.c 2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";
+#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 <rpc/rpc.h>
+#include <sys/socket.h>
+#include <errno.h>
+
+
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+#ifndef MAX
+#define MAX(a, b) ((a > b) ? a : b)
+#endif
+
+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 void cache_set();
+static int cache_get();
+
+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 {
+ unsigned int su_iosz; /* byte size of send.recv buffer */
+ rpc_u_int32 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;
+ unsigned 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;
+ }
+ memset((char *)&addr, 0, 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;
+ rpc_u_int32 replylen;
+
+ 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 < (int) 4*sizeof(rpc_u_int32))
+ 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;
+
+ xdrproc_t xdr_results;
+ caddr_t xdr_location;
+ bool_t has_args;
+
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ has_args = TRUE;
+ xdr_results = msg->acpted_rply.ar_results.proc;
+ xdr_location = msg->acpted_rply.ar_results.where;
+
+ msg->acpted_rply.ar_results.proc = xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+ } else
+ has_args = FALSE;
+
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ msg->rm_xid = su->su_xid;
+ if (xdr_replymsg(xdrs, msg) &&
+ (!has_args ||
+ (SVCAUTH_WRAP(xprt->xp_auth, xdrs, xdr_results, xdr_location)))) {
+ 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, (rpc_u_int32) slen);
+ }
+ }
+ }
+ return (stat);
+}
+
+static bool_t
+svcudp_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ caddr_t args_ptr;
+{
+ return (SVCAUTH_UNWRAP(xprt->xp_auth, &(su_data(xprt)->su_xdrs),
+ xdr_args, 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) \
+ memset((char *) addr, 0, 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
+ */
+ rpc_u_int32 cache_xid;
+ rpc_u_int32 cache_proc;
+ rpc_u_int32 cache_vers;
+ rpc_u_int32 cache_prog;
+ struct sockaddr_in cache_addr;
+ /*
+ * The cached reply and length
+ */
+ char * cache_reply;
+ rpc_u_int32 cache_replylen;
+ /*
+ * Next node on the list, if there is a collision
+ */
+ cache_ptr cache_next;
+};
+
+
+
+/*
+ * The entire cache
+ */
+struct udp_cache {
+ rpc_u_int32 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 */
+ rpc_u_int32 uc_nextvictim; /* points to next victim in fifo list */
+ rpc_u_int32 uc_prog; /* saved program number */
+ rpc_u_int32 uc_vers; /* saved version number */
+ rpc_u_int32 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;
+ rpc_u_int32 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;
+ rpc_u_int32 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;
+ unsigned 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 int
+cache_get(xprt, msg, replyp, replylenp)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+ char **replyp;
+ rpc_u_int32 *replylenp;
+{
+ unsigned 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) (memcmp((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/src/lib/rpc/types.hin b/src/lib/rpc/types.hin
new file mode 100644
index 0000000..619a9ce
--- /dev/null
+++ b/src/lib/rpc/types.hin
@@ -0,0 +1,90 @@
+/* @(#)types.h 2.3 88/08/15 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)types.h 1.18 87/07/24 SMI */
+
+/*
+ * Rpc additions to <sys/types.h>
+ */
+#ifndef __TYPES_RPC_HEADER__
+#define __TYPES_RPC_HEADER__
+
+#include <sys/types.h>
+
+/* this is a 32-bit int type */
+
+#if @SIZEOF_INT@ == 4
+typedef int rpc_int32;
+typedef unsigned int rpc_u_int32;
+#elif @SIZEOF_LONG@ == 4
+typedef long rpc_int32;
+typedef unsigned long rpc_u_int32;
+#endif
+
+#define bool_t int
+#define enum_t int
+#ifndef FALSE
+# define FALSE (0)
+#endif
+#ifndef TRUE
+# define TRUE (1)
+#endif
+#define __dontcare__ -1
+#ifndef NULL
+# define NULL 0
+#endif
+
+#if defined(__osf__)
+#include <stdlib.h>
+#endif
+#define mem_alloc(bsize) (char *) malloc(bsize)
+#define mem_free(ptr, bsize) free(ptr)
+
+#ifndef makedev /* ie, we haven't already included it */
+#include <sys/types.h>
+#endif
+#ifdef _AIX
+#include <sys/select.h>
+#endif
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <sys/param.h>
+#include <netdb.h> /* XXX This should not have to be here.
+ * I got sick of seeing the warnings for MAXHOSTNAMELEN
+ * and the two values were different. -- shanzer
+ */
+
+#ifndef INADDR_LOOPBACK
+#define INADDR_LOOPBACK (rpc_u_int32)0x7F000001
+#endif
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#endif /* ndef __TYPES_RPC_HEADER__ */
diff --git a/src/lib/rpc/unit-test/Makefile b/src/lib/rpc/unit-test/Makefile
new file mode 100644
index 0000000..31853cb
--- /dev/null
+++ b/src/lib/rpc/unit-test/Makefile
@@ -0,0 +1,97 @@
+# Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+#
+# $Id$
+# $Source$
+#
+# $Log$
+# Revision 1.9 1996/07/22 20:41:38 marc
+# this commit includes all the changes on the OV_9510_INTEGRATION and
+# OV_MERGE branches. This includes, but is not limited to, the new openvision
+# admin system, and major changes to gssapi to add functionality, and bring
+# the implementation in line with rfc1964. before committing, the
+# code was built and tested for netbsd and solaris.
+#
+# Revision 1.8.4.1 1996/07/18 04:20:01 marc
+# merged in changes from OV_9510_BP to OV_9510_FINAL1
+#
+# Revision 1.8.2.1 1996/06/20 23:41:48 marc
+# File added to the repository on a branch
+#
+# Revision 1.8 1995/12/07 17:36:54 jik
+# Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on
+# some systems. See PR 3553.
+#
+# Revision 1.7 1995/10/02 08:02:49 jik
+# Delete rpc-tset_clnt.c, rpc-test_svc.c and rpc-test.h before creating
+# them, because rpcgen on some platforms won't output to a file that
+# already exists.
+#
+# Revision 1.6 1994/10/24 19:35:57 bjaspan
+# [secure-build/2649: cannot use -L when compiling]
+#
+# Sandbox:
+#
+# [secure-build/2649] don't use -L
+#
+# Revision 1.7 1994/10/11 20:06:14 bjaspan
+# [secure-build/2649] don't use -L
+#
+# Revision 1.6 1994/09/30 22:25:29 jik
+# Don't need to set MDFLAGS to -a anymore, because it's done
+# automatically by the rules now.
+#
+# Revision 1.5 1994/03/22 19:55:34 shanzer
+# change NETLIBS to NETLIB
+#
+# Revision 1.4 1994/03/18 17:47:00 shanzer
+# added NETLIBS and BSDLIB
+#
+# Revision 1.3 1993/12/13 02:00:39 bjaspan
+# recurse to testsuite subdir.
+#
+# Revision 1.2 1993/12/08 21:45:47 bjaspan
+# misc
+#
+# Revision 1.1 1993/11/03 23:53:58 bjaspan
+# Initial revision
+#
+
+TOP = ../..
+include $(TOP)/config.mk/template
+
+SUBDIRS = testsuite
+
+expand SubdirTarget
+
+SRCS = client.c server.c
+
+CFLAGS := -I../.. -I. $(CFLAGS)
+
+#LIBS = ../librpclib.a $(LIBGSSAPI_TRUST) $(LIBDB) $(LIBCOM_ERR) $(LIBDYN)
+LIBS = ../librpclib.a $(LIBGSSAPI_KRB5) $(LIBDB) $(LIBKRB5) \
+ $(LIBCRYPTO) $(LIBISODE) $(LIBCOM_ERR) $(LIBDYN) $(BSDLIB) $(NETLIB)
+DEPS = ../librpclib.a rpc_test.h
+DEPENDS = rpc_test.h
+
+PROG = client
+SRCS = client.c
+OBJS = client.o rpc_test_clnt.o
+
+expand Program
+expand Depend
+
+PROG = server
+SRCS = server.c
+OBJS = server.o rpc_test_svc.o
+
+expand Program
+expand Depend
+
+rpc_test.h rpc_test_clnt.c rpc_test_svc.c: rpc_test.x
+ -rm -f rpc_test_clnt.c rpc_test_svc.c rpc_test.h
+ rpcgen -l rpc_test.x -o rpc_test_clnt.c
+ rpcgen -m rpc_test.x -o rpc_test_svc.c
+ rpcgen -h rpc_test.x -o rpc_test.h
+
+clean::
+ rm -f rpc_test.h rpc_test_clnt.c rpc_test_svc.c
diff --git a/src/lib/rpc/unit-test/client.c b/src/lib/rpc/unit-test/client.c
new file mode 100644
index 0000000..bcf2700
--- /dev/null
+++ b/src/lib/rpc/unit-test/client.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.13 1996/07/22 20:41:40 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.12.4.1 1996/07/18 04:20:03 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.12.2.1 1996/06/20 23:41:56 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.12 1996/05/12 06:58:10 marc
+ * type renamings for compatibility with beta6
+ *
+ * Revision 1.11 1996/02/12 15:58:42 grier
+ * [secure/3570]
+ * long conversion
+ *
+ * Revision 1.10 1995/12/07 17:37:03 jik
+ * Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on
+ * some systems. See PR 3553.
+ *
+ * Revision 1.9 1994/09/21 18:38:56 bjaspan
+ * [secure-rpc/2536: unit test client.c: memory initialization and out-of-bounds reference bugs]
+ * [secure-releng/2537: audit secure-rpc/2536: minor memory problems in unit-test client]
+ *
+ * Sandbox:
+ *
+ * 1. Don't allow the count specifie on the command line to be bigger
+ * than the size of the buffer use for testing.
+ * 2. When initializing the buffer for the lengths test, initialize it to
+ * count bytes.
+ *
+ * Revision 1.9 1994/09/19 01:28:04 root
+ * 1. Don't allow the count specifie on the command line to be bigger
+ * than the size of the buffer use for testing.
+ * 2. When initializing the buffer for the lengths test, initialize it to
+ * count bytes.
+ *
+ * Revision 1.8 1994/04/06 22:13:01 jik
+ * Change -auth_once to -o, add -a, -m and -s arguments to set
+ * auth_debug_gssapi, svc_debug_gssapi and misc_debug_gssapi variables.
+ *
+ * Revision 1.7 1994/04/05 20:50:09 bjaspan
+ * fix typo that causes coredump when server blocks/fails
+ *
+ * Revision 1.6 1993/12/08 21:44:45 bjaspan
+ * test fix for secure-rpc/586, improve arg handlng
+ *
+ * Revision 1.5 1993/12/06 21:23:30 bjaspan
+ * accept count arg for RPC_TEST_LENGTHS
+ *
+ * Revision 1.4 1993/12/01 23:41:45 bjaspan
+ * don't free echo_resp if call fails
+ *
+ * Revision 1.3 1993/11/15 19:53:09 bjaspan
+ * test auto-syncrhonization
+ *
+ * Revision 1.2 1993/11/12 02:33:43 bjaspan
+ * use clnt_pcreateerror for auth failures
+ *
+ * Revision 1.1 1993/11/03 23:53:58 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <gssapi/gssapi.h>
+#include <rpc/rpc.h>
+#include <rpc/auth_gssapi.h>
+#include "rpc_test.h"
+
+#define BIG_BUF 4096
+/* copied from auth_gssapi.c for hackery */
+struct auth_gssapi_data {
+ bool_t established;
+ CLIENT *clnt;
+ gss_ctx_id_t context;
+ gss_buffer_desc client_handle;
+ OM_uint32 seq_num;
+ int def_cred;
+
+ /* pre-serialized ah_cred */
+ u_char cred_buf[MAX_AUTH_BYTES];
+ rpc_int32 cred_len;
+};
+#define AUTH_PRIVATE(auth) ((struct auth_gssapi_data *)auth->ah_private)
+
+extern int auth_debug_gssapi;
+char *whoami;
+
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ char *host, *target, *echo_arg, **echo_resp, buf[BIG_BUF];
+ CLIENT *clnt;
+ AUTH *tmp_auth;
+ struct rpc_err e;
+ int i, count, auth_once;
+ extern int optind;
+ extern char *optarg;
+ extern int svc_debug_gssapi, misc_debug_gssapi, auth_debug_gssapi;
+ int c;
+
+ whoami = argv[0];
+ count = 1026;
+ auth_once = 0;
+
+ while ((c = getopt(argc, argv, "a:m:os:")) != -1) {
+ switch (c) {
+ case 'a':
+ auth_debug_gssapi = atoi(optarg);
+ break;
+ case 'm':
+ misc_debug_gssapi = atoi(optarg);
+ break;
+ case 'o':
+ auth_once++;
+ break;
+ case 's':
+ svc_debug_gssapi = atoi(optarg);
+ break;
+ case '?':
+ usage();
+ break;
+ }
+ }
+
+ argv += optind;
+ argc -= optind;
+
+ switch (argc) {
+ case 3:
+ count = atoi(argv[2]);
+ if (count > BIG_BUF) {
+ fprintf(stderr, "Test count cannot exceed %d.\n", BIG_BUF);
+ usage();
+ }
+ case 2:
+ host = argv[0];
+ target = argv[1];
+ break;
+ default:
+ usage();
+ }
+
+ /* client handle to rstat */
+ clnt = clnt_create(host, RPC_TEST_PROG, RPC_TEST_VERS_1, "tcp");
+ if (clnt == NULL) {
+ clnt_pcreateerror(whoami);
+ exit(1);
+ }
+
+ clnt->cl_auth = auth_gssapi_create_default(clnt, target);
+ if (clnt->cl_auth == NULL) {
+ clnt_pcreateerror(whoami);
+ exit(2);
+ }
+
+ /*
+ * Call the echo service multiple times.
+ */
+ echo_arg = buf;
+ for (i = 0; i < 3; i++) {
+ sprintf(buf, "testing %d\n", i);
+
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL) {
+ fprintf(stderr, "RPC_TEST_ECHO call %d%s", i,
+ clnt_sperror(clnt, ""));
+ }
+ if (strncmp(*echo_resp, "Echo: ", 6) &&
+ strcmp(echo_arg, (*echo_resp) + 6) != 0)
+ fprintf(stderr, "RPC_TEST_ECHO call %d response wrong: "
+ "arg = %s, resp = %s\n", echo_arg, *echo_resp);
+ xdr_free(xdr_wrapstring, echo_resp);
+ }
+
+ /*
+ * Make a call with an invalid verifier and check for error;
+ * server should log error message. It is important to
+ *increment* seq_num here, since a decrement would be fixed (see
+ * below). Note that seq_num will be incremented (by
+ * authg_gssapi_refresh) twice, so we need to decrement by three
+ * to reset.
+ */
+ AUTH_PRIVATE(clnt->cl_auth)->seq_num++;
+
+ echo_arg = "testing with bad verf";
+
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL) {
+ CLNT_GETERR(clnt, &e);
+ if (e.re_status != RPC_AUTHERROR || e.re_why != AUTH_REJECTEDVERF)
+ clnt_perror(clnt, whoami);
+ } else {
+ fprintf(stderr, "bad seq didn't cause failure\n");
+ }
+
+ AUTH_PRIVATE(clnt->cl_auth)->seq_num -= 3;
+
+ /*
+ * Make sure we're resyncronized.
+ */
+ echo_arg = "testing for reset";
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL)
+ clnt_perror(clnt, "Sequence number improperly reset");
+
+ /*
+ * Now simulate a lost server response, and see if
+ * auth_gssapi_refresh recovers.
+ */
+ AUTH_PRIVATE(clnt->cl_auth)->seq_num--;
+ echo_arg = "forcing auto-resynchronization";
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL)
+ clnt_perror(clnt, "Auto-resynchronization failed");
+
+ /*
+ * Now make sure auto-resyncrhonization actually worked
+ */
+ echo_arg = "testing for resynchronization";
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL)
+ clnt_perror(clnt, "Auto-resynchronization did not work");
+
+ /*
+ * Test fix for secure-rpc/586, part 1: btree keys must be
+ * unique. Create another context from the same credentials; it
+ * should have the same expiration time and will cause the server
+ * to abort if the clients are not differentiated.
+ *
+ * Test fix for secure-rpc/586, part 2: btree keys cannot be
+ * mutated in place. To test this: a second client, *with a
+ * later expiration time*, must be run. The second client should
+ * destroy itself *after* the first one; if the key-mutating bug
+ * is not fixed, the second client_data will be in the btree
+ * before the first, but its key will be larger; thus, when the
+ * first client calls AUTH_DESTROY, the server won't find it in
+ * the btree and call abort.
+ *
+ * For unknown reasons, running just a second client didn't
+ * tickle the bug; the btree code seemed to guess which node to
+ * look at first. Running a total of three clients does ticket
+ * the bug. Thus, the full test sequence looks like this:
+ *
+ * kinit -l 20m user && client server test@ddn 200
+ * sleep 1
+ * kini -l 30m user && client server test@ddn 300
+ * sleep 1
+ * kinit -l 40m user && client server test@ddn 400
+ */
+ if (! auth_once) {
+ tmp_auth = clnt->cl_auth;
+ clnt->cl_auth = auth_gssapi_create_default(clnt, target);
+ if (clnt->cl_auth == NULL) {
+ clnt_pcreateerror(whoami);
+ exit(2);
+ }
+ AUTH_DESTROY(clnt->cl_auth);
+ clnt->cl_auth = tmp_auth;
+ }
+
+ /*
+ * Try RPC calls with argument/result lengths [0, 1025]. Do
+ * this last, since it takes a while..
+ */
+ echo_arg = buf;
+ memset(buf, 0, count);
+ for (i = 0; i < count; i++) {
+ echo_resp = rpc_test_echo_1(&echo_arg, clnt);
+ if (echo_resp == NULL) {
+ fprintf(stderr, "RPC_TEST_LENGTHS call %d%s", i,
+ clnt_sperror(clnt, ""));
+ break;
+ } else {
+ if (strncmp(*echo_resp, "Echo: ", 6) &&
+ strcmp(echo_arg, (*echo_resp) + 6) != 0)
+ fprintf(stderr,
+ "RPC_TEST_LENGTHS call %d response wrong\n");
+ xdr_free(xdr_wrapstring, echo_resp);
+ }
+
+ /* cycle from 1 to 255 */
+ buf[i] = (i % 255) + 1;
+
+ if (i % 100 == 0) {
+ fputc('.', stdout);
+ fflush(stdout);
+ }
+ }
+ fputc('\n', stdout);
+
+ AUTH_DESTROY(clnt->cl_auth);
+ CLNT_DESTROY(clnt);
+ exit(0);
+}
+
+usage()
+{
+ fprintf(stderr, "usage: %s [-a] [-s num] [-m num] host service [count]\n",
+ whoami);
+ exit(1);
+}
diff --git a/src/lib/rpc/unit-test/rpc_test.x b/src/lib/rpc/unit-test/rpc_test.x
new file mode 100644
index 0000000..e9ae27c
--- /dev/null
+++ b/src/lib/rpc/unit-test/rpc_test.x
@@ -0,0 +1,30 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.2 1996/07/22 20:41:42 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.1.4.1 1996/07/18 04:20:04 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+# Revision 1.1.2.1 1996/06/20 23:42:06 marc
+# File added to the repository on a branch
+#
+# Revision 1.1 1993/11/03 23:53:58 bjaspan
+# Initial revision
+#
+ */
+
+program RPC_TEST_PROG {
+ version RPC_TEST_VERS_1 {
+ string RPC_TEST_ECHO(string) = 1;
+ } = 1;
+} = 1000001;
diff --git a/src/lib/rpc/unit-test/server.c b/src/lib/rpc/unit-test/server.c
new file mode 100644
index 0000000..d98b2df
--- /dev/null
+++ b/src/lib/rpc/unit-test/server.c
@@ -0,0 +1,306 @@
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Id$
+ * $Source$
+ *
+ * $Log$
+ * Revision 1.15 1996/07/22 20:41:44 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.14.4.1 1996/07/18 04:20:06 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.14.2.1 1996/06/20 23:42:16 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.14 1996/05/12 06:59:06 marc
+ * change SERVICE_NAME to "host" instead of "server"
+ *
+ * remove KRB5KTNAME support, since the library supports it internally now.
+ *
+ * Revision 1.13 1995/12/07 17:36:58 jik
+ * Use "rpc_test" instead of "rpc-test", to avoid problems with rpcgen on
+ * some systems. See PR 3553.
+ *
+ * Revision 1.12 1995/11/07 23:20:44 grier
+ * Add stdlib.h
+ * Add string.h
+ *
+ * Revision 1.11 1995/03/24 19:55:28 jik
+ * Cast a const gss_OID to (gss_OID) to prevent a compiler warning.
+ *
+ * Revision 1.10 1995/02/22 15:54:17 jik
+ * I was a moron in revision 1.8. This is the server function, not the
+ * client function, so it gets a struct svc_req *, not a CLIENT *.
+ *
+ * Revision 1.9 1995/02/22 15:21:51 jik
+ * Linux's rpcgen names the server function differently from the client
+ * function ("_svc" is appended to the end of it).
+ *
+ * Revision 1.8 1995/02/22 14:35:05 jik
+ * RPC server functions have CLIENT * passed into them, so I added it as
+ * an argument to rpc_test_echo_1.
+ *
+ * Revision 1.7 1994/09/21 18:35:57 bjaspan
+ * [gssapi/438: gss_nt_service_name should default to local host]
+ * [secure-releng/2513: audit gssapi/438: gss_nt_service_name should default to local host]
+ *
+ * Sandbox:
+ *
+ * Don't need to get local host name and put it in the service name,
+ * since the gssapi library does that now. See PR 438.
+ *
+ * Revision 1.8 1994/09/01 17:21:59 jik
+ * Don't need to get local host name and put it in the service name,
+ * since the gssapi library does that now. See PR 438.
+ *
+ * Revision 1.7 1994/04/08 17:22:11 bjaspan
+ * add KRB5KTNAME hack so unit tests continue to work
+ *
+ * Revision 1.6 1994/04/05 20:50:26 bjaspan
+ * print "running" when ready to tests can proceed
+ *
+ * Revision 1.5 1994/04/05 19:49:54 jik
+ * Use host name instead of localhost.
+ *
+ * Revision 1.4 1994/03/08 00:14:58 shanzer
+ * changed call to inet_ntoa
+ *
+ * Revision 1.3 1993/12/13 01:37:54 bjaspan
+ * update for new test system
+ * ,.
+ *
+ * Revision 1.2 1993/12/08 21:45:16 bjaspan
+ * display badauth errors, improve arg handling
+ *
+ * Revision 1.1 1993/11/03 23:53:58 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <arpa/inet.h> /* inet_ntoa */
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_generic.h>
+#include <rpc/auth_gssapi.h>
+#include <sys/param.h> /* MAXHOSTNAMELEN */
+#include "rpc_test.h"
+
+#ifdef linux
+/*
+ For some reason, Linux's rpcgen names the server function
+ differently from the client function. I suppose this is useful if
+ you want to include them both in the same library or something, but
+ not useful at all if you want to link the client code directly to
+ the server code for testing, instead of going through the RPC layer.
+ */
+#define rpc_test_echo_1 rpc_test_echo_1_svc
+#endif
+
+extern void rpc_test_prog_1();
+
+extern int svc_debug_gssapi, misc_debug_gssapi;
+
+void rpc_test_badauth(OM_uint32 major, OM_uint32 minor,
+ struct sockaddr_in *addr, void *data);
+void log_badauth_display_status(OM_uint32 major, OM_uint32 minor);
+void log_badauth_display_status_1(OM_uint32 code, int type, int rec);
+static void rpc_test_badverf(gss_name_t client, gss_name_t server,
+ struct svc_req *rqst, struct rpc_msg *msg,
+ caddr_t data);
+
+#ifndef SERVICE_NAME
+#define SERVICE_NAME "host"
+#endif
+
+main(int argc, char **argv)
+{
+ auth_gssapi_name names[2];
+ register SVCXPRT *transp;
+
+ names[0].name = SERVICE_NAME;
+ names[0].type = (gss_OID) gss_nt_service_name;
+ names[1].name = 0;
+ names[1].type = 0;
+
+ switch (argc) {
+ case 3:
+ misc_debug_gssapi = atoi(argv[2]);
+ case 2:
+ svc_debug_gssapi = atoi(argv[1]);
+ case 1:
+ break;
+ default:
+ fprintf(stderr, "Usage: server [svc-debug] [misc-debug]\n");
+ exit(1);
+ }
+
+ (void) pmap_unset(RPC_TEST_PROG, RPC_TEST_VERS_1);
+
+ transp = svctcp_create(RPC_ANYSOCK, 0, 0);
+ if (transp == NULL) {
+ fprintf(stderr, "cannot create tcp service.");
+ exit(1);
+ }
+ if (!svc_register(transp, RPC_TEST_PROG, RPC_TEST_VERS_1,
+ rpc_test_prog_1, IPPROTO_TCP)) {
+ fprintf(stderr,
+ "unable to register (RPC_TEST_PROG, RPC_TEST_VERS_1, tcp).");
+ exit(1);
+ }
+
+ if (_svcauth_gssapi_set_names(names, 0) == FALSE) {
+ fprintf(stderr, "unable to set gssapi names\n");
+ exit(1);
+ }
+
+ _svcauth_gssapi_set_log_badauth_func(rpc_test_badauth, NULL);
+ _svcauth_gssapi_set_log_badverf_func(rpc_test_badverf, NULL);
+
+ printf("running\n");
+
+ svc_run();
+ fprintf(stderr, "svc_run returned");
+ exit(1);
+ /* NOTREACHED */
+}
+
+char **rpc_test_echo_1(char **arg, struct svc_req *h)
+{
+ static char *res = NULL;
+
+ if (res)
+ free(res);
+ res = (char *) malloc(strlen(*arg) + strlen("Echo: ") + 1);
+ sprintf(res, "Echo: %s", *arg);
+ return &res;
+}
+
+static void rpc_test_badverf(gss_name_t client, gss_name_t server,
+ struct svc_req *rqst, struct rpc_msg *msg,
+ caddr_t data)
+{
+ OM_uint32 minor_stat;
+ gss_OID type;
+ gss_buffer_desc client_name, server_name;
+
+ (void) gss_display_name(&minor_stat, client, &client_name, &type);
+ (void) gss_display_name(&minor_stat, server, &server_name, &type);
+
+ printf("rpc_test server: bad verifier from %s at %s:%d for %s\n",
+ client_name.value,
+ inet_ntoa(rqst->rq_xprt->xp_raddr.sin_addr),
+ ntohs(rqst->rq_xprt->xp_raddr.sin_port),
+ server_name.value);
+
+ (void) gss_release_buffer(&minor_stat, &client_name);
+ (void) gss_release_buffer(&minor_stat, &server_name);
+}
+
+/*
+ * Function: log_badauth
+ *
+ * Purpose: Callback from GSS-API Sun RPC for authentication
+ * failures/errors.
+ *
+ * Arguments:
+ * major (r) GSS-API major status
+ * minor (r) GSS-API minor status
+ * addr (r) originating address
+ * data (r) arbitrary data (NULL), not used
+ *
+ * Effects:
+ *
+ * Logs the GSS-API error to stdout.
+ */
+void rpc_test_badauth(OM_uint32 major, OM_uint32 minor,
+ struct sockaddr_in *addr, void *data)
+{
+ char *a;
+
+ /* Authentication attempt failed: <IP address>, <GSS-API error */
+ /* strings> */
+
+ a = inet_ntoa(addr->sin_addr);
+
+ printf("rpc_test server: Authentication attempt failed: %s", a);
+ log_badauth_display_status(major, minor);
+ printf("\n");
+}
+
+void log_badauth_display_status(OM_uint32 major, OM_uint32 minor)
+{
+ log_badauth_display_status_1(major, GSS_C_GSS_CODE, 0);
+ log_badauth_display_status_1(minor, GSS_C_MECH_CODE, 0);
+}
+
+void log_badauth_display_status_1(OM_uint32 code, int type, int rec)
+{
+ OM_uint32 gssstat, minor_stat;
+ gss_buffer_desc msg;
+ int msg_ctx;
+
+ msg_ctx = 0;
+ while (1) {
+ gssstat = gss_display_status(&minor_stat, code,
+ type, GSS_C_NULL_OID,
+ &msg_ctx, &msg);
+ if (gssstat != GSS_S_COMPLETE) {
+ if (!rec) {
+ log_badauth_display_status_1(gssstat,GSS_C_GSS_CODE,1);
+ log_badauth_display_status_1(minor_stat,
+ GSS_C_MECH_CODE, 1);
+ } else
+ printf("GSS-API authentication error %s: "
+ "recursive failure!\n", msg);
+ return;
+ }
+
+ printf(", %s", (char *)msg.value);
+ (void) gss_release_buffer(&minor_stat, &msg);
+
+ if (!msg_ctx)
+ break;
+ }
+}
+
+
+#if 0
+
+/* this hack is no longer necessary, since the library supports it
+ internally */
+
+/* This is a hack to change the default keytab name */
+
+#include <krb5/krb5.h>
+extern char *krb5_defkeyname;
+
+krb5_error_code
+krb5_kt_default_name(char *name, int namesize)
+{
+ char *ktname;
+
+ if ((ktname = getenv("KRB5KTNAME")) == NULL)
+ ktname = krb5_defkeyname;
+
+ if (namesize < strlen(ktname)+1)
+ return(KRB5_CONFIG_NOTENUFSPACE);
+
+ strcpy(name, ktname);
+
+ return(0);
+}
+
+#endif
diff --git a/src/lib/rpc/unit-test/testsuite/Makefile b/src/lib/rpc/unit-test/testsuite/Makefile
new file mode 100644
index 0000000..8a2cccd
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/Makefile
@@ -0,0 +1,24 @@
+#
+# $Id$
+#
+
+TOP = ../../..
+include $(TOP)/config.mk/template
+
+export RPC_TEST_SRVTAB := /tmp/rpc_test_v5srvtab
+
+unit-test:: unit-test-setup unit-test-body unit-test-cleanup
+
+unit-test-setup::
+ $(START_SERVERS)
+ ./rpc_test_setup.sh
+
+unit-test-body::
+ $(RUNTEST) SERVER=../server CLIENT=../client --tool rpc_test
+
+unit-test-cleanup::
+ $(STOP_SERVERS)
+ -rm -f /tmp/rpc_test_v5srvtab /tmp/krb5cc_rpc_test_fullrun
+
+clean::
+ $(CLEAN) rpc_test.log rpc_test.plog rpc_test.sum rpc_test.psum
diff --git a/src/lib/rpc/unit-test/testsuite/config/unix.exp b/src/lib/rpc/unit-test/testsuite/config/unix.exp
new file mode 100644
index 0000000..030837d
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/config/unix.exp
@@ -0,0 +1,79 @@
+#
+# $Id$
+#
+
+set kill /bin/kill
+set sleep /bin/sleep
+set kinit $env(TOP)/install/bin/kinit
+set kdestroy $env(TOP)/install/bin/kdestroy
+
+set hostname [exec hostname]
+
+proc rpc_test_version {} {
+ global CLIENT
+ global SERVER
+
+ clone_output "$CLIENT version <unknown>"
+ clone_output "$SERVER version <unknown>"
+}
+
+proc rpc_test_load {} {
+ #
+}
+
+# rpc_test_exit -- clean up and exit
+proc rpc_test_exit {} {
+ global server_id
+ global server_pid
+ global server_started
+ global kill
+
+ if {[catch {
+ expect {
+ -i $server_id
+ eof {
+ fail "server exited!"
+ verbose $expect_out(buffer) 1
+ }
+ timeout { pass "server survived" }
+ }
+ } tmp]} {
+ fail "server exited! (expect failed)"
+ }
+}
+
+#
+# rpc_test_start -- start the rpc_test server running
+#
+proc rpc_test_start { } {
+ global SERVER
+ global server_id
+ global server_pid
+ global server_started
+ global env
+
+ set env(KRB5KTNAME) FILE:$env(RPC_TEST_SRVTAB)
+
+ verbose "% $SERVER" 1
+ set server_pid [spawn $SERVER]
+ set server_id $spawn_id
+
+ unset env(KRB5KTNAME)
+
+ set timeout 30
+
+ expect {
+ "running" { }
+ eof {
+ fail "server exited!"
+ verbose $expect_out(buffer) 1
+ }
+ timeout {
+ fail "server didn't start in $timeout seconds"
+ verbose $expect_out(buffer) 1
+ }
+ }
+
+}
+
+rpc_test_start
diff --git a/src/lib/rpc/unit-test/testsuite/helpers.exp b/src/lib/rpc/unit-test/testsuite/helpers.exp
new file mode 100644
index 0000000..1a37ad5
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/helpers.exp
@@ -0,0 +1,128 @@
+if {[info commands exp_version] != {}} {
+ set exp_version_4 [regexp {^4} [exp_version]]
+} else {
+ set exp_version_4 [regexp {^4} [expect_version]]
+}
+
+# Backward compatibility until we're using expect 5 everywhere
+if {$exp_version_4} {
+ global wait_error_index wait_errno_index wait_status_index
+ set wait_error_index 0
+ set wait_errno_index 1
+ set wait_status_index 1
+} else {
+ set wait_error_index 2
+ set wait_errno_index 3
+ set wait_status_index 3
+}
+
+
+proc kinit {princ pass lifetime} {
+ global kinit
+ global wait_error_index wait_errno_index wait_status_index
+
+ spawn -noecho $kinit -l $lifetime $princ
+ expect {
+ -re "Password for $princ.*: " { send "$pass\n" }
+ timeout { error "Timeout waiting for kinit"; close }
+ }
+ expect { eof {} }
+
+ set ret [wait]
+ if {[lindex $ret $wait_error_index] == -1} {
+ error \
+ "wait(kinit $princ) returned error [lindex $ret $wait_errno_index]"
+ } else {
+ if {[lindex $ret $wait_status_index] != 0} {
+ error \
+ "kinit $princ failed with [lindex $ret $wait_status_index]"
+ }
+ }
+}
+
+proc flush_server {} {
+ global server_id
+ global expect_out
+
+ verbose "flushing server output" 1
+
+ while {1} {
+ set timeout 5
+
+ expect {
+ -i $server_id
+ -re "^.+$" {
+ verbose "server output: $expect_out(buffer)"
+ }
+ timeout { break }
+ }
+ }
+}
+
+proc start_client {testname ccname user password lifetime count
+ {target ""}} {
+ global env
+ global CLIENT
+ global hostname
+ global spawn_id
+ global verbose
+
+ if {$target == ""} {
+ set target "server@$hostname"
+ }
+
+ set env(KRB5CCNAME) FILE:/tmp/krb5cc_rpc_test_$ccname
+ kinit $user $password $lifetime
+
+ if {$verbose > 0} {
+ spawn $CLIENT -a 1 -s 1 -m 1 $hostname $target $count
+ } else {
+ spawn $CLIENT $hostname $target $count
+ }
+
+ verbose "$testname: client $ccname started"
+
+ unset env(KRB5CCNAME)
+}
+
+proc eof_client {testname ccname id status} {
+ verbose "$testname: eof'ing for client $ccname" 1
+
+ expect {
+ -i $id
+ eof { verbose $expect_out(buffer) 1 }
+ timeout {
+ fail "$testname: timeout waiting for client $ccname to exit"
+ }
+ }
+ wait_client $testname $ccname $id $status
+}
+
+
+proc wait_client {testname ccname id status} {
+ global env
+ global kill
+ global kdestroy
+ global wait_error_index wait_errno_index wait_status_index
+
+ verbose "$testname: waiting for client $ccname" 1
+
+ set ret [wait -i $id]
+ if {[lindex $ret $wait_error_index] == -1} {
+ fail \
+ "$testname: wait $ccname returned error [lindex $ret $wait_errno_index]"
+ } else {
+ if {[lindex $ret $wait_status_index] == $status} {
+ pass "$testname: client $ccname"
+ } else {
+ fail "$testname: client $ccname: unexpected return status [lindex $ret $wait_status_index], should be $status."
+ }
+ }
+
+ set env(KRB5CCNAME) FILE:/tmp/krb5cc_rpc_test_$ccname
+ if {[catch "exec $kdestroy"] != 0} {
+ error "$testname: cannot destroy client $ccname ccache"
+ }
+
+ unset env(KRB5CCNAME)
+}
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp
new file mode 100644
index 0000000..d80bae6
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/expire.exp
@@ -0,0 +1,21 @@
+set timeout 40
+
+load_lib "helpers.exp"
+
+global spawn_id
+
+start_client expire 1 testuser notathena 20m 100
+set client1_id $spawn_id
+flush_server
+
+start_client expire 2 testuser notathena 40m 300
+set client2_id $spawn_id
+flush_server
+
+start_client expire 3 testuser notathena 60m 500
+set client3_id $spawn_id
+flush_server
+
+eof_client expire 1 $client1_id 0
+eof_client expire 2 $client2_id 0
+eof_client expire 3 $client3_id 0
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp
new file mode 100644
index 0000000..6e8acf8
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/fullrun.exp
@@ -0,0 +1,95 @@
+set timeout 120
+
+load_lib "helpers.exp"
+
+global spawn_id
+global server_id
+
+# Start the client and do a full run
+start_client "full run" fullrun testuser notathena 8 1026
+set client_id $spawn_id
+
+#
+# test: did we get 11 dots?
+#
+verbose "Starting RPC echo test. This will take about 50 seconds.\n"
+
+set ver_line "rpc_test server: bad verifier\[^\r\n\]*\n"
+
+set dots 0
+set server_lines 0
+while {1} {
+ set oldtimeout $timeout
+ set timeout 5
+ while {1} {
+ expect {
+ -i $server_id
+ -re $ver_line {
+ verbose "Got line from server."
+ incr server_lines
+ }
+ default {
+ break
+ }
+ }
+ }
+ set timeout $oldtimeout
+ expect {
+ -i $client_id
+ . {
+ incr dots
+ verbose "$expect_out(buffer)" 1
+ if ($dots==11) { break }
+ }
+ eof {
+ #
+ # test: was the exit status right?
+ #
+ wait_client "full run" fullrun $client_id 0
+ break
+ }
+
+ timeout {
+ verbose "Timeout waiting for dot\n" 1
+ fail "full run: timeout waiting for dot"
+ break
+ }
+
+ }
+}
+if {$dots==11} {
+ pass "fullrun: echo test"
+} else {
+ fail "fullrun: echo test: expected 11 dots, got $dots"
+}
+
+#
+# test: server logged four bad verifiers?
+#
+verbose "full run: checking server output"
+
+# Small timeout, since the server should have already printed everything
+set timeout 5
+
+while {$server_lines < 4} {
+ expect {
+ -i $server_id
+ -re $ver_line {
+ incr server_lines
+ }
+ -re ".+\r\n" {
+ verbose "Unexpected server output: $expect_out(buffer)"
+ }
+ default {
+ break
+ }
+ }
+}
+
+if {$server_lines == 4} {
+ pass "fullrun: bad verifiers"
+} else {
+ fail "fullrun: expected four bad verifiers, got $server_lines"
+}
+
+flush_server
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp b/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp
new file mode 100644
index 0000000..f9d5305
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test.0/gsserr.exp
@@ -0,0 +1,27 @@
+set timeout 30
+
+load_lib "helpers.exp"
+
+global spawn_id
+global server_id
+global hostname
+
+start_client "gss err" gsserr testuser notathena 8 1026 notserver@$hostname
+
+eof_client "gss err" gsserr $spawn_id 2
+
+#
+# test: server logged an authentication attempted failed?
+#
+verbose "gss err: checking server output"
+
+expect {
+ -i $server_id
+ -re "rpc_test server: Authent.*failed: .* Wrong princ" {
+ pass "gss err: server logged auth error"
+ }
+ eof { fail "gss err: server exited" }
+ timeout { fail "gss err: timeout waiting for server output" }
+}
+
+flush_server
diff --git a/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh b/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh
new file mode 100644
index 0000000..2a97af4
--- /dev/null
+++ b/src/lib/rpc/unit-test/testsuite/rpc_test_setup.sh
@@ -0,0 +1,56 @@
+#!/bin/sh
+#
+# This script performs additional setup for the RPC unit test. It
+# assumes that gmake has put TOP and RPC_TEST_SRVTAB into the
+# environment.
+#
+# $Id$
+# $Source$
+
+DUMMY=${TESTDIR=$TOP/testing}
+DUMMY=${CLNTTCL=$TESTDIR/util/ovsec_kadm_clnt_tcl}
+DUMMY=${TCLUTIL=$TESTDIR/tcl/util.t}; export TCLUTIL
+DUMMY=${MAKE_KEYTAB=$TESTDIR/scripts/make-host-keytab.pl}
+
+# If it's set, set it to true
+VERBOSE=${VERBOSE_TEST:+true}
+# Otherwise, set it to false
+DUMMY=${VERBOSE:=false}
+
+if $VERBOSE; then
+ REDIRECT=
+else
+ REDIRECT='>/dev/null'
+fi
+
+PATH=$TOP/install/admin:$PATH; export PATH
+
+CANON_HOST=`perl -e 'chop($_=\`hostname\`);($n,$a,$t,$l,@a)=gethostbyname($_);($_)=gethostbyaddr($a[0],$t); print;'`
+export CANON_HOST
+
+eval $CLNTTCL <<'EOF' $REDIRECT
+source $env(TCLUTIL)
+set h $env(CANON_HOST)
+puts stdout [ovsec_kadm_init admin admin $OVSEC_KADM_ADMIN_SERVICE null $OVSEC_KADM_STRUCT_VERSION $OVSEC_KADM_API_VERSION_1 server_handle]
+puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal server/$h] {OVSEC_KADM_PRINCIPAL} admin]
+puts stdout [ovsec_kadm_randkey_principal $server_handle server/$h key]
+puts stdout [ovsec_kadm_create_principal $server_handle [simple_principal notserver/$h] {OVSEC_KADM_PRINCIPAL} admin]
+puts stdout [ovsec_kadm_randkey_principal $server_handle notserver/$h key]
+puts stdout [ovsec_kadm_destroy $server_handle]
+EOF
+
+rm -f $RPC_TEST_SRVTAB
+
+eval $MAKE_KEYTAB -princ server/$CANON_HOST $RPC_TEST_SRVTAB $REDIRECT
+
+grep -s "$CANON_HOST SECURE-TEST.OV.COM" /etc/krb.realms
+if [ $? != 0 ]; then
+ eval echo \"Adding \$CANON_HOST SECURE-TEST.OV.COM to /etc/krb.realms\" $REDIRECT
+ ed /etc/krb.realms <<EOF >/dev/null
+1i
+$CANON_HOST SECURE-TEST.OV.COM
+.
+w
+q
+EOF
+fi
diff --git a/src/lib/rpc/xdr.c b/src/lib/rpc/xdr.c
new file mode 100644
index 0000000..7f44181
--- /dev/null
+++ b/src/lib/rpc/xdr.c
@@ -0,0 +1,674 @@
+/* @(#)xdr.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr.c 1.35 87/08/12";
+#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 <string.h>
+char *malloc();
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE ((rpc_int32) 0)
+#define XDR_TRUE ((rpc_int32) 1)
+#define LASTUNSIGNED ((unsigned 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, (rpc_int32 *)ip));
+#else
+ if (sizeof (int) >= 4) {
+ long l;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ l = *ip;
+ return (xdr_long(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!xdr_long(xdrs, &l)) {
+ return (FALSE);
+ }
+ *ip = l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ } else {
+ return (xdr_short(xdrs, (short *)ip));
+ }
+#endif
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ unsigned int *up;
+{
+#ifdef lint
+ (void) (xdr_short(xdrs, (short *)up));
+ return (xdr_u_long(xdrs, (rpc_u_int32 *)up));
+#else
+ if (sizeof (unsigned int) >= 4) {
+ unsigned long l;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ l = *up;
+ return (xdr_u_long(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!xdr_u_long(xdrs, &l)) {
+ return (FALSE);
+ }
+ *up = l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ } 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) {
+ if (sizeof (long) > 4) {
+ /* See if the dereferenced value fits in 4 bytes. If not, return FALSE.
+ * Check by loading value into a rpc_int32, then loading back and comparing
+ * results.
+ */
+ rpc_int32 i = (int) *lp;
+ long l = i;
+ if (l != *lp) {
+ return (FALSE);
+ }
+ }
+ 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;
+ unsigned long *ulp;
+{
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (sizeof (unsigned long) > 4) {
+ /* See if the dereferenced value fits in 4 bytes. If not, return FALSE.
+ * Check by loading value into a rpc_int32, then loading back and comparing
+ * results.
+ */
+ unsigned int ui = *ulp;
+ unsigned long ul = ui;
+ if (ul != *ulp) {
+ return (FALSE);
+ }
+ }
+ return (XDR_PUTLONG(xdrs, ulp));
+ }
+ if (xdrs->x_op == XDR_DECODE) {
+ return (XDR_GETLONG(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;
+ unsigned short *usp;
+{
+ unsigned long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (unsigned long) *usp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *usp = (unsigned 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;
+{
+ unsigned 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 (rpc_int32)) {
+ return (xdr_int32(xdrs, (rpc_int32 *)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 unsigned int cnt;
+{
+ register unsigned 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 unsigned int *sizep;
+ unsigned int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ register unsigned 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));
+}
+
+bool_t
+xdr_int32(xdrs, ip)
+ XDR *xdrs;
+ rpc_int32 *ip;
+{
+ long l;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ l = *ip;
+ return (xdr_long(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!xdr_long(xdrs, &l)) {
+ return (FALSE);
+ }
+ *ip = l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+}
+
+xdr_u_int32(xdrs, up)
+ XDR *xdrs;
+ rpc_u_int32 *up;
+{
+ unsigned long ul;
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul = *up;
+ return (xdr_u_long(xdrs, &ul));
+
+ case XDR_DECODE:
+ if (!xdr_u_long(xdrs, &ul)) {
+ return (FALSE);
+ }
+ *up = ul;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+}
+
+/*
+ * 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;
+ unsigned int maxsize;
+{
+ register char *sp = *cpp; /* sp is the actual string pointer */
+ unsigned int size;
+ unsigned 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/src/lib/rpc/xdr.h b/src/lib/rpc/xdr.h
new file mode 100644
index 0000000..9f0819b
--- /dev/null
+++ b/src/lib/rpc/xdr.h
@@ -0,0 +1,276 @@
+/* @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* @(#)xdr.h 1.19 87/04/22 SMI */
+
+/*
+ * xdr.h, External Data Representation Serialization Routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#ifndef __XDR_HEADER__
+#define __XDR_HEADER__
+
+/*
+ * 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 " */
+ unsigned int (*x_getpostn)();/* returns bytes off from beginning */
+ bool_t (*x_setpostn)();/* lets you reposition the stream */
+ rpc_int32 * (*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;
+ * rpc_int32 *longp;
+ * caddr_t addr;
+ * unsigned int len;
+ * unsigned 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((rpc_u_int32)*(buf)++))
+#define IXDR_PUT_LONG(buf, v) (*(buf)++ = (rpc_int32)htonl((rpc_u_int32)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) ((rpc_u_int32)IXDR_GET_LONG(buf))
+#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf))
+#define IXDR_GET_U_SHORT(buf) ((unsigned short)IXDR_GET_LONG(buf))
+
+#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), ((rpc_int32)(v)))
+
+/*
+ * These are the "generic" xdr routines.
+ */
+extern bool_t xdr_void();
+extern bool_t xdr_int(XDR *, int *);
+extern bool_t xdr_u_int(XDR *, unsigned int *);
+extern bool_t xdr_long(XDR *, long *);
+extern bool_t xdr_u_long(XDR *, unsigned long *);
+extern bool_t xdr_short(XDR *, short *);
+extern bool_t xdr_u_short(XDR *, unsigned short *);
+extern bool_t xdr_bool(XDR *, bool_t *);
+extern bool_t xdr_enum(XDR *, enum_t *);
+extern bool_t xdr_array(XDR *, caddr_t *, unsigned int*, unsigned int, unsigned int, xdrproc_t);
+extern bool_t xdr_bytes(XDR *, char **, unsigned int *, unsigned int);
+extern bool_t xdr_opaque(XDR *, caddr_t, unsigned int);
+extern bool_t xdr_string(XDR *, char **, unsigned int);
+extern bool_t xdr_union(XDR *, enum_t *, char *, struct xdr_discrim *, xdrproc_t);
+extern bool_t xdr_char(XDR *, char *);
+extern bool_t xdr_u_char(XDR *, char *);
+extern bool_t xdr_vector(XDR *, char *, unsigned int, unsigned int, xdrproc_t);
+extern bool_t xdr_float(XDR *, float *);
+extern bool_t xdr_double(XDR *, double *);
+extern bool_t xdr_reference(XDR *, caddr_t *, unsigned int, xdrproc_t);
+extern bool_t xdr_pointer(XDR *, char **, unsigned int, xdrproc_t);
+extern bool_t xdr_wrapstring(XDR *, char **);
+
+/*
+ * Common opaque bytes objects used by many rpc protocols;
+ * declared here due to commonality.
+ */
+#define MAX_NETOBJ_SZ 1024
+struct netobj {
+ unsigned int n_len;
+ char *n_bytes;
+};
+typedef struct netobj netobj;
+extern bool_t xdr_netobj(XDR *, struct netobj *);
+
+extern bool_t xdr_int32(XDR *, rpc_int32 *);
+extern bool_t xdr_u_int32(XDR *, rpc_u_int32 *);
+
+/*
+ * These are the public routines for the various implementations of
+ * xdr streams.
+ */
+extern void xdrmem_create(); /* XDR using memory buffers */
+extern void xdrstdio_create(); /* XDR using stdio library */
+extern void xdrrec_create(); /* XDR pseudo records for tcp */
+extern void xdralloc_create(); /* XDR allocating memory buffer */
+extern void xdralloc_release(); /* destroy xdralloc, save buf */
+extern bool_t xdrrec_endofrecord(); /* make end of xdr record */
+extern bool_t xdrrec_skiprecord(); /* move to beginning of next record */
+extern bool_t xdrrec_eof(); /* true if no more input */
+extern caddr_t xdralloc_getdata(); /* get buffer from xdralloc */
+
+#endif /* !__XDR_HEADER__ */
diff --git a/src/lib/rpc/xdr_alloc.c b/src/lib/rpc/xdr_alloc.c
new file mode 100644
index 0000000..37ae71e
--- /dev/null
+++ b/src/lib/rpc/xdr_alloc.c
@@ -0,0 +1,173 @@
+/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#endif
+
+/*
+ * Copyright 1993 OpenVision Technologies, Inc., All Rights Reserved.
+ *
+ * $Header$
+ *
+ * $Log$
+ * Revision 1.6 1996/07/22 20:41:21 marc
+ * this commit includes all the changes on the OV_9510_INTEGRATION and
+ * OV_MERGE branches. This includes, but is not limited to, the new openvision
+ * admin system, and major changes to gssapi to add functionality, and bring
+ * the implementation in line with rfc1964. before committing, the
+ * code was built and tested for netbsd and solaris.
+ *
+ * Revision 1.5.4.1 1996/07/18 04:19:49 marc
+ * merged in changes from OV_9510_BP to OV_9510_FINAL1
+ *
+ * Revision 1.5.2.1 1996/06/20 23:40:30 marc
+ * File added to the repository on a branch
+ *
+ * Revision 1.5 1996/05/12 06:19:25 marc
+ * renamed lots of types: u_foo to unsigned foo, and foo32 to rpc_foo32. This is to make autoconfiscation less painful.
+ *
+ * Revision 1.4 1995/12/13 14:03:14 grier
+ * Longs to ints for Alpha
+ *
+ * Revision 1.3 1993/12/09 18:57:25 bjaspan
+ * [secure-releng/833] misc bugfixes to admin library
+ *
+ * Revision 1.3 1993/12/06 21:23:08 bjaspan
+ * add xdralloc_release
+ *
+ * Revision 1.2 1993/10/26 21:13:19 bjaspan
+ * add casts for correctness
+ *
+ * Revision 1.1 1993/10/19 03:11:39 bjaspan
+ * Initial revision
+ *
+ */
+
+#if !defined(lint) && !defined(__CODECENTER__)
+static char *rcsid = "$Header$";
+#endif
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <dyn.h>
+
+static bool_t xdralloc_putlong();
+static bool_t xdralloc_putbytes();
+static unsigned int xdralloc_getpos();
+static rpc_int32 * xdralloc_inline();
+static void xdralloc_destroy();
+static bool_t xdralloc_notsup();
+
+static struct xdr_ops xdralloc_ops = {
+ xdralloc_notsup,
+ xdralloc_putlong,
+ xdralloc_notsup,
+ xdralloc_putbytes,
+ xdralloc_getpos,
+ xdralloc_notsup,
+ xdralloc_inline,
+ xdralloc_destroy,
+};
+
+/*
+ * The procedure xdralloc_create initializes a stream descriptor for a
+ * memory buffer.
+ */
+void xdralloc_create(xdrs, op)
+ register XDR *xdrs;
+ enum xdr_op op;
+{
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdralloc_ops;
+ xdrs->x_private = (caddr_t) DynCreate(sizeof(char), -4);
+ /* not allowed to fail */
+}
+
+caddr_t xdralloc_getdata(xdrs)
+ XDR *xdrs;
+{
+ return (caddr_t) DynGet((DynObject) xdrs->x_private, 0);
+}
+
+void xdralloc_release(xdrs)
+ XDR *xdrs;
+{
+ DynRelease((DynObject) xdrs->x_private);
+}
+
+static void xdralloc_destroy(xdrs)
+ XDR *xdrs;
+{
+ DynDestroy((DynObject) xdrs->x_private);
+}
+
+static bool_t xdralloc_notsup()
+{
+ return FALSE;
+}
+
+static bool_t xdralloc_putlong(xdrs, lp)
+ register XDR *xdrs;
+ rpc_int32 *lp;
+{
+ int l = htonl((rpc_u_int32) *(int *)lp);
+
+ if (DynInsert((DynObject) xdrs->x_private,
+ DynSize((DynObject) xdrs->x_private), &l,
+ sizeof(int)) != DYN_OK)
+ return FALSE;
+ return (TRUE);
+}
+
+static bool_t xdralloc_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register unsigned int len;
+{
+ if (DynInsert((DynObject) xdrs->x_private,
+ DynSize((DynObject) xdrs->x_private),
+ addr, len) != DYN_OK)
+ return FALSE;
+ return TRUE;
+}
+
+static unsigned int xdralloc_getpos(xdrs)
+ register XDR *xdrs;
+{
+ return DynSize((DynObject) xdrs->x_private);
+}
+
+
+static rpc_int32 *xdralloc_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ return (rpc_int32 *) 0;
+}
diff --git a/src/lib/rpc/xdr_array.c b/src/lib/rpc/xdr_array.c
new file mode 100644
index 0000000..09bd50a
--- /dev/null
+++ b/src/lib/rpc/xdr_array.c
@@ -0,0 +1,153 @@
+/* @(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+#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 <rpc/types.h>
+#include <rpc/xdr.h>
+
+#define LASTUNSIGNED ((unsigned 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 */
+ unsigned int *sizep; /* number of elements */
+ unsigned int maxsize; /* max numberof elements */
+ unsigned int elsize; /* size in bytes of each element */
+ xdrproc_t elproc; /* xdr routine to handle each element */
+{
+ register unsigned int i;
+ register caddr_t target = *addrp;
+ register unsigned int c; /* the actual element count */
+ register bool_t stat = TRUE;
+ register unsigned 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);
+ }
+ memset(target, 0, 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 unsigned int nelem;
+ register unsigned int elemsize;
+ register xdrproc_t xdr_elem;
+{
+ register unsigned 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/src/lib/rpc/xdr_float.c b/src/lib/rpc/xdr_float.c
new file mode 100644
index 0000000..0c153c4
--- /dev/null
+++ b/src/lib/rpc/xdr_float.c
@@ -0,0 +1,293 @@
+/* @(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+#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 <rpc/types.h>
+#include <rpc/xdr.h>
+
+/*
+ * NB: Not portable.
+ * This routine works on Suns (Sky / 68000's) and Vaxen.
+ */
+#ifdef IGNORE
+
+#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;
+{
+#if defined(vax)
+ struct ieee_single is;
+ struct vax_single vs, *vsp;
+ struct sgl_limits *lim;
+ int i;
+#endif
+ long lg;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#if !defined(vax)
+ lg = * (int_32 *) fp;
+ return (XDR_PUTLONG(xdrs, &lg));
+#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, (rpc_int32 *)&is));
+#endif
+
+ case XDR_DECODE:
+#if !defined(vax)
+ if (!(XDR_GETLONG(xdrs, &lg))) {
+ return (FALSE);
+ }
+ *fp = (float) ((int) lg);
+ return (TRUE);
+#else
+ vsp = (struct vax_single *)fp;
+ if (!XDR_GETLONG(xdrs, (rpc_int32 *)&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) 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 rpc_int32 *lp;
+#if defined(vax)
+ struct ieee_double id;
+ struct vax_double vd;
+ register struct dbl_limits *lim;
+ int i;
+#endif
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#if !defined(vax)
+ lp = (rpc_int32 *)dp;
+ if (sizeof(rpc_int32) == sizeof(long)) {
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+ } else {
+ long lg1 = *lp++;;
+ long lg2 = *lp;
+ return (XDR_PUTLONG(xdrs, &lg1) && XDR_PUTLONG(xdrs, &lg2));
+ }
+#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 = (rpc_int32 *)&id;
+ return (XDR_PUTLONG(xdrs, lp++) && XDR_PUTLONG(xdrs, lp));
+#endif
+
+ case XDR_DECODE:
+#if !defined(vax)
+ lp = (rpc_int32 *)dp;
+ if (sizeof(rpc_int32) == sizeof(long)) {
+ return (XDR_GETLONG(xdrs, lp++) && XDR_GETLONG(xdrs, lp));
+ } else {
+ long lg1, lg2;
+ bool_t flag =
+ (XDR_GETLONG(xdrs, &lg1) && XDR_GETLONG(xdrs, &lg2));
+ *lp++ = lg1;
+ *lp = lg2;
+ return flag;
+ }
+#else
+ lp = (rpc_int32 *)&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);
+}
+
+#endif /* IGNORE */
diff --git a/src/lib/rpc/xdr_mem.c b/src/lib/rpc/xdr_mem.c
new file mode 100644
index 0000000..39c0df2
--- /dev/null
+++ b/src/lib/rpc/xdr_mem.c
@@ -0,0 +1,188 @@
+/* @(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+#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>
+#include <stdio.h>
+
+static bool_t xdrmem_getlong();
+static bool_t xdrmem_putlong();
+static bool_t xdrmem_getbytes();
+static bool_t xdrmem_putbytes();
+static unsigned int xdrmem_getpos();
+static bool_t xdrmem_setpos();
+static rpc_int32 * 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;
+ unsigned 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(rpc_int32)) < 0)
+ return (FALSE);
+ *lp = (long)ntohl(*((rpc_u_int32 *)(xdrs->x_private)));
+ xdrs->x_private += sizeof(rpc_int32);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong(xdrs, lp)
+ register XDR *xdrs;
+ long *lp;
+{
+
+ if ((xdrs->x_handy -= sizeof(rpc_int32)) < 0)
+ return (FALSE);
+ *(rpc_int32 *)xdrs->x_private = (rpc_int32)htonl((rpc_u_int32)(*lp));
+ xdrs->x_private += sizeof(rpc_int32);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register unsigned int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memmove(addr, xdrs->x_private, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(xdrs, addr, len)
+ register XDR *xdrs;
+ caddr_t addr;
+ register unsigned int len;
+{
+
+ if ((xdrs->x_handy -= len) < 0)
+ return (FALSE);
+ memmove(xdrs->x_private, addr, len);
+ xdrs->x_private += len;
+ return (TRUE);
+}
+
+static unsigned int
+xdrmem_getpos(xdrs)
+ register XDR *xdrs;
+{
+/*
+ * 11/3/95 - JRG - Rather than recast everything for 64 bit, just convert
+ * pointers to longs, then cast to int.
+ */
+ return (unsigned int)((unsigned long)xdrs->x_private - (unsigned long)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(xdrs, pos)
+ register XDR *xdrs;
+ unsigned 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)((long)lastaddr - (long)newaddr);
+ return (TRUE);
+}
+
+static rpc_int32 *
+xdrmem_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ rpc_int32 *buf = 0;
+
+ if (xdrs->x_handy >= len) {
+ xdrs->x_handy -= len;
+ buf = (rpc_int32 *) xdrs->x_private;
+ xdrs->x_private += len;
+ }
+ return (buf);
+}
diff --git a/src/lib/rpc/xdr_rec.c b/src/lib/rpc/xdr_rec.c
new file mode 100644
index 0000000..99ce923
--- /dev/null
+++ b/src/lib/rpc/xdr_rec.c
@@ -0,0 +1,596 @@
+/* @(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+#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(rpc_u_int32). 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 <rpc/types.h>
+#include <rpc/xdr.h>
+#include <netinet/in.h>
+
+#include <unistd.h>
+
+static unsigned 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 unsigned int xdrrec_getpos();
+static bool_t xdrrec_setpos();
+static rpc_int32 * 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 an unsigned 32 bit integer 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 ((rpc_u_int32)(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 */
+ rpc_u_int32 *frag_header; /* beginning of curren fragment */
+ bool_t frag_sent; /* true if buffer sent in middle of record */
+ /*
+ * in-coming bits
+ */
+ int (*readit)();
+ rpc_u_int32 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 */
+ rpc_int32 fbtbc; /* fragment bytes to be consumed */
+ bool_t last_frag;
+ unsigned int sendsize;
+ unsigned 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 unsigned int sendsize;
+ register unsigned 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;
+ /* Pointer arithmetic - long cast allowed... */
+ (unsigned long)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 = (rpc_u_int32 *)rstrm->out_base;
+ rstrm->out_finger += sizeof(rpc_u_int32);
+ 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 rpc_int32 *buflp = (rpc_int32 *)(rstrm->in_finger);
+ int mylong;
+
+ /* first try the inline, fast case */
+ if ((rstrm->fbtbc >= sizeof(rpc_int32)) &&
+ (((long)rstrm->in_boundry - (long)buflp) >= sizeof(rpc_int32))) {
+ *lp = (long)ntohl((rpc_u_int32)(*buflp));
+ rstrm->fbtbc -= sizeof(rpc_int32);
+ rstrm->in_finger += sizeof(rpc_int32);
+ } else {
+ if (! xdrrec_getbytes(xdrs, (caddr_t)&mylong, sizeof(rpc_int32)))
+ return (FALSE);
+ *lp = (long)ntohl((unsigned int)mylong);
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register rpc_int32 *dest_lp = ((rpc_int32 *)(rstrm->out_finger));
+
+ if ((rstrm->out_finger += sizeof(rpc_int32)) > rstrm->out_boundry) {
+ /*
+ * this case should almost never happen so the code is
+ * inefficient
+ */
+ rstrm->out_finger -= sizeof(rpc_int32);
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ dest_lp = ((rpc_int32 *)(rstrm->out_finger));
+ rstrm->out_finger += sizeof(rpc_int32);
+ }
+ *dest_lp = (rpc_int32)htonl((rpc_u_int32)(*lp));
+ return (TRUE);
+}
+
+static bool_t /* must manage buffers, fragments, and records */
+xdrrec_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ register caddr_t addr;
+ register unsigned 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 unsigned int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ register int current;
+
+ while (len > 0) {
+ current = (int) ((long)rstrm->out_boundry -
+ (long)rstrm->out_finger);
+ current = (len < current) ? len : current;
+ memmove(rstrm->out_finger, addr, 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 unsigned int
+xdrrec_getpos(xdrs)
+ register XDR *xdrs;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ register int pos;
+
+/* 11/5/95 JRG HELP! lseek() can't take a pointer as the first arg
+ * This code must have always failed, and the failure let the arithmetic
+ * calculations proceed
+ */
+#ifdef __osf__
+ pos = -1;
+#else
+ pos = lseek((int)rstrm->tcp_handle, (long) 0, 1);
+#endif
+ 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 = (unsigned int) -1;
+ break;
+ }
+ return ((unsigned int) pos);
+}
+
+static bool_t
+xdrrec_setpos(xdrs, pos)
+ register XDR *xdrs;
+ unsigned int pos;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ unsigned 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 rpc_int32 *
+xdrrec_inline(xdrs, len)
+ register XDR *xdrs;
+ int len;
+{
+ register RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ rpc_int32 * buf = NULL;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
+ buf = (rpc_int32 *) rstrm->out_finger;
+ rstrm->out_finger += len;
+ }
+ break;
+
+ case XDR_DECODE:
+ if ((len <= rstrm->fbtbc) &&
+ ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
+ buf = (rpc_int32 *) 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 rpc_u_int32 len; /* fragment length */
+
+ if (sendnow || rstrm->frag_sent ||
+ ((long)rstrm->out_finger + sizeof(unsigned int) >=
+ (long)rstrm->out_boundry)) {
+ rstrm->frag_sent = FALSE;
+ return (flush_out(rstrm, TRUE));
+ }
+ len = (long)(rstrm->out_finger) - (long)(rstrm->frag_header) -
+ sizeof(unsigned int);
+ *(rstrm->frag_header) = htonl((unsigned int)len | LAST_FRAG);
+ rstrm->frag_header = (rpc_u_int32 *)rstrm->out_finger;
+ rstrm->out_finger += sizeof(unsigned int);
+ return (TRUE);
+}
+
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(rstrm, eor)
+ register RECSTREAM *rstrm;
+ bool_t eor;
+{
+ register rpc_u_int32 eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ register rpc_u_int32 len = (unsigned long)(rstrm->out_finger) -
+ (unsigned long)(rstrm->frag_header) - sizeof(rpc_u_int32);
+
+ *(rstrm->frag_header) = htonl(len | eormask);
+ len = (unsigned long)(rstrm->out_finger) - (unsigned long)(rstrm->out_base);
+ if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+ != (int)len)
+ return (FALSE);
+ rstrm->frag_header = (rpc_u_int32 *)rstrm->out_base;
+ rstrm->out_finger = (caddr_t)rstrm->out_base + sizeof(rpc_u_int32);
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+fill_input_buf(rstrm)
+ register RECSTREAM *rstrm;
+{
+ register caddr_t where;
+ unsigned int i;
+ register int len;
+
+ where = rstrm->in_base;
+ i = (unsigned int)((unsigned long)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)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ memmove(addr, rstrm->in_finger, 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;
+{
+ rpc_u_int32 header;
+
+ if (! get_input_bytes(rstrm, (caddr_t)&header, sizeof(header)))
+ return (FALSE);
+ header = (int)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;
+ rpc_int32 cnt;
+{
+ register int current;
+
+ while (cnt > 0) {
+ current = (int)((long)rstrm->in_boundry -
+ (long)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 unsigned int
+fix_buf_size(s)
+ register unsigned int s;
+{
+
+ if (s < 100)
+ s = 4000;
+ return (RNDUP(s));
+}
diff --git a/src/lib/rpc/xdr_reference.c b/src/lib/rpc/xdr_reference.c
new file mode 100644
index 0000000..ebf14b6
--- /dev/null
+++ b/src/lib/rpc/xdr_reference.c
@@ -0,0 +1,132 @@
+/* @(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
+#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 ((unsigned 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 */
+ unsigned 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);
+ }
+ memset(loc, 0, (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;
+ unsigned 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/src/lib/rpc/xdr_stdio.c b/src/lib/rpc/xdr_stdio.c
new file mode 100644
index 0000000..6d59ad5
--- /dev/null
+++ b/src/lib/rpc/xdr_stdio.c
@@ -0,0 +1,189 @@
+/* @(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC */
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+#if !defined(lint) && defined(SCCSIDS)
+static char sccsid[] = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
+#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 unsigned int xdrstdio_getpos();
+static bool_t xdrstdio_setpos();
+static rpc_int32 * 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;
+{
+ rpc_int32 tmp;
+ if (fread((caddr_t)&tmp,
+ sizeof(rpc_int32), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+#ifndef mc68000
+ *lp = ntohl(tmp);
+#endif
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+
+#ifndef mc68000
+ rpc_int32 mycopy = htonl((rpc_int32)*lp);
+#endif
+ if (fwrite((caddr_t)&mycopy, sizeof(rpc_int32), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ caddr_t addr;
+ unsigned 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;
+ unsigned int len;
+{
+
+ if ((len != 0) && (fwrite(addr, (int)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static unsigned int
+xdrstdio_getpos(xdrs)
+ XDR *xdrs;
+{
+
+ return ((unsigned int) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(xdrs, pos)
+ XDR *xdrs;
+ unsigned int pos;
+{
+
+ return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
+ FALSE : TRUE);
+}
+
+static rpc_int32 *
+xdrstdio_inline(xdrs, len)
+ XDR *xdrs;
+ unsigned 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);
+}