diff options
Diffstat (limited to 'REORG.TODO/sunrpc')
123 files changed, 29076 insertions, 0 deletions
diff --git a/REORG.TODO/sunrpc/Makefile b/REORG.TODO/sunrpc/Makefile new file mode 100644 index 0000000000..125d538208 --- /dev/null +++ b/REORG.TODO/sunrpc/Makefile @@ -0,0 +1,252 @@ +# Copyright (C) 1994-2017 Free Software Foundation, Inc. +# This file is part of the GNU C Library. + +# The GNU C Library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. + +# The GNU C Library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. + +# You should have received a copy of the GNU Lesser General Public +# License along with the GNU C Library; if not, see +# <http://www.gnu.org/licenses/>. + +# +# Sub-makefile for sunrpc portion of the library. +# +subdir := sunrpc + +include ../Makeconfig + +# The code in this subdirectory is taken from Sun's RPCSRC-4.0 +# distribution with some additional changes from the TI-RPC package +# which is also available from Sun. The files are heavily changed to +# compile cleanly and to fit in the GNU environment. All the code +# from Sun's rpc, etc, and rpcgen subdirectories is in this directory; +# the rpc subdirectory contains only the header files. Other than +# that, several files were renamed so as not to exceed 14-character +# file name limits: +# +# authunix_prot.c -> authuxprot.c +# bindresvport.c -> bindrsvprt.c +# clnt_generic.c -> clnt_gen.c +# clnt_perror.c -> clnt_perr.c +# clnt_simple.c -> clnt_simp.c +# get_myaddress.c -> get_myaddr.c +# pmap_getmaps.c -> pm_getmaps.c +# pmap_getport.c -> pm_getport.c +# rpc_callmsg.c -> rpc_cmsg.c +# rpc_commondata.c -> rpc_common.c +# rpc_dtablesize.c -> rpc_dtable.c +# svc_auth_unix.c -> svc_authux.c +# xdr_reference.c -> xdr_ref.c + +rpcsvc = bootparam_prot.x nlm_prot.x rstat.x \ + yppasswd.x klm_prot.x rex.x sm_inter.x mount.x \ + rusers.x spray.x nfs_prot.x rquota.x key_prot.x +headers-sunrpc = $(addprefix rpc/,auth.h auth_unix.h clnt.h pmap_clnt.h \ + pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h \ + svc.h svc_auth.h types.h xdr.h auth_des.h \ + des_crypt.h key_prot.h rpc_des.h) \ + $(rpcsvc:%=rpcsvc/%) rpcsvc/bootparam.h +headers = rpc/netdb.h +install-others = $(inst_sysconfdir)/rpc +generated += $(rpcsvc:%.x=rpcsvc/%.h) $(rpcsvc:%.x=x%.c) $(rpcsvc:%.x=x%.stmp) \ + $(rpcsvc:%.x=rpcsvc/%.stmp) rpcgen +generated-dirs += rpcsvc + +ifeq ($(link-obsolete-rpc),yes) +headers += $(headers-sunrpc) +endif + +ifeq ($(build-shared),yes) +need-export-routines := auth_des auth_unix clnt_gen clnt_perr clnt_tcp \ + clnt_udp get_myaddr key_call netname pm_getport \ + rpc_thread svc svc_tcp svc_udp xcrypt xdr_array xdr \ + xdr_intXX_t xdr_mem xdr_ref xdr_sizeof xdr_stdio \ + svc_run + +routines := auth_none authuxprot bindrsvprt clnt_raw clnt_simp \ + rpc_dtable getrpcport pmap_clnt pm_getmaps pmap_prot pmap_prot2 \ + pmap_rmt rpc_prot rpc_common rpc_cmsg svc_auth svc_authux svc_raw \ + svc_simple xdr_float xdr_rec publickey authdes_prot \ + des_crypt des_impl des_soft key_prot openchild rtime svcauth_des \ + getrpcent getrpcbyname getrpcbynumber \ + getrpcent_r getrpcbyname_r getrpcbynumber_r \ + clnt_unix svc_unix create_xid $(need-export-routines) \ + rpc_gethostbyname +ifneq ($(link-obsolete-rpc),yes) +# We only add the RPC for compatibility to libc.so. +shared-only-routines = $(routines) +endif +endif + +ifeq ($(link-obsolete-rpc),yes) +install-bin := rpcgen +rpcgen-objs = rpc_main.o rpc_hout.o rpc_cout.o rpc_parse.o \ + rpc_scan.o rpc_util.o rpc_svcout.o rpc_clntout.o \ + rpc_tblout.o rpc_sample.o +extra-objs = $(rpcgen-objs) $(addprefix cross-,$(rpcgen-objs)) +others += rpcgen +endif + +tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \ + tst-udp-nonblocking +xtests := tst-getmyaddr + +ifeq ($(have-thread-library),yes) +xtests += thrsvc +tests += tst-udp-garbage +tests-internal += tst-svc_register +endif + +ifeq ($(run-built-tests),yes) +ifeq ($(link-obsolete-rpc),yes) +rpcgen-tests := $(objpfx)bug20790.out +tests-special += $(rpcgen-tests) +endif +endif + +ifeq ($(link-obsolete-rpc),yes) +headers += $(rpcsvc:%.x=rpcsvc/%.h) +extra-libs := librpcsvc +extra-libs-others := librpcsvc # Make it in `others' pass, not `lib' pass. +librpcsvc-routines = $(rpcsvc:%.x=x%) +librpcsvc-inhibit-o = .os # Build no shared rpcsvc library. +omit-deps = $(librpcsvc-routines) +endif + +ifeq (yes,$(build-shared)) +rpc-compat-routines = $(addprefix compat-,$(need-export-routines)) +rpc-compat-routines.os = $(addprefix $(objpfx), \ + $(addsuffix .os,$(rpc-compat-routines))) +extra-objs += $(addsuffix .os,$(rpc-compat-routines)) +endif + +include ../Rules + +ifeq (yes,$(build-shared)) +subdir_lib: $(objpfx)librpc_compat_pic.a +$(objpfx)librpc_compat_pic.a: $(rpc-compat-routines.os) + $(AR) cr$(verbose) $@ $^ +$(rpc-compat-routines.os): $(objpfx)compat-%.os: %.c $(before-compile) + $(compile-command.c) -DEXPORT_RPC_SYMBOLS +endif + +CFLAGS-xbootparam_prot.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xnlm_prot.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xrstat.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xyppasswd.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xklm_prot.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xrex.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xsm_inter.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xmount.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xrusers.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xspray.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xnfs_prot.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xrquota.c = -Wno-unused $(PIC-ccflag) +CFLAGS-xkey_prot.c = -Wno-unused $(PIC-ccflag) +CFLAGS-auth_unix.c = -fexceptions +CFLAGS-key_call.c = -fexceptions +CFLAGS-pmap_rmt.c = -fexceptions +CFLAGS-clnt_perr.c = -fexceptions +CFLAGS-openchild.c = -fexceptions + +sunrpc-CPPFLAGS = -D_RPC_THREAD_SAFE_ +CPPFLAGS += $(sunrpc-CPPFLAGS) +BUILD_CPPFLAGS += $(sunrpc-CPPFLAGS) + +$(objpfx)tst-getmyaddr: $(common-objpfx)linkobj/libc.so +$(objpfx)tst-xdrmem: $(common-objpfx)linkobj/libc.so +$(objpfx)tst-xdrmem2: $(common-objpfx)linkobj/libc.so +$(objpfx)tst-udp-error: $(common-objpfx)linkobj/libc.so +$(objpfx)tst-svc_register: \ + $(common-objpfx)linkobj/libc.so $(shared-thread-library) + +$(objpfx)rpcgen: $(addprefix $(objpfx),$(rpcgen-objs)) + +cross-rpcgen-objs := $(addprefix $(objpfx)cross-,$(rpcgen-objs)) + +# When generic makefile support for build system programs is +# available, it should replace this code. See +# <http://sourceware.org/bugzilla/show_bug.cgi?id=14087>. +$(cross-rpcgen-objs): $(objpfx)cross-%.o: %.c $(before-compile) + $(BUILD_CC) $($(basename $(<F))-CFLAGS) $(ALL_BUILD_CFLAGS) $< \ + $(OUTPUT_OPTION) $(native-compile-mkdep-flags) -c + +$(objpfx)cross-rpcgen: $(cross-rpcgen-objs) + $(BUILD_CC) $^ $(BUILD_LDFLAGS) -o $@ + +# This makes sure -DIN_MODULE is passed for all these modules. +cpp-srcs-left := $(rpcgen-objs:.o=.c) +lib := nonlib +include $(patsubst %,$(..)libof-iterator.mk,$(cpp-srcs-left)) + +# How we run rpcgen to generate sources and headers in the rules below. +# Setting CPP tells it how to run the C preprocessor correctly. Note +# that $(built-program-file) requires that the just-built cross-rpcgen +# binary be the second dependency listed in each rule using rpcgen-cmd. +rpcgen-cmd = CPP='$(CC) -E -x c-header' $(built-program-file) -Y ../scripts + +# Install the rpc data base file. +$(inst_sysconfdir)/rpc: etc.rpc $(+force) + $(do-install) + +# Generate the rpcsvc headers with rpcgen. +# We use a stamp file to avoid unnessary recompilation each time rpcgen is +# relinked. +$(rpcsvc:%.x=$(objpfx)rpcsvc/%.h): $(objpfx)rpcsvc/%.h: $(objpfx)rpcsvc/%.stmp + @: +$(objpfx)rpcsvc/%.stmp: rpcsvc/%.x $(objpfx)cross-rpcgen + $(make-target-directory) + -@rm -f ${@:stmp=T} $@ + $(rpcgen-cmd) -h $< -o ${@:stmp=T} + $(move-if-change) $(@:stmp=T) $(@:stmp=h) + touch $@ + +# Generate the rpcsvc XDR functions with rpcgen. +$(rpcsvc:%.x=$(objpfx)x%.c): $(objpfx)x%.c: $(objpfx)x%.stmp + @: +$(objpfx)x%.stmp: rpcsvc/%.x $(objpfx)cross-rpcgen + -@rm -f ${@:stmp=T} $@ + $(rpcgen-cmd) -c $< -o ${@:stmp=T} + $(move-if-change) $(@:stmp=T) $(@:stmp=c) + touch $@ + +# The generated source files depend on the corresponding generated headers. +# Gratuitous dependency on generated .c file here just gets it mentioned to +# avoid being an intermediate file and getting removed. +define o-iterator-doit +$(rpcsvc:%.x=$(objpfx)x%$o): $(objpfx)x%$o: $(objpfx)x%.c $(objpfx)rpcsvc/%.h +endef +object-suffixes-left = $(filter-out $(librpcsvc-inhibit-o),$(object-suffixes)) +include $(o-iterator) + +rpcsvc-dt-files := $(foreach o,$(filter-out $(librpcsvc-inhibit-o),\ + $(object-suffixes)),\ + $(rpcsvc:%.x=$(objpfx)x%$o.dt)) +rpcsvc-depfiles := $(patsubst %.dt,%.d,$(wildcard $(rpcsvc-dt-files))) \ + $(wildcard $(rpcsvc-dt-files:.dt=.d)) +ifdef rpcsvc-depfiles +ifneq ($(no_deps),t) +-include $(rpcsvc-depfiles) +endif +endif + +$(objpfx)thrsvc: $(common-objpfx)linkobj/libc.so $(shared-thread-library) + +ifeq ($(run-built-tests),yes) +$(rpcgen-tests): $(objpfx)%.out: %.x $(objpfx)rpcgen + -rm -f $@ + $(built-program-cmd) -c $< -o $@; \ + $(evaluate-test) +endif + +$(objpfx)tst-udp-timeout: $(common-objpfx)linkobj/libc.so +$(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so +$(objpfx)tst-udp-garbage: \ + $(common-objpfx)linkobj/libc.so $(shared-thread-library) diff --git a/REORG.TODO/sunrpc/Versions b/REORG.TODO/sunrpc/Versions new file mode 100644 index 0000000000..77bc6a4c9b --- /dev/null +++ b/REORG.TODO/sunrpc/Versions @@ -0,0 +1,131 @@ +libc { + GLIBC_2.0 { + # global variables. + _null_auth; + + # functions used in other libraries + _rpc_dtablesize; _seterr_reply; + + # variables in normal name space + rpc_createerr; svc_fdset; svcauthdes_stats; + + # a* + authnone_create; authunix_create; authunix_create_default; + + # b* + bindresvport; + + # c* + callrpc; + clnt_broadcast; clnt_create; clnt_pcreateerror; clnt_perrno; + clnt_perror; clnt_spcreateerror; clnt_sperrno; clnt_sperror; + clntraw_create; clnttcp_create; clntudp_bufcreate; clntudp_create; + + # e* + endrpcent; + + # g* + get_myaddress; getpublickey; getsecretkey; + getrpcbyname; getrpcbyname_r; getrpcbynumber; getrpcbynumber_r; + getrpcent; getrpcent_r; getrpcport; + + # p* + pmap_getmaps; pmap_getport; pmap_rmtcall; pmap_set; pmap_unset; + + # r* + registerrpc; + + # s* + setrpcent; + svc_exit; svc_getreq; svc_getreqset; svc_register; svc_run; + svc_sendreply; svc_unregister; svcerr_auth; svcerr_decode; + svcerr_noproc; svcerr_noprog; svcerr_progvers; svcerr_systemerr; + svcerr_weakauth; svcfd_create; svcraw_create; svctcp_create; + svcudp_bufcreate; svcudp_create; svcudp_enablecache; + + # x* + xdr_accepted_reply; xdr_array; xdr_authunix_parms; xdr_bool; xdr_bytes; + xdr_callhdr; xdr_callmsg; xdr_char; xdr_cryptkeyarg; xdr_cryptkeyarg2; + xdr_cryptkeyres; xdr_des_block; xdr_double; xdr_enum; xdr_float; + xdr_free; xdr_int; xdr_key_netstarg; xdr_key_netstres; xdr_keybuf; + xdr_keystatus; xdr_long; xdr_netobj; xdr_opaque; xdr_opaque_auth; + xdr_pmap; xdr_pmaplist; xdr_pointer; xdr_reference; xdr_rejected_reply; + xdr_replymsg; xdr_rmtcall_args; xdr_rmtcallres; xdr_short; xdr_string; + xdr_u_char; xdr_u_int; xdr_u_long; xdr_u_short; xdr_union; xdr_vector; + xdr_void; xdr_wrapstring; xdrmem_create; xdrrec_create; + xdrrec_endofrecord; xdrrec_eof; xdrrec_skiprecord; xdrstdio_create; + xencrypt; xprt_register; xprt_unregister; + } + GLIBC_2.1 { + # Special Pointer to avoid keyserv deadlock + __key_decryptsession_pk_LOCAL; __key_encryptsession_pk_LOCAL; + __key_gendes_LOCAL; + + # _* + _authenticate; + + # a* + authdes_create; authdes_getucred; authdes_pk_create; + + # c* + cbc_crypt; clntunix_create; + + # d* + des_setparity; + + # e* + ecb_crypt; + + # g* + getnetname; + + # h* + host2netname; + + # k* + key_decryptsession; key_decryptsession_pk; key_encryptsession; + key_encryptsession_pk; key_gendes; key_get_conv; key_secretkey_is_set; + key_setnet; key_setsecret; + + # n* + netname2host; netname2user; + + # p* + passwd2des; + + # r* + rtime; + + # s* + svcunix_create; svcunixfd_create; + + # u* + user2netname; + + # x* + xdecrypt; xdr_authdes_cred; xdr_authdes_verf; + xdr_getcredres; xdr_int16_t; xdr_int32_t; xdr_int8_t; + xdr_netnamestr; xdr_sizeof; + xdr_uint16_t; xdr_uint32_t; xdr_uint8_t; xdr_unixcred; + } + GLIBC_2.1.1 { + xdr_hyper; xdr_u_hyper; xdr_longlong_t; xdr_u_longlong_t; + xdr_int64_t; xdr_uint64_t; + } + GLIBC_2.1.2 { + getrpcbyname_r; getrpcbynumber_r; getrpcent_r; + } + GLIBC_2.2 { + svc_getreq_common; svc_getreq_poll; svc_max_pollfd; svc_pollfd; + } + GLIBC_2.2.3 { + __rpc_thread_svc_fdset; __rpc_thread_createerr; + __rpc_thread_svc_pollfd; __rpc_thread_svc_max_pollfd; + } + GLIBC_2.3.4 { + xdr_quad_t; xdr_u_quad_t; + } + GLIBC_PRIVATE { + __libc_clntudp_bufcreate; __libc_rpc_getport; + } +} diff --git a/REORG.TODO/sunrpc/auth_des.c b/REORG.TODO/sunrpc/auth_des.c new file mode 100644 index 0000000000..42d6b552f4 --- /dev/null +++ b/REORG.TODO/sunrpc/auth_des.c @@ -0,0 +1,467 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * auth_des.c, client-side implementation of DES authentication + */ + +#include <string.h> +#include <stdint.h> +#include <rpc/des_crypt.h> +#include <rpc/types.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <rpc/xdr.h> +#include <netinet/in.h> /* XXX: just to get htonl() and ntohl() */ +#include <sys/socket.h> +#include <shlib-compat.h> + +#define MILLION 1000000L +#define RTIME_TIMEOUT 5 /* seconds to wait for sync */ + +#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private +#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type)) +#define FREE(ptr, size) mem_free((char *)(ptr), (int) size) +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +#define debug(msg) /* printf("%s\n", msg) */ + + +/* + * DES authenticator operations vector + */ +static void authdes_nextverf (AUTH *); +static bool_t authdes_marshal (AUTH *, XDR *); +static bool_t authdes_validate (AUTH *, struct opaque_auth *); +static bool_t authdes_refresh (AUTH *); +static void authdes_destroy (AUTH *); +static bool_t synchronize (struct sockaddr *, struct rpc_timeval *) + internal_function; + +static const struct auth_ops authdes_ops = { + authdes_nextverf, + authdes_marshal, + authdes_validate, + authdes_refresh, + authdes_destroy +}; + + +/* + * This struct is pointed to by the ah_private field of an "AUTH *" + */ +struct ad_private { + char *ad_fullname; /* client's full name */ + u_int ad_fullnamelen; /* length of name, rounded up */ + char *ad_servername; /* server's full name */ + u_int ad_servernamelen; /* length of name, rounded up */ + uint32_t ad_window; /* client specified window */ + bool_t ad_dosync; /* synchronize? */ + struct sockaddr ad_syncaddr; /* remote host to synch with */ + struct rpc_timeval ad_timediff; /* server's time - client's time */ + uint32_t ad_nickname; /* server's nickname for client */ + struct authdes_cred ad_cred; /* storage for credential */ + struct authdes_verf ad_verf; /* storage for verifier */ + struct rpc_timeval ad_timestamp; /* timestamp sent */ + des_block ad_xkey; /* encrypted conversation key */ + u_char ad_pkey[1024]; /* Servers actual public key */ +}; + + +/* + * Create the client des authentication object + */ +AUTH * +authdes_create (const char *servername, u_int window, + struct sockaddr *syncaddr, des_block *ckey) + /* servername - network name of server */ + /* window - time to live */ + /* syncaddr - optional addr of host to sync with */ + /* ckey - optional conversation key to use */ +{ + char pkey_data[1024]; + netobj pkey; + + if (!getpublickey (servername, pkey_data)) + return NULL; + + pkey.n_bytes = pkey_data; + pkey.n_len = strlen (pkey_data) + 1; + return authdes_pk_create (servername, &pkey, window, syncaddr, ckey); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (authdes_create) +#else +libc_hidden_nolink_sunrpc (authdes_create, GLIBC_2_1) +#endif + +AUTH * +authdes_pk_create (const char *servername, netobj *pkey, u_int window, + struct sockaddr *syncaddr, des_block *ckey) +{ + AUTH *auth; + struct ad_private *ad; + char namebuf[MAXNETNAMELEN + 1]; + + /* + * Allocate everything now + */ + auth = ALLOC (AUTH); + ad = ALLOC (struct ad_private); + + if (auth == NULL || ad == NULL) + { + debug ("authdes_create: out of memory"); + goto failed; + } + + memset (ad, 0, sizeof (struct ad_private)); + memcpy (ad->ad_pkey, pkey->n_bytes, pkey->n_len); + if (!getnetname (namebuf)) + goto failed; + ad->ad_fullnamelen = RNDUP (strlen (namebuf)); + ad->ad_fullname = mem_alloc (ad->ad_fullnamelen + 1); + + ad->ad_servernamelen = strlen (servername); + ad->ad_servername = mem_alloc (ad->ad_servernamelen + 1); + + if (ad->ad_fullname == NULL || ad->ad_servername == NULL) + { + debug ("authdes_create: out of memory"); + goto failed; + } + + /* + * Set up private data + */ + memcpy (ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); + memcpy (ad->ad_servername, servername, ad->ad_servernamelen + 1); + ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0; + if (syncaddr != NULL) + { + ad->ad_syncaddr = *syncaddr; + ad->ad_dosync = TRUE; + } + else + ad->ad_dosync = FALSE; + + ad->ad_window = window; + if (ckey == NULL) + { + if (key_gendes (&auth->ah_key) < 0) + { + debug ("authdes_create: unable to gen conversation key"); + goto failed; + } + } + else + auth->ah_key = *ckey; + + /* + * Set up auth handle + */ + auth->ah_cred.oa_flavor = AUTH_DES; + auth->ah_verf.oa_flavor = AUTH_DES; + auth->ah_ops = (struct auth_ops *) &authdes_ops; + auth->ah_private = (caddr_t) ad; + + if (!authdes_refresh (auth)) + goto failed; + + return auth; + +failed: + if (auth != NULL) + FREE (auth, sizeof (AUTH)); + if (ad != NULL) + { + if (ad->ad_fullname != NULL) + FREE (ad->ad_fullname, ad->ad_fullnamelen + 1); + if (ad->ad_servername != NULL) + FREE (ad->ad_servername, ad->ad_servernamelen + 1); + FREE (ad, sizeof (struct ad_private)); + } + return NULL; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (authdes_pk_create) +#else +libc_hidden_nolink_sunrpc (authdes_pk_create, GLIBC_2_1) +#endif + +/* + * Implement the five authentication operations + */ + + +/* + * 1. Next Verifier + */ +/*ARGSUSED */ +static void +authdes_nextverf (AUTH *auth) +{ + /* what the heck am I supposed to do??? */ +} + + + +/* + * 2. Marshal + */ +static bool_t +authdes_marshal (AUTH *auth, XDR *xdrs) +{ + struct ad_private *ad = AUTH_PRIVATE (auth); + struct authdes_cred *cred = &ad->ad_cred; + struct authdes_verf *verf = &ad->ad_verf; + des_block cryptbuf[2]; + des_block ivec; + int status; + int len; + register int32_t *ixdr; + struct timeval tval; + + /* + * Figure out the "time", accounting for any time difference + * with the server if necessary. + */ + __gettimeofday (&tval, (struct timezone *) NULL); + ad->ad_timestamp.tv_sec = tval.tv_sec + ad->ad_timediff.tv_sec; + ad->ad_timestamp.tv_usec = tval.tv_usec + ad->ad_timediff.tv_usec; + if (ad->ad_timestamp.tv_usec >= MILLION) + { + ad->ad_timestamp.tv_usec -= MILLION; + ad->ad_timestamp.tv_sec += 1; + } + + /* + * XDR the timestamp and possibly some other things, then + * encrypt them. + * XXX We have a real Year 2038 problem here. + */ + ixdr = (int32_t *) cryptbuf; + IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_sec); + IXDR_PUT_INT32 (ixdr, ad->ad_timestamp.tv_usec); + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) + { + IXDR_PUT_U_INT32 (ixdr, ad->ad_window); + IXDR_PUT_U_INT32 (ixdr, ad->ad_window - 1); + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt ((char *) &auth->ah_key, (char *) cryptbuf, + 2 * sizeof (des_block), DES_ENCRYPT | DES_HW, (char *) &ivec); + } + else + status = ecb_crypt ((char *) &auth->ah_key, (char *) cryptbuf, + sizeof (des_block), DES_ENCRYPT | DES_HW); + + if (DES_FAILED (status)) + { + debug ("authdes_marshal: DES encryption failure"); + return FALSE; + } + ad->ad_verf.adv_xtimestamp = cryptbuf[0]; + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) + { + ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; + ad->ad_verf.adv_winverf = cryptbuf[1].key.low; + } + else + { + ad->ad_cred.adc_nickname = ad->ad_nickname; + ad->ad_verf.adv_winverf = 0; + } + + /* + * Serialize the credential and verifier into opaque + * authentication data. + */ + if (ad->ad_cred.adc_namekind == ADN_FULLNAME) + len = ((1 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); + else + len = (1 + 1) * BYTES_PER_XDR_UNIT; + + if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) + { + IXDR_PUT_INT32 (ixdr, AUTH_DES); + IXDR_PUT_U_INT32 (ixdr, len); + } + else + { + ATTEMPT (xdr_putint32 (xdrs, &auth->ah_cred.oa_flavor)); + ATTEMPT (xdr_putint32 (xdrs, &len)); + } + ATTEMPT (xdr_authdes_cred (xdrs, cred)); + + len = (2 + 1) * BYTES_PER_XDR_UNIT; + if ((ixdr = xdr_inline (xdrs, 2 * BYTES_PER_XDR_UNIT)) != NULL) + { + IXDR_PUT_INT32 (ixdr, AUTH_DES); + IXDR_PUT_U_INT32 (ixdr, len); + } + else + { + ATTEMPT (xdr_putint32 (xdrs, &auth->ah_verf.oa_flavor)); + ATTEMPT (xdr_putint32 (xdrs, &len)); + } + ATTEMPT (xdr_authdes_verf (xdrs, verf)); + + return TRUE; +} + + +/* + * 3. Validate + */ +static bool_t +authdes_validate (AUTH *auth, struct opaque_auth *rverf) +{ + struct ad_private *ad = AUTH_PRIVATE (auth); + struct authdes_verf verf; + int status; + register uint32_t *ixdr; + + if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) + return FALSE; + + ixdr = (uint32_t *) rverf->oa_base; + verf.adv_xtimestamp.key.high = *ixdr++; + verf.adv_xtimestamp.key.low = *ixdr++; + verf.adv_int_u = *ixdr++; /* nickname not XDR'd ! */ + + /* + * Decrypt the timestamp + */ + status = ecb_crypt ((char *) &auth->ah_key, (char *) &verf.adv_xtimestamp, + sizeof (des_block), DES_DECRYPT | DES_HW); + + if (DES_FAILED (status)) + { + debug ("authdes_validate: DES decryption failure"); + return FALSE; + } + + /* + * xdr the decrypted timestamp + */ + ixdr = (uint32_t *) verf.adv_xtimestamp.c; + verf.adv_timestamp.tv_sec = IXDR_GET_U_INT32 (ixdr) + 1; + verf.adv_timestamp.tv_usec = IXDR_GET_U_INT32 (ixdr); + + /* + * validate + */ + if (memcmp ((char *) &ad->ad_timestamp, (char *) &verf.adv_timestamp, + sizeof (struct rpc_timeval)) != 0) + { + debug ("authdes_validate: verifier mismatch\n"); + return FALSE; + } + + /* + * We have a nickname now, let's use it + */ + ad->ad_nickname = verf.adv_nickname; + ad->ad_cred.adc_namekind = ADN_NICKNAME; + return TRUE; +} + +/* + * 4. Refresh + */ +static bool_t +authdes_refresh (AUTH *auth) +{ + netobj pkey; + struct ad_private *ad = AUTH_PRIVATE (auth); + struct authdes_cred *cred = &ad->ad_cred; + + if (ad->ad_dosync && !synchronize (&ad->ad_syncaddr, &ad->ad_timediff)) + { + /* + * Hope the clocks are synced! + */ + ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0; + debug ("authdes_refresh: unable to synchronize with server"); + } + ad->ad_xkey = auth->ah_key; + pkey.n_bytes = (char *) (ad->ad_pkey); + pkey.n_len = strlen ((char *) ad->ad_pkey) + 1; + if (key_encryptsession_pk (ad->ad_servername, &pkey, &ad->ad_xkey) < 0) + { + debug ("authdes_create: unable to encrypt conversation key"); + return FALSE; + } + cred->adc_fullname.key = ad->ad_xkey; + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = ad->ad_fullname; + return TRUE; +} + +/* + * 5. Destroy + */ +static void +authdes_destroy (AUTH *auth) +{ + struct ad_private *ad = AUTH_PRIVATE (auth); + + FREE (ad->ad_fullname, ad->ad_fullnamelen + 1); + FREE (ad->ad_servername, ad->ad_servernamelen + 1); + FREE (ad, sizeof (struct ad_private)); + FREE (auth, sizeof (AUTH)); +} + +/* + * Synchronize with the server at the given address, that is, + * adjust timep to reflect the delta between our clocks + */ +static bool_t +internal_function +synchronize (struct sockaddr *syncaddr, struct rpc_timeval *timep) +{ + struct timeval mytime; + struct rpc_timeval timeout; + + timeout.tv_sec = RTIME_TIMEOUT; + timeout.tv_usec = 0; + if (rtime ((struct sockaddr_in *) syncaddr, timep, &timeout) < 0) + return FALSE; + + __gettimeofday (&mytime, (struct timezone *) NULL); + timep->tv_sec -= mytime.tv_sec; + if (mytime.tv_usec > timep->tv_usec) + { + timep->tv_sec -= 1; + timep->tv_usec += MILLION; + } + timep->tv_usec -= mytime.tv_usec; + return TRUE; +} diff --git a/REORG.TODO/sunrpc/auth_none.c b/REORG.TODO/sunrpc/auth_none.c new file mode 100644 index 0000000000..b1effb7a00 --- /dev/null +++ b/REORG.TODO/sunrpc/auth_none.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * auth_none.c + * Creates a client authentication handle for passing "null" + * credentials and verifiers to remote systems. + */ + +#include <rpc/rpc.h> +#include <libc-lock.h> +#include <shlib-compat.h> + +#define MAX_MARSHAL_SIZE 20 + +/* + * Authenticator operations routines + */ +static void authnone_verf (AUTH *); +static void authnone_destroy (AUTH *); +static bool_t authnone_marshal (AUTH *, XDR *); +static bool_t authnone_validate (AUTH *, struct opaque_auth *); +static bool_t authnone_refresh (AUTH *); + +static const struct auth_ops ops = { + authnone_verf, + authnone_marshal, + authnone_validate, + authnone_refresh, + authnone_destroy +}; + +/* Internal data and routines */ + +struct authnone_private_s { + AUTH no_client; + char marshalled_client[MAX_MARSHAL_SIZE]; + u_int mcnt; +}; + +static struct authnone_private_s authnone_private; +__libc_once_define(static, authnone_private_guard); + +static void authnone_create_once (void); + +static void +authnone_create_once (void) +{ + struct authnone_private_s *ap; + XDR xdr_stream; + XDR *xdrs; + + ap = &authnone_private; + + ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; + ap->no_client.ah_ops = (struct auth_ops *) &ops; + xdrs = &xdr_stream; + xdrmem_create (xdrs, ap->marshalled_client, + (u_int) MAX_MARSHAL_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); +} + +AUTH * +authnone_create (void) +{ + __libc_once (authnone_private_guard, authnone_create_once); + return &authnone_private.no_client; +} +libc_hidden_nolink_sunrpc (authnone_create, GLIBC_2_0) + +static bool_t +authnone_marshal (AUTH *client, XDR *xdrs) +{ + struct authnone_private_s *ap; + + /* authnone_create returned authnone_private->no_client, which is + the first field of struct authnone_private_s. */ + ap = (struct authnone_private_s *) client; + if (ap == NULL) + return FALSE; + return (*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt); +} + +static void +authnone_verf (AUTH *auth) +{ +} + +static bool_t +authnone_validate (AUTH *auth, struct opaque_auth *oa) +{ + return TRUE; +} + +static bool_t +authnone_refresh (AUTH *auth) +{ + return FALSE; +} + +static void +authnone_destroy (AUTH *auth) +{ +} diff --git a/REORG.TODO/sunrpc/auth_unix.c b/REORG.TODO/sunrpc/auth_unix.c new file mode 100644 index 0000000000..b71612cd80 --- /dev/null +++ b/REORG.TODO/sunrpc/auth_unix.c @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2010, 2011, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * auth_unix.c, Implements UNIX style authentication parameters. + * + * 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 <errno.h> +#include <limits.h> +#include <stdbool.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <libintl.h> +#include <sys/param.h> +#include <wchar.h> +#include <shlib-compat.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 (AUTH *); +static bool_t authunix_marshal (AUTH *, XDR *); +static bool_t authunix_validate (AUTH *, struct opaque_auth *); +static bool_t authunix_refresh (AUTH *); +static void authunix_destroy (AUTH *); + +static const struct auth_ops auth_unix_ops = { + authunix_nextverf, + authunix_marshal, + authunix_validate, + authunix_refresh, + authunix_destroy +}; + +/* + * This struct is pointed to by the ah_private field of an auth_handle. + */ +struct audata { + struct opaque_auth au_origcred; /* original credentials */ + struct opaque_auth au_shcred; /* short hand cred */ + u_long au_shfaults; /* short hand cache faults */ + char au_marshed[MAX_AUTH_BYTES]; + u_int au_mpos; /* xdr pos at end of marshed */ +}; +#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) + +static bool_t marshal_new_auth (AUTH *) internal_function; + + +/* + * Create a unix style authenticator. + * Returns an auth handle with the given stuff in it. + */ +AUTH * +authunix_create (char *machname, uid_t uid, gid_t gid, int len, + gid_t *aup_gids) +{ + struct authunix_parms aup; + char mymem[MAX_AUTH_BYTES]; + struct timeval now; + XDR xdrs; + AUTH *auth; + struct audata *au; + + /* + * Allocate and set up auth handle + */ + auth = (AUTH *) mem_alloc (sizeof (*auth)); + au = (struct audata *) mem_alloc (sizeof (*au)); + if (auth == NULL || au == NULL) + { +no_memory: + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + mem_free (auth, sizeof (*auth)); + mem_free (au, sizeof (*au)); + return NULL; + } + auth->ah_ops = (struct auth_ops *) &auth_unix_ops; + auth->ah_private = (caddr_t) au; + auth->ah_verf = au->au_shcred = _null_auth; + au->au_shfaults = 0; + + /* + * fill in param struct from the given params + */ + (void) __gettimeofday (&now, (struct timezone *) 0); + aup.aup_time = now.tv_sec; + aup.aup_machname = machname; + aup.aup_uid = uid; + aup.aup_gid = gid; + aup.aup_len = (u_int) len; + aup.aup_gids = aup_gids; + + /* + * Serialize the parameters into origcred + */ + xdrmem_create (&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); + if (!xdr_authunix_parms (&xdrs, &aup)) + abort (); + au->au_origcred.oa_length = len = XDR_GETPOS (&xdrs); + au->au_origcred.oa_flavor = AUTH_UNIX; + au->au_origcred.oa_base = mem_alloc ((u_int) len); + if (au->au_origcred.oa_base == NULL) + goto no_memory; + memcpy(au->au_origcred.oa_base, mymem, (u_int) len); + + /* + * set auth handle to reflect new cred. + */ + auth->ah_cred = au->au_origcred; + marshal_new_auth (auth); + return auth; +} +libc_hidden_nolink_sunrpc (authunix_create, GLIBC_2_0) + +/* + * Returns an auth handle with parameters determined by doing lots of + * syscalls. + */ +AUTH * +authunix_create_default (void) +{ + char machname[MAX_MACHINE_NAME + 1]; + + if (__gethostname (machname, MAX_MACHINE_NAME) == -1) + abort (); + machname[MAX_MACHINE_NAME] = 0; + uid_t uid = __geteuid (); + gid_t gid = __getegid (); + + int max_nr_groups; + /* When we have to try a second time, do not use alloca() again. We + might have reached the stack limit already. */ + bool retry = false; + again: + /* Ask the kernel how many groups there are exactly. Note that we + might have to redo all this if the number of groups has changed + between the two calls. */ + max_nr_groups = __getgroups (0, NULL); + + /* Just some random reasonable stack limit. */ +#define ALLOCA_LIMIT (1024 / sizeof (gid_t)) + gid_t *gids = NULL; + if (max_nr_groups < ALLOCA_LIMIT && ! retry) + gids = (gid_t *) alloca (max_nr_groups * sizeof (gid_t)); + else + { + gids = (gid_t *) malloc (max_nr_groups * sizeof (gid_t)); + if (gids == NULL) + return NULL; + } + + int len = __getgroups (max_nr_groups, gids); + if (len == -1) + { + if (errno == EINVAL) + { + /* New groups added in the meantime. Try again. */ + if (max_nr_groups >= ALLOCA_LIMIT || retry) + free (gids); + retry = true; + goto again; + } + /* No other error can happen. */ + abort (); + } + + /* This braindamaged Sun code forces us here to truncate the + list of groups to NGRPS members since the code in + authuxprot.c transforms a fixed array. Grrr. */ + AUTH *result = authunix_create (machname, uid, gid, MIN (NGRPS, len), gids); + + if (max_nr_groups >= ALLOCA_LIMIT || retry) + free (gids); + + return result; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (authunix_create_default) +#else +libc_hidden_nolink_sunrpc (authunix_create_default, GLIBC_2_0) +#endif + +/* + * authunix operations + */ + +static void +authunix_nextverf (AUTH *auth) +{ + /* no action necessary */ +} + +static bool_t +authunix_marshal (AUTH *auth, XDR *xdrs) +{ + struct audata *au = AUTH_PRIVATE (auth); + + return XDR_PUTBYTES (xdrs, au->au_marshed, au->au_mpos); +} + +static bool_t +authunix_validate (AUTH *auth, struct opaque_auth *verf) +{ + 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 *auth) +{ + struct audata *au = AUTH_PRIVATE (auth); + struct authunix_parms aup; + struct timeval now; + XDR xdrs; + 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 = (gid_t *) 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 *auth) +{ + 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 +internal_function +marshal_new_auth (AUTH *auth) +{ + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + 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_unix.c: Fatal marshalling problem")); + else + au->au_mpos = XDR_GETPOS (xdrs); + + XDR_DESTROY (xdrs); + + return TRUE; +} diff --git a/REORG.TODO/sunrpc/authdes_prot.c b/REORG.TODO/sunrpc/authdes_prot.c new file mode 100644 index 0000000000..93b7cfc04b --- /dev/null +++ b/REORG.TODO/sunrpc/authdes_prot.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * authdes_prot.c, XDR routines for DES authentication + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <shlib-compat.h> + +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +bool_t +xdr_authdes_cred (XDR *xdrs, struct authdes_cred *cred) +{ + /* + * Unrolled xdr + */ + ATTEMPT (xdr_enum (xdrs, (enum_t *) & cred->adc_namekind)); + switch (cred->adc_namekind) + { + case ADN_FULLNAME: + ATTEMPT (xdr_string (xdrs, &cred->adc_fullname.name, MAXNETNAMELEN)); + ATTEMPT (xdr_opaque (xdrs, (caddr_t) & cred->adc_fullname.key, + sizeof (des_block))); + ATTEMPT (xdr_opaque (xdrs, (caddr_t) & cred->adc_fullname.window, + sizeof (cred->adc_fullname.window))); + return (TRUE); + case ADN_NICKNAME: + ATTEMPT (xdr_opaque (xdrs, (caddr_t) & cred->adc_nickname, + sizeof (cred->adc_nickname))); + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_authdes_cred, GLIBC_2_1) + + +bool_t +xdr_authdes_verf (register XDR *xdrs, register struct authdes_verf *verf) +{ + /* + * Unrolled xdr + */ + ATTEMPT (xdr_opaque (xdrs, (caddr_t) & verf->adv_xtimestamp, + sizeof (des_block))); + ATTEMPT (xdr_opaque (xdrs, (caddr_t) & verf->adv_int_u, + sizeof (verf->adv_int_u))); + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_authdes_verf, GLIBC_2_1) diff --git a/REORG.TODO/sunrpc/authuxprot.c b/REORG.TODO/sunrpc/authuxprot.c new file mode 100644 index 0000000000..14fe9f56c8 --- /dev/null +++ b/REORG.TODO/sunrpc/authuxprot.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * authunix_prot.c + * XDR for UNIX style authentication parameters for RPC + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_unix.h> +#include <shlib-compat.h> + +/* + * XDR for unix authentication parameters. + * Unfortunately, none of these can be declared const. + */ +bool_t +xdr_authunix_parms (XDR * xdrs, struct authunix_parms *p) +{ + if (xdr_u_long (xdrs, &(p->aup_time)) + && xdr_string (xdrs, &(p->aup_machname), MAX_MACHINE_NAME) + && (sizeof (uid_t) == sizeof (short int) + ? xdr_u_short (xdrs, (u_short *) & (p->aup_uid)) + : xdr_u_int (xdrs, (u_int *) & (p->aup_uid))) + && (sizeof (gid_t) == sizeof (short int) + ? xdr_u_short (xdrs, (u_short *) & (p->aup_gid)) + : xdr_u_int (xdrs, (u_int *) & (p->aup_gid))) + && xdr_array (xdrs, (caddr_t *) & (p->aup_gids), + & (p->aup_len), NGRPS, sizeof (gid_t), + (sizeof (gid_t) == sizeof (short int) + ? (xdrproc_t) xdr_u_short + : (xdrproc_t) xdr_u_int))) + { + return TRUE; + } + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_authunix_parms, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/bindrsvprt.c b/REORG.TODO/sunrpc/bindrsvprt.c new file mode 100644 index 0000000000..13bcb27d4d --- /dev/null +++ b/REORG.TODO/sunrpc/bindrsvprt.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <errno.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <libc-lock.h> + +/* + * Locks the static variables in this file. + */ +__libc_lock_define_initialized (static, lock); + +/* + * Bind a socket to a privileged IP port + */ +int +bindresvport (int sd, struct sockaddr_in *sin) +{ + static short port; + struct sockaddr_in myaddr; + int i; + +#define STARTPORT 600 +#define LOWPORT 512 +#define ENDPORT (IPPORT_RESERVED - 1) +#define NPORTS (ENDPORT - STARTPORT + 1) + static short startport = STARTPORT; + + if (sin == (struct sockaddr_in *) 0) + { + sin = &myaddr; + __bzero (sin, sizeof (*sin)); + sin->sin_family = AF_INET; + } + else if (sin->sin_family != AF_INET) + { + __set_errno (EAFNOSUPPORT); + return -1; + } + + if (port == 0) + { + port = (__getpid () % NPORTS) + STARTPORT; + } + + /* Initialize to make gcc happy. */ + int res = -1; + + int nports = ENDPORT - startport + 1; + int endport = ENDPORT; + + __libc_lock_lock (lock); + + again: + for (i = 0; i < nports; ++i) + { + sin->sin_port = htons (port++); + if (port > endport) + port = startport; + res = __bind (sd, sin, sizeof (struct sockaddr_in)); + if (res >= 0 || errno != EADDRINUSE) + break; + } + + if (i == nports && startport != LOWPORT) + { + startport = LOWPORT; + endport = STARTPORT - 1; + nports = STARTPORT - LOWPORT; + port = LOWPORT + port % (STARTPORT - LOWPORT); + goto again; + } + + __libc_lock_unlock (lock); + + return res; +} +libc_hidden_def (bindresvport) diff --git a/REORG.TODO/sunrpc/bug20790.x b/REORG.TODO/sunrpc/bug20790.x new file mode 100644 index 0000000000..a00c9b3830 --- /dev/null +++ b/REORG.TODO/sunrpc/bug20790.x @@ -0,0 +1 @@ +program TPROG { version TVERS { int FUNC(int aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa) = 1; } = 1; } = 1; diff --git a/REORG.TODO/sunrpc/clnt_gen.c b/REORG.TODO/sunrpc/clnt_gen.c new file mode 100644 index 0000000000..542f85dd35 --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_gen.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <alloca.h> +#include <errno.h> +#include <string.h> +#include <rpc/rpc.h> +#include <sys/socket.h> +#include <netdb.h> +#include <shlib-compat.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 (const char *hostname, u_long prog, u_long vers, + const char *proto) +{ + struct protoent protobuf, *p; + size_t prtbuflen; + char *prttmpbuf; + struct sockaddr_in sin; + struct sockaddr_un sun; + int sock; + struct timeval tv; + CLIENT *client; + + if (strcmp (proto, "unix") == 0) + { + __bzero ((char *)&sun, sizeof (sun)); + sun.sun_family = AF_UNIX; + strcpy (sun.sun_path, hostname); + sock = RPC_ANYSOCK; + client = clntunix_create (&sun, prog, vers, &sock, 0, 0); + if (client == NULL) + return NULL; +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + tv.tv_usec = 0; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + return client; + } + + if (__libc_rpc_gethostbyname (hostname, &sin) != 0) + return NULL; + + prtbuflen = 1024; + prttmpbuf = __alloca (prtbuflen); + while (__getprotobyname_r (proto, &protobuf, prttmpbuf, prtbuflen, &p) != 0 + || p == NULL) + if (errno != ERANGE) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_UNKNOWNPROTO; + ce->cf_error.re_errno = EPFNOSUPPORT; + return NULL; + } + else + { + /* Enlarge the buffer. */ + prtbuflen *= 2; + prttmpbuf = __alloca (prtbuflen); + } + + 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; + } +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + break; + case IPPROTO_TCP: + client = clnttcp_create (&sin, prog, vers, &sock, 0, 0); + if (client == NULL) + { + return NULL; + } +#if 0 + /* This is not wanted. This would disable the user from having + a timeout in the clnt_call() call. Only a call to cnlt_control() + by the user should set the timeout value. */ + tv.tv_sec = 25; + tv.tv_usec = 0; + clnt_control (client, CLSET_TIMEOUT, (char *)&tv); +#endif + break; + default: + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EPFNOSUPPORT; + } + return (NULL); + } + return client; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (clnt_create) +#else +libc_hidden_nolink_sunrpc (clnt_create, GLIBC_2_0) +#endif diff --git a/REORG.TODO/sunrpc/clnt_perr.c b/REORG.TODO/sunrpc/clnt_perr.c new file mode 100644 index 0000000000..f682243eae --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_perr.c @@ -0,0 +1,397 @@ +/* + * clnt_perror.c + * + * Copyright (c) 2010, 2011, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdio.h> +#include <string.h> +#include <libintl.h> +#include <rpc/rpc.h> +#include <wchar.h> +#include <libio/iolibio.h> +#include <shlib-compat.h> + +static char *auth_errmsg (enum auth_stat stat) internal_function; + +#ifdef _RPC_THREAD_SAFE_ +/* + * Making buf a preprocessor macro requires renaming the local + * buf variable in a few functions. Overriding a global variable + * with a local variable of the same name is a bad idea, anyway. + */ +#define buf RPC_THREAD_VARIABLE(clnt_perr_buf_s) +#else +static char *buf; +#endif + +/* + * Print reply error info + */ +char * +clnt_sperror (CLIENT * rpch, const char *msg) +{ + struct rpc_err e; + CLNT_GETERR (rpch, &e); + + const char *errstr = clnt_sperrno (e.re_status); + + char chrbuf[1024]; + char *str; + char *tmpstr; + int res; + 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: + res = __asprintf (&str, "%s: %s\n", msg, errstr); + break; + + case RPC_CANTSEND: + case RPC_CANTRECV: + res = __asprintf (&str, "%s: %s; errno = %s\n", + msg, errstr, __strerror_r (e.re_errno, + chrbuf, sizeof chrbuf)); + break; + + case RPC_VERSMISMATCH: + res = __asprintf (&str, + _("%s: %s; low version = %lu, high version = %lu"), + msg, errstr, e.re_vers.low, e.re_vers.high); + break; + + case RPC_AUTHERROR: + tmpstr = auth_errmsg (e.re_why); + if (tmpstr != NULL) + res = __asprintf (&str, _("%s: %s; why = %s\n"), msg, errstr, tmpstr); + else + res = __asprintf (&str, _("\ +%s: %s; why = (unknown authentication error - %d)\n"), + msg, errstr, (int) e.re_why); + break; + + case RPC_PROGVERSMISMATCH: + res = __asprintf (&str, + _("%s: %s; low version = %lu, high version = %lu"), + msg, errstr, e.re_vers.low, e.re_vers.high); + break; + + default: /* unknown */ + res = __asprintf (&str, "%s: %s; s1 = %lu, s2 = %lu", + msg, errstr, e.re_lb.s1, e.re_lb.s2); + break; + } + + if (res < 0) + return NULL; + + char *oldbuf = buf; + buf = str; + free (oldbuf); + + return str; +} +libc_hidden_nolink_sunrpc (clnt_sperror, GLIBC_2_0) + +void +clnt_perror (CLIENT * rpch, const char *msg) +{ + (void) __fxprintf (NULL, "%s", clnt_sperror (rpch, msg)); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (clnt_perror) +#else +libc_hidden_nolink_sunrpc (clnt_perror, GLIBC_2_0) +#endif + + +struct rpc_errtab +{ + enum clnt_stat status; + unsigned int message_off; +}; + +static const char rpc_errstr[] = +{ +#define RPC_SUCCESS_IDX 0 + N_("RPC: Success") + "\0" +#define RPC_CANTENCODEARGS_IDX (RPC_SUCCESS_IDX + sizeof "RPC: Success") + N_("RPC: Can't encode arguments") + "\0" +#define RPC_CANTDECODERES_IDX (RPC_CANTENCODEARGS_IDX \ + + sizeof "RPC: Can't encode arguments") + N_("RPC: Can't decode result") + "\0" +#define RPC_CANTSEND_IDX (RPC_CANTDECODERES_IDX \ + + sizeof "RPC: Can't decode result") + N_("RPC: Unable to send") + "\0" +#define RPC_CANTRECV_IDX (RPC_CANTSEND_IDX \ + + sizeof "RPC: Unable to send") + N_("RPC: Unable to receive") + "\0" +#define RPC_TIMEDOUT_IDX (RPC_CANTRECV_IDX \ + + sizeof "RPC: Unable to receive") + N_("RPC: Timed out") + "\0" +#define RPC_VERSMISMATCH_IDX (RPC_TIMEDOUT_IDX \ + + sizeof "RPC: Timed out") + N_("RPC: Incompatible versions of RPC") + "\0" +#define RPC_AUTHERROR_IDX (RPC_VERSMISMATCH_IDX \ + + sizeof "RPC: Incompatible versions of RPC") + N_("RPC: Authentication error") + "\0" +#define RPC_PROGUNAVAIL_IDX (RPC_AUTHERROR_IDX \ + + sizeof "RPC: Authentication error") + N_("RPC: Program unavailable") + "\0" +#define RPC_PROGVERSMISMATCH_IDX (RPC_PROGUNAVAIL_IDX \ + + sizeof "RPC: Program unavailable") + N_("RPC: Program/version mismatch") + "\0" +#define RPC_PROCUNAVAIL_IDX (RPC_PROGVERSMISMATCH_IDX \ + + sizeof "RPC: Program/version mismatch") + N_("RPC: Procedure unavailable") + "\0" +#define RPC_CANTDECODEARGS_IDX (RPC_PROCUNAVAIL_IDX \ + + sizeof "RPC: Procedure unavailable") + N_("RPC: Server can't decode arguments") + "\0" +#define RPC_SYSTEMERROR_IDX (RPC_CANTDECODEARGS_IDX \ + + sizeof "RPC: Server can't decode arguments") + N_("RPC: Remote system error") + "\0" +#define RPC_UNKNOWNHOST_IDX (RPC_SYSTEMERROR_IDX \ + + sizeof "RPC: Remote system error") + N_("RPC: Unknown host") + "\0" +#define RPC_UNKNOWNPROTO_IDX (RPC_UNKNOWNHOST_IDX \ + + sizeof "RPC: Unknown host") + N_("RPC: Unknown protocol") + "\0" +#define RPC_PMAPFAILURE_IDX (RPC_UNKNOWNPROTO_IDX \ + + sizeof "RPC: Unknown protocol") + N_("RPC: Port mapper failure") + "\0" +#define RPC_PROGNOTREGISTERED_IDX (RPC_PMAPFAILURE_IDX \ + + sizeof "RPC: Port mapper failure") + N_("RPC: Program not registered") + "\0" +#define RPC_FAILED_IDX (RPC_PROGNOTREGISTERED_IDX \ + + sizeof "RPC: Program not registered") + N_("RPC: Failed (unspecified error)") +}; + +static const struct rpc_errtab rpc_errlist[] = +{ + { RPC_SUCCESS, RPC_SUCCESS_IDX }, + { RPC_CANTENCODEARGS, RPC_CANTENCODEARGS_IDX }, + { RPC_CANTDECODERES, RPC_CANTDECODERES_IDX }, + { RPC_CANTSEND, RPC_CANTSEND_IDX }, + { RPC_CANTRECV, RPC_CANTRECV_IDX }, + { RPC_TIMEDOUT, RPC_TIMEDOUT_IDX }, + { RPC_VERSMISMATCH, RPC_VERSMISMATCH_IDX }, + { RPC_AUTHERROR, RPC_AUTHERROR_IDX }, + { RPC_PROGUNAVAIL, RPC_PROGUNAVAIL_IDX }, + { RPC_PROGVERSMISMATCH, RPC_PROGVERSMISMATCH_IDX }, + { RPC_PROCUNAVAIL, RPC_PROCUNAVAIL_IDX }, + { RPC_CANTDECODEARGS, RPC_CANTDECODEARGS_IDX }, + { RPC_SYSTEMERROR, RPC_SYSTEMERROR_IDX }, + { RPC_UNKNOWNHOST, RPC_UNKNOWNHOST_IDX }, + { RPC_UNKNOWNPROTO, RPC_UNKNOWNPROTO_IDX }, + { RPC_PMAPFAILURE, RPC_PMAPFAILURE_IDX }, + { RPC_PROGNOTREGISTERED, RPC_PROGNOTREGISTERED_IDX }, + { RPC_FAILED, RPC_FAILED_IDX } +}; + + +/* + * This interface for use by clntrpc + */ +char * +clnt_sperrno (enum clnt_stat stat) +{ + size_t i; + + for (i = 0; i < sizeof (rpc_errlist) / sizeof (struct rpc_errtab); i++) + { + if (rpc_errlist[i].status == stat) + { + return _(rpc_errstr + rpc_errlist[i].message_off); + } + } + return _("RPC: (unknown error code)"); +} +libc_hidden_def (clnt_sperrno) + +void +clnt_perrno (enum clnt_stat num) +{ + (void) __fxprintf (NULL, "%s", clnt_sperrno (num)); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (clnt_perrno) +#else +libc_hidden_nolink_sunrpc (clnt_perrno, GLIBC_2_0) +#endif + +char * +clnt_spcreateerror (const char *msg) +{ + struct rpc_createerr *ce = &get_rpc_createerr (); + + char chrbuf[1024]; + const char *connector = ""; + const char *errstr = ""; + switch (ce->cf_stat) + { + case RPC_PMAPFAILURE: + connector = " - "; + errstr = clnt_sperrno (ce->cf_error.re_status); + break; + + case RPC_SYSTEMERROR: + connector = " - "; + errstr = __strerror_r (ce->cf_error.re_errno, chrbuf, sizeof chrbuf); + break; + + default: + break; + } + + char *str; + if (__asprintf (&str, "%s: %s%s%s\n", + msg, clnt_sperrno (ce->cf_stat), connector, errstr) < 0) + return NULL; + + char *oldbuf = buf; + buf = str; + free (oldbuf); + + return str; +} +libc_hidden_nolink_sunrpc (clnt_spcreateerror, GLIBC_2_0) + +void +clnt_pcreateerror (const char *msg) +{ + (void) __fxprintf (NULL, "%s", clnt_spcreateerror (msg)); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (clnt_pcreateerror) +#else +libc_hidden_nolink_sunrpc (clnt_pcreateerror, GLIBC_2_0) +#endif + +struct auth_errtab +{ + enum auth_stat status; + unsigned int message_off; +}; + +static const char auth_errstr[] = +{ +#define AUTH_OK_IDX 0 + N_("Authentication OK") + "\0" +#define AUTH_BADCRED_IDX (AUTH_OK_IDX + sizeof "Authentication OK") + N_("Invalid client credential") + "\0" +#define AUTH_REJECTEDCRED_IDX (AUTH_BADCRED_IDX \ + + sizeof "Invalid client credential") + N_("Server rejected credential") + "\0" +#define AUTH_BADVERF_IDX (AUTH_REJECTEDCRED_IDX \ + + sizeof "Server rejected credential") + N_("Invalid client verifier") + "\0" +#define AUTH_REJECTEDVERF_IDX (AUTH_BADVERF_IDX \ + + sizeof "Invalid client verifier") + N_("Server rejected verifier") + "\0" +#define AUTH_TOOWEAK_IDX (AUTH_REJECTEDVERF_IDX \ + + sizeof "Server rejected verifier") + N_("Client credential too weak") + "\0" +#define AUTH_INVALIDRESP_IDX (AUTH_TOOWEAK_IDX \ + + sizeof "Client credential too weak") + N_("Invalid server verifier") + "\0" +#define AUTH_FAILED_IDX (AUTH_INVALIDRESP_IDX \ + + sizeof "Invalid server verifier") + N_("Failed (unspecified error)") +}; + +static const struct auth_errtab auth_errlist[] = +{ + { AUTH_OK, AUTH_OK_IDX }, + { AUTH_BADCRED, AUTH_BADCRED_IDX }, + { AUTH_REJECTEDCRED, AUTH_REJECTEDCRED_IDX }, + { AUTH_BADVERF, AUTH_BADVERF_IDX }, + { AUTH_REJECTEDVERF, AUTH_REJECTEDVERF_IDX }, + { AUTH_TOOWEAK, AUTH_TOOWEAK_IDX }, + { AUTH_INVALIDRESP, AUTH_INVALIDRESP_IDX }, + { AUTH_FAILED, AUTH_FAILED_IDX } +}; + +static char * +internal_function +auth_errmsg (enum auth_stat stat) +{ + size_t i; + + for (i = 0; i < sizeof (auth_errlist) / sizeof (struct auth_errtab); i++) + { + if (auth_errlist[i].status == stat) + { + return _(auth_errstr + auth_errlist[i].message_off); + } + } + return NULL; +} + + +libc_freeres_fn (free_mem) +{ + /* Not libc_freeres_ptr, since buf is a macro. */ + free (buf); +} diff --git a/REORG.TODO/sunrpc/clnt_raw.c b/REORG.TODO/sunrpc/clnt_raw.c new file mode 100644 index 0000000000..d62a11a2ca --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_raw.c @@ -0,0 +1,250 @@ +/* + * clnt_raw.c + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Memory based rpc for simple testing and timing. + * Interface to create an rpc client and server in the same process. + * This lets us simulate rpc and get round trip overhead, without + * any interference from the kernel. + */ + +#include <rpc/rpc.h> +#include <rpc/svc.h> +#include <rpc/xdr.h> +#include <libintl.h> +#include <shlib-compat.h> + +#define MCALL_MSG_SIZE 24 + +/* + * This is the "network" we will be moving stuff over. + */ +struct clntraw_private_s + { + CLIENT client_object; + XDR xdr_stream; + char _raw_buf[UDPMSGSIZE]; + union + { + char msg[MCALL_MSG_SIZE]; + u_long rm_xid; + } mashl_callmsg; + u_int mcnt; + }; +#ifdef _RPC_THREAD_SAFE_ +#define clntraw_private RPC_THREAD_VARIABLE(clntraw_private_s) +#else +static struct clntraw_private_s *clntraw_private; +#endif + +static enum clnt_stat clntraw_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntraw_abort (void); +static void clntraw_geterr (CLIENT *, struct rpc_err *); +static bool_t clntraw_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntraw_control (CLIENT *, int, char *); +static void clntraw_destroy (CLIENT *); + +static const struct clnt_ops client_ops = +{ + clntraw_call, + clntraw_abort, + clntraw_geterr, + clntraw_freeres, + clntraw_destroy, + clntraw_control +}; + +/* + * Create a client handle for memory based rpc. + */ +CLIENT * +clntraw_create (u_long prog, u_long vers) +{ + struct clntraw_private_s *clp = clntraw_private; + struct rpc_msg call_msg; + XDR *xdrs; + CLIENT *client; + + if (clp == 0) + { + clp = (struct clntraw_private_s *) calloc (1, sizeof (*clp)); + if (clp == 0) + return (0); + clntraw_private = clp; + } + xdrs = &clp->xdr_stream; + client = &clp->client_object; + /* + * pre-serialize the static 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.msg, 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 = (struct clnt_ops *) &client_ops; + client->cl_auth = authnone_create (); + return client; +} +libc_hidden_nolink_sunrpc (clntraw_create, GLIBC_2_0) + +static enum clnt_stat +clntraw_call (CLIENT *h, u_long proc, xdrproc_t xargs, caddr_t argsp, + xdrproc_t xresults, caddr_t resultsp, struct timeval timeout) +{ + struct clntraw_private_s *clp = clntraw_private; + XDR *xdrs = &clp->xdr_stream; + struct rpc_msg msg; + enum clnt_stat status; + struct rpc_err error; + + if (clp == NULL) + return RPC_FAILED; +call_again: + /* + * send request + */ + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + /* Just checking the union definition to access rm_xid is correct. */ + if (offsetof (struct rpc_msg, rm_xid) != 0) + abort (); + clp->mashl_callmsg.rm_xid++; + if ((!XDR_PUTBYTES (xdrs, clp->mashl_callmsg.msg, clp->mcnt)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xargs) (xdrs, argsp))) + { + return (RPC_CANTENCODEARGS); + } + (void) XDR_GETPOS (xdrs); /* called just to cause overhead */ + + /* + * We have to call server input routine here because this is + * all going on in one process. Yuk. + */ + svc_getreq (1); + + /* + * get results + */ + xdrs->x_op = XDR_DECODE; + XDR_SETPOS (xdrs, 0); + msg.acpted_rply.ar_verf = _null_auth; + msg.acpted_rply.ar_results.where = resultsp; + msg.acpted_rply.ar_results.proc = xresults; + if (!xdr_replymsg (xdrs, &msg)) + return RPC_CANTDECODERES; + _seterr_reply (&msg, &error); + status = error.re_status; + + if (status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) + { + status = RPC_AUTHERROR; + } + } /* end successful completion */ + else + { + if (AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + + if (status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &msg.acpted_rply.ar_verf)) + { + status = RPC_AUTHERROR; + } + if (msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(msg.acpted_rply.ar_verf)); + } + } + + return status; +} + +static void +clntraw_geterr (CLIENT *cl, struct rpc_err *err) +{ +} + + +static bool_t +clntraw_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct clntraw_private_s *clp = clntraw_private; + XDR *xdrs = &clp->xdr_stream; + bool_t rval; + + if (clp == NULL) + { + rval = (bool_t) RPC_FAILED; + return rval; + } + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntraw_abort (void) +{ +} + +static bool_t +clntraw_control (CLIENT *cl, int i, char *c) +{ + return FALSE; +} + +static void +clntraw_destroy (CLIENT *cl) +{ +} diff --git a/REORG.TODO/sunrpc/clnt_simp.c b/REORG.TODO/sunrpc/clnt_simp.c new file mode 100644 index 0000000000..bdf6322fc4 --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_simp.c @@ -0,0 +1,138 @@ +/* + * clnt_simple.c + * Simplified front end to rpc. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <alloca.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <sys/socket.h> +#include <netdb.h> +#include <string.h> +#include <shlib-compat.h> + +struct callrpc_private_s + { + CLIENT *client; + int socket; + u_long oldprognum, oldversnum, valid; + char *oldhost; + }; +#ifdef _RPC_THREAD_SAFE_ +#define callrpc_private RPC_THREAD_VARIABLE(callrpc_private_s) +#else +static struct callrpc_private_s *callrpc_private; +#endif + +int +callrpc (const char *host, u_long prognum, u_long versnum, u_long procnum, + xdrproc_t inproc, const char *in, xdrproc_t outproc, char *out) +{ + struct callrpc_private_s *crp = callrpc_private; + struct sockaddr_in server_addr; + enum clnt_stat clnt_stat; + struct timeval timeout, tottimeout; + + if (crp == 0) + { + crp = (struct callrpc_private_s *) calloc (1, sizeof (*crp)); + if (crp == 0) + return 0; + callrpc_private = crp; + } + if (crp->oldhost == NULL) + { + crp->oldhost = malloc (256); + crp->oldhost[0] = 0; + crp->socket = RPC_ANYSOCK; + } + if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum + && strcmp (crp->oldhost, host) == 0) + { + /* reuse old client */ + } + else + { + crp->valid = 0; + if (crp->socket != RPC_ANYSOCK) + { + (void) __close (crp->socket); + crp->socket = RPC_ANYSOCK; + } + if (crp->client) + { + clnt_destroy (crp->client); + crp->client = NULL; + } + + if (__libc_rpc_gethostbyname (host, &server_addr) != 0) + return (int) get_rpc_createerr().cf_stat; + + timeout.tv_usec = 0; + timeout.tv_sec = 5; + if ((crp->client = clntudp_create (&server_addr, (u_long) prognum, + (u_long) versnum, timeout, &crp->socket)) == NULL) + return (int) get_rpc_createerr().cf_stat; + crp->valid = 1; + crp->oldprognum = prognum; + crp->oldversnum = versnum; + (void) strncpy (crp->oldhost, host, 255); + crp->oldhost[255] = '\0'; + } + tottimeout.tv_sec = 25; + tottimeout.tv_usec = 0; + clnt_stat = clnt_call (crp->client, procnum, inproc, (char *) in, + outproc, out, tottimeout); + /* + * if call failed, empty cache + */ + if (clnt_stat != RPC_SUCCESS) + crp->valid = 0; + return (int) clnt_stat; +} +libc_hidden_nolink_sunrpc (callrpc, GLIBC_2_0) + +#ifdef _RPC_THREAD_SAFE_ +void +__rpc_thread_clnt_cleanup (void) +{ + struct callrpc_private_s *rcp = RPC_THREAD_VARIABLE(callrpc_private_s); + + if (rcp) { + if (rcp->client) + CLNT_DESTROY (rcp->client); + free (rcp); + } +} +#endif /* _RPC_THREAD_SAFE_ */ diff --git a/REORG.TODO/sunrpc/clnt_tcp.c b/REORG.TODO/sunrpc/clnt_tcp.c new file mode 100644 index 0000000000..e311b35a25 --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_tcp.c @@ -0,0 +1,530 @@ +/* + * clnt_tcp.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <netdb.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <libintl.h> +#include <rpc/rpc.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <rpc/pmap_clnt.h> +#include <wchar.h> +#include <shlib-compat.h> + +extern u_long _create_xid (void); + +#define MCALL_MSG_SIZE 24 + +struct ct_data + { + int ct_sock; + bool_t ct_closeit; + struct timeval ct_wait; + bool_t ct_waitset; /* wait set by clnt_control? */ + struct sockaddr_in ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; + }; + +static int readtcp (char *, char *, int); +static int writetcp (char *, char *, int); + +static enum clnt_stat clnttcp_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clnttcp_abort (void); +static void clnttcp_geterr (CLIENT *, struct rpc_err *); +static bool_t clnttcp_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clnttcp_control (CLIENT *, int, char *); +static void clnttcp_destroy (CLIENT *); + +static const struct clnt_ops tcp_ops = +{ + clnttcp_call, + clnttcp_abort, + clnttcp_geterr, + clnttcp_freeres, + clnttcp_destroy, + clnttcp_control +}; + +/* + * 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 (struct sockaddr_in *raddr, u_long prog, u_long vers, + int *sockp, u_int sendsz, u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct; + struct rpc_msg call_msg; + + h = (CLIENT *) mem_alloc (sizeof (*h)); + ct = (struct ct_data *) mem_alloc (sizeof (*ct)); + if (h == NULL || ct == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + + /* + * If no port number given ask the pmap for one + */ + if (raddr->sin_port == 0) + { + u_short port; + if ((port = pmap_getport (raddr, prog, vers, IPPROTO_TCP)) == 0) + { + mem_free ((caddr_t) ct, sizeof (struct ct_data)); + mem_free ((caddr_t) h, sizeof (CLIENT)); + return ((CLIENT *) NULL); + } + raddr->sin_port = htons (port); + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) + { + *sockp = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + (void) bindresvport (*sockp, (struct sockaddr_in *) 0); + if ((*sockp < 0) + || (__connect (*sockp, (struct sockaddr *) raddr, + sizeof (*raddr)) < 0)) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + if (*sockp >= 0) + (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 + */ + call_msg.rm_xid = _create_xid (); + 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 static 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 = (struct clnt_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); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (clnttcp_create) +#else +libc_hidden_nolink_sunrpc (clnttcp_create, GLIBC_2_0) +#endif + +static enum clnt_stat +clnttcp_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, + xdrproc_t xdr_results, caddr_t results_ptr, + struct timeval timeout) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */ + bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) + { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0 + && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl (--(*msg_x_id)); + if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xdr_args) (xdrs, args_ptr))) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void) xdrrec_endofrecord (xdrs, TRUE); + return (ct->ct_error.re_status); + } + if (!xdrrec_endofrecord (xdrs, shipnow)) + return ct->ct_error.re_status = RPC_CANTSEND; + if (!shipnow) + return RPC_SUCCESS; + /* + * Hack to provide rpc-based message passing + */ + if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.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 = (xdrproc_t)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 ((u_int32_t) reply_msg.rm_xid == (u_int32_t) x_id) + break; + } + + /* + * process header + */ + _seterr_reply (&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf)) + { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } + else if (!(*xdr_results) (xdrs, results_ptr)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return ct->ct_error.re_status; +} + +static void +clnttcp_geterr (CLIENT *h, struct rpc_err *errp) +{ + struct ct_data *ct = + (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clnttcp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clnttcp_abort (void) +{ +} + +static bool_t +clnttcp_control (CLIENT *cl, int request, char *info) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + u_long ul; + u_int32_t ui32; + + + switch (request) + { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + 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_FD: + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + memcpy (&ui32, ct->ct_mcall, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul - 1); + memcpy (ct->ct_mcall, &ui32, sizeof (ui32)); + /* decrement by 1 as clnttcp_call() increments once */ + break; + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * beginning of the RPC header. MUST be changed if the + * call_struct is changed + */ + memcpy (&ui32, ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_VERS: + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul); + memcpy (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32)); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * beginning of the RPC header. MUST be changed if the + * call_struct is changed + */ + memcpy (&ui32, ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_PROG: + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul); + memcpy (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32)); + break; + /* The following are only possible with TI-RPC */ + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + + +static void +clnttcp_destroy (CLIENT *h) +{ + 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 (char *ctptr, char *buf, int len) +{ + struct ct_data *ct = (struct ct_data *)ctptr; + struct pollfd fd; + int milliseconds = (ct->ct_wait.tv_sec * 1000) + + (ct->ct_wait.tv_usec / 1000); + + if (len == 0) + return 0; + + fd.fd = ct->ct_sock; + fd.events = POLLIN; + while (TRUE) + { + switch (__poll(&fd, 1, milliseconds)) + { + 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 (char *ctptr, char *buf, int len) +{ + int i, cnt; + struct ct_data *ct = (struct ct_data*)ctptr; + + 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/REORG.TODO/sunrpc/clnt_udp.c b/REORG.TODO/sunrpc/clnt_udp.c new file mode 100644 index 0000000000..df21e28f64 --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_udp.c @@ -0,0 +1,646 @@ +/* + * clnt_udp.c, Implements a UDP/IP based, client side RPC. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <unistd.h> +#include <libintl.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpc/clnt.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <netdb.h> +#include <errno.h> +#include <stdint.h> +#include <rpc/pmap_clnt.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <wchar.h> +#include <fcntl.h> + +#ifdef IP_RECVERR +#include <errqueue.h> +#include <sys/uio.h> +#endif + +#include <kernel-features.h> +#include <inet/net-internal.h> +#include <shlib-compat.h> + +extern u_long _create_xid (void); + +/* + * UDP bases client side rpc operations + */ +static enum clnt_stat clntudp_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntudp_abort (void); +static void clntudp_geterr (CLIENT *, struct rpc_err *); +static bool_t clntudp_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntudp_control (CLIENT *, int, char *); +static void clntudp_destroy (CLIENT *); + +static const struct clnt_ops udp_ops = +{ + clntudp_call, + clntudp_abort, + clntudp_geterr, + clntudp_freeres, + clntudp_destroy, + clntudp_control +}; + +/* + * Private data kept per client handle. This private struct is + * unfortunately part of the ABI; ypbind contains a copy of it and + * accesses it through CLIENT::cl_private field. + */ +struct cu_data + { + int cu_sock; + bool_t cu_closeit; + struct sockaddr_in cu_raddr; + int cu_rlen; + struct timeval cu_wait; + struct timeval cu_total; + struct rpc_err cu_error; + XDR cu_outxdrs; + u_int cu_xdrpos; + u_int cu_sendsz; + char *cu_outbuf; + u_int cu_recvsz; + char cu_inbuf[1]; + }; + +/* + * Create a UDP based client handle. + * If *sockp<0, *sockp is set to a newly created UPD socket. + * If raddr->sin_port is 0 a binder on the remote machine + * is consulted for the correct port number. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is initialized to null authentication. + * Caller may wish to set this something more useful. + * + * wait is the amount of time used between retransmitting a call if + * no response has been heard; retransmission occurs until the actual + * rpc call times out. + * + * sendsz and recvsz are the maximum allowable packet sizes that can be + * sent and received. + */ +CLIENT * +__libc_clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, + u_long version, struct timeval wait, int *sockp, + u_int sendsz, u_int recvsz, int flags) +{ + CLIENT *cl; + struct cu_data *cu = NULL; + struct rpc_msg call_msg; + + cl = (CLIENT *) mem_alloc (sizeof (CLIENT)); + sendsz = ((sendsz + 3) / 4) * 4; + recvsz = ((recvsz + 3) / 4) * 4; + cu = (struct cu_data *) mem_alloc (sizeof (*cu) + sendsz + recvsz); + if (cl == NULL || cu == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + (void) __fxprintf (NULL, "%s: %s", + "clntudp_create", _("out of memory\n")); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + cu->cu_outbuf = &cu->cu_inbuf[recvsz]; + + if (raddr->sin_port == 0) + { + u_short port; + if ((port = + pmap_getport (raddr, program, version, IPPROTO_UDP)) == 0) + { + goto fooy; + } + raddr->sin_port = htons (port); + } + cl->cl_ops = (struct clnt_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 = _create_xid (); + 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) + { + *sockp = __socket (AF_INET, SOCK_DGRAM|SOCK_NONBLOCK|flags, IPPROTO_UDP); + if (__glibc_unlikely (*sockp < 0)) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + goto fooy; + } + /* attempt to bind to prov port */ + (void) bindresvport (*sockp, (struct sockaddr_in *) 0); +#ifdef IP_RECVERR + { + int on = 1; + __setsockopt (*sockp, SOL_IP, IP_RECVERR, &on, sizeof(on)); + } +#endif + 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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (__libc_clntudp_bufcreate) +#else +libc_hidden_nolink_sunrpc (__libc_clntudp_bufcreate, GLIBC_PRIVATE) +#endif + +CLIENT * +clntudp_bufcreate (struct sockaddr_in *raddr, u_long program, u_long version, + struct timeval wait, int *sockp, u_int sendsz, + u_int recvsz) +{ + return __libc_clntudp_bufcreate (raddr, program, version, wait, + sockp, sendsz, recvsz, 0); +} +libc_hidden_nolink_sunrpc (clntudp_bufcreate, GLIBC_2_0) + +CLIENT * +clntudp_create (struct sockaddr_in *raddr, u_long program, u_long version, + struct timeval wait, int *sockp) +{ + return __libc_clntudp_bufcreate (raddr, program, version, wait, + sockp, UDPMSGSIZE, UDPMSGSIZE, 0); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (clntudp_create) +#else +libc_hidden_nolink_sunrpc (clntudp_create, GLIBC_2_0) +#endif + +static int +is_network_up (int sock) +{ + struct ifaddrs *ifa; + + if (getifaddrs (&ifa) != 0) + return 0; + + struct ifaddrs *run = ifa; + while (run != NULL) + { + if ((run->ifa_flags & IFF_UP) != 0 + && run->ifa_addr != NULL + && run->ifa_addr->sa_family == AF_INET) + break; + + run = run->ifa_next; + } + + freeifaddrs (ifa); + + return run != NULL; +} + +static enum clnt_stat +clntudp_call (/* client handle */ + CLIENT *cl, + /* procedure number */ + u_long proc, + /* xdr routine for args */ + xdrproc_t xargs, + /* pointer to args */ + caddr_t argsp, + /* xdr routine for results */ + xdrproc_t xresults, + /* pointer to results */ + caddr_t resultsp, + /* seconds to wait before giving up */ + struct timeval utimeout) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + XDR *xdrs; + int outlen = 0; + int inlen; + socklen_t fromlen; + struct pollfd fd; + struct sockaddr_in from; + struct rpc_msg reply_msg; + XDR reply_xdrs; + bool_t ok; + int nrefreshes = 2; /* number of times to refresh cred */ + int anyup; /* any network interface up */ + + struct deadline_current_time current_time = __deadline_current_time (); + struct deadline total_deadline; /* Determined once by overall timeout. */ + struct deadline response_deadline; /* Determined anew for each query. */ + + /* Choose the timeout value. For non-sending usage (xargs == NULL), + the total deadline does not matter, only cu->cu_wait is used + below. */ + if (xargs != NULL) + { + struct timeval tv; + if (cu->cu_total.tv_usec == -1) + /* Use supplied timeout. */ + tv = utimeout; + else + /* Use default timeout. */ + tv = cu->cu_total; + if (!__is_timeval_valid_timeout (tv)) + return (cu->cu_error.re_status = RPC_TIMEDOUT); + total_deadline = __deadline_from_timeval (current_time, tv); + } + + /* Guard against bad timeout specification. */ + if (!__is_timeval_valid_timeout (cu->cu_wait)) + return (cu->cu_error.re_status = RPC_TIMEDOUT); + +call_again: + xdrs = &(cu->cu_outxdrs); + if (xargs == NULL) + goto get_reply; + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, cu->cu_xdrpos); + /* + * the transaction is the first thing in the out buffer + */ + (*(uint32_t *) (cu->cu_outbuf))++; + if ((!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (cl->cl_auth, xdrs)) || + (!(*xargs) (xdrs, argsp))) + return (cu->cu_error.re_status = RPC_CANTENCODEARGS); + outlen = (int) XDR_GETPOS (xdrs); + +send_again: + if (__sendto (cu->cu_sock, cu->cu_outbuf, outlen, 0, + (struct sockaddr *) &(cu->cu_raddr), cu->cu_rlen) + != outlen) + { + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTSEND); + } + + /* sendto may have blocked, so recompute the current time. */ + current_time = __deadline_current_time (); + get_reply: + response_deadline = __deadline_from_timeval (current_time, cu->cu_wait); + + reply_msg.acpted_rply.ar_verf = _null_auth; + reply_msg.acpted_rply.ar_results.where = resultsp; + reply_msg.acpted_rply.ar_results.proc = xresults; + fd.fd = cu->cu_sock; + fd.events = POLLIN; + anyup = 0; + + /* Per-response retry loop. current_time must be up-to-date at the + top of the loop. */ + for (;;) + { + int milliseconds; + if (xargs != NULL) + { + if (__deadline_elapsed (current_time, total_deadline)) + /* Overall timeout expired. */ + return (cu->cu_error.re_status = RPC_TIMEDOUT); + milliseconds = __deadline_to_ms + (current_time, __deadline_first (total_deadline, + response_deadline)); + if (milliseconds == 0) + /* Per-query timeout expired. */ + goto send_again; + } + else + { + /* xatgs == NULL. Collect a response without sending a + query. In this mode, we need to ignore the total + deadline. */ + milliseconds = __deadline_to_ms (current_time, response_deadline); + if (milliseconds == 0) + /* Cannot send again, so bail out. */ + return (cu->cu_error.re_status = RPC_CANTSEND); + } + + switch (__poll (&fd, 1, milliseconds)) + { + + case 0: + if (anyup == 0) + { + anyup = is_network_up (cu->cu_sock); + if (!anyup) + return (cu->cu_error.re_status = RPC_CANTRECV); + } + goto next_response; + case -1: + if (errno == EINTR) + goto next_response; + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } +#ifdef IP_RECVERR + if (fd.revents & POLLERR) + { + struct msghdr msg; + struct cmsghdr *cmsg; + struct sock_extended_err *e; + struct sockaddr_in err_addr; + struct iovec iov; + char *cbuf = malloc (outlen + 256); + int ret; + + if (cbuf == NULL) + { + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } + + iov.iov_base = cbuf + 256; + iov.iov_len = outlen; + msg.msg_name = (void *) &err_addr; + msg.msg_namelen = sizeof (err_addr); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_flags = 0; + msg.msg_control = cbuf; + msg.msg_controllen = 256; + ret = __recvmsg (cu->cu_sock, &msg, MSG_ERRQUEUE); + if (ret >= 0 + && memcmp (cbuf + 256, cu->cu_outbuf, ret) == 0 + && (msg.msg_flags & MSG_ERRQUEUE) + && ((msg.msg_namelen == 0 + && ret >= 12) + || (msg.msg_namelen == sizeof (err_addr) + && err_addr.sin_family == AF_INET + && memcmp (&err_addr.sin_addr, &cu->cu_raddr.sin_addr, + sizeof (err_addr.sin_addr)) == 0 + && err_addr.sin_port == cu->cu_raddr.sin_port))) + for (cmsg = CMSG_FIRSTHDR (&msg); cmsg; + cmsg = CMSG_NXTHDR (&msg, cmsg)) + if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR) + { + e = (struct sock_extended_err *) CMSG_DATA(cmsg); + cu->cu_error.re_errno = e->ee_errno; + free (cbuf); + return (cu->cu_error.re_status = RPC_CANTRECV); + } + free (cbuf); + } +#endif + do + { + fromlen = sizeof (struct sockaddr); + inlen = __recvfrom (cu->cu_sock, cu->cu_inbuf, + (int) cu->cu_recvsz, MSG_DONTWAIT, + (struct sockaddr *) &from, &fromlen); + } + while (inlen < 0 && errno == EINTR); + if (inlen < 0) + { + if (errno == EWOULDBLOCK) + goto next_response; + cu->cu_error.re_errno = errno; + return (cu->cu_error.re_status = RPC_CANTRECV); + } + /* Accept the response if the packet is sufficiently long and + the transaction ID matches the query (if available). */ + if (inlen >= 4 + && (xargs == NULL + || memcmp (cu->cu_inbuf, cu->cu_outbuf, + sizeof (u_int32_t)) == 0)) + break; + + next_response: + /* Update the current time because poll and recvmsg waited for + an unknown time. */ + current_time = __deadline_current_time (); + } + + /* + * now decode and validate the response + */ + xdrmem_create (&reply_xdrs, cu->cu_inbuf, (u_int) inlen, XDR_DECODE); + ok = xdr_replymsg (&reply_xdrs, &reply_msg); + /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */ + if (ok) + { + _seterr_reply (&reply_msg, &(cu->cu_error)); + if (cu->cu_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (cl->cl_auth, + &reply_msg.acpted_rply.ar_verf)) + { + cu->cu_error.re_status = RPC_AUTHERROR; + cu->cu_error.re_why = AUTH_INVALIDRESP; + } + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (nrefreshes > 0 && AUTH_REFRESH (cl->cl_auth)) + { + nrefreshes--; + goto call_again; + } + } /* end of unsuccessful completion */ + } /* end of valid reply message */ + else + { + cu->cu_error.re_status = RPC_CANTDECODERES; + } + return cu->cu_error.re_status; +} + +static void +clntudp_geterr (CLIENT *cl, struct rpc_err *errp) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + + *errp = cu->cu_error; +} + + +static bool_t +clntudp_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + XDR *xdrs = &(cu->cu_outxdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntudp_abort (void) +{ +} + +static bool_t +clntudp_control (CLIENT *cl, int request, char *info) +{ + struct cu_data *cu = (struct cu_data *) cl->cl_private; + u_long ul; + u_int32_t ui32; + + switch (request) + { + case CLSET_FD_CLOSE: + cu->cu_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + cu->cu_closeit = FALSE; + break; + 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_FD: + *(int *)info = cu->cu_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + memcpy (&ui32, cu->cu_outbuf, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul - 1); + memcpy (cu->cu_outbuf, &ui32, sizeof (ui32)); + /* decrement by 1 as clntudp_call() increments once */ + break; + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * beginning of the RPC header. MUST be changed if the + * call_struct is changed + */ + memcpy (&ui32, cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_VERS: + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul); + memcpy (cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32)); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * beginning of the RPC header. MUST be changed if the + * call_struct is changed + */ + memcpy (&ui32, cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_PROG: + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul); + memcpy (cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32)); + break; + /* The following are only possible with TI-RPC */ + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + +static void +clntudp_destroy (CLIENT *cl) +{ + 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/REORG.TODO/sunrpc/clnt_unix.c b/REORG.TODO/sunrpc/clnt_unix.c new file mode 100644 index 0000000000..8591be5580 --- /dev/null +++ b/REORG.TODO/sunrpc/clnt_unix.c @@ -0,0 +1,598 @@ +/* + * clnt_unix.c, Implements a TCP/IP based, client side RPC. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <netdb.h> +#include <errno.h> +#include <stdio.h> +#include <unistd.h> +#include <libintl.h> +#include <rpc/rpc.h> +#include <sys/uio.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <rpc/pmap_clnt.h> +#include <wchar.h> +#include <shlib-compat.h> + +extern u_long _create_xid (void); + +#define MCALL_MSG_SIZE 24 + +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_un ct_addr; + struct rpc_err ct_error; + char ct_mcall[MCALL_MSG_SIZE]; /* marshalled callmsg */ + u_int ct_mpos; /* pos after marshal */ + XDR ct_xdrs; + }; + +static int readunix (char *, char *, int); +static int writeunix (char *, char *, int); + +static enum clnt_stat clntunix_call (CLIENT *, u_long, xdrproc_t, caddr_t, + xdrproc_t, caddr_t, struct timeval); +static void clntunix_abort (void); +static void clntunix_geterr (CLIENT *, struct rpc_err *); +static bool_t clntunix_freeres (CLIENT *, xdrproc_t, caddr_t); +static bool_t clntunix_control (CLIENT *, int, char *); +static void clntunix_destroy (CLIENT *); + +static const struct clnt_ops unix_ops = +{ + clntunix_call, + clntunix_abort, + clntunix_geterr, + clntunix_freeres, + clntunix_destroy, + clntunix_control +}; + +/* + * 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 * +clntunix_create (struct sockaddr_un *raddr, u_long prog, u_long vers, + int *sockp, u_int sendsz, u_int recvsz) +{ + CLIENT *h; + struct ct_data *ct = (struct ct_data *) mem_alloc (sizeof (*ct)); + struct rpc_msg call_msg; + int len; + + h = (CLIENT *) mem_alloc (sizeof (*h)); + if (h == NULL || ct == NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + goto fooy; + } + + /* + * If no socket given, open one + */ + if (*sockp < 0) + { + *sockp = __socket (AF_UNIX, SOCK_STREAM, 0); + len = strlen (raddr->sun_path) + sizeof (raddr->sun_family) + 1; + if (*sockp < 0 + || __connect (*sockp, (struct sockaddr *) raddr, len) < 0) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = errno; + if (*sockp != -1) + __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 + */ + call_msg.rm_xid = _create_xid (); + 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 static 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) + __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, readunix, writeunix); + h->cl_ops = (struct clnt_ops *) &unix_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; +} +libc_hidden_nolink_sunrpc (clntunix_create, GLIBC_2_1) + +static enum clnt_stat +clntunix_call (CLIENT *h, u_long proc, xdrproc_t xdr_args, caddr_t args_ptr, + xdrproc_t xdr_results, caddr_t results_ptr, + struct timeval timeout) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + struct rpc_msg reply_msg; + u_long x_id; + u_int32_t *msg_x_id = (u_int32_t *) (ct->ct_mcall); /* yuk */ + bool_t shipnow; + int refreshes = 2; + + if (!ct->ct_waitset) + { + ct->ct_wait = timeout; + } + + shipnow = + (xdr_results == (xdrproc_t) 0 && ct->ct_wait.tv_sec == 0 + && ct->ct_wait.tv_usec == 0) ? FALSE : TRUE; + +call_again: + xdrs->x_op = XDR_ENCODE; + ct->ct_error.re_status = RPC_SUCCESS; + x_id = ntohl (--(*msg_x_id)); + if ((!XDR_PUTBYTES (xdrs, ct->ct_mcall, ct->ct_mpos)) || + (!XDR_PUTLONG (xdrs, (long *) &proc)) || + (!AUTH_MARSHALL (h->cl_auth, xdrs)) || + (!(*xdr_args) (xdrs, args_ptr))) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTENCODEARGS; + (void) xdrrec_endofrecord (xdrs, TRUE); + return ct->ct_error.re_status; + } + if (!xdrrec_endofrecord (xdrs, shipnow)) + return ct->ct_error.re_status = RPC_CANTSEND; + if (!shipnow) + return RPC_SUCCESS; + /* + * Hack to provide rpc-based message passing + */ + if (ct->ct_wait.tv_sec == 0 && ct->ct_wait.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 = (xdrproc_t)xdr_void; + if (!xdrrec_skiprecord (xdrs)) + return ct->ct_error.re_status; + /* now decode and validate the response header */ + if (!xdr_replymsg (xdrs, &reply_msg)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + continue; + return ct->ct_error.re_status; + } + if (reply_msg.rm_xid == x_id) + break; + } + + /* + * process header + */ + _seterr_reply (&reply_msg, &(ct->ct_error)); + if (ct->ct_error.re_status == RPC_SUCCESS) + { + if (!AUTH_VALIDATE (h->cl_auth, &reply_msg.acpted_rply.ar_verf)) + { + ct->ct_error.re_status = RPC_AUTHERROR; + ct->ct_error.re_why = AUTH_INVALIDRESP; + } + else if (!(*xdr_results) (xdrs, results_ptr)) + { + if (ct->ct_error.re_status == RPC_SUCCESS) + ct->ct_error.re_status = RPC_CANTDECODERES; + } + /* free verifier ... */ + if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) + { + xdrs->x_op = XDR_FREE; + (void) xdr_opaque_auth (xdrs, &(reply_msg.acpted_rply.ar_verf)); + } + } /* end successful completion */ + else + { + /* maybe our credentials need to be refreshed ... */ + if (refreshes-- && AUTH_REFRESH (h->cl_auth)) + goto call_again; + } /* end of unsuccessful completion */ + return ct->ct_error.re_status; +} + +static void +clntunix_geterr (CLIENT *h, struct rpc_err *errp) +{ + struct ct_data *ct = (struct ct_data *) h->cl_private; + + *errp = ct->ct_error; +} + +static bool_t +clntunix_freeres (CLIENT *cl, xdrproc_t xdr_res, caddr_t res_ptr) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + XDR *xdrs = &(ct->ct_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_res) (xdrs, res_ptr); +} + +static void +clntunix_abort (void) +{ +} + +static bool_t +clntunix_control (CLIENT *cl, int request, char *info) +{ + struct ct_data *ct = (struct ct_data *) cl->cl_private; + u_long ul; + u_int32_t ui32; + + switch (request) + { + case CLSET_FD_CLOSE: + ct->ct_closeit = TRUE; + break; + case CLSET_FD_NCLOSE: + ct->ct_closeit = FALSE; + break; + case CLSET_TIMEOUT: + ct->ct_wait = *(struct timeval *) info; + break; + case CLGET_TIMEOUT: + *(struct timeval *) info = ct->ct_wait; + break; + case CLGET_SERVER_ADDR: + *(struct sockaddr_un *) info = ct->ct_addr; + break; + case CLGET_FD: + *(int *)info = ct->ct_sock; + break; + case CLGET_XID: + /* + * use the knowledge that xid is the + * first element in the call structure *. + * This will get the xid of the PREVIOUS call + */ + memcpy (&ui32, ct->ct_mcall, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_XID: + /* This will set the xid of the NEXT call */ + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul - 1); + memcpy (ct->ct_mcall, &ui32, sizeof (ui32)); + /* decrement by 1 as clntunix_call() increments once */ + break; + case CLGET_VERS: + /* + * This RELIES on the information that, in the call body, + * the version number field is the fifth field from the + * beginning of the RPC header. MUST be changed if the + * call_struct is changed + */ + memcpy (&ui32, ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_VERS: + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul); + memcpy (ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32)); + break; + case CLGET_PROG: + /* + * This RELIES on the information that, in the call body, + * the program number field is the field from the + * beginning of the RPC header. MUST be changed if the + * call_struct is changed + */ + memcpy (&ui32, ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, sizeof (ui32)); + ul = ntohl (ui32); + memcpy (info, &ul, sizeof (ul)); + break; + case CLSET_PROG: + memcpy (&ul, info, sizeof (ul)); + ui32 = htonl (ul); + memcpy (ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT, &ui32, sizeof (ui32)); + break; + /* The following are only possible with TI-RPC */ + case CLGET_RETRY_TIMEOUT: + case CLSET_RETRY_TIMEOUT: + case CLGET_SVC_ADDR: + case CLSET_SVC_ADDR: + case CLSET_PUSH_TIMOD: + case CLSET_POP_TIMOD: + default: + return FALSE; + } + return TRUE; +} + + +static void +clntunix_destroy (CLIENT *h) +{ + 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)); +} + +static int +__msgread (int sock, void *data, size_t cnt) +{ + struct iovec iov; + struct msghdr msg; +#ifdef SCM_CREDENTIALS + static char cm[CMSG_SPACE(sizeof (struct ucred))]; +#endif + int len; + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; +#ifdef SCM_CREDENTIALS + msg.msg_control = (caddr_t) &cm; + msg.msg_controllen = CMSG_SPACE(sizeof (struct ucred)); +#endif + msg.msg_flags = 0; + +#ifdef SO_PASSCRED + { + int on = 1; + if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on))) + return -1; + } +#endif + + restart: + len = __recvmsg (sock, &msg, 0); + if (len >= 0) + { + if (msg.msg_flags & MSG_CTRUNC || len == 0) + return 0; + else + return len; + } + if (errno == EINTR) + goto restart; + return -1; +} + +static int +__msgwrite (int sock, void *data, size_t cnt) +{ +#ifndef SCM_CREDENTIALS + /* We cannot implement this reliably. */ + __set_errno (ENOSYS); + return -1; +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg = alloca (CMSG_SPACE(sizeof (struct ucred))); + struct ucred cred; + int len; + + /* XXX I'm not sure, if gete?id() is always correct, or if we should use + get?id(). But since keyserv needs geteuid(), we have no other chance. + It would be much better, if the kernel could pass both to the server. */ + cred.pid = __getpid (); + cred.uid = __geteuid (); + cred.gid = __getegid (); + + memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred); + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); + msg.msg_flags = 0; + + restart: + len = __sendmsg (sock, &msg, 0); + if (len >= 0) + return len; + if (errno == EINTR) + goto restart; + return -1; + +#endif +} + + +/* + * Interface between xdr serializer and unix connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readunix (char *ctptr, char *buf, int len) +{ + struct ct_data *ct = (struct ct_data *) ctptr; + struct pollfd fd; + int milliseconds = ((ct->ct_wait.tv_sec * 1000) + + (ct->ct_wait.tv_usec / 1000)); + + if (len == 0) + return 0; + + fd.fd = ct->ct_sock; + fd.events = POLLIN; + while (TRUE) + { + switch (__poll (&fd, 1, milliseconds)) + { + 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 = __msgread (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 +writeunix (char *ctptr, char *buf, int len) +{ + int i, cnt; + struct ct_data *ct = (struct ct_data *) ctptr; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = __msgwrite (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/REORG.TODO/sunrpc/create_xid.c b/REORG.TODO/sunrpc/create_xid.c new file mode 100644 index 0000000000..815589049e --- /dev/null +++ b/REORG.TODO/sunrpc/create_xid.c @@ -0,0 +1,55 @@ +/* Copyright (c) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <unistd.h> +#include <stdlib.h> +#include <sys/time.h> +#include <libc-lock.h> +#include <rpc/rpc.h> + +/* The RPC code is not threadsafe, but new code should be threadsafe. */ + +__libc_lock_define_initialized (static, createxid_lock) + +static pid_t is_initialized; +static struct drand48_data __rpc_lrand48_data; + +unsigned long +_create_xid (void) +{ + long int res; + + __libc_lock_lock (createxid_lock); + + pid_t pid = getpid (); + if (is_initialized != pid) + { + struct timeval now; + + __gettimeofday (&now, (struct timezone *) 0); + __srand48_r (now.tv_sec ^ now.tv_usec ^ pid, + &__rpc_lrand48_data); + is_initialized = pid; + } + + lrand48_r (&__rpc_lrand48_data, &res); + + __libc_lock_unlock (createxid_lock); + + return res; +} diff --git a/REORG.TODO/sunrpc/des_crypt.c b/REORG.TODO/sunrpc/des_crypt.c new file mode 100644 index 0000000000..a4d8b2936b --- /dev/null +++ b/REORG.TODO/sunrpc/des_crypt.c @@ -0,0 +1,118 @@ +/* + * des_crypt.c, DES encryption library routines + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/types.h> +#include <rpc/des_crypt.h> +#include <shlib-compat.h> +#include "des.h" + +extern int _des_crypt (char *, unsigned, struct desparams *); + +/* + * Copy 8 bytes + */ +#define COPY8(src, dst) { \ + register char *a = (char *) dst; \ + register char *b = (char *) src; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +} + +/* + * Copy multiple of 8 bytes + */ +#define DESCOPY(src, dst, len) { \ + register char *a = (char *) dst; \ + register char *b = (char *) src; \ + register int i; \ + for (i = (int) len; i > 0; i -= 8) { \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ + } \ +} + +/* + * Common code to cbc_crypt() & ecb_crypt() + */ +static int +common_crypt (char *key, char *buf, register unsigned len, + unsigned mode, register struct desparams *desp) +{ + register int desdev; + + if ((len % 8) != 0 || len > DES_MAXDATA) + return DESERR_BADPARAM; + + desp->des_dir = + ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT; + + desdev = mode & DES_DEVMASK; + COPY8 (key, desp->des_key); + /* + * software + */ + if (!_des_crypt (buf, len, desp)) + return DESERR_HWERROR; + + return desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE; +} + +/* + * CBC mode encryption + */ +int +cbc_crypt (char *key, char *buf, unsigned int len, unsigned int mode, + char *ivec) +{ + int err; + struct desparams dp; + + dp.des_mode = CBC; + COPY8 (ivec, dp.des_ivec); + err = common_crypt (key, buf, len, mode, &dp); + COPY8 (dp.des_ivec, ivec); + return err; +} +libc_hidden_nolink_sunrpc (cbc_crypt, GLIBC_2_1) + +/* + * ECB mode encryption + */ +int +ecb_crypt (char *key, char *buf, unsigned int len, unsigned int mode) +{ + struct desparams dp; + + dp.des_mode = ECB; + return common_crypt (key, buf, len, mode, &dp); +} +libc_hidden_nolink_sunrpc (ecb_crypt, GLIBC_2_1) diff --git a/REORG.TODO/sunrpc/des_impl.c b/REORG.TODO/sunrpc/des_impl.c new file mode 100644 index 0000000000..1757dc1fb2 --- /dev/null +++ b/REORG.TODO/sunrpc/des_impl.c @@ -0,0 +1,596 @@ +/* Copyright (C) 1992 Eric Young */ +/* Collected from libdes and modified for SECURE RPC by Martin Kuck 1994 */ +/* This file is distributed under the terms of the GNU Lesser General */ +/* Public License, version 2.1 or later - see the file COPYING.LIB for details.*/ +/* If you did not receive a copy of the license with this program, please*/ +/* see <http://www.gnu.org/licenses/> to obtain a copy. */ +#include <string.h> +#include <stdint.h> +#include "des.h" + + +static const uint32_t des_SPtrans[8][64] = +{ + { /* nibble 0 */ + 0x00820200, 0x00020000, 0x80800000, 0x80820200, + 0x00800000, 0x80020200, 0x80020000, 0x80800000, + 0x80020200, 0x00820200, 0x00820000, 0x80000200, + 0x80800200, 0x00800000, 0x00000000, 0x80020000, + 0x00020000, 0x80000000, 0x00800200, 0x00020200, + 0x80820200, 0x00820000, 0x80000200, 0x00800200, + 0x80000000, 0x00000200, 0x00020200, 0x80820000, + 0x00000200, 0x80800200, 0x80820000, 0x00000000, + 0x00000000, 0x80820200, 0x00800200, 0x80020000, + 0x00820200, 0x00020000, 0x80000200, 0x00800200, + 0x80820000, 0x00000200, 0x00020200, 0x80800000, + 0x80020200, 0x80000000, 0x80800000, 0x00820000, + 0x80820200, 0x00020200, 0x00820000, 0x80800200, + 0x00800000, 0x80000200, 0x80020000, 0x00000000, + 0x00020000, 0x00800000, 0x80800200, 0x00820200, + 0x80000000, 0x80820000, 0x00000200, 0x80020200}, + + { /* nibble 1 */ + 0x10042004, 0x00000000, 0x00042000, 0x10040000, + 0x10000004, 0x00002004, 0x10002000, 0x00042000, + 0x00002000, 0x10040004, 0x00000004, 0x10002000, + 0x00040004, 0x10042000, 0x10040000, 0x00000004, + 0x00040000, 0x10002004, 0x10040004, 0x00002000, + 0x00042004, 0x10000000, 0x00000000, 0x00040004, + 0x10002004, 0x00042004, 0x10042000, 0x10000004, + 0x10000000, 0x00040000, 0x00002004, 0x10042004, + 0x00040004, 0x10042000, 0x10002000, 0x00042004, + 0x10042004, 0x00040004, 0x10000004, 0x00000000, + 0x10000000, 0x00002004, 0x00040000, 0x10040004, + 0x00002000, 0x10000000, 0x00042004, 0x10002004, + 0x10042000, 0x00002000, 0x00000000, 0x10000004, + 0x00000004, 0x10042004, 0x00042000, 0x10040000, + 0x10040004, 0x00040000, 0x00002004, 0x10002000, + 0x10002004, 0x00000004, 0x10040000, 0x00042000}, + + { /* nibble 2 */ + 0x41000000, 0x01010040, 0x00000040, 0x41000040, + 0x40010000, 0x01000000, 0x41000040, 0x00010040, + 0x01000040, 0x00010000, 0x01010000, 0x40000000, + 0x41010040, 0x40000040, 0x40000000, 0x41010000, + 0x00000000, 0x40010000, 0x01010040, 0x00000040, + 0x40000040, 0x41010040, 0x00010000, 0x41000000, + 0x41010000, 0x01000040, 0x40010040, 0x01010000, + 0x00010040, 0x00000000, 0x01000000, 0x40010040, + 0x01010040, 0x00000040, 0x40000000, 0x00010000, + 0x40000040, 0x40010000, 0x01010000, 0x41000040, + 0x00000000, 0x01010040, 0x00010040, 0x41010000, + 0x40010000, 0x01000000, 0x41010040, 0x40000000, + 0x40010040, 0x41000000, 0x01000000, 0x41010040, + 0x00010000, 0x01000040, 0x41000040, 0x00010040, + 0x01000040, 0x00000000, 0x41010000, 0x40000040, + 0x41000000, 0x40010040, 0x00000040, 0x01010000}, + + { /* nibble 3 */ + 0x00100402, 0x04000400, 0x00000002, 0x04100402, + 0x00000000, 0x04100000, 0x04000402, 0x00100002, + 0x04100400, 0x04000002, 0x04000000, 0x00000402, + 0x04000002, 0x00100402, 0x00100000, 0x04000000, + 0x04100002, 0x00100400, 0x00000400, 0x00000002, + 0x00100400, 0x04000402, 0x04100000, 0x00000400, + 0x00000402, 0x00000000, 0x00100002, 0x04100400, + 0x04000400, 0x04100002, 0x04100402, 0x00100000, + 0x04100002, 0x00000402, 0x00100000, 0x04000002, + 0x00100400, 0x04000400, 0x00000002, 0x04100000, + 0x04000402, 0x00000000, 0x00000400, 0x00100002, + 0x00000000, 0x04100002, 0x04100400, 0x00000400, + 0x04000000, 0x04100402, 0x00100402, 0x00100000, + 0x04100402, 0x00000002, 0x04000400, 0x00100402, + 0x00100002, 0x00100400, 0x04100000, 0x04000402, + 0x00000402, 0x04000000, 0x04000002, 0x04100400}, + + { /* nibble 4 */ + 0x02000000, 0x00004000, 0x00000100, 0x02004108, + 0x02004008, 0x02000100, 0x00004108, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x00004100, + 0x02000108, 0x02004008, 0x02004100, 0x00000000, + 0x00004100, 0x02000000, 0x00004008, 0x00000108, + 0x02000100, 0x00004108, 0x00000000, 0x02000008, + 0x00000008, 0x02000108, 0x02004108, 0x00004008, + 0x02004000, 0x00000100, 0x00000108, 0x02004100, + 0x02004100, 0x02000108, 0x00004008, 0x02004000, + 0x00004000, 0x00000008, 0x02000008, 0x02000100, + 0x02000000, 0x00004100, 0x02004108, 0x00000000, + 0x00004108, 0x02000000, 0x00000100, 0x00004008, + 0x02000108, 0x00000100, 0x00000000, 0x02004108, + 0x02004008, 0x02004100, 0x00000108, 0x00004000, + 0x00004100, 0x02004008, 0x02000100, 0x00000108, + 0x00000008, 0x00004108, 0x02004000, 0x02000008}, + + { /* nibble 5 */ + 0x20000010, 0x00080010, 0x00000000, 0x20080800, + 0x00080010, 0x00000800, 0x20000810, 0x00080000, + 0x00000810, 0x20080810, 0x00080800, 0x20000000, + 0x20000800, 0x20000010, 0x20080000, 0x00080810, + 0x00080000, 0x20000810, 0x20080010, 0x00000000, + 0x00000800, 0x00000010, 0x20080800, 0x20080010, + 0x20080810, 0x20080000, 0x20000000, 0x00000810, + 0x00000010, 0x00080800, 0x00080810, 0x20000800, + 0x00000810, 0x20000000, 0x20000800, 0x00080810, + 0x20080800, 0x00080010, 0x00000000, 0x20000800, + 0x20000000, 0x00000800, 0x20080010, 0x00080000, + 0x00080010, 0x20080810, 0x00080800, 0x00000010, + 0x20080810, 0x00080800, 0x00080000, 0x20000810, + 0x20000010, 0x20080000, 0x00080810, 0x00000000, + 0x00000800, 0x20000010, 0x20000810, 0x20080800, + 0x20080000, 0x00000810, 0x00000010, 0x20080010}, + + { /* nibble 6 */ + 0x00001000, 0x00000080, 0x00400080, 0x00400001, + 0x00401081, 0x00001001, 0x00001080, 0x00000000, + 0x00400000, 0x00400081, 0x00000081, 0x00401000, + 0x00000001, 0x00401080, 0x00401000, 0x00000081, + 0x00400081, 0x00001000, 0x00001001, 0x00401081, + 0x00000000, 0x00400080, 0x00400001, 0x00001080, + 0x00401001, 0x00001081, 0x00401080, 0x00000001, + 0x00001081, 0x00401001, 0x00000080, 0x00400000, + 0x00001081, 0x00401000, 0x00401001, 0x00000081, + 0x00001000, 0x00000080, 0x00400000, 0x00401001, + 0x00400081, 0x00001081, 0x00001080, 0x00000000, + 0x00000080, 0x00400001, 0x00000001, 0x00400080, + 0x00000000, 0x00400081, 0x00400080, 0x00001080, + 0x00000081, 0x00001000, 0x00401081, 0x00400000, + 0x00401080, 0x00000001, 0x00001001, 0x00401081, + 0x00400001, 0x00401080, 0x00401000, 0x00001001}, + + { /* nibble 7 */ + 0x08200020, 0x08208000, 0x00008020, 0x00000000, + 0x08008000, 0x00200020, 0x08200000, 0x08208020, + 0x00000020, 0x08000000, 0x00208000, 0x00008020, + 0x00208020, 0x08008020, 0x08000020, 0x08200000, + 0x00008000, 0x00208020, 0x00200020, 0x08008000, + 0x08208020, 0x08000020, 0x00000000, 0x00208000, + 0x08000000, 0x00200000, 0x08008020, 0x08200020, + 0x00200000, 0x00008000, 0x08208000, 0x00000020, + 0x00200000, 0x00008000, 0x08000020, 0x08208020, + 0x00008020, 0x08000000, 0x00000000, 0x00208000, + 0x08200020, 0x08008020, 0x08008000, 0x00200020, + 0x08208000, 0x00000020, 0x00200020, 0x08008000, + 0x08208020, 0x00200000, 0x08200000, 0x08000020, + 0x00208000, 0x00008020, 0x08008020, 0x08200000, + 0x00000020, 0x08208000, 0x00208020, 0x00000000, + 0x08000000, 0x08200020, 0x00008000, 0x00208020}}; + +static const uint32_t des_skb[8][64] = +{ + { /* for C bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000, 0x00000010, 0x20000000, 0x20000010, + 0x00010000, 0x00010010, 0x20010000, 0x20010010, + 0x00000800, 0x00000810, 0x20000800, 0x20000810, + 0x00010800, 0x00010810, 0x20010800, 0x20010810, + 0x00000020, 0x00000030, 0x20000020, 0x20000030, + 0x00010020, 0x00010030, 0x20010020, 0x20010030, + 0x00000820, 0x00000830, 0x20000820, 0x20000830, + 0x00010820, 0x00010830, 0x20010820, 0x20010830, + 0x00080000, 0x00080010, 0x20080000, 0x20080010, + 0x00090000, 0x00090010, 0x20090000, 0x20090010, + 0x00080800, 0x00080810, 0x20080800, 0x20080810, + 0x00090800, 0x00090810, 0x20090800, 0x20090810, + 0x00080020, 0x00080030, 0x20080020, 0x20080030, + 0x00090020, 0x00090030, 0x20090020, 0x20090030, + 0x00080820, 0x00080830, 0x20080820, 0x20080830, + 0x00090820, 0x00090830, 0x20090820, 0x20090830}, + { /* for C bits (numbered as per FIPS 46) 7 8 10 11 12 13 */ + 0x00000000, 0x02000000, 0x00002000, 0x02002000, + 0x00200000, 0x02200000, 0x00202000, 0x02202000, + 0x00000004, 0x02000004, 0x00002004, 0x02002004, + 0x00200004, 0x02200004, 0x00202004, 0x02202004, + 0x00000400, 0x02000400, 0x00002400, 0x02002400, + 0x00200400, 0x02200400, 0x00202400, 0x02202400, + 0x00000404, 0x02000404, 0x00002404, 0x02002404, + 0x00200404, 0x02200404, 0x00202404, 0x02202404, + 0x10000000, 0x12000000, 0x10002000, 0x12002000, + 0x10200000, 0x12200000, 0x10202000, 0x12202000, + 0x10000004, 0x12000004, 0x10002004, 0x12002004, + 0x10200004, 0x12200004, 0x10202004, 0x12202004, + 0x10000400, 0x12000400, 0x10002400, 0x12002400, + 0x10200400, 0x12200400, 0x10202400, 0x12202400, + 0x10000404, 0x12000404, 0x10002404, 0x12002404, + 0x10200404, 0x12200404, 0x10202404, 0x12202404}, + { /* for C bits (numbered as per FIPS 46) 14 15 16 17 19 20 */ + 0x00000000, 0x00000001, 0x00040000, 0x00040001, + 0x01000000, 0x01000001, 0x01040000, 0x01040001, + 0x00000002, 0x00000003, 0x00040002, 0x00040003, + 0x01000002, 0x01000003, 0x01040002, 0x01040003, + 0x00000200, 0x00000201, 0x00040200, 0x00040201, + 0x01000200, 0x01000201, 0x01040200, 0x01040201, + 0x00000202, 0x00000203, 0x00040202, 0x00040203, + 0x01000202, 0x01000203, 0x01040202, 0x01040203, + 0x08000000, 0x08000001, 0x08040000, 0x08040001, + 0x09000000, 0x09000001, 0x09040000, 0x09040001, + 0x08000002, 0x08000003, 0x08040002, 0x08040003, + 0x09000002, 0x09000003, 0x09040002, 0x09040003, + 0x08000200, 0x08000201, 0x08040200, 0x08040201, + 0x09000200, 0x09000201, 0x09040200, 0x09040201, + 0x08000202, 0x08000203, 0x08040202, 0x08040203, + 0x09000202, 0x09000203, 0x09040202, 0x09040203}, + { /* for C bits (numbered as per FIPS 46) 21 23 24 26 27 28 */ + 0x00000000, 0x00100000, 0x00000100, 0x00100100, + 0x00000008, 0x00100008, 0x00000108, 0x00100108, + 0x00001000, 0x00101000, 0x00001100, 0x00101100, + 0x00001008, 0x00101008, 0x00001108, 0x00101108, + 0x04000000, 0x04100000, 0x04000100, 0x04100100, + 0x04000008, 0x04100008, 0x04000108, 0x04100108, + 0x04001000, 0x04101000, 0x04001100, 0x04101100, + 0x04001008, 0x04101008, 0x04001108, 0x04101108, + 0x00020000, 0x00120000, 0x00020100, 0x00120100, + 0x00020008, 0x00120008, 0x00020108, 0x00120108, + 0x00021000, 0x00121000, 0x00021100, 0x00121100, + 0x00021008, 0x00121008, 0x00021108, 0x00121108, + 0x04020000, 0x04120000, 0x04020100, 0x04120100, + 0x04020008, 0x04120008, 0x04020108, 0x04120108, + 0x04021000, 0x04121000, 0x04021100, 0x04121100, + 0x04021008, 0x04121008, 0x04021108, 0x04121108}, + { /* for D bits (numbered as per FIPS 46) 1 2 3 4 5 6 */ + 0x00000000, 0x10000000, 0x00010000, 0x10010000, + 0x00000004, 0x10000004, 0x00010004, 0x10010004, + 0x20000000, 0x30000000, 0x20010000, 0x30010000, + 0x20000004, 0x30000004, 0x20010004, 0x30010004, + 0x00100000, 0x10100000, 0x00110000, 0x10110000, + 0x00100004, 0x10100004, 0x00110004, 0x10110004, + 0x20100000, 0x30100000, 0x20110000, 0x30110000, + 0x20100004, 0x30100004, 0x20110004, 0x30110004, + 0x00001000, 0x10001000, 0x00011000, 0x10011000, + 0x00001004, 0x10001004, 0x00011004, 0x10011004, + 0x20001000, 0x30001000, 0x20011000, 0x30011000, + 0x20001004, 0x30001004, 0x20011004, 0x30011004, + 0x00101000, 0x10101000, 0x00111000, 0x10111000, + 0x00101004, 0x10101004, 0x00111004, 0x10111004, + 0x20101000, 0x30101000, 0x20111000, 0x30111000, + 0x20101004, 0x30101004, 0x20111004, 0x30111004}, + { /* for D bits (numbered as per FIPS 46) 8 9 11 12 13 14 */ + 0x00000000, 0x08000000, 0x00000008, 0x08000008, + 0x00000400, 0x08000400, 0x00000408, 0x08000408, + 0x00020000, 0x08020000, 0x00020008, 0x08020008, + 0x00020400, 0x08020400, 0x00020408, 0x08020408, + 0x00000001, 0x08000001, 0x00000009, 0x08000009, + 0x00000401, 0x08000401, 0x00000409, 0x08000409, + 0x00020001, 0x08020001, 0x00020009, 0x08020009, + 0x00020401, 0x08020401, 0x00020409, 0x08020409, + 0x02000000, 0x0A000000, 0x02000008, 0x0A000008, + 0x02000400, 0x0A000400, 0x02000408, 0x0A000408, + 0x02020000, 0x0A020000, 0x02020008, 0x0A020008, + 0x02020400, 0x0A020400, 0x02020408, 0x0A020408, + 0x02000001, 0x0A000001, 0x02000009, 0x0A000009, + 0x02000401, 0x0A000401, 0x02000409, 0x0A000409, + 0x02020001, 0x0A020001, 0x02020009, 0x0A020009, + 0x02020401, 0x0A020401, 0x02020409, 0x0A020409}, + { /* for D bits (numbered as per FIPS 46) 16 17 18 19 20 21 */ + 0x00000000, 0x00000100, 0x00080000, 0x00080100, + 0x01000000, 0x01000100, 0x01080000, 0x01080100, + 0x00000010, 0x00000110, 0x00080010, 0x00080110, + 0x01000010, 0x01000110, 0x01080010, 0x01080110, + 0x00200000, 0x00200100, 0x00280000, 0x00280100, + 0x01200000, 0x01200100, 0x01280000, 0x01280100, + 0x00200010, 0x00200110, 0x00280010, 0x00280110, + 0x01200010, 0x01200110, 0x01280010, 0x01280110, + 0x00000200, 0x00000300, 0x00080200, 0x00080300, + 0x01000200, 0x01000300, 0x01080200, 0x01080300, + 0x00000210, 0x00000310, 0x00080210, 0x00080310, + 0x01000210, 0x01000310, 0x01080210, 0x01080310, + 0x00200200, 0x00200300, 0x00280200, 0x00280300, + 0x01200200, 0x01200300, 0x01280200, 0x01280300, + 0x00200210, 0x00200310, 0x00280210, 0x00280310, + 0x01200210, 0x01200310, 0x01280210, 0x01280310}, + { /* for D bits (numbered as per FIPS 46) 22 23 24 25 27 28 */ + 0x00000000, 0x04000000, 0x00040000, 0x04040000, + 0x00000002, 0x04000002, 0x00040002, 0x04040002, + 0x00002000, 0x04002000, 0x00042000, 0x04042000, + 0x00002002, 0x04002002, 0x00042002, 0x04042002, + 0x00000020, 0x04000020, 0x00040020, 0x04040020, + 0x00000022, 0x04000022, 0x00040022, 0x04040022, + 0x00002020, 0x04002020, 0x00042020, 0x04042020, + 0x00002022, 0x04002022, 0x00042022, 0x04042022, + 0x00000800, 0x04000800, 0x00040800, 0x04040800, + 0x00000802, 0x04000802, 0x00040802, 0x04040802, + 0x00002800, 0x04002800, 0x00042800, 0x04042800, + 0x00002802, 0x04002802, 0x00042802, 0x04042802, + 0x00000820, 0x04000820, 0x00040820, 0x04040820, + 0x00000822, 0x04000822, 0x00040822, 0x04040822, + 0x00002820, 0x04002820, 0x00042820, 0x04042820, + 0x00002822, 0x04002822, 0x00042822, 0x04042822}, +}; + +#define c2l(c,l) (l =((unsigned long)(*((c)++))) , \ + l|=((unsigned long)(*((c)++)))<< 8, \ + l|=((unsigned long)(*((c)++)))<<16, \ + l|=((unsigned long)(*((c)++)))<<24) + +#define l2c(l,c) (*((c)++)=(unsigned char)(((l) )&0xff), \ + *((c)++)=(unsigned char)(((l)>> 8)&0xff), \ + *((c)++)=(unsigned char)(((l)>>16)&0xff), \ + *((c)++)=(unsigned char)(((l)>>24)&0xff)) + +/* + * IP and FP + * The problem is more of a geometric problem that random bit fiddling. + * 0 1 2 3 4 5 6 7 62 54 46 38 30 22 14 6 + * 8 9 10 11 12 13 14 15 60 52 44 36 28 20 12 4 + * 16 17 18 19 20 21 22 23 58 50 42 34 26 18 10 2 + * 24 25 26 27 28 29 30 31 to 56 48 40 32 24 16 8 0 + * + * 32 33 34 35 36 37 38 39 63 55 47 39 31 23 15 7 + * 40 41 42 43 44 45 46 47 61 53 45 37 29 21 13 5 + * 48 49 50 51 52 53 54 55 59 51 43 35 27 19 11 3 + * 56 57 58 59 60 61 62 63 57 49 41 33 25 17 9 1 + * + * The output has been subject to swaps of the form + * 0 1 -> 3 1 but the odd and even bits have been put into + * 2 3 2 0 + * different words. The main trick is to remember that + * t=((l>>size)^r)&(mask); + * r^=t; + * l^=(t<<size); + * can be used to swap and move bits between words. + * + * So l = 0 1 2 3 r = 16 17 18 19 + * 4 5 6 7 20 21 22 23 + * 8 9 10 11 24 25 26 27 + * 12 13 14 15 28 29 30 31 + * becomes (for size == 2 and mask == 0x3333) + * t = 2^16 3^17 -- -- l = 0 1 16 17 r = 2 3 18 19 + * 6^20 7^21 -- -- 4 5 20 21 6 7 22 23 + * 10^24 11^25 -- -- 8 9 24 25 10 11 24 25 + * 14^28 15^29 -- -- 12 13 28 29 14 15 28 29 + * + * Thanks for hints from Richard Outerbridge - he told me IP&FP + * could be done in 15 xor, 10 shifts and 5 ands. + * When I finally started to think of the problem in 2D + * I first got ~42 operations without xors. When I remembered + * how to use xors :-) I got it to its final state. + */ + +#define PERM_OP(a,b,t,n,m) ((t)=((((a)>>(n))^(b))&(m)),\ + (b)^=(t),\ + (a)^=((t)<<(n))) + +#define HPERM_OP(a,t,n,m) ((t)=((((a)<<(16-(n)))^(a))&(m)),\ + (a)=(a)^(t)^(t>>(16-(n)))) + + +#define D_ENCRYPT(L,R,S) \ + u=(R^s[S ]); \ + t=R^s[S+1]; \ + t=((t>>4)+(t<<28)); \ + L^= des_SPtrans[1][(t )&0x3f]| \ + des_SPtrans[3][(t>> 8)&0x3f]| \ + des_SPtrans[5][(t>>16)&0x3f]| \ + des_SPtrans[7][(t>>24)&0x3f]| \ + des_SPtrans[0][(u )&0x3f]| \ + des_SPtrans[2][(u>> 8)&0x3f]| \ + des_SPtrans[4][(u>>16)&0x3f]| \ + des_SPtrans[6][(u>>24)&0x3f]; + +#define ITERATIONS 16 + +static const char shifts2[16] = +{0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 0}; + +static void des_set_key (unsigned char *, unsigned long *) internal_function; +static void des_encrypt (unsigned long *, unsigned long *, int) + internal_function; +int _des_crypt (char *, unsigned, struct desparams *); + +static void +internal_function +des_set_key (unsigned char *key, unsigned long *schedule) +{ + register unsigned long c, d, t, s; + register unsigned char *in; + register unsigned long *k; + register int i; + + k = (unsigned long *) schedule; + in = key; + + c2l (in, c); + c2l (in, d); + + /* I now do it in 47 simple operations :-) + * Thanks to John Fletcher (john_fletcher@lccmail.ocf.llnl.gov) + * for the inspiration. :-) */ + PERM_OP (d, c, t, 4, 0x0f0f0f0f); + HPERM_OP (c, t, -2, 0xcccc0000); + HPERM_OP (d, t, -2, 0xcccc0000); + PERM_OP (d, c, t, 1, 0x55555555); + PERM_OP (c, d, t, 8, 0x00ff00ff); + PERM_OP (d, c, t, 1, 0x55555555); + d = (((d & 0x000000ff) << 16) | (d & 0x0000ff00) | + ((d & 0x00ff0000) >> 16) | ((c & 0xf0000000) >> 4)); + c &= 0x0fffffff; + + for (i = 0; i < ITERATIONS; i++) + { + if (shifts2[i]) + { + c = ((c >> 2) | (c << 26)); + d = ((d >> 2) | (d << 26)); + } + else + { + c = ((c >> 1) | (c << 27)); + d = ((d >> 1) | (d << 27)); + } + c &= 0x0fffffff; + d &= 0x0fffffff; + /* could be a few less shifts but I am to lazy at this + * point in time to investigate */ + s = des_skb[0][(c) & 0x3f] | + des_skb[1][((c >> 6) & 0x03) | ((c >> 7) & 0x3c)] | + des_skb[2][((c >> 13) & 0x0f) | ((c >> 14) & 0x30)] | + des_skb[3][((c >> 20) & 0x01) | ((c >> 21) & 0x06) | ((c >> 22) & 0x38)]; + t = des_skb[4][(d) & 0x3f] | + des_skb[5][((d >> 7) & 0x03) | ((d >> 8) & 0x3c)] | + des_skb[6][(d >> 15) & 0x3f] | + des_skb[7][((d >> 21) & 0x0f) | ((d >> 22) & 0x30)]; + + /* table contained 0213 4657 */ + *(k++) = ((t << 16) | (s & 0x0000ffff)) & 0xffffffff; + s = ((s >> 16) | (t & 0xffff0000)); + + s = (s << 4) | (s >> 28); + *(k++) = s & 0xffffffff; + } +} + + +static void +internal_function +des_encrypt (unsigned long *buf, unsigned long *schedule, int encrypt) +{ + register unsigned long l, r, t, u; + register int i; + register unsigned long *s; + + l = buf[0]; + r = buf[1]; + + /* do IP */ + PERM_OP (r, l, t, 4, 0x0f0f0f0f); + PERM_OP (l, r, t, 16, 0x0000ffff); + PERM_OP (r, l, t, 2, 0x33333333); + PERM_OP (l, r, t, 8, 0x00ff00ff); + PERM_OP (r, l, t, 1, 0x55555555); + /* r and l are reversed - remember that :-) - fix + * it in the next step */ + + /* Things have been modified so that the initial rotate is + * done outside the loop. This required the + * des_SPtrans values in sp.h to be rotated 1 bit to the right. + * One perl script later and things have a 5% speed up on a sparc2. + * Thanks to Richard Outerbridge <71755.204@CompuServe.COM> + * for pointing this out. */ + t = (r << 1) | (r >> 31); + r = (l << 1) | (l >> 31); + l = t; + + /* clear the top bits on machines with 8byte longs */ + l &= 0xffffffff; + r &= 0xffffffff; + + s = (unsigned long *) schedule; + /* I don't know if it is worth the effort of loop unrolling the + * inner loop */ + if (encrypt) + { + for (i = 0; i < 32; i += 4) + { + D_ENCRYPT (l, r, i + 0); /* 1 */ + D_ENCRYPT (r, l, i + 2); /* 2 */ + } + } + else + { + for (i = 30; i > 0; i -= 4) + { + D_ENCRYPT (l, r, i - 0); /* 16 */ + D_ENCRYPT (r, l, i - 2); /* 15 */ + } + } + l = (l >> 1) | (l << 31); + r = (r >> 1) | (r << 31); + /* clear the top bits on machines with 8byte longs */ + l &= 0xffffffff; + r &= 0xffffffff; + + /* swap l and r + * we will not do the swap so just remember they are + * reversed for the rest of the subroutine + * luckily FP fixes this problem :-) */ + + PERM_OP (r, l, t, 1, 0x55555555); + PERM_OP (l, r, t, 8, 0x00ff00ff); + PERM_OP (r, l, t, 2, 0x33333333); + PERM_OP (l, r, t, 16, 0x0000ffff); + PERM_OP (r, l, t, 4, 0x0f0f0f0f); + + buf[0] = l; + buf[1] = r; + + l = r = t = u = 0; +} + + +int +_des_crypt (char *buf, unsigned len, struct desparams *desp) +{ + unsigned long schedule[32]; + register unsigned long tin0, tin1; + register unsigned long tout0, tout1, xor0, xor1; + register unsigned char *in, *out; + unsigned long tbuf[2]; + unsigned char *iv, *oiv; + int cbc_mode; + + cbc_mode = (desp->des_mode == CBC) ? 1 : 0; + + in = (unsigned char *) buf; + out = (unsigned char *) buf; + oiv = iv = (unsigned char *) desp->des_ivec; + + des_set_key (desp->des_key, schedule); + + tin0 = tin1 = 0; /* For GCC */ + if (desp->des_dir == ENCRYPT) + { + c2l (iv, tout0); + c2l (iv, tout1); + for (; len > 0; len -= 8) + { + c2l (in, tin0); + c2l (in, tin1); + if (cbc_mode) + { + tin0 ^= tout0; + tin1 ^= tout1; + } + tbuf[0] = tin0; + tbuf[1] = tin1; + des_encrypt (tbuf, schedule, 1); + tout0 = tbuf[0]; + tout1 = tbuf[1]; + l2c (tout0, out); + l2c (tout1, out); + } + l2c (tout0, oiv); + l2c (tout1, oiv); + } + else + { + c2l (iv, xor0); + c2l (iv, xor1); + for (; len > 0; len -= 8) + { + c2l (in, tin0); + c2l (in, tin1); + tbuf[0] = tin0; + tbuf[1] = tin1; + des_encrypt (tbuf, schedule, 0); + if (cbc_mode) + { + tout0 = tbuf[0] ^ xor0; + tout1 = tbuf[1] ^ xor1; + xor0 = tin0; + xor1 = tin1; + } + else + { + tout0 = tbuf[0]; + tout1 = tbuf[1]; + } + l2c (tout0, out); + l2c (tout1, out); + } + l2c (tin0, oiv); + l2c (tin1, oiv); + } + tin0 = tin1 = tout0 = tout1 = xor0 = xor1 = 0; + tbuf[0] = tbuf[1] = 0; + __bzero (schedule, sizeof (schedule)); + + return (1); +} diff --git a/REORG.TODO/sunrpc/des_soft.c b/REORG.TODO/sunrpc/des_soft.c new file mode 100644 index 0000000000..f884f8f21b --- /dev/null +++ b/REORG.TODO/sunrpc/des_soft.c @@ -0,0 +1,74 @@ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; +#endif +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/des_crypt.h> +#include <shlib-compat.h> + +/* + * Table giving odd parity in the low bit for ASCII characters + */ +static const char partab[128] = +{ + 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, + 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, + 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, + 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, + 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, + 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, + 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, + 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, + 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, + 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, + 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, + 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, + 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, + 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, + 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, + 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, +}; + +/* + * Add odd parity to low bit of 8 byte key + */ +void +des_setparity (char *p) +{ + int i; + + for (i = 0; i < 8; i++) + { + *p = partab[*p & 0x7f]; + p++; + } +} +libc_hidden_nolink_sunrpc (des_setparity, GLIBC_2_1) diff --git a/REORG.TODO/sunrpc/etc.rpc b/REORG.TODO/sunrpc/etc.rpc new file mode 100644 index 0000000000..e099ebb289 --- /dev/null +++ b/REORG.TODO/sunrpc/etc.rpc @@ -0,0 +1,70 @@ +#ident "@(#)rpc 1.11 95/07/14 SMI" /* SVr4.0 1.2 */ +# +# rpc +# +portmapper 100000 portmap sunrpc rpcbind +rstatd 100001 rstat rup perfmeter rstat_svc +rusersd 100002 rusers +nfs 100003 nfsprog +ypserv 100004 ypprog +mountd 100005 mount showmount +ypbind 100007 +walld 100008 rwall shutdown +yppasswdd 100009 yppasswd +etherstatd 100010 etherstat +rquotad 100011 rquotaprog quota rquota +sprayd 100012 spray +3270_mapper 100013 +rje_mapper 100014 +selection_svc 100015 selnsvc +database_svc 100016 +rexd 100017 rex +alis 100018 +sched 100019 +llockmgr 100020 +nlockmgr 100021 +x25.inr 100022 +statmon 100023 +status 100024 +bootparam 100026 +ypupdated 100028 ypupdate +keyserv 100029 keyserver +sunlink_mapper 100033 +tfsd 100037 +nsed 100038 +nsemntd 100039 +showfhd 100043 showfh +ioadmd 100055 rpc.ioadmd +NETlicense 100062 +sunisamd 100065 +debug_svc 100066 dbsrv +ypxfrd 100069 rpc.ypxfrd +bugtraqd 100071 +kerbd 100078 +event 100101 na.event # SunNet Manager +logger 100102 na.logger # SunNet Manager +sync 100104 na.sync +hostperf 100107 na.hostperf +activity 100109 na.activity # SunNet Manager +hostmem 100112 na.hostmem +sample 100113 na.sample +x25 100114 na.x25 +ping 100115 na.ping +rpcnfs 100116 na.rpcnfs +hostif 100117 na.hostif +etherif 100118 na.etherif +iproutes 100120 na.iproutes +layers 100121 na.layers +snmp 100122 na.snmp snmp-cmc snmp-synoptics snmp-unisys snmp-utk +traffic 100123 na.traffic +nfs_acl 100227 +sadmind 100232 +nisd 100300 rpc.nisd +nispasswd 100303 rpc.nispasswdd +ufsd 100233 ufsd +fedfs_admin 100418 +pcnfsd 150001 pcnfs +amd 300019 amq +sgi_fam 391002 fam +bwnfsd 545580417 +fypxfrd 600100069 freebsd-ypxfrd diff --git a/REORG.TODO/sunrpc/get_myaddr.c b/REORG.TODO/sunrpc/get_myaddr.c new file mode 100644 index 0000000000..df334e4134 --- /dev/null +++ b/REORG.TODO/sunrpc/get_myaddr.c @@ -0,0 +1,103 @@ +/* + * get_myaddress.c + * + * Get client's IP address via ioctl. This avoids using the yellowpages. + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/types.h> +#include <rpc/clnt.h> +#include <rpc/pmap_prot.h> +#include <sys/socket.h> +#include <stdio.h> +#include <unistd.h> +#include <libintl.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <sys/ioctl.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <shlib-compat.h> + +/* + * don't use gethostbyname, which would invoke yellow pages + * + * Avoid loopback interfaces. We return information from a loopback + * interface only if there are no other possible interfaces. + */ +void +get_myaddress (struct sockaddr_in *addr) +{ + struct ifaddrs *ifa; + + if (getifaddrs (&ifa) != 0) + { + perror ("get_myaddress: getifaddrs"); + exit (1); + } + + int loopback = 0; + struct ifaddrs *run; + + again: + run = ifa; + while (run != NULL) + { + if ((run->ifa_flags & IFF_UP) + && run->ifa_addr != NULL + && run->ifa_addr->sa_family == AF_INET + && (!(run->ifa_flags & IFF_LOOPBACK) + || (loopback == 1 && (run->ifa_flags & IFF_LOOPBACK)))) + { + *addr = *((struct sockaddr_in *) run->ifa_addr); + addr->sin_port = htons (PMAPPORT); + goto out; + } + + run = run->ifa_next; + } + + if (loopback == 0) + { + loopback = 1; + goto again; + } + out: + freeifaddrs (ifa); + + /* The function is horribly specified. It does not return any error + if no interface is up. Probably this won't happen (at least + loopback is there) but still... */ +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (get_myaddress) +#else +libc_hidden_nolink_sunrpc (get_myaddress, GLIBC_2_0) +#endif diff --git a/REORG.TODO/sunrpc/getrpcbyname.c b/REORG.TODO/sunrpc/getrpcbyname.c new file mode 100644 index 0000000000..ed15bbef75 --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcbyname.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/netdb.h> + + +#define LOOKUP_TYPE struct rpcent +#define FUNCTION_NAME getrpcbyname +#define DATABASE_NAME rpc +#define ADD_PARAMS const char *name +#define ADD_VARIABLES name +#define BUFLEN 1024 + +/* There is no nscd support for the rpc file. */ +#undef USE_NSCD + +#include "../nss/getXXbyYY.c" diff --git a/REORG.TODO/sunrpc/getrpcbyname_r.c b/REORG.TODO/sunrpc/getrpcbyname_r.c new file mode 100644 index 0000000000..46a79acbcd --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcbyname_r.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/netdb.h> + + +#define LOOKUP_TYPE struct rpcent +#define FUNCTION_NAME getrpcbyname +#define DATABASE_NAME rpc +#define ADD_PARAMS const char *name +#define ADD_VARIABLES name + +/* There is no nscd support for the rpc file. */ +#undef USE_NSCD + +#include "../nss/getXXbyYY_r.c" diff --git a/REORG.TODO/sunrpc/getrpcbynumber.c b/REORG.TODO/sunrpc/getrpcbynumber.c new file mode 100644 index 0000000000..35a2a37d81 --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcbynumber.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/netdb.h> + + +#define LOOKUP_TYPE struct rpcent +#define FUNCTION_NAME getrpcbynumber +#define DATABASE_NAME rpc +#define ADD_PARAMS int number +#define ADD_VARIABLES number +#define BUFLEN 1024 + +/* There is no nscd support for the rpc file. */ +#undef USE_NSCD + +#include "../nss/getXXbyYY.c" diff --git a/REORG.TODO/sunrpc/getrpcbynumber_r.c b/REORG.TODO/sunrpc/getrpcbynumber_r.c new file mode 100644 index 0000000000..42dbfe02b5 --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcbynumber_r.c @@ -0,0 +1,31 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/netdb.h> + + +#define LOOKUP_TYPE struct rpcent +#define FUNCTION_NAME getrpcbynumber +#define DATABASE_NAME rpc +#define ADD_PARAMS int number +#define ADD_VARIABLES number + +/* There is no nscd support for the rpc file. */ +#undef USE_NSCD + +#include "../nss/getXXbyYY_r.c" diff --git a/REORG.TODO/sunrpc/getrpcent.c b/REORG.TODO/sunrpc/getrpcent.c new file mode 100644 index 0000000000..c7df97f415 --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcent.c @@ -0,0 +1,28 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/netdb.h> + + +#define LOOKUP_TYPE struct rpcent +#define GETFUNC_NAME getrpcent +#define BUFLEN 1024 + +/* There is no nscd support for the rpc file. */ +#undef USE_NSCD + +#include "../nss/getXXent.c" diff --git a/REORG.TODO/sunrpc/getrpcent_r.c b/REORG.TODO/sunrpc/getrpcent_r.c new file mode 100644 index 0000000000..0fe57d239a --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcent_r.c @@ -0,0 +1,32 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netdb.h> + + +#define LOOKUP_TYPE struct rpcent +#define SETFUNC_NAME setrpcent +#define GETFUNC_NAME getrpcent +#define ENDFUNC_NAME endrpcent +#define DATABASE_NAME rpc +#define STAYOPEN int stayopen +#define STAYOPEN_VAR stayopen + +/* There is no nscd support for the rpc file. */ +#undef USE_NSCD + +#include "../nss/getXXent_r.c" diff --git a/REORG.TODO/sunrpc/getrpcport.c b/REORG.TODO/sunrpc/getrpcport.c new file mode 100644 index 0000000000..02dd533f2b --- /dev/null +++ b/REORG.TODO/sunrpc/getrpcport.c @@ -0,0 +1,68 @@ +/* Obtain the RPC port number for an RPC service on a host. + Copyright (C) 2016-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <alloca.h> +#include <errno.h> +#include <stdio.h> +#include <netdb.h> +#include <string.h> +#include <rpc/rpc.h> +#include <rpc/clnt.h> +#include <rpc/pmap_clnt.h> +#include <sys/socket.h> + +int +getrpcport (const char *host, u_long prognum, u_long versnum, u_int proto) +{ + struct sockaddr_in addr; + + if (__libc_rpc_gethostbyname (host, &addr) != 0) + return 0; + return pmap_getport (&addr, prognum, versnum, proto); +} diff --git a/REORG.TODO/sunrpc/key_call.c b/REORG.TODO/sunrpc/key_call.c new file mode 100644 index 0000000000..b871c04648 --- /dev/null +++ b/REORG.TODO/sunrpc/key_call.c @@ -0,0 +1,576 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * The original source is from the RPCSRC 4.0 package from Sun Microsystems. + * The Interface to keyserver protocoll 2, RPC over AF_UNIX and Linux/doors + * was added by Thorsten Kukuk <kukuk@suse.de> + * Since the Linux/doors project was stopped, I doubt that this code will + * ever be useful <kukuk@suse.de>. + */ + +#include <stdio.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <rpc/auth.h> +#include <sys/wait.h> +#include <sys/param.h> +#include <sys/socket.h> +#include <rpc/key_prot.h> +#include <libc-lock.h> +#include <shlib-compat.h> + +#define KEY_TIMEOUT 5 /* per-try timeout in seconds */ +#define KEY_NRETRY 12 /* number of retries */ + +#define debug(msg) /* turn off debugging */ + +#ifndef SO_PASSCRED +extern int _openchild (const char *command, FILE **fto, FILE **ffrom); +#endif + +static int key_call (u_long, xdrproc_t xdr_arg, char *, + xdrproc_t xdr_rslt, char *) internal_function; + +static const struct timeval trytimeout = {KEY_TIMEOUT, 0}; +static const struct timeval tottimeout = {KEY_TIMEOUT *KEY_NRETRY, 0}; + +int +key_setsecret (char *secretkey) +{ + keystatus status; + + if (!key_call ((u_long) KEY_SET, (xdrproc_t) xdr_keybuf, secretkey, + (xdrproc_t) xdr_keystatus, (char *) &status)) + return -1; + if (status != KEY_SUCCESS) + { + debug ("set status is nonzero"); + return -1; + } + return 0; +} +libc_hidden_nolink_sunrpc (key_setsecret, GLIBC_2_1) + +/* key_secretkey_is_set() returns 1 if the keyserver has a secret key + * stored for the caller's effective uid; it returns 0 otherwise + * + * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't + * be using it, because it allows them to get the user's secret key. + */ +int +key_secretkey_is_set (void) +{ + struct key_netstres kres; + + memset (&kres, 0, sizeof (kres)); + if (key_call ((u_long) KEY_NET_GET, (xdrproc_t) xdr_void, + (char *) NULL, (xdrproc_t) xdr_key_netstres, + (char *) &kres) && + (kres.status == KEY_SUCCESS) && + (kres.key_netstres_u.knet.st_priv_key[0] != 0)) + { + /* avoid leaving secret key in memory */ + memset (kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); + return 1; + } + return 0; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (key_secretkey_is_set) +#else +libc_hidden_nolink_sunrpc (key_secretkey_is_set, GLIBC_2_1) +#endif + +int +key_encryptsession (char *remotename, des_block *deskey) +{ + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.deskey = *deskey; + if (!key_call ((u_long) KEY_ENCRYPT, (xdrproc_t) xdr_cryptkeyarg, + (char *) &arg, (xdrproc_t) xdr_cryptkeyres, + (char *) &res)) + return -1; + + if (res.status != KEY_SUCCESS) + { + debug ("encrypt status is nonzero"); + return -1; + } + *deskey = res.cryptkeyres_u.deskey; + return 0; +} +libc_hidden_nolink_sunrpc (key_encryptsession, GLIBC_2_1) + +int +key_decryptsession (char *remotename, des_block *deskey) +{ + cryptkeyarg arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.deskey = *deskey; + if (!key_call ((u_long) KEY_DECRYPT, (xdrproc_t) xdr_cryptkeyarg, + (char *) &arg, (xdrproc_t) xdr_cryptkeyres, + (char *) &res)) + return -1; + if (res.status != KEY_SUCCESS) + { + debug ("decrypt status is nonzero"); + return -1; + } + *deskey = res.cryptkeyres_u.deskey; + return 0; +} +libc_hidden_nolink_sunrpc (key_decryptsession, GLIBC_2_1) + +int +key_encryptsession_pk (char *remotename, netobj *remotekey, + des_block *deskey) +{ + cryptkeyarg2 arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.remotekey = *remotekey; + arg.deskey = *deskey; + if (!key_call ((u_long) KEY_ENCRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, + (char *) &arg, (xdrproc_t) xdr_cryptkeyres, + (char *) &res)) + return -1; + + if (res.status != KEY_SUCCESS) + { + debug ("encrypt status is nonzero"); + return -1; + } + *deskey = res.cryptkeyres_u.deskey; + return 0; +} +libc_hidden_nolink_sunrpc (key_encryptsession_pk, GLIBC_2_1) + +int +key_decryptsession_pk (char *remotename, netobj *remotekey, + des_block *deskey) +{ + cryptkeyarg2 arg; + cryptkeyres res; + + arg.remotename = remotename; + arg.remotekey = *remotekey; + arg.deskey = *deskey; + if (!key_call ((u_long) KEY_DECRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, + (char *) &arg, (xdrproc_t) xdr_cryptkeyres, + (char *) &res)) + return -1; + + if (res.status != KEY_SUCCESS) + { + debug ("decrypt status is nonzero"); + return -1; + } + *deskey = res.cryptkeyres_u.deskey; + return 0; +} +libc_hidden_nolink_sunrpc (key_decryptsession_pk, GLIBC_2_1) + +int +key_gendes (des_block *key) +{ + struct sockaddr_in sin; + CLIENT *client; + int socket; + enum clnt_stat stat; + + sin.sin_family = AF_INET; + sin.sin_port = 0; + sin.sin_addr.s_addr = htonl (INADDR_LOOPBACK); + __bzero (sin.sin_zero, sizeof (sin.sin_zero)); + socket = RPC_ANYSOCK; + client = clntudp_bufcreate (&sin, (u_long) KEY_PROG, (u_long) KEY_VERS, + trytimeout, &socket, RPCSMALLMSGSIZE, + RPCSMALLMSGSIZE); + if (client == NULL) + return -1; + + stat = clnt_call (client, KEY_GEN, (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_des_block, (caddr_t) key, + tottimeout); + clnt_destroy (client); + __close (socket); + if (stat != RPC_SUCCESS) + return -1; + + return 0; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (key_gendes) +#else +libc_hidden_nolink_sunrpc (key_gendes, GLIBC_2_1) +#endif + +int +key_setnet (struct key_netstarg *arg) +{ + keystatus status; + + if (!key_call ((u_long) KEY_NET_PUT, (xdrproc_t) xdr_key_netstarg, + (char *) arg,(xdrproc_t) xdr_keystatus, + (char *) &status)) + return -1; + + if (status != KEY_SUCCESS) + { + debug ("key_setnet status is nonzero"); + return -1; + } + return 1; +} +libc_hidden_nolink_sunrpc (key_setnet, GLIBC_2_1) + +int +key_get_conv (char *pkey, des_block *deskey) +{ + cryptkeyres res; + + if (!key_call ((u_long) KEY_GET_CONV, (xdrproc_t) xdr_keybuf, pkey, + (xdrproc_t) xdr_cryptkeyres, (char *) &res)) + return -1; + + if (res.status != KEY_SUCCESS) + { + debug ("get_conv status is nonzero"); + return -1; + } + *deskey = res.cryptkeyres_u.deskey; + return 0; +} +libc_hidden_nolink_sunrpc (key_get_conv, GLIBC_2_1) + +/* + * Hack to allow the keyserver to use AUTH_DES (for authenticated + * NIS+ calls, for example). The only functions that get called + * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. + * + * The approach is to have the keyserver fill in pointers to local + * implementations of these functions, and to call those in key_call(). + */ + +cryptkeyres *(*__key_encryptsession_pk_LOCAL) (uid_t, char *); +cryptkeyres *(*__key_decryptsession_pk_LOCAL) (uid_t, char *); +des_block *(*__key_gendes_LOCAL) (uid_t, char *); + +#ifndef SO_PASSCRED +static int +internal_function +key_call_keyenvoy (u_long proc, xdrproc_t xdr_arg, char *arg, + xdrproc_t xdr_rslt, char *rslt) +{ + XDR xdrargs; + XDR xdrrslt; + FILE *fargs; + FILE *frslt; + sigset_t oldmask, mask; + int status; + int pid; + int success; + uid_t ruid; + uid_t euid; + static const char MESSENGER[] = "/usr/etc/keyenvoy"; + + success = 1; + sigemptyset (&mask); + sigaddset (&mask, SIGCHLD); + __sigprocmask (SIG_BLOCK, &mask, &oldmask); + + /* + * We are going to exec a set-uid program which makes our effective uid + * zero, and authenticates us with our real uid. We need to make the + * effective uid be the real uid for the setuid program, and + * the real uid be the effective uid so that we can change things back. + */ + euid = __geteuid (); + ruid = __getuid (); + __setreuid (euid, ruid); + pid = _openchild (MESSENGER, &fargs, &frslt); + __setreuid (ruid, euid); + if (pid < 0) + { + debug ("open_streams"); + __sigprocmask (SIG_SETMASK, &oldmask, NULL); + return (0); + } + xdrstdio_create (&xdrargs, fargs, XDR_ENCODE); + xdrstdio_create (&xdrrslt, frslt, XDR_DECODE); + + if (!xdr_u_long (&xdrargs, &proc) || !(*xdr_arg) (&xdrargs, arg)) + { + debug ("xdr args"); + success = 0; + } + fclose (fargs); + + if (success && !(*xdr_rslt) (&xdrrslt, rslt)) + { + debug ("xdr rslt"); + success = 0; + } + fclose(frslt); + + wait_again: + if (__wait4 (pid, &status, 0, NULL) < 0) + { + if (errno == EINTR) + goto wait_again; + debug ("wait4"); + if (errno == ECHILD || errno == ESRCH) + perror ("wait"); + else + success = 0; + } + else + if (status != 0) + { + debug ("wait4 1"); + success = 0; + } + __sigprocmask (SIG_SETMASK, &oldmask, NULL); + + return success; +} +#endif + +struct key_call_private { + CLIENT *client; /* Client handle */ + pid_t pid; /* process-id at moment of creation */ + uid_t uid; /* user-id at last authorization */ +}; +#ifdef _RPC_THREAD_SAFE_ +#define key_call_private_main RPC_THREAD_VARIABLE(key_call_private_s) +#else +static struct key_call_private *key_call_private_main; +#endif +__libc_lock_define_initialized (static, keycall_lock) + +/* + * Keep the handle cached. This call may be made quite often. + */ +static CLIENT * +getkeyserv_handle (int vers) +{ + struct key_call_private *kcp = key_call_private_main; + struct timeval wait_time; + int fd; + struct sockaddr_un name; + socklen_t namelen = sizeof(struct sockaddr_un); + +#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ +#define TOTAL_TRIES 5 /* Number of tries */ + + if (kcp == (struct key_call_private *)NULL) + { + kcp = (struct key_call_private *)malloc (sizeof (*kcp)); + if (kcp == (struct key_call_private *)NULL) + return (CLIENT *) NULL; + + key_call_private_main = kcp; + kcp->client = NULL; + } + + /* if pid has changed, destroy client and rebuild */ + if (kcp->client != NULL && kcp->pid != __getpid ()) + { + auth_destroy (kcp->client->cl_auth); + clnt_destroy (kcp->client); + kcp->client = NULL; + } + + if (kcp->client != NULL) + { + /* if other side closed socket, build handle again */ + clnt_control (kcp->client, CLGET_FD, (char *)&fd); + if (__getpeername (fd,(struct sockaddr *)&name,&namelen) == -1) + { + auth_destroy (kcp->client->cl_auth); + clnt_destroy (kcp->client); + kcp->client = NULL; + } + } + + if (kcp->client != NULL) + { + /* if uid has changed, build client handle again */ + if (kcp->uid != __geteuid ()) + { + kcp->uid = __geteuid (); + auth_destroy (kcp->client->cl_auth); + kcp->client->cl_auth = + authunix_create ((char *)"", kcp->uid, 0, 0, NULL); + if (kcp->client->cl_auth == NULL) + { + clnt_destroy (kcp->client); + kcp->client = NULL; + return ((CLIENT *) NULL); + } + } + /* Change the version number to the new one */ + clnt_control (kcp->client, CLSET_VERS, (void *)&vers); + return kcp->client; + } + + if ((kcp->client == (CLIENT *) NULL)) + /* Use the AF_UNIX transport */ + kcp->client = clnt_create ("/var/run/keyservsock", KEY_PROG, vers, "unix"); + + if (kcp->client == (CLIENT *) NULL) + return (CLIENT *) NULL; + + kcp->uid = __geteuid (); + kcp->pid = __getpid (); + kcp->client->cl_auth = authunix_create ((char *)"", kcp->uid, 0, 0, NULL); + if (kcp->client->cl_auth == NULL) + { + clnt_destroy (kcp->client); + kcp->client = NULL; + return (CLIENT *) NULL; + } + + wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; + wait_time.tv_usec = 0; + clnt_control (kcp->client, CLSET_RETRY_TIMEOUT, + (char *)&wait_time); + if (clnt_control (kcp->client, CLGET_FD, (char *)&fd)) + __fcntl (fd, F_SETFD, FD_CLOEXEC); /* make it "close on exec" */ + + return kcp->client; +} + +/* returns 0 on failure, 1 on success */ +static int +internal_function +key_call_socket (u_long proc, xdrproc_t xdr_arg, char *arg, + xdrproc_t xdr_rslt, char *rslt) +{ + CLIENT *clnt; + struct timeval wait_time; + int result = 0; + + __libc_lock_lock (keycall_lock); + if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || + (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || + (proc == KEY_GET_CONV)) + clnt = getkeyserv_handle(2); /* talk to version 2 */ + else + clnt = getkeyserv_handle(1); /* talk to version 1 */ + + if (clnt != NULL) + { + wait_time.tv_sec = TOTAL_TIMEOUT; + wait_time.tv_usec = 0; + + if (clnt_call (clnt, proc, xdr_arg, arg, xdr_rslt, rslt, + wait_time) == RPC_SUCCESS) + result = 1; + } + + __libc_lock_unlock (keycall_lock); + + return result; +} + + +/* returns 0 on failure, 1 on success */ +static int +internal_function +key_call (u_long proc, xdrproc_t xdr_arg, char *arg, + xdrproc_t xdr_rslt, char *rslt) +{ +#ifndef SO_PASSCRED + static int use_keyenvoy; +#endif + + if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) + { + cryptkeyres *res; + res = (*__key_encryptsession_pk_LOCAL) (__geteuid (), arg); + *(cryptkeyres *) rslt = *res; + return 1; + } + else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) + { + cryptkeyres *res; + res = (*__key_decryptsession_pk_LOCAL) (__geteuid (), arg); + *(cryptkeyres *) rslt = *res; + return 1; + } + else if (proc == KEY_GEN && __key_gendes_LOCAL) + { + des_block *res; + res = (*__key_gendes_LOCAL) (__geteuid (), 0); + *(des_block *) rslt = *res; + return 1; + } + +#ifdef SO_PASSCRED + return key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt); +#else + if (!use_keyenvoy) + { + if (key_call_socket (proc, xdr_arg, arg, xdr_rslt, rslt)) + return 1; + use_keyenvoy = 1; + } + return key_call_keyenvoy (proc, xdr_arg, arg, xdr_rslt, rslt); +#endif +} + +#ifdef _RPC_THREAD_SAFE_ +void +__rpc_thread_key_cleanup (void) +{ + struct key_call_private *kcp = RPC_THREAD_VARIABLE(key_call_private_s); + + if (kcp) { + if (kcp->client) { + if (kcp->client->cl_auth) + auth_destroy (kcp->client->cl_auth); + clnt_destroy(kcp->client); + } + free (kcp); + } +} +#endif /* _RPC_THREAD_SAFE_ */ diff --git a/REORG.TODO/sunrpc/key_prot.c b/REORG.TODO/sunrpc/key_prot.c new file mode 100644 index 0000000000..3659bab1d3 --- /dev/null +++ b/REORG.TODO/sunrpc/key_prot.c @@ -0,0 +1,170 @@ +/* Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/key_prot.h> +#include <shlib-compat.h> + +bool_t +xdr_keystatus (XDR * xdrs, keystatus * objp) +{ + if (!xdr_enum (xdrs, (enum_t *) objp)) + return FALSE; + + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_keystatus, GLIBC_2_0) + +bool_t +xdr_keybuf (XDR * xdrs, keybuf objp) +{ + if (!xdr_opaque (xdrs, objp, HEXKEYBYTES)) + return FALSE; + + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_keybuf, GLIBC_2_0) + +bool_t +xdr_netnamestr (XDR * xdrs, netnamestr * objp) +{ + if (!xdr_string (xdrs, objp, MAXNETNAMELEN)) + return FALSE; + + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_netnamestr, GLIBC_2_1) + +bool_t +xdr_cryptkeyarg (XDR * xdrs, cryptkeyarg * objp) +{ + if (!xdr_netnamestr (xdrs, &objp->remotename)) + return FALSE; + + if (!xdr_des_block (xdrs, &objp->deskey)) + return FALSE; + + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_cryptkeyarg, GLIBC_2_0) + +bool_t +xdr_cryptkeyarg2 (XDR * xdrs, cryptkeyarg2 * objp) +{ + if (!xdr_netnamestr (xdrs, &objp->remotename)) + return FALSE; + if (!xdr_netobj (xdrs, &objp->remotekey)) + return FALSE; + if (!xdr_des_block (xdrs, &objp->deskey)) + return FALSE; + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_cryptkeyarg2, GLIBC_2_0) + +bool_t +xdr_cryptkeyres (XDR * xdrs, cryptkeyres * objp) +{ + if (!xdr_keystatus (xdrs, &objp->status)) + return FALSE; + switch (objp->status) + { + case KEY_SUCCESS: + if (!xdr_des_block (xdrs, &objp->cryptkeyres_u.deskey)) + return FALSE; + break; + default: + break; + } + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_cryptkeyres, GLIBC_2_0) + +bool_t +xdr_unixcred (XDR * xdrs, unixcred * objp) +{ + if (!xdr_u_int (xdrs, &objp->uid)) + return FALSE; + if (!xdr_u_int (xdrs, &objp->gid)) + return FALSE; + if (!xdr_array (xdrs, (void *) &objp->gids.gids_val, + (u_int *) & objp->gids.gids_len, MAXGIDS, + sizeof (u_int), (xdrproc_t) xdr_u_int)) + return FALSE; + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_unixcred, GLIBC_2_1) + +bool_t +xdr_getcredres (XDR * xdrs, getcredres * objp) +{ + if (!xdr_keystatus (xdrs, &objp->status)) + return FALSE; + switch (objp->status) + { + case KEY_SUCCESS: + if (!xdr_unixcred (xdrs, &objp->getcredres_u.cred)) + return FALSE; + break; + default: + break; + } + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_getcredres, GLIBC_2_1) + +bool_t +xdr_key_netstarg (XDR * xdrs, key_netstarg * objp) +{ + if (!xdr_keybuf (xdrs, objp->st_priv_key)) + return FALSE; + if (!xdr_keybuf (xdrs, objp->st_pub_key)) + return FALSE; + if (!xdr_netnamestr (xdrs, &objp->st_netname)) + return FALSE; + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_key_netstarg, GLIBC_2_0) + +bool_t +xdr_key_netstres (XDR * xdrs, key_netstres * objp) +{ + if (!xdr_keystatus (xdrs, &objp->status)) + return FALSE; + switch (objp->status) + { + case KEY_SUCCESS: + if (!xdr_key_netstarg (xdrs, &objp->key_netstres_u.knet)) + return FALSE; + break; + default: + break; + } + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_key_netstres, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/netname.c b/REORG.TODO/sunrpc/netname.c new file mode 100644 index 0000000000..9aee3e4042 --- /dev/null +++ b/REORG.TODO/sunrpc/netname.c @@ -0,0 +1,218 @@ +/* Copyright (C) 1997-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1997. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <shlib-compat.h> + +#include "nsswitch.h" + +#define OPSYS_LEN 4 +#define MAXIPRINT (11) /* max length of printed integer */ +static const char OPSYS[] = "unix"; + +int +user2netname (char netname[MAXNETNAMELEN + 1], const uid_t uid, + const char *domain) +{ + char dfltdom[MAXNETNAMELEN + 1]; + size_t i; + + if (domain == NULL) + { + if (getdomainname (dfltdom, sizeof (dfltdom)) < 0) + return 0; + } + else + { + strncpy (dfltdom, domain, MAXNETNAMELEN); + dfltdom[MAXNETNAMELEN] = '\0'; + } + + if ((strlen (dfltdom) + OPSYS_LEN + 3 + MAXIPRINT) > (size_t) MAXNETNAMELEN) + return 0; + + sprintf (netname, "%s.%d@%s", OPSYS, uid, dfltdom); + i = strlen (netname); + if (netname[i - 1] == '.') + netname[i - 1] = '\0'; + return 1; +} +libc_hidden_nolink_sunrpc (user2netname, GLIBC_2_1) + +int +host2netname (char netname[MAXNETNAMELEN + 1], const char *host, + const char *domain) +{ + char *p; + char hostname[MAXHOSTNAMELEN + 1]; + char domainname[MAXHOSTNAMELEN + 1]; + char *dot_in_host; + size_t i; + + netname[0] = '\0'; /* make null first (no need for memset) */ + + if (host == NULL) + __gethostname (hostname, MAXHOSTNAMELEN); + else + { + strncpy (hostname, host, MAXHOSTNAMELEN); + hostname[MAXHOSTNAMELEN] = '\0'; + } + + dot_in_host = strchr (hostname, '.'); + if (domain == NULL) + { + p = dot_in_host; + if (p) + { + ++p; + strncpy (domainname, p, MAXHOSTNAMELEN); + domainname[MAXHOSTNAMELEN] = '\0'; + } + else + { + domainname[0] = 0; + getdomainname (domainname, MAXHOSTNAMELEN); + } + } + else + { + strncpy (domainname, domain, MAXHOSTNAMELEN); + domainname[MAXHOSTNAMELEN] = '\0'; + } + + i = strlen (domainname); + if (i == 0) + /* No domainname */ + return 0; + if (domainname[i - 1] == '.') + domainname[i - 1] = 0; + + if (dot_in_host) /* strip off rest of name */ + *dot_in_host = '\0'; + + if ((strlen (domainname) + strlen (hostname) + OPSYS_LEN + 3) + > MAXNETNAMELEN) + return 0; + + sprintf (netname, "%s.%s@%s", OPSYS, hostname, domainname); + return 1; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (host2netname) +#else +libc_hidden_nolink_sunrpc (host2netname, GLIBC_2_1) +#endif + +int +getnetname (char name[MAXNETNAMELEN + 1]) +{ + uid_t uid; + int dummy; + + uid = __geteuid (); + if (uid == 0) + dummy = host2netname (name, NULL, NULL); + else + dummy = user2netname (name, uid, NULL); + return (dummy); +} +libc_hidden_nolink_sunrpc (getnetname, GLIBC_2_1) + +/* Type of the lookup function for netname2user. */ +typedef int (*netname2user_function) (const char netname[MAXNETNAMELEN + 1], + uid_t *, gid_t *, int *, gid_t *); +/* The lookup function for the first entry of this service. */ +extern int __nss_publickey_lookup (service_user ** nip, const char *name, + void **fctp) internal_function; + +int +netname2user (const char netname[MAXNETNAMELEN + 1], uid_t * uidp, gid_t * gidp, + int *gidlenp, gid_t * gidlist) +{ + static service_user *startp; + static netname2user_function start_fct; + service_user *nip; + union + { + netname2user_function f; + void *ptr; + } fct; + enum nss_status status = NSS_STATUS_UNAVAIL; + int no_more; + + if (startp == NULL) + { + no_more = __nss_publickey_lookup (&nip, "netname2user", &fct.ptr); + if (no_more) + startp = (service_user *) - 1; + else + { + startp = nip; + start_fct = fct.f; + } + } + else + { + fct.f = start_fct; + no_more = (nip = startp) == (service_user *) - 1; + } + + while (!no_more) + { + status = (*fct.f) (netname, uidp, gidp, gidlenp, gidlist); + + no_more = __nss_next2 (&nip, "netname2user", NULL, &fct.ptr, status, 0); + } + + return status == NSS_STATUS_SUCCESS; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (netname2user) +#else +libc_hidden_nolink_sunrpc (netname2user, GLIBC_2_1) +#endif + +int +netname2host (const char netname[MAXNETNAMELEN + 1], char *hostname, + const int hostlen) +{ + char *p1, *p2; + + p1 = strchr (netname, '.'); + if (p1 == NULL) + return 0; + p1++; + + p2 = strchr (p1, '@'); + if (p2 == NULL) + return 0; + *p2 = '\0'; + + if (hostlen > MAXNETNAMELEN) + return 0; + + strncpy (hostname, p1, hostlen); + hostname[hostlen] = '\0'; + + return 1; +} +libc_hidden_nolink_sunrpc (netname2host, GLIBC_2_1) diff --git a/REORG.TODO/sunrpc/openchild.c b/REORG.TODO/sunrpc/openchild.c new file mode 100644 index 0000000000..29f274a8ad --- /dev/null +++ b/REORG.TODO/sunrpc/openchild.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Open two pipes to a child process, one for reading, one for writing. + * The pipes are accessed by FILE pointers. This is NOT a public + * interface, but for internal use only! + */ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <rpc/clnt.h> + +#include <libio/iolibio.h> +#define fflush(s) _IO_fflush (s) +#define __fdopen(fd,m) _IO_fdopen (fd,m) + +/* + * returns pid, or -1 for failure + */ +int +_openchild (const char *command, FILE ** fto, FILE ** ffrom) +{ + int i; + int pid; + int pdto[2]; + int pdfrom[2]; + + if (__pipe (pdto) < 0) + goto error1; + if (__pipe (pdfrom) < 0) + goto error2; + switch (pid = __fork ()) + { + case -1: + goto error3; + + case 0: + /* + * child: read from pdto[0], write into pdfrom[1] + */ + __close (0); + __dup (pdto[0]); + __close (1); + __dup (pdfrom[1]); + fflush (stderr); + for (i = _rpc_dtablesize () - 1; i >= 3; i--) + __close (i); + fflush (stderr); + execlp (command, command, NULL); + perror ("exec"); + _exit (~0); + + default: + /* + * parent: write into pdto[1], read from pdfrom[0] + */ + *fto = __fdopen (pdto[1], "w"); + __close (pdto[0]); + *ffrom = __fdopen (pdfrom[0], "r"); + __close (pdfrom[1]); + break; + } + return pid; + + /* + * error cleanup and return + */ +error3: + __close (pdfrom[0]); + __close (pdfrom[1]); +error2: + __close (pdto[0]); + __close (pdto[1]); +error1: + return -1; +} diff --git a/REORG.TODO/sunrpc/pm_getmaps.c b/REORG.TODO/sunrpc/pm_getmaps.c new file mode 100644 index 0000000000..88c44f0154 --- /dev/null +++ b/REORG.TODO/sunrpc/pm_getmaps.c @@ -0,0 +1,88 @@ +/* + * pmap_getmap.c + * Client interface to pmap rpc service. + * contains pmap_getmaps, which is only tcp service involved + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/rpc.h> +#include <rpc/pmap_prot.h> +#include <rpc/pmap_clnt.h> +#include <sys/socket.h> +#include <netdb.h> +#include <stdbool.h> +#include <stdio.h> +#include <errno.h> +#include <libintl.h> +#include <unistd.h> +#include <not-cancel.h> +#include <shlib-compat.h> + + +/* + * Get a copy of the current port maps. + * Calls the pmap service remotely to do get the maps. + */ +struct pmaplist * +pmap_getmaps (struct sockaddr_in *address) +{ + struct pmaplist *head = (struct pmaplist *) NULL; + struct timeval minutetimeout; + CLIENT *client; + bool closeit = false; + + minutetimeout.tv_sec = 60; + minutetimeout.tv_usec = 0; + address->sin_port = htons (PMAPPORT); + + /* Don't need a reserved port to get ports from the portmapper. */ + int socket = __get_socket (address); + if (socket != -1) + closeit = true; + + client = clnttcp_create (address, PMAPPROG, PMAPVERS, &socket, 50, 500); + if (client != (CLIENT *) NULL) + { + if (CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t)xdr_void, NULL, + (xdrproc_t)xdr_pmaplist, (caddr_t)&head, + minutetimeout) != RPC_SUCCESS) + { + clnt_perror (client, _("pmap_getmaps.c: rpc problem")); + } + CLNT_DESTROY (client); + } + /* We only need to close the socket here if we opened it. */ + if (closeit) + close_not_cancel (socket); + address->sin_port = 0; + return head; +} +libc_hidden_nolink_sunrpc (pmap_getmaps, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/pm_getport.c b/REORG.TODO/sunrpc/pm_getport.c new file mode 100644 index 0000000000..54d2e439d2 --- /dev/null +++ b/REORG.TODO/sunrpc/pm_getport.c @@ -0,0 +1,156 @@ +/* + * pmap_getport.c + * Client interface to pmap rpc service. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdbool.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <rpc/pmap_prot.h> +#include <rpc/pmap_clnt.h> +#include <sys/socket.h> +#include <shlib-compat.h> + +/* + * Create a socket that is locally bound to a non-reserve port. For + * any failures, -1 is returned which will cause the RPC code to + * create the socket. + */ +int +internal_function +__get_socket (struct sockaddr_in *saddr) +{ + int so = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP); + if (so < 0) + return -1; + + struct sockaddr_in laddr; + socklen_t namelen = sizeof (laddr); + laddr.sin_family = AF_INET; + laddr.sin_port = 0; + laddr.sin_addr.s_addr = htonl (INADDR_ANY); + + int cc = __bind (so, (struct sockaddr *) &laddr, namelen); + if (__glibc_unlikely (cc < 0)) + { + fail: + __close (so); + return -1; + } + + cc = __connect (so, (struct sockaddr *) saddr, namelen); + if (__glibc_unlikely (cc < 0)) + goto fail; + + return so; +} + + +/* + * Find the mapped port for program,version. + * Internal version with additional parameters. + * Calls the pmap service remotely to do the lookup. + * Returns 0 if no map exists. + */ +u_short +internal_function +__libc_rpc_getport (struct sockaddr_in *address, u_long program, + u_long version, u_int protocol, time_t timeout_sec, + time_t tottimeout_sec) +{ + const struct timeval timeout = {timeout_sec, 0}; + const struct timeval tottimeout = {tottimeout_sec, 0}; + + u_short port = 0; + int socket = -1; + CLIENT *client; + struct pmap parms; + bool closeit = false; + + address->sin_port = htons (PMAPPORT); + if (protocol == IPPROTO_TCP) + { + /* Don't need a reserved port to get ports from the portmapper. */ + socket = __get_socket(address); + if (socket != -1) + closeit = true; + client = clnttcp_create (address, PMAPPROG, PMAPVERS, &socket, + RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + } + else + client = clntudp_bufcreate (address, PMAPPROG, PMAPVERS, timeout, + &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); + if (client != (CLIENT *) NULL) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + 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, (xdrproc_t)xdr_pmap, + (caddr_t)&parms, (xdrproc_t)xdr_u_short, + (caddr_t)&port, tottimeout) != RPC_SUCCESS) + { + ce->cf_stat = RPC_PMAPFAILURE; + clnt_geterr (client, &ce->cf_error); + } + else if (port == 0) + { + ce->cf_stat = RPC_PROGNOTREGISTERED; + } + CLNT_DESTROY (client); + } + /* We only need to close the socket here if we opened it. */ + if (closeit) + (void) __close (socket); + address->sin_port = 0; + return port; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (__libc_rpc_getport) +#else +libc_hidden_nolink_sunrpc (__libc_rpc_getport, GLIBC_PRIVATE) +#endif + + +/* + * Find the mapped port for program,version. + * Calls the pmap service remotely to do the lookup. + * Returns 0 if no map exists. + */ +u_short +pmap_getport (struct sockaddr_in *address, u_long program, u_long version, + u_int protocol) +{ + return __libc_rpc_getport (address, program, version, protocol, 5, 60); +} +libc_hidden_nolink_sunrpc (pmap_getport, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/pmap_clnt.c b/REORG.TODO/sunrpc/pmap_clnt.c new file mode 100644 index 0000000000..69b4907b3a --- /dev/null +++ b/REORG.TODO/sunrpc/pmap_clnt.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * pmap_clnt.c + * Client interface to pmap rpc service. + */ + +#include <stdio.h> +#include <unistd.h> +#include <libintl.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <sys/ioctl.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <rpc/rpc.h> +#include <rpc/pmap_prot.h> +#include <rpc/pmap_clnt.h> +#include <shlib-compat.h> + +/* + * Same as get_myaddress, but we try to use the loopback + * interface. portmap caches interfaces, and on DHCP clients, + * it could be that only loopback is started at this time. + */ +static bool_t +__get_myaddress (struct sockaddr_in *addr) +{ + struct ifaddrs *ifa; + + if (getifaddrs (&ifa) != 0) + { + perror ("get_myaddress: getifaddrs"); + exit (1); + } + + int loopback = 1; + struct ifaddrs *run; + + again: + run = ifa; + while (run != NULL) + { + if ((run->ifa_flags & IFF_UP) + && run->ifa_addr != NULL + && run->ifa_addr->sa_family == AF_INET + && ((run->ifa_flags & IFF_LOOPBACK) || loopback == 0)) + { + *addr = *((struct sockaddr_in *) run->ifa_addr); + addr->sin_port = htons (PMAPPORT); + goto out; + } + + run = run->ifa_next; + } + + if (loopback == 1) + { + loopback = 0; + goto again; + } + out: + freeifaddrs (ifa); + + return run == NULL ? FALSE : TRUE; +} + + +static const struct timeval timeout = {5, 0}; +static const struct timeval tottimeout = {60, 0}; + +/* + * Set a mapping between program,version and port. + * Calls the pmap service remotely to do the mapping. + */ +bool_t +pmap_set (u_long program, u_long version, int protocol, u_short port) +{ + struct sockaddr_in myaddress; + int socket = -1; + CLIENT *client; + struct pmap parms; + bool_t rslt; + + if (!__get_myaddress (&myaddress)) + return FALSE; + 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, (xdrproc_t)xdr_pmap, + (caddr_t)&parms, (xdrproc_t)xdr_bool, (caddr_t)&rslt, + tottimeout) != RPC_SUCCESS) + { + clnt_perror (client, _("Cannot register service")); + rslt = FALSE; + } + CLNT_DESTROY (client); + /* (void)close(socket); CLNT_DESTROY closes it */ + return rslt; +} +libc_hidden_nolink_sunrpc (pmap_set, GLIBC_2_0) + +/* + * Remove the mapping between program,version and port. + * Calls the pmap service remotely to do the un-mapping. + */ +bool_t +pmap_unset (u_long program, u_long version) +{ + struct sockaddr_in myaddress; + int socket = -1; + CLIENT *client; + struct pmap parms; + bool_t rslt; + + if (!__get_myaddress (&myaddress)) + return FALSE; + 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, (xdrproc_t)xdr_pmap, + (caddr_t)&parms, (xdrproc_t)xdr_bool, (caddr_t)&rslt, + tottimeout); + CLNT_DESTROY (client); + /* (void)close(socket); CLNT_DESTROY already closed it */ + return rslt; +} +libc_hidden_nolink_sunrpc (pmap_unset, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/pmap_prot.c b/REORG.TODO/sunrpc/pmap_prot.c new file mode 100644 index 0000000000..d8d75a7b47 --- /dev/null +++ b/REORG.TODO/sunrpc/pmap_prot.c @@ -0,0 +1,51 @@ +/* + * pmap_prot.c + * Protocol for the local binder service, or pmap. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/pmap_prot.h> +#include <shlib-compat.h> + + +bool_t +xdr_pmap (XDR *xdrs, struct pmap *regs) +{ + + if (xdr_u_long (xdrs, ®s->pm_prog) && + xdr_u_long (xdrs, ®s->pm_vers) && + xdr_u_long (xdrs, ®s->pm_prot)) + return xdr_u_long (xdrs, ®s->pm_port); + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_pmap, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/pmap_prot2.c b/REORG.TODO/sunrpc/pmap_prot2.c new file mode 100644 index 0000000000..c414db0298 --- /dev/null +++ b/REORG.TODO/sunrpc/pmap_prot2.c @@ -0,0 +1,112 @@ +/* + * pmap_prot2.c + * Protocol for the local binder service, or pmap. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/pmap_prot.h> +#include <shlib-compat.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 (XDR *xdrs, 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; + int freeing = (xdrs->x_op == XDR_FREE); + struct pmaplist *next = NULL; + + while (TRUE) + { + more_elements = (bool_t) (*rp != NULL); + if (!xdr_bool (xdrs, &more_elements)) + return FALSE; + if (!more_elements) + return TRUE; /* we are done */ + /* + * the unfortunate side effect of non-recursion is that in + * the case of freeing we must remember the next object + * before we free the current object ... + */ + if (freeing) + next = (*rp)->pml_next; + if (!xdr_reference (xdrs, (caddr_t *) rp, + (u_int) sizeof (struct pmaplist), + (xdrproc_t) xdr_pmap)) + return FALSE; + rp = freeing ? &next : &((*rp)->pml_next); + } +} +libc_hidden_nolink_sunrpc (xdr_pmaplist, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/pmap_rmt.c b/REORG.TODO/sunrpc/pmap_rmt.c new file mode 100644 index 0000000000..c036d889ef --- /dev/null +++ b/REORG.TODO/sunrpc/pmap_rmt.c @@ -0,0 +1,393 @@ +/* + * pmap_rmt.c + * Client interface to pmap rpc service. + * remote call and broadcast service + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <string.h> +#include <libintl.h> +#include <rpc/rpc.h> +#include <rpc/pmap_prot.h> +#include <rpc/pmap_clnt.h> +#include <rpc/pmap_rmt.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <stdio.h> +#include <errno.h> +#include <sys/param.h> +#include <net/if.h> +#include <ifaddrs.h> +#include <sys/ioctl.h> +#include <arpa/inet.h> +#include <shlib-compat.h> + +#define MAX_BROADCAST_SIZE 1400 + +extern u_long _create_xid (void); + +static const 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 (struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, + xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, + struct timeval tout, u_long *port_ptr) +{ + int socket = -1; + 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, + (xdrproc_t)xdr_rmtcall_args, + (caddr_t)&a, (xdrproc_t)xdr_rmtcallres, + (caddr_t)&r, tout); + CLNT_DESTROY (client); + } + else + { + stat = RPC_FAILED; + } + /* (void)__close(socket); CLNT_DESTROY already closed it */ + addr->sin_port = 0; + return stat; +} +libc_hidden_nolink_sunrpc (pmap_rmtcall, GLIBC_2_0) + + +/* + * XDR remote call arguments + * written for XDR_ENCODE direction only + */ +bool_t +xdr_rmtcall_args (XDR *xdrs, struct rmtcallargs *cap) +{ + u_int lenposition, argposition, position; + + if (xdr_u_long (xdrs, &(cap->prog)) && + xdr_u_long (xdrs, &(cap->vers)) && + xdr_u_long (xdrs, &(cap->proc))) + { + u_long dummy_arglen = 0; + lenposition = XDR_GETPOS (xdrs); + if (!xdr_u_long (xdrs, &dummy_arglen)) + return FALSE; + argposition = XDR_GETPOS (xdrs); + if (!(*(cap->xdr_args)) (xdrs, cap->args_ptr)) + return FALSE; + position = XDR_GETPOS (xdrs); + cap->arglen = (u_long) position - (u_long) argposition; + XDR_SETPOS (xdrs, lenposition); + if (!xdr_u_long (xdrs, &(cap->arglen))) + return FALSE; + XDR_SETPOS (xdrs, position); + return TRUE; + } + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_rmtcall_args, GLIBC_2_0) + +/* + * XDR remote call results + * written for XDR_DECODE direction only + */ +bool_t +xdr_rmtcallres (XDR *xdrs, struct rmtcallres *crp) +{ + caddr_t port_ptr; + + port_ptr = (caddr_t) crp->port_ptr; + if (xdr_reference (xdrs, &port_ptr, sizeof (u_long), + (xdrproc_t) xdr_u_long) + && xdr_u_long (xdrs, &crp->resultslen)) + { + crp->port_ptr = (u_long *) port_ptr; + return (*(crp->xdr_results)) (xdrs, crp->results_ptr); + } + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_rmtcallres, GLIBC_2_0) + + +/* + * 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 +internal_function +getbroadcastnets (struct in_addr *addrs, int naddrs) +{ + struct ifaddrs *ifa; + + if (getifaddrs (&ifa) != 0) + { + perror ("broadcast: getifaddrs"); + return 0; + } + + int i = 0; + struct ifaddrs *run = ifa; + while (run != NULL && i < naddrs) + { + if ((run->ifa_flags & IFF_BROADCAST) != 0 + && (run->ifa_flags & IFF_UP) != 0 + && run->ifa_addr != NULL + && run->ifa_addr->sa_family == AF_INET) + /* Copy the broadcast address. */ + addrs[i++] = ((struct sockaddr_in *) run->ifa_broadaddr)->sin_addr; + + run = run->ifa_next; + } + + freeifaddrs (ifa); + + return i; +} + + +enum clnt_stat +clnt_broadcast (/* program number */ + u_long prog, + /* version number */ + u_long vers, + /* procedure number */ + u_long proc, + /* xdr routine for args */ + xdrproc_t xargs, + /* pointer to args */ + caddr_t argsp, + /* xdr routine for results */ + xdrproc_t xresults, + /* pointer to results */ + caddr_t resultsp, + /* call with each result obtained */ + resultproc_t eachresult) +{ + enum clnt_stat stat = RPC_FAILED; + AUTH *unix_auth = authunix_create_default (); + XDR xdr_stream; + XDR *xdrs = &xdr_stream; + struct timeval t; + int outlen, inlen, nets; + socklen_t fromlen; + int sock; + int on = 1; + struct pollfd fd; + int milliseconds; + int i; + bool_t done = FALSE; + u_long xid; + u_long port; + struct in_addr addrs[20]; + struct sockaddr_in baddr, raddr; /* broadcast and response addresses */ + struct rmtcallargs a; + struct rmtcallres r; + struct rpc_msg msg; + char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; + + /* + * initialization: create a socket, a broadcast address, and + * preserialize the arguments into a send buffer. + */ + if ((sock = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + perror (_("Cannot create socket for broadcast rpc")); + stat = RPC_CANTSEND; + goto done_broad; + } +#ifdef SO_BROADCAST + if (__setsockopt (sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (on)) < 0) + { + perror (_("Cannot set socket option SO_BROADCAST")); + stat = RPC_CANTSEND; + goto done_broad; + } +#endif /* def SO_BROADCAST */ + fd.fd = sock; + fd.events = POLLIN; + nets = getbroadcastnets (addrs, sizeof (addrs) / sizeof (addrs[0])); + __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); */ + msg.rm_xid = xid = _create_xid (); + 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 = (xdrproc_t) xdr_rmtcallres; + milliseconds = t.tv_sec * 1000 + t.tv_usec / 1000; + switch (__poll(&fd, 1, milliseconds)) + { + + case 0: /* timed out */ + stat = RPC_TIMEDOUT; + continue; + + case -1: /* some kind of error */ + if (errno == EINTR) + goto recv_again; + perror (_("Broadcast poll problem")); + stat = RPC_CANTRECV; + goto done_broad; + + } /* end of poll 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 ((size_t) inlen < sizeof (u_long)) + goto recv_again; + /* + * see if reply transaction id matches sent id. + * If so, decode the results. + */ + xdrmem_create (xdrs, inbuf, (u_int) inlen, XDR_DECODE); + if (xdr_replymsg (xdrs, &msg)) + { + if (((u_int32_t) msg.rm_xid == (u_int32_t) xid) && + (msg.rm_reply.rp_stat == MSG_ACCEPTED) && + (msg.acpted_rply.ar_stat == SUCCESS)) + { + raddr.sin_port = htons ((u_short) port); + done = (*eachresult) (resultsp, &raddr); + } + /* otherwise, we just ignore the errors ... */ + } + else + { +#ifdef notdef + /* some kind of deserialization problem ... */ + if ((u_int32_t) msg.rm_xid == (u_int32_t) xid) + fprintf (stderr, "Broadcast deserialization problem"); + /* otherwise, just random garbage */ +#endif + } + xdrs->x_op = XDR_FREE; + msg.acpted_rply.ar_results.proc = (xdrproc_t)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; +} +libc_hidden_nolink_sunrpc (clnt_broadcast, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/proto.h b/REORG.TODO/sunrpc/proto.h new file mode 100644 index 0000000000..ea28565b1e --- /dev/null +++ b/REORG.TODO/sunrpc/proto.h @@ -0,0 +1,65 @@ +/****** rpc_clntout.c ******/ + +void write_stubs(void); +void printarglist(proc_list *proc, const char *result, + const char *addargname, const char *addargtype); + +/****** rpc_cout.c ******/ + +void emit (definition *def); + +/****** rpc_hout.c ******/ + +void print_datadef(definition *def); +void print_funcdef(definition *def); +void pxdrfuncdecl(const char *name, int pointerp); +void pprocdef(proc_list *proc, version_list *vp, + const char *addargtype, int server_p, int mode); +void pdeclaration(const char *name, declaration *dec, int tab, + const char *separator); +void print_xdr_func_def (char* name, int pointerp, int i); + +/****** rpc_main.c ******/ + /* nil */ + +/****** rpc_parse.c ******/ +definition *get_definition(void); + +/****** rpc_sample.c ******/ +void write_sample_svc(definition *def); +int write_sample_clnt(definition *def); +void add_sample_msg(void); +void write_sample_clnt_main(void); + +/****** rpc_scan.c ******/ + /* see rpc_scan.h */ + +/****** rpc_svcout.c ******/ +int nullproc(const proc_list *proc); +void write_svc_aux(int nomain); +void write_msg_out(void); + +/****** rpc_tblout.c ******/ +void write_tables(void); + +/****** rpc_util.c ******/ +void reinitialize(void); +int streq(const char *a, const char *b); +void error(const char *msg) __attribute__ ((noreturn)); +void crash(void) __attribute__ ((noreturn)); +void tabify(FILE *f, int tab); +char *make_argname(const char *pname, const char *vname); +void add_type(int len, const char *type); + +/* This header is the last one included in all rpc_*.c files, + so we define stuff for cross-rpcgen here to avoid conflicts with + $build's C library and $host's glibc. */ + +#ifdef IS_IN_build + +/* Disable translated messages when built for $build and used in + building glibc. */ +#define _(X) (X) +#define textdomain(X) ((void) 0) + +#endif diff --git a/REORG.TODO/sunrpc/publickey.c b/REORG.TODO/sunrpc/publickey.c new file mode 100644 index 0000000000..ca6e4303d4 --- /dev/null +++ b/REORG.TODO/sunrpc/publickey.c @@ -0,0 +1,122 @@ +/* Get public or secret key from key server. + Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Ulrich Drepper <drepper@cygnus.com>, 1996. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <rpc/netdb.h> +#include <rpc/auth_des.h> +#include <shlib-compat.h> + +#include "nsswitch.h" + + +/* Type of the lookup function for the public key. */ +typedef int (*public_function) (const char *, char *, int *); + +/* Type of the lookup function for the secret key. */ +typedef int (*secret_function) (const char *, char *, const char *, int *); + +/* The lookup function for the first entry of this service. */ +extern int __nss_publickey_lookup (service_user **nip, const char *name, + void **fctp) internal_function; + + +int +getpublickey (const char *name, char *key) +{ + static service_user *startp; + static public_function start_fct; + service_user *nip; + union + { + public_function f; + void *ptr; + } fct; + enum nss_status status = NSS_STATUS_UNAVAIL; + int no_more; + + if (startp == NULL) + { + no_more = __nss_publickey_lookup (&nip, "getpublickey", &fct.ptr); + if (no_more) + startp = (service_user *) -1; + else + { + startp = nip; + start_fct = fct.f; + } + } + else + { + fct.f = start_fct; + no_more = (nip = startp) == (service_user *) -1; + } + + while (! no_more) + { + status = (*fct.f) (name, key, &errno); + + no_more = __nss_next2 (&nip, "getpublickey", NULL, &fct.ptr, status, 0); + } + + return status == NSS_STATUS_SUCCESS; +} +libc_hidden_nolink_sunrpc (getpublickey, GLIBC_2_0) + + +int +getsecretkey (const char *name, char *key, const char *passwd) +{ + static service_user *startp; + static secret_function start_fct; + service_user *nip; + union + { + secret_function f; + void *ptr; + } fct; + enum nss_status status = NSS_STATUS_UNAVAIL; + int no_more; + + if (startp == NULL) + { + no_more = __nss_publickey_lookup (&nip, "getsecretkey", &fct.ptr); + if (no_more) + startp = (service_user *) -1; + else + { + startp = nip; + start_fct = fct.f; + } + } + else + { + fct.f = start_fct; + no_more = (nip = startp) == (service_user *) -1; + } + + while (! no_more) + { + status = (*fct.f) (name, key, passwd, &errno); + + no_more = __nss_next2 (&nip, "getsecretkey", NULL, &fct.ptr, status, 0); + } + + return status == NSS_STATUS_SUCCESS; +} +libc_hidden_nolink_sunrpc (getsecretkey, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/rpc/auth.h b/REORG.TODO/sunrpc/rpc/auth.h new file mode 100644 index 0000000000..b25dcfc116 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/auth.h @@ -0,0 +1,210 @@ +/* + * auth.h, Authentication interface. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The data structures are completely opaque to the client. The client + * is required to pass a AUTH * to routines that create rpc + * "sessions". + */ + +#ifndef _RPC_AUTH_H + +#define _RPC_AUTH_H 1 +#include <features.h> +#include <rpc/xdr.h> + +__BEGIN_DECLS + +#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 { + struct { + u_int32_t high; + u_int32_t low; + } key; + char c[8]; +}; +typedef union des_block des_block; +extern bool_t xdr_des_block (XDR *__xdrs, des_block *__blkp) __THROW; + +/* + * Authentication info. Opaque to client. + */ +struct opaque_auth { + enum_t oa_flavor; /* flavor of auth */ + caddr_t oa_base; /* address of more auth stuff */ + u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ +}; + +/* + * Auth handle, interface to client side authenticators. + */ +typedef struct AUTH AUTH; +struct AUTH { + struct opaque_auth ah_cred; + struct opaque_auth ah_verf; + union des_block ah_key; + struct auth_ops { + void (*ah_nextverf) (AUTH *); + int (*ah_marshal) (AUTH *, XDR *); /* nextverf & serialize */ + int (*ah_validate) (AUTH *, struct opaque_auth *); + /* validate verifier */ + int (*ah_refresh) (AUTH *); /* refresh credentials */ + void (*ah_destroy) (AUTH *); /* destroy this structure */ + } *ah_ops; + caddr_t ah_private; +}; + + +/* + * Authentication ops. + * The ops and the auth handle provide the interface to the authenticators. + * + * AUTH *auth; + * XDR *xdrs; + * struct opaque_auth verf; + */ +#define AUTH_NEXTVERF(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) +#define auth_nextverf(auth) \ + ((*((auth)->ah_ops->ah_nextverf))(auth)) + +#define AUTH_MARSHALL(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) +#define auth_marshall(auth, xdrs) \ + ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) + +#define AUTH_VALIDATE(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) +#define auth_validate(auth, verfp) \ + ((*((auth)->ah_ops->ah_validate))((auth), verfp)) + +#define AUTH_REFRESH(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) +#define auth_refresh(auth) \ + ((*((auth)->ah_ops->ah_refresh))(auth)) + +#define AUTH_DESTROY(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) +#define auth_destroy(auth) \ + ((*((auth)->ah_ops->ah_destroy))(auth)) + + +extern struct opaque_auth _null_auth; + + +/* + * These are the various implementations of client side authenticators. + */ + +/* + * Unix style authentication + * AUTH *authunix_create(machname, uid, gid, len, aup_gids) + * char *machname; + * int uid; + * int gid; + * int len; + * int *aup_gids; + */ +extern AUTH *authunix_create (char *__machname, __uid_t __uid, __gid_t __gid, + int __len, __gid_t *__aup_gids); +extern AUTH *authunix_create_default (void); +extern AUTH *authnone_create (void) __THROW; +extern AUTH *authdes_create (const char *__servername, u_int __window, + struct sockaddr *__syncaddr, des_block *__ckey) + __THROW; +extern AUTH *authdes_pk_create (const char *, netobj *, u_int, + struct sockaddr *, des_block *) __THROW; + + +#define AUTH_NONE 0 /* no authentication */ +#define AUTH_NULL 0 /* backward compatibility */ +#define AUTH_SYS 1 /* unix style (uid, gids) */ +#define AUTH_UNIX AUTH_SYS +#define AUTH_SHORT 2 /* short hand unix style */ +#define AUTH_DES 3 /* des style (encrypted timestamps) */ +#define AUTH_DH AUTH_DES /* Diffie-Hellman (this is DES) */ +#define AUTH_KERB 4 /* kerberos style */ + +/* + * Netname manipulating functions + * + */ +extern int getnetname (char *) __THROW; +extern int host2netname (char *, const char *, const char *) __THROW; +extern int user2netname (char *, const uid_t, const char *) __THROW; +extern int netname2user (const char *, uid_t *, gid_t *, int *, gid_t *) + __THROW; +extern int netname2host (const char *, char *, const int) __THROW; + +/* + * + * These routines interface to the keyserv daemon + * + */ +extern int key_decryptsession (char *, des_block *); +extern int key_decryptsession_pk (char *, netobj *, des_block *); +extern int key_encryptsession (char *, des_block *); +extern int key_encryptsession_pk (char *, netobj *, des_block *); +extern int key_gendes (des_block *); +extern int key_setsecret (char *); +extern int key_secretkey_is_set (void); +extern int key_get_conv (char *, des_block *); + +/* + * XDR an opaque authentication struct. + */ +extern bool_t xdr_opaque_auth (XDR *, struct opaque_auth *) __THROW; + +__END_DECLS + +#endif /* rpc/auth.h */ diff --git a/REORG.TODO/sunrpc/rpc/auth_des.h b/REORG.TODO/sunrpc/rpc/auth_des.h new file mode 100644 index 0000000000..6c22610ca9 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/auth_des.h @@ -0,0 +1,111 @@ +/* Copyright (C) 1996-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _RPC_AUTH_DES_H +#define _RPC_AUTH_DES_H 1 + +#include <sys/cdefs.h> +#include <rpc/auth.h> + +__BEGIN_DECLS + +/* There are two kinds of "names": fullnames and nicknames */ +enum authdes_namekind + { + ADN_FULLNAME, + ADN_NICKNAME + }; + +/* A fullname contains the network name of the client, + a conversation key and the window */ +struct authdes_fullname + { + char *name; /* network name of client, up to MAXNETNAMELEN */ + des_block key; /* conversation key */ + uint32_t window; /* associated window */ + }; + +/* A credential */ +struct authdes_cred + { + enum authdes_namekind adc_namekind; + struct authdes_fullname adc_fullname; + uint32_t adc_nickname; + }; + +/* A timeval replacement for !32bit platforms */ +struct rpc_timeval + { + uint32_t tv_sec; /* Seconds. */ + uint32_t tv_usec; /* Microseconds. */ + }; + +/* A des authentication verifier */ +struct authdes_verf + { + union + { + struct rpc_timeval adv_ctime; /* clear time */ + des_block adv_xtime; /* crypt time */ + } + adv_time_u; + uint32_t adv_int_u; + }; + +/* des authentication verifier: client variety + + adv_timestamp is the current time. + adv_winverf is the credential window + 1. + Both are encrypted using the conversation key. */ +#define adv_timestamp adv_time_u.adv_ctime +#define adv_xtimestamp adv_time_u.adv_xtime +#define adv_winverf adv_int_u + +/* des authentication verifier: server variety + + adv_timeverf is the client's timestamp + client's window + adv_nickname is the server's nickname for the client. + adv_timeverf is encrypted using the conversation key. */ +#define adv_timeverf adv_time_u.adv_ctime +#define adv_xtimeverf adv_time_u.adv_xtime +#define adv_nickname adv_int_u + +/* Map a des credential into a unix cred. */ +extern int authdes_getucred (const struct authdes_cred * __adc, + uid_t * __uid, gid_t * __gid, + short *__grouplen, gid_t * __groups) __THROW; + +/* Get the public key for NAME and place it in KEY. NAME can only be + up to MAXNETNAMELEN bytes long and the destination buffer KEY should + have HEXKEYBYTES + 1 bytes long to fit all characters from the key. */ +extern int getpublickey (const char *__name, char *__key) __THROW; + +/* Get the secret key for NAME and place it in KEY. PASSWD is used to + decrypt the encrypted key stored in the database. NAME can only be + up to MAXNETNAMELEN bytes long and the destination buffer KEY + should have HEXKEYBYTES + 1 bytes long to fit all characters from + the key. */ +extern int getsecretkey (const char *__name, char *__key, + const char *__passwd) __THROW; + +extern int rtime (struct sockaddr_in *__addrp, struct rpc_timeval *__timep, + struct rpc_timeval *__timeout) __THROW; + +__END_DECLS + + +#endif /* rpc/auth_des.h */ diff --git a/REORG.TODO/sunrpc/rpc/auth_unix.h b/REORG.TODO/sunrpc/rpc/auth_unix.h new file mode 100644 index 0000000000..2f4ee1d61b --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/auth_unix.h @@ -0,0 +1,86 @@ +/* + * auth_unix.h, Protocol for UNIX style authentication parameters for RPC + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * The system is very weak. The client uses no encryption for it + * credentials and only sends null verifiers. The server sends backs + * null verifiers or optionally a verifier that suggests a new short hand + * for the credentials. + */ + +#ifndef _RPC_AUTH_UNIX_H +#define _RPC_AUTH_UNIX_H 1 + +#include <features.h> +#include <sys/types.h> +#include <rpc/types.h> +#include <rpc/auth.h> +#include <rpc/xdr.h> + +__BEGIN_DECLS + +/* The machine name is part of a credential; it may not exceed 255 bytes */ +#define MAX_MACHINE_NAME 255 + +/* gids compose part of a credential; there may not be more than 16 of them */ +#define NGRPS 16 + +/* + * Unix style credentials. + */ +struct authunix_parms + { + u_long aup_time; + char *aup_machname; + __uid_t aup_uid; + __gid_t aup_gid; + u_int aup_len; + __gid_t *aup_gids; + }; + +extern bool_t xdr_authunix_parms (XDR *__xdrs, struct authunix_parms *__p) + __THROW; + +/* + * 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; + }; + +__END_DECLS + +#endif /* rpc/auth_unix.h */ diff --git a/REORG.TODO/sunrpc/rpc/clnt.h b/REORG.TODO/sunrpc/rpc/clnt.h new file mode 100644 index 0000000000..f4d4a941c7 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/clnt.h @@ -0,0 +1,418 @@ +/* + * clnt.h - Client side remote procedure call interface. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_CLNT_H +#define _RPC_CLNT_H 1 + +#include <features.h> +#include <sys/types.h> +#include <rpc/types.h> +#include <rpc/auth.h> +#include <sys/un.h> + +__BEGIN_DECLS + +/* + * 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" */ + RPC_NOBROADCAST = 21, /* Broadcasting not supported */ + /* + * callrpc & clnt_create errors + */ + RPC_UNKNOWNHOST=13, /* unknown host name */ + RPC_UNKNOWNPROTO=17, /* unknown protocol */ + RPC_UNKNOWNADDR = 19, /* Remote address unknown */ + + /* + * rpcbind errors + */ + RPC_RPCBFAILURE=14, /* portmapper failed in its call */ +#define RPC_PMAPFAILURE RPC_RPCBFAILURE + RPC_PROGNOTREGISTERED=15, /* remote program is not registered */ + RPC_N2AXLATEFAILURE = 22, /* Name to addr translation failed */ + /* + * unspecified error + */ + RPC_FAILED=16, + RPC_INTR=18, + RPC_TLIERROR=20, + RPC_UDERROR=23, + /* + * asynchronous errors + */ + RPC_INPROGRESS = 24, + RPC_STALERACHANDLE = 25 +}; + + +/* + * Error info. + */ +struct rpc_err { + enum clnt_stat re_status; + union { + int RE_errno; /* related system error */ + enum auth_stat RE_why; /* why the auth error occurred */ + struct { + u_long low; /* lowest verion supported */ + u_long high; /* highest verion supported */ + } RE_vers; + struct { /* maybe meaningful if RPC_FAILED */ + long s1; + long s2; + } RE_lb; /* life boot & debugging only */ + } ru; +#define re_errno ru.RE_errno +#define re_why ru.RE_why +#define re_vers ru.RE_vers +#define re_lb ru.RE_lb +}; + + +/* + * Client rpc handle. + * Created by individual implementations, see e.g. rpc_udp.c. + * Client is responsible for initializing auth, see e.g. auth_none.c. + */ +typedef struct CLIENT CLIENT; +struct CLIENT { + AUTH *cl_auth; /* authenticator */ + struct clnt_ops { + enum clnt_stat (*cl_call) (CLIENT *, u_long, xdrproc_t, caddr_t, xdrproc_t, + caddr_t, struct timeval); + /* call remote procedure */ + void (*cl_abort) (void); /* abort a call */ + void (*cl_geterr) (CLIENT *, struct rpc_err *); + /* get specific error code */ + bool_t (*cl_freeres) (CLIENT *, xdrproc_t, caddr_t); + /* frees results */ + void (*cl_destroy) (CLIENT *); /* destroy this structure */ + bool_t (*cl_control) (CLIENT *, int, char *); + /* the ioctl() of rpc */ + } *cl_ops; + caddr_t cl_private; /* private stuff */ +}; + + +/* + * client side rpc interface ops + * + * Parameter types are: + * + */ + +/* + * enum clnt_stat + * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) + * CLIENT *rh; + * u_long proc; + * xdrproc_t xargs; + * caddr_t argsp; + * xdrproc_t xres; + * caddr_t resp; + * struct timeval timeout; + */ +#define CLNT_CALL(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) +#define clnt_call(rh, proc, xargs, argsp, xres, resp, secs) \ + ((*(rh)->cl_ops->cl_call)(rh, proc, xargs, argsp, xres, resp, secs)) + +/* + * void + * CLNT_ABORT(rh); + * CLIENT *rh; + */ +#define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) +#define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) + +/* + * struct rpc_err + * CLNT_GETERR(rh); + * CLIENT *rh; + */ +#define CLNT_GETERR(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) +#define clnt_geterr(rh,errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) + + +/* + * bool_t + * CLNT_FREERES(rh, xres, resp); + * CLIENT *rh; + * xdrproc_t xres; + * caddr_t resp; + */ +#define CLNT_FREERES(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) +#define clnt_freeres(rh,xres,resp) ((*(rh)->cl_ops->cl_freeres)(rh,xres,resp)) + +/* + * bool_t + * CLNT_CONTROL(cl, request, info) + * CLIENT *cl; + * u_int request; + * char *info; + */ +#define CLNT_CONTROL(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) +#define clnt_control(cl,rq,in) ((*(cl)->cl_ops->cl_control)(cl,rq,in)) + +/* + * control operations that apply to all transports + * + * Note: options marked XXX are no-ops in this implementation of RPC. + * The are present in TI-RPC but can't be implemented here since they + * depend on the presence of STREAMS/TLI, which we don't have. + */ +#define CLSET_TIMEOUT 1 /* set timeout (timeval) */ +#define CLGET_TIMEOUT 2 /* get timeout (timeval) */ +#define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ +#define CLGET_FD 6 /* get connections file descriptor */ +#define CLGET_SVC_ADDR 7 /* get server's address (netbuf) XXX */ +#define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */ +#define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy*/ +#define CLGET_XID 10 /* Get xid */ +#define CLSET_XID 11 /* Set xid */ +#define CLGET_VERS 12 /* Get version number */ +#define CLSET_VERS 13 /* Set version number */ +#define CLGET_PROG 14 /* Get program number */ +#define CLSET_PROG 15 /* Set program number */ +#define CLSET_SVC_ADDR 16 /* get server's address (netbuf) XXX */ +#define CLSET_PUSH_TIMOD 17 /* push timod if not already present XXX */ +#define CLSET_POP_TIMOD 18 /* pop timod XXX */ +/* + * Connectionless only control operations + */ +#define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ +#define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ + +/* + * void + * CLNT_DESTROY(rh); + * CLIENT *rh; + */ +#define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) +#define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) + + +/* + * RPCTEST is a test program which is accessible on every rpc + * transport/port. It is used for testing, performance evaluation, + * and network administration. + */ + +#define RPCTEST_PROGRAM ((u_long)1) +#define RPCTEST_VERSION ((u_long)1) +#define RPCTEST_NULL_PROC ((u_long)2) +#define RPCTEST_NULL_BATCH_PROC ((u_long)3) + +/* + * By convention, procedure 0 takes null arguments and returns them + */ + +#define NULLPROC ((u_long)0) + +/* + * Below are the client handle creation routines for the various + * implementations of client side rpc. They can return NULL if a + * creation failure occurs. + */ + +/* + * Memory based rpc (for speed check and testing) + * CLIENT * + * clntraw_create(prog, vers) + * u_long prog; + * u_long vers; + */ +extern CLIENT *clntraw_create (const u_long __prog, const u_long __vers) + __THROW; + + +/* + * Generic client creation routine. Supported protocols are "udp", "tcp" and + * "unix" + * CLIENT * + * clnt_create(host, prog, vers, prot) + * char *host; -- hostname + * u_long prog; -- program number + * u_ong vers; -- version number + * char *prot; -- protocol + */ +extern CLIENT *clnt_create (const char *__host, const u_long __prog, + const u_long __vers, const char *__prot) + __THROW; + + +/* + * TCP based rpc + * CLIENT * + * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clnttcp_create (struct sockaddr_in *__raddr, u_long __prog, + u_long __version, int *__sockp, u_int __sendsz, + u_int __recvsz) __THROW; + +/* + * UDP based rpc. + * CLIENT * + * clntudp_create(raddr, program, version, wait, sockp) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait_resend; + * int *sockp; + * + * Same as above, but you specify max packet sizes. + * CLIENT * + * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) + * struct sockaddr_in *raddr; + * u_long program; + * u_long version; + * struct timeval wait_resend; + * int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntudp_create (struct sockaddr_in *__raddr, u_long __program, + u_long __version, struct timeval __wait_resend, + int *__sockp) __THROW; +extern CLIENT *clntudp_bufcreate (struct sockaddr_in *__raddr, + u_long __program, u_long __version, + struct timeval __wait_resend, int *__sockp, + u_int __sendsz, u_int __recvsz) __THROW; + + + + +/* + * AF_UNIX based rpc + * CLIENT * + * clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz) + * struct sockaddr_un *raddr; + * u_long prog; + * u_long version; + * register int *sockp; + * u_int sendsz; + * u_int recvsz; + */ +extern CLIENT *clntunix_create (struct sockaddr_un *__raddr, u_long __program, + u_long __version, int *__sockp, + u_int __sendsz, u_int __recvsz) __THROW; + + +extern int callrpc (const char *__host, const u_long __prognum, + const u_long __versnum, const u_long __procnum, + const xdrproc_t __inproc, const char *__in, + const xdrproc_t __outproc, char *__out) __THROW; +extern int _rpc_dtablesize (void) __THROW; + +/* + * Print why creation failed + */ +extern void clnt_pcreateerror (const char *__msg); /* stderr */ +extern char *clnt_spcreateerror(const char *__msg) __THROW; /* string */ + +/* + * Like clnt_perror(), but is more verbose in its output + */ +extern void clnt_perrno (enum clnt_stat __num); /* stderr */ + +/* + * Print an English error message, given the client error code + */ +extern void clnt_perror (CLIENT *__clnt, const char *__msg); + /* stderr */ +extern char *clnt_sperror (CLIENT *__clnt, const char *__msg) __THROW; + /* 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. + */ +extern char *clnt_sperrno (enum clnt_stat __num) __THROW; /* string */ + +/* + * get the port number on the host for the rpc program,version and proto + */ +extern int getrpcport (const char * __host, u_long __prognum, + u_long __versnum, u_int __proto) __THROW; + +/* + * get the local host's IP address without consulting + * name service library functions + */ +extern void get_myaddress (struct sockaddr_in *) __THROW; + +#define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ +#define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ + +__END_DECLS + +#endif /* rpc/clnt.h */ diff --git a/REORG.TODO/sunrpc/rpc/des_crypt.h b/REORG.TODO/sunrpc/rpc/des_crypt.h new file mode 100644 index 0000000000..77cca3cbed --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/des_crypt.h @@ -0,0 +1,96 @@ +/* + * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC + * + * des_crypt.h, des library routine interface + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef __DES_CRYPT_H__ +#define __DES_CRYPT_H__ 1 + +#include <features.h> + +__BEGIN_DECLS + +#define DES_MAXDATA 8192 /* max bytes encrypted in one call */ +#define DES_DIRMASK (1 << 0) +#define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */ +#define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */ + + +#define DES_DEVMASK (1 << 1) +#define DES_HW (0*DES_DEVMASK) /* Use hardware device */ +#define DES_SW (1*DES_DEVMASK) /* Use software device */ + + +#define DESERR_NONE 0 /* succeeded */ +#define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */ +#define DESERR_HWERROR 2 /* failed, hardware/driver error */ +#define DESERR_BADPARAM 3 /* failed, bad parameter to call */ + +#define DES_FAILED(err) \ + ((err) > DESERR_NOHWDEVICE) + +/* + * cbc_crypt() + * ecb_crypt() + * + * Encrypt (or decrypt) len bytes of a buffer buf. + * The length must be a multiple of eight. + * The key should have odd parity in the low bit of each byte. + * ivec is the input vector, and is updated to the new one (cbc only). + * The mode is created by oring together the appropriate parameters. + * DESERR_NOHWDEVICE is returned if DES_HW was specified but + * there was no hardware to do it on (the data will still be + * encrypted though, in software). + */ + + +/* + * Cipher Block Chaining mode + */ +extern int cbc_crypt (char *__key, char *__buf, unsigned __len, + unsigned __mode, char *__ivec) __THROW; + +/* + * Electronic Code Book mode + */ +extern int ecb_crypt (char *__key, char *__buf, unsigned __len, + unsigned __mode) __THROW; + +/* + * Set des parity for a key. + * DES parity is odd and in the low bit of each byte + */ +extern void des_setparity (char *__key) __THROW; + +__END_DECLS + +#endif diff --git a/REORG.TODO/sunrpc/rpc/key_prot.h b/REORG.TODO/sunrpc/rpc/key_prot.h new file mode 100644 index 0000000000..74627e66cc --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/key_prot.h @@ -0,0 +1,343 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _KEY_PROT_H_RPCGEN +#define _KEY_PROT_H_RPCGEN + +#include <rpc/rpc.h> + +/* Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ +#define PROOT 3 +#define HEXMODULUS "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b" +#define HEXKEYBYTES 48 +#define KEYSIZE 192 +#define KEYBYTES 24 +#define KEYCHECKSUMSIZE 16 + +enum keystatus { + KEY_SUCCESS = 0, + KEY_NOSECRET = 1, + KEY_UNKNOWN = 2, + KEY_SYSTEMERR = 3, +}; +typedef enum keystatus keystatus; +#ifdef __cplusplus +extern "C" bool_t xdr_keystatus(XDR *, keystatus*); +#elif __STDC__ +extern bool_t xdr_keystatus(XDR *, keystatus*); +#else /* Old Style C */ +bool_t xdr_keystatus(); +#endif /* Old Style C */ + + +typedef char keybuf[HEXKEYBYTES]; +#ifdef __cplusplus +extern "C" bool_t xdr_keybuf(XDR *, keybuf); +#elif __STDC__ +extern bool_t xdr_keybuf(XDR *, keybuf); +#else /* Old Style C */ +bool_t xdr_keybuf(); +#endif /* Old Style C */ + + +typedef char *netnamestr; +#ifdef __cplusplus +extern "C" bool_t xdr_netnamestr(XDR *, netnamestr*); +#elif __STDC__ +extern bool_t xdr_netnamestr(XDR *, netnamestr*); +#else /* Old Style C */ +bool_t xdr_netnamestr(); +#endif /* Old Style C */ + + +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; +typedef struct cryptkeyarg cryptkeyarg; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*); +#elif __STDC__ +extern bool_t xdr_cryptkeyarg(XDR *, cryptkeyarg*); +#else /* Old Style C */ +bool_t xdr_cryptkeyarg(); +#endif /* Old Style C */ + + +struct cryptkeyarg2 { + netnamestr remotename; + netobj remotekey; + des_block deskey; +}; +typedef struct cryptkeyarg2 cryptkeyarg2; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*); +#elif __STDC__ +extern bool_t xdr_cryptkeyarg2(XDR *, cryptkeyarg2*); +#else /* Old Style C */ +bool_t xdr_cryptkeyarg2(); +#endif /* Old Style C */ + + +struct cryptkeyres { + keystatus status; + union { + des_block deskey; + } cryptkeyres_u; +}; +typedef struct cryptkeyres cryptkeyres; +#ifdef __cplusplus +extern "C" bool_t xdr_cryptkeyres(XDR *, cryptkeyres*); +#elif __STDC__ +extern bool_t xdr_cryptkeyres(XDR *, cryptkeyres*); +#else /* Old Style C */ +bool_t xdr_cryptkeyres(); +#endif /* Old Style C */ + +#define MAXGIDS 16 + +struct unixcred { + u_int uid; + u_int gid; + struct { + u_int gids_len; + u_int *gids_val; + } gids; +}; +typedef struct unixcred unixcred; +#ifdef __cplusplus +extern "C" bool_t xdr_unixcred(XDR *, unixcred*); +#elif __STDC__ +extern bool_t xdr_unixcred(XDR *, unixcred*); +#else /* Old Style C */ +bool_t xdr_unixcred(); +#endif /* Old Style C */ + + +struct getcredres { + keystatus status; + union { + unixcred cred; + } getcredres_u; +}; +typedef struct getcredres getcredres; +#ifdef __cplusplus +extern "C" bool_t xdr_getcredres(XDR *, getcredres*); +#elif __STDC__ +extern bool_t xdr_getcredres(XDR *, getcredres*); +#else /* Old Style C */ +bool_t xdr_getcredres(); +#endif /* Old Style C */ + + +struct key_netstarg { + keybuf st_priv_key; + keybuf st_pub_key; + netnamestr st_netname; +}; +typedef struct key_netstarg key_netstarg; +#ifdef __cplusplus +extern "C" bool_t xdr_key_netstarg(XDR *, key_netstarg*); +#elif __STDC__ +extern bool_t xdr_key_netstarg(XDR *, key_netstarg*); +#else /* Old Style C */ +bool_t xdr_key_netstarg(); +#endif /* Old Style C */ + + +struct key_netstres { + keystatus status; + union { + key_netstarg knet; + } key_netstres_u; +}; +typedef struct key_netstres key_netstres; +#ifdef __cplusplus +extern "C" bool_t xdr_key_netstres(XDR *, key_netstres*); +#elif __STDC__ +extern bool_t xdr_key_netstres(XDR *, key_netstres*); +#else /* Old Style C */ +bool_t xdr_key_netstres(); +#endif /* Old Style C */ + + +#ifndef opaque +#define opaque char +#endif + + +#define KEY_PROG ((u_long)100029) +#define KEY_VERS ((u_long)1) + +#ifdef __cplusplus +#define KEY_SET ((u_long)1) +extern "C" keystatus * key_set_1(opaque *, CLIENT *); +extern "C" keystatus * key_set_1_svc(opaque *, struct svc_req *); +#define KEY_ENCRYPT ((u_long)2) +extern "C" cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_DECRYPT ((u_long)3) +extern "C" cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_GEN ((u_long)4) +extern "C" des_block * key_gen_1(void *, CLIENT *); +extern "C" des_block * key_gen_1_svc(void *, struct svc_req *); +#define KEY_GETCRED ((u_long)5) +extern "C" getcredres * key_getcred_1(netnamestr *, CLIENT *); +extern "C" getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *); + +#elif __STDC__ +#define KEY_SET ((u_long)1) +extern keystatus * key_set_1(opaque *, CLIENT *); +extern keystatus * key_set_1_svc(opaque *, struct svc_req *); +#define KEY_ENCRYPT ((u_long)2) +extern cryptkeyres * key_encrypt_1(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_encrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_DECRYPT ((u_long)3) +extern cryptkeyres * key_decrypt_1(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_decrypt_1_svc(cryptkeyarg *, struct svc_req *); +#define KEY_GEN ((u_long)4) +extern des_block * key_gen_1(void *, CLIENT *); +extern des_block * key_gen_1_svc(void *, struct svc_req *); +#define KEY_GETCRED ((u_long)5) +extern getcredres * key_getcred_1(netnamestr *, CLIENT *); +extern getcredres * key_getcred_1_svc(netnamestr *, struct svc_req *); + +#else /* Old Style C */ +#define KEY_SET ((u_long)1) +extern keystatus * key_set_1(); +extern keystatus * key_set_1_svc(); +#define KEY_ENCRYPT ((u_long)2) +extern cryptkeyres * key_encrypt_1(); +extern cryptkeyres * key_encrypt_1_svc(); +#define KEY_DECRYPT ((u_long)3) +extern cryptkeyres * key_decrypt_1(); +extern cryptkeyres * key_decrypt_1_svc(); +#define KEY_GEN ((u_long)4) +extern des_block * key_gen_1(); +extern des_block * key_gen_1_svc(); +#define KEY_GETCRED ((u_long)5) +extern getcredres * key_getcred_1(); +extern getcredres * key_getcred_1_svc(); +#endif /* Old Style C */ +#define KEY_VERS2 ((u_long)2) + +#ifdef __cplusplus +extern "C" keystatus * key_set_2(opaque *, CLIENT *); +extern "C" keystatus * key_set_2_svc(opaque *, struct svc_req *); +extern "C" cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern "C" cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern "C" des_block * key_gen_2(void *, CLIENT *); +extern "C" des_block * key_gen_2_svc(void *, struct svc_req *); +extern "C" getcredres * key_getcred_2(netnamestr *, CLIENT *); +extern "C" getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *); +#define KEY_ENCRYPT_PK ((u_long)6) +extern "C" cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern "C" cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_DECRYPT_PK ((u_long)7) +extern "C" cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern "C" cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_NET_PUT ((u_long)8) +extern "C" keystatus * key_net_put_2(key_netstarg *, CLIENT *); +extern "C" keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *); +#define KEY_NET_GET ((u_long)9) +extern "C" key_netstres * key_net_get_2(void *, CLIENT *); +extern "C" key_netstres * key_net_get_2_svc(void *, struct svc_req *); +#define KEY_GET_CONV ((u_long)10) +extern "C" cryptkeyres * key_get_conv_2(opaque *, CLIENT *); +extern "C" cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *); + +#elif __STDC__ +extern keystatus * key_set_2(opaque *, CLIENT *); +extern keystatus * key_set_2_svc(opaque *, struct svc_req *); +extern cryptkeyres * key_encrypt_2(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_encrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern cryptkeyres * key_decrypt_2(cryptkeyarg *, CLIENT *); +extern cryptkeyres * key_decrypt_2_svc(cryptkeyarg *, struct svc_req *); +extern des_block * key_gen_2(void *, CLIENT *); +extern des_block * key_gen_2_svc(void *, struct svc_req *); +extern getcredres * key_getcred_2(netnamestr *, CLIENT *); +extern getcredres * key_getcred_2_svc(netnamestr *, struct svc_req *); +#define KEY_ENCRYPT_PK ((u_long)6) +extern cryptkeyres * key_encrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern cryptkeyres * key_encrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_DECRYPT_PK ((u_long)7) +extern cryptkeyres * key_decrypt_pk_2(cryptkeyarg2 *, CLIENT *); +extern cryptkeyres * key_decrypt_pk_2_svc(cryptkeyarg2 *, struct svc_req *); +#define KEY_NET_PUT ((u_long)8) +extern keystatus * key_net_put_2(key_netstarg *, CLIENT *); +extern keystatus * key_net_put_2_svc(key_netstarg *, struct svc_req *); +#define KEY_NET_GET ((u_long)9) +extern key_netstres * key_net_get_2(void *, CLIENT *); +extern key_netstres * key_net_get_2_svc(void *, struct svc_req *); +#define KEY_GET_CONV ((u_long)10) +extern cryptkeyres * key_get_conv_2(opaque *, CLIENT *); +extern cryptkeyres * key_get_conv_2_svc(opaque *, struct svc_req *); + +#else /* Old Style C */ +extern keystatus * key_set_2(); +extern keystatus * key_set_2_svc(); +extern cryptkeyres * key_encrypt_2(); +extern cryptkeyres * key_encrypt_2_svc(); +extern cryptkeyres * key_decrypt_2(); +extern cryptkeyres * key_decrypt_2_svc(); +extern des_block * key_gen_2(); +extern des_block * key_gen_2_svc(); +extern getcredres * key_getcred_2(); +extern getcredres * key_getcred_2_svc(); +#define KEY_ENCRYPT_PK ((u_long)6) +extern cryptkeyres * key_encrypt_pk_2(); +extern cryptkeyres * key_encrypt_pk_2_svc(); +#define KEY_DECRYPT_PK ((u_long)7) +extern cryptkeyres * key_decrypt_pk_2(); +extern cryptkeyres * key_decrypt_pk_2_svc(); +#define KEY_NET_PUT ((u_long)8) +extern keystatus * key_net_put_2(); +extern keystatus * key_net_put_2_svc(); +#define KEY_NET_GET ((u_long)9) +extern key_netstres * key_net_get_2(); +extern key_netstres * key_net_get_2_svc(); +#define KEY_GET_CONV ((u_long)10) +extern cryptkeyres * key_get_conv_2(); +extern cryptkeyres * key_get_conv_2_svc(); +#endif /* Old Style C */ + +#endif /* !_KEY_PROT_H_RPCGEN */ diff --git a/REORG.TODO/sunrpc/rpc/netdb.h b/REORG.TODO/sunrpc/rpc/netdb.h new file mode 100644 index 0000000000..529a4ada21 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/netdb.h @@ -0,0 +1,74 @@ +/* @(#)netdb.h 2.1 88/07/29 3.9 RPCSRC */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* Cleaned up for GNU C library roland@gnu.ai.mit.edu: + added multiple inclusion protection and use of <sys/cdefs.h>. + In GNU this file is #include'd by <netdb.h>. */ + +#ifndef _RPC_NETDB_H +#define _RPC_NETDB_H 1 + +#include <features.h> + +#define __need_size_t +#include <stddef.h> + +__BEGIN_DECLS + +struct rpcent +{ + char *r_name; /* Name of server for this rpc program. */ + char **r_aliases; /* Alias list. */ + int r_number; /* RPC program number. */ +}; + +extern void setrpcent (int __stayopen) __THROW; +extern void endrpcent (void) __THROW; +extern struct rpcent *getrpcbyname (const char *__name) __THROW; +extern struct rpcent *getrpcbynumber (int __number) __THROW; +extern struct rpcent *getrpcent (void) __THROW; + +#ifdef __USE_MISC +extern int getrpcbyname_r (const char *__name, struct rpcent *__result_buf, + char *__buffer, size_t __buflen, + struct rpcent **__result) __THROW; + +extern int getrpcbynumber_r (int __number, struct rpcent *__result_buf, + char *__buffer, size_t __buflen, + struct rpcent **__result) __THROW; + +extern int getrpcent_r (struct rpcent *__result_buf, char *__buffer, + size_t __buflen, struct rpcent **__result) __THROW; +#endif + +__END_DECLS + +#endif /* rpc/netdb.h */ diff --git a/REORG.TODO/sunrpc/rpc/pmap_clnt.h b/REORG.TODO/sunrpc/rpc/pmap_clnt.h new file mode 100644 index 0000000000..1cc94b8fee --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/pmap_clnt.h @@ -0,0 +1,95 @@ +/* + * pmap_clnt.h + * Supplies C routines to get to portmap services. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_PMAP_CLNT_H +#define _RPC_PMAP_CLNT_H 1 + +#include <features.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/clnt.h> + +__BEGIN_DECLS + +typedef bool_t (*resultproc_t) (caddr_t __resp, struct sockaddr_in *__raddr); + +/* + * 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 (const u_long __program, const u_long __vers, + int __protocol, u_short __port) __THROW; +extern bool_t pmap_unset (const u_long __program, const u_long __vers) + __THROW; +extern struct pmaplist *pmap_getmaps (struct sockaddr_in *__address) __THROW; +extern enum clnt_stat pmap_rmtcall (struct sockaddr_in *__addr, + const u_long __prog, + const u_long __vers, + const u_long __proc, + xdrproc_t __xdrargs, + caddr_t __argsp, xdrproc_t __xdrres, + caddr_t __resp, struct timeval __tout, + u_long *__port_ptr) __THROW; +extern enum clnt_stat clnt_broadcast (const u_long __prog, + const u_long __vers, + const u_long __proc, xdrproc_t __xargs, + caddr_t __argsp, xdrproc_t __xresults, + caddr_t __resultsp, + resultproc_t __eachresult) __THROW; +extern u_short pmap_getport (struct sockaddr_in *__address, + const u_long __program, + const u_long __version, u_int __protocol) + __THROW; + +__END_DECLS + +#endif /* rpc/pmap_clnt.h */ diff --git a/REORG.TODO/sunrpc/rpc/pmap_prot.h b/REORG.TODO/sunrpc/rpc/pmap_prot.h new file mode 100644 index 0000000000..e5fd7cb0a6 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/pmap_prot.h @@ -0,0 +1,105 @@ +/* + * pmap_prot.h + * Protocol for the local binder service, or pmap. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_PMAP_PROT_H +#define _RPC_PMAP_PROT_H 1 + +#include <features.h> + +#include <rpc/xdr.h> + +__BEGIN_DECLS + +/* The following procedures are supported by the protocol: + * + * PMAPPROC_NULL() returns () + * takes nothing, returns nothing + * + * PMAPPROC_SET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Registers the tuple + * [prog, vers, prot, port]. + * + * PMAPPROC_UNSET(struct pmap) returns (bool_t) + * TRUE is success, FALSE is failure. Un-registers pair + * [prog, vers]. prot and port are ignored. + * + * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). + * 0 is failure. Otherwise returns the port number where the pair + * [prog, vers] is registered. It may lie! + * + * PMAPPROC_DUMP() RETURNS (struct pmaplist *) + * + * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) + * RETURNS (port, string<>); + * usage: encapsulatedresults = PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); + * Calls the procedure on the local machine. If it is not registered, + * this procedure is quite; ie it does not return error information!!! + * This procedure only is supported on rpc/udp and calls via + * rpc/udp. This routine only passes null authentication parameters. + * This file has no interface to xdr routines for PMAPPROC_CALLIT. + * + * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. + */ + +#define PMAPPORT ((u_short)111) +#define PMAPPROG ((u_long)100000) +#define PMAPVERS ((u_long)2) +#define PMAPVERS_PROTO ((u_long)2) +#define PMAPVERS_ORIG ((u_long)1) +#define PMAPPROC_NULL ((u_long)0) +#define PMAPPROC_SET ((u_long)1) +#define PMAPPROC_UNSET ((u_long)2) +#define PMAPPROC_GETPORT ((u_long)3) +#define PMAPPROC_DUMP ((u_long)4) +#define PMAPPROC_CALLIT ((u_long)5) + +struct pmap { + long unsigned pm_prog; + long unsigned pm_vers; + long unsigned pm_prot; + long unsigned pm_port; +}; + +extern bool_t xdr_pmap (XDR *__xdrs, struct pmap *__regs) __THROW; + +struct pmaplist { + struct pmap pml_map; + struct pmaplist *pml_next; +}; + +extern bool_t xdr_pmaplist (XDR *__xdrs, struct pmaplist **__rp) __THROW; + +__END_DECLS + +#endif /* rpc/pmap_prot.h */ diff --git a/REORG.TODO/sunrpc/rpc/pmap_rmt.h b/REORG.TODO/sunrpc/rpc/pmap_rmt.h new file mode 100644 index 0000000000..f8680141ae --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/pmap_rmt.h @@ -0,0 +1,65 @@ +/* + * Structures and XDR routines for parameters to and replies from + * the portmapper remote-call-service. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_PMAP_RMT_H +#define _RPC_PMAP_RMT_H 1 + +#include <features.h> +#include <sys/types.h> +#include <rpc/types.h> +#include <rpc/xdr.h> + +__BEGIN_DECLS + +struct rmtcallargs { + u_long prog, vers, proc, arglen; + caddr_t args_ptr; + xdrproc_t xdr_args; +}; + +extern bool_t xdr_rmtcall_args (XDR *__xdrs, struct rmtcallargs *__crp) + __THROW; + +struct rmtcallres { + u_long *port_ptr; + u_long resultslen; + caddr_t results_ptr; + xdrproc_t xdr_results; +}; + +extern bool_t xdr_rmtcallres (XDR *__xdrs, struct rmtcallres *__crp) __THROW; + +__END_DECLS + +#endif /* rpc/pmap_rmt.h */ diff --git a/REORG.TODO/sunrpc/rpc/rpc.h b/REORG.TODO/sunrpc/rpc/rpc.h new file mode 100644 index 0000000000..173a4e31ea --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/rpc.h @@ -0,0 +1,94 @@ +/* + * rpc.h, Just includes the billions of rpc header files necessary to + * do remote procedure calling. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_RPC_H +#define _RPC_RPC_H 1 + +#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 */ +#include <rpc/auth_des.h> /* protocol for des style cred */ + +/* Server side only remote procedure callee */ +#include <rpc/svc.h> /* service manager and multiplexer */ +#include <rpc/svc_auth.h> /* service side authenticator */ + +/* + * COMMENT OUT THE NEXT INCLUDE 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 <rpc/netdb.h> /* structures and routines to parse /etc/rpc */ + +__BEGIN_DECLS + +/* Global variables, protected for multi-threaded applications. */ +extern fd_set *__rpc_thread_svc_fdset (void) __attribute__ ((__const__)); +#define svc_fdset (*__rpc_thread_svc_fdset ()) + +extern struct rpc_createerr *__rpc_thread_createerr (void) + __attribute__ ((__const__)); +#define get_rpc_createerr() (*__rpc_thread_createerr ()) +/* The people who "engineered" RPC should bee punished for naming the + data structure and the variable the same. We cannot always define the + macro 'rpc_createerr' because this would prevent people from defining + object of type 'struct rpc_createerr'. So we leave it up to the user + to select transparent replacement also of this variable. */ +#ifdef _RPC_MT_VARS +# define rpc_createerr (*__rpc_thread_createerr ()) +#endif + +extern struct pollfd **__rpc_thread_svc_pollfd (void) + __attribute__ ((__const__)); +#define svc_pollfd (*__rpc_thread_svc_pollfd ()) + +extern int *__rpc_thread_svc_max_pollfd (void) __attribute__ ((__const__)); +#define svc_max_pollfd (*__rpc_thread_svc_max_pollfd ()) + +__END_DECLS + +#endif /* rpc/rpc.h */ diff --git a/REORG.TODO/sunrpc/rpc/rpc_des.h b/REORG.TODO/sunrpc/rpc/rpc_des.h new file mode 100644 index 0000000000..2091f52414 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/rpc_des.h @@ -0,0 +1,71 @@ +/* + * Generic DES driver interface + * Keep this file hardware independent! + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _DES_H +#define _DES_H + +#include <sys/types.h> + +#define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ +#define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ + +enum desdir + { + ENCRYPT, DECRYPT + }; +enum desmode + { + CBC, ECB + }; + +/* + * parameters to ioctl call + */ +struct desparams + { + unsigned char des_key[8]; /* key (with low bit parity) */ + enum desdir des_dir; /* direction */ + enum desmode des_mode; /* mode */ + unsigned char des_ivec[8]; /* input vector */ + unsigned des_len; /* number of bytes to crypt */ + union + { + unsigned char UDES_data[DES_QUICKLEN]; + unsigned char *UDES_buf; + } + UDES; +#define des_data UDES.UDES_data /* direct data here if quick */ +#define des_buf UDES.UDES_buf /* otherwise, pointer to data */ + }; + +#endif diff --git a/REORG.TODO/sunrpc/rpc/rpc_msg.h b/REORG.TODO/sunrpc/rpc/rpc_msg.h new file mode 100644 index 0000000000..273b187d14 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/rpc_msg.h @@ -0,0 +1,198 @@ +/* + * rpc_msg.h + * rpc message definition + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_MSG_H +#define _RPC_MSG_H 1 + +#include <sys/cdefs.h> + +#include <rpc/xdr.h> +#include <rpc/clnt.h> + +#define RPC_MSG_VERSION ((u_long) 2) +#define RPC_SERVICE_PORT ((u_short) 2048) + +__BEGIN_DECLS + +/* + * Bottom up definition of an rpc message. + * NOTE: call and reply use the same overall struct but + * different parts of unions within it. + */ + +enum msg_type { + CALL=0, + REPLY=1 +}; + +enum reply_stat { + MSG_ACCEPTED=0, + MSG_DENIED=1 +}; + +enum accept_stat { + SUCCESS=0, + PROG_UNAVAIL=1, + PROG_MISMATCH=2, + PROC_UNAVAIL=3, + GARBAGE_ARGS=4, + SYSTEM_ERR=5 +}; + +enum reject_stat { + RPC_MISMATCH=0, + AUTH_ERROR=1 +}; + +/* + * Reply part of an rpc exchange + */ + +/* + * Reply to an rpc request that was accepted by the server. + * Note: there could be an error even though the request was + * accepted. + */ +struct accepted_reply { + struct opaque_auth ar_verf; + enum accept_stat ar_stat; + union { + struct { + u_long low; + u_long high; + } AR_versions; + struct { + caddr_t where; + xdrproc_t proc; + } AR_results; + /* and many other null cases */ + } ru; +#define ar_results ru.AR_results +#define ar_vers ru.AR_versions +}; + +/* + * Reply to an rpc request that was rejected by the server. + */ +struct rejected_reply { + enum reject_stat rj_stat; + union { + struct { + u_long low; + u_long high; + } RJ_versions; + enum auth_stat RJ_why; /* why authentication did not work */ + } ru; +#define rj_vers ru.RJ_versions +#define rj_why ru.RJ_why +}; + +/* + * Body of a reply to an rpc request. + */ +struct reply_body { + enum reply_stat rp_stat; + union { + struct accepted_reply RP_ar; + struct rejected_reply RP_dr; + } ru; +#define rp_acpt ru.RP_ar +#define rp_rjct ru.RP_dr +}; + +/* + * Body of an rpc request call. + */ +struct call_body { + u_long cb_rpcvers; /* must be equal to two */ + u_long cb_prog; + u_long cb_vers; + u_long cb_proc; + struct opaque_auth cb_cred; + struct opaque_auth cb_verf; /* protocol specific - provided by client */ +}; + +/* + * The rpc message + */ +struct rpc_msg { + u_long rm_xid; + enum msg_type rm_direction; + union { + struct call_body RM_cmb; + struct reply_body RM_rmb; + } ru; +#define rm_call ru.RM_cmb +#define rm_reply ru.RM_rmb +}; +#define acpted_rply ru.RM_rmb.ru.RP_ar +#define rjcted_rply ru.RM_rmb.ru.RP_dr + + +/* + * XDR routine to handle a rpc message. + * xdr_callmsg(xdrs, cmsg) + * XDR *xdrs; + * struct rpc_msg *cmsg; + */ +extern bool_t xdr_callmsg (XDR *__xdrs, struct rpc_msg *__cmsg) __THROW; + +/* + * 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 *__xdrs, struct rpc_msg *__cmsg) __THROW; + +/* + * XDR routine to handle a rpc reply. + * xdr_replymsg(xdrs, rmsg) + * XDR *xdrs; + * struct rpc_msg *rmsg; + */ +extern bool_t xdr_replymsg (XDR *__xdrs, struct rpc_msg *__rmsg) __THROW; + +/* + * 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 (struct rpc_msg *__msg, struct rpc_err *__error) + __THROW; + +__END_DECLS + +#endif /* rpc/rpc_msg.h */ diff --git a/REORG.TODO/sunrpc/rpc/svc.h b/REORG.TODO/sunrpc/rpc/svc.h new file mode 100644 index 0000000000..9294afb311 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/svc.h @@ -0,0 +1,336 @@ +/* + * svc.h, Server-side remote procedure call interface. + * + * Copyright (C) 2012-2017 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_SVC_H +#define _RPC_SVC_H 1 + +#include <features.h> +#include <rpc/rpc_msg.h> + +__BEGIN_DECLS + +/* + * 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 SVCXPRT SVCXPRT; +struct SVCXPRT { + int xp_sock; + u_short xp_port; /* associated port number */ + const struct xp_ops { + bool_t (*xp_recv) (SVCXPRT *__xprt, struct rpc_msg *__msg); + /* receive incoming requests */ + enum xprt_stat (*xp_stat) (SVCXPRT *__xprt); + /* get transport status */ + bool_t (*xp_getargs) (SVCXPRT *__xprt, xdrproc_t __xdr_args, + caddr_t __args_ptr); /* get arguments */ + bool_t (*xp_reply) (SVCXPRT *__xprt, struct rpc_msg *__msg); + /* send reply */ + bool_t (*xp_freeargs) (SVCXPRT *__xprt, xdrproc_t __xdr_args, + caddr_t __args_ptr); + /* free mem allocated for args */ + void (*xp_destroy) (SVCXPRT *__xprt); + /* destroy this struct */ + } *xp_ops; + int xp_addrlen; /* length of remote address */ + struct sockaddr_in xp_raddr; /* remote address */ + struct opaque_auth xp_verf; /* raw response verifier */ + caddr_t xp_p1; /* private */ + caddr_t xp_p2; /* private */ + char xp_pad [256]; /* padding, internal use */ +}; + +/* + * Approved way of getting address of caller + */ +#define svc_getcaller(x) (&(x)->xp_raddr) + +/* + * Operations defined on an SVCXPRT handle + * + * SVCXPRT *xprt; + * struct rpc_msg *msg; + * xdrproc_t xargs; + * caddr_t argsp; + */ +#define SVC_RECV(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) +#define svc_recv(xprt, msg) \ + (*(xprt)->xp_ops->xp_recv)((xprt), (msg)) + +#define SVC_STAT(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) +#define svc_stat(xprt) \ + (*(xprt)->xp_ops->xp_stat)(xprt) + +#define SVC_GETARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) +#define svc_getargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_getargs)((xprt), (xargs), (argsp)) + +#define SVC_REPLY(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) +#define svc_reply(xprt, msg) \ + (*(xprt)->xp_ops->xp_reply) ((xprt), (msg)) + +#define SVC_FREEARGS(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) +#define svc_freeargs(xprt, xargs, argsp) \ + (*(xprt)->xp_ops->xp_freeargs)((xprt), (xargs), (argsp)) + +#define SVC_DESTROY(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) +#define svc_destroy(xprt) \ + (*(xprt)->xp_ops->xp_destroy)(xprt) + + +/* + * Service request + */ +struct svc_req { + rpcprog_t rq_prog; /* service program number */ + rpcvers_t rq_vers; /* service protocol version */ + rpcproc_t rq_proc; /* the desired procedure */ + struct opaque_auth rq_cred; /* raw creds from the wire */ + caddr_t rq_clntcred; /* read only cooked cred */ + SVCXPRT *rq_xprt; /* associated transport */ +}; + +#ifndef __DISPATCH_FN_T +#define __DISPATCH_FN_T +typedef void (*__dispatch_fn_t) (struct svc_req*, SVCXPRT*); +#endif + +/* + * Service registration + * + * svc_register(xprt, prog, vers, dispatch, protocol) + * SVCXPRT *xprt; + * rpcprog_t prog; + * rpcvers_t vers; + * void (*dispatch)(struct svc_req*, SVCXPRT*); + * rpcprot_t protocol; like TCP or UDP, zero means do not register + */ +extern bool_t svc_register (SVCXPRT *__xprt, rpcprog_t __prog, + rpcvers_t __vers, __dispatch_fn_t __dispatch, + rpcprot_t __protocol) __THROW; + +/* + * Service un-registration + * + * svc_unregister(prog, vers) + * rpcprog_t prog; + * rpcvers_t vers; + */ +extern void svc_unregister (rpcprog_t __prog, rpcvers_t __vers) __THROW; + +/* + * Transport registration. + * + * xprt_register(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_register (SVCXPRT *__xprt) __THROW; + +/* + * Transport un-register + * + * xprt_unregister(xprt) + * SVCXPRT *xprt; + */ +extern void xprt_unregister (SVCXPRT *__xprt) __THROW; + + +/* + * When the service routine is called, it must first check to see if it + * knows about the procedure; if not, it should call svcerr_noproc + * and return. If so, it should deserialize its arguments via + * SVC_GETARGS (defined above). If the deserialization does not work, + * svcerr_decode should be called followed by a return. Successful + * decoding of the arguments should be followed the execution of the + * procedure's code and a call to svc_sendreply. + * + * Also, if the service refuses to execute the procedure due to too- + * weak authentication parameters, svcerr_weakauth should be called. + * Note: do not confuse access-control failure with weak authentication! + * + * NB: In pure implementations of rpc, the caller always waits for a reply + * msg. This message is sent when svc_sendreply is called. + * Therefore pure service implementations should always call + * svc_sendreply even if the function logically returns void; use + * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows + * for the abuse of pure rpc via batched calling or pipelining. In the + * case of a batched call, svc_sendreply should NOT be called since + * this would send a return message, which is what batching tries to avoid. + * It is the service/protocol writer's responsibility to know which calls are + * batched and which are not. Warning: responding to batch calls may + * deadlock the caller and server processes! + */ + +extern bool_t svc_sendreply (SVCXPRT *__xprt, xdrproc_t __xdr_results, + caddr_t __xdr_location) __THROW; + +extern void svcerr_decode (SVCXPRT *__xprt) __THROW; + +extern void svcerr_weakauth (SVCXPRT *__xprt) __THROW; + +extern void svcerr_noproc (SVCXPRT *__xprt) __THROW; + +extern void svcerr_progvers (SVCXPRT *__xprt, rpcvers_t __low_vers, + rpcvers_t __high_vers) __THROW; + +extern void svcerr_auth (SVCXPRT *__xprt, enum auth_stat __why) __THROW; + +extern void svcerr_noprog (SVCXPRT *__xprt) __THROW; + +extern void svcerr_systemerr (SVCXPRT *__xprt) __THROW; + +/* + * 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 (coexistent) 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 + */ + +extern struct pollfd *svc_pollfd; +extern int svc_max_pollfd; +extern fd_set svc_fdset; +#define svc_fds svc_fdset.fds_bits[0] /* compatibility */ + +/* + * a small program implemented by the svc_rpc implementation itself; + * also see clnt.h for protocol numbers. + */ +extern void svc_getreq (int __rdfds) __THROW; +extern void svc_getreq_common (const int __fd) __THROW; +extern void svc_getreqset (fd_set *__readfds) __THROW; +extern void svc_getreq_poll (struct pollfd *, const int) __THROW; +extern void svc_exit (void) __THROW; +extern void svc_run (void) __THROW; + +/* + * 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 (void) __THROW; + +/* + * Udp based rpc. + */ +extern SVCXPRT *svcudp_create (int __sock) __THROW; +extern SVCXPRT *svcudp_bufcreate (int __sock, u_int __sendsz, u_int __recvsz) + __THROW; + +/* + * Tcp based rpc. + */ +extern SVCXPRT *svctcp_create (int __sock, u_int __sendsize, u_int __recvsize) + __THROW; + +/* + * FD based rpc. + */ +extern SVCXPRT *svcfd_create (int __sock, u_int __sendsize, u_int __recvsize) + __THROW; + +/* + * Unix based rpc. + */ +extern SVCXPRT *svcunix_create (int __sock, u_int __sendsize, u_int __recvsize, + char *__path) __THROW; + + +__END_DECLS + +#endif /* rpc/svc.h */ diff --git a/REORG.TODO/sunrpc/rpc/svc_auth.h b/REORG.TODO/sunrpc/rpc/svc_auth.h new file mode 100644 index 0000000000..4ba27411e7 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/svc_auth.h @@ -0,0 +1,50 @@ +/* + * svc_auth.h, Service side of rpc authentication. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_SVC_AUTH_H +#define _RPC_SVC_AUTH_H 1 + +#include <features.h> +#include <rpc/svc.h> + +__BEGIN_DECLS + +/* + * Server side authenticator + */ +extern enum auth_stat _authenticate (struct svc_req *__rqst, + struct rpc_msg *__msg) __THROW; + +__END_DECLS + +#endif /* rpc/svc_auth.h */ diff --git a/REORG.TODO/sunrpc/rpc/types.h b/REORG.TODO/sunrpc/rpc/types.h new file mode 100644 index 0000000000..beded52555 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/types.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* fixincludes should not add extern "C" to this file */ +/* + * Rpc additions to <sys/types.h> + */ +#ifndef _RPC_TYPES_H +#define _RPC_TYPES_H 1 + +typedef int bool_t; +typedef int enum_t; +/* This needs to be changed to uint32_t in the future */ +typedef unsigned long rpcprog_t; +typedef unsigned long rpcvers_t; +typedef unsigned long rpcproc_t; +typedef unsigned long rpcprot_t; +typedef unsigned long rpcport_t; + +#define __dontcare__ -1 + +#ifndef FALSE +# define FALSE (0) +#endif + +#ifndef TRUE +# define TRUE (1) +#endif + +#ifndef NULL +# define NULL 0 +#endif + +#include <stdlib.h> /* For malloc decl. */ +#define mem_alloc(bsize) malloc(bsize) +/* + * XXX: This must not use the second argument, or code in xdr_array.c needs + * to be modified. + */ +#define mem_free(ptr, bsize) free(ptr) + +#ifndef makedev /* ie, we haven't already included it */ +#include <sys/types.h> +#endif + +#if defined __APPLE_CC__ || defined __FreeBSD__ +# define __u_char_defined +# define __daddr_t_defined +#endif + +#ifndef __u_char_defined +typedef __u_char u_char; +typedef __u_short u_short; +typedef __u_int u_int; +typedef __u_long u_long; +typedef __quad_t quad_t; +typedef __u_quad_t u_quad_t; +typedef __fsid_t fsid_t; +# define __u_char_defined +#endif +#ifndef __daddr_t_defined +typedef __daddr_t daddr_t; +typedef __caddr_t caddr_t; +# define __daddr_t_defined +#endif + +#include <sys/time.h> +#include <sys/param.h> + +#include <netinet/in.h> + +#ifndef INADDR_LOOPBACK +#define INADDR_LOOPBACK (u_long)0x7F000001 +#endif +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 64 +#endif + +#endif /* rpc/types.h */ diff --git a/REORG.TODO/sunrpc/rpc/xdr.h b/REORG.TODO/sunrpc/rpc/xdr.h new file mode 100644 index 0000000000..d80d8f735d --- /dev/null +++ b/REORG.TODO/sunrpc/rpc/xdr.h @@ -0,0 +1,377 @@ +/* + * xdr.h, External Data Representation Serialization Routines. + * + * Copyright (c) 2010, 2012, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _RPC_XDR_H +#define _RPC_XDR_H 1 + +#include <features.h> +#include <sys/types.h> +#include <rpc/types.h> + +/* We need FILE. */ +#include <stdio.h> + +__BEGIN_DECLS + +/* + * 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) +/* + * This only works if the above is a power of 2. But it's defined to be + * 4 by the appropriate RFCs. So it will work. And it's normally quicker + * than the old routine. + */ +#if 1 +#define RNDUP(x) (((x) + BYTES_PER_XDR_UNIT - 1) & ~(BYTES_PER_XDR_UNIT - 1)) +#else /* this is the old routine */ +#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ + * BYTES_PER_XDR_UNIT) +#endif + +/* + * The XDR handle. + * Contains operation which is being applied to the stream, + * an operations vector for the particular implementation (e.g. see xdr_mem.c), + * and two private fields for the use of the particular implementation. + */ +typedef struct XDR XDR; +struct XDR + { + enum xdr_op x_op; /* operation; fast additional param */ + struct xdr_ops + { + bool_t (*x_getlong) (XDR *__xdrs, long *__lp); + /* get a long from underlying stream */ + bool_t (*x_putlong) (XDR *__xdrs, const long *__lp); + /* put a long to " */ + bool_t (*x_getbytes) (XDR *__xdrs, caddr_t __addr, u_int __len); + /* get some bytes from " */ + bool_t (*x_putbytes) (XDR *__xdrs, const char *__addr, u_int __len); + /* put some bytes to " */ + u_int (*x_getpostn) (const XDR *__xdrs); + /* returns bytes off from beginning */ + bool_t (*x_setpostn) (XDR *__xdrs, u_int __pos); + /* lets you reposition the stream */ + int32_t *(*x_inline) (XDR *__xdrs, u_int __len); + /* buf quick ptr to buffered data */ + void (*x_destroy) (XDR *__xdrs); + /* free privates of this xdr_stream */ + bool_t (*x_getint32) (XDR *__xdrs, int32_t *__ip); + /* get a int from underlying stream */ + bool_t (*x_putint32) (XDR *__xdrs, const int32_t *__ip); + /* put a int to " */ + } + *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 */ + u_int x_handy; /* extra private word */ + }; + +/* + * 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) (XDR *, void *,...); + + +/* + * Operations defined on a XDR handle + * + * XDR *xdrs; + * int32_t *int32p; + * long *longp; + * caddr_t addr; + * u_int len; + * u_int pos; + */ +#define XDR_GETINT32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_getint32)(xdrs, int32p) +#define xdr_getint32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_getint32)(xdrs, int32p) + +#define XDR_PUTINT32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_putint32)(xdrs, int32p) +#define xdr_putint32(xdrs, int32p) \ + (*(xdrs)->x_ops->x_putint32)(xdrs, int32p) + +#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) \ + do { \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs); \ + } while (0) +#define xdr_destroy(xdrs) \ + do { \ + if ((xdrs)->x_ops->x_destroy) \ + (*(xdrs)->x_ops->x_destroy)(xdrs); \ + } while (0) + +/* + * Support struct for discriminated unions. + * You create an array of xdrdiscrim structures, terminated with + * an 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; +}; + +/* + * Inline routines for fast encode/decode of primitive 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_INT32(buf) ((int32_t)ntohl((uint32_t)*(buf)++)) +#define IXDR_PUT_INT32(buf, v) (*(buf)++ = (int32_t)htonl((uint32_t)(v))) +#define IXDR_GET_U_INT32(buf) ((uint32_t)IXDR_GET_INT32(buf)) +#define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32(buf, (int32_t)(v)) + +/* WARNING: The IXDR_*_LONG defines are removed by Sun for new platforms + * and shouldn't be used any longer. Code which use this defines or longs + * in the RPC code will not work on 64bit Solaris platforms ! + */ +#define IXDR_GET_LONG(buf) ((long)IXDR_GET_U_INT32(buf)) +#define IXDR_PUT_LONG(buf, v) ((long)IXDR_PUT_INT32(buf, (long)(v))) +#define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) +#define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG(buf, (long)(v)) + + +#define IXDR_GET_BOOL(buf) ((bool_t)IXDR_GET_LONG(buf)) +#define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) +#define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) +#define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) + +#define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v)) +#define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG(buf, (long)(v)) + +/* + * These are the "generic" xdr routines. + * None of these can have const applied because it's not possible to + * know whether the call is a read or a write to the passed parameter + * also, the XDR structure is always updated by some of these calls. + */ +extern bool_t xdr_void (void) __THROW; +extern bool_t xdr_short (XDR *__xdrs, short *__sp) __THROW; +extern bool_t xdr_u_short (XDR *__xdrs, u_short *__usp) __THROW; +extern bool_t xdr_int (XDR *__xdrs, int *__ip) __THROW; +extern bool_t xdr_u_int (XDR *__xdrs, u_int *__up) __THROW; +extern bool_t xdr_long (XDR *__xdrs, long *__lp) __THROW; +extern bool_t xdr_u_long (XDR *__xdrs, u_long *__ulp) __THROW; +extern bool_t xdr_hyper (XDR *__xdrs, quad_t *__llp) __THROW; +extern bool_t xdr_u_hyper (XDR *__xdrs, u_quad_t *__ullp) __THROW; +extern bool_t xdr_longlong_t (XDR *__xdrs, quad_t *__llp) __THROW; +extern bool_t xdr_u_longlong_t (XDR *__xdrs, u_quad_t *__ullp) __THROW; +extern bool_t xdr_int8_t (XDR *__xdrs, int8_t *__ip) __THROW; +extern bool_t xdr_uint8_t (XDR *__xdrs, uint8_t *__up) __THROW; +extern bool_t xdr_int16_t (XDR *__xdrs, int16_t *__ip) __THROW; +extern bool_t xdr_uint16_t (XDR *__xdrs, uint16_t *__up) __THROW; +extern bool_t xdr_int32_t (XDR *__xdrs, int32_t *__ip) __THROW; +extern bool_t xdr_uint32_t (XDR *__xdrs, uint32_t *__up) __THROW; +extern bool_t xdr_int64_t (XDR *__xdrs, int64_t *__ip) __THROW; +extern bool_t xdr_uint64_t (XDR *__xdrs, uint64_t *__up) __THROW; +extern bool_t xdr_quad_t (XDR *__xdrs, quad_t *__ip) __THROW; +extern bool_t xdr_u_quad_t (XDR *__xdrs, u_quad_t *__up) __THROW; +extern bool_t xdr_bool (XDR *__xdrs, bool_t *__bp) __THROW; +extern bool_t xdr_enum (XDR *__xdrs, enum_t *__ep) __THROW; +extern bool_t xdr_array (XDR * _xdrs, caddr_t *__addrp, u_int *__sizep, + u_int __maxsize, u_int __elsize, xdrproc_t __elproc) + __THROW; +extern bool_t xdr_bytes (XDR *__xdrs, char **__cpp, u_int *__sizep, + u_int __maxsize) __THROW; +extern bool_t xdr_opaque (XDR *__xdrs, caddr_t __cp, u_int __cnt) __THROW; +extern bool_t xdr_string (XDR *__xdrs, char **__cpp, u_int __maxsize) __THROW; +extern bool_t xdr_union (XDR *__xdrs, enum_t *__dscmp, char *__unp, + const struct xdr_discrim *__choices, + xdrproc_t __dfault) __THROW; +extern bool_t xdr_char (XDR *__xdrs, char *__cp) __THROW; +extern bool_t xdr_u_char (XDR *__xdrs, u_char *__cp) __THROW; +extern bool_t xdr_vector (XDR *__xdrs, char *__basep, u_int __nelem, + u_int __elemsize, xdrproc_t __xdr_elem) __THROW; +extern bool_t xdr_float (XDR *__xdrs, float *__fp) __THROW; +extern bool_t xdr_double (XDR *__xdrs, double *__dp) __THROW; +extern bool_t xdr_reference (XDR *__xdrs, caddr_t *__xpp, u_int __size, + xdrproc_t __proc) __THROW; +extern bool_t xdr_pointer (XDR *__xdrs, char **__objpp, + u_int __obj_size, xdrproc_t __xdr_obj) __THROW; +extern bool_t xdr_wrapstring (XDR *__xdrs, char **__cpp) __THROW; +extern u_long xdr_sizeof (xdrproc_t, void *) __THROW; + +/* + * Common opaque bytes objects used by many rpc protocols; + * declared here due to commonality. + */ +#define MAX_NETOBJ_SZ 1024 +struct netobj +{ + u_int n_len; + char *n_bytes; +}; +typedef struct netobj netobj; +extern bool_t xdr_netobj (XDR *__xdrs, struct netobj *__np) __THROW; + +/* + * These are the public routines for the various implementations of + * xdr streams. + */ + +/* XDR using memory buffers */ +extern void xdrmem_create (XDR *__xdrs, const caddr_t __addr, + u_int __size, enum xdr_op __xop) __THROW; + +/* XDR using stdio library */ +extern void xdrstdio_create (XDR *__xdrs, FILE *__file, enum xdr_op __xop) + __THROW; + +/* XDR pseudo records for tcp */ +extern void xdrrec_create (XDR *__xdrs, u_int __sendsize, + u_int __recvsize, caddr_t __tcp_handle, + int (*__readit) (char *, char *, int), + int (*__writeit) (char *, char *, int)) __THROW; + +/* make end of xdr record */ +extern bool_t xdrrec_endofrecord (XDR *__xdrs, bool_t __sendnow) __THROW; + +/* move to beginning of next record */ +extern bool_t xdrrec_skiprecord (XDR *__xdrs) __THROW; + +/* true if no more input */ +extern bool_t xdrrec_eof (XDR *__xdrs) __THROW; + +/* free memory buffers for xdr */ +extern void xdr_free (xdrproc_t __proc, char *__objp) __THROW; + +__END_DECLS + +#endif /* rpc/xdr.h */ diff --git a/REORG.TODO/sunrpc/rpc_clntout.c b/REORG.TODO/sunrpc/rpc_clntout.c new file mode 100644 index 0000000000..ce4d2a4c95 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_clntout.c @@ -0,0 +1,333 @@ +/* + * rpc_clntout.c, Client-stub outputter for the RPC protocol compiler + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <stdio.h> +#include <string.h> +#include "rpc/types.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define DEFAULT_TIMEOUT 25 /* in seconds */ +static const char RESULT[] = "clnt_res"; + +static void write_program (definition * def); +static void printbody (proc_list * proc); +static const char *ampr (const char *type); +static void printbody (proc_list * proc); + + +void +write_stubs (void) +{ + list *l; + definition *def; + + fprintf (fout, + "\n/* Default timeout can be changed using clnt_control() */\n"); + fprintf (fout, "static struct timeval TIMEOUT = { %d, 0 };\n", + DEFAULT_TIMEOUT); + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_program (def); + } + } +} + +static void +write_program (definition * def) +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + fprintf (fout, "\n"); + if (mtflag == 0) + { + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*\n"); + pvname (proc->proc_name, vp->vers_num); + printarglist (proc, RESULT, "clnt", "CLIENT *"); + } + else + { + fprintf (fout, "enum clnt_stat \n"); + pvname (proc->proc_name, vp->vers_num); + printarglist (proc, RESULT, "clnt", "CLIENT *"); + } + fprintf (fout, "{\n"); + printbody (proc); + fprintf (fout, "}\n"); + } + } +} + +/* Writes out declarations of procedure's argument list. + In either ANSI C style, in one of old rpcgen style (pass by reference), + or new rpcgen style (multiple arguments, pass by value); + */ + +/* sample addargname = "clnt"; sample addargtype = "CLIENT * " */ + +void +printarglist (proc_list * proc, const char *result, + const char *addargname, const char *addargtype) +{ + + decl_list *l; + + if (!newstyle) + { /* old style: always pass argument by reference */ + if (Cflag) + { /* C++ style heading */ + fprintf (fout, "("); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); + + if (mtflag) + {/* Generate result field */ + fprintf (fout, "*argp, "); + ptype(proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname); + } + else + fprintf (fout, "*argp, %s%s)\n", addargtype, addargname); + } + else + { + if (!mtflag) + fprintf (fout, "(argp, %s)\n", addargname); + else + fprintf (fout, "(argp, %s, %s)\n", result, addargname); + fprintf (fout, "\t"); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); + fprintf (fout, "*argp;\n"); + if (mtflag) + { + fprintf (fout, "\t"); + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s;\n", result); + } + } + } + else if (streq (proc->args.decls->decl.type, "void")) + { + /* newstyle, 0 argument */ + if (mtflag) + { + fprintf (fout, "("); + if (Cflag) + { + ptype(proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s, %s%s)\n", result, addargtype, addargname); + } + else + fprintf (fout, "(%s)\n", addargname); + } + else if (Cflag) + fprintf (fout, "(%s%s)\n", addargtype, addargname); + else + fprintf (fout, "(%s)\n", addargname); + } + else + { + /* new style, 1 or multiple arguments */ + if (!Cflag) + { + fprintf (fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) + fprintf (fout, "%s, ", l->decl.name); + if (mtflag) + fprintf (fout, "%s, ", result); + fprintf (fout, "%s)\n", addargname); + for (l = proc->args.decls; l != NULL; l = l->next) + { + pdeclaration (proc->args.argname, &l->decl, 1, ";\n"); + } + if (mtflag) + { + fprintf (fout, "\t"); + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s;\n", result); + } + } + else + { /* C++ style header */ + fprintf (fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) + { + pdeclaration (proc->args.argname, &l->decl, 0, ", "); + } + if (mtflag) + { + ptype (proc->res_prefix, proc->res_type, 1); + fprintf (fout, "*%s, ", result); + } + fprintf (fout, " %s%s)\n", addargtype, addargname); + } + } + + if (!Cflag) + fprintf (fout, "\t%s%s;\n", addargtype, addargname); +} + + +static +const char * +ampr (const char *type) +{ + if (isvectordef (type, REL_ALIAS)) + { + return ""; + } + else + { + return "&"; + } +} + +static void +printbody (proc_list * proc) +{ + decl_list *l; + bool_t args2 = (proc->arg_num > 1); +/* int i; */ + + /* For new style with multiple arguments, need a structure in which + to stuff the arguments. */ + if (newstyle && args2) + { + fprintf (fout, "\t%s", proc->args.argname); + fprintf (fout, " arg;\n"); + } + if (!mtflag) + { + fprintf (fout, "\tstatic "); + if (streq (proc->res_type, "void")) + { + fprintf (fout, "char "); + } + else + { + ptype (proc->res_prefix, proc->res_type, 0); + } + fprintf (fout, "%s;\n", RESULT); + fprintf (fout, "\n"); + fprintf (fout, "\tmemset((char *)%s%s, 0, sizeof(%s));\n", + ampr (proc->res_type), RESULT, RESULT); + } + if (newstyle && !args2 && (streq (proc->args.decls->decl.type, "void"))) + { + /* newstyle, 0 arguments */ + if (mtflag) + fprintf (fout, "\t return "); + else + fprintf (fout, "\t if "); + fprintf (fout, + "(clnt_call (clnt, %s, (xdrproc_t) xdr_void, ", proc->proc_name); + + fprintf (fout, + "(caddr_t) NULL,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,", + stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type), + RESULT); + if (mtflag) + fprintf (fout, "\n\t\tTIMEOUT));\n\n"); + else + fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); + } + else if (newstyle && args2) + { + /* newstyle, multiple arguments: stuff arguments into structure */ + for (l = proc->args.decls; l != NULL; l = l->next) + { + fprintf (fout, "\targ.%s = %s;\n", + l->decl.name, l->decl.name); + } + if (mtflag) + fprintf (fout, "\treturn "); + else + fprintf (fout, "\tif "); + + fprintf (fout, + "(clnt_call (clnt, %s, (xdrproc_t) xdr_%s", proc->proc_name, + proc->args.argname); + fprintf (fout, + ", (caddr_t) &arg,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,", + stringfix(proc->res_type), (mtflag)?"":ampr(proc->res_type), + RESULT); + if (mtflag) + fprintf (fout, "\n\t\tTIMEOUT));\n"); + else + fprintf (fout, "\n\t\tTIMEOUT) != RPC_SUCCESS) {\n"); + } + else + { /* single argument, new or old style */ + if (!mtflag) + fprintf (fout, + "\tif (clnt_call (clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT) != RPC_SUCCESS) {\n", + proc->proc_name, + stringfix (proc->args.decls->decl.type), + (newstyle ? "&" : ""), + (newstyle ? proc->args.decls->decl.name : "argp"), + stringfix (proc->res_type), ampr (proc->res_type), + RESULT); + else + fprintf(fout, + "\treturn (clnt_call(clnt, %s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\t(xdrproc_t) xdr_%s, (caddr_t) %s%s,\n\t\tTIMEOUT));\n", + proc->proc_name, + stringfix (proc->args.decls->decl.type), + (newstyle ? "&" : ""), + (newstyle ? proc->args.decls->decl.name : "argp"), + stringfix (proc->res_type), "", + RESULT); + } + if (!mtflag) + { + fprintf (fout, "\t\treturn (NULL);\n"); + fprintf (fout, "\t}\n"); + if (streq (proc->res_type, "void")) + { + fprintf (fout, "\treturn ((void *)%s%s);\n", + ampr (proc->res_type), RESULT); + } + else + { + fprintf (fout, "\treturn (%s%s);\n", ampr (proc->res_type), RESULT); + } + } +} diff --git a/REORG.TODO/sunrpc/rpc_cmsg.c b/REORG.TODO/sunrpc/rpc_cmsg.c new file mode 100644 index 0000000000..ec8cc6ccca --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_cmsg.c @@ -0,0 +1,198 @@ +/* + * rpc_callmsg.c + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <string.h> +#include <sys/param.h> +#include <rpc/rpc.h> +#include <shlib-compat.h> + +/* + * XDR a call message + */ +bool_t +xdr_callmsg (XDR *xdrs, struct rpc_msg *cmsg) +{ + int32_t *buf; + struct opaque_auth *oa; + + if (xdrs->x_op == XDR_ENCODE) + { + if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) + { + return (FALSE); + } + if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) + { + return (FALSE); + } + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT + + RNDUP (cmsg->rm_call.cb_cred.oa_length) + + 2 * BYTES_PER_XDR_UNIT + + RNDUP (cmsg->rm_call.cb_verf.oa_length)); + if (buf != NULL) + { + (void) IXDR_PUT_LONG (buf, cmsg->rm_xid); + (void) IXDR_PUT_ENUM (buf, cmsg->rm_direction); + if (cmsg->rm_direction != CALL) + return FALSE; + (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_rpcvers); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) + return FALSE; + (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_prog); + (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_vers); + (void) IXDR_PUT_LONG (buf, cmsg->rm_call.cb_proc); + oa = &cmsg->rm_call.cb_cred; + (void) IXDR_PUT_ENUM (buf, oa->oa_flavor); + (void) IXDR_PUT_INT32 (buf, oa->oa_length); + if (oa->oa_length) + { + memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); + buf = (int32_t *) ((char *) buf + RNDUP (oa->oa_length)); + } + oa = &cmsg->rm_call.cb_verf; + (void) IXDR_PUT_ENUM (buf, oa->oa_flavor); + (void) IXDR_PUT_INT32 (buf, oa->oa_length); + if (oa->oa_length) + { + memcpy ((caddr_t) buf, oa->oa_base, oa->oa_length); + /* no real need.... + buf = (long *) ((char *) buf + RNDUP(oa->oa_length)); + */ + } + return TRUE; + } + } + if (xdrs->x_op == XDR_DECODE) + { + buf = XDR_INLINE (xdrs, 8 * BYTES_PER_XDR_UNIT); + if (buf != NULL) + { + cmsg->rm_xid = IXDR_GET_LONG (buf); + cmsg->rm_direction = IXDR_GET_ENUM (buf, enum msg_type); + if (cmsg->rm_direction != CALL) + { + return FALSE; + } + cmsg->rm_call.cb_rpcvers = IXDR_GET_LONG (buf); + if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) + { + return FALSE; + } + cmsg->rm_call.cb_prog = IXDR_GET_LONG (buf); + cmsg->rm_call.cb_vers = IXDR_GET_LONG (buf); + cmsg->rm_call.cb_proc = IXDR_GET_LONG (buf); + oa = &cmsg->rm_call.cb_cred; + oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); + oa->oa_length = IXDR_GET_INT32 (buf); + if (oa->oa_length) + { + if (oa->oa_length > MAX_AUTH_BYTES) + return FALSE; + if (oa->oa_base == NULL) + { + oa->oa_base = (caddr_t) + mem_alloc (oa->oa_length); + } + buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); + if (buf == NULL) + { + if (xdr_opaque (xdrs, oa->oa_base, + oa->oa_length) == FALSE) + return FALSE; + } + else + { + memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); + /* no real need.... + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); + */ + } + } + oa = &cmsg->rm_call.cb_verf; + buf = XDR_INLINE (xdrs, 2 * BYTES_PER_XDR_UNIT); + if (buf == NULL) + { + if (xdr_enum (xdrs, &oa->oa_flavor) == FALSE || + xdr_u_int (xdrs, &oa->oa_length) == FALSE) + { + return FALSE; + } + } + else + { + oa->oa_flavor = IXDR_GET_ENUM (buf, enum_t); + oa->oa_length = IXDR_GET_INT32 (buf); + } + if (oa->oa_length) + { + if (oa->oa_length > MAX_AUTH_BYTES) + return FALSE; + if (oa->oa_base == NULL) + { + oa->oa_base = (caddr_t) + mem_alloc (oa->oa_length); + } + buf = XDR_INLINE (xdrs, RNDUP (oa->oa_length)); + if (buf == NULL) + { + if (xdr_opaque (xdrs, oa->oa_base, + oa->oa_length) == FALSE) + return FALSE; + } + else + { + memcpy (oa->oa_base, (caddr_t) buf, oa->oa_length); + /* no real need... + buf = (long *) ((char *) buf + + RNDUP(oa->oa_length)); + */ + } + } + return TRUE; + } + } + if ( + xdr_u_long (xdrs, &(cmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) && + (cmsg->rm_direction == CALL) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) && + (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_proc)) && + xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_cred))) + return xdr_opaque_auth (xdrs, &(cmsg->rm_call.cb_verf)); + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_callmsg, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/rpc_common.c b/REORG.TODO/sunrpc/rpc_common.c new file mode 100644 index 0000000000..710191163c --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_common.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include <rpc/rpc.h> +#include <shlib-compat.h> + +#ifdef _RPC_THREAD_SAFE_ +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd +#endif /* _RPC_THREAD_SAFE_ */ + +/* + * This file should only contain common data (global data) that is exported + * by public interfaces + */ +/* We are very tricky here. We want to have _null_auth in a read-only + section but we cannot add const to the type because this isn't how + the variable is declared. So we use the section attribute. */ +struct opaque_auth _null_auth __attribute__ ((nocommon)); +libc_hidden_nolink_sunrpc (_null_auth, GLIBC_2_0) +fd_set svc_fdset; +struct rpc_createerr rpc_createerr; +struct pollfd *svc_pollfd; +int svc_max_pollfd; diff --git a/REORG.TODO/sunrpc/rpc_cout.c b/REORG.TODO/sunrpc/rpc_cout.c new file mode 100644 index 0000000000..db7b571b33 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_cout.c @@ -0,0 +1,811 @@ +/* + * From: @(#)rpc_cout.c 1.13 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_cout.c, XDR routine outputter for the RPC protocol compiler + */ +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +static void emit_enum (definition * def); +static void emit_program (const definition * def); +static void emit_union (const definition * def); +static void emit_struct (definition * def); +static void emit_typedef (const definition * def); +static void emit_inline (int indent, declaration * decl, int flag); +static void emit_single_in_line (int indent, declaration *decl, int flag, + relation rel); +static int findtype (const definition * def, const char *type); +static int undefined (const char *type); +static void print_generic_header (const char *procname, int pointerp); +static void print_ifopen (int indent, const char *name); +static void print_ifarg (const char *arg); +static void print_ifsizeof (int indent, const char *prefix, const char *type); +static void print_ifclose (int indent); +static void print_ifstat (int indent, const char *prefix, const char *type, + relation rel, const char *amax, + const char *objname, const char *name); +static void print_stat (int indent, const declaration * dec); +static void print_header (const definition * def); +static void print_trailer (void); +static char *upcase (const char *str); + +/* + * Emit the C-routine for the given definition + */ +void +emit (definition * def) +{ + if (def->def_kind == DEF_CONST) + { + return; + } + if (def->def_kind == DEF_PROGRAM) + { + emit_program (def); + return; + } + if (def->def_kind == DEF_TYPEDEF) + { + /* now we need to handle declarations like + struct typedef foo foo; + since we don't want this to be expanded + into 2 calls to xdr_foo */ + + if (strcmp (def->def.ty.old_type, def->def_name) == 0) + return; + }; + + print_header (def); + switch (def->def_kind) + { + case DEF_UNION: + emit_union (def); + break; + case DEF_ENUM: + emit_enum (def); + break; + case DEF_STRUCT: + emit_struct (def); + break; + case DEF_TYPEDEF: + emit_typedef (def); + break; + default: + /* can't happen */ + break; + } + print_trailer (); +} + +static int +findtype (const definition * def, const char *type) +{ + if (def->def_kind == DEF_PROGRAM || def->def_kind == DEF_CONST) + { + return 0; + } + else + { + return (streq (def->def_name, type)); + } +} + +static int +undefined (const char *type) +{ + definition *def; + def = (definition *) FINDVAL (defined, type, findtype); + return (def == NULL); +} + + +static void +print_generic_header (const char *procname, int pointerp) +{ + f_print (fout, "\n"); + f_print (fout, "bool_t\n"); + if (Cflag) + { + f_print (fout, "xdr_%s (", procname); + f_print (fout, "XDR *xdrs, "); + f_print (fout, "%s ", procname); + if (pointerp) + f_print (fout, "*"); + f_print (fout, "objp)\n{\n"); + } + else + { + f_print (fout, "xdr_%s (xdrs, objp)\n", procname); + f_print (fout, "\tXDR *xdrs;\n"); + f_print (fout, "\t%s ", procname); + if (pointerp) + f_print (fout, "*"); + f_print (fout, "objp;\n{\n"); + } +} + +static void +print_header (const definition * def) +{ + print_generic_header (def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef (def->def.ty.old_type, + def->def.ty.rel)); + + /* Now add Inline support */ + + if (inlineflag == 0) + return; + /*May cause lint to complain. but ... */ + f_print (fout, "\tregister int32_t *buf;\n\n"); +} + +static void +print_prog_header (const proc_list * plist) +{ + print_generic_header (plist->args.argname, 1); +} + +static void +print_trailer (void) +{ + f_print (fout, "\treturn TRUE;\n"); + f_print (fout, "}\n"); +} + + +static void +print_ifopen (int indent, const char *name) +{ + tabify (fout, indent); + f_print (fout, " if (!xdr_%s (xdrs", name); +} + +static void +print_ifarg (const char *arg) +{ + f_print (fout, ", %s", arg); +} + +static void +print_ifsizeof (int indent, const char *prefix, const char *type) +{ + if (indent) + { + fprintf (fout, ",\n"); + tabify (fout, indent); + } + else + fprintf (fout, ", "); + + if (streq (type, "bool")) + fprintf (fout, "sizeof (bool_t), (xdrproc_t) xdr_bool"); + else + { + fprintf (fout, "sizeof ("); + if (undefined (type) && prefix) + { + f_print (fout, "%s ", prefix); + } + fprintf (fout, "%s), (xdrproc_t) xdr_%s", type, type); + } +} + +static void +print_ifclose (int indent) +{ + f_print (fout, "))\n"); + tabify (fout, indent); + f_print (fout, "\t return FALSE;\n"); +} + +static void +print_ifstat (int indent, const char *prefix, const char *type, relation rel, + const char *amax, const char *objname, const char *name) +{ + const char *alt = NULL; + + switch (rel) + { + case REL_POINTER: + print_ifopen (indent, "pointer"); + print_ifarg ("(char **)"); + f_print (fout, "%s", objname); + print_ifsizeof (0, prefix, type); + break; + case REL_VECTOR: + if (streq (type, "string")) + { + alt = "string"; + } + else if (streq (type, "opaque")) + { + alt = "opaque"; + } + if (alt) + { + print_ifopen (indent, alt); + print_ifarg (objname); + } + else + { + print_ifopen (indent, "vector"); + print_ifarg ("(char *)"); + f_print (fout, "%s", objname); + } + print_ifarg (amax); + if (!alt) + { + print_ifsizeof (indent + 1, prefix, type); + } + break; + case REL_ARRAY: + if (streq (type, "string")) + { + alt = "string"; + } + else if (streq (type, "opaque")) + { + alt = "bytes"; + } + if (streq (type, "string")) + { + print_ifopen (indent, alt); + print_ifarg (objname); + } + else + { + if (alt) + { + print_ifopen (indent, alt); + } + else + { + print_ifopen (indent, "array"); + } + print_ifarg ("(char **)"); + if (*objname == '&') + { + f_print (fout, "%s.%s_val, (u_int *) %s.%s_len", + objname, name, objname, name); + } + else + { + f_print (fout, "&%s->%s_val, (u_int *) &%s->%s_len", + objname, name, objname, name); + } + } + print_ifarg (amax); + if (!alt) + { + print_ifsizeof (indent + 1, prefix, type); + } + break; + case REL_ALIAS: + print_ifopen (indent, type); + print_ifarg (objname); + break; + } + print_ifclose (indent); +} + +static void +emit_enum (definition * def) +{ + (void) def; + + print_ifopen (1, "enum"); + print_ifarg ("(enum_t *) objp"); + print_ifclose (1); +} + +static void +emit_program (const definition * def) +{ + decl_list *dl; + version_list *vlist; + proc_list *plist; + + for (vlist = def->def.pr.versions; vlist != NULL; vlist = vlist->next) + for (plist = vlist->procs; plist != NULL; plist = plist->next) + { + if (!newstyle || plist->arg_num < 2) + continue; /* old style, or single argument */ + print_prog_header (plist); + for (dl = plist->args.decls; dl != NULL; + dl = dl->next) + print_stat (1, &dl->decl); + print_trailer (); + } +} + +static void +emit_union (const definition * def) +{ + declaration *dflt; + case_list *cl; + declaration *cs; + char *object; + const char *vecformat = "objp->%s_u.%s"; + const char *format = "&objp->%s_u.%s"; + + print_stat (1, &def->def.un.enum_decl); + f_print (fout, "\tswitch (objp->%s) {\n", def->def.un.enum_decl.name); + for (cl = def->def.un.cases; cl != NULL; cl = cl->next) + { + + f_print (fout, "\tcase %s:\n", cl->case_name); + if (cl->contflag == 1) /* a continued case statement */ + continue; + cs = &cl->case_decl; + if (!streq (cs->type, "void")) + { + object = alloc (strlen (def->def_name) + strlen (format) + + strlen (cs->name) + 1); + if (isvectordef (cs->type, cs->rel)) + { + s_print (object, vecformat, def->def_name, + cs->name); + } + else + { + s_print (object, format, def->def_name, + cs->name); + } + print_ifstat (2, cs->prefix, cs->type, cs->rel, cs->array_max, + object, cs->name); + free (object); + } + f_print (fout, "\t\tbreak;\n"); + } + dflt = def->def.un.default_decl; + if (dflt != NULL) + { + if (!streq (dflt->type, "void")) + { + f_print (fout, "\tdefault:\n"); + object = alloc (strlen (def->def_name) + strlen (format) + + strlen (dflt->name) + 1); + if (isvectordef (dflt->type, dflt->rel)) + { + s_print (object, vecformat, def->def_name, + dflt->name); + } + else + { + s_print (object, format, def->def_name, + dflt->name); + } + + print_ifstat (2, dflt->prefix, dflt->type, dflt->rel, + dflt->array_max, object, dflt->name); + free (object); + f_print (fout, "\t\tbreak;\n"); + } + else + { + f_print (fout, "\tdefault:\n"); + f_print (fout, "\t\tbreak;\n"); + } + } + else + { + f_print (fout, "\tdefault:\n"); + f_print (fout, "\t\treturn FALSE;\n"); + } + + f_print (fout, "\t}\n"); +} + +static void +inline_struct (definition *def, int flag) +{ + decl_list *dl; + int i, size; + decl_list *cur = NULL; + decl_list *psav; + bas_type *ptr; + char *sizestr; + const char *plus; + char ptemp[256]; + int indent = 1; + + if (flag == PUT) + f_print (fout, "\n\tif (xdrs->x_op == XDR_ENCODE) {\n"); + else + f_print (fout, + "\t\treturn TRUE;\n\t} else if (xdrs->x_op == XDR_DECODE) {\n"); + + i = 0; + size = 0; + sizestr = NULL; + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + { /* xxx */ + /* now walk down the list and check for basic types */ + if ((dl->decl.prefix == NULL) && + ((ptr = find_type (dl->decl.type)) != NULL) && + ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) + { + if (i == 0) + cur = dl; + ++i; + + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else + { + /* this is required to handle arrays */ + if (sizestr == NULL) + plus = ""; + else + plus = "+ "; + + if (ptr->length != 1) + s_print (ptemp, " %s %s * %d", plus, dl->decl.array_max, + ptr->length); + else + s_print (ptemp, " %s%s ", plus, dl->decl.array_max); + + /*now concatenate to sizestr !!!! */ + if (sizestr == NULL) + sizestr = strdup (ptemp); + else + { + sizestr = realloc (sizestr, strlen (sizestr) + + strlen (ptemp) + 1); + if (sizestr == NULL) + { + f_print (stderr, "Fatal error : no memory \n"); + crash (); + }; + sizestr = strcat (sizestr, ptemp); + /*build up length of array */ + } + } + } + else + { + if (i > 0) + { + if (sizestr == NULL && size < inlineflag) + { + /* don't expand into inline code if size < inlineflag */ + while (cur != dl) + { + print_stat (indent + 1, &cur->decl); + cur = cur->next; + } + } + else + { + /* were already looking at a xdr_inlineable structure */ + tabify (fout, indent + 1); + if (sizestr == NULL) + f_print (fout, "buf = XDR_INLINE (xdrs, %d * BYTES_PER_XDR_UNIT);", size); + else if (size == 0) + f_print (fout, + "buf = XDR_INLINE (xdrs, (%s) * BYTES_PER_XDR_UNIT);", + sizestr); + else + f_print (fout, + "buf = XDR_INLINE (xdrs, (%d + (%s)) * BYTES_PER_XDR_UNIT);", + size, sizestr); + f_print (fout, "\n"); + tabify (fout, indent + 1); + fprintf (fout, "if (buf == NULL) {\n"); + psav = cur; + while (cur != dl) + { + print_stat (indent + 2, &cur->decl); + cur = cur->next; + } + + f_print (fout, "\n\t\t} else {\n"); + cur = psav; + while (cur != dl) + { + emit_inline (indent + 1, &cur->decl, flag); + cur = cur->next; + } + tabify (fout, indent + 1); + f_print (fout, "}\n"); + } + } + size = 0; + i = 0; + free (sizestr); + sizestr = NULL; + print_stat (indent + 1, &dl->decl); + } + } + if (i > 0) + { + if (sizestr == NULL && size < inlineflag) + { + /* don't expand into inline code if size < inlineflag */ + while (cur != dl) + { + print_stat (indent + 1, &cur->decl); + cur = cur->next; + } + } + else + { + /* were already looking at a xdr_inlineable structure */ + if (sizestr == NULL) + f_print (fout, + "\t\tbuf = XDR_INLINE (xdrs, %d * BYTES_PER_XDR_UNIT);", + size); + else if (size == 0) + f_print (fout, + "\t\tbuf = XDR_INLINE (xdrs, (%s) * BYTES_PER_XDR_UNIT);", + sizestr); + else + f_print (fout, + "\t\tbuf = XDR_INLINE (xdrs, (%d + %s)* BYTES_PER_XDR_UNIT);", + size, sizestr); + f_print (fout, "\n\t\tif (buf == NULL) {\n"); + psav = cur; + while (cur != NULL) + { + print_stat (indent + 2, &cur->decl); + cur = cur->next; + } + f_print (fout, "\t\t} else {\n"); + + cur = psav; + while (cur != dl) + { + emit_inline (indent + 2, &cur->decl, flag); + cur = cur->next; + } + f_print (fout, "\t\t}\n"); + } + } +} + +/* this may be const. i haven't traced this one through yet. */ + +static void +emit_struct (definition * def) +{ + decl_list *dl; + int j, size, flag; + bas_type *ptr; + int can_inline; + + + if (inlineflag == 0) + { + /* No xdr_inlining at all */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat (1, &dl->decl); + return; + } + + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + if (dl->decl.rel == REL_VECTOR) + { + f_print (fout, "\tint i;\n"); + break; + } + + size = 0; + can_inline = 0; + /* + * Make a first pass and see if inling is possible. + */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + if ((dl->decl.prefix == NULL) && + ((ptr = find_type (dl->decl.type)) != NULL) && + ((dl->decl.rel == REL_ALIAS) || (dl->decl.rel == REL_VECTOR))) + { + if (dl->decl.rel == REL_ALIAS) + size += ptr->length; + else + { + can_inline = 1; + break; /* can be inlined */ + } + } + else + { + if (size >= inlineflag) + { + can_inline = 1; + break; /* can be inlined */ + } + size = 0; + } + if (size > inlineflag) + can_inline = 1; + + if (can_inline == 0) + { /* can not inline, drop back to old mode */ + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat (1, &dl->decl); + return; + }; + + flag = PUT; + for (j = 0; j < 2; j++) + { + inline_struct (def, flag); + if (flag == PUT) + flag = GET; + } + + f_print (fout, "\t return TRUE;\n\t}\n\n"); + + /* now take care of XDR_FREE case */ + + for (dl = def->def.st.decls; dl != NULL; dl = dl->next) + print_stat (1, &dl->decl); +} + +static void +emit_typedef (const definition * def) +{ + const char *prefix = def->def.ty.old_prefix; + const char *type = def->def.ty.old_type; + const char *amax = def->def.ty.array_max; + relation rel = def->def.ty.rel; + + print_ifstat (1, prefix, type, rel, amax, "objp", def->def_name); +} + +static void +print_stat (int indent, const declaration * dec) +{ + const char *prefix = dec->prefix; + const char *type = dec->type; + const char *amax = dec->array_max; + relation rel = dec->rel; + char name[256]; + + if (isvectordef (type, rel)) + { + s_print (name, "objp->%s", dec->name); + } + else + { + s_print (name, "&objp->%s", dec->name); + } + print_ifstat (indent, prefix, type, rel, amax, name, dec->name); +} + + +static void +emit_inline (int indent, declaration * decl, int flag) +{ + switch (decl->rel) + { + case REL_ALIAS: + emit_single_in_line (indent, decl, flag, REL_ALIAS); + break; + case REL_VECTOR: + tabify (fout, indent); + f_print (fout, "{\n"); + tabify (fout, indent + 1); + f_print (fout, "register %s *genp;\n\n", decl->type); + tabify (fout, indent + 1); + f_print (fout, + "for (i = 0, genp = objp->%s;\n", decl->name); + tabify (fout, indent + 2); + f_print (fout, "i < %s; ++i) {\n", decl->array_max); + emit_single_in_line (indent + 2, decl, flag, REL_VECTOR); + tabify (fout, indent + 1); + f_print (fout, "}\n"); + tabify (fout, indent); + f_print (fout, "}\n"); + break; + default: + break; + /* ?... do nothing I guess */ + } +} + +static void +emit_single_in_line (int indent, declaration *decl, int flag, relation rel) +{ + char *upp_case; + int freed = 0; + + tabify (fout, indent); + if (flag == PUT) + f_print (fout, "IXDR_PUT_"); + else + { + if (rel == REL_ALIAS) + f_print (fout, "objp->%s = IXDR_GET_", decl->name); + else + f_print (fout, "*genp++ = IXDR_GET_"); + } + + upp_case = upcase (decl->type); + + /* hack - XX */ + if (!strcmp (upp_case, "INT")) + { + free (upp_case); + freed = 1; + /* Casting is safe since the `freed' flag is set. */ + upp_case = (char *) "LONG"; + } + + if (!strcmp (upp_case, "U_INT")) + { + free (upp_case); + freed = 1; + /* Casting is safe since the `freed' flag is set. */ + upp_case = (char *) "U_LONG"; + } + + if (flag == PUT) + { + if (rel == REL_ALIAS) + f_print (fout, "%s(buf, objp->%s);\n", upp_case, decl->name); + else + f_print (fout, "%s(buf, *genp++);\n", upp_case); + } + else + { + f_print (fout, "%s(buf);\n", upp_case); + } + + if (!freed) + free (upp_case); +} + + +static char * +upcase (const char *str) +{ + char *ptr, *hptr; + ptr = malloc (strlen (str) + 1); + if (ptr == NULL) + { + f_print (stderr, "malloc failed\n"); + exit (1); + } + hptr = ptr; + while (*str != '\0') + *ptr++ = toupper (*str++); + + *ptr = '\0'; + return hptr; +} diff --git a/REORG.TODO/sunrpc/rpc_dtable.c b/REORG.TODO/sunrpc/rpc_dtable.c new file mode 100644 index 0000000000..7fe48e1811 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_dtable.c @@ -0,0 +1,50 @@ +/* @(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC */ +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <unistd.h> +#include <rpc/clnt.h> +#include <shlib-compat.h> + +/* + * Cache the result of getdtablesize(), so we don't have to do an + * expensive system call every time. + */ +int +_rpc_dtablesize (void) +{ + static int size; + + if (size == 0) + size = __getdtablesize (); + + return size; +} +libc_hidden_nolink_sunrpc (_rpc_dtablesize, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/rpc_gethostbyname.c b/REORG.TODO/sunrpc/rpc_gethostbyname.c new file mode 100644 index 0000000000..98bc1639ca --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_gethostbyname.c @@ -0,0 +1,73 @@ +/* IPv4-only variant of gethostbyname. + Copyright (C) 2016-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1 of the + License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; see the file COPYING.LIB. If + not, see <http://www.gnu.org/licenses/>. */ + +#include <errno.h> +#include <netdb.h> +#include <rpc/rpc.h> +#include <scratch_buffer.h> +#include <string.h> + +int +__libc_rpc_gethostbyname (const char *host, struct sockaddr_in *addr) +{ + struct hostent hostbuf; + struct hostent *hp = NULL; + int herr; + struct scratch_buffer tmpbuf; + scratch_buffer_init (&tmpbuf); + + while (__gethostbyname2_r (host, AF_INET, + &hostbuf, tmpbuf.data, tmpbuf.length, &hp, + &herr) != 0 + || hp == NULL) + if (herr != NETDB_INTERNAL || errno != ERANGE) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_UNKNOWNHOST; + scratch_buffer_free (&tmpbuf); + return -1; + } + else + { + if (!scratch_buffer_grow (&tmpbuf)) + { + /* If memory allocation failed, allocating the RPC error + structure might could as well, so this could lead to a + crash. */ + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = ENOMEM; + return -1; + } + } + + if (hp->h_addrtype != AF_INET || hp->h_length != sizeof (addr->sin_addr)) + { + struct rpc_createerr *ce = &get_rpc_createerr (); + ce->cf_stat = RPC_SYSTEMERROR; + ce->cf_error.re_errno = EAFNOSUPPORT; + scratch_buffer_free (&tmpbuf); + return -1; + } + + addr->sin_family = AF_INET; + addr->sin_port = htons (0); + memcpy (&addr->sin_addr, hp->h_addr, sizeof (addr->sin_addr)); + scratch_buffer_free (&tmpbuf); + return 0; +} diff --git a/REORG.TODO/sunrpc/rpc_hout.c b/REORG.TODO/sunrpc/rpc_hout.c new file mode 100644 index 0000000000..10f793d233 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_hout.c @@ -0,0 +1,607 @@ +/* + * From: @(#)rpc_hout.c 1.12 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_hout.c, Header file outputter for the RPC protocol compiler + */ +#include <stdio.h> +#include <ctype.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +static void pconstdef (definition * def); +static void pargdef (definition * def); +static void pstructdef (definition * def); +static void puniondef (definition * def); +static void pdefine (const char *name, const char *num); +static int define_printed (proc_list * stop, version_list * start); +static void pprogramdef (definition * def); +static void parglist (proc_list * proc, const char *addargtype); +static void penumdef (definition * def); +static void ptypedef (definition * def); +static int undefined2 (const char *type, const char *stop); + +/* store away enough information to allow the XDR functions to be spat + out at the end of the file */ + +static void +storexdrfuncdecl (const char *name, int pointerp) +{ + xdrfunc * xdrptr; + + xdrptr = (xdrfunc *) malloc(sizeof (struct xdrfunc)); + + xdrptr->name = (char *)name; + xdrptr->pointerp = pointerp; + xdrptr->next = NULL; + + if (xdrfunc_tail == NULL) + { + xdrfunc_head = xdrptr; + xdrfunc_tail = xdrptr; + } + else + { + xdrfunc_tail->next = xdrptr; + xdrfunc_tail = xdrptr; + } +} + +/* + * Print the C-version of an xdr definition + */ +void +print_datadef (definition *def) +{ + + if (def->def_kind == DEF_PROGRAM) /* handle data only */ + return; + + if (def->def_kind != DEF_CONST) + { + f_print (fout, "\n"); + } + switch (def->def_kind) + { + case DEF_STRUCT: + pstructdef (def); + break; + case DEF_UNION: + puniondef (def); + break; + case DEF_ENUM: + penumdef (def); + break; + case DEF_TYPEDEF: + ptypedef (def); + break; + case DEF_PROGRAM: + pprogramdef (def); + break; + case DEF_CONST: + pconstdef (def); + break; + } + if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) + { + storexdrfuncdecl(def->def_name, + def->def_kind != DEF_TYPEDEF || + !isvectordef(def->def.ty.old_type, + def->def.ty.rel)); + } +} + + +void +print_funcdef (definition *def) +{ + switch (def->def_kind) + { + case DEF_PROGRAM: + f_print (fout, "\n"); + pprogramdef (def); + break; + default: + break; + /* ?... shouldn't happen I guess */ + } +} + +void +print_xdr_func_def (char *name, int pointerp, int i) +{ + if (i == 2) + { + f_print (fout, "extern bool_t xdr_%s ();\n", name); + return; + } + else + f_print(fout, "extern bool_t xdr_%s (XDR *, %s%s);\n", name, + name, pointerp ? "*" : ""); +} + +static void +pconstdef (definition *def) +{ + pdefine (def->def_name, def->def.co); +} + +/* print out the definitions for the arguments of functions in the + header file + */ +static void +pargdef (definition * def) +{ + decl_list *l; + version_list *vers; + const char *name; + proc_list *plist; + + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) + { + for (plist = vers->procs; plist != NULL; + plist = plist->next) + { + + if (!newstyle || plist->arg_num < 2) + { + continue; /* old style or single args */ + } + name = plist->args.argname; + f_print (fout, "struct %s {\n", name); + for (l = plist->args.decls; + l != NULL; l = l->next) + { + pdeclaration (name, &l->decl, 1, ";\n"); + } + f_print (fout, "};\n"); + f_print (fout, "typedef struct %s %s;\n", name, name); + storexdrfuncdecl (name, 1); + f_print (fout, "\n"); + } + } + +} + +static void +pstructdef (definition *def) +{ + decl_list *l; + const char *name = def->def_name; + + f_print (fout, "struct %s {\n", name); + for (l = def->def.st.decls; l != NULL; l = l->next) + { + pdeclaration (name, &l->decl, 1, ";\n"); + } + f_print (fout, "};\n"); + f_print (fout, "typedef struct %s %s;\n", name, name); +} + +static void +puniondef (definition *def) +{ + case_list *l; + const char *name = def->def_name; + declaration *decl; + + f_print (fout, "struct %s {\n", name); + decl = &def->def.un.enum_decl; + if (streq (decl->type, "bool")) + { + f_print (fout, "\tbool_t %s;\n", decl->name); + } + else + { + f_print (fout, "\t%s %s;\n", decl->type, decl->name); + } + f_print (fout, "\tunion {\n"); + for (l = def->def.un.cases; l != NULL; l = l->next) + { + if (l->contflag == 0) + pdeclaration (name, &l->case_decl, 2, ";\n"); + } + decl = def->def.un.default_decl; + if (decl && !streq (decl->type, "void")) + { + pdeclaration (name, decl, 2, ";\n"); + } + f_print (fout, "\t} %s_u;\n", name); + f_print (fout, "};\n"); + f_print (fout, "typedef struct %s %s;\n", name, name); +} + +static void +pdefine (const char *name, const char *num) +{ + f_print (fout, "#define %s %s\n", name, num); +} + +static int +define_printed (proc_list *stop, version_list *start) +{ + version_list *vers; + proc_list *proc; + + for (vers = start; vers != NULL; vers = vers->next) + { + for (proc = vers->procs; proc != NULL; proc = proc->next) + { + if (proc == stop) + { + return 0; + } + else if (streq (proc->proc_name, stop->proc_name)) + { + return 1; + } + } + } + abort (); + /* NOTREACHED */ +} + +static void +pfreeprocdef (const char *name, const char *vers, int mode) +{ + f_print (fout, "extern int "); + pvname (name, vers); + if (mode == 1) + f_print (fout,"_freeresult (SVCXPRT *, xdrproc_t, caddr_t);\n"); + else + f_print (fout,"_freeresult ();\n"); +} + +static void +pprogramdef (definition *def) +{ + version_list *vers; + proc_list *proc; + int i; + const char *ext; + + pargdef (def); + + pdefine (def->def_name, def->def.pr.prog_num); + for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) + { + if (tblflag) + { + f_print (fout, "extern struct rpcgen_table %s_%s_table[];\n", + locase (def->def_name), vers->vers_num); + f_print (fout, "extern %s_%s_nproc;\n", + locase (def->def_name), vers->vers_num); + } + pdefine (vers->vers_name, vers->vers_num); + + /* + * Print out 2 definitions, one for ANSI-C, another for + * old K & R C + */ + + if(!Cflag) + { + ext = "extern "; + for (proc = vers->procs; proc != NULL; + proc = proc->next) + { + if (!define_printed(proc, def->def.pr.versions)) + { + pdefine (proc->proc_name, proc->proc_num); + } + f_print (fout, "%s", ext); + pprocdef (proc, vers, NULL, 0, 2); + + if (mtflag) + { + f_print(fout, "%s", ext); + pprocdef (proc, vers, NULL, 1, 2); + } + } + pfreeprocdef (def->def_name, vers->vers_num, 2); + } + else + { + for (i = 1; i < 3; i++) + { + if (i == 1) + { + f_print (fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); + ext = "extern "; + } + else + { + f_print (fout, "\n#else /* K&R C */\n"); + ext = "extern "; + } + + for (proc = vers->procs; proc != NULL; proc = proc->next) + { + if (!define_printed(proc, def->def.pr.versions)) + { + pdefine(proc->proc_name, proc->proc_num); + } + f_print (fout, "%s", ext); + pprocdef (proc, vers, "CLIENT *", 0, i); + f_print (fout, "%s", ext); + pprocdef (proc, vers, "struct svc_req *", 1, i); + } + pfreeprocdef (def->def_name, vers->vers_num, i); + } + f_print (fout, "#endif /* K&R C */\n"); + } + } +} + +void +pprocdef (proc_list * proc, version_list * vp, + const char *addargtype, int server_p, int mode) +{ + if (mtflag) + {/* Print MT style stubs */ + if (server_p) + f_print (fout, "bool_t "); + else + f_print (fout, "enum clnt_stat "); + } + else + { + ptype (proc->res_prefix, proc->res_type, 1); + f_print (fout, "* "); + } + if (server_p) + pvname_svc (proc->proc_name, vp->vers_num); + else + pvname (proc->proc_name, vp->vers_num); + + /* + * mode 1 = ANSI-C, mode 2 = K&R C + */ + if (mode == 1) + parglist (proc, addargtype); + else + f_print (fout, "();\n"); +} + +/* print out argument list of procedure */ +static void +parglist (proc_list *proc, const char *addargtype) +{ + decl_list *dl; + + f_print(fout,"("); + if (proc->arg_num < 2 && newstyle && + streq (proc->args.decls->decl.type, "void")) + { + /* 0 argument in new style: do nothing */ + } + else + { + for (dl = proc->args.decls; dl != NULL; dl = dl->next) + { + ptype (dl->decl.prefix, dl->decl.type, 1); + if (!newstyle) + f_print (fout, "*"); /* old style passes by reference */ + + f_print (fout, ", "); + } + } + if (mtflag) + { + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*, "); + } + + f_print (fout, "%s);\n", addargtype); +} + +static void +penumdef (definition *def) +{ + const char *name = def->def_name; + enumval_list *l; + const char *last = NULL; + int count = 0; + + f_print (fout, "enum %s {\n", name); + for (l = def->def.en.vals; l != NULL; l = l->next) + { + f_print (fout, "\t%s", l->name); + if (l->assignment) + { + f_print (fout, " = %s", l->assignment); + last = l->assignment; + count = 1; + } + else + { + if (last == NULL) + { + f_print (fout, " = %d", count++); + } + else + { + f_print (fout, " = %s + %d", last, count++); + } + } + f_print (fout, ",\n"); + } + f_print (fout, "};\n"); + f_print (fout, "typedef enum %s %s;\n", name, name); +} + +static void +ptypedef (definition *def) +{ + const char *name = def->def_name; + const char *old = def->def.ty.old_type; + char prefix[8]; /* enough to contain "struct ", including NUL */ + relation rel = def->def.ty.rel; + + if (!streq (name, old)) + { + if (streq (old, "string")) + { + old = "char"; + rel = REL_POINTER; + } + else if (streq (old, "opaque")) + { + old = "char"; + } + else if (streq (old, "bool")) + { + old = "bool_t"; + } + if (undefined2 (old, name) && def->def.ty.old_prefix) + { + s_print (prefix, "%s ", def->def.ty.old_prefix); + } + else + { + prefix[0] = 0; + } + f_print (fout, "typedef "); + switch (rel) + { + case REL_ARRAY: + f_print (fout, "struct {\n"); + f_print (fout, "\tu_int %s_len;\n", name); + f_print (fout, "\t%s%s *%s_val;\n", prefix, old, name); + f_print (fout, "} %s", name); + break; + case REL_POINTER: + f_print (fout, "%s%s *%s", prefix, old, name); + break; + case REL_VECTOR: + f_print (fout, "%s%s %s[%s]", prefix, old, name, + def->def.ty.array_max); + break; + case REL_ALIAS: + f_print (fout, "%s%s %s", prefix, old, name); + break; + } + f_print (fout, ";\n"); + } +} + +void +pdeclaration (const char *name, declaration * dec, int tab, + const char *separator) +{ + char buf[8]; /* enough to hold "struct ", include NUL */ + const char *prefix; + const char *type; + + if (streq (dec->type, "void")) + { + return; + } + tabify (fout, tab); + if (streq (dec->type, name) && !dec->prefix) + { + f_print (fout, "struct "); + } + if (streq (dec->type, "string")) + { + f_print (fout, "char *%s", dec->name); + } + else + { + prefix = ""; + if (streq (dec->type, "bool")) + { + type = "bool_t"; + } + else if (streq (dec->type, "opaque")) + { + type = "char"; + } + else + { + if (dec->prefix) + { + s_print (buf, "%s ", dec->prefix); + prefix = buf; + } + type = dec->type; + } + switch (dec->rel) + { + case REL_ALIAS: + f_print (fout, "%s%s %s", prefix, type, dec->name); + break; + case REL_VECTOR: + f_print (fout, "%s%s %s[%s]", prefix, type, dec->name, + dec->array_max); + break; + case REL_POINTER: + f_print (fout, "%s%s *%s", prefix, type, dec->name); + break; + case REL_ARRAY: + f_print (fout, "struct {\n"); + tabify (fout, tab); + f_print (fout, "\tu_int %s_len;\n", dec->name); + tabify (fout, tab); + f_print (fout, "\t%s%s *%s_val;\n", prefix, type, dec->name); + tabify (fout, tab); + f_print (fout, "} %s", dec->name); + break; + } + } + f_print (fout, "%s", separator); +} + +static int +undefined2 (const char *type, const char *stop) +{ + list *l; + definition *def; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + if (streq (def->def_name, stop)) + { + return 1; + } + else if (streq (def->def_name, type)) + { + return 0; + } + } + } + return 1; +} diff --git a/REORG.TODO/sunrpc/rpc_main.c b/REORG.TODO/sunrpc/rpc_main.c new file mode 100644 index 0000000000..f94bc91546 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_main.c @@ -0,0 +1,1460 @@ +/* + * From @(#)rpc_main.c 1.30 89/03/30 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_main.c, Top level of the RPC protocol compiler. + */ + +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <libintl.h> +#include <locale.h> +#include <ctype.h> +#include <sys/types.h> +#include <sys/param.h> +#include <sys/file.h> +#include <sys/stat.h> +#include <sys/wait.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "rpc_scan.h" +#include "proto.h" + +#include "../version.h" +#define PACKAGE _libc_intl_domainname + +#define EXTEND 1 /* alias for TRUE */ +#define DONT_EXTEND 0 /* alias for FALSE */ + +struct commandline + { + int cflag; /* xdr C routines */ + int hflag; /* header file */ + int lflag; /* client side stubs */ + int mflag; /* server side stubs */ + int nflag; /* netid flag */ + int sflag; /* server stubs for the given transport */ + int tflag; /* dispatch Table file */ + int Ssflag; /* produce server sample code */ + int Scflag; /* produce client sample code */ + int makefileflag; /* Generate a template Makefile */ + const char *infile; /* input module name */ + const char *outfile; /* output module name */ + }; + + +static const char *cmdname; + +static const char *svcclosetime = "120"; +static int cppDefined; /* explicit path for C preprocessor */ +static const char *CPP = "/lib/cpp"; +static const char CPPFLAGS[] = "-C"; +static char *pathbuf; +static int cpp_pid; +static const char *allv[] = +{ + "rpcgen", "-s", "udp", "-s", "tcp" +}; +static int allc = sizeof (allv) / sizeof (allv[0]); +static const char *allnv[] = +{ + "rpcgen", "-s", "netpath", +}; +static int allnc = sizeof (allnv) / sizeof (allnv[0]); + +/* + * machinations for handling expanding argument list + */ +static void addarg (const char *); /* add another argument to the list */ +static void putarg (int, const char *); /* put argument at specified location */ +static void clear_args (void); /* clear argument list */ +static void checkfiles (const char *, const char *); + /* check if out file already exists */ + +static void clear_args (void); +static char *extendfile (const char *file, const char *ext); +static void open_output (const char *infile, const char *outfile); +static void add_warning (void); +static void clear_args (void); +static void find_cpp (void); +static void open_input (const char *infile, const char *define); +static int check_nettype (const char *name, const char *list_to_check[]); +static void c_output (const char *infile, const char *define, + int extend, const char *outfile); +static void h_output (const char *infile, const char *define, + int extend, const char *outfile); +static void s_output (int argc, const char *argv[], const char *infile, + const char *define, int extend, + const char *outfile, int nomain, int netflag); +static void l_output (const char *infile, const char *define, + int extend, const char *outfile); +static void t_output (const char *infile, const char *define, + int extend, const char *outfile); +static void svc_output (const char *infile, const char *define, + int extend, const char *outfile); +static void clnt_output (const char *infile, const char *define, + int extend, const char *outfile); +static void mkfile_output (struct commandline *cmd); +static int do_registers (int argc, const char *argv[]); +static void addarg (const char *cp); +static void putarg (int whereto, const char *cp); +static void checkfiles (const char *infile, const char *outfile); +static int parseargs (int argc, const char *argv[], struct commandline *cmd); +static void usage (FILE *stream, int status) __attribute__ ((noreturn)); +static void options_usage (FILE *stream, int status) __attribute__ ((noreturn)); +static void print_version (void); +static void c_initialize (void); +static char *generate_guard (const char *pathname); + + +#define ARGLISTLEN 20 +#define FIXEDARGS 2 + +static const char *arglist[ARGLISTLEN]; +static int argcount = FIXEDARGS; + + +int nonfatalerrors; /* errors */ +int inetdflag /* = 1 */ ; /* Support for inetd *//* is now the default */ +int pmflag; /* Support for port monitors */ +int logflag; /* Use syslog instead of fprintf for errors */ +int tblflag; /* Support for dispatch table file */ +int mtflag; /* Support for MT */ + +#define INLINE 3 +/*length at which to start doing an inline */ + +int inlineflag = INLINE; /* length at which to start doing an inline. 3 = default + if 0, no xdr_inline code */ + +int indefinitewait; /* If started by port monitors, hang till it wants */ +int exitnow; /* If started by port monitors, exit after the call */ +int timerflag; /* TRUE if !indefinite && !exitnow */ +int newstyle; /* newstyle of passing arguments (by value) */ +int Cflag = 1; /* ANSI C syntax */ +int CCflag; /* C++ files */ +static int allfiles; /* generate all files */ +int tirpcflag; /* generating code for tirpc, by default */ +xdrfunc *xdrfunc_head; /* xdr function list */ +xdrfunc *xdrfunc_tail; /* xdr function list */ + +int +main (int argc, const char *argv[]) +{ + struct commandline cmd; + + setlocale (LC_ALL, ""); + textdomain (_libc_intl_domainname); + + (void) memset ((char *) &cmd, 0, sizeof (struct commandline)); + clear_args (); + if (!parseargs (argc, argv, &cmd)) + usage (stderr, 1); + + if (cmd.cflag || cmd.hflag || cmd.lflag || cmd.tflag || cmd.sflag || + cmd.mflag || cmd.nflag || cmd.Ssflag || cmd.Scflag) + { + checkfiles (cmd.infile, cmd.outfile); + } + else + checkfiles (cmd.infile, NULL); + + if (cmd.cflag) + c_output (cmd.infile, "-DRPC_XDR", DONT_EXTEND, cmd.outfile); + else if (cmd.hflag) + h_output (cmd.infile, "-DRPC_HDR", DONT_EXTEND, cmd.outfile); + else if (cmd.lflag) + l_output (cmd.infile, "-DRPC_CLNT", DONT_EXTEND, cmd.outfile); + else if (cmd.sflag || cmd.mflag || (cmd.nflag)) + s_output (argc, argv, cmd.infile, "-DRPC_SVC", DONT_EXTEND, + cmd.outfile, cmd.mflag, cmd.nflag); + else if (cmd.tflag) + t_output (cmd.infile, "-DRPC_TBL", DONT_EXTEND, cmd.outfile); + else if (cmd.Ssflag) + svc_output (cmd.infile, "-DRPC_SERVER", DONT_EXTEND, cmd.outfile); + else if (cmd.Scflag) + clnt_output (cmd.infile, "-DRPC_CLIENT", DONT_EXTEND, cmd.outfile); + else if (cmd.makefileflag) + mkfile_output (&cmd); + else + { + /* the rescans are required, since cpp may effect input */ + c_output (cmd.infile, "-DRPC_XDR", EXTEND, "_xdr.c"); + reinitialize (); + h_output (cmd.infile, "-DRPC_HDR", EXTEND, ".h"); + reinitialize (); + l_output (cmd.infile, "-DRPC_CLNT", EXTEND, "_clnt.c"); + reinitialize (); + if (inetdflag || !tirpcflag) + s_output (allc, allv, cmd.infile, "-DRPC_SVC", EXTEND, + "_svc.c", cmd.mflag, cmd.nflag); + else + s_output (allnc, allnv, cmd.infile, "-DRPC_SVC", + EXTEND, "_svc.c", cmd.mflag, cmd.nflag); + if (tblflag) + { + reinitialize (); + t_output (cmd.infile, "-DRPC_TBL", EXTEND, "_tbl.i"); + } + if (allfiles) + { + reinitialize (); + svc_output (cmd.infile, "-DRPC_SERVER", EXTEND, "_server.c"); + reinitialize (); + clnt_output (cmd.infile, "-DRPC_CLIENT", EXTEND, "_client.c"); + } + if (allfiles || (cmd.makefileflag == 1)) + { + reinitialize (); + mkfile_output (&cmd); + } + } + + return nonfatalerrors; +} + +/* + * add extension to filename + */ +static char * +extendfile (const char *file, const char *ext) +{ + char *res; + const char *p; + + res = alloc (strlen (file) + strlen (ext) + 1); + if (res == NULL) + abort (); + p = strrchr (file, '.'); + if (p == NULL) + p = file + strlen (file); + strcpy (res, file); + strcpy (res + (p - file), ext); + return res; +} + +/* + * Open output file with given extension + */ +static void +open_output (const char *infile, const char *outfile) +{ + if (outfile == NULL) + { + fout = stdout; + return; + } + + if (infile != NULL && streq (outfile, infile)) + { + fprintf (stderr, _ ("%s: output would overwrite %s\n"), cmdname, + infile); + crash (); + } + fout = fopen (outfile, "w"); + if (fout == NULL) + { + fprintf (stderr, _ ("%s: unable to open %s: %m\n"), cmdname, outfile); + crash (); + } + record_open (outfile); +} + +/* Close the output file and check for write errors. */ +static void +close_output (const char *outfile) +{ + if (fclose (fout) == EOF) + { + fprintf (stderr, _("%s: while writing output %s: %m"), cmdname, + outfile ?: "<stdout>"); + crash (); + } +} + +static void +add_warning (void) +{ + fprintf (fout, "/*\n"); + fprintf (fout, " * Please do not edit this file.\n"); + fprintf (fout, " * It was generated using rpcgen.\n"); + fprintf (fout, " */\n\n"); +} + +/* clear list of arguments */ +static void +clear_args (void) +{ + int i; + for (i = FIXEDARGS; i < ARGLISTLEN; ++i) + arglist[i] = NULL; + argcount = FIXEDARGS; +} + +/* make sure that a CPP exists */ +static void +find_cpp (void) +{ + struct stat64 buf; + + if (stat64 (CPP, &buf) == 0) + return; + + if (cppDefined) /* user specified cpp but it does not exist */ + { + fprintf (stderr, _ ("cannot find C preprocessor: %s\n"), CPP); + crash (); + } + + /* fall back to system CPP */ + CPP = "cpp"; +} + +/* + * Open input file with given define for C-preprocessor + */ +static void +open_input (const char *infile, const char *define) +{ + int pd[2]; + + infilename = (infile == NULL) ? "<stdin>" : infile; + if (pipe (pd) != 0) + { + perror ("pipe"); + exit (1); + } + cpp_pid = fork (); + switch (cpp_pid) + { + case 0: + find_cpp (); + putarg (0, CPP); + putarg (1, CPPFLAGS); + addarg (define); + if (infile) + addarg (infile); + addarg ((char *) NULL); + close (1); + dup2 (pd[1], 1); + close (pd[0]); + execvp (arglist[0], (char **) arglist); + if (errno == ENOENT) + { + fprintf (stderr, _ ("cannot find C preprocessor: %s\n"), CPP); + exit (1); + } + perror ("execvp"); + exit (1); + case -1: + perror ("fork"); + exit (1); + } + close (pd[1]); + fin = fdopen (pd[0], "r"); + if (fin == NULL) + { + fprintf (stderr, "%s: ", cmdname); + perror (infilename); + crash (); + } +} + +/* Close the connection to the C-preprocessor and check for successfull + termination. */ +static void +close_input (void) +{ + int status; + + fclose (fin); + /* Check the termination status. */ + if (waitpid (cpp_pid, &status, 0) < 0) + { + perror ("waitpid"); + crash (); + } + if (WIFSIGNALED (status) || WEXITSTATUS (status) != 0) + { + if (WIFSIGNALED (status)) + fprintf (stderr, _("%s: C preprocessor failed with signal %d\n"), + cmdname, WTERMSIG (status)); + else + fprintf (stderr, _("%s: C preprocessor failed with exit code %d\n"), + cmdname, WEXITSTATUS (status)); + crash (); + } +} + +/* valid tirpc nettypes */ +static const char *valid_ti_nettypes[] = +{ + "netpath", + "visible", + "circuit_v", + "datagram_v", + "circuit_n", + "datagram_n", + "udp", + "tcp", + "raw", + NULL +}; + +/* valid inetd nettypes */ +static const char *valid_i_nettypes[] = +{ + "udp", + "tcp", + NULL +}; + +static int +check_nettype (const char *name, const char *list_to_check[]) +{ + int i; + for (i = 0; list_to_check[i] != NULL; i++) + { + if (strcmp (name, list_to_check[i]) == 0) + { + return 1; + } + } + fprintf (stderr, _ ("illegal nettype: `%s'\n"), name); + return 0; +} + +/* + * Compile into an XDR routine output file + */ + +static void +c_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + char *include; + const char *outfilename; + long tell; + + c_initialize (); + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + /* .h file already contains rpc/rpc.h */ + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + tell = ftell (fout); + while ((def = get_definition ()) != NULL) + emit (def); + + if (extend && tell == ftell (fout)) + unlink (outfilename); + close_input (); + close_output (outfilename); +} + +void +c_initialize (void) +{ + + /* add all the starting basic types */ + + add_type (1, "int"); + add_type (1, "long"); + add_type (1, "short"); + add_type (1, "bool"); + + add_type (1, "u_int"); + add_type (1, "u_long"); + add_type (1, "u_short"); + +} + +char rpcgen_table_dcl[] = "struct rpcgen_table {\n\ + char *(*proc)();\n\ + xdrproc_t xdr_arg;\n\ + unsigned len_arg;\n\ + xdrproc_t xdr_res;\n\ + unsigned len_res;\n\ +};\n"; + + +static char * +generate_guard (const char *pathname) +{ + const char *filename; + char *guard, *tmp; + + filename = strrchr (pathname, '/'); /* find last component */ + filename = ((filename == NULL) ? pathname : filename + 1); + guard = extendfile (filename, "_H_RPCGEN"); + /* convert to upper case */ + tmp = guard; + while (*tmp) + { + if (islower (*tmp)) + *tmp = toupper (*tmp); + tmp++; + } + + return guard; +} + +/* + * Compile into an XDR header file + */ + + +static void +h_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + xdrfunc *xdrfuncp; + definition *def; + const char *ifilename; + const char *outfilename; + long tell; + char *guard; + list *l; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + ifilename = (infile == NULL) ? "STDIN" : infile; + guard = generate_guard (outfilename ? outfilename : ifilename); + + fprintf (fout, "#ifndef _%s\n#define _%s\n\n", guard, + guard); + + fprintf (fout, "#include <rpc/rpc.h>\n\n"); + + if (mtflag) + { + fprintf (fout, "#include <pthread.h>\n"); + } + + /* put the C++ support */ + if (Cflag && !CCflag) + { + fprintf (fout, "\n#ifdef __cplusplus\n"); + fprintf (fout, "extern \"C\" {\n"); + fprintf (fout, "#endif\n\n"); + } + + tell = ftell (fout); + /* print data definitions */ + while ((def = get_definition ()) != NULL) + { + print_datadef (def); + } + + /* print function declarations. + Do this after data definitions because they might be used as + arguments for functions */ + for (l = defined; l != NULL; l = l->next) + { + print_funcdef (l->val); + } + /* Now print all xdr func declarations */ + if (xdrfunc_head != NULL) + { + fprintf (fout, "\n/* the xdr functions */\n"); + if (CCflag) + { + fprintf (fout, "\n#ifdef __cplusplus\n"); + fprintf (fout, "extern \"C\" {\n"); + fprintf (fout, "#endif\n"); + } + if (!Cflag) + { + xdrfuncp = xdrfunc_head; + while (xdrfuncp != NULL) + { + print_xdr_func_def (xdrfuncp->name, + xdrfuncp->pointerp, 2); + xdrfuncp = xdrfuncp->next; + } + } + else + { + int i; + + for (i = 1; i < 3; ++i) + { + if (i == 1) + fprintf (fout, "\n#if defined(__STDC__) || defined(__cplusplus)\n"); + else + fprintf (fout, "\n#else /* K&R C */\n"); + + xdrfuncp = xdrfunc_head; + while (xdrfuncp != NULL) + { + print_xdr_func_def (xdrfuncp->name, + xdrfuncp->pointerp, i); + xdrfuncp = xdrfuncp->next; + } + } + fprintf (fout, "\n#endif /* K&R C */\n"); + } + } + + if (extend && tell == ftell (fout)) + { + unlink (outfilename); + } + else if (tblflag) + { + fprintf (fout, "%s", rpcgen_table_dcl); + } + + if (Cflag) + { + fprintf (fout, "\n#ifdef __cplusplus\n"); + fprintf (fout, "}\n"); + fprintf (fout, "#endif\n"); + } + + fprintf (fout, "\n#endif /* !_%s */\n", guard); + free (guard); + close_input (); + close_output (outfilename); +} + +/* + * Compile into an RPC service + */ +static void +s_output (int argc, const char *argv[], const char *infile, const char *define, + int extend, const char *outfile, int nomain, int netflag) +{ + char *include; + definition *def; + int foundprogram = 0; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + + fprintf (fout, "#include <stdio.h>\n"); + fprintf (fout, "#include <stdlib.h>\n"); + fprintf (fout, "#include <rpc/pmap_clnt.h>\n"); + if (Cflag) + fprintf (fout, "#include <string.h>\n"); + if (strcmp (svcclosetime, "-1") == 0) + indefinitewait = 1; + else if (strcmp (svcclosetime, "0") == 0) + exitnow = 1; + else if (inetdflag || pmflag) + { + fprintf (fout, "#include <signal.h>\n"); + timerflag = 1; + } + + if (!tirpcflag && inetdflag) + fprintf (fout, "#include <sys/ioctl.h> /* ioctl, TIOCNOTTY */\n"); + if (Cflag && (inetdflag || pmflag)) + { + fprintf (fout, "#include <sys/types.h> /* open */\n"); + fprintf (fout, "#include <sys/stat.h> /* open */\n"); + fprintf (fout, "#include <fcntl.h> /* open */\n"); + fprintf (fout, "#include <unistd.h> /* getdtablesize */\n"); + } + if (tirpcflag && !(Cflag && (inetdflag || pmflag))) + fprintf (fout, "#include <sys/types.h>\n"); + + fprintf (fout, "#include <memory.h>\n"); + if (inetdflag || !tirpcflag) + { + fprintf (fout, "#include <sys/socket.h>\n"); + fprintf (fout, "#include <netinet/in.h>\n"); + } + + if ((netflag || pmflag) && tirpcflag && !nomain) + { + fprintf (fout, "#include <netconfig.h>\n"); + } + if ( /*timerflag && */ tirpcflag) + fprintf (fout, "#include <sys/resource.h> /* rlimit */\n"); + if (logflag || inetdflag || pmflag) + { + fprintf (fout, "#include <syslog.h>\n"); + } + + /* for ANSI-C */ + if (Cflag) + fprintf (fout, "\n#ifndef SIG_PF\n#define SIG_PF void(*)(int)\n#endif\n"); + + if (timerflag) + fprintf (fout, "\n#define _RPCSVC_CLOSEDOWN %s\n", svcclosetime); + while ((def = get_definition ()) != NULL) + { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) + { + unlink (outfilename); + return; + } + write_most (infile, netflag, nomain); + if (!nomain) + { + if (!do_registers (argc, argv)) + { + if (outfilename) + unlink (outfilename); + usage (stderr, 1); + } + write_rest (); + } + close_input (); + close_output (outfilename); +} + +/* + * generate client side stubs + */ +static void +l_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + char *include; + definition *def; + int foundprogram = 0; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + if (Cflag) + fprintf (fout, "#include <memory.h> /* for memset */\n"); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + while ((def = get_definition ()) != NULL) + { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) + { + unlink (outfilename); + return; + } + write_stubs (); + close_input (); + close_output (outfilename); +} + +/* + * generate the dispatch table + */ +static void +t_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + int foundprogram = 0; + const char *outfilename; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + open_output (infile, outfilename); + add_warning (); + while ((def = get_definition ()) != NULL) + { + foundprogram |= (def->def_kind == DEF_PROGRAM); + } + if (extend && !foundprogram) + { + unlink (outfilename); + return; + } + write_tables (); + close_input (); + close_output (outfilename); +} + +/* sample routine for the server template */ +static void +svc_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + char *include; + const char *outfilename; + long tell; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + checkfiles (infile, outfilename); + /*check if outfile already exists. + if so, print an error message and exit */ + open_output (infile, outfilename); + add_sample_msg (); + + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + + tell = ftell (fout); + while ((def = get_definition ()) != NULL) + { + write_sample_svc (def); + } + if (extend && tell == ftell (fout)) + { + unlink (outfilename); + } + close_input (); + close_output (outfilename); +} + + +/* sample main routine for client */ +static void +clnt_output (const char *infile, const char *define, int extend, + const char *outfile) +{ + definition *def; + char *include; + const char *outfilename; + long tell; + int has_program = 0; + + open_input (infile, define); + outfilename = extend ? extendfile (infile, outfile) : outfile; + checkfiles (infile, outfilename); + /*check if outfile already exists. + if so, print an error message and exit */ + + open_output (infile, outfilename); + add_sample_msg (); + if (infile && (include = extendfile (infile, ".h"))) + { + fprintf (fout, "#include \"%s\"\n", include); + free (include); + } + else + fprintf (fout, "#include <rpc/rpc.h>\n"); + tell = ftell (fout); + while ((def = get_definition ()) != NULL) + { + has_program += write_sample_clnt (def); + } + + if (has_program) + write_sample_clnt_main (); + + if (extend && tell == ftell (fout)) + { + unlink (outfilename); + } + close_input (); + close_output (outfilename); +} + +static const char space[] = " "; + +static char * +file_name (const char *file, const char *ext) +{ + char *temp; + temp = extendfile (file, ext); + + if (access (temp, F_OK) != -1) + return (temp); + + free (temp); + return (char *) space; +} + +static void +mkfile_output (struct commandline *cmd) +{ + char *mkfilename; + char *clientname, *clntname, *xdrname, *hdrname; + char *servername, *svcname, *servprogname, *clntprogname; + + svcname = file_name (cmd->infile, "_svc.c"); + clntname = file_name (cmd->infile, "_clnt.c"); + xdrname = file_name (cmd->infile, "_xdr.c"); + hdrname = file_name (cmd->infile, ".h"); + + if (allfiles) + { + servername = extendfile (cmd->infile, "_server.c"); + clientname = extendfile (cmd->infile, "_client.c"); + } + else + { + servername = (char *) space; + clientname = (char *) space; + } + servprogname = extendfile (cmd->infile, "_server"); + clntprogname = extendfile (cmd->infile, "_client"); + + if (allfiles) + { + char *cp, *temp; + + mkfilename = alloc (strlen ("Makefile.") + strlen (cmd->infile) + 1); + if (mkfilename == NULL) + abort (); + temp = strrchr (cmd->infile, '.'); + cp = stpcpy (mkfilename, "Makefile."); + if (temp != NULL) + *((char *) stpncpy (cp, cmd->infile, temp - cmd->infile)) = '\0'; + else + stpcpy (cp, cmd->infile); + + } + else + mkfilename = (char *) cmd->outfile; + + checkfiles (NULL, mkfilename); + open_output (NULL, mkfilename); + + fprintf (fout, "\n# This is a template Makefile generated by rpcgen\n"); + + f_print (fout, "\n# Parameters\n\n"); + + f_print (fout, "CLIENT = %s\nSERVER = %s\n\n", clntprogname, servprogname); + f_print (fout, "SOURCES_CLNT.c = \nSOURCES_CLNT.h = \n"); + f_print (fout, "SOURCES_SVC.c = \nSOURCES_SVC.h = \n"); + f_print (fout, "SOURCES.x = %s\n\n", cmd->infile); + f_print (fout, "TARGETS_SVC.c = %s %s %s \n", + svcname, servername, xdrname); + f_print (fout, "TARGETS_CLNT.c = %s %s %s \n", + clntname, clientname, xdrname); + f_print (fout, "TARGETS = %s %s %s %s %s %s\n\n", + hdrname, xdrname, clntname, + svcname, clientname, servername); + + f_print (fout, "OBJECTS_CLNT = $(SOURCES_CLNT.c:%%.c=%%.o) \ +$(TARGETS_CLNT.c:%%.c=%%.o)"); + + f_print (fout, "\nOBJECTS_SVC = $(SOURCES_SVC.c:%%.c=%%.o) \ +$(TARGETS_SVC.c:%%.c=%%.o)"); + + f_print (fout, "\n# Compiler flags \n"); + if (mtflag) + fprintf (fout, "\nCPPFLAGS += -D_REENTRANT\nCFLAGS += -g \nLDLIBS \ ++= -lnsl -lpthread \n "); + else + f_print (fout, "\nCFLAGS += -g \nLDLIBS += -lnsl\n"); + f_print (fout, "RPCGENFLAGS = \n"); + + f_print (fout, "\n# Targets \n\n"); + + f_print (fout, "all : $(CLIENT) $(SERVER)\n\n"); + f_print (fout, "$(TARGETS) : $(SOURCES.x) \n"); + f_print (fout, "\trpcgen $(RPCGENFLAGS) $(SOURCES.x)\n\n"); + f_print (fout, "$(OBJECTS_CLNT) : $(SOURCES_CLNT.c) $(SOURCES_CLNT.h) \ +$(TARGETS_CLNT.c) \n\n"); + + f_print (fout, "$(OBJECTS_SVC) : $(SOURCES_SVC.c) $(SOURCES_SVC.h) \ +$(TARGETS_SVC.c) \n\n"); + f_print (fout, "$(CLIENT) : $(OBJECTS_CLNT) \n"); + f_print (fout, "\t$(LINK.c) -o $(CLIENT) $(OBJECTS_CLNT) \ +$(LDLIBS) \n\n"); + f_print (fout, "$(SERVER) : $(OBJECTS_SVC) \n"); + f_print (fout, "\t$(LINK.c) -o $(SERVER) $(OBJECTS_SVC) $(LDLIBS)\n\n "); + f_print (fout, "clean:\n\t $(RM) core $(TARGETS) $(OBJECTS_CLNT) \ +$(OBJECTS_SVC) $(CLIENT) $(SERVER)\n\n"); + close_output (mkfilename); + + free (clntprogname); + free (servprogname); + if (servername != space) + free (servername); + if (clientname != space) + free (clientname); + if (mkfilename != (char *) cmd->outfile) + free (mkfilename); + if (svcname != space) + free (svcname); + if (clntname != space) + free (clntname); + if (xdrname != space) + free (xdrname); + if (hdrname != space) + free (hdrname); +} + +/* + * Perform registrations for service output + * Return 0 if failed; 1 otherwise. + */ +static int +do_registers (int argc, const char *argv[]) +{ + int i; + + if (inetdflag || !tirpcflag) + { + for (i = 1; i < argc; i++) + { + if (streq (argv[i], "-s")) + { + if (!check_nettype (argv[i + 1], valid_i_nettypes)) + return 0; + write_inetd_register (argv[i + 1]); + i++; + } + } + } + else + { + for (i = 1; i < argc; i++) + if (streq (argv[i], "-s")) + { + if (!check_nettype (argv[i + 1], valid_ti_nettypes)) + return 0; + write_nettype_register (argv[i + 1]); + i++; + } + else if (streq (argv[i], "-n")) + { + write_netid_register (argv[i + 1]); + i++; + } + } + return 1; +} + +/* + * Add another argument to the arg list + */ +static void +addarg (const char *cp) +{ + if (argcount >= ARGLISTLEN) + { + fprintf (stderr, _("rpcgen: too many defines\n")); + crash (); + /*NOTREACHED */ + } + arglist[argcount++] = cp; +} + +static void +putarg (int whereto, const char *cp) +{ + if (whereto >= ARGLISTLEN) + { + fprintf (stderr, _("rpcgen: arglist coding error\n")); + crash (); + /*NOTREACHED */ + } + arglist[whereto] = cp; +} + +/* + * if input file is stdin and an output file is specified then complain + * if the file already exists. Otherwise the file may get overwritten + * If input file does not exist, exit with an error + */ + +static void +checkfiles (const char *infile, const char *outfile) +{ + struct stat64 buf; + + if (infile) /* infile ! = NULL */ + if (stat64 (infile, &buf) < 0) + { + perror (infile); + crash (); + } + if (outfile) + { + if (stat64 (outfile, &buf) < 0) + return; /* file does not exist */ + else + { + fprintf (stderr, + /* TRANS: the file will not be removed; this is an + TRANS: informative message. */ + _("file `%s' already exists and may be overwritten\n"), + outfile); + crash (); + } + } +} + +/* + * Parse command line arguments + */ +static int +parseargs (int argc, const char *argv[], struct commandline *cmd) +{ + int i; + int j; + int c; + char flag[(1 << 8 * sizeof (char))]; + int nflags; + + cmdname = argv[0]; + cmd->infile = cmd->outfile = NULL; + if (argc < 2) + { + return (0); + } + allfiles = 0; + flag['c'] = 0; + flag['h'] = 0; + flag['l'] = 0; + flag['m'] = 0; + flag['o'] = 0; + flag['s'] = 0; + flag['n'] = 0; + flag['t'] = 0; + flag['S'] = 0; + flag['C'] = 0; + flag['M'] = 0; + + for (i = 1; i < argc; i++) + { + if (argv[i][0] != '-') + { + if (cmd->infile) + { + fprintf (stderr, + _("Cannot specify more than one input file!\n")); + return 0; + } + cmd->infile = argv[i]; + } + else if (strcmp (argv[i], "--help") == 0) + usage (stdout, 0); + else if (strcmp (argv[i], "--version") == 0) + print_version (); + else + { + for (j = 1; argv[i][j] != 0; j++) + { + c = argv[i][j]; + switch (c) + { + case 'a': + allfiles = 1; + break; + case 'c': + case 'h': + case 'l': + case 'm': + case 't': + if (flag[c]) + return 0; + flag[c] = 1; + break; + case 'S': + /* sample flag: Ss or Sc. + Ss means set flag['S']; + Sc means set flag['C']; + Sm means set flag['M']; */ + c = argv[i][++j]; /* get next char */ + if (c == 's') + c = 'S'; + else if (c == 'c') + c = 'C'; + else if (c == 'm') + c = 'M'; + else + return 0; + + if (flag[c]) + return 0; + flag[c] = 1; + break; + case 'C': /* ANSI C syntax */ + Cflag = 1; + break; + + case 'k': /* K&R C syntax */ + Cflag = 0; + break; + + case 'b': /* turn TIRPC flag off for + generating backward compatible + */ + tirpcflag = 0; + break; + + case '5': /* turn TIRPC flag on for + generating SysVr4 compatible + */ + tirpcflag = 1; + break; + case 'I': + inetdflag = 1; + break; + case 'N': + newstyle = 1; + break; + case 'L': + logflag = 1; + break; + case 'K': + if (++i == argc) + { + return (0); + } + svcclosetime = argv[i]; + goto nextarg; + case 'T': + tblflag = 1; + break; + case 'M': + mtflag = 1; + break; + case 'i': + if (++i == argc) + { + return (0); + } + inlineflag = atoi (argv[i]); + goto nextarg; + case 'n': + case 'o': + case 's': + if (argv[i][j - 1] != '-' || + argv[i][j + 1] != 0) + { + return (0); + } + flag[c] = 1; + if (++i == argc) + { + return (0); + } + if (c == 's') + { + if (!streq (argv[i], "udp") && + !streq (argv[i], "tcp")) + return 0; + } + else if (c == 'o') + { + if (cmd->outfile) + return 0; + cmd->outfile = argv[i]; + } + goto nextarg; + case 'D': + if (argv[i][j - 1] != '-') + return 0; + addarg (argv[i]); + goto nextarg; + case 'Y': + if (++i == argc) + return 0; + { + size_t len = strlen (argv[i]); + pathbuf = malloc (len + 5); + if (pathbuf == NULL) + { + perror (cmdname); + crash (); + } + stpcpy (stpcpy (pathbuf, + argv[i]), + "/cpp"); + CPP = pathbuf; + cppDefined = 1; + goto nextarg; + } + + default: + return 0; + } + } + nextarg: + ; + } + } + + cmd->cflag = flag['c']; + cmd->hflag = flag['h']; + cmd->lflag = flag['l']; + cmd->mflag = flag['m']; + cmd->nflag = flag['n']; + cmd->sflag = flag['s']; + cmd->tflag = flag['t']; + cmd->Ssflag = flag['S']; + cmd->Scflag = flag['C']; + cmd->makefileflag = flag['M']; + +#ifndef _RPC_THREAD_SAFE_ + if (mtflag || newstyle) + { + /* glibc doesn't support these flags. */ + f_print (stderr, + _("This implementation doesn't support newstyle or MT-safe code!\n")); + return (0); + } +#endif + if (tirpcflag) + { + pmflag = inetdflag ? 0 : 1; /* pmflag or inetdflag is always TRUE */ + if ((inetdflag && cmd->nflag)) + { /* netid not allowed with inetdflag */ + fprintf (stderr, _("Cannot use netid flag with inetd flag!\n")); + return 0; + } + } + else + { /* 4.1 mode */ + pmflag = 0; /* set pmflag only in tirpcmode */ + if (cmd->nflag) + { /* netid needs TIRPC */ + f_print (stderr, _("Cannot use netid flag without TIRPC!\n")); + return (0); + } + } + + if (newstyle && (tblflag || cmd->tflag)) + { + f_print (stderr, _("Cannot use table flags with newstyle!\n")); + return (0); + } + + /* check no conflicts with file generation flags */ + nflags = cmd->cflag + cmd->hflag + cmd->lflag + cmd->mflag + + cmd->sflag + cmd->nflag + cmd->tflag + cmd->Ssflag + cmd->Scflag; + + if (nflags == 0) + { + if (cmd->outfile != NULL || cmd->infile == NULL) + { + return (0); + } + } + else if (cmd->infile == NULL && + (cmd->Ssflag || cmd->Scflag || cmd->makefileflag)) + { + fprintf (stderr, + _("\"infile\" is required for template generation flags.\n")); + return 0; + } + if (nflags > 1) + { + fprintf (stderr, _("Cannot have more than one file generation flag!\n")); + return 0; + } + return 1; +} + +static void +usage (FILE *stream, int status) +{ + fprintf (stream, _("usage: %s infile\n"), cmdname); + fprintf (stream, _("\t%s [-abkCLNTM][-Dname[=value]] [-i size] \ +[-I [-K seconds]] [-Y path] infile\n"), cmdname); + fprintf (stream, _("\t%s [-c | -h | -l | -m | -t | -Sc | -Ss | -Sm] \ +[-o outfile] [infile]\n"), cmdname); + fprintf (stream, _("\t%s [-s nettype]* [-o outfile] [infile]\n"), cmdname); + fprintf (stream, _("\t%s [-n netid]* [-o outfile] [infile]\n"), cmdname); + options_usage (stream, status); + exit (status); +} + +static void +options_usage (FILE *stream, int status) +{ + f_print (stream, _("options:\n")); + f_print (stream, _("-a\t\tgenerate all files, including samples\n")); + f_print (stream, _("-b\t\tbackward compatibility mode (generates code for SunOS 4.1)\n")); + f_print (stream, _("-c\t\tgenerate XDR routines\n")); + f_print (stream, _("-C\t\tANSI C mode\n")); + f_print (stream, _("-Dname[=value]\tdefine a symbol (same as #define)\n")); + f_print (stream, _("-h\t\tgenerate header file\n")); + f_print (stream, _("-i size\t\tsize at which to start generating inline code\n")); + f_print (stream, _("-I\t\tgenerate code for inetd support in server (for SunOS 4.1)\n")); + f_print (stream, _("-K seconds\tserver exits after K seconds of inactivity\n")); + f_print (stream, _("-l\t\tgenerate client side stubs\n")); + f_print (stream, _("-L\t\tserver errors will be printed to syslog\n")); + f_print (stream, _("-m\t\tgenerate server side stubs\n")); + f_print (stream, _("-M\t\tgenerate MT-safe code\n")); + f_print (stream, _("-n netid\tgenerate server code that supports named netid\n")); + f_print (stream, _("-N\t\tsupports multiple arguments and call-by-value\n")); + f_print (stream, _("-o outfile\tname of the output file\n")); + f_print (stream, _("-s nettype\tgenerate server code that supports named nettype\n")); + f_print (stream, _("-Sc\t\tgenerate sample client code that uses remote procedures\n")); + f_print (stream, _("-Ss\t\tgenerate sample server code that defines remote procedures\n")); + f_print (stream, _("-Sm \t\tgenerate makefile template \n")); + f_print (stream, _("-t\t\tgenerate RPC dispatch table\n")); + f_print (stream, _("-T\t\tgenerate code to support RPC dispatch tables\n")); + f_print (stream, _("-Y path\t\tdirectory name to find C preprocessor (cpp)\n")); + f_print (stream, _("-5\t\tSysVr4 compatibility mode\n")); + f_print (stream, _("--help\t\tgive this help list\n")); + f_print (stream, _("--version\tprint program version\n")); + + f_print (stream, _("\n\ +For bug reporting instructions, please see:\n\ +%s.\n"), REPORT_BUGS_TO); + exit (status); +} + +static void +print_version (void) +{ + printf ("rpcgen %s%s\n", PKGVERSION, VERSION); + exit (0); +} diff --git a/REORG.TODO/sunrpc/rpc_parse.c b/REORG.TODO/sunrpc/rpc_parse.c new file mode 100644 index 0000000000..505a6554cf --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_parse.c @@ -0,0 +1,687 @@ +/* + * From: @(#)rpc_parse.c 1.8 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_parse.c, Parser for the RPC protocol compiler + * Copyright (C) 1987 Sun Microsystems, Inc. + */ +#include <stdio.h> +#include <string.h> +#include "rpc/types.h" +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define ARGNAME "arg" + +static void isdefined (definition * defp); +static void def_struct (definition * defp); +static void def_program (definition * defp); +static void def_enum (definition * defp); +static void def_const (definition * defp); +static void def_union (definition * defp); +static void check_type_name (const char *name, int new_type); +static void def_typedef (definition * defp); +static void get_declaration (declaration * dec, defkind dkind); +static void get_prog_declaration (declaration * dec, defkind dkind, int num); +static void get_type (const char **prefixp, const char **typep, defkind dkind); +static void unsigned_dec (const char **typep); + +/* + * return the next definition you see + */ +definition * +get_definition (void) +{ + definition *defp; + token tok; + + defp = ALLOC (definition); + get_token (&tok); + switch (tok.kind) + { + case TOK_STRUCT: + def_struct (defp); + break; + case TOK_UNION: + def_union (defp); + break; + case TOK_TYPEDEF: + def_typedef (defp); + break; + case TOK_ENUM: + def_enum (defp); + break; + case TOK_PROGRAM: + def_program (defp); + break; + case TOK_CONST: + def_const (defp); + break; + case TOK_EOF: + free (defp); + return (NULL); + default: + error ("definition keyword expected"); + } + scan (TOK_SEMICOLON, &tok); + isdefined (defp); + return (defp); +} + +static void +isdefined (definition * defp) +{ + STOREVAL (&defined, defp); +} + +static void +def_struct (definition * defp) +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + + defp->def_kind = DEF_STRUCT; + + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_LBRACE, &tok); + tailp = &defp->def.st.decls; + do + { + get_declaration (&dec, DEF_STRUCT); + decls = ALLOC (decl_list); + decls->decl = dec; + *tailp = decls; + tailp = &decls->next; + scan (TOK_SEMICOLON, &tok); + peek (&tok); + } + while (tok.kind != TOK_RBRACE); + get_token (&tok); + *tailp = NULL; +} + +static void +def_program (definition * defp) +{ + token tok; + declaration dec; + decl_list *decls; + decl_list **tailp; + version_list *vlist; + version_list **vtailp; + proc_list *plist; + proc_list **ptailp; + int num_args; + bool_t isvoid = FALSE; /* whether first argument is void */ + defp->def_kind = DEF_PROGRAM; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_LBRACE, &tok); + vtailp = &defp->def.pr.versions; + tailp = &defp->def.st.decls; + scan (TOK_VERSION, &tok); + do + { + scan (TOK_IDENT, &tok); + vlist = ALLOC (version_list); + vlist->vers_name = tok.str; + scan (TOK_LBRACE, &tok); + ptailp = &vlist->procs; + do + { + /* get result type */ + plist = ALLOC (proc_list); + get_type (&plist->res_prefix, &plist->res_type, + DEF_PROGRAM); + if (streq (plist->res_type, "opaque")) + { + error ("illegal result type"); + } + scan (TOK_IDENT, &tok); + plist->proc_name = tok.str; + scan (TOK_LPAREN, &tok); + /* get args - first one */ + num_args = 1; + isvoid = FALSE; + /* type of DEF_PROGRAM in the first + * get_prog_declaration and DEF_STURCT in the next + * allows void as argument if it is the only argument + */ + get_prog_declaration (&dec, DEF_PROGRAM, num_args); + if (streq (dec.type, "void")) + isvoid = TRUE; + decls = ALLOC (decl_list); + plist->args.decls = decls; + decls->decl = dec; + tailp = &decls->next; + /* get args */ + while (peekscan (TOK_COMMA, &tok)) + { + num_args++; + get_prog_declaration (&dec, DEF_STRUCT, + num_args); + decls = ALLOC (decl_list); + decls->decl = dec; + *tailp = decls; + if (streq (dec.type, "void")) + isvoid = TRUE; + tailp = &decls->next; + } + /* multiple arguments are only allowed in newstyle */ + if (!newstyle && num_args > 1) + { + error ("only one argument is allowed"); + } + if (isvoid && num_args > 1) + { + error ("illegal use of void in program definition"); + } + *tailp = NULL; + scan (TOK_RPAREN, &tok); + scan (TOK_EQUAL, &tok); + scan_num (&tok); + scan (TOK_SEMICOLON, &tok); + plist->proc_num = tok.str; + plist->arg_num = num_args; + *ptailp = plist; + ptailp = &plist->next; + peek (&tok); + } + while (tok.kind != TOK_RBRACE); + *ptailp = NULL; + *vtailp = vlist; + vtailp = &vlist->next; + scan (TOK_RBRACE, &tok); + scan (TOK_EQUAL, &tok); + scan_num (&tok); + vlist->vers_num = tok.str; + /* make the argument structure name for each arg */ + for (plist = vlist->procs; plist != NULL; + plist = plist->next) + { + plist->args.argname = make_argname (plist->proc_name, + vlist->vers_num); + /* free the memory ?? */ + } + scan (TOK_SEMICOLON, &tok); + scan2 (TOK_VERSION, TOK_RBRACE, &tok); + } + while (tok.kind == TOK_VERSION); + scan (TOK_EQUAL, &tok); + scan_num (&tok); + defp->def.pr.prog_num = tok.str; + *vtailp = NULL; +} + + +static void +def_enum (definition * defp) +{ + token tok; + enumval_list *elist; + enumval_list **tailp; + + defp->def_kind = DEF_ENUM; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_LBRACE, &tok); + tailp = &defp->def.en.vals; + do + { + scan (TOK_IDENT, &tok); + elist = ALLOC (enumval_list); + elist->name = tok.str; + elist->assignment = NULL; + scan3 (TOK_COMMA, TOK_RBRACE, TOK_EQUAL, &tok); + if (tok.kind == TOK_EQUAL) + { + scan_num (&tok); + elist->assignment = tok.str; + scan2 (TOK_COMMA, TOK_RBRACE, &tok); + } + *tailp = elist; + tailp = &elist->next; + } + while (tok.kind != TOK_RBRACE); + *tailp = NULL; +} + +static void +def_const (definition * defp) +{ + token tok; + + defp->def_kind = DEF_CONST; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_EQUAL, &tok); + scan2 (TOK_IDENT, TOK_STRCONST, &tok); + defp->def.co = tok.str; +} + +static void +def_union (definition *defp) +{ + token tok; + declaration dec; + case_list *cases; +/* case_list *tcase; */ + case_list **tailp; +#if 0 + int flag; +#endif + + defp->def_kind = DEF_UNION; + scan (TOK_IDENT, &tok); + defp->def_name = tok.str; + scan (TOK_SWITCH, &tok); + scan (TOK_LPAREN, &tok); + get_declaration (&dec, DEF_UNION); + defp->def.un.enum_decl = dec; + tailp = &defp->def.un.cases; + scan (TOK_RPAREN, &tok); + scan (TOK_LBRACE, &tok); + scan (TOK_CASE, &tok); + while (tok.kind == TOK_CASE) + { + scan2 (TOK_IDENT, TOK_CHARCONST, &tok); + cases = ALLOC (case_list); + cases->case_name = tok.str; + scan (TOK_COLON, &tok); + /* now peek at next token */ +#if 0 + flag = 0; +#endif + if (peekscan (TOK_CASE, &tok)) + { + + do + { + scan2 (TOK_IDENT, TOK_CHARCONST, &tok); + cases->contflag = 1; /* continued case statement */ + *tailp = cases; + tailp = &cases->next; + cases = ALLOC (case_list); + cases->case_name = tok.str; + scan (TOK_COLON, &tok); + + } + while (peekscan (TOK_CASE, &tok)); + } +#if 0 + else if (flag) + { + + *tailp = cases; + tailp = &cases->next; + cases = ALLOC (case_list); + }; +#endif + + get_declaration (&dec, DEF_UNION); + cases->case_decl = dec; + cases->contflag = 0; /* no continued case statement */ + *tailp = cases; + tailp = &cases->next; + scan (TOK_SEMICOLON, &tok); + + scan3 (TOK_CASE, TOK_DEFAULT, TOK_RBRACE, &tok); + } + *tailp = NULL; + if (tok.kind == TOK_DEFAULT) + { + scan (TOK_COLON, &tok); + get_declaration (&dec, DEF_UNION); + defp->def.un.default_decl = ALLOC (declaration); + *defp->def.un.default_decl = dec; + scan (TOK_SEMICOLON, &tok); + scan (TOK_RBRACE, &tok); + } + else + { + defp->def.un.default_decl = NULL; + } +} + +static const char *reserved_words[] = +{ + "array", + "bytes", + "destroy", + "free", + "getpos", + "inline", + "pointer", + "reference", + "setpos", + "sizeof", + "union", + "vector", + NULL +}; + +static const char *reserved_types[] = +{ + "opaque", + "string", + NULL +}; + +/* + * check that the given name is not one that would eventually result in + * xdr routines that would conflict with internal XDR routines. + */ +static void +check_type_name (const char *name, int new_type) +{ + int i; + char tmp[100]; + + for (i = 0; reserved_words[i] != NULL; i++) + { + if (strcmp (name, reserved_words[i]) == 0) + { + sprintf (tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error (tmp); + } + } + if (new_type) + { + for (i = 0; reserved_types[i] != NULL; i++) + { + if (strcmp (name, reserved_types[i]) == 0) + { + sprintf (tmp, + "illegal (reserved) name :\'%s\' in type definition", name); + error (tmp); + } + } + } +} + + + +static void +def_typedef (definition * defp) +{ + declaration dec; + + defp->def_kind = DEF_TYPEDEF; + get_declaration (&dec, DEF_TYPEDEF); + defp->def_name = dec.name; + check_type_name (dec.name, 1); + defp->def.ty.old_prefix = dec.prefix; + defp->def.ty.old_type = dec.type; + defp->def.ty.rel = dec.rel; + defp->def.ty.array_max = dec.array_max; +} + +static void +get_declaration (declaration * dec, defkind dkind) +{ + token tok; + + get_type (&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (streq (dec->type, "void")) + { + return; + } + + check_type_name (dec->type, 0); + + scan2 (TOK_STAR, TOK_IDENT, &tok); + if (tok.kind == TOK_STAR) + { + dec->rel = REL_POINTER; + scan (TOK_IDENT, &tok); + } + dec->name = tok.str; + if (peekscan (TOK_LBRACKET, &tok)) + { + if (dec->rel == REL_POINTER) + { + error ("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_VECTOR; + scan_num (&tok); + dec->array_max = tok.str; + scan (TOK_RBRACKET, &tok); + } + else if (peekscan (TOK_LANGLE, &tok)) + { + if (dec->rel == REL_POINTER) + { + error ("no array-of-pointer declarations -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan (TOK_RANGLE, &tok)) + { + dec->array_max = "~0"; /* unspecified size, use max */ + } + else + { + scan_num (&tok); + dec->array_max = tok.str; + scan (TOK_RANGLE, &tok); + } + } + if (streq (dec->type, "opaque")) + { + if (dec->rel != REL_ARRAY && dec->rel != REL_VECTOR) + { + error ("array declaration expected"); + } + } + else if (streq (dec->type, "string")) + { + if (dec->rel != REL_ARRAY) + { + error ("variable-length array declaration expected"); + } + } +} + +static void +get_prog_declaration (declaration * dec, defkind dkind, int num /* arg number */ ) +{ + token tok; + char name[MAXLINESIZE]; /* argument name */ + + if (dkind == DEF_PROGRAM) + { + peek (&tok); + if (tok.kind == TOK_RPAREN) + { /* no arguments */ + dec->rel = REL_ALIAS; + dec->type = "void"; + dec->prefix = NULL; + dec->name = NULL; + return; + } + } + get_type (&dec->prefix, &dec->type, dkind); + dec->rel = REL_ALIAS; + if (peekscan (TOK_IDENT, &tok)) /* optional name of argument */ + strcpy (name, tok.str); + else + sprintf (name, "%s%d", ARGNAME, num); /* default name of argument */ + + dec->name = (char *) strdup (name); + + if (streq (dec->type, "void")) + { + return; + } + + if (streq (dec->type, "opaque")) + { + error ("opaque -- illegal argument type"); + } + if (peekscan (TOK_STAR, &tok)) + { + if (streq (dec->type, "string")) + { + error ("pointer to string not allowed in program arguments\n"); + } + dec->rel = REL_POINTER; + if (peekscan (TOK_IDENT, &tok)) /* optional name of argument */ + dec->name = strdup (tok.str); + } + if (peekscan (TOK_LANGLE, &tok)) + { + if (!streq (dec->type, "string")) + { + error ("arrays cannot be declared as arguments to procedures -- use typedef"); + } + dec->rel = REL_ARRAY; + if (peekscan (TOK_RANGLE, &tok)) + { + dec->array_max = "~0"; /* unspecified size, use max */ + } + else + { + scan_num (&tok); + dec->array_max = tok.str; + scan (TOK_RANGLE, &tok); + } + } + if (streq (dec->type, "string")) + { + if (dec->rel != REL_ARRAY) + { /* .x specifies just string as + * type of argument + * - make it string<> + */ + dec->rel = REL_ARRAY; + dec->array_max = "~0"; /* unspecified size, use max */ + } + } +} + +static void +get_type (const char **prefixp, const char **typep, defkind dkind) +{ + token tok; + + *prefixp = NULL; + get_token (&tok); + switch (tok.kind) + { + case TOK_IDENT: + *typep = tok.str; + break; + case TOK_STRUCT: + case TOK_ENUM: + case TOK_UNION: + *prefixp = tok.str; + scan (TOK_IDENT, &tok); + *typep = tok.str; + break; + case TOK_UNSIGNED: + unsigned_dec (typep); + break; + case TOK_SHORT: + *typep = "short"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_LONG: + *typep = "long"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_HYPER: + *typep = "quad_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_VOID: + if (dkind != DEF_UNION && dkind != DEF_PROGRAM) + { + error ("voids allowed only inside union and program definitions with one argument"); + } + *typep = tok.str; + break; + case TOK_STRING: + case TOK_OPAQUE: + case TOK_CHAR: + case TOK_INT: + case TOK_FLOAT: + case TOK_DOUBLE: + case TOK_BOOL: + *typep = tok.str; + break; + default: + error ("expected type specifier"); + } +} + +static void +unsigned_dec (const char **typep) +{ + token tok; + + peek (&tok); + switch (tok.kind) + { + case TOK_CHAR: + get_token (&tok); + *typep = "u_char"; + break; + case TOK_SHORT: + get_token (&tok); + *typep = "u_short"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_LONG: + get_token (&tok); + *typep = "u_long"; + (void) peekscan (TOK_INT, &tok); + break; + case TOK_HYPER: + get_token (&tok); + *typep = "u_quad_t"; + (void) peekscan(TOK_INT, &tok); + break; + case TOK_INT: + get_token (&tok); + *typep = "u_int"; + break; + default: + *typep = "u_int"; + break; + } +} diff --git a/REORG.TODO/sunrpc/rpc_parse.h b/REORG.TODO/sunrpc/rpc_parse.h new file mode 100644 index 0000000000..e2e2f1e106 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_parse.h @@ -0,0 +1,165 @@ +/* @(#)rpc_parse.h 1.3 90/08/29 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * rpc_parse.h, Definitions for the RPCL parser + */ + +enum defkind { + DEF_CONST, + DEF_STRUCT, + DEF_UNION, + DEF_ENUM, + DEF_TYPEDEF, + DEF_PROGRAM +}; +typedef enum defkind defkind; + +typedef const char *const_def; + +enum relation { + REL_VECTOR, /* fixed length array */ + REL_ARRAY, /* variable length array */ + REL_POINTER, /* pointer */ + REL_ALIAS /* simple */ +}; +typedef enum relation relation; + +struct typedef_def { + const char *old_prefix; + const char *old_type; + relation rel; + const char *array_max; +}; +typedef struct typedef_def typedef_def; + +struct enumval_list { + const char *name; + const char *assignment; + struct enumval_list *next; +}; +typedef struct enumval_list enumval_list; + +struct enum_def { + enumval_list *vals; +}; +typedef struct enum_def enum_def; + +struct declaration { + const char *prefix; + const char *type; + const char *name; + relation rel; + const char *array_max; +}; +typedef struct declaration declaration; + +struct decl_list { + declaration decl; + struct decl_list *next; +}; +typedef struct decl_list decl_list; + +struct struct_def { + decl_list *decls; +}; +typedef struct struct_def struct_def; + +struct case_list { + const char *case_name; + int contflag; + declaration case_decl; + struct case_list *next; +}; +typedef struct case_list case_list; + +struct union_def { + declaration enum_decl; + case_list *cases; + declaration *default_decl; +}; +typedef struct union_def union_def; + +struct arg_list { + const char *argname; /* name of struct for arg*/ + decl_list *decls; +}; + +typedef struct arg_list arg_list; + +struct proc_list { + const char *proc_name; + const char *proc_num; + arg_list args; + int arg_num; + const char *res_type; + const char *res_prefix; + struct proc_list *next; +}; +typedef struct proc_list proc_list; + +struct version_list { + const char *vers_name; + const char *vers_num; + proc_list *procs; + struct version_list *next; +}; +typedef struct version_list version_list; + +struct program_def { + const char *prog_num; + version_list *versions; +}; +typedef struct program_def program_def; + +struct definition { + const char *def_name; + defkind def_kind; + union { + const_def co; + struct_def st; + union_def un; + enum_def en; + typedef_def ty; + program_def pr; + } def; +}; +typedef struct definition definition; + +definition *get_definition(void); + + +struct bas_type +{ + const char *name; + int length; + struct bas_type *next; +}; + +typedef struct bas_type bas_type; diff --git a/REORG.TODO/sunrpc/rpc_prot.c b/REORG.TODO/sunrpc/rpc_prot.c new file mode 100644 index 0000000000..46582f2a35 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_prot.c @@ -0,0 +1,276 @@ +/* + * rpc_prot.c + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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> +#include <shlib-compat.h> + +/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ + +/* + * XDR an opaque authentication struct + * (see auth.h) + */ +bool_t +xdr_opaque_auth (XDR *xdrs, 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; +} +libc_hidden_nolink_sunrpc (xdr_opaque_auth, GLIBC_2_0) + +/* + * XDR a DES block + */ +bool_t +xdr_des_block (XDR *xdrs, des_block *blkp) +{ + return xdr_opaque (xdrs, (caddr_t) blkp, sizeof (des_block)); +} +libc_hidden_nolink_sunrpc (xdr_des_block, GLIBC_2_0) + +/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ + +/* + * XDR the MSG_ACCEPTED part of a reply message union + */ +bool_t +xdr_accepted_reply (XDR *xdrs, struct accepted_reply *ar) +{ + /* personalized union, rather than calling xdr_union */ + if (!xdr_opaque_auth (xdrs, &(ar->ar_verf))) + return FALSE; + if (!xdr_enum (xdrs, (enum_t *) & (ar->ar_stat))) + return FALSE; + switch (ar->ar_stat) + { + case SUCCESS: + return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where)); + case PROG_MISMATCH: + if (!xdr_u_long (xdrs, &(ar->ar_vers.low))) + return FALSE; + return (xdr_u_long (xdrs, &(ar->ar_vers.high))); + default: + return TRUE; + } + return TRUE; /* TRUE => open ended set of problems */ +} +libc_hidden_nolink_sunrpc (xdr_accepted_reply, GLIBC_2_0) + +/* + * XDR the MSG_DENIED part of a reply message union + */ +bool_t +xdr_rejected_reply (XDR *xdrs, struct rejected_reply *rr) +{ + /* personalized union, rather than calling xdr_union */ + if (!xdr_enum (xdrs, (enum_t *) & (rr->rj_stat))) + return FALSE; + switch (rr->rj_stat) + { + case RPC_MISMATCH: + if (!xdr_u_long (xdrs, &(rr->rj_vers.low))) + return FALSE; + return xdr_u_long (xdrs, &(rr->rj_vers.high)); + + case AUTH_ERROR: + return xdr_enum (xdrs, (enum_t *) & (rr->rj_why)); + } + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_rejected_reply, GLIBC_2_0) + +static const struct xdr_discrim reply_dscrm[3] = +{ + {(int) MSG_ACCEPTED, (xdrproc_t) xdr_accepted_reply}, + {(int) MSG_DENIED, (xdrproc_t) xdr_rejected_reply}, + {__dontcare__, NULL_xdrproc_t}}; + +/* + * XDR a reply message + */ +bool_t +xdr_replymsg (XDR *xdrs, struct rpc_msg *rmsg) +{ + if (xdr_u_long (xdrs, &(rmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (rmsg->rm_direction)) && + (rmsg->rm_direction == REPLY)) + return xdr_union (xdrs, (enum_t *) & (rmsg->rm_reply.rp_stat), + (caddr_t) & (rmsg->rm_reply.ru), reply_dscrm, + NULL_xdrproc_t); + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_replymsg, GLIBC_2_0) + + +/* + * 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 (XDR *xdrs, struct rpc_msg *cmsg) +{ + + cmsg->rm_direction = CALL; + cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; + if ( + (xdrs->x_op == XDR_ENCODE) && + xdr_u_long (xdrs, &(cmsg->rm_xid)) && + xdr_enum (xdrs, (enum_t *) & (cmsg->rm_direction)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_rpcvers)) && + xdr_u_long (xdrs, &(cmsg->rm_call.cb_prog))) + return xdr_u_long (xdrs, &(cmsg->rm_call.cb_vers)); + return FALSE; +} +libc_hidden_nolink_sunrpc (xdr_callhdr, GLIBC_2_0) + +/* ************************** Client utility routine ************* */ + +static void +accepted (enum accept_stat acpt_stat, + struct rpc_err *error) +{ + switch (acpt_stat) + { + + case PROG_UNAVAIL: + error->re_status = RPC_PROGUNAVAIL; + return; + + case PROG_MISMATCH: + error->re_status = RPC_PROGVERSMISMATCH; + return; + + case PROC_UNAVAIL: + error->re_status = RPC_PROCUNAVAIL; + return; + + case GARBAGE_ARGS: + error->re_status = RPC_CANTDECODEARGS; + return; + + case SYSTEM_ERR: + error->re_status = RPC_SYSTEMERROR; + return; + + case SUCCESS: + error->re_status = RPC_SUCCESS; + return; + } + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) MSG_ACCEPTED; + error->re_lb.s2 = (long) acpt_stat; +} + +static void +rejected (enum reject_stat rjct_stat, + struct rpc_err *error) +{ + switch (rjct_stat) + { + case RPC_MISMATCH: + error->re_status = RPC_VERSMISMATCH; + return; + case AUTH_ERROR: + error->re_status = RPC_AUTHERROR; + return; + default: + /* something's wrong, but we don't know what ... */ + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) MSG_DENIED; + error->re_lb.s2 = (long) rjct_stat; + return; + } +} + +/* + * given a reply message, fills in the error + */ +void +_seterr_reply (struct rpc_msg *msg, + struct rpc_err *error) +{ + /* optimized for normal, SUCCESSful case */ + switch (msg->rm_reply.rp_stat) + { + case MSG_ACCEPTED: + if (msg->acpted_rply.ar_stat == SUCCESS) + { + error->re_status = RPC_SUCCESS; + return; + }; + accepted (msg->acpted_rply.ar_stat, error); + break; + + case MSG_DENIED: + rejected (msg->rjcted_rply.rj_stat, error); + break; + + default: + error->re_status = RPC_FAILED; + error->re_lb.s1 = (long) (msg->rm_reply.rp_stat); + break; + } + switch (error->re_status) + { + + case RPC_VERSMISMATCH: + error->re_vers.low = msg->rjcted_rply.rj_vers.low; + error->re_vers.high = msg->rjcted_rply.rj_vers.high; + break; + + case RPC_AUTHERROR: + error->re_why = msg->rjcted_rply.rj_why; + break; + + case RPC_PROGVERSMISMATCH: + error->re_vers.low = msg->acpted_rply.ar_vers.low; + error->re_vers.high = msg->acpted_rply.ar_vers.high; + break; + default: + break; + } +} +libc_hidden_nolink_sunrpc (_seterr_reply, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/rpc_sample.c b/REORG.TODO/sunrpc/rpc_sample.c new file mode 100644 index 0000000000..e90b58c080 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_sample.c @@ -0,0 +1,336 @@ +/* + * From: @(#)rpc_sample.c 1.1 90/08/30 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_sample.c, Sample client-server code outputter for the RPC protocol compiler + */ + +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + + +static const char RQSTP[] = "rqstp"; + +static void write_sample_client (const char *program_name, version_list * vp); +static void write_sample_server (definition * def); +static void return_type (proc_list * plist); + + +void +write_sample_svc (definition * def) +{ + + if (def->def_kind != DEF_PROGRAM) + return; + write_sample_server (def); +} + + +int +write_sample_clnt (definition * def) +{ + version_list *vp; + int count = 0; + + if (def->def_kind != DEF_PROGRAM) + return 0; + /* generate sample code for each version */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + write_sample_client (def->def_name, vp); + ++count; + } + return count; +} + + +static void +write_sample_client (const char *program_name, version_list * vp) +{ + proc_list *proc; + int i; + decl_list *l; + + f_print (fout, "\n\nvoid\n"); + pvname (program_name, vp->vers_num); + if (Cflag) + f_print (fout, "(char *host)\n{\n"); + else + f_print (fout, "(host)\nchar *host;\n{\n"); + f_print (fout, "\tCLIENT *clnt;\n"); + + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + f_print (fout, "\t"); + ++i; + if (mtflag) + { + f_print (fout, "enum clnt_stat retval_%d;\n\t", i); + ptype (proc->res_prefix, proc->res_type, 1); + if (!streq (proc->res_type, "void")) + f_print (fout, "result_%d;\n", i); + else + fprintf (fout, "*result_%d;\n", i); + } + else + { + ptype (proc->res_prefix, proc->res_type, 1); + f_print (fout, " *result_%d;\n", i); + } + /* print out declarations for arguments */ + if (proc->arg_num < 2 && !newstyle) + { + f_print (fout, "\t"); + if (!streq (proc->args.decls->decl.type, "void")) + { + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 1); + f_print (fout, " "); + } + else + f_print (fout, "char *"); /* cannot have "void" type */ + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_arg;\n"); + } + else if (!streq (proc->args.decls->decl.type, "void")) + { + for (l = proc->args.decls; l != NULL; l = l->next) + { + f_print (fout, "\t"); + ptype (l->decl.prefix, l->decl.type, 1); + if (strcmp (l->decl.type, "string") == 1) + f_print (fout, " "); + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_%s;\n", l->decl.name); + } + } + } + + /* generate creation of client handle */ + f_print(fout, "\n#ifndef\tDEBUG\n"); + f_print (fout, "\tclnt = clnt_create (host, %s, %s, \"%s\");\n", + program_name, vp->vers_name, tirpcflag ? "netpath" : "udp"); + f_print (fout, "\tif (clnt == NULL) {\n"); + f_print (fout, "\t\tclnt_pcreateerror (host);\n"); + f_print (fout, "\t\texit (1);\n\t}\n"); + f_print(fout, "#endif\t/* DEBUG */\n\n"); + + /* generate calls to procedures */ + i = 0; + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + if (mtflag) + f_print(fout, "\tretval_%d = ",++i); + else + f_print (fout, "\tresult_%d = ", ++i); + pvname (proc->proc_name, vp->vers_num); + if (proc->arg_num < 2 && !newstyle) + { + f_print (fout, "("); + if (streq (proc->args.decls->decl.type, "void"))/* cast to void* */ + f_print (fout, "(void*)"); + f_print (fout, "&"); + pvname (proc->proc_name, vp->vers_num); + if (mtflag) + f_print(fout, "_arg, &result_%d, clnt);\n", i); + else + f_print (fout, "_arg, clnt);\n"); + } + else if (streq (proc->args.decls->decl.type, "void")) + { + if (mtflag) + f_print (fout, "(&result_%d, clnt);\n", i); + else + f_print (fout, "(clnt);\n"); + } + else + { + f_print (fout, "("); + for (l = proc->args.decls; l != NULL; l = l->next) + { + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_%s, ", l->decl.name); + } + if (mtflag) + f_print(fout, "&result_%d, ", i); + f_print (fout, "clnt);\n"); + } + if (mtflag) + { + f_print(fout, "\tif (retval_%d != RPC_SUCCESS) {\n", i); + } + else + { + f_print(fout, "\tif (result_%d == (", i); + ptype(proc->res_prefix, proc->res_type, 1); + f_print(fout, "*) NULL) {\n"); + } + f_print(fout, "\t\tclnt_perror (clnt, \"call failed\");\n"); + f_print(fout, "\t}\n"); + } + + f_print (fout, "#ifndef\tDEBUG\n"); + f_print (fout, "\tclnt_destroy (clnt);\n"); + f_print (fout, "#endif\t /* DEBUG */\n"); + f_print (fout, "}\n"); +} + +static void +write_sample_server (definition * def) +{ + version_list *vp; + proc_list *proc; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + f_print (fout, "\n"); + if (!mtflag) + { + return_type (proc); + f_print (fout, "*\n"); + } + else + f_print (fout, "bool_t\n"); + if (Cflag || mtflag) + pvname_svc (proc->proc_name, vp->vers_num); + else + pvname(proc->proc_name, vp->vers_num); + printarglist(proc, "result", RQSTP, "struct svc_req *"); + f_print(fout, "{\n"); + if (!mtflag) + { + f_print(fout, "\tstatic "); + if(!streq(proc->res_type, "void")) + return_type(proc); + else + f_print(fout, "char *"); + /* cannot have void type */ + /* f_print(fout, " result;\n", proc->res_type); */ + f_print(fout, " result;\n"); + } + else + f_print(fout, "\tbool_t retval;\n"); + fprintf (fout, "\n\t/*\n\t * insert server code here\n\t */\n\n"); + + if (!mtflag) + { + if (!streq(proc->res_type, "void")) + f_print(fout, "\treturn &result;\n}\n"); + else /* cast back to void * */ + f_print(fout, "\treturn (void *) &result;\n}\n"); + } + else + f_print(fout, "\treturn retval;\n}\n"); + } + + /* put in sample freeing routine */ + if (mtflag) + { + f_print(fout, "\nint\n"); + pvname(def->def_name, vp->vers_num); + if (Cflag) + f_print(fout,"_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)\n"); + else + { + f_print(fout,"_freeresult (transp, xdr_result, result)\n"); + f_print(fout,"\tSVCXPRT *transp;\n"); + f_print(fout,"\txdrproc_t xdr_result;\n"); + f_print(fout,"\tcaddr_t result;\n"); + } + f_print(fout, "{\n"); + f_print(fout, "\txdr_free (xdr_result, result);\n"); + f_print(fout, + "\n\t/*\n\t * Insert additional freeing code here, if needed\n\t */\n"); + f_print(fout, "\n\treturn 1;\n}\n"); + } + } +} + + + +static void +return_type (proc_list * plist) +{ + ptype (plist->res_prefix, plist->res_type, 1); +} + +void +add_sample_msg (void) +{ + f_print (fout, "/*\n"); + f_print (fout, " * This is sample code generated by rpcgen.\n"); + f_print (fout, " * These are only templates and you can use them\n"); + f_print (fout, " * as a guideline for developing your own functions.\n"); + f_print (fout, " */\n\n"); +} + +void +write_sample_clnt_main (void) +{ + list *l; + definition *def; + version_list *vp; + + f_print (fout, "\n\n"); + if (Cflag) + f_print (fout, "int\nmain (int argc, char *argv[])\n{\n"); + else + f_print (fout, "int\nmain (argc, argv)\nint argc;\nchar *argv[];\n{\n"); + + f_print (fout, "\tchar *host;"); + f_print (fout, "\n\n\tif (argc < 2) {"); + f_print (fout, "\n\t\tprintf (\"usage: %%s server_host\\n\", argv[0]);\n"); + f_print (fout, "\t\texit (1);\n\t}"); + f_print (fout, "\n\thost = argv[1];\n"); + + for (l = defined; l != NULL; l = l->next) + { + def = l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "\t"); + pvname (def->def_name, vp->vers_num); + f_print (fout, " (host);\n"); + } + } + f_print (fout, "exit (0);\n}\n"); +} diff --git a/REORG.TODO/sunrpc/rpc_scan.c b/REORG.TODO/sunrpc/rpc_scan.c new file mode 100644 index 0000000000..0a88bafe76 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_scan.c @@ -0,0 +1,544 @@ +/* + * From: @(#)rpc_scan.c 1.11 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_scan.c, Scanner for the RPC protocol compiler + * Copyright (C) 1987, Sun Microsystems, Inc. + */ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <libintl.h> +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define startcomment(where) (where[0] == '/' && where[1] == '*') +#define endcomment(where) (where[-1] == '*' && where[0] == '/') + +static int pushed = 0; /* is a token pushed */ +static token lasttok; /* last token, if pushed */ + +static void unget_token (token * tokp); +static void findstrconst (const char **str, const char **val); +static void findchrconst (const char **str, const char **val); +static void findconst (const char **str, const char **val); +static void findkind (const char **mark, token * tokp); +static int cppline (const char *line); +static int directive (const char *line); +static void printdirective (const char *line); +static void docppline (const char *line, int *lineno, const char **fname); + +/* + * scan expecting 1 given token + */ +void +scan (tok_kind expect, token * tokp) +{ + get_token (tokp); + if (tokp->kind != expect) + expected1 (expect); +} + +/* + * scan expecting any of the 2 given tokens + */ +void +scan2 (tok_kind expect1, tok_kind expect2, token * tokp) +{ + get_token (tokp); + if (tokp->kind != expect1 && tokp->kind != expect2) + { + expected2 (expect1, expect2); + } +} + +/* + * scan expecting any of the 3 given token + */ +void +scan3 (tok_kind expect1, tok_kind expect2, tok_kind expect3, token * tokp) +{ + get_token (tokp); + if (tokp->kind != expect1 && tokp->kind != expect2 + && tokp->kind != expect3) + { + expected3 (expect1, expect2, expect3); + } +} + +/* + * scan expecting a constant, possibly symbolic + */ +void +scan_num (token *tokp) +{ + get_token (tokp); + switch (tokp->kind) + { + case TOK_IDENT: + break; + default: + error (_("constant or identifier expected")); + } +} + +/* + * Peek at the next token + */ +void +peek (token *tokp) +{ + get_token (tokp); + unget_token (tokp); +} + +/* + * Peek at the next token and scan it if it matches what you expect + */ +int +peekscan (tok_kind expect, token *tokp) +{ + peek (tokp); + if (tokp->kind == expect) + { + get_token (tokp); + return 1; + } + return 0; +} + +/* + * Get the next token, printing out any directive that are encountered. + */ +void +get_token (token *tokp) +{ + int commenting; + + if (pushed) + { + pushed = 0; + *tokp = lasttok; + return; + } + commenting = 0; + for (;;) + { + if (*where == 0) + { + for (;;) + { + if (!fgets (curline, MAXLINESIZE, fin)) + { + tokp->kind = TOK_EOF; + *curline = 0; + where = curline; + return; + } + linenum++; + if (commenting) + { + break; + } + else if (cppline (curline)) + { + docppline (curline, &linenum, + &infilename); + } + else if (directive (curline)) + { + printdirective (curline); + } + else + { + break; + } + } + where = curline; + } + else if (isspace (*where)) + { + while (isspace (*where)) + { + where++; /* eat */ + } + } + else if (commenting) + { + for (where++; *where; where++) + { + if (endcomment (where)) + { + where++; + commenting--; + break; + } + } + } + else if (startcomment (where)) + { + where += 2; + commenting++; + } + else + { + break; + } + } + + /* + * 'where' is not whitespace, comment or directive Must be a token! + */ + switch (*where) + { + case ':': + tokp->kind = TOK_COLON; + where++; + break; + case ';': + tokp->kind = TOK_SEMICOLON; + where++; + break; + case ',': + tokp->kind = TOK_COMMA; + where++; + break; + case '=': + tokp->kind = TOK_EQUAL; + where++; + break; + case '*': + tokp->kind = TOK_STAR; + where++; + break; + case '[': + tokp->kind = TOK_LBRACKET; + where++; + break; + case ']': + tokp->kind = TOK_RBRACKET; + where++; + break; + case '{': + tokp->kind = TOK_LBRACE; + where++; + break; + case '}': + tokp->kind = TOK_RBRACE; + where++; + break; + case '(': + tokp->kind = TOK_LPAREN; + where++; + break; + case ')': + tokp->kind = TOK_RPAREN; + where++; + break; + case '<': + tokp->kind = TOK_LANGLE; + where++; + break; + case '>': + tokp->kind = TOK_RANGLE; + where++; + break; + + case '"': + tokp->kind = TOK_STRCONST; + findstrconst (&where, &tokp->str); + break; + case '\'': + tokp->kind = TOK_CHARCONST; + findchrconst (&where, &tokp->str); + break; + + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + tokp->kind = TOK_IDENT; + findconst (&where, &tokp->str); + break; + + default: + if (!(isalpha (*where) || *where == '_')) + { + char buf[100]; + char *p; + + s_print (buf, _("illegal character in file: ")); + p = buf + strlen (buf); + if (isprint (*where)) + { + s_print (p, "%c", *where); + } + else + { + s_print (p, "%d", *where); + } + error (buf); + } + findkind (&where, tokp); + break; + } +} + +static void +unget_token (token * tokp) +{ + lasttok = *tokp; + pushed = 1; +} + +static void +findstrconst (const char **str, const char **val) +{ + const char *p; + char *tmp; + int size; + + p = *str; + do + { + p++; + } + while (*p && *p != '"'); + if (*p == 0) + { + error (_("unterminated string constant")); + } + p++; + size = p - *str; + tmp = alloc (size + 1); + strncpy (tmp, *str, size); + tmp[size] = 0; + *val = tmp; + *str = p; +} + +static void +findchrconst (const char **str, const char **val) +{ + const char *p; + char *tmp; + int size; + + p = *str; + do + { + p++; + } + while (*p && *p != '\''); + if (*p == 0) + { + error (_("unterminated string constant")); + } + p++; + size = p - *str; + if (size != 3) + { + error (_("empty char string")); + } + tmp = alloc (size + 1); + strncpy (tmp, *str, size); + tmp[size] = 0; + *val = tmp; + *str = p; +} + +static void +findconst (const char **str, const char **val) +{ + const char *p; + char *tmp; + int size; + + p = *str; + if (*p == '0' && *(p + 1) == 'x') + { + p++; + do + { + p++; + } + while (isxdigit (*p)); + } + else + { + do + { + p++; + } + while (isdigit (*p)); + } + size = p - *str; + tmp = alloc (size + 1); + strncpy (tmp, *str, size); + tmp[size] = 0; + *val = tmp; + *str = p; +} + +static const token symbols[] = +{ + {TOK_CONST, "const"}, + {TOK_UNION, "union"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_STRUCT, "struct"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_ENUM, "enum"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_CHAR, "char"}, + {TOK_INT, "int"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_HYPER, "hyper"}, + {TOK_FLOAT, "float"}, + {TOK_DOUBLE, "double"}, + {TOK_STRING, "string"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"}, +}; + +static void +findkind (const char **mark, token *tokp) +{ + int len; + const token *s; + const char *str; + char *tmp; + + str = *mark; + for (s = symbols; s->kind != TOK_EOF; s++) + { + len = strlen (s->str); + if (strncmp (str, s->str, len) == 0) + { + if (!isalnum (str[len]) && str[len] != '_') + { + tokp->kind = s->kind; + tokp->str = s->str; + *mark = str + len; + return; + } + } + } + tokp->kind = TOK_IDENT; + for (len = 0; isalnum (str[len]) || str[len] == '_'; len++); + tmp = alloc (len + 1); + strncpy (tmp, str, len); + tmp[len] = 0; + tokp->str = tmp; + *mark = str + len; +} + +static int +cppline (const char *line) +{ + return line == curline && *line == '#'; +} + +static int +directive (const char *line) +{ + return line == curline && *line == '%'; +} + +static void +printdirective (const char *line) +{ + f_print (fout, "%s", line + 1); +} + +static void +docppline (const char *line, int *lineno, const char **fname) +{ + char *file; + int num; + char *p; + + line++; + while (isspace (*line)) + { + line++; + } + num = atoi (line); + while (isdigit (*line)) + { + line++; + } + while (isspace (*line)) + { + line++; + } + if (*line != '"') + { + error (_("preprocessor error")); + } + line++; + p = file = alloc (strlen (line) + 1); + while (*line && *line != '"') + { + *p++ = *line++; + } + if (*line == 0) + { + error (_("preprocessor error")); + } + *p = 0; + if (*file == 0) + { + free (file); + *fname = NULL; + } + else + { + *fname = file; + } + *lineno = num - 1; +} diff --git a/REORG.TODO/sunrpc/rpc_scan.h b/REORG.TODO/sunrpc/rpc_scan.h new file mode 100644 index 0000000000..9786a513b9 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_scan.h @@ -0,0 +1,104 @@ +/* @(#)rpc_scan.h 1.3 90/08/29 */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * rpc_scan.h, Definitions for the RPCL scanner + */ + +/* + * kinds of tokens + */ +enum tok_kind { + TOK_IDENT, + TOK_CHARCONST, + TOK_STRCONST, + TOK_LPAREN, + TOK_RPAREN, + TOK_LBRACE, + TOK_RBRACE, + TOK_LBRACKET, + TOK_RBRACKET, + TOK_LANGLE, + TOK_RANGLE, + TOK_STAR, + TOK_COMMA, + TOK_EQUAL, + TOK_COLON, + TOK_SEMICOLON, + TOK_CONST, + TOK_STRUCT, + TOK_UNION, + TOK_SWITCH, + TOK_CASE, + TOK_DEFAULT, + TOK_ENUM, + TOK_TYPEDEF, + TOK_INT, + TOK_SHORT, + TOK_LONG, + TOK_HYPER, + TOK_UNSIGNED, + TOK_FLOAT, + TOK_DOUBLE, + TOK_OPAQUE, + TOK_CHAR, + TOK_STRING, + TOK_BOOL, + TOK_VOID, + TOK_PROGRAM, + TOK_VERSION, + TOK_EOF +}; +typedef enum tok_kind tok_kind; + +/* + * a token + */ +struct token { + tok_kind kind; + const char *str; +}; +typedef struct token token; + + +/* + * routine interface + */ +void scan(tok_kind expect, token *tokp); +void scan2(tok_kind expect1, tok_kind expect2, token *tokp); +void scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp); +void scan_num(token *tokp); +void peek(token *tokp); +int peekscan(tok_kind expect, token *tokp); +void get_token(token *tokp); +void expected1(tok_kind exp1) __attribute__ ((noreturn)); +void expected2(tok_kind exp1, tok_kind exp2) __attribute__ ((noreturn)); +void expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3) + __attribute__ ((noreturn)); diff --git a/REORG.TODO/sunrpc/rpc_svcout.c b/REORG.TODO/sunrpc/rpc_svcout.c new file mode 100644 index 0000000000..4f12a8146c --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_svcout.c @@ -0,0 +1,1093 @@ +/* + * From: @(#)rpc_svcout.c 1.29 89/03/30 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_svcout.c, Server-skeleton outputter for the RPC protocol compiler + */ +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +static const char RQSTP[] = "rqstp"; +static const char TRANSP[] = "transp"; +static const char ARG[] = "argument"; +static const char RESULT[] = "result"; +static const char ROUTINE[] = "local"; +static char RETVAL[] = "retval"; + +char _errbuf[256]; /* For all messages */ + +static void internal_proctype (const proc_list * plist); +static void p_xdrfunc (const char *rname, const char *typename); +static void write_real_program (const definition * def); +static void write_program (const definition * def, const char *storage); +static void printerr (const char *err, const char *transp); +static void printif (const char *proc, const char *transp, const char *arg); +static void write_inetmost (const char *infile); +static void print_return (const char *space); +static void print_pmapunset (const char *space); +static void print_err_message (const char *space); +static void write_timeout_func (void); +static void write_pm_most (const char *infile, int netflag); +static void write_rpc_svc_fg (const char *infile, const char *sp); +static void open_log_file (const char *infile, const char *sp); + +static void +p_xdrfunc (const char *rname, const char *typename) +{ + if (Cflag) + f_print (fout, "\t\t_xdr_%s = (xdrproc_t) xdr_%s;\n", rname, + stringfix (typename)); + else + f_print (fout, "\t\t_xdr_%s = xdr_%s;\n", rname, stringfix (typename)); +} + +void +internal_proctype (const proc_list * plist) +{ + f_print (fout, "static "); + ptype (plist->res_prefix, plist->res_type, 1); + f_print (fout, "*"); +} + + +/* + * write most of the service, that is, everything but the registrations. + */ +void +write_most (const char *infile /* our name */ , int netflag, int nomain) +{ + if (inetdflag || pmflag) + { + const char *var_type; + /* WHY? */ + var_type = (nomain ? "extern" : ""); + f_print (fout, "%s int _rpcpmstart;", var_type); + f_print (fout, "\t\t/* Started by a port monitor ? */\n"); + if (!tirpcflag) + { + f_print (fout, "%s int _rpcfdtype;", var_type); + f_print (fout, "\t\t/* Whether Stream or Datagram ? */\n"); + } + if (timerflag) + { +#if 0 + f_print (fout, "%s int _rpcsvcdirty;", var_type); + f_print (fout, "\t/* Still serving ? */\n"); +#else + f_print(fout, " /* States a server can be in wrt request */\n\n"); + f_print(fout, "#define\t_IDLE 0\n"); + f_print(fout, "#define\t_SERVED 1\n"); + f_print(fout, "#define\t_SERVING 2\n\n"); + f_print(fout, "static int _rpcsvcstate = _IDLE;"); + f_print(fout, "\t /* Set when a request is serviced */\n"); + + if (mtflag) + { + f_print (fout, "mutex_t _svcstate_lock;"); + f_print (fout, + "\t\t\t/* Mutex lock for variable_rpcsvcstate */\n"); + } +#endif + } + write_svc_aux (nomain); + } + /* write out dispatcher and stubs */ + write_programs (nomain ? NULL : "static"); + + if (nomain) + return; + + if (Cflag) + f_print (fout, "\nint\nmain (int argc, char **argv)\n"); + else + { + f_print (fout, "\nint\nmain (argc, argv)\n"); + f_print (fout, "\tint argc;\n"); + f_print (fout, "\tchar **argv;\n"); + } + f_print (fout, "{\n"); + if (inetdflag) + { + write_inetmost (infile); /* Includes call to write_rpc_svc_fg() */ + } + else + { + if (tirpcflag) + { + if (netflag) + { + f_print (fout, "\tregister SVCXPRT *%s;\n", TRANSP); + f_print (fout, "\tstruct netconfig *nconf = NULL;\n"); + } + f_print (fout, "\tpid_t pid;\n"); + f_print (fout, "\tint i;\n"); + f_print (fout, "\tchar mname[FMNAMESZ + 1];\n\n"); + + if (mtflag & timerflag) + f_print (fout, + "\tmutex_init (&_svcstate_lock, USYNC_THREAD, NULL);\n"); + + write_pm_most (infile, netflag); + f_print (fout, "\telse {\n"); + write_rpc_svc_fg (infile, "\t\t"); + f_print (fout, "\t}\n"); + } + else + { + f_print (fout, "\tregister SVCXPRT *%s;\n", TRANSP); + f_print (fout, "\n"); + print_pmapunset ("\t"); + } + } + + if (logflag && !inetdflag) + { + open_log_file (infile, "\t"); + } +} + +/* + * write a registration for the given transport + */ +void +write_netid_register (const char *transp) +{ + list *l; + definition *def; + version_list *vp; + const char *sp; + char tmpbuf[32]; + + sp = ""; + f_print (fout, "\n"); + f_print (fout, "%s\tnconf = getnetconfigent (\"%s\");\n", sp, transp); + f_print (fout, "%s\tif (nconf == NULL) {\n", sp); + (void) sprintf (_errbuf, "cannot find %s netid.", transp); + sprintf (tmpbuf, "%s\t\t", sp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit (1);\n", sp); + f_print (fout, "%s\t}\n", sp); + f_print (fout, "%s\t%s = svc_tli_create (RPC_ANYFD, nconf, 0, 0, 0);\n", + sp, TRANSP /*, transp *//* ?!?... */ ); + f_print (fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); + sprintf (_errbuf, "cannot create %s service.", transp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit (1);\n", sp); + f_print (fout, "%s\t}\n", sp); + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "%s\t(void) rpcb_unset (%s, %s, nconf);\n", + sp, def->def_name, vp->vers_name); + f_print (fout, "%s\tif (!svc_reg (%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname (def->def_name, vp->vers_num); + f_print (fout, ", nconf)) {\n"); + (void) sprintf (_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit (1);\n", sp); + f_print (fout, "%s\t}\n", sp); + } + } + f_print (fout, "%s\tfreenetconfigent (nconf);\n", sp); +} + +/* + * write a registration for the given transport for TLI + */ +void +write_nettype_register (const char *transp) +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "\tif (!svc_create ("); + pvname (def->def_name, vp->vers_num); + f_print (fout, ", %s, %s, \"%s\")) {\n ", + def->def_name, vp->vers_name, transp); + (void) sprintf (_errbuf, + "unable to create (%s, %s) for %s.", + def->def_name, vp->vers_name, transp); + print_err_message ("\t\t"); + f_print (fout, "\t\texit (1);\n"); + f_print (fout, "\t}\n"); + } + } +} + +/* + * write the rest of the service + */ +void +write_rest (void) +{ + f_print (fout, "\n"); + if (inetdflag) + { + f_print (fout, "\tif (%s == (SVCXPRT *)NULL) {\n", TRANSP); + (void) sprintf (_errbuf, "could not create a handle"); + print_err_message ("\t\t"); + f_print (fout, "\t\texit (1);\n"); + f_print (fout, "\t}\n"); + if (timerflag) + { + f_print (fout, "\tif (_rpcpmstart) {\n"); + f_print (fout, + "\t\t(void) signal (SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print (fout, "\t\t(void) alarm (_RPCSVC_CLOSEDOWN);\n"); + f_print (fout, "\t}\n"); + } + } + f_print (fout, "\tsvc_run ();\n"); + (void) sprintf (_errbuf, "svc_run returned"); + print_err_message ("\t"); + f_print (fout, "\texit (1);\n"); + f_print (fout, "\t/* NOTREACHED */\n"); + f_print (fout, "}\n"); +} + +void +write_programs (const char *storage) +{ + list *l; + definition *def; + + /* write out stubs for procedure definitions */ + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_real_program (def); + } + } + + /* write out dispatcher for each program */ + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_program (def, storage); + } + } +} + +/* write out definition of internal function (e.g. _printmsg_1(...)) + which calls server's defintion of actual function (e.g. printmsg_1(...)). + Unpacks single user argument of printmsg_1 to call-by-value format + expected by printmsg_1. */ +static void +write_real_program (const definition * def) +{ + version_list *vp; + proc_list *proc; + decl_list *l; + + if (!newstyle) + return; /* not needed for old style */ + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + fprintf (fout, "\n"); + if (!mtflag) + internal_proctype (proc); + else + f_print (fout, "int"); + f_print (fout, "\n_"); + pvname (proc->proc_name, vp->vers_num); + if (Cflag) + { + f_print (fout, " ("); + /* arg name */ + if (proc->arg_num > 1) + f_print (fout, "%s", proc->args.argname); + else + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + if (mtflag) + { + f_print(fout, " *argp, void *%s, struct svc_req *%s)\n", + RESULT, RQSTP); + } + else + f_print (fout, " *argp, struct svc_req *%s)\n", + RQSTP); + } + else + { + if (mtflag) + f_print(fout, " (argp, %s, %s)\n", RESULT, RQSTP); + else + f_print (fout, " (argp, %s)\n", RQSTP); + /* arg name */ + if (proc->arg_num > 1) + f_print (fout, "\t%s *argp;\n", proc->args.argname); + else + { + f_print (fout, "\t"); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + f_print (fout, " *argp;\n"); + } + f_print (fout, " struct svc_req *%s;\n", RQSTP); + } + + f_print (fout, "{\n"); + f_print (fout, "\treturn ("); + if (Cflag || mtflag) + pvname_svc (proc->proc_name, vp->vers_num); + else + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "("); + if (proc->arg_num < 2) + { /* single argument */ + if (!streq (proc->args.decls->decl.type, "void")) + f_print (fout, "*argp, "); /* non-void */ + } + else + { + for (l = proc->args.decls; l != NULL; l = l->next) + f_print (fout, "argp->%s, ", l->decl.name); + } + if (mtflag) + f_print (fout, "%s, ", RESULT); + f_print (fout, "%s));\n}\n", RQSTP); + } + } +} + +static void +write_program (const definition * def, const char *storage) +{ + version_list *vp; + proc_list *proc; + int filled; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "\n"); + if (storage != NULL) + { + f_print (fout, "%s ", storage); + } + f_print (fout, "void\n"); + pvname (def->def_name, vp->vers_num); + + if (Cflag) + { + f_print (fout, "(struct svc_req *%s, ", RQSTP); + f_print (fout, "register SVCXPRT *%s)\n", TRANSP); + } + else + { + f_print (fout, "(%s, %s)\n", RQSTP, TRANSP); + f_print (fout, " struct svc_req *%s;\n", RQSTP); + f_print (fout, " register SVCXPRT *%s;\n", TRANSP); + } + + f_print (fout, "{\n"); + + filled = 0; + f_print (fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + if (proc->arg_num < 2) + { /* single argument */ + if (streq (proc->args.decls->decl.type, + "void")) + { + continue; + } + filled = 1; + f_print (fout, "\t\t"); + ptype (proc->args.decls->decl.prefix, + proc->args.decls->decl.type, 0); + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_arg;\n"); + + } + else + { + filled = 1; + f_print (fout, "\t\t%s", proc->args.argname); + f_print (fout, " "); + pvname (proc->proc_name, vp->vers_num); + f_print (fout, "_arg;\n"); + } + } + if (!filled) + { + f_print (fout, "\t\tint fill;\n"); + } + f_print (fout, "\t} %s;\n", ARG); + if (mtflag) + { + f_print(fout, "\tunion {\n"); + for (proc = vp->procs; proc != NULL; proc = proc->next) + if (!streq (proc->res_type, "void")) + { + f_print(fout, "\t\t"); + ptype(proc->res_prefix, proc->res_type, 0); + pvname(proc->proc_name, vp->vers_num); + f_print(fout, "_res;\n"); + } + f_print(fout, "\t} %s;\n", RESULT); + f_print(fout, "\tbool_t %s;\n", RETVAL); + + } else + f_print (fout, "\tchar *%s;\n", RESULT); + + if (Cflag) + { + f_print (fout, "\txdrproc_t _xdr_%s, _xdr_%s;\n", ARG, RESULT); + if (mtflag) + f_print(fout, + "\tbool_t (*%s)(char *, void *, struct svc_req *);\n", + ROUTINE); + else + f_print (fout, "\tchar *(*%s)(char *, struct svc_req *);\n", + ROUTINE); + } + else + { + f_print (fout, "\tbool_t (*_xdr_%s)(), (*_xdr_%s)();\n", ARG, RESULT); + if (mtflag) + f_print(fout, "\tbool_t (*%s)();\n", ROUTINE); + else + f_print (fout, "\tchar *(*%s)();\n", ROUTINE); + } + f_print (fout, "\n"); + + if (timerflag) +#if 0 + f_print (fout, "\t_rpcsvcdirty = 1;\n"); +#else + { + if (mtflag) + f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); + f_print(fout, "\t_rpcsvcstate = _SERVING;\n"); + if (mtflag) + f_print(fout, "\tmutex_unlock(&_svcstate_lock);\n"); + } +#endif + + f_print (fout, "\tswitch (%s->rq_proc) {\n", RQSTP); + if (!nullproc (vp->procs)) + { + f_print (fout, "\tcase NULLPROC:\n"); + f_print (fout, + "\t\t(void) svc_sendreply (%s, (xdrproc_t) xdr_void, (char *)NULL);\n", + TRANSP); + print_return ("\t\t"); + f_print (fout, "\n"); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + f_print (fout, "\tcase %s:\n", proc->proc_name); + if (proc->arg_num < 2) + { /* single argument */ + p_xdrfunc (ARG, proc->args.decls->decl.type); + } + else + { + p_xdrfunc (ARG, proc->args.argname); + } + p_xdrfunc (RESULT, proc->res_type); + if (Cflag) + { + if (mtflag) + f_print(fout, + "\t\t%s = (bool_t (*) (char *, void *, struct svc_req *))", + ROUTINE); + else + f_print (fout, + "\t\t%s = (char *(*)(char *, struct svc_req *)) ", + ROUTINE); + } + else + if (mtflag) + f_print(fout, "\t\t%s = (bool_t (*)()) ", ROUTINE); + else + f_print (fout, "\t\t%s = (char *(*)()) ", ROUTINE); + + if (newstyle) + { /* new style: calls internal routine */ + f_print (fout, "_"); + } + if ((Cflag || mtflag) && !newstyle) + pvname_svc (proc->proc_name, vp->vers_num); + else + pvname (proc->proc_name, vp->vers_num); + f_print (fout, ";\n"); + f_print (fout, "\t\tbreak;\n\n"); + } + f_print (fout, "\tdefault:\n"); + printerr ("noproc", TRANSP); + print_return ("\t\t"); + f_print (fout, "\t}\n"); + + f_print (fout, "\tmemset ((char *)&%s, 0, sizeof (%s));\n", ARG, ARG); + printif ("getargs", TRANSP, ARG); + printerr ("decode", TRANSP); + print_return ("\t\t"); + f_print (fout, "\t}\n"); + + if (!mtflag) + { + if (Cflag) + f_print (fout, "\t%s = (*%s)((char *)&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); + else + f_print (fout, "\t%s = (*%s)(&%s, %s);\n", + RESULT, ROUTINE, ARG, RQSTP); + } + else + if (Cflag) + f_print(fout, "\t%s = (bool_t) (*%s)((char *)&%s, (void *)&%s, %s);\n", + RETVAL, ROUTINE, ARG, RESULT, RQSTP); + else + f_print(fout, "\t%s = (bool_t) (*%s)(&%s, &%s, %s);\n", + RETVAL, ROUTINE, ARG, RESULT, RQSTP); + if (mtflag) + f_print(fout, + "\tif (%s > 0 && !svc_sendreply(%s, (xdrproc_t) _xdr_%s, (char *)&%s)) {\n", + RETVAL, TRANSP, RESULT, RESULT); + else + f_print(fout, + "\tif (%s != NULL && !svc_sendreply(%s, (xdrproc_t) _xdr_%s, %s)) {\n", + RESULT, TRANSP, RESULT, RESULT); + + printerr ("systemerr", TRANSP); + f_print (fout, "\t}\n"); + + printif ("freeargs", TRANSP, ARG); + + sprintf (_errbuf, "unable to free arguments"); + print_err_message ("\t\t"); + f_print (fout, "\t\texit (1);\n"); + f_print (fout, "\t}\n"); + /* print out free routine */ + if (mtflag) + { + f_print(fout,"\tif (!"); + pvname(def->def_name, vp->vers_num); + f_print(fout,"_freeresult (%s, _xdr_%s, (caddr_t) &%s))\n", + TRANSP, RESULT, RESULT); + (void) sprintf(_errbuf, "unable to free results"); + print_err_message("\t\t"); + f_print(fout, "\n"); + } + print_return ("\t"); + f_print (fout, "}\n"); + } +} + +static void +printerr (const char *err, const char *transp) +{ + f_print (fout, "\t\tsvcerr_%s (%s);\n", err, transp); +} + +static void +printif (const char *proc, const char *transp, const char *arg) +{ + f_print (fout, "\tif (!svc_%s (%s, (xdrproc_t) _xdr_%s, (caddr_t) &%s)) {\n", + proc, transp, arg, arg); +} + +int +nullproc (const proc_list * proc) +{ + for (; proc != NULL; proc = proc->next) + { + if (streq (proc->proc_num, "0")) + { + return 1; + } + } + return 0; +} + +static void +write_inetmost (const char *infile) +{ + f_print (fout, "\tregister SVCXPRT *%s;\n", TRANSP); + f_print (fout, "\tint sock;\n"); + f_print (fout, "\tint proto;\n"); + f_print (fout, "\tstruct sockaddr_in saddr;\n"); + f_print (fout, "\tint asize = sizeof (saddr);\n"); + f_print (fout, "\n"); + f_print (fout, + "\tif (getsockname (0, (struct sockaddr *)&saddr, &asize) == 0) {\n"); + f_print (fout, "\t\tint ssize = sizeof (int);\n\n"); + f_print (fout, "\t\tif (saddr.sin_family != AF_INET)\n"); + f_print (fout, "\t\t\texit (1);\n"); + f_print (fout, "\t\tif (getsockopt (0, SOL_SOCKET, SO_TYPE,\n"); + f_print (fout, "\t\t\t\t(char *)&_rpcfdtype, &ssize) == -1)\n"); + f_print (fout, "\t\t\texit (1);\n"); + f_print (fout, "\t\tsock = 0;\n"); + f_print (fout, "\t\t_rpcpmstart = 1;\n"); + f_print (fout, "\t\tproto = 0;\n"); + open_log_file (infile, "\t\t"); + f_print (fout, "\t} else {\n"); + write_rpc_svc_fg (infile, "\t\t"); + f_print (fout, "\t\tsock = RPC_ANYSOCK;\n"); + print_pmapunset ("\t\t"); + f_print (fout, "\t}\n"); +} + +static void +print_return (const char *space) +{ + if (exitnow) + f_print (fout, "%sexit (0);\n", space); + else + { + if (timerflag) + { +#if 0 + f_print (fout, "%s_rpcsvcdirty = 0;\n", space); +#else + if (mtflag) + f_print(fout, "%smutex_lock(&_svcstate_lock);\n", space); + f_print(fout, "%s_rpcsvcstate = _SERVED;\n", space); + if (mtflag) + f_print(fout, "%smutex_unlock(&_svcstate_lock);\n", space); +#endif + } + f_print (fout, "%sreturn;\n", space); + } +} + +static void +print_pmapunset (const char *space) +{ + list *l; + definition *def; + version_list *vp; + + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + for (vp = def->def.pr.versions; vp != NULL; + vp = vp->next) + { + f_print (fout, "%spmap_unset (%s, %s);\n", + space, def->def_name, vp->vers_name); + } + } + } +} + +static void +print_err_message (const char *space) +{ + if (logflag) + f_print (fout, "%ssyslog (LOG_ERR, \"%%s\", \"%s\");\n", space, _errbuf); + else if (inetdflag || pmflag) + f_print (fout, "%s_msgout (\"%s\");\n", space, _errbuf); + else + f_print (fout, "%sfprintf (stderr, \"%%s\", \"%s\");\n", space, _errbuf); +} + +/* + * Write the server auxiliary function ( _msgout, timeout) + */ +void +write_svc_aux (int nomain) +{ + if (!logflag) + write_msg_out (); + if (!nomain) + write_timeout_func (); +} + +/* + * Write the _msgout function + */ + +void +write_msg_out (void) +{ + f_print (fout, "\n"); + f_print (fout, "static\n"); + if (!Cflag) + { + f_print (fout, "void _msgout (msg)\n"); + f_print (fout, "\tchar *msg;\n"); + } + else + { + f_print (fout, "void _msgout (char* msg)\n"); + } + f_print (fout, "{\n"); + f_print (fout, "#ifdef RPC_SVC_FG\n"); + if (inetdflag || pmflag) + f_print (fout, "\tif (_rpcpmstart)\n"); + f_print (fout, "\t\tsyslog (LOG_ERR, \"%%s\", msg);\n"); + f_print (fout, "\telse\n"); + f_print (fout, "\t\tfprintf (stderr, \"%%s\\n\", msg);\n"); + f_print (fout, "#else\n"); + f_print (fout, "\tsyslog (LOG_ERR, \"%%s\", msg);\n"); + f_print (fout, "#endif\n"); + f_print (fout, "}\n"); +} + +/* + * Write the timeout function + */ +static void +write_timeout_func (void) +{ + if (!timerflag) + return; + f_print (fout, "\n"); + f_print (fout, "static void\n"); + if (Cflag) + f_print (fout, "closedown (int sig)\n"); + else + f_print (fout, "closedown (sig)\n\tint sig;\n"); + f_print (fout, "{\n"); + +#if 0 + f_print (fout, "\t(void) signal (sig, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); +#endif + if (mtflag) + f_print(fout, "\tmutex_lock(&_svcstate_lock);\n"); +#if 0 + f_print (fout, "\tif (_rpcsvcdirty == 0) {\n"); +#else + f_print(fout, "\tif (_rpcsvcstate == _IDLE) {\n"); +#endif + f_print (fout, "\t\textern fd_set svc_fdset;\n"); + f_print (fout, "\t\tstatic int size;\n"); + f_print (fout, "\t\tint i, openfd;\n"); + if (tirpcflag && pmflag) + { + f_print (fout, "\t\tstruct t_info tinfo;\n\n"); + f_print (fout, "\t\tif (!t_getinfo(0, &tinfo) && (tinfo.servtype == T_CLTS))\n"); + } + else + { + f_print (fout, "\n\t\tif (_rpcfdtype == SOCK_DGRAM)\n"); + } + f_print (fout, "\t\t\texit (0);\n"); + f_print (fout, "\t\tif (size == 0) {\n"); + if (tirpcflag) + { + f_print (fout, "\t\t\tstruct rlimit rl;\n\n"); + f_print (fout, "\t\t\trl.rlim_max = 0;\n"); + f_print (fout, "\t\t\tgetrlimit(RLIMIT_NOFILE, &rl);\n"); + f_print (fout, "\t\t\tif ((size = rl.rlim_max) == 0) {\n"); + if (mtflag) + f_print(fout, "\t\t\t\tmutex_unlock(&_svcstate_lock);\n"); + f_print (fout, "\t\t\t\treturn;\n\t\t\t}\n"); + } + else + { + f_print (fout, "\t\t\tsize = getdtablesize();\n"); + } + f_print (fout, "\t\t}\n"); + f_print (fout, "\t\tfor (i = 0, openfd = 0; i < size && openfd < 2; i++)\n"); + f_print (fout, "\t\t\tif (FD_ISSET(i, &svc_fdset))\n"); + f_print (fout, "\t\t\t\topenfd++;\n"); + f_print (fout, "\t\tif (openfd <= 1)\n"); + f_print (fout, "\t\t\texit (0);\n"); + f_print (fout, "\t}\n"); + f_print(fout, "\tif (_rpcsvcstate == _SERVED)\n"); + f_print(fout, "\t\t_rpcsvcstate = _IDLE;\n\n"); + if (mtflag) + f_print(fout, "\tmutex_unlock(&_svcstate_lock);\n"); + f_print(fout, "\t(void) signal(SIGALRM, %s closedown);\n", + Cflag? "(SIG_PF)" : "(void(*)())"); + f_print (fout, "\talarm (_RPCSVC_CLOSEDOWN);\n"); + f_print (fout, "}\n"); +} + +/* + * Write the most of port monitor support + */ +static void +write_pm_most (const char *infile, int netflag) +{ + list *l; + definition *def; + version_list *vp; + + f_print (fout, "\tif (!ioctl(0, I_LOOK, mname) &&\n"); + f_print (fout, "\t\t(!strcmp(mname, \"sockmod\") ||"); + f_print (fout, " !strcmp(mname, \"timod\"))) {\n"); + f_print (fout, "\t\tchar *netid;\n"); + if (!netflag) + { /* Not included by -n option */ + f_print (fout, "\t\tstruct netconfig *nconf = NULL;\n"); + f_print (fout, "\t\tSVCXPRT *%s;\n", TRANSP); + } + if (timerflag) + f_print (fout, "\t\tint pmclose;\n"); +/* not necessary, defined in /usr/include/stdlib */ +/* f_print(fout, "\t\textern char *getenv();\n"); */ + f_print (fout, "\n"); + f_print (fout, "\t\t_rpcpmstart = 1;\n"); + if (logflag) + open_log_file (infile, "\t\t"); + f_print (fout, "\t\tif ((netid = getenv(\"NLSPROVIDER\")) == NULL) {\n"); + sprintf (_errbuf, "cannot get transport name"); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t} else if ((nconf = getnetconfigent(netid)) == NULL) {\n"); + sprintf (_errbuf, "cannot get transport info"); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t}\n"); + /* + * A kludgy support for inetd services. Inetd only works with + * sockmod, and RPC works only with timod, hence all this jugglery + */ + f_print (fout, "\t\tif (strcmp(mname, \"sockmod\") == 0) {\n"); + f_print (fout, "\t\t\tif (ioctl(0, I_POP, 0) || ioctl(0, I_PUSH, \"timod\")) {\n"); + sprintf (_errbuf, "could not get the right module"); + print_err_message ("\t\t\t\t"); + f_print (fout, "\t\t\t\texit(1);\n"); + f_print (fout, "\t\t\t}\n"); + f_print (fout, "\t\t}\n"); + if (timerflag) + f_print (fout, "\t\tpmclose = (t_getstate(0) != T_DATAXFER);\n"); + f_print (fout, "\t\tif ((%s = svc_tli_create(0, nconf, NULL, 0, 0)) == NULL) {\n", + TRANSP); + sprintf (_errbuf, "cannot create server handle"); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t\texit(1);\n"); + f_print (fout, "\t\t}\n"); + f_print (fout, "\t\tif (nconf)\n"); + f_print (fout, "\t\t\tfreenetconfigent(nconf);\n"); + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, + "\t\tif (!svc_reg(%s, %s, %s, ", + TRANSP, def->def_name, vp->vers_name); + pvname (def->def_name, vp->vers_num); + f_print (fout, ", 0)) {\n"); + (void) sprintf (_errbuf, "unable to register (%s, %s).", + def->def_name, vp->vers_name); + print_err_message ("\t\t\t"); + f_print (fout, "\t\t\texit(1);\n"); + f_print (fout, "\t\t}\n"); + } + } + if (timerflag) + { + f_print (fout, "\t\tif (pmclose) {\n"); + f_print (fout, "\t\t\t(void) signal(SIGALRM, %s closedown);\n", + Cflag ? "(SIG_PF)" : "(void(*)())"); + f_print (fout, "\t\t\t(void) alarm(_RPCSVC_CLOSEDOWN);\n"); + f_print (fout, "\t\t}\n"); + } + f_print (fout, "\t\tsvc_run();\n"); + f_print (fout, "\t\texit(1);\n"); + f_print (fout, "\t\t/* NOTREACHED */\n"); + f_print (fout, "\t}\n"); +} + +/* + * Support for backgrounding the server if self started. + */ +static void +write_rpc_svc_fg (const char *infile, const char *sp) +{ + f_print (fout, "#ifndef RPC_SVC_FG\n"); + f_print (fout, "%sint size;\n", sp); + if (tirpcflag) + f_print (fout, "%sstruct rlimit rl;\n", sp); + if (inetdflag) + f_print (fout, "%sint pid, i;\n\n", sp); + f_print (fout, "%spid = fork();\n", sp); + f_print (fout, "%sif (pid < 0) {\n", sp); + f_print (fout, "%s\tperror(\"cannot fork\");\n", sp); + f_print (fout, "%s\texit(1);\n", sp); + f_print (fout, "%s}\n", sp); + f_print (fout, "%sif (pid)\n", sp); + f_print (fout, "%s\texit(0);\n", sp); + /* get number of file descriptors */ + if (tirpcflag) + { + f_print (fout, "%srl.rlim_max = 0;\n", sp); + f_print (fout, "%sgetrlimit(RLIMIT_NOFILE, &rl);\n", sp); + f_print (fout, "%sif ((size = rl.rlim_max) == 0)\n", sp); + f_print (fout, "%s\texit(1);\n", sp); + } + else + { + f_print (fout, "%ssize = getdtablesize();\n", sp); + } + + f_print (fout, "%sfor (i = 0; i < size; i++)\n", sp); + f_print (fout, "%s\t(void) close(i);\n", sp); + /* Redirect stderr and stdout to console */ + f_print (fout, "%si = open(\"/dev/console\", 2);\n", sp); + f_print (fout, "%s(void) dup2(i, 1);\n", sp); + f_print (fout, "%s(void) dup2(i, 2);\n", sp); + /* This removes control of the controlling terminal */ + if (tirpcflag) + f_print (fout, "%ssetsid();\n", sp); + else + { + f_print (fout, "%si = open(\"/dev/tty\", 2);\n", sp); + f_print (fout, "%sif (i >= 0) {\n", sp); + f_print (fout, "%s\t(void) ioctl(i, TIOCNOTTY, (char *)NULL);\n", sp);; + f_print (fout, "%s\t(void) close(i);\n", sp); + f_print (fout, "%s}\n", sp); + } + if (!logflag) + open_log_file (infile, sp); + f_print (fout, "#endif\n"); + if (logflag) + open_log_file (infile, sp); +} + +static void +open_log_file (const char *infile, const char *sp) +{ + char *s; + + s = strrchr (infile, '.'); + if (s) + *s = '\0'; + f_print (fout, "%sopenlog(\"%s\", LOG_PID, LOG_DAEMON);\n", sp, infile); + if (s) + *s = '.'; +} + +/* + * write a registration for the given transport for Inetd + */ +void +write_inetd_register (const char *transp) +{ + list *l; + definition *def; + version_list *vp; + const char *sp; + int isudp; + char tmpbuf[32]; + + if (inetdflag) + sp = "\t"; + else + sp = ""; + if (streq (transp, "udp") || streq (transp, "udp6")) + isudp = 1; + else + isudp = 0; + f_print (fout, "\n"); + if (inetdflag) + { + f_print (fout, "\tif ((_rpcfdtype == 0) || (_rpcfdtype == %s)) {\n", + isudp ? "SOCK_DGRAM" : "SOCK_STREAM"); + } + f_print (fout, "%s\t%s = svc%s_create(%s", + sp, TRANSP, transp, inetdflag ? "sock" : "RPC_ANYSOCK"); + if (!isudp) + f_print (fout, ", 0, 0"); + f_print (fout, ");\n"); + f_print (fout, "%s\tif (%s == NULL) {\n", sp, TRANSP); + (void) sprintf (_errbuf, "cannot create %s service.", transp); + (void) sprintf (tmpbuf, "%s\t\t", sp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit(1);\n", sp); + f_print (fout, "%s\t}\n", sp); + + if (inetdflag) + { + f_print (fout, "%s\tif (!_rpcpmstart)\n\t", sp); + f_print (fout, "%s\tproto = IPPROTO_%s;\n", + sp, isudp ? "UDP" : "TCP"); + } + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind != DEF_PROGRAM) + { + continue; + } + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + f_print (fout, "%s\tif (!svc_register(%s, %s, %s, ", + sp, TRANSP, def->def_name, vp->vers_name); + pvname (def->def_name, vp->vers_num); + if (inetdflag) + f_print (fout, ", proto)) {\n"); + else + f_print (fout, ", IPPROTO_%s)) {\n", + isudp ? "UDP" : "TCP"); + (void) sprintf (_errbuf, "unable to register (%s, %s, %s).", + def->def_name, vp->vers_name, transp); + print_err_message (tmpbuf); + f_print (fout, "%s\t\texit(1);\n", sp); + f_print (fout, "%s\t}\n", sp); + } + } + if (inetdflag) + f_print (fout, "\t}\n"); +} diff --git a/REORG.TODO/sunrpc/rpc_tblout.c b/REORG.TODO/sunrpc/rpc_tblout.c new file mode 100644 index 0000000000..a7d2f43528 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_tblout.c @@ -0,0 +1,178 @@ +/* + * From: @(#)rpc_tblout.c 1.4 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_tblout.c, Dispatch table outputter for the RPC protocol compiler + */ +#include <stdio.h> +#include <string.h> +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define TABSIZE 8 +#define TABCOUNT 5 +#define TABSTOP (TABSIZE*TABCOUNT) + +static const char tabstr[TABCOUNT + 1] = "\t\t\t\t\t"; + +static const char tbl_hdr[] = "struct rpcgen_table %s_table[] = {\n"; +static const char tbl_end[] = "};\n"; + +static const char null_entry[] = "\n\t(char *(*)())0,\n\ + \t(xdrproc_t) xdr_void,\t\t\t0,\n\ + \t(xdrproc_t) xdr_void,\t\t\t0,\n"; + + +static const char tbl_nproc[] = "int %s_nproc =\n\tsizeof(%s_table)/sizeof(%s_table[0]);\n\n"; + +static void write_table (const definition * def); +static void printit (const char *prefix, const char *type); + +void +write_tables (void) +{ + list *l; + definition *def; + + f_print (fout, "\n"); + for (l = defined; l != NULL; l = l->next) + { + def = (definition *) l->val; + if (def->def_kind == DEF_PROGRAM) + { + write_table (def); + } + } +} + +static void +write_table (const definition * def) +{ + version_list *vp; + proc_list *proc; + int current; + int expected; + char progvers[100]; + int warning; + + for (vp = def->def.pr.versions; vp != NULL; vp = vp->next) + { + warning = 0; + s_print (progvers, "%s_%s", + locase (def->def_name), vp->vers_num); + /* print the table header */ + f_print (fout, tbl_hdr, progvers); + + if (nullproc (vp->procs)) + { + expected = 0; + } + else + { + expected = 1; + f_print (fout, null_entry); + } + for (proc = vp->procs; proc != NULL; proc = proc->next) + { + current = atoi (proc->proc_num); + if (current != expected++) + { + f_print (fout, + "\n/*\n * WARNING: table out of order\n */\n"); + if (warning == 0) + { + f_print (stderr, + "WARNING %s table is out of order\n", + progvers); + warning = 1; + nonfatalerrors = 1; + } + expected = current + 1; + } + f_print (fout, "\n\t(char *(*)())RPCGEN_ACTION("); + + /* routine to invoke */ + if (Cflag && !newstyle) + pvname_svc (proc->proc_name, vp->vers_num); + else + { + if (newstyle) + f_print (fout, "_"); /* calls internal func */ + pvname (proc->proc_name, vp->vers_num); + } + f_print (fout, "),\n"); + + /* argument info */ + if (proc->arg_num > 1) + printit ((char *) NULL, proc->args.argname); + else + /* do we have to do something special for newstyle */ + printit (proc->args.decls->decl.prefix, + proc->args.decls->decl.type); + /* result info */ + printit (proc->res_prefix, proc->res_type); + } + + /* print the table trailer */ + f_print (fout, tbl_end); + f_print (fout, tbl_nproc, progvers, progvers, progvers); + } +} + +static void +printit (const char *prefix, const char *type) +{ + int len; + int tabs; + + + len = fprintf (fout, "\txdr_%s,", stringfix (type)); + /* account for leading tab expansion */ + len += TABSIZE - 1; + /* round up to tabs required */ + tabs = (TABSTOP - len + TABSIZE - 1) / TABSIZE; + f_print (fout, "%s", &tabstr[TABCOUNT - tabs]); + + if (streq (type, "void")) + { + f_print (fout, "0"); + } + else + { + f_print (fout, "sizeof ( "); + /* XXX: should "follow" be 1 ??? */ + ptype (prefix, type, 0); + f_print (fout, ")"); + } + f_print (fout, ",\n"); +} diff --git a/REORG.TODO/sunrpc/rpc_thread.c b/REORG.TODO/sunrpc/rpc_thread.c new file mode 100644 index 0000000000..ccbf9bb69b --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_thread.c @@ -0,0 +1,140 @@ +#include <stdio.h> +#include <rpc/rpc.h> +#include <assert.h> + +#include <libc-lock.h> +#include <libc-tsd.h> +#include <shlib-compat.h> + +#ifdef _RPC_THREAD_SAFE_ + +/* Variable used in non-threaded applications or for the first thread. */ +static struct rpc_thread_variables __libc_tsd_RPC_VARS_mem; +static __thread struct rpc_thread_variables *thread_rpc_vars + attribute_tls_model_ie; + +/* + * Task-variable destructor + */ +void __attribute__ ((section ("__libc_thread_freeres_fn"))) +__rpc_thread_destroy (void) +{ + struct rpc_thread_variables *tvp = thread_rpc_vars; + + if (tvp != NULL) { + __rpc_thread_svc_cleanup (); + __rpc_thread_clnt_cleanup (); + __rpc_thread_key_cleanup (); + free (tvp->clnt_perr_buf_s); + free (tvp->clntraw_private_s); + free (tvp->svcraw_private_s); + free (tvp->authdes_cache_s); + free (tvp->authdes_lru_s); + free (tvp->svc_xports_s); + free (tvp->svc_pollfd_s); + if (tvp != &__libc_tsd_RPC_VARS_mem) + free (tvp); + thread_rpc_vars = NULL; + } +} +#ifdef _LIBC_REENTRANT +text_set_element (__libc_thread_subfreeres, __rpc_thread_destroy); +#endif +text_set_element (__libc_subfreeres, __rpc_thread_destroy); + + +/* + * Initialize RPC multi-threaded operation + */ +static void +rpc_thread_multi (void) +{ + thread_rpc_vars = &__libc_tsd_RPC_VARS_mem; +} + + +struct rpc_thread_variables * +__rpc_thread_variables (void) +{ + __libc_once_define (static, once); + struct rpc_thread_variables *tvp = thread_rpc_vars; + + if (tvp == NULL) { + __libc_once (once, rpc_thread_multi); + tvp = thread_rpc_vars; + if (tvp == NULL) { + tvp = calloc (1, sizeof *tvp); + if (tvp != NULL) + thread_rpc_vars = tvp; + } + } + return tvp; +} + + +/* Global variables If we're single-threaded, or if this is the first + thread using the variable, use the existing global variable. This + provides backwards compatibility for existing applications which + dynamically link against this code. */ +#undef svc_fdset +#undef rpc_createerr +#undef svc_pollfd +#undef svc_max_pollfd + +fd_set * +__rpc_thread_svc_fdset (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_fdset; + return &tvp->svc_fdset_s; +} +libc_hidden_nolink_sunrpc (__rpc_thread_svc_fdset, GLIBC_2_2_3) + +struct rpc_createerr * +__rpc_thread_createerr (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &rpc_createerr; + return &tvp->rpc_createerr_s; +} +libc_hidden_nolink_sunrpc (__rpc_thread_createerr, GLIBC_2_2_3) + +struct pollfd ** +__rpc_thread_svc_pollfd (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_pollfd; + return &tvp->svc_pollfd_s; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (__rpc_thread_svc_pollfd) +#else +libc_hidden_nolink_sunrpc (__rpc_thread_svc_pollfd, GLIBC_2_2_3) +#endif + +int * +__rpc_thread_svc_max_pollfd (void) +{ + struct rpc_thread_variables *tvp; + + tvp = __rpc_thread_variables (); + if (tvp == &__libc_tsd_RPC_VARS_mem) + return &svc_max_pollfd; + return &tvp->svc_max_pollfd_s; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (__rpc_thread_svc_max_pollfd) +#else +libc_hidden_nolink_sunrpc (__rpc_thread_svc_max_pollfd, GLIBC_2_2_3) +#endif + +#endif /* _RPC_THREAD_SAFE_ */ diff --git a/REORG.TODO/sunrpc/rpc_util.c b/REORG.TODO/sunrpc/rpc_util.c new file mode 100644 index 0000000000..52aa69757b --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_util.c @@ -0,0 +1,525 @@ +/* + * From: @(#)rpc_util.c 1.11 89/02/22 + * + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * rpc_util.c, Utility routines for the RPC protocol compiler + */ +#include <stdio.h> +#include <ctype.h> +#include <string.h> +#include <unistd.h> +#include "rpc_scan.h" +#include "rpc_parse.h" +#include "rpc_util.h" +#include "proto.h" + +#define ARGEXT "argument" + +char curline[MAXLINESIZE]; /* current read line */ +const char *where = curline; /* current point in line */ +int linenum = 0; /* current line number */ + +const char *infilename; /* input filename */ + +#define NFILES 7 +const char *outfiles[NFILES]; /* output file names */ +int nfiles; + +FILE *fout; /* file pointer of current output */ +FILE *fin; /* file pointer of current input */ + +list *defined; /* list of defined things */ + +static int findit (const definition * def, const char *type); +static const char *fixit (const char *type, const char *orig); +static int typedefed (const definition * def, const char *type); +static const char *toktostr (tok_kind kind); +static void printbuf (void); +static void printwhere (void); + +/* + * Reinitialize the world + */ +void +reinitialize (void) +{ + memset (curline, 0, MAXLINESIZE); + where = curline; + linenum = 0; + defined = NULL; +} + +/* + * string equality + */ +int +streq (const char *a, const char *b) +{ + return strcmp (a, b) == 0; +} + +/* + * find a value in a list + */ +definition * +findval (list *lst, const char *val, + int (*cmp) (const definition *, const char *)) +{ + + for (; lst != NULL; lst = lst->next) + { + if (cmp (lst->val, val)) + { + return lst->val; + } + } + return NULL; +} + +/* + * store a value in a list + */ +void +storeval (list **lstp, definition *val) +{ + list **l; + list *lst; + + + for (l = lstp; *l != NULL; l = (list **) & (*l)->next); + lst = ALLOC (list); + lst->val = val; + lst->next = NULL; + *l = lst; +} + +static int +findit (const definition * def, const char *type) +{ + return streq (def->def_name, type); +} + +static const char * +fixit (const char *type, const char *orig) +{ + definition *def; + + def = findval (defined, type, findit); + if (def == NULL || def->def_kind != DEF_TYPEDEF) + { + return orig; + } + switch (def->def.ty.rel) + { + case REL_VECTOR: + if (streq (def->def.ty.old_type, "opaque")) + return ("char"); + else + return (def->def.ty.old_type); + case REL_ALIAS: + return (fixit (def->def.ty.old_type, orig)); + default: + return orig; + } +} + +const char * +fixtype (const char *type) +{ + return fixit (type, type); +} + +const char * +stringfix (const char *type) +{ + if (streq (type, "string")) + { + return "wrapstring"; + } + else + { + return type; + } +} + +void +ptype (const char *prefix, const char *type, int follow) +{ + if (prefix != NULL) + { + if (streq (prefix, "enum")) + { + f_print (fout, "enum "); + } + else + { + f_print (fout, "struct "); + } + } + if (streq (type, "bool")) + { + f_print (fout, "bool_t "); + } + else if (streq (type, "string")) + { + f_print (fout, "char *"); + } + else + { + f_print (fout, "%s ", follow ? fixtype (type) : type); + } +} + +static int +typedefed (const definition * def, const char *type) +{ + if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) + { + return 0; + } + else + { + return streq (def->def_name, type); + } +} + +int +isvectordef (const char *type, relation rel) +{ + definition *def; + + for (;;) + { + switch (rel) + { + case REL_VECTOR: + return !streq (type, "string"); + case REL_ARRAY: + return 0; + case REL_POINTER: + return 0; + case REL_ALIAS: + def = findval (defined, type, typedefed); + if (def == NULL) + { + return 0; + } + type = def->def.ty.old_type; + rel = def->def.ty.rel; + } + } +} + +char * +locase (const char *str) +{ + char c; + static char buf[100]; + char *p = buf; + + while ((c = *str++) != 0) + { + *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; + } + *p = 0; + return buf; +} + +void +pvname_svc (const char *pname, const char *vnum) +{ + f_print (fout, "%s_%s_svc", locase (pname), vnum); +} + +void +pvname (const char *pname, const char *vnum) +{ + f_print (fout, "%s_%s", locase (pname), vnum); +} + +/* + * print a useful (?) error message, and then die + */ +void +error (const char *msg) +{ + printwhere (); + f_print (stderr, "%s, line %d: ", infilename, linenum); + f_print (stderr, "%s\n", msg); + crash (); +} + +/* + * Something went wrong, unlink any files that we may have created and then + * die. + */ +void +crash (void) +{ + int i; + + for (i = 0; i < nfiles; i++) + { + unlink (outfiles[i]); + } + exit (1); +} + +void +record_open (const char *file) +{ + if (nfiles < NFILES) + { + outfiles[nfiles++] = file; + } + else + { + f_print (stderr, "too many files!\n"); + crash (); + } +} + +static char expectbuf[100]; + +/* + * error, token encountered was not the expected one + */ +void +expected1 (tok_kind exp1) +{ + s_print (expectbuf, "expected '%s'", + toktostr (exp1)); + error (expectbuf); +} + +/* + * error, token encountered was not one of two expected ones + */ +void +expected2 (tok_kind exp1, tok_kind exp2) +{ + s_print (expectbuf, "expected '%s' or '%s'", + toktostr (exp1), + toktostr (exp2)); + error (expectbuf); +} + +/* + * error, token encountered was not one of 3 expected ones + */ +void +expected3 (tok_kind exp1, tok_kind exp2, tok_kind exp3) +{ + s_print (expectbuf, "expected '%s', '%s' or '%s'", + toktostr (exp1), + toktostr (exp2), + toktostr (exp3)); + error (expectbuf); +} + +void +tabify (FILE * f, int tab) +{ + while (tab--) + { + (void) fputc ('\t', f); + } +} + + +static const token tokstrings[] = +{ + {TOK_IDENT, "identifier"}, + {TOK_CONST, "const"}, + {TOK_RPAREN, ")"}, + {TOK_LPAREN, "("}, + {TOK_RBRACE, "}"}, + {TOK_LBRACE, "{"}, + {TOK_LBRACKET, "["}, + {TOK_RBRACKET, "]"}, + {TOK_STAR, "*"}, + {TOK_COMMA, ","}, + {TOK_EQUAL, "="}, + {TOK_COLON, ":"}, + {TOK_SEMICOLON, ";"}, + {TOK_UNION, "union"}, + {TOK_STRUCT, "struct"}, + {TOK_SWITCH, "switch"}, + {TOK_CASE, "case"}, + {TOK_DEFAULT, "default"}, + {TOK_ENUM, "enum"}, + {TOK_TYPEDEF, "typedef"}, + {TOK_INT, "int"}, + {TOK_SHORT, "short"}, + {TOK_LONG, "long"}, + {TOK_UNSIGNED, "unsigned"}, + {TOK_DOUBLE, "double"}, + {TOK_FLOAT, "float"}, + {TOK_CHAR, "char"}, + {TOK_STRING, "string"}, + {TOK_OPAQUE, "opaque"}, + {TOK_BOOL, "bool"}, + {TOK_VOID, "void"}, + {TOK_PROGRAM, "program"}, + {TOK_VERSION, "version"}, + {TOK_EOF, "??????"} +}; + +static const char * +toktostr (tok_kind kind) +{ + const token *sp; + + for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++); + return sp->str; +} + +static void +printbuf (void) +{ + char c; + int i; + int cnt; + +#define TABSIZE 4 + + for (i = 0; (c = curline[i]) != 0; i++) + { + if (c == '\t') + { + cnt = 8 - (i % TABSIZE); + c = ' '; + } + else + { + cnt = 1; + } + while (cnt--) + { + (void) fputc (c, stderr); + } + } +} + +static void +printwhere (void) +{ + int i; + char c; + int cnt; + + printbuf (); + for (i = 0; i < where - curline; i++) + { + c = curline[i]; + if (c == '\t') + { + cnt = 8 - (i % TABSIZE); + } + else + { + cnt = 1; + } + while (cnt--) + { + (void) fputc ('^', stderr); + } + } + (void) fputc ('\n', stderr); +} + +char * +make_argname (const char *pname, const char *vname) +{ + char *name; + + name = malloc (strlen (pname) + strlen (vname) + strlen (ARGEXT) + 3); + if (!name) + { + fprintf (stderr, "failed in malloc"); + exit (1); + } + sprintf (name, "%s_%s_%s", locase (pname), vname, ARGEXT); + return name; +} + +bas_type *typ_list_h; +bas_type *typ_list_t; + +void +add_type (int len, const char *type) +{ + bas_type *ptr; + + + if ((ptr = malloc (sizeof (bas_type))) == NULL) + { + fprintf (stderr, "failed in malloc"); + exit (1); + } + + ptr->name = type; + ptr->length = len; + ptr->next = NULL; + if (typ_list_t == NULL) + { + + typ_list_t = ptr; + typ_list_h = ptr; + } + else + { + + typ_list_t->next = ptr; + typ_list_t = ptr; + } + +} + + +bas_type * +find_type (const char *type) +{ + bas_type *ptr; + + ptr = typ_list_h; + + + while (ptr != NULL) + { + if (strcmp (ptr->name, type) == 0) + return ptr; + else + ptr = ptr->next; + }; + return NULL; +} diff --git a/REORG.TODO/sunrpc/rpc_util.h b/REORG.TODO/sunrpc/rpc_util.h new file mode 100644 index 0000000000..53316d9516 --- /dev/null +++ b/REORG.TODO/sunrpc/rpc_util.h @@ -0,0 +1,154 @@ +/* @(#)rpc_util.h 1.5 90/08/29 */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * rpc_util.h, Useful definitions for the RPC protocol compiler + */ + +#include <stdlib.h> + +#define alloc(size) malloc((unsigned)(size)) +#define ALLOC(object) (object *) malloc(sizeof(object)) + +#define s_print (void) sprintf +#define f_print (void) fprintf + +struct list { + definition *val; + struct list *next; +}; +typedef struct list list; + +struct xdrfunc { + char *name; + int pointerp; + struct xdrfunc *next; +}; +typedef struct xdrfunc xdrfunc; + +#define PUT 1 +#define GET 2 + +/* + * Global variables + */ +#define MAXLINESIZE 1024 +extern char curline[MAXLINESIZE]; +extern const char *where; +extern int linenum; + +extern const char *infilename; +extern FILE *fout; +extern FILE *fin; + +extern list *defined; + +extern bas_type *typ_list_h; +extern bas_type *typ_list_t; +extern xdrfunc *xdrfunc_head, *xdrfunc_tail; + +/* + * All the option flags + */ +extern int inetdflag; +extern int pmflag; +extern int tblflag; +extern int logflag; +extern int newstyle; +extern int Cflag; /* C++ flag */ +extern int CCflag; /* C++ flag */ +extern int tirpcflag; /* flag for generating tirpc code */ +extern int inlineflag; /* if this is 0, then do not generate inline code */ +extern int mtflag; + +/* + * Other flags related with inetd jumpstart. + */ +extern int indefinitewait; +extern int exitnow; +extern int timerflag; + +extern int nonfatalerrors; + +/* + * rpc_util routines + */ +void storeval(list **lstp, definition *val); +#define STOREVAL(list,item) storeval(list,item) + +definition *findval(list *lst, const char *val, + int (*cmp)(const definition *, const char *)); +#define FINDVAL(list,item,finder) findval(list, item, finder) + +const char *fixtype(const char *type); +const char *stringfix(const char *type); +char *locase(const char *str); +void pvname_svc(const char *pname, const char *vnum); +void pvname(const char *pname, const char *vnum); +void ptype(const char *prefix, const char *type, int follow); +int isvectordef(const char *type, relation rel); +int streq(const char *a, const char *b); +void error(const char *msg); +void tabify(FILE *f, int tab); +void record_open(const char *file); +bas_type *find_type(const char *type); + + +/* + * rpc_cout routines + */ +void emit(definition *def); + +/* + * rpc_hout routines + */ +void print_datadef(definition *def); +void print_funcdef(definition *def); + +/* + * rpc_svcout routines + */ +void write_most(const char *infile, int netflag, int nomain); +void write_register(void); +void write_rest(void); +void write_programs(const char *storage); +void write_svc_aux(int nomain); +void write_inetd_register(const char *transp); +void write_netid_register(const char *); +void write_nettype_register(const char *); +/* + * rpc_clntout routines + */ +void write_stubs(void); + +/* + * rpc_tblout routines + */ +void write_tables(void); diff --git a/REORG.TODO/sunrpc/rpcgen.c b/REORG.TODO/sunrpc/rpcgen.c new file mode 100644 index 0000000000..1b455ba243 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcgen.c @@ -0,0 +1,2 @@ +/* Empty file expected by glibc's standard build rules for + executables. */ diff --git a/REORG.TODO/sunrpc/rpcsvc/bootparam.h b/REORG.TODO/sunrpc/rpcsvc/bootparam.h new file mode 100644 index 0000000000..d3ca5043e7 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/bootparam.h @@ -0,0 +1,23 @@ +/* Copyright (C) 1999-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#ifndef _RPCSVC_BOOTPARAM_H +#define _RPCSVC_BOOTPARAM_H + +#include <rpcsvc/bootparam_prot.h> + +#endif /* _RPCSVC_BOOTPARAM_H */ diff --git a/REORG.TODO/sunrpc/rpcsvc/bootparam_prot.x b/REORG.TODO/sunrpc/rpcsvc/bootparam_prot.x new file mode 100644 index 0000000000..117e428560 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/bootparam_prot.x @@ -0,0 +1,97 @@ +/* @(#)bootparam_prot.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * RPC for bootparms service. + * There are two procedures: + * WHOAMI takes a net address and returns a client name and also a + * likely net address for routing + * GETFILE takes a client name and file identifier and returns the + * server name, server net address and pathname for the file. + * file identifiers typically include root, swap, pub and dump + */ + +#ifdef RPC_HDR +%#include <rpc/types.h> +%#include <sys/time.h> +%#include <sys/errno.h> +%#include <nfs/nfs.h> +#endif + +const MAX_MACHINE_NAME = 255; +const MAX_PATH_LEN = 1024; +const MAX_FILEID = 32; +const IP_ADDR_TYPE = 1; + +typedef string bp_machine_name_t<MAX_MACHINE_NAME>; +typedef string bp_path_t<MAX_PATH_LEN>; +typedef string bp_fileid_t<MAX_FILEID>; + +struct ip_addr_t { + char net; + char host; + char lh; + char impno; +}; + +union bp_address switch (int address_type) { + case IP_ADDR_TYPE: + ip_addr_t ip_addr; +}; + +struct bp_whoami_arg { + bp_address client_address; +}; + +struct bp_whoami_res { + bp_machine_name_t client_name; + bp_machine_name_t domain_name; + bp_address router_address; +}; + +struct bp_getfile_arg { + bp_machine_name_t client_name; + bp_fileid_t file_id; +}; + +struct bp_getfile_res { + bp_machine_name_t server_name; + bp_address server_address; + bp_path_t server_path; +}; + +program BOOTPARAMPROG { + version BOOTPARAMVERS { + bp_whoami_res BOOTPARAMPROC_WHOAMI(bp_whoami_arg) = 1; + bp_getfile_res BOOTPARAMPROC_GETFILE(bp_getfile_arg) = 2; + } = 1; +} = 100026; diff --git a/REORG.TODO/sunrpc/rpcsvc/key_prot.x b/REORG.TODO/sunrpc/rpcsvc/key_prot.x new file mode 100644 index 0000000000..9baf943916 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/key_prot.x @@ -0,0 +1,283 @@ +/* + * Key server protocol definition + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * The keyserver is a public key storage/encryption/decryption service + * The encryption method used is based on the Diffie-Hellman exponential + * key exchange technology. + * + * The key server is local to each machine, akin to the portmapper. + * Under TI-RPC, communication with the keyserver is through the + * loopback transport. + * + * NOTE: This .x file generates the USER level headers for the keyserver. + * the KERNEL level headers are created by hand as they kernel has special + * requirements. + */ + +%#if 0 +%#pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" +%#endif +% +%/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ +% +%/* +% * Compiled from key_prot.x using rpcgen. +% * DO NOT EDIT THIS FILE! +% * This is NOT source code! +% */ + +/* + * PROOT and MODULUS define the way the Diffie-Hellman key is generated. + * + * MODULUS should be chosen as a prime of the form: MODULUS == 2*p + 1, + * where p is also prime. + * + * PROOT satisfies the following two conditions: + * (1) (PROOT ** 2) % MODULUS != 1 + * (2) (PROOT ** p) % MODULUS != 1 + * + */ + +const PROOT = 3; +const HEXMODULUS = "d4a0ba0250b6fd2ec626e7efd637df76c716e22d0944b88b"; + +const HEXKEYBYTES = 48; /* HEXKEYBYTES == strlen(HEXMODULUS) */ +const KEYSIZE = 192; /* KEYSIZE == bit length of key */ +const KEYBYTES = 24; /* byte length of key */ + +/* + * The first 16 hex digits of the encrypted secret key are used as + * a checksum in the database. + */ +const KEYCHECKSUMSIZE = 16; + +/* + * status of operation + */ +enum keystatus { + KEY_SUCCESS, /* no problems */ + KEY_NOSECRET, /* no secret key stored */ + KEY_UNKNOWN, /* unknown netname */ + KEY_SYSTEMERR /* system error (out of memory, encryption failure) */ +}; + +typedef opaque keybuf[HEXKEYBYTES]; /* store key in hex */ + +typedef string netnamestr<MAXNETNAMELEN>; + +/* + * Argument to ENCRYPT or DECRYPT + */ +struct cryptkeyarg { + netnamestr remotename; + des_block deskey; +}; + +/* + * Argument to ENCRYPT_PK or DECRYPT_PK + */ +struct cryptkeyarg2 { + netnamestr remotename; + netobj remotekey; /* Contains a length up to 1024 bytes */ + des_block deskey; +}; + + +/* + * Result of ENCRYPT, DECRYPT, ENCRYPT_PK, and DECRYPT_PK + */ +union cryptkeyres switch (keystatus status) { +case KEY_SUCCESS: + des_block deskey; +default: + void; +}; + +const MAXGIDS = 16; /* max number of gids in gid list */ + +/* + * Unix credential + */ +struct unixcred { + u_int uid; + u_int gid; + u_int gids<MAXGIDS>; +}; + +/* + * Result returned from GETCRED + */ +union getcredres switch (keystatus status) { +case KEY_SUCCESS: + unixcred cred; +default: + void; +}; +/* + * key_netstarg; + */ + +struct key_netstarg { + keybuf st_priv_key; + keybuf st_pub_key; + netnamestr st_netname; +}; + +union key_netstres switch (keystatus status){ +case KEY_SUCCESS: + key_netstarg knet; +default: + void; +}; + +#ifdef RPC_HDR +% +%#ifndef opaque +%#define opaque char +%#endif +% +#endif +program KEY_PROG { + version KEY_VERS { + + /* + * This is my secret key. + * Store it for me. + */ + keystatus + KEY_SET(keybuf) = 1; + + /* + * I want to talk to X. + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT(cryptkeyarg) = 2; + + /* + * X just sent me a message. + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT(cryptkeyarg) = 3; + + /* + * Generate a secure conversation key for me + */ + des_block + KEY_GEN(void) = 4; + + /* + * Get me the uid, gid and group-access-list associated + * with this netname (for kernel which cannot use NIS) + */ + getcredres + KEY_GETCRED(netnamestr) = 5; + } = 1; + version KEY_VERS2 { + + /* + * ####### + * Procedures 1-5 are identical to version 1 + * ####### + */ + + /* + * This is my secret key. + * Store it for me. + */ + keystatus + KEY_SET(keybuf) = 1; + + /* + * I want to talk to X. + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT(cryptkeyarg) = 2; + + /* + * X just sent me a message. + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT(cryptkeyarg) = 3; + + /* + * Generate a secure conversation key for me + */ + des_block + KEY_GEN(void) = 4; + + /* + * Get me the uid, gid and group-access-list associated + * with this netname (for kernel which cannot use NIS) + */ + getcredres + KEY_GETCRED(netnamestr) = 5; + + /* + * I want to talk to X. and I know X's public key + * Encrypt a conversation key for me. + */ + cryptkeyres + KEY_ENCRYPT_PK(cryptkeyarg2) = 6; + + /* + * X just sent me a message. and I know X's public key + * Decrypt the conversation key for me. + */ + cryptkeyres + KEY_DECRYPT_PK(cryptkeyarg2) = 7; + + /* + * Store my public key, netname and private key. + */ + keystatus + KEY_NET_PUT(key_netstarg) = 8; + + /* + * Retrieve my public key, netname and private key. + */ + key_netstres + KEY_NET_GET(void) = 9; + + /* + * Return me the conversation key that is constructed + * from my secret key and this publickey. + */ + + cryptkeyres + KEY_GET_CONV(keybuf) = 10; + + + } = 2; +} = 100029; diff --git a/REORG.TODO/sunrpc/rpcsvc/klm_prot.x b/REORG.TODO/sunrpc/rpcsvc/klm_prot.x new file mode 100644 index 0000000000..aee5b1a962 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/klm_prot.x @@ -0,0 +1,130 @@ +/* @(#)klm_prot.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Kernel/lock manager protocol definition + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * protocol used between the UNIX kernel (the "client") and the + * local lock manager. The local lock manager is a deamon running + * above the kernel. + */ + +const LM_MAXSTRLEN = 1024; + +/* + * lock manager status returns + */ +enum klm_stats { + klm_granted = 0, /* lock is granted */ + klm_denied = 1, /* lock is denied */ + klm_denied_nolocks = 2, /* no lock entry available */ + klm_working = 3 /* lock is being processed */ +}; + +/* + * lock manager lock identifier + */ +struct klm_lock { + string server_name<LM_MAXSTRLEN>; + netobj fh; /* a counted file handle */ + int pid; /* holder of the lock */ + unsigned l_offset; /* beginning offset of the lock */ + unsigned l_len; /* byte length of the lock; + * zero means through end of file */ +}; + +/* + * lock holder identifier + */ +struct klm_holder { + bool exclusive; /* FALSE if shared lock */ + int svid; /* holder of the lock (pid) */ + unsigned l_offset; /* beginning offset of the lock */ + unsigned l_len; /* byte length of the lock; + * zero means through end of file */ +}; + +/* + * reply to KLM_LOCK / KLM_UNLOCK / KLM_CANCEL + */ +struct klm_stat { + klm_stats stat; +}; + +/* + * reply to a KLM_TEST call + */ +union klm_testrply switch (klm_stats stat) { + case klm_denied: + struct klm_holder holder; + default: /* All other cases return no arguments */ + void; +}; + + +/* + * arguments to KLM_LOCK + */ +struct klm_lockargs { + bool block; + bool exclusive; + struct klm_lock alock; +}; + +/* + * arguments to KLM_TEST + */ +struct klm_testargs { + bool exclusive; + struct klm_lock alock; +}; + +/* + * arguments to KLM_UNLOCK + */ +struct klm_unlockargs { + struct klm_lock alock; +}; + +program KLM_PROG { + version KLM_VERS { + + klm_testrply KLM_TEST (struct klm_testargs) = 1; + + klm_stat KLM_LOCK (struct klm_lockargs) = 2; + + klm_stat KLM_CANCEL (struct klm_lockargs) = 3; + /* klm_granted=> the cancel request fails due to lock is already granted */ + /* klm_denied=> the cancel request successfully aborts +lock request */ + + klm_stat KLM_UNLOCK (struct klm_unlockargs) = 4; + } = 1; +} = 100020; diff --git a/REORG.TODO/sunrpc/rpcsvc/mount.x b/REORG.TODO/sunrpc/rpcsvc/mount.x new file mode 100644 index 0000000000..ed3b339c49 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/mount.x @@ -0,0 +1,161 @@ +/* @(#)mount.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Protocol description for the mount program + */ + + +const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */ +const MNTNAMLEN = 255; /* maximum bytes in a name argument */ +const FHSIZE = 32; /* size in bytes of a file handle */ + +/* + * The fhandle is the file handle that the server passes to the client. + * All file operations are done using the file handles to refer to a file + * or a directory. The file handle can contain whatever information the + * server needs to distinguish an individual file. + */ +typedef opaque fhandle[FHSIZE]; + +/* + * If a status of zero is returned, the call completed successfully, and + * a file handle for the directory follows. A non-zero status indicates + * some sort of error. The status corresponds with UNIX error numbers. + */ +union fhstatus switch (unsigned fhs_status) { +case 0: + fhandle fhs_fhandle; +default: + void; +}; + +/* + * The type dirpath is the pathname of a directory + */ +typedef string dirpath<MNTPATHLEN>; + +/* + * The type name is used for arbitrary names (hostnames, groupnames) + */ +typedef string name<MNTNAMLEN>; + +/* + * A list of who has what mounted + */ +typedef struct mountbody *mountlist; +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; + +/* + * A list of netgroups + */ +typedef struct groupnode *groups; +struct groupnode { + name gr_name; + groups gr_next; +}; + +/* + * A list of what is exported and to whom + */ +typedef struct exportnode *exports; +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; + +program MOUNTPROG { + /* + * Version one of the mount protocol communicates with version two + * of the NFS protocol. The only connecting point is the fhandle + * structure, which is the same for both protocols. + */ + version MOUNTVERS { + /* + * Does no work. It is made available in all RPC services + * to allow server response testing and timing + */ + void + MOUNTPROC_NULL(void) = 0; + + /* + * If fhs_status is 0, then fhs_fhandle contains the + * file handle for the directory. This file handle may + * be used in the NFS protocol. This procedure also adds + * a new entry to the mount list for this client mounting + * the directory. + * Unix authentication required. + */ + fhstatus + MOUNTPROC_MNT(dirpath) = 1; + + /* + * Returns the list of remotely mounted filesystems. The + * mountlist contains one entry for each hostname and + * directory pair. + */ + mountlist + MOUNTPROC_DUMP(void) = 2; + + /* + * Removes the mount list entry for the directory + * Unix authentication required. + */ + void + MOUNTPROC_UMNT(dirpath) = 3; + + /* + * Removes all of the mount list entries for this client + * Unix authentication required. + */ + void + MOUNTPROC_UMNTALL(void) = 4; + + /* + * Returns a list of all the exported filesystems, and which + * machines are allowed to import it. + */ + exports + MOUNTPROC_EXPORT(void) = 5; + + /* + * Identical to MOUNTPROC_EXPORT above + */ + exports + MOUNTPROC_EXPORTALL(void) = 6; + } = 1; +} = 100005; diff --git a/REORG.TODO/sunrpc/rpcsvc/nfs_prot.x b/REORG.TODO/sunrpc/rpcsvc/nfs_prot.x new file mode 100644 index 0000000000..ad992e238f --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/nfs_prot.x @@ -0,0 +1,352 @@ +/* @(#)nfs_prot.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * nfs_prot.x 1.2 87/10/12 + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +const NFS_PORT = 2049; +const NFS_MAXDATA = 8192; +const NFS_MAXPATHLEN = 1024; +const NFS_MAXNAMLEN = 255; +const NFS_FHSIZE = 32; +const NFS_COOKIESIZE = 4; +const NFS_FIFO_DEV = -1; /* size kludge for named pipes */ + +/* + * File types + */ +const NFSMODE_FMT = 0170000; /* type of file */ +const NFSMODE_DIR = 0040000; /* directory */ +const NFSMODE_CHR = 0020000; /* character special */ +const NFSMODE_BLK = 0060000; /* block special */ +const NFSMODE_REG = 0100000; /* regular */ +const NFSMODE_LNK = 0120000; /* symbolic link */ +const NFSMODE_SOCK = 0140000; /* socket */ +const NFSMODE_FIFO = 0010000; /* fifo */ + +/* + * Error status + */ +enum nfsstat { + NFS_OK= 0, /* no error */ + NFSERR_PERM=1, /* Not owner */ + NFSERR_NOENT=2, /* No such file or directory */ + NFSERR_IO=5, /* I/O error */ + NFSERR_NXIO=6, /* No such device or address */ + NFSERR_ACCES=13, /* Permission denied */ + NFSERR_EXIST=17, /* File exists */ + NFSERR_NODEV=19, /* No such device */ + NFSERR_NOTDIR=20, /* Not a directory*/ + NFSERR_ISDIR=21, /* Is a directory */ + NFSERR_FBIG=27, /* File too large */ + NFSERR_NOSPC=28, /* No space left on device */ + NFSERR_ROFS=30, /* Read-only file system */ + NFSERR_NAMETOOLONG=63, /* File name too long */ + NFSERR_NOTEMPTY=66, /* Directory not empty */ + NFSERR_DQUOT=69, /* Disc quota exceeded */ + NFSERR_STALE=70, /* Stale NFS file handle */ + NFSERR_WFLUSH=99 /* write cache flushed */ +}; + +/* + * File types + */ +enum ftype { + NFNON = 0, /* non-file */ + NFREG = 1, /* regular file */ + NFDIR = 2, /* directory */ + NFBLK = 3, /* block special */ + NFCHR = 4, /* character special */ + NFLNK = 5, /* symbolic link */ + NFSOCK = 6, /* unix domain sockets */ + NFBAD = 7, /* unused */ + NFFIFO = 8 /* named pipe */ +}; + +/* + * File access handle + */ +struct nfs_fh { + opaque data[NFS_FHSIZE]; +}; + +/* + * Timeval + */ +struct nfstime { + unsigned seconds; + unsigned useconds; +}; + + +/* + * File attributes + */ +struct fattr { + ftype type; /* file type */ + unsigned mode; /* protection mode bits */ + unsigned nlink; /* # hard links */ + unsigned uid; /* owner user id */ + unsigned gid; /* owner group id */ + unsigned size; /* file size in bytes */ + unsigned blocksize; /* preferred block size */ + unsigned rdev; /* special device # */ + unsigned blocks; /* Kb of disk used by file */ + unsigned fsid; /* device # */ + unsigned fileid; /* inode # */ + nfstime atime; /* time of last access */ + nfstime mtime; /* time of last modification */ + nfstime ctime; /* time of last change */ +}; + +/* + * File attributes which can be set + */ +struct sattr { + unsigned mode; /* protection mode bits */ + unsigned uid; /* owner user id */ + unsigned gid; /* owner group id */ + unsigned size; /* file size in bytes */ + nfstime atime; /* time of last access */ + nfstime mtime; /* time of last modification */ +}; + + +typedef string filename<NFS_MAXNAMLEN>; +typedef string nfspath<NFS_MAXPATHLEN>; + +/* + * Reply status with file attributes + */ +union attrstat switch (nfsstat status) { +case NFS_OK: + fattr attributes; +default: + void; +}; + +struct sattrargs { + nfs_fh file; + sattr attributes; +}; + +/* + * Arguments for directory operations + */ +struct diropargs { + nfs_fh dir; /* directory file handle */ + filename name; /* name (up to NFS_MAXNAMLEN bytes) */ +}; + +struct diropokres { + nfs_fh file; + fattr attributes; +}; + +/* + * Results from directory operation + */ +union diropres switch (nfsstat status) { +case NFS_OK: + diropokres diropres; +default: + void; +}; + +union readlinkres switch (nfsstat status) { +case NFS_OK: + nfspath data; +default: + void; +}; + +/* + * Arguments to remote read + */ +struct readargs { + nfs_fh file; /* handle for file */ + unsigned offset; /* byte offset in file */ + unsigned count; /* immediate read count */ + unsigned totalcount; /* total read count (from this offset)*/ +}; + +/* + * Status OK portion of remote read reply + */ +struct readokres { + fattr attributes; /* attributes, need for pagin*/ + opaque data<NFS_MAXDATA>; +}; + +union readres switch (nfsstat status) { +case NFS_OK: + readokres reply; +default: + void; +}; + +/* + * Arguments to remote write + */ +struct writeargs { + nfs_fh file; /* handle for file */ + unsigned beginoffset; /* beginning byte offset in file */ + unsigned offset; /* current byte offset in file */ + unsigned totalcount; /* total write count (to this offset)*/ + opaque data<NFS_MAXDATA>; +}; + +struct createargs { + diropargs where; + sattr attributes; +}; + +struct renameargs { + diropargs from; + diropargs to; +}; + +struct linkargs { + nfs_fh from; + diropargs to; +}; + +struct symlinkargs { + diropargs from; + nfspath to; + sattr attributes; +}; + + +typedef opaque nfscookie[NFS_COOKIESIZE]; + +/* + * Arguments to readdir + */ +struct readdirargs { + nfs_fh dir; /* directory handle */ + nfscookie cookie; + unsigned count; /* number of directory bytes to read */ +}; + +struct entry { + unsigned fileid; + filename name; + nfscookie cookie; + entry *nextentry; +}; + +struct dirlist { + entry *entries; + bool eof; +}; + +union readdirres switch (nfsstat status) { +case NFS_OK: + dirlist reply; +default: + void; +}; + +struct statfsokres { + unsigned tsize; /* preferred transfer size in bytes */ + unsigned bsize; /* fundamental file system block size */ + unsigned blocks; /* total blocks in file system */ + unsigned bfree; /* free blocks in fs */ + unsigned bavail; /* free blocks avail to non-superuser */ +}; + +union statfsres switch (nfsstat status) { +case NFS_OK: + statfsokres reply; +default: + void; +}; + +/* + * Remote file service routines + */ +program NFS_PROGRAM { + version NFS_VERSION { + void + NFSPROC_NULL(void) = 0; + + attrstat + NFSPROC_GETATTR(nfs_fh) = 1; + + attrstat + NFSPROC_SETATTR(sattrargs) = 2; + + void + NFSPROC_ROOT(void) = 3; + + diropres + NFSPROC_LOOKUP(diropargs) = 4; + + readlinkres + NFSPROC_READLINK(nfs_fh) = 5; + + readres + NFSPROC_READ(readargs) = 6; + + void + NFSPROC_WRITECACHE(void) = 7; + + attrstat + NFSPROC_WRITE(writeargs) = 8; + + diropres + NFSPROC_CREATE(createargs) = 9; + + nfsstat + NFSPROC_REMOVE(diropargs) = 10; + + nfsstat + NFSPROC_RENAME(renameargs) = 11; + + nfsstat + NFSPROC_LINK(linkargs) = 12; + + nfsstat + NFSPROC_SYMLINK(symlinkargs) = 13; + + diropres + NFSPROC_MKDIR(createargs) = 14; + + nfsstat + NFSPROC_RMDIR(diropargs) = 15; + + readdirres + NFSPROC_READDIR(readdirargs) = 16; + + statfsres + NFSPROC_STATFS(nfs_fh) = 17; + } = 2; +} = 100003; diff --git a/REORG.TODO/sunrpc/rpcsvc/nlm_prot.x b/REORG.TODO/sunrpc/rpcsvc/nlm_prot.x new file mode 100644 index 0000000000..81ff13735e --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/nlm_prot.x @@ -0,0 +1,203 @@ +/* @(#)nlm_prot.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Network lock manager protocol definition + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * protocol used between local lock manager and remote lock manager + */ + +#ifdef RPC_HDR +%#define LM_MAXSTRLEN 1024 +%#define MAXNAMELEN LM_MAXSTRLEN+1 +#endif + +/* + * status of a call to the lock manager + */ +enum nlm_stats { + nlm_granted = 0, + nlm_denied = 1, + nlm_denied_nolocks = 2, + nlm_blocked = 3, + nlm_denied_grace_period = 4 +}; + +struct nlm_holder { + bool exclusive; + int svid; + netobj oh; + unsigned l_offset; + unsigned l_len; +}; + +union nlm_testrply switch (nlm_stats stat) { + case nlm_denied: + struct nlm_holder holder; + default: + void; +}; + +struct nlm_stat { + nlm_stats stat; +}; + +struct nlm_res { + netobj cookie; + nlm_stat stat; +}; + +struct nlm_testres { + netobj cookie; + nlm_testrply stat; +}; + +struct nlm_lock { + string caller_name<LM_MAXSTRLEN>; + netobj fh; /* identify a file */ + netobj oh; /* identify owner of a lock */ + int svid; /* generated from pid for svid */ + unsigned l_offset; + unsigned l_len; +}; + +struct nlm_lockargs { + netobj cookie; + bool block; + bool exclusive; + struct nlm_lock alock; + bool reclaim; /* used for recovering locks */ + int state; /* specify local status monitor state */ +}; + +struct nlm_cancargs { + netobj cookie; + bool block; + bool exclusive; + struct nlm_lock alock; +}; + +struct nlm_testargs { + netobj cookie; + bool exclusive; + struct nlm_lock alock; +}; + +struct nlm_unlockargs { + netobj cookie; + struct nlm_lock alock; +}; + + +#ifdef RPC_HDR +%/* +% * The following enums are actually bit encoded for efficient +% * boolean algebra.... DON'T change them..... +% */ +#endif +enum fsh_mode { + fsm_DN = 0, /* deny none */ + fsm_DR = 1, /* deny read */ + fsm_DW = 2, /* deny write */ + fsm_DRW = 3 /* deny read/write */ +}; + +enum fsh_access { + fsa_NONE = 0, /* for completeness */ + fsa_R = 1, /* read only */ + fsa_W = 2, /* write only */ + fsa_RW = 3 /* read/write */ +}; + +struct nlm_share { + string caller_name<LM_MAXSTRLEN>; + netobj fh; + netobj oh; + fsh_mode mode; + fsh_access access; +}; + +struct nlm_shareargs { + netobj cookie; + nlm_share share; + bool reclaim; +}; + +struct nlm_shareres { + netobj cookie; + nlm_stats stat; + int sequence; +}; + +struct nlm_notify { + string name<MAXNAMELEN>; + long state; +}; + +/* + * Over-the-wire protocol used between the network lock managers + */ + +program NLM_PROG { + version NLM_VERS { + + nlm_testres NLM_TEST(struct nlm_testargs) = 1; + + nlm_res NLM_LOCK(struct nlm_lockargs) = 2; + + nlm_res NLM_CANCEL(struct nlm_cancargs) = 3; + nlm_res NLM_UNLOCK(struct nlm_unlockargs) = 4; + + /* + * remote lock manager call-back to grant lock + */ + nlm_res NLM_GRANTED(struct nlm_testargs)= 5; + /* + * message passing style of requesting lock + */ + void NLM_TEST_MSG(struct nlm_testargs) = 6; + void NLM_LOCK_MSG(struct nlm_lockargs) = 7; + void NLM_CANCEL_MSG(struct nlm_cancargs) =8; + void NLM_UNLOCK_MSG(struct nlm_unlockargs) = 9; + void NLM_GRANTED_MSG(struct nlm_testargs) = 10; + void NLM_TEST_RES(nlm_testres) = 11; + void NLM_LOCK_RES(nlm_res) = 12; + void NLM_CANCEL_RES(nlm_res) = 13; + void NLM_UNLOCK_RES(nlm_res) = 14; + void NLM_GRANTED_RES(nlm_res) = 15; + } = 1; + + version NLM_VERSX { + nlm_shareres NLM_SHARE(nlm_shareargs) = 20; + nlm_shareres NLM_UNSHARE(nlm_shareargs) = 21; + nlm_res NLM_NM_LOCK(nlm_lockargs) = 22; + void NLM_FREE_ALL(nlm_notify) = 23; + } = 3; + +} = 100021; diff --git a/REORG.TODO/sunrpc/rpcsvc/rex.x b/REORG.TODO/sunrpc/rpcsvc/rex.x new file mode 100644 index 0000000000..b5baf15a85 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/rex.x @@ -0,0 +1,229 @@ +/* @(#)rex.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Remote execution (rex) protocol specification + */ + +const STRINGSIZE = 1024; +typedef string rexstring<1024>; + +/* + * values to pass to REXPROC_SIGNAL + */ +const SIGINT = 2; /* interrupt */ + +/* + * Values for rst_flags, below + */ +const REX_INTERACTIVE = 1; /* interactive mode */ + +struct rex_start { + rexstring rst_cmd<>; /* list of command and args */ + rexstring rst_host; /* working directory host name */ + rexstring rst_fsname; /* working directory file system name */ + rexstring rst_dirwithin;/* working directory within file system */ + rexstring rst_env<>; /* list of environment */ + unsigned int rst_port0; /* port for stdin */ + unsigned int rst_port1; /* port for stdout */ + unsigned int rst_port2; /* port for stderr */ + unsigned int rst_flags; /* options - see const above */ +}; + +struct rex_result { + int rlt_stat; /* integer status code */ + rexstring rlt_message; /* string message for human consumption */ +}; + + +struct sgttyb { + unsigned four; /* always equals 4 */ + opaque chars[4]; + /* chars[0] == input speed */ + /* chars[1] == output speed */ + /* chars[2] == kill character */ + /* chars[3] == erase character */ + unsigned flags; +}; +/* values for speeds above (baud rates) */ +const B0 = 0; +const B50 = 1; +const B75 = 2; +const B110 = 3; +const B134 = 4; +const B150 = 5; +const B200 = 6; +const B300 = 7; +const B600 = 8; +const B1200 = 9; +const B1800 = 10; +const B2400 = 11; +const B4800 = 12; +const B9600 = 13; +const B19200 = 14; +const B38400 = 15; + +/* values for flags above */ +const TANDEM = 0x00000001; /* send stopc on out q full */ +const CBREAK = 0x00000002; /* half-cooked mode */ +const LCASE = 0x00000004; /* simulate lower case */ +const ECHO = 0x00000008; /* echo input */ +const CRMOD = 0x00000010; /* map \r to \r\n on output */ +const RAW = 0x00000020; /* no i/o processing */ +const ODDP = 0x00000040; /* get/send odd parity */ +const EVENP = 0x00000080; /* get/send even parity */ +const ANYP = 0x000000c0; /* get any parity/send none */ +const NLDELAY = 0x00000300; /* \n delay */ +const NL0 = 0x00000000; +const NL1 = 0x00000100; /* tty 37 */ +const NL2 = 0x00000200; /* vt05 */ +const NL3 = 0x00000300; +const TBDELAY = 0x00000c00; /* horizontal tab delay */ +const TAB0 = 0x00000000; +const TAB1 = 0x00000400; /* tty 37 */ +const TAB2 = 0x00000800; +const XTABS = 0x00000c00; /* expand tabs on output */ +const CRDELAY = 0x00003000; /* \r delay */ +const CR0 = 0x00000000; +const CR1 = 0x00001000; /* tn 300 */ +const CR2 = 0x00002000; /* tty 37 */ +const CR3 = 0x00003000; /* concept 100 */ +const VTDELAY = 0x00004000; /* vertical tab delay */ +const FF0 = 0x00000000; +const FF1 = 0x00004000; /* tty 37 */ +const BSDELAY = 0x00008000; /* \b delay */ +const BS0 = 0x00000000; +const BS1 = 0x00008000; +const CRTBS = 0x00010000; /* do backspacing for crt */ +const PRTERA = 0x00020000; /* \ ... / erase */ +const CRTERA = 0x00040000; /* " \b " to wipe out char */ +const TILDE = 0x00080000; /* hazeltine tilde kludge */ +const MDMBUF = 0x00100000; /* start/stop output on carrier intr */ +const LITOUT = 0x00200000; /* literal output */ +const TOSTOP = 0x00400000; /* SIGTTOU on background output */ +const FLUSHO = 0x00800000; /* flush output to terminal */ +const NOHANG = 0x01000000; /* no SIGHUP on carrier drop */ +const L001000 = 0x02000000; +const CRTKIL = 0x04000000; /* kill line with " \b " */ +const PASS8 = 0x08000000; +const CTLECH = 0x10000000; /* echo control chars as ^X */ +const PENDIN = 0x20000000; /* tp->t_rawq needs reread */ +const DECCTQ = 0x40000000; /* only ^Q starts after ^S */ +const NOFLSH = 0x80000000; /* no output flush on signal */ + +struct tchars { + unsigned six; /* always equals 6 */ + opaque chars[6]; + /* chars[0] == interrupt char */ + /* chars[1] == quit char */ + /* chars[2] == start output char */ + /* chars[3] == stop output char */ + /* chars[4] == end-of-file char */ + /* chars[5] == input delimiter (like nl) */ +}; + +struct ltchars { + unsigned six; /* always equals 6 */ + opaque chars[6]; + /* chars[0] == stop process signal */ + /* chars[1] == delayed stop process signal */ + /* chars[2] == reprint line */ + /* chars[3] == flush output */ + /* chars[4] == word erase */ + /* chars[5] == literal next character */ + unsigned mode; +}; + +struct rex_ttysize { + int ts_lines; + int ts_cols; +}; + +struct rex_ttymode { + sgttyb basic; /* standard unix tty flags */ + tchars more; /* interrupt, kill characters, etc. */ + ltchars yetmore; /* special Berkeley characters */ + unsigned andmore; /* and Berkeley modes */ +}; + +/* values for andmore above */ +const LCRTBS = 0x0001; /* do backspacing for crt */ +const LPRTERA = 0x0002; /* \ ... / erase */ +const LCRTERA = 0x0004; /* " \b " to wipe out char */ +const LTILDE = 0x0008; /* hazeltine tilde kludge */ +const LMDMBUF = 0x0010; /* start/stop output on carrier intr */ +const LLITOUT = 0x0020; /* literal output */ +const LTOSTOP = 0x0040; /* SIGTTOU on background output */ +const LFLUSHO = 0x0080; /* flush output to terminal */ +const LNOHANG = 0x0100; /* no SIGHUP on carrier drop */ +const LL001000 = 0x0200; +const LCRTKIL = 0x0400; /* kill line with " \b " */ +const LPASS8 = 0x0800; +const LCTLECH = 0x1000; /* echo control chars as ^X */ +const LPENDIN = 0x2000; /* needs reread */ +const LDECCTQ = 0x4000; /* only ^Q starts after ^S */ +const LNOFLSH = 0x8000; /* no output flush on signal */ + +program REXPROG { + version REXVERS { + + /* + * Start remote execution + */ + rex_result + REXPROC_START(rex_start) = 1; + + /* + * Wait for remote execution to terminate + */ + rex_result + REXPROC_WAIT(void) = 2; + + /* + * Send tty modes + */ + void + REXPROC_MODES(rex_ttymode) = 3; + + /* + * Send window size change + */ + void + REXPROC_WINCH(rex_ttysize) = 4; + + /* + * Send other signal + */ + void + REXPROC_SIGNAL(int) = 5; + } = 1; +} = 100017; diff --git a/REORG.TODO/sunrpc/rpcsvc/rquota.x b/REORG.TODO/sunrpc/rpcsvc/rquota.x new file mode 100644 index 0000000000..c4575240d3 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/rquota.x @@ -0,0 +1,61 @@ +/* @(#)rquota.x 2.1 88/08/01 4.0 RPCSRC */ +/* @(#)rquota.x 1.2 87/09/20 Copyr 1987 Sun Micro */ + +/* + * Remote quota protocol + * Requires unix authentication + */ + +const RQ_PATHLEN = 1024; + +struct getquota_args { + string gqa_pathp<RQ_PATHLEN>; /* path to filesystem of interest */ + int gqa_uid; /* inquire about quota for uid */ +}; + +/* + * remote quota structure + */ +struct rquota { + int rq_bsize; /* block size for block counts */ + bool rq_active; /* indicates whether quota is active */ + unsigned int rq_bhardlimit; /* absolute limit on disk blks alloc */ + unsigned int rq_bsoftlimit; /* preferred limit on disk blks */ + unsigned int rq_curblocks; /* current block count */ + unsigned int rq_fhardlimit; /* absolute limit on allocated files */ + unsigned int rq_fsoftlimit; /* preferred file limit */ + unsigned int rq_curfiles; /* current # allocated files */ + unsigned int rq_btimeleft; /* time left for excessive disk use */ + unsigned int rq_ftimeleft; /* time left for excessive files */ +}; + +enum gqr_status { + Q_OK = 1, /* quota returned */ + Q_NOQUOTA = 2, /* noquota for uid */ + Q_EPERM = 3 /* no permission to access quota */ +}; + +union getquota_rslt switch (gqr_status status) { +case Q_OK: + rquota gqr_rquota; /* valid if status == Q_OK */ +case Q_NOQUOTA: + void; +case Q_EPERM: + void; +}; + +program RQUOTAPROG { + version RQUOTAVERS { + /* + * Get all quotas + */ + getquota_rslt + RQUOTAPROC_GETQUOTA(getquota_args) = 1; + + /* + * Get active quotas only + */ + getquota_rslt + RQUOTAPROC_GETACTIVEQUOTA(getquota_args) = 2; + } = 1; +} = 100011; diff --git a/REORG.TODO/sunrpc/rpcsvc/rstat.x b/REORG.TODO/sunrpc/rpcsvc/rstat.x new file mode 100644 index 0000000000..9b7b102218 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/rstat.x @@ -0,0 +1,145 @@ +/* @(#)rstat.x 2.2 88/08/01 4.0 RPCSRC */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Gather statistics on remote machines + */ + +#ifdef RPC_HDR + +%#ifndef FSCALE +%/* +% * Scale factor for scaled integers used to count load averages. +% */ +%#define FSHIFT 8 /* bits to right of fixed binary point */ +%#define FSCALE (1<<FSHIFT) +% +%#endif /* ndef FSCALE */ + +#endif /* def RPC_HDR */ + +const CPUSTATES = 4; +const DK_NDRIVE = 4; + +/* + * GMT since 0:00, January 1, 1970 + */ +struct rstat_timeval { + unsigned int tv_sec; /* seconds */ + unsigned int tv_usec; /* and microseconds */ +}; + +struct statstime { /* RSTATVERS_TIME */ + int cp_time[CPUSTATES]; + int dk_xfer[DK_NDRIVE]; + unsigned int v_pgpgin; /* these are cumulative sum */ + unsigned int v_pgpgout; + unsigned int v_pswpin; + unsigned int v_pswpout; + unsigned int v_intr; + int if_ipackets; + int if_ierrors; + int if_oerrors; + int if_collisions; + unsigned int v_swtch; + int avenrun[3]; /* scaled by FSCALE */ + rstat_timeval boottime; + rstat_timeval curtime; + int if_opackets; +}; + +struct statsswtch { /* RSTATVERS_SWTCH */ + int cp_time[CPUSTATES]; + int dk_xfer[DK_NDRIVE]; + unsigned int v_pgpgin; /* these are cumulative sum */ + unsigned int v_pgpgout; + unsigned int v_pswpin; + unsigned int v_pswpout; + unsigned int v_intr; + int if_ipackets; + int if_ierrors; + int if_oerrors; + int if_collisions; + unsigned int v_swtch; + unsigned int avenrun[3];/* scaled by FSCALE */ + rstat_timeval boottime; + int if_opackets; +}; + +struct stats { /* RSTATVERS_ORIG */ + int cp_time[CPUSTATES]; + int dk_xfer[DK_NDRIVE]; + unsigned int v_pgpgin; /* these are cumulative sum */ + unsigned int v_pgpgout; + unsigned int v_pswpin; + unsigned int v_pswpout; + unsigned int v_intr; + int if_ipackets; + int if_ierrors; + int if_oerrors; + int if_collisions; + int if_opackets; +}; + + +program RSTATPROG { + /* + * Newest version includes current time and context switching info + */ + version RSTATVERS_TIME { + statstime + RSTATPROC_STATS(void) = 1; + + unsigned int + RSTATPROC_HAVEDISK(void) = 2; + } = 3; + /* + * Does not have current time + */ + version RSTATVERS_SWTCH { + statsswtch + RSTATPROC_STATS(void) = 1; + + unsigned int + RSTATPROC_HAVEDISK(void) = 2; + } = 2; + /* + * Old version has no info about current time or context switching + */ + version RSTATVERS_ORIG { + stats + RSTATPROC_STATS(void) = 1; + + unsigned int + RSTATPROC_HAVEDISK(void) = 2; + } = 1; +} = 100001; diff --git a/REORG.TODO/sunrpc/rpcsvc/rusers.x b/REORG.TODO/sunrpc/rpcsvc/rusers.x new file mode 100644 index 0000000000..5bbfe97e79 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/rusers.x @@ -0,0 +1,228 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +%/* +% * Find out about remote users +% */ + +const RUSERS_MAXUSERLEN = 32; +const RUSERS_MAXLINELEN = 32; +const RUSERS_MAXHOSTLEN = 257; + +struct rusers_utmp { + string ut_user<RUSERS_MAXUSERLEN>; /* aka ut_name */ + string ut_line<RUSERS_MAXLINELEN>; /* device */ + string ut_host<RUSERS_MAXHOSTLEN>; /* host user logged on from */ + int ut_type; /* type of entry */ + int ut_time; /* time entry was made */ + unsigned int ut_idle; /* minutes idle */ +}; + +typedef rusers_utmp utmp_array<>; + +#ifdef RPC_HDR +% +%/* +% * Values for ut_type field above. +% */ +#endif +const RUSERS_EMPTY = 0; +const RUSERS_RUN_LVL = 1; +const RUSERS_BOOT_TIME = 2; +const RUSERS_OLD_TIME = 3; +const RUSERS_NEW_TIME = 4; +const RUSERS_INIT_PROCESS = 5; +const RUSERS_LOGIN_PROCESS = 6; +const RUSERS_USER_PROCESS = 7; +const RUSERS_DEAD_PROCESS = 8; +const RUSERS_ACCOUNTING = 9; + +program RUSERSPROG { + + version RUSERSVERS_3 { + int + RUSERSPROC_NUM(void) = 1; + + utmp_array + RUSERSPROC_NAMES(void) = 2; + + utmp_array + RUSERSPROC_ALLNAMES(void) = 3; + } = 3; + +} = 100002; + +#ifdef RPC_HDR +% +% +%#ifdef __cplusplus +%extern "C" { +%#endif +% +%#include <rpc/xdr.h> +% +%/* +% * The following structures are used by version 2 of the rusersd protocol. +% * They were not developed with rpcgen, so they do not appear as RPCL. +% */ +% +%#define RUSERSVERS_IDLE 2 +%#define RUSERSVERS 3 /* current version */ +%#define MAXUSERS 100 +% +%/* +% * This is the structure used in version 2 of the rusersd RPC service. +% * It corresponds to the utmp structure for BSD systems. +% */ +%struct ru_utmp { +% char ut_line[8]; /* tty name */ +% char ut_name[8]; /* user id */ +% char ut_host[16]; /* host name, if remote */ +% long int ut_time; /* time on */ +%}; +% +%struct utmparr { +% struct ru_utmp **uta_arr; +% int uta_cnt; +%}; +%typedef struct utmparr utmparr; +% +%extern bool_t xdr_utmparr (XDR *xdrs, struct utmparr *objp) __THROW; +% +%struct utmpidle { +% struct ru_utmp ui_utmp; +% unsigned int ui_idle; +%}; +% +%struct utmpidlearr { +% struct utmpidle **uia_arr; +% int uia_cnt; +%}; +% +%extern bool_t xdr_utmpidlearr (XDR *xdrs, struct utmpidlearr *objp) __THROW; +% +%#ifdef __cplusplus +%} +%#endif +#endif + + +#ifdef RPC_XDR +%bool_t xdr_utmp (XDR *xdrs, struct ru_utmp *objp); +% +%bool_t +%xdr_utmp (XDR *xdrs, struct ru_utmp *objp) +%{ +% /* Since the fields are char foo [xxx], we should not free them. */ +% if (xdrs->x_op != XDR_FREE) +% { +% char *ptr; +% unsigned int size; +% ptr = objp->ut_line; +% size = sizeof (objp->ut_line); +% if (!xdr_bytes (xdrs, &ptr, &size, size)) { +% return (FALSE); +% } +% ptr = objp->ut_name; +% size = sizeof (objp->ut_name); +% if (!xdr_bytes (xdrs, &ptr, &size, size)) { +% return (FALSE); +% } +% ptr = objp->ut_host; +% size = sizeof (objp->ut_host); +% if (!xdr_bytes (xdrs, &ptr, &size, size)) { +% return (FALSE); +% } +% } +% if (!xdr_long(xdrs, &objp->ut_time)) { +% return (FALSE); +% } +% return (TRUE); +%} +% +%bool_t xdr_utmpptr(XDR *xdrs, struct ru_utmp **objpp); +% +%bool_t +%xdr_utmpptr (XDR *xdrs, struct ru_utmp **objpp) +%{ +% if (!xdr_reference(xdrs, (char **) objpp, sizeof (struct ru_utmp), +% (xdrproc_t) xdr_utmp)) { +% return (FALSE); +% } +% return (TRUE); +%} +% +%bool_t +%xdr_utmparr (XDR *xdrs, struct utmparr *objp) +%{ +% if (!xdr_array(xdrs, (char **)&objp->uta_arr, (u_int *)&objp->uta_cnt, +% MAXUSERS, sizeof(struct ru_utmp *), +% (xdrproc_t) xdr_utmpptr)) { +% return (FALSE); +% } +% return (TRUE); +%} +% +%bool_t xdr_utmpidle(XDR *xdrs, struct utmpidle *objp); +% +%bool_t +%xdr_utmpidle (XDR *xdrs, struct utmpidle *objp) +%{ +% if (!xdr_utmp(xdrs, &objp->ui_utmp)) { +% return (FALSE); +% } +% if (!xdr_u_int(xdrs, &objp->ui_idle)) { +% return (FALSE); +% } +% return (TRUE); +%} +% +%bool_t xdr_utmpidleptr(XDR *xdrs, struct utmpidle **objp); +% +%bool_t +%xdr_utmpidleptr (XDR *xdrs, struct utmpidle **objpp) +%{ +% if (!xdr_reference(xdrs, (char **) objpp, sizeof (struct utmpidle), +% (xdrproc_t) xdr_utmpidle)) { +% return (FALSE); +% } +% return (TRUE); +%} +% +%bool_t +%xdr_utmpidlearr (XDR *xdrs, struct utmpidlearr *objp) +%{ +% if (!xdr_array(xdrs, (char **)&objp->uia_arr, (u_int *)&objp->uia_cnt, +% MAXUSERS, sizeof(struct utmpidle *), +% (xdrproc_t) xdr_utmpidleptr)) { +% return (FALSE); +% } +% return (TRUE); +%} +#endif diff --git a/REORG.TODO/sunrpc/rpcsvc/sm_inter.x b/REORG.TODO/sunrpc/rpcsvc/sm_inter.x new file mode 100644 index 0000000000..767f0e0856 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/sm_inter.x @@ -0,0 +1,110 @@ +/* + * Status monitor protocol specification + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +program SM_PROG { + version SM_VERS { + /* res_stat = stat_succ if status monitor agrees to monitor */ + /* res_stat = stat_fail if status monitor cannot monitor */ + /* if res_stat == stat_succ, state = state number of site sm_name */ + struct sm_stat_res SM_STAT(struct sm_name) = 1; + + /* res_stat = stat_succ if status monitor agrees to monitor */ + /* res_stat = stat_fail if status monitor cannot monitor */ + /* stat consists of state number of local site */ + struct sm_stat_res SM_MON(struct mon) = 2; + + /* stat consists of state number of local site */ + struct sm_stat SM_UNMON(struct mon_id) = 3; + + /* stat consists of state number of local site */ + struct sm_stat SM_UNMON_ALL(struct my_id) = 4; + + void SM_SIMU_CRASH(void) = 5; + + } = 1; +} = 100024; + +const SM_MAXSTRLEN = 1024; + +struct sm_name { + string mon_name<SM_MAXSTRLEN>; +}; + +struct my_id { + string my_name<SM_MAXSTRLEN>; /* name of the site initiating the monitoring request*/ + int my_prog; /* rpc program # of the requesting process */ + int my_vers; /* rpc version # of the requesting process */ + int my_proc; /* rpc procedure # of the requesting process */ +}; + +struct mon_id { + string mon_name<SM_MAXSTRLEN>; /* name of the site to be monitored */ + struct my_id my_id; +}; + + +struct mon{ + struct mon_id mon_id; + opaque priv[16]; /* private information to store at monitor for requesting process */ +}; + + +/* + * state # of status monitor monotonically increases each time + * status of the site changes: + * an even number (>= 0) indicates the site is down and + * an odd number (> 0) indicates the site is up; + */ +struct sm_stat { + int state; /* state # of status monitor */ +}; + +enum res { + stat_succ = 0, /* status monitor agrees to monitor */ + stat_fail = 1 /* status monitor cannot monitor */ +}; + +struct sm_stat_res { + res res_stat; + int state; +}; + +/* + * structure of the status message sent back by the status monitor + * when monitor site status changes + */ +struct status { + string mon_name<SM_MAXSTRLEN>; + int state; + opaque priv[16]; /* stored private information */ +}; diff --git a/REORG.TODO/sunrpc/rpcsvc/spray.x b/REORG.TODO/sunrpc/rpcsvc/spray.x new file mode 100644 index 0000000000..68b7c48442 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/spray.x @@ -0,0 +1,84 @@ +/* @(#)spray.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * Spray a server with packets + * Useful for testing flakiness of network interfaces + */ + +const SPRAYMAX = 8845; /* max amount can spray */ + +/* + * GMT since 0:00, 1 January 1970 + */ +struct spraytimeval { + unsigned int sec; + unsigned int usec; +}; + +/* + * spray statistics + */ +struct spraycumul { + unsigned int counter; + spraytimeval clock; +}; + +/* + * spray data + */ +typedef opaque sprayarr<SPRAYMAX>; + +program SPRAYPROG { + version SPRAYVERS { + /* + * Just throw away the data and increment the counter + * This call never returns, so the client should always + * time it out. + */ + void + SPRAYPROC_SPRAY(sprayarr) = 1; + + /* + * Get the value of the counter and elapsed time since + * last CLEAR. + */ + spraycumul + SPRAYPROC_GET(void) = 2; + + /* + * Clear the counter and reset the elapsed time + */ + void + SPRAYPROC_CLEAR(void) = 3; + } = 1; +} = 100012; diff --git a/REORG.TODO/sunrpc/rpcsvc/yppasswd.x b/REORG.TODO/sunrpc/rpcsvc/yppasswd.x new file mode 100644 index 0000000000..34e3efe3f9 --- /dev/null +++ b/REORG.TODO/sunrpc/rpcsvc/yppasswd.x @@ -0,0 +1,61 @@ +/* @(#)yppasswd.x 2.1 88/08/01 4.0 RPCSRC */ + +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* + * YP password update protocol + * Requires unix authentication + */ +program YPPASSWDPROG { + version YPPASSWDVERS { + /* + * Update my passwd entry + */ + int + YPPASSWDPROC_UPDATE(yppasswd) = 1; + } = 1; +} = 100009; + + +struct passwd { + string pw_name<>; /* username */ + string pw_passwd<>; /* encrypted password */ + int pw_uid; /* user id */ + int pw_gid; /* group id */ + string pw_gecos<>; /* in real life name */ + string pw_dir<>; /* home directory */ + string pw_shell<>; /* default shell */ +}; + +struct yppasswd { + string oldpass<>; /* unencrypted old password */ + passwd newpw; /* new passwd entry */ +}; diff --git a/REORG.TODO/sunrpc/rtime.c b/REORG.TODO/sunrpc/rtime.c new file mode 100644 index 0000000000..e3cffe26d4 --- /dev/null +++ b/REORG.TODO/sunrpc/rtime.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/* + * rtime - get time from remote machine + * + * gets time, obtaining value from host + * on the udp/time socket. Since timeserver returns + * with time of day in seconds since Jan 1, 1900, must + * subtract seconds before Jan 1, 1970 to get + * what unix uses. + */ +#include <stdio.h> +#include <unistd.h> +#include <stdint.h> +#include <rpc/rpc.h> +#include <rpc/clnt.h> +#include <sys/types.h> +#include <sys/poll.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <rpc/auth_des.h> +#include <errno.h> +#include <netinet/in.h> +#include <shlib-compat.h> + +#define NYEARS (u_long)(1970 - 1900) +#define TOFFSET (u_long)(60*60*24*(365*NYEARS + (NYEARS/4))) + +static void do_close (int); + +static void +do_close (int s) +{ + int save; + + save = errno; + __close (s); + __set_errno (save); +} + +int +rtime (struct sockaddr_in *addrp, struct rpc_timeval *timep, + struct rpc_timeval *timeout) +{ + int s; + struct pollfd fd; + int milliseconds; + int res; + /* RFC 868 says the time is transmitted as a 32-bit value. */ + uint32_t thetime; + struct sockaddr_in from; + socklen_t fromlen; + int type; + + if (timeout == NULL) + type = SOCK_STREAM; + else + type = SOCK_DGRAM; + + s = __socket (AF_INET, type, 0); + if (s < 0) + return (-1); + + addrp->sin_family = AF_INET; + addrp->sin_port = htons (IPPORT_TIMESERVER); + if (type == SOCK_DGRAM) + { + res = __sendto (s, (char *) &thetime, sizeof (thetime), 0, + (struct sockaddr *) addrp, sizeof (*addrp)); + if (res < 0) + { + do_close (s); + return -1; + } + milliseconds = (timeout->tv_sec * 1000) + (timeout->tv_usec / 1000); + fd.fd = s; + fd.events = POLLIN; + do + res = __poll (&fd, 1, milliseconds); + while (res < 0 && errno == EINTR); + if (res <= 0) + { + if (res == 0) + __set_errno (ETIMEDOUT); + do_close (s); + return (-1); + } + fromlen = sizeof (from); + res = __recvfrom (s, (char *) &thetime, sizeof (thetime), 0, + (struct sockaddr *) &from, &fromlen); + do_close (s); + if (res < 0) + return -1; + } + else + { + if (__connect (s, (struct sockaddr *) addrp, sizeof (*addrp)) < 0) + { + do_close (s); + return -1; + } + res = __read (s, (char *) &thetime, sizeof (thetime)); + do_close (s); + if (res < 0) + return (-1); + } + if (res != sizeof (thetime)) + { + __set_errno (EIO); + return -1; + } + thetime = ntohl (thetime); + timep->tv_sec = thetime - TOFFSET; + timep->tv_usec = 0; + return 0; +} +libc_hidden_nolink_sunrpc (rtime, GLIBC_2_1) diff --git a/REORG.TODO/sunrpc/svc.c b/REORG.TODO/sunrpc/svc.c new file mode 100644 index 0000000000..f713e2eb72 --- /dev/null +++ b/REORG.TODO/sunrpc/svc.c @@ -0,0 +1,582 @@ +/* + * 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) 2002-2017 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <errno.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <rpc/svc.h> +#include <rpc/pmap_clnt.h> +#include <sys/poll.h> +#include <time.h> +#include <shlib-compat.h> + +#ifdef _RPC_THREAD_SAFE_ +#define xports RPC_THREAD_VARIABLE(svc_xports_s) +#else +static SVCXPRT **xports; +#endif + +#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 + appropriate procedure. */ +struct svc_callout { + struct svc_callout *sc_next; + rpcprog_t sc_prog; + rpcvers_t sc_vers; + void (*sc_dispatch) (struct svc_req *, SVCXPRT *); + bool_t sc_mapped; +}; +#ifdef _RPC_THREAD_SAFE_ +#define svc_head RPC_THREAD_VARIABLE(svc_head_s) +#else +static struct svc_callout *svc_head; +#endif + +/* *************** SVCXPRT related stuff **************** */ + +/* Activate a transport handle. */ +void +xprt_register (SVCXPRT *xprt) +{ + register int sock = xprt->xp_sock; + register int i; + + if (xports == NULL) + { + xports = (SVCXPRT **) calloc (_rpc_dtablesize (), sizeof (SVCXPRT *)); + if (xports == NULL) /* Don't add handle */ + return; + } + + if (sock < _rpc_dtablesize ()) + { + struct pollfd *new_svc_pollfd; + + xports[sock] = xprt; + if (sock < FD_SETSIZE) + FD_SET (sock, &svc_fdset); + + /* Check if we have an empty slot */ + for (i = 0; i < svc_max_pollfd; ++i) + if (svc_pollfd[i].fd == -1) + { + svc_pollfd[i].fd = sock; + svc_pollfd[i].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + return; + } + + new_svc_pollfd = (struct pollfd *) realloc (svc_pollfd, + sizeof (struct pollfd) + * (svc_max_pollfd + 1)); + if (new_svc_pollfd == NULL) /* Out of memory */ + return; + svc_pollfd = new_svc_pollfd; + ++svc_max_pollfd; + + svc_pollfd[svc_max_pollfd - 1].fd = sock; + svc_pollfd[svc_max_pollfd - 1].events = (POLLIN | POLLPRI | + POLLRDNORM | POLLRDBAND); + } +} +libc_hidden_nolink_sunrpc (xprt_register, GLIBC_2_0) + +/* De-activate a transport handle. */ +void +xprt_unregister (SVCXPRT *xprt) +{ + register int sock = xprt->xp_sock; + register int i; + + if ((sock < _rpc_dtablesize ()) && (xports[sock] == xprt)) + { + xports[sock] = (SVCXPRT *) 0; + + if (sock < FD_SETSIZE) + FD_CLR (sock, &svc_fdset); + + for (i = 0; i < svc_max_pollfd; ++i) + if (svc_pollfd[i].fd == sock) + svc_pollfd[i].fd = -1; + } +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xprt_unregister) +#else +libc_hidden_nolink_sunrpc (xprt_unregister, GLIBC_2_0) +#endif + + +/* ********************** CALLOUT list related stuff ************* */ + +/* Search the callout list for a program number, return the callout + struct. */ +static struct svc_callout * +svc_find (rpcprog_t prog, rpcvers_t 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; +} + +/* 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 (SVCXPRT * xprt, rpcprog_t prog, rpcvers_t vers, + void (*dispatch) (struct svc_req *, SVCXPRT *), + rpcproc_t 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; + s->sc_mapped = FALSE; + svc_head = s; + +pmap_it: + /* now register the information with the local binder service */ + if (protocol) + { + if (! pmap_set (prog, vers, protocol, xprt->xp_port)) + return FALSE; + + s->sc_mapped = TRUE; + } + + return TRUE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svc_register) +#else +libc_hidden_nolink_sunrpc (svc_register, GLIBC_2_0) +#endif + +/* Remove a service program from the callout list. */ +void +svc_unregister (rpcprog_t prog, rpcvers_t vers) +{ + struct svc_callout *prev; + register struct svc_callout *s; + + if ((s = svc_find (prog, vers, &prev)) == NULL_SVC) + return; + bool is_mapped = s->sc_mapped; + + if (prev == NULL_SVC) + svc_head = s->sc_next; + else + prev->sc_next = s->sc_next; + + s->sc_next = NULL_SVC; + mem_free ((char *) s, (u_int) sizeof (struct svc_callout)); + /* now unregister the information with the local binder service */ + if (is_mapped) + pmap_unset (prog, vers); +} +libc_hidden_nolink_sunrpc (svc_unregister, GLIBC_2_0) + +/* ******************* REPLY GENERATION ROUTINES ************ */ + +/* Send a reply to an rpc request */ +bool_t +svc_sendreply (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); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svc_sendreply) +#else +libc_hidden_nolink_sunrpc (svc_sendreply, GLIBC_2_0) +#endif + +/* No procedure error reply */ +void +svcerr_noproc (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); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svcerr_noproc) +#else +libc_hidden_nolink_sunrpc (svcerr_noproc, GLIBC_2_0) +#endif + +/* Can't decode args error reply */ +void +svcerr_decode (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); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svcerr_decode) +#else +libc_hidden_nolink_sunrpc (svcerr_decode, GLIBC_2_0) +#endif + +/* Some system error */ +void +svcerr_systemerr (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); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svcerr_systemerr) +#else +libc_hidden_nolink_sunrpc (svcerr_systemerr, GLIBC_2_0) +#endif + +/* Authentication error reply */ +void +svcerr_auth (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); +} +libc_hidden_nolink_sunrpc (svcerr_auth, GLIBC_2_0) + +/* Auth too weak error reply */ +void +svcerr_weakauth (SVCXPRT *xprt) +{ + svcerr_auth (xprt, AUTH_TOOWEAK); +} +libc_hidden_nolink_sunrpc (svcerr_weakauth, GLIBC_2_0) + +/* Program unavailable error reply */ +void +svcerr_noprog (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); +} +libc_hidden_nolink_sunrpc (svcerr_noprog, GLIBC_2_0) + +/* Program version mismatch error reply */ +void +svcerr_progvers (register SVCXPRT *xprt, rpcvers_t low_vers, + rpcvers_t 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); +} +libc_hidden_nolink_sunrpc (svcerr_progvers, GLIBC_2_0) + +/* ******************* 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 (int rdfds) +{ + fd_set readfds; + + FD_ZERO (&readfds); + readfds.fds_bits[0] = rdfds; + svc_getreqset (&readfds); +} +libc_hidden_nolink_sunrpc (svc_getreq, GLIBC_2_0) + +void +svc_getreqset (fd_set *readfds) +{ + register fd_mask mask; + register fd_mask *maskp; + register int setsize; + register int sock; + register int bit; + + setsize = _rpc_dtablesize (); + if (setsize > FD_SETSIZE) + setsize = FD_SETSIZE; + maskp = readfds->fds_bits; + for (sock = 0; sock < setsize; sock += NFDBITS) + for (mask = *maskp++; (bit = ffsl (mask)); mask ^= (1L << (bit - 1))) + svc_getreq_common (sock + bit - 1); +} +libc_hidden_nolink_sunrpc (svc_getreqset, GLIBC_2_0) + +void +svc_getreq_poll (struct pollfd *pfdp, int pollretval) +{ + if (pollretval == 0) + return; + + register int fds_found; + for (int i = fds_found = 0; i < svc_max_pollfd; ++i) + { + register struct pollfd *p = &pfdp[i]; + + if (p->fd != -1 && p->revents) + { + /* fd has input waiting */ + if (p->revents & POLLNVAL) + xprt_unregister (xports[p->fd]); + else + svc_getreq_common (p->fd); + + if (++fds_found >= pollretval) + break; + } + } +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svc_getreq_poll) +#else +libc_hidden_nolink_sunrpc (svc_getreq_poll, GLIBC_2_2) +#endif + + +void +svc_getreq_common (const int fd) +{ + enum xprt_stat stat; + struct rpc_msg msg; + register SVCXPRT *xprt; + char cred_area[2 * MAX_AUTH_BYTES + RQCRED_SIZE]; + msg.rm_call.cb_cred.oa_base = cred_area; + msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]); + + xprt = xports[fd]; + /* Do we control fd? */ + if (xprt == NULL) + return; + + /* now receive msgs from xprtprt (support batch calls) */ + do + { + if (SVC_RECV (xprt, &msg)) + { + /* now find the exported program and call it */ + struct svc_callout *s; + struct svc_req r; + enum auth_stat why; + rpcvers_t low_vers; + rpcvers_t high_vers; + int prog_found; + + r.rq_clntcred = &(cred_area[2 * MAX_AUTH_BYTES]); + r.rq_xprt = xprt; + r.rq_prog = msg.rm_call.cb_prog; + r.rq_vers = msg.rm_call.cb_vers; + r.rq_proc = msg.rm_call.cb_proc; + r.rq_cred = msg.rm_call.cb_cred; + + /* first authenticate the message */ + /* Check for null flavor and bypass these calls if possible */ + + if (msg.rm_call.cb_cred.oa_flavor == AUTH_NULL) + { + r.rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + r.rq_xprt->xp_verf.oa_length = 0; + } + else if ((why = _authenticate (&r, &msg)) != AUTH_OK) + { + svcerr_auth (xprt, why); + goto call_done; + } + + /* now match message with a registered service */ + prog_found = FALSE; + low_vers = 0 - 1; + high_vers = 0; + + for (s = svc_head; s != NULL_SVC; s = s->sc_next) + { + if (s->sc_prog == r.rq_prog) + { + if (s->sc_vers == r.rq_vers) + { + (*s->sc_dispatch) (&r, xprt); + goto call_done; + } + /* found correct version */ + prog_found = TRUE; + if (s->sc_vers < low_vers) + low_vers = s->sc_vers; + if (s->sc_vers > high_vers) + high_vers = s->sc_vers; + } + /* found correct program */ + } + /* if we got here, the program or version + is not served ... */ + if (prog_found) + svcerr_progvers (xprt, low_vers, high_vers); + else + svcerr_noprog (xprt); + /* Fall through to ... */ + } + call_done: + if ((stat = SVC_STAT (xprt)) == XPRT_DIED) + { + SVC_DESTROY (xprt); + break; + } + } + while (stat == XPRT_MOREREQS); +} +libc_hidden_nolink_sunrpc (svc_getreq_common, GLIBC_2_2) + +/* If there are no file descriptors available, then accept will fail. + We want to delay here so the connection request can be dequeued; + otherwise we can bounce between polling and accepting, never giving the + request a chance to dequeue and eating an enormous amount of cpu time + in svc_run if we're polling on many file descriptors. */ +void +__svc_accept_failed (void) +{ + if (errno == EMFILE) + { + struct timespec ts = { .tv_sec = 0, .tv_nsec = 50000000 }; + __nanosleep (&ts, NULL); + } +} + +#ifdef _RPC_THREAD_SAFE_ + +void +__rpc_thread_svc_cleanup (void) +{ + struct svc_callout *svcp; + + while ((svcp = svc_head) != NULL) + svc_unregister (svcp->sc_prog, svcp->sc_vers); +} + +#endif /* _RPC_THREAD_SAFE_ */ diff --git a/REORG.TODO/sunrpc/svc_auth.c b/REORG.TODO/sunrpc/svc_auth.c new file mode 100644 index 0000000000..5bca9557e3 --- /dev/null +++ b/REORG.TODO/sunrpc/svc_auth.c @@ -0,0 +1,115 @@ +/* + * svc_auth.c, Server-side rpc authenticator interface. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/rpc.h> +#include <rpc/svc.h> +#include <rpc/svc_auth.h> +#include <shlib-compat.h> + +/* + * svcauthsw is the bdevsw of server side authentication. + * + * Server side authenticators are called from authenticate by + * using the client auth struct flavor field to index into svcauthsw. + * The server auth flavors must implement a routine that looks + * like: + * + * enum auth_stat + * flavorx_auth(rqst, msg) + * register struct svc_req *rqst; + * register struct rpc_msg *msg; + * + */ + +static enum auth_stat _svcauth_null (struct svc_req *, struct rpc_msg *); + /* no authentication */ +extern enum auth_stat _svcauth_unix (struct svc_req *, struct rpc_msg *); + /* unix style (uid, gids) */ +extern enum auth_stat _svcauth_short (struct svc_req *, struct rpc_msg *); + /* short hand unix style */ +extern enum auth_stat _svcauth_des (struct svc_req *, struct rpc_msg *); + /* des style */ + +static const struct + { + enum auth_stat (*authenticator) (struct svc_req *, struct rpc_msg *); + } +svcauthsw[] = +{ + { _svcauth_null }, /* AUTH_NULL */ + { _svcauth_unix }, /* AUTH_UNIX */ + { _svcauth_short }, /* AUTH_SHORT */ + { _svcauth_des } /* AUTH_DES */ +}; +#define AUTH_MAX 3 /* HIGHEST AUTH NUMBER */ + + +/* + * The call rpc message, msg has been obtained from the wire. The msg contains + * the raw form of credentials and verifiers. authenticate returns AUTH_OK + * if the msg is successfully authenticated. If AUTH_OK then the routine also + * does the following things: + * set rqst->rq_xprt->verf to the appropriate response verifier; + * sets rqst->rq_client_cred to the "cooked" form of the credentials. + * + * NB: rqst->rq_cxprt->verf must be pre-allocated; + * its length is set appropriately. + * + * The caller still owns and is responsible for msg->u.cmb.cred and + * msg->u.cmb.verf. The authentication system retains ownership of + * rqst->rq_client_cred, the cooked credentials. + * + * There is an assumption that any flavour less than AUTH_NULL is + * invalid. + */ +enum auth_stat +_authenticate (register struct svc_req *rqst, struct rpc_msg *msg) +{ + register int cred_flavor; + + rqst->rq_cred = msg->rm_call.cb_cred; + rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; + rqst->rq_xprt->xp_verf.oa_length = 0; + cred_flavor = rqst->rq_cred.oa_flavor; + if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) + return (*(svcauthsw[cred_flavor].authenticator)) (rqst, msg); + + return AUTH_REJECTEDCRED; +} +libc_hidden_nolink_sunrpc (_authenticate, GLIBC_2_1) + +static enum auth_stat +_svcauth_null (struct svc_req *rqst, struct rpc_msg *msg) +{ + return AUTH_OK; +} diff --git a/REORG.TODO/sunrpc/svc_authux.c b/REORG.TODO/sunrpc/svc_authux.c new file mode 100644 index 0000000000..0c6b0242cd --- /dev/null +++ b/REORG.TODO/sunrpc/svc_authux.c @@ -0,0 +1,147 @@ +/* + * 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) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <rpc/rpc.h> +#include <rpc/svc.h> + +/* + * Unix longhand authenticator + */ +enum auth_stat +_svcauth_unix (struct svc_req *rqst, struct rpc_msg *msg) +{ + enum auth_stat stat; + XDR xdrs; + struct authunix_parms *aup; + int32_t *buf; + struct area + { + struct authunix_parms area_aup; + char area_machname[MAX_MACHINE_NAME + 1]; + gid_t area_gids[NGRPS]; + } + *area; + u_int auth_len; + u_int str_len, gid_len; + u_int i; + + area = (struct area *) rqst->rq_clntcred; + aup = &area->area_aup; + aup->aup_machname = area->area_machname; + aup->aup_gids = area->area_gids; + auth_len = (u_int) msg->rm_call.cb_cred.oa_length; + xdrmem_create (&xdrs, msg->rm_call.cb_cred.oa_base, auth_len, XDR_DECODE); + buf = XDR_INLINE (&xdrs, auth_len); + if (buf != NULL) + { + aup->aup_time = IXDR_GET_LONG (buf); + str_len = IXDR_GET_U_INT32 (buf); + if (str_len > MAX_MACHINE_NAME) + { + stat = AUTH_BADCRED; + goto done; + } + memcpy (aup->aup_machname, (caddr_t) buf, (u_int) str_len); + aup->aup_machname[str_len] = 0; + str_len = RNDUP (str_len); + buf = (int32_t *) ((char *) buf + str_len); + aup->aup_uid = IXDR_GET_LONG (buf); + aup->aup_gid = IXDR_GET_LONG (buf); + gid_len = IXDR_GET_U_INT32 (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) + { + 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; + } + + /* get the verifier */ + if ((u_int)msg->rm_call.cb_verf.oa_length) + { + rqst->rq_xprt->xp_verf.oa_flavor = + msg->rm_call.cb_verf.oa_flavor; + rqst->rq_xprt->xp_verf.oa_base = + msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + msg->rm_call.cb_verf.oa_length; + } + else + { + 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 (struct svc_req *rqst, struct rpc_msg *msg) +{ + return AUTH_REJECTEDCRED; +} diff --git a/REORG.TODO/sunrpc/svc_raw.c b/REORG.TODO/sunrpc/svc_raw.c new file mode 100644 index 0000000000..4787203613 --- /dev/null +++ b/REORG.TODO/sunrpc/svc_raw.c @@ -0,0 +1,159 @@ +/* + * 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 simulate rpc and get rpc (round trip) overhead, without + * any interference from the kernel. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <rpc/rpc.h> +#include <rpc/svc.h> +#include <shlib-compat.h> + +/* + * This is the "network" that we will be moving data over + */ +struct svcraw_private_s + { + char _raw_buf[UDPMSGSIZE]; + SVCXPRT server; + XDR xdr_stream; + char verf_body[MAX_AUTH_BYTES]; + }; +#ifdef _RPC_THREAD_SAFE_ +#define svcraw_private RPC_THREAD_VARIABLE(svcraw_private_s) +#else +static struct svcraw_private_s *svcraw_private; +#endif + +static bool_t svcraw_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcraw_stat (SVCXPRT *); +static bool_t svcraw_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcraw_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svcraw_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcraw_destroy (SVCXPRT *); + +static const struct xp_ops server_ops = +{ + svcraw_recv, + svcraw_stat, + svcraw_getargs, + svcraw_reply, + svcraw_freeargs, + svcraw_destroy +}; + +SVCXPRT * +svcraw_create (void) +{ + struct svcraw_private_s *srp = svcraw_private; + + if (srp == 0) + { + srp = (struct svcraw_private_s *) calloc (1, sizeof (*srp)); + if (srp == 0) + return NULL; + } + srp->server.xp_sock = 0; + srp->server.xp_port = 0; + srp->server.xp_ops = (struct 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; +} +libc_hidden_nolink_sunrpc (svcraw_create, GLIBC_2_0) + +static enum xprt_stat +svcraw_stat (SVCXPRT *xprt) +{ + return XPRT_IDLE; +} + +static bool_t +svcraw_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct svcraw_private_s *srp = svcraw_private; + XDR *xdrs; + + if (srp == 0) + return FALSE; + 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 (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct svcraw_private_s *srp = svcraw_private; + 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 (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + struct svcraw_private_s *srp = svcraw_private; + + if (srp == 0) + return FALSE; + return (*xdr_args) (&srp->xdr_stream, args_ptr); +} + +static bool_t +svcraw_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + struct svcraw_private_s *srp = svcraw_private; + 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 (SVCXPRT *xprt) +{ +} diff --git a/REORG.TODO/sunrpc/svc_run.c b/REORG.TODO/sunrpc/svc_run.c new file mode 100644 index 0000000000..e563707fcc --- /dev/null +++ b/REORG.TODO/sunrpc/svc_run.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * This is the rpc server side idle loop + * Wait for input, call server program. + */ + +#include <errno.h> +#include <unistd.h> +#include <libintl.h> +#include <sys/poll.h> +#include <rpc/rpc.h> +#include <shlib-compat.h> + +/* This function can be used as a signal handler to terminate the + server loop. */ +void +svc_exit (void) +{ + free (svc_pollfd); + svc_pollfd = NULL; + svc_max_pollfd = 0; +} +libc_hidden_nolink_sunrpc (svc_exit, GLIBC_2_0) + +void +svc_run (void) +{ + int i; + struct pollfd *my_pollfd = NULL; + int last_max_pollfd = 0; + + for (;;) + { + int max_pollfd = svc_max_pollfd; + if (max_pollfd == 0 && svc_pollfd == NULL) + break; + + if (last_max_pollfd != max_pollfd) + { + struct pollfd *new_pollfd + = realloc (my_pollfd, sizeof (struct pollfd) * max_pollfd); + + if (new_pollfd == NULL) + { + perror (_("svc_run: - out of memory")); + break; + } + + my_pollfd = new_pollfd; + last_max_pollfd = max_pollfd; + } + + for (i = 0; i < max_pollfd; ++i) + { + my_pollfd[i].fd = svc_pollfd[i].fd; + my_pollfd[i].events = svc_pollfd[i].events; + my_pollfd[i].revents = 0; + } + + switch (i = __poll (my_pollfd, max_pollfd, -1)) + { + case -1: + if (errno == EINTR) + continue; + perror (_("svc_run: - poll failed")); + break; + case 0: + continue; + default: + svc_getreq_poll (my_pollfd, i); + continue; + } + break; + } + + free (my_pollfd); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svc_run) +#else +libc_hidden_nolink_sunrpc (svc_run, GLIBC_2_0) +#endif diff --git a/REORG.TODO/sunrpc/svc_simple.c b/REORG.TODO/sunrpc/svc_simple.c new file mode 100644 index 0000000000..acc9b9db14 --- /dev/null +++ b/REORG.TODO/sunrpc/svc_simple.c @@ -0,0 +1,186 @@ +/* + * svc_simple.c + * Simplified front end to rpc. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <string.h> +#include <libintl.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <sys/socket.h> +#include <netdb.h> + +#include <wchar.h> +#include <libio/iolibio.h> +#include <shlib-compat.h> + +struct proglst_ + { + char *(*p_progname) (char *); + int p_prognum; + int p_procnum; + xdrproc_t p_inproc, p_outproc; + struct proglst_ *p_nxt; + }; +#ifdef _RPC_THREAD_SAFE_ +#define proglst RPC_THREAD_VARIABLE(svcsimple_proglst_s) +#else +static struct proglst_ *proglst; +#endif + + +static void universal (struct svc_req *rqstp, SVCXPRT *transp_s); +#ifdef _RPC_THREAD_SAFE_ +#define transp RPC_THREAD_VARIABLE(svcsimple_transp_s) +#else +static SVCXPRT *transp; +#endif + +int +__registerrpc (u_long prognum, u_long versnum, u_long procnum, + char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc) +{ + struct proglst_ *pl; + char *buf; + + if (procnum == NULLPROC) + { + + if (__asprintf (&buf, _("can't reassign procedure number %ld\n"), + NULLPROC) < 0) + buf = NULL; + goto err_out; + } + if (transp == 0) + { + transp = svcudp_create (RPC_ANYSOCK); + if (transp == NULL) + { + buf = __strdup (_("couldn't create an rpc server\n")); + goto err_out; + } + } + (void) pmap_unset ((u_long) prognum, (u_long) versnum); + if (!svc_register (transp, (u_long) prognum, (u_long) versnum, + universal, IPPROTO_UDP)) + { + if (__asprintf (&buf, _("couldn't register prog %ld vers %ld\n"), + prognum, versnum) < 0) + buf = NULL; + goto err_out; + } + pl = (struct proglst_ *) malloc (sizeof (struct proglst_)); + if (pl == NULL) + { + buf = __strdup (_("registerrpc: out of memory\n")); + goto err_out; + } + 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; + + err_out: + if (buf == NULL) + return -1; + (void) __fxprintf (NULL, "%s", buf); + free (buf); + return -1; +} + +libc_sunrpc_symbol (__registerrpc, registerrpc, GLIBC_2_0) + + +static void +universal (struct svc_req *rqstp, SVCXPRT *transp_l) +{ + int prog, proc; + char *outdata; + char xdrbuf[UDPMSGSIZE]; + struct proglst_ *pl; + char *buf = NULL; + + /* + * enforce "procnum 0 is echo" convention + */ + if (rqstp->rq_proc == NULLPROC) + { + if (svc_sendreply (transp_l, (xdrproc_t)xdr_void, + (char *) NULL) == FALSE) + { + __write (STDERR_FILENO, "xxx\n", 4); + exit (1); + } + return; + } + prog = rqstp->rq_prog; + proc = rqstp->rq_proc; + for (pl = proglst; pl != NULL; pl = pl->p_nxt) + if (pl->p_prognum == prog && pl->p_procnum == proc) + { + /* decode arguments into a CLEAN buffer */ + __bzero (xdrbuf, sizeof (xdrbuf)); /* required ! */ + if (!svc_getargs (transp_l, pl->p_inproc, xdrbuf)) + { + svcerr_decode (transp_l); + return; + } + outdata = (*(pl->p_progname)) (xdrbuf); + if (outdata == NULL && pl->p_outproc != (xdrproc_t)xdr_void) + /* there was an error */ + return; + if (!svc_sendreply (transp_l, pl->p_outproc, outdata)) + { + if (__asprintf (&buf, _("trouble replying to prog %d\n"), + pl->p_prognum) < 0) + buf = NULL; + goto err_out2; + } + /* free the decoded arguments */ + (void) svc_freeargs (transp_l, pl->p_inproc, xdrbuf); + return; + } + if (__asprintf (&buf, _("never registered prog %d\n"), prog) < 0) + buf = NULL; + err_out2: + if (buf == NULL) + exit (1); + __fxprintf (NULL, "%s", buf); + free (buf); + exit (1); +} diff --git a/REORG.TODO/sunrpc/svc_tcp.c b/REORG.TODO/sunrpc/svc_tcp.c new file mode 100644 index 0000000000..fd9c1e83ca --- /dev/null +++ b/REORG.TODO/sunrpc/svc_tcp.c @@ -0,0 +1,429 @@ +/* + * svc_tcp.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 2012-2017 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Actually implements two flavors of transporter - + * a tcp rendezvouser (a listener and connection establisher) + * and a record/tcp stream. + */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <libintl.h> +#include <rpc/rpc.h> +#include <sys/socket.h> +#include <sys/poll.h> +#include <errno.h> +#include <stdlib.h> + +#include <wchar.h> +#include <libio/iolibio.h> +#include <shlib-compat.h> + +/* + * Ops vector for TCP/IP based rpc service handle + */ +static bool_t svctcp_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svctcp_stat (SVCXPRT *); +static bool_t svctcp_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svctcp_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svctcp_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svctcp_destroy (SVCXPRT *); + +static const 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 (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat (SVCXPRT *); +static void svctcp_rendezvous_abort (void) __attribute__ ((__noreturn__)); + +/* This function makes sure abort() relocation goes through PLT + and thus can be lazy bound. */ +static void +svctcp_rendezvous_abort (void) +{ + abort (); +}; + +static const struct xp_ops svctcp_rendezvous_op = +{ + rendezvous_request, + rendezvous_stat, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort, + (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svctcp_rendezvous_abort, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svctcp_rendezvous_abort, + svctcp_destroy +}; + +static int readtcp (char*, char *, int); +static int writetcp (char *, char *, int); +static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function; + +struct tcp_rendezvous + { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; + }; + +struct tcp_conn + { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; + }; + +/* + * Usage: + * xprt = svctcp_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) tcp based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register). This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svctcp_create + * binds it to an arbitrary port. The routine then starts a tcp + * listener on the socket's associated port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since tcp streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svctcp_create (int sock, u_int sendsize, u_int recvsize) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); + + if (sock == RPC_ANYSOCK) + { + if ((sock = __socket (AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) + { + perror (_("svc_tcp.c - tcp socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + __bzero ((char *) &addr, sizeof (addr)); + addr.sin_family = AF_INET; + if (bindresvport (sock, &addr)) + { + addr.sin_port = 0; + (void) __bind (sock, (struct sockaddr *) &addr, len); + } + if ((__getsockname (sock, (struct sockaddr *) &addr, &len) != 0) || + (__listen (sock, SOMAXCONN) != 0)) + { + perror (_("svc_tcp.c - cannot getsockname or listen")); + if (madesock) + (void) __close (sock); + return (SVCXPRT *) NULL; + } + r = (struct tcp_rendezvous *) mem_alloc (sizeof (*r)); + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + if (r == NULL || xprt == NULL) + { + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + mem_free (r, sizeof (*r)); + mem_free (xprt, sizeof (SVCXPRT)); + return NULL; + } + r->sendsize = sendsize; + r->recvsize = recvsize; + 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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svctcp_create) +#else +libc_hidden_nolink_sunrpc (svctcp_create, GLIBC_2_0) +#endif + +/* + * Like svtcp_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcfd_create (int fd, u_int sendsize, u_int recvsize) +{ + return makefd_xprt (fd, sendsize, recvsize); +} +libc_hidden_nolink_sunrpc (svcfd_create, GLIBC_2_0) + +static SVCXPRT * +internal_function +makefd_xprt (int fd, u_int sendsize, u_int recvsize) +{ + SVCXPRT *xprt; + struct tcp_conn *cd; + + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + cd = (struct tcp_conn *) mem_alloc (sizeof (struct tcp_conn)); + if (xprt == (SVCXPRT *) NULL || cd == NULL) + { + (void) __fxprintf (NULL, "%s: %s", "svc_tcp: makefd_xprt", + _("out of memory\n")); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (cd, sizeof (struct tcp_conn)); + return NULL; + } + 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; /* truly deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register (xprt); + return xprt; +} + +static bool_t +rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg) +{ + int sock; + struct tcp_rendezvous *r; + struct sockaddr_in addr; + socklen_t 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; + __svc_accept_failed (); + return FALSE; + } + /* + * make a new transporter (re-uses xprt) + */ + xprt = makefd_xprt (sock, r->sendsize, r->recvsize); + memcpy (&xprt->xp_raddr, &addr, sizeof (addr)); + xprt->xp_addrlen = len; + return FALSE; /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat (SVCXPRT *xprt) +{ + return XPRT_IDLE; +} + +static void +svctcp_destroy (SVCXPRT *xprt) +{ + 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)); +} + + +/* + * reads data from the tcp connection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readtcp (char *xprtptr, char *buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *)xprtptr; + int sock = xprt->xp_sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + + do + { + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (__poll (&pollfd, 1, milliseconds)) + { + case -1: + if (errno == EINTR) + continue; + /*FALLTHROUGH*/ + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; + } + } + while ((pollfd.revents & POLLIN) == 0); + + 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 (char *xprtptr, char * buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *)xprtptr; + 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 (SVCXPRT *xprt) +{ + 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 (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); + 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; + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return FALSE; +} + +static bool_t +svctcp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + return ((*xdr_args) (&(((struct tcp_conn *) + (xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svctcp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + 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 (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct tcp_conn *cd = (struct tcp_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg (xdrs, msg); + (void) xdrrec_endofrecord (xdrs, TRUE); + return stat; +} diff --git a/REORG.TODO/sunrpc/svc_udp.c b/REORG.TODO/sunrpc/svc_udp.c new file mode 100644 index 0000000000..1592bcca9e --- /dev/null +++ b/REORG.TODO/sunrpc/svc_udp.c @@ -0,0 +1,620 @@ +/* + * 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) 2012-2017 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <sys/socket.h> +#include <errno.h> +#include <libintl.h> + +#ifdef IP_PKTINFO +#include <sys/uio.h> +#endif + +#include <wchar.h> +#include <libio/iolibio.h> +#include <shlib-compat.h> + +#define rpc_buffer(xprt) ((xprt)->xp_p1) +#ifndef MAX +#define MAX(a, b) ((a > b) ? a : b) +#endif + +static bool_t svcudp_recv (SVCXPRT *, struct rpc_msg *); +static bool_t svcudp_reply (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcudp_stat (SVCXPRT *); +static bool_t svcudp_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcudp_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcudp_destroy (SVCXPRT *); + +static const struct xp_ops svcudp_op = +{ + svcudp_recv, + svcudp_stat, + svcudp_getargs, + svcudp_reply, + svcudp_freeargs, + svcudp_destroy +}; + +static int cache_get (SVCXPRT *, struct rpc_msg *, char **replyp, + u_long *replylenp); +static void cache_set (SVCXPRT *xprt, u_long replylen); + +/* + * kept in xprt->xp_p2 + */ +struct svcudp_data + { + u_int su_iosz; /* byte size of send.recv buffer */ + u_long su_xid; /* transaction id */ + XDR su_xdrs; /* XDR handle */ + char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */ + char *su_cache; /* cached data, NULL if no cache */ + }; +#define su_data(xprt) ((struct svcudp_data *)(xprt->xp_p2)) + +/* + * Usage: + * xprt = svcudp_create(sock); + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcudp_create + * binds it to an arbitrary port. In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * Once *xprt is initialized, it is registered as a transporter; + * see (svc.h, xprt_register). + * The routines returns NULL if a problem occurred. + */ +SVCXPRT * +svcudp_bufcreate (int sock, u_int sendsz, u_int recvsz) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct svcudp_data *su; + struct sockaddr_in addr; + socklen_t len = sizeof (struct sockaddr_in); + int pad; + void *buf; + + if (sock == RPC_ANYSOCK) + { + if ((sock = __socket (AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) + { + perror (_("svcudp_create: socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + __bzero ((char *) &addr, sizeof (addr)); + addr.sin_family = AF_INET; + if (bindresvport (sock, &addr)) + { + addr.sin_port = 0; + (void) __bind (sock, (struct sockaddr *) &addr, len); + } + if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0) + { + perror (_("svcudp_create - cannot getsockname")); + if (madesock) + (void) __close (sock); + return (SVCXPRT *) NULL; + } + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + su = (struct svcudp_data *) mem_alloc (sizeof (*su)); + buf = mem_alloc (((MAX (sendsz, recvsz) + 3) / 4) * 4); + if (xprt == NULL || su == NULL || buf == NULL) + { + (void) __fxprintf (NULL, "%s: %s", + "svcudp_create", _("out of memory\n")); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (su, sizeof (*su)); + mem_free (buf, ((MAX (sendsz, recvsz) + 3) / 4) * 4); + return NULL; + } + su->su_iosz = ((MAX (sendsz, recvsz) + 3) / 4) * 4; + rpc_buffer (xprt) = buf; + 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; + +#ifdef IP_PKTINFO + if ((sizeof (struct iovec) + sizeof (struct msghdr) + + sizeof(struct cmsghdr) + sizeof (struct in_pktinfo)) + > sizeof (xprt->xp_pad)) + { + (void) __fxprintf (NULL,"%s", _("\ +svcudp_create: xp_pad is too small for IP_PKTINFO\n")); + return NULL; + } + pad = 1; + if (__setsockopt (sock, SOL_IP, IP_PKTINFO, (void *) &pad, + sizeof (pad)) == 0) + /* Set the padding to all 1s. */ + pad = 0xff; + else +#endif + /* Clear the padding. */ + pad = 0; + memset (&xprt->xp_pad [0], pad, sizeof (xprt->xp_pad)); + + xprt_register (xprt); + return xprt; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svcudp_bufcreate) +#else +libc_hidden_nolink_sunrpc (svcudp_bufcreate, GLIBC_2_0) +#endif + +SVCXPRT * +svcudp_create (int sock) +{ + return svcudp_bufcreate (sock, UDPMSGSIZE, UDPMSGSIZE); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (svcudp_create) +#else +libc_hidden_nolink_sunrpc (svcudp_create, GLIBC_2_0) +#endif + +static enum xprt_stat +svcudp_stat (SVCXPRT *xprt) +{ + + return XPRT_IDLE; +} + +static bool_t +svcudp_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct svcudp_data *su = su_data (xprt); + XDR *xdrs = &(su->su_xdrs); + int rlen; + char *reply; + u_long replylen; + socklen_t len; + + /* It is very tricky when you have IP aliases. We want to make sure + that we are sending the packet from the IP address where the + incoming packet is addressed to. H.J. */ +#ifdef IP_PKTINFO + struct iovec *iovp; + struct msghdr *mesgp; +#endif + +again: + /* FIXME -- should xp_addrlen be a size_t? */ + len = (socklen_t) sizeof(struct sockaddr_in); +#ifdef IP_PKTINFO + iovp = (struct iovec *) &xprt->xp_pad [0]; + mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)]; + if (mesgp->msg_iovlen) + { + iovp->iov_base = rpc_buffer (xprt); + iovp->iov_len = su->su_iosz; + mesgp->msg_iov = iovp; + mesgp->msg_iovlen = 1; + mesgp->msg_name = &(xprt->xp_raddr); + mesgp->msg_namelen = len; + mesgp->msg_control = &xprt->xp_pad [sizeof (struct iovec) + + sizeof (struct msghdr)]; + mesgp->msg_controllen = sizeof(xprt->xp_pad) + - sizeof (struct iovec) - sizeof (struct msghdr); + rlen = __recvmsg (xprt->xp_sock, mesgp, 0); + if (rlen >= 0) + { + struct cmsghdr *cmsg; + len = mesgp->msg_namelen; + cmsg = CMSG_FIRSTHDR (mesgp); + if (cmsg == NULL + || CMSG_NXTHDR (mesgp, cmsg) != NULL + || cmsg->cmsg_level != SOL_IP + || cmsg->cmsg_type != IP_PKTINFO + || cmsg->cmsg_len < (sizeof (struct cmsghdr) + + sizeof (struct in_pktinfo))) + { + /* Not a simple IP_PKTINFO, ignore it. */ + mesgp->msg_control = NULL; + mesgp->msg_controllen = 0; + } + else + { + /* It was a simple IP_PKTIFO as we expected, discard the + interface field. */ + struct in_pktinfo *pkti = (struct in_pktinfo *) CMSG_DATA (cmsg); + pkti->ipi_ifindex = 0; + } + } + } + else +#endif + rlen = __recvfrom (xprt->xp_sock, rpc_buffer (xprt), + (int) su->su_iosz, 0, + (struct sockaddr *) &(xprt->xp_raddr), &len); + xprt->xp_addrlen = len; + if (rlen == -1) + { + if (errno == EINTR) + goto again; + __svc_accept_failed (); + } + if (rlen < 16) /* < 4 32-bit ints? */ + 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)) + { +#ifdef IP_PKTINFO + if (mesgp->msg_iovlen) + { + iovp->iov_base = reply; + iovp->iov_len = replylen; + (void) __sendmsg (xprt->xp_sock, mesgp, 0); + } + else +#endif + (void) __sendto (xprt->xp_sock, reply, (int) replylen, 0, + (struct sockaddr *) &xprt->xp_raddr, len); + return TRUE; + } + } + return TRUE; +} + +static bool_t +svcudp_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct svcudp_data *su = su_data (xprt); + XDR *xdrs = &(su->su_xdrs); + int slen, sent; + bool_t stat = FALSE; +#ifdef IP_PKTINFO + struct iovec *iovp; + struct msghdr *mesgp; +#endif + + xdrs->x_op = XDR_ENCODE; + XDR_SETPOS (xdrs, 0); + msg->rm_xid = su->su_xid; + if (xdr_replymsg (xdrs, msg)) + { + slen = (int) XDR_GETPOS (xdrs); +#ifdef IP_PKTINFO + mesgp = (struct msghdr *) &xprt->xp_pad [sizeof (struct iovec)]; + if (mesgp->msg_iovlen) + { + iovp = (struct iovec *) &xprt->xp_pad [0]; + iovp->iov_base = rpc_buffer (xprt); + iovp->iov_len = slen; + sent = __sendmsg (xprt->xp_sock, mesgp, 0); + } + else +#endif + sent = __sendto (xprt->xp_sock, rpc_buffer (xprt), slen, 0, + (struct sockaddr *) &(xprt->xp_raddr), + xprt->xp_addrlen); + if (sent == slen) + { + stat = TRUE; + if (su->su_cache && slen >= 0) + { + cache_set (xprt, (u_long) slen); + } + } + } + return stat; +} + +static bool_t +svcudp_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + + return (*xdr_args) (&(su_data (xprt)->su_xdrs), args_ptr); +} + +static bool_t +svcudp_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(su_data (xprt)->su_xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static void +svcudp_destroy (SVCXPRT *xprt) +{ + 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) __fxprintf(NULL, "%s\n", msg) + +#define ALLOC(type, size) \ + (type *) mem_alloc((unsigned) (sizeof(type) * (size))) + +#define CALLOC(type, size) \ + (type *) calloc (sizeof (type), size) + +/* + * An entry in the cache + */ +typedef struct cache_node *cache_ptr; +struct cache_node + { + /* + * Index into cache is xid, proc, vers, prog and address + */ + u_long cache_xid; + u_long cache_proc; + u_long cache_vers; + u_long cache_prog; + struct sockaddr_in cache_addr; + /* + * The cached reply and length + */ + char *cache_reply; + u_long cache_replylen; + /* + * Next node on the list, if there is a collision + */ + cache_ptr cache_next; + }; + + + +/* + * The entire cache + */ +struct udp_cache + { + u_long uc_size; /* size of cache */ + cache_ptr *uc_entries; /* hash table of entries in cache */ + cache_ptr *uc_fifo; /* fifo list of entries in cache */ + u_long uc_nextvictim; /* points to next victim in fifo list */ + u_long uc_prog; /* saved program number */ + u_long uc_vers; /* saved version number */ + u_long uc_proc; /* saved procedure number */ + struct sockaddr_in uc_addr; /* saved caller's address */ + }; + + +/* + * the hashing function + */ +#define CACHE_LOC(transp, xid) \ + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size)) + + +/* + * Enable use of the cache. + * Note: there is no disable. + */ +int +svcudp_enablecache (SVCXPRT *transp, u_long size) +{ + struct svcudp_data *su = su_data (transp); + struct udp_cache *uc; + + if (su->su_cache != NULL) + { + CACHE_PERROR (_("enablecache: cache already enabled")); + return 0; + } + uc = ALLOC (struct udp_cache, 1); + if (uc == NULL) + { + CACHE_PERROR (_("enablecache: could not allocate cache")); + return 0; + } + uc->uc_size = size; + uc->uc_nextvictim = 0; + uc->uc_entries = CALLOC (cache_ptr, size * SPARSENESS); + if (uc->uc_entries == NULL) + { + mem_free (uc, sizeof (struct udp_cache)); + CACHE_PERROR (_("enablecache: could not allocate cache data")); + return 0; + } + uc->uc_fifo = CALLOC (cache_ptr, size); + if (uc->uc_fifo == NULL) + { + mem_free (uc->uc_entries, size * SPARSENESS); + mem_free (uc, sizeof (struct udp_cache)); + CACHE_PERROR (_("enablecache: could not allocate cache fifo")); + return 0; + } + su->su_cache = (char *) uc; + return 1; +} +libc_hidden_nolink_sunrpc (svcudp_enablecache, GLIBC_2_0) + + +/* + * Set an entry in the cache + */ +static void +cache_set (SVCXPRT *xprt, u_long replylen) +{ + cache_ptr victim; + cache_ptr *vicp; + struct svcudp_data *su = su_data (xprt); + struct udp_cache *uc = (struct udp_cache *) su->su_cache; + u_int loc; + char *newbuf; + + /* + * Find space for the new entry, either by + * reusing an old entry, or by mallocing a new one + */ + victim = uc->uc_fifo[uc->uc_nextvictim]; + if (victim != NULL) + { + loc = CACHE_LOC (xprt, victim->cache_xid); + for (vicp = &uc->uc_entries[loc]; + *vicp != NULL && *vicp != victim; + vicp = &(*vicp)->cache_next) + ; + if (*vicp == NULL) + { + CACHE_PERROR (_("cache_set: victim not found")); + return; + } + *vicp = victim->cache_next; /* remote from cache */ + newbuf = victim->cache_reply; + } + else + { + victim = ALLOC (struct cache_node, 1); + if (victim == NULL) + { + CACHE_PERROR (_("cache_set: victim alloc failed")); + return; + } + newbuf = mem_alloc (su->su_iosz); + if (newbuf == NULL) + { + mem_free (victim, sizeof (struct cache_node)); + 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 (SVCXPRT *xprt, struct rpc_msg *msg, char **replyp, + u_long *replylenp) +{ + u_int loc; + cache_ptr ent; + struct svcudp_data *su = su_data (xprt); + 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; + memcpy (&uc->uc_addr, &xprt->xp_raddr, sizeof (uc->uc_addr)); + return 0; +} diff --git a/REORG.TODO/sunrpc/svc_unix.c b/REORG.TODO/sunrpc/svc_unix.c new file mode 100644 index 0000000000..a8da3b2262 --- /dev/null +++ b/REORG.TODO/sunrpc/svc_unix.c @@ -0,0 +1,537 @@ +/* + * svc_unix.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 2012-2017 Free Software Foundation, Inc. + * This file is part of the GNU C Library. + * + * The GNU C Library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * The GNU C Library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with the GNU C Library; if not, see + * <http://www.gnu.org/licenses/>. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Actually implements two flavors of transporter - + * a unix rendezvouser (a listener and connection establisher) + * and a record/unix stream. + */ + +#include <stdio.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <rpc/svc.h> +#include <sys/socket.h> +#include <sys/uio.h> +#include <sys/poll.h> +#include <errno.h> +#include <stdlib.h> +#include <libintl.h> +#include <wchar.h> +#include <shlib-compat.h> + +/* + * Ops vector for AF_UNIX based rpc service handle + */ +static bool_t svcunix_recv (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat svcunix_stat (SVCXPRT *); +static bool_t svcunix_getargs (SVCXPRT *, xdrproc_t, caddr_t); +static bool_t svcunix_reply (SVCXPRT *, struct rpc_msg *); +static bool_t svcunix_freeargs (SVCXPRT *, xdrproc_t, caddr_t); +static void svcunix_destroy (SVCXPRT *); + +static const struct xp_ops svcunix_op = +{ + svcunix_recv, + svcunix_stat, + svcunix_getargs, + svcunix_reply, + svcunix_freeargs, + svcunix_destroy +}; + +/* + * Ops vector for AF_UNIX rendezvous handler + */ +static bool_t rendezvous_request (SVCXPRT *, struct rpc_msg *); +static enum xprt_stat rendezvous_stat (SVCXPRT *); +static void svcunix_rendezvous_abort (void) __attribute__ ((__noreturn__)); + +/* This function makes sure abort() relocation goes through PLT + and thus can be lazy bound. */ +static void +svcunix_rendezvous_abort (void) +{ + abort (); +}; + +static const struct xp_ops svcunix_rendezvous_op = +{ + rendezvous_request, + rendezvous_stat, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort, + (bool_t (*) (SVCXPRT *, struct rpc_msg *)) svcunix_rendezvous_abort, + (bool_t (*) (SVCXPRT *, xdrproc_t, caddr_t)) svcunix_rendezvous_abort, + svcunix_destroy +}; + +static int readunix (char*, char *, int); +static int writeunix (char *, char *, int); +static SVCXPRT *makefd_xprt (int, u_int, u_int) internal_function; + +struct unix_rendezvous { /* kept in xprt->xp_p1 */ + u_int sendsize; + u_int recvsize; +}; + +struct unix_conn { /* kept in xprt->xp_p1 */ + enum xprt_stat strm_stat; + u_long x_id; + XDR xdrs; + char verf_body[MAX_AUTH_BYTES]; +}; + +/* + * Usage: + * xprt = svcunix_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) unix 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 svcunix_create + * binds it to an arbitrary port. The routine then starts a unix + * 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 unix 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 * +svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path) +{ + bool_t madesock = FALSE; + SVCXPRT *xprt; + struct unix_rendezvous *r; + struct sockaddr_un addr; + socklen_t len = sizeof (struct sockaddr_in); + + if (sock == RPC_ANYSOCK) + { + if ((sock = __socket (AF_UNIX, SOCK_STREAM, 0)) < 0) + { + perror (_("svc_unix.c - AF_UNIX socket creation problem")); + return (SVCXPRT *) NULL; + } + madesock = TRUE; + } + memset (&addr, '\0', sizeof (addr)); + addr.sun_family = AF_UNIX; + len = strlen (path) + 1; + memcpy (addr.sun_path, path, len); + len += sizeof (addr.sun_family); + + __bind (sock, (struct sockaddr *) &addr, len); + + if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0 + || __listen (sock, SOMAXCONN) != 0) + { + perror (_("svc_unix.c - cannot getsockname or listen")); + if (madesock) + __close (sock); + return (SVCXPRT *) NULL; + } + + r = (struct unix_rendezvous *) mem_alloc (sizeof (*r)); + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + if (r == NULL || xprt == NULL) + { + __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + mem_free (r, sizeof (*r)); + mem_free (xprt, sizeof (SVCXPRT)); + return NULL; + } + r->sendsize = sendsize; + r->recvsize = recvsize; + xprt->xp_p2 = NULL; + xprt->xp_p1 = (caddr_t) r; + xprt->xp_verf = _null_auth; + xprt->xp_ops = &svcunix_rendezvous_op; + xprt->xp_port = -1; + xprt->xp_sock = sock; + xprt_register (xprt); + return xprt; +} +libc_hidden_nolink_sunrpc (svcunix_create, GLIBC_2_1) + +/* + * Like svunix_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcunixfd_create (int fd, u_int sendsize, u_int recvsize) +{ + return makefd_xprt (fd, sendsize, recvsize); +} +libc_hidden_nolink_sunrpc (svcunixfd_create, GLIBC_2_1) + +static SVCXPRT * +internal_function +makefd_xprt (int fd, u_int sendsize, u_int recvsize) +{ + SVCXPRT *xprt; + struct unix_conn *cd; + + xprt = (SVCXPRT *) mem_alloc (sizeof (SVCXPRT)); + cd = (struct unix_conn *) mem_alloc (sizeof (struct unix_conn)); + if (xprt == (SVCXPRT *) NULL || cd == (struct unix_conn *) NULL) + { + (void) __fxprintf (NULL, "%s: %s", "svc_unix: makefd_xprt", + _("out of memory\n")); + mem_free (xprt, sizeof (SVCXPRT)); + mem_free (cd, sizeof (struct unix_conn)); + return NULL; + } + cd->strm_stat = XPRT_IDLE; + xdrrec_create (&(cd->xdrs), sendsize, recvsize, + (caddr_t) xprt, readunix, writeunix); + 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 = &svcunix_op; /* truly deals with calls */ + xprt->xp_port = 0; /* this is a connection, not a rendezvouser */ + xprt->xp_sock = fd; + xprt_register (xprt); + return xprt; +} + +static bool_t +rendezvous_request (SVCXPRT *xprt, struct rpc_msg *errmsg) +{ + int sock; + struct unix_rendezvous *r; + struct sockaddr_un addr; + struct sockaddr_in in_addr; + socklen_t len; + + r = (struct unix_rendezvous *) xprt->xp_p1; +again: + len = sizeof (struct sockaddr_un); + if ((sock = accept (xprt->xp_sock, (struct sockaddr *) &addr, &len)) < 0) + { + if (errno == EINTR) + goto again; + __svc_accept_failed (); + return FALSE; + } + /* + * make a new transporter (re-uses xprt) + */ + memset (&in_addr, '\0', sizeof (in_addr)); + in_addr.sin_family = AF_UNIX; + xprt = makefd_xprt (sock, r->sendsize, r->recvsize); + memcpy (&xprt->xp_raddr, &in_addr, sizeof (in_addr)); + xprt->xp_addrlen = len; + return FALSE; /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat (SVCXPRT *xprt) +{ + return XPRT_IDLE; +} + +static void +svcunix_destroy (SVCXPRT *xprt) +{ + struct unix_conn *cd = (struct unix_conn *) xprt->xp_p1; + + xprt_unregister (xprt); + __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 unix_conn)); + mem_free ((caddr_t) xprt, sizeof (SVCXPRT)); +} + +#ifdef SCM_CREDENTIALS +struct cmessage { + struct cmsghdr cmsg; + struct ucred cmcred; + /* hack to make sure we have enough memory */ + char dummy[(CMSG_ALIGN (sizeof (struct ucred)) - sizeof (struct ucred) + sizeof (long))]; +}; + +/* XXX This is not thread safe, but since the main functions in svc.c + and the rpcgen generated *_svc functions for the daemon are also not + thread safe and uses static global variables, it doesn't matter. */ +static struct cmessage cm; +#endif + +static int +__msgread (int sock, void *data, size_t cnt) +{ + struct iovec iov; + struct msghdr msg; + int len; + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; +#ifdef SCM_CREDENTIALS + msg.msg_control = (caddr_t) &cm; + msg.msg_controllen = sizeof (struct cmessage); +#endif + msg.msg_flags = 0; + +#ifdef SO_PASSCRED + { + int on = 1; + if (__setsockopt (sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on))) + return -1; + } +#endif + + restart: + len = __recvmsg (sock, &msg, 0); + if (len >= 0) + { + if (msg.msg_flags & MSG_CTRUNC || len == 0) + return 0; + else + return len; + } + if (errno == EINTR) + goto restart; + return -1; +} + +static int +__msgwrite (int sock, void *data, size_t cnt) +{ +#ifndef SCM_CREDENTIALS + /* We cannot implement this reliably. */ + __set_errno (ENOSYS); + return -1; +#else + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg = &cm.cmsg; + struct ucred cred; + int len; + + /* XXX I'm not sure, if gete?id() is always correct, or if we should use + get?id(). But since keyserv needs geteuid(), we have no other chance. + It would be much better, if the kernel could pass both to the server. */ + cred.pid = __getpid (); + cred.uid = __geteuid (); + cred.gid = __getegid (); + + memcpy (CMSG_DATA(cmsg), &cred, sizeof (struct ucred)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_CREDENTIALS; + cmsg->cmsg_len = sizeof(*cmsg) + sizeof(struct ucred); + + iov.iov_base = data; + iov.iov_len = cnt; + + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_control = cmsg; + msg.msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); + msg.msg_flags = 0; + + restart: + len = __sendmsg (sock, &msg, 0); + if (len >= 0) + return len; + if (errno == EINTR) + goto restart; + return -1; + +#endif +} + +/* + * reads data from the unix connection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readunix (char *xprtptr, char *buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *) xprtptr; + int sock = xprt->xp_sock; + int milliseconds = 35 * 1000; + struct pollfd pollfd; + + do + { + pollfd.fd = sock; + pollfd.events = POLLIN; + switch (__poll (&pollfd, 1, milliseconds)) + { + case -1: + if (errno == EINTR) + continue; + /*FALLTHROUGH*/ + case 0: + goto fatal_err; + default: + if ((pollfd.revents & POLLERR) || (pollfd.revents & POLLHUP) + || (pollfd.revents & POLLNVAL)) + goto fatal_err; + break; + } + } + while ((pollfd.revents & POLLIN) == 0); + + if ((len = __msgread (sock, buf, len)) > 0) + return len; + + fatal_err: + ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; +} + +/* + * writes data to the unix connection. + * Any error is fatal and the connection is closed. + */ +static int +writeunix (char *xprtptr, char * buf, int len) +{ + SVCXPRT *xprt = (SVCXPRT *) xprtptr; + int i, cnt; + + for (cnt = len; cnt > 0; cnt -= i, buf += i) + { + if ((i = __msgwrite (xprt->xp_sock, buf, cnt)) < 0) + { + ((struct unix_conn *) (xprt->xp_p1))->strm_stat = XPRT_DIED; + return -1; + } + } + return len; +} + +static enum xprt_stat +svcunix_stat (SVCXPRT *xprt) +{ + struct unix_conn *cd = + (struct unix_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 +svcunix_recv (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + + xdrs->x_op = XDR_DECODE; + xdrrec_skiprecord (xdrs); + if (xdr_callmsg (xdrs, msg)) + { + cd->x_id = msg->rm_xid; + /* set up verifiers */ +#ifdef SCM_CREDENTIALS + msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX; + msg->rm_call.cb_verf.oa_base = (caddr_t) &cm; + msg->rm_call.cb_verf.oa_length = sizeof (cm); +#endif + return TRUE; + } + cd->strm_stat = XPRT_DIED; /* XXXX */ + return FALSE; +} + +static bool_t +svcunix_getargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + return (*xdr_args) (&(((struct unix_conn *) (xprt->xp_p1))->xdrs), + args_ptr); +} + +static bool_t +svcunix_freeargs (SVCXPRT *xprt, xdrproc_t xdr_args, caddr_t args_ptr) +{ + XDR *xdrs = &(((struct unix_conn *) (xprt->xp_p1))->xdrs); + + xdrs->x_op = XDR_FREE; + return (*xdr_args) (xdrs, args_ptr); +} + +static bool_t +svcunix_reply (SVCXPRT *xprt, struct rpc_msg *msg) +{ + struct unix_conn *cd = (struct unix_conn *) (xprt->xp_p1); + XDR *xdrs = &(cd->xdrs); + bool_t stat; + + xdrs->x_op = XDR_ENCODE; + msg->rm_xid = cd->x_id; + stat = xdr_replymsg (xdrs, msg); + (void) xdrrec_endofrecord (xdrs, TRUE); + return stat; +} diff --git a/REORG.TODO/sunrpc/svcauth_des.c b/REORG.TODO/sunrpc/svcauth_des.c new file mode 100644 index 0000000000..8e6cb86e39 --- /dev/null +++ b/REORG.TODO/sunrpc/svcauth_des.c @@ -0,0 +1,597 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * svcauth_des.c, server-side des authentication + * + * We insure for the service the following: + * (1) The timestamp microseconds do not exceed 1 million. + * (2) The timestamp plus the window is less than the current time. + * (3) The timestamp is not less than the one previously + * seen in the current session. + * + * It is up to the server to determine if the window size is + * too small . + * + */ + +#include <limits.h> +#include <string.h> +#include <stdint.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <rpc/rpc.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <rpc/svc_auth.h> +#include <rpc/svc.h> +#include <rpc/des_crypt.h> +#include <shlib-compat.h> + +#define debug(msg) /*printf("svcauth_des: %s\n", msg) */ + +#define USEC_PER_SEC ((uint32_t) 1000000L) +#define BEFORE(t1, t2) timercmp(t1, t2, <) + +/* + * LRU cache of conversation keys and some other useful items. + */ +#define AUTHDES_CACHESZ 64 +struct cache_entry + { + des_block key; /* conversation key */ + char *rname; /* client's name */ + u_int window; /* credential lifetime window */ + struct rpc_timeval laststamp; /* detect replays of creds */ + char *localcred; /* generic local credential */ + }; +#ifdef _RPC_THREAD_SAFE_ +#define authdes_cache RPC_THREAD_VARIABLE(authdes_cache_s) +#define authdes_lru RPC_THREAD_VARIABLE(authdes_lru_s) +#else +static struct cache_entry *authdes_cache; +static int *authdes_lru; +#endif + +static void cache_init (void) internal_function; /* initialize the cache */ +static short cache_spot (des_block *, char *, struct rpc_timeval *) + internal_function; /* find an entry in the cache */ +static void cache_ref (uint32_t sid) internal_function; + /* note that sid was ref'd */ + +static void invalidate (char *cred) internal_function; + /* invalidate entry in cache */ + +/* + * cache statistics + */ +struct + { + u_long ncachehits; /* times cache hit, and is not replay */ + u_long ncachereplays; /* times cache hit, and is replay */ + u_long ncachemisses; /* times cache missed */ + } +svcauthdes_stats; + +/* + * Service side authenticator for AUTH_DES + */ +enum auth_stat +_svcauth_des (register struct svc_req *rqst, register struct rpc_msg *msg) +{ + register uint32_t *ixdr; + des_block cryptbuf[2]; + register struct authdes_cred *cred; + struct authdes_verf verf; + int status; + register struct cache_entry *entry; + uint32_t sid = 0; + des_block *sessionkey; + des_block ivec; + u_int window; + struct rpc_timeval timestamp; + uint32_t namelen; + struct area + { + struct authdes_cred area_cred; + char area_netname[MAXNETNAMELEN + 1]; + } + *area; + + if (authdes_cache == NULL) + cache_init (); + if (authdes_cache == NULL) /* No free memory */ + return AUTH_FAILED; + + area = (struct area *) rqst->rq_clntcred; + cred = (struct authdes_cred *) &area->area_cred; + + /* + * Get the credential + */ + if (msg->rm_call.cb_cred.oa_length <= 0 || + msg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) + return AUTH_BADCRED; + + ixdr = (uint32_t *) msg->rm_call.cb_cred.oa_base; + cred->adc_namekind = IXDR_GET_ENUM (ixdr, enum authdes_namekind); + switch (cred->adc_namekind) + { + case ADN_FULLNAME: + namelen = IXDR_GET_U_INT32 (ixdr); + if (namelen > MAXNETNAMELEN) + { + return AUTH_BADCRED; + } + cred->adc_fullname.name = area->area_netname; + memcpy (cred->adc_fullname.name, (char *) ixdr, namelen); + cred->adc_fullname.name[namelen] = 0; + ixdr += (RNDUP (namelen) / BYTES_PER_XDR_UNIT); + cred->adc_fullname.key.key.high = *ixdr++; + cred->adc_fullname.key.key.low = *ixdr++; + cred->adc_fullname.window = *ixdr++; + break; + case ADN_NICKNAME: + cred->adc_nickname = *ixdr++; + break; + default: + return AUTH_BADCRED; + } + + /* + * Get the verifier + */ + if (msg->rm_call.cb_verf.oa_length <= 0 || + msg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) + return AUTH_BADCRED; + + ixdr = (uint32_t *) msg->rm_call.cb_verf.oa_base; + verf.adv_xtimestamp.key.high = *ixdr++; + verf.adv_xtimestamp.key.low = *ixdr++; + verf.adv_int_u = *ixdr++; + + /* + * Get the conversation key + */ + if (cred->adc_namekind == ADN_FULLNAME) + { + netobj pkey; + char pkey_data[1024]; + + sessionkey = &cred->adc_fullname.key; + if (!getpublickey (cred->adc_fullname.name, pkey_data)) + { + debug("getpublickey"); + return AUTH_BADCRED; + } + pkey.n_bytes = pkey_data; + pkey.n_len = strlen (pkey_data) + 1; + if (key_decryptsession_pk (cred->adc_fullname.name, &pkey, + sessionkey) < 0) + { + debug ("decryptsessionkey"); + return AUTH_BADCRED; /* key not found */ + } + } + else + { /* ADN_NICKNAME */ + if (cred->adc_nickname >= AUTHDES_CACHESZ) + { + debug ("bad nickname"); + return AUTH_BADCRED; /* garbled credential */ + } + else + sid = cred->adc_nickname; + + /* XXX This could be wrong, but else we have a + security problem */ + if (authdes_cache[sid].rname == NULL) + return AUTH_BADCRED; + sessionkey = &authdes_cache[sid].key; + } + + + /* + * Decrypt the timestamp + */ + cryptbuf[0] = verf.adv_xtimestamp; + if (cred->adc_namekind == ADN_FULLNAME) + { + cryptbuf[1].key.high = cred->adc_fullname.window; + cryptbuf[1].key.low = verf.adv_winverf; + ivec.key.high = ivec.key.low = 0; + status = cbc_crypt ((char *) sessionkey, (char *) cryptbuf, + 2 * sizeof (des_block), DES_DECRYPT | DES_HW, + (char *) &ivec); + } + else + status = ecb_crypt ((char *) sessionkey, (char *) cryptbuf, + sizeof (des_block), DES_DECRYPT | DES_HW); + + if (DES_FAILED (status)) + { + debug ("decryption failure"); + return AUTH_FAILED; /* system error */ + } + + /* + * XDR the decrypted timestamp + */ + ixdr = (uint32_t *) cryptbuf; + timestamp.tv_sec = IXDR_GET_INT32 (ixdr); + timestamp.tv_usec = IXDR_GET_INT32 (ixdr); + + /* + * Check for valid credentials and verifiers. + * They could be invalid because the key was flushed + * out of the cache, and so a new session should begin. + * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case. + */ + { + struct timeval current; + int nick; + u_int winverf; + + if (cred->adc_namekind == ADN_FULLNAME) + { + short tmp_spot; + + window = IXDR_GET_U_INT32 (ixdr); + winverf = IXDR_GET_U_INT32 (ixdr); + if (winverf != window - 1) + { + debug ("window verifier mismatch"); + return AUTH_BADCRED; /* garbled credential */ + } + tmp_spot = cache_spot (sessionkey, cred->adc_fullname.name, + ×tamp); + if (tmp_spot < 0 || tmp_spot > AUTHDES_CACHESZ) + { + debug ("replayed credential"); + return AUTH_REJECTEDCRED; /* replay */ + } + sid = tmp_spot; + nick = 0; + } + else + { /* ADN_NICKNAME */ + window = authdes_cache[sid].window; + nick = 1; + } + + if (timestamp.tv_usec >= USEC_PER_SEC) + { + debug ("invalid usecs"); + /* cached out (bad key), or garbled verifier */ + return nick ? AUTH_REJECTEDVERF : AUTH_BADVERF; + } + if (nick && BEFORE (×tamp, &authdes_cache[sid].laststamp)) + { + debug ("timestamp before last seen"); + return AUTH_REJECTEDVERF; /* replay */ + } + __gettimeofday (¤t, (struct timezone *) NULL); + current.tv_sec -= window; /* allow for expiration */ + if (!BEFORE (¤t, ×tamp)) + { + debug ("timestamp expired"); + /* replay, or garbled credential */ + return nick ? AUTH_REJECTEDVERF : AUTH_BADCRED; + } + } + + /* + * Set up the reply verifier + */ + verf.adv_nickname = sid; + + /* + * xdr the timestamp before encrypting + */ + ixdr = (uint32_t *) cryptbuf; + IXDR_PUT_INT32 (ixdr, timestamp.tv_sec - 1); + IXDR_PUT_INT32 (ixdr, timestamp.tv_usec); + + /* + * encrypt the timestamp + */ + status = ecb_crypt ((char *) sessionkey, (char *) cryptbuf, + sizeof (des_block), DES_ENCRYPT | DES_HW); + if (DES_FAILED (status)) + { + debug ("encryption failure"); + return AUTH_FAILED; /* system error */ + } + verf.adv_xtimestamp = cryptbuf[0]; + + /* + * Serialize the reply verifier, and update rqst + */ + ixdr = (uint32_t *) msg->rm_call.cb_verf.oa_base; + *ixdr++ = verf.adv_xtimestamp.key.high; + *ixdr++ = verf.adv_xtimestamp.key.low; + *ixdr++ = verf.adv_int_u; + + rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES; + rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; + rqst->rq_xprt->xp_verf.oa_length = + (char *) ixdr - msg->rm_call.cb_verf.oa_base; + + /* + * We succeeded, commit the data to the cache now and + * finish cooking the credential. + */ + entry = &authdes_cache[sid]; + entry->laststamp = timestamp; + cache_ref (sid); + if (cred->adc_namekind == ADN_FULLNAME) + { + size_t full_len; + + cred->adc_fullname.window = window; + cred->adc_nickname = sid; /* save nickname */ + if (entry->rname != NULL) + mem_free (entry->rname, strlen (entry->rname) + 1); + full_len = strlen (cred->adc_fullname.name) + 1; + entry->rname = mem_alloc ((u_int) full_len); + if (entry->rname != NULL) + memcpy (entry->rname, cred->adc_fullname.name, full_len); + else + { + debug ("out of memory"); + return AUTH_FAILED; /* out of memory is bad */ + } + entry->key = *sessionkey; + entry->window = window; + invalidate (entry->localcred); /* mark any cached cred invalid */ + } + else + { /* ADN_NICKNAME */ + /* + * nicknames are cooked into fullnames + */ + cred->adc_namekind = ADN_FULLNAME; + cred->adc_fullname.name = entry->rname; + cred->adc_fullname.key = entry->key; + cred->adc_fullname.window = entry->window; + } + return AUTH_OK; /* we made it! */ +} + + +/* + * Initialize the cache + */ +static void +internal_function +cache_init (void) +{ + register int i; + + authdes_cache = (struct cache_entry *) + calloc (sizeof (struct cache_entry) * AUTHDES_CACHESZ, 1); + if (authdes_cache == NULL) + return; + + authdes_lru = (int *) mem_alloc (sizeof (int) * AUTHDES_CACHESZ); + /* + * Initialize the lru list + */ + for (i = 0; i < AUTHDES_CACHESZ; ++i) + authdes_lru[i] = i; +} + + +/* + * Find the lru victim + */ +static short +cache_victim (void) +{ + return authdes_lru[AUTHDES_CACHESZ - 1]; +} + +/* + * Note that sid was referenced + */ +static void +internal_function +cache_ref (register uint32_t sid) +{ + register int i; + register int curr; + register int prev; + + prev = authdes_lru[0]; + authdes_lru[0] = sid; + for (i = 1; prev != sid; ++i) + { + curr = authdes_lru[i]; + authdes_lru[i] = prev; + prev = curr; + } +} + +/* + * Find a spot in the cache for a credential containing + * the items given. Return -1 if a replay is detected, otherwise + * return the spot in the cache. + */ +static short +internal_function +cache_spot (register des_block *key, char *name, + struct rpc_timeval *timestamp) +{ + register struct cache_entry *cp; + register int i; + register uint32_t hi; + + hi = key->key.high; + for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; ++i, ++cp) + { + if (cp->key.key.high == hi && + cp->key.key.low == key->key.low && + cp->rname != NULL && + memcmp (cp->rname, name, strlen (name) + 1) == 0) + { + if (BEFORE (timestamp, &cp->laststamp)) + { + ++svcauthdes_stats.ncachereplays; + return -1; /* replay */ + } + ++svcauthdes_stats.ncachehits; + return i; /* refresh */ + } + } + ++svcauthdes_stats.ncachemisses; + return cache_victim (); /* new credential */ +} + +/* + * Local credential handling stuff. + * NOTE: bsd unix dependent. + * Other operating systems should put something else here. + */ +#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */ +#define INVALID -1 /* grouplen, if cache entry is invalid */ + +struct bsdcred +{ + uid_t uid; /* cached uid */ + gid_t gid; /* cached gid */ + int grouplen; /* length of cached groups */ + int grouplen_max; /* length of allocated cached groups */ + gid_t groups[0]; /* cached groups */ +}; + +/* + * Map a des credential into a unix cred. + * We cache the credential here so the application does + * not have to make an rpc call every time to interpret + * the credential. + */ +int +authdes_getucred (const struct authdes_cred *adc, uid_t * uid, gid_t * gid, + short *grouplen, gid_t * groups) +{ + unsigned sid; + register int i; + uid_t i_uid; + gid_t i_gid; + int i_grouplen; + struct bsdcred *cred; + + sid = adc->adc_nickname; + if (sid >= AUTHDES_CACHESZ) + { + debug ("invalid nickname"); + return 0; + } + cred = (struct bsdcred *) authdes_cache[sid].localcred; + if (cred == NULL || cred->grouplen == INVALID) + { + /* + * not in cache: lookup + */ + if (!netname2user (adc->adc_fullname.name, &i_uid, &i_gid, + &i_grouplen, groups)) + { + debug ("unknown netname"); + if (cred != NULL) + cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */ + return 0; + } + + if (cred != NULL && cred->grouplen_max < i_grouplen) + { + /* We already have an allocated data structure. But it is + too small. */ + free (cred); + authdes_cache[sid].localcred = NULL; + cred = NULL; + } + + if (cred == NULL) + { + /* We should allocate room for at least NGROUPS groups. */ + int ngroups_max = MAX (i_grouplen, NGROUPS); + + cred = (struct bsdcred *) mem_alloc (sizeof (struct bsdcred) + + ngroups_max * sizeof (gid_t)); + if (cred == NULL) + return 0; + + authdes_cache[sid].localcred = (char *) cred; + cred->grouplen = INVALID; + cred->grouplen_max = ngroups_max; + } + + debug ("missed ucred cache"); + *uid = cred->uid = i_uid; + *gid = cred->gid = i_gid; + cred->grouplen = i_grouplen; + for (i = i_grouplen - 1; i >= 0; --i) + cred->groups[i] = groups[i]; + /* Make sure no too large values are reported. */ + *grouplen = MIN (SHRT_MAX, i_grouplen); + return 1; + } + else if (cred->grouplen == UNKNOWN) + { + /* + * Already lookup up, but no match found + */ + return 0; + } + + /* + * cached credentials + */ + *uid = cred->uid; + *gid = cred->gid; + + /* Another stupidity in the interface: *grouplen is of type short. + So we might have to cut the information passed up short. */ + int grouplen_copy = MIN (SHRT_MAX, cred->grouplen); + *grouplen = grouplen_copy; + for (i = grouplen_copy - 1; i >= 0; --i) + groups[i] = cred->groups[i]; + return 1; +} +libc_hidden_nolink_sunrpc (authdes_getucred, GLIBC_2_1) + +static void +internal_function +invalidate (char *cred) +{ + if (cred == NULL) + return; + ((struct bsdcred *) cred)->grouplen = INVALID; +} diff --git a/REORG.TODO/sunrpc/test-rpcent.c b/REORG.TODO/sunrpc/test-rpcent.c new file mode 100644 index 0000000000..fc21373f8a --- /dev/null +++ b/REORG.TODO/sunrpc/test-rpcent.c @@ -0,0 +1,74 @@ +/* Test getrpcent and friends. + Copyright (C) 2015-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* This is taken from nss/test-netdb.c and is intended to follow that + test's model for everything. This test is separate only because + the <rpc/netdb.h> interfaces do not exist in configurations that + omit sunrpc/ from the build. */ + +#include <stdio.h> +#include <rpc/netdb.h> + + +static void +output_rpcent (const char *call, struct rpcent *rptr) +{ + char **pptr; + + if (rptr == NULL) + printf ("Call: %s returned NULL\n", call); + else + { + printf ("Call: %s, returned: r_name: %s, r_number: %d\n", + call, rptr->r_name, rptr->r_number); + for (pptr = rptr->r_aliases; *pptr != NULL; pptr++) + printf (" alias: %s\n", *pptr); + } +} + +static void +test_rpc (void) +{ + struct rpcent *rptr; + + rptr = getrpcbyname ("portmap"); + output_rpcent ("getrpcyname (\"portmap\")", rptr); + + rptr = getrpcbynumber (100000); + output_rpcent ("getrpcbynumber (100000)", rptr); + + setrpcent (0); + do + { + rptr = getrpcent (); + output_rpcent ("getrpcent ()", rptr); + } + while (rptr != NULL); + endrpcent (); +} + +static int +do_test (void) +{ + test_rpc (); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/sunrpc/thrsvc.c b/REORG.TODO/sunrpc/thrsvc.c new file mode 100644 index 0000000000..63cfbf9810 --- /dev/null +++ b/REORG.TODO/sunrpc/thrsvc.c @@ -0,0 +1,109 @@ +#include <pthread.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <rpc/rpc.h> +#include <arpa/inet.h> + +#define PROGNUM 1234 +#define VERSNUM 1 +#define PROCNUM 1 +#define PROCQUIT 2 + +static int exitcode; + +struct rpc_arg +{ + CLIENT *client; + u_long proc; +}; + +static void +dispatch(struct svc_req *request, SVCXPRT *xprt) +{ + svc_sendreply(xprt, (xdrproc_t)xdr_void, 0); + if (request->rq_proc == PROCQUIT) + exit (0); +} + +static void +test_one_call (struct rpc_arg *a) +{ + struct timeval tout = { 60, 0 }; + enum clnt_stat result; + + printf ("test_one_call: "); + result = clnt_call (a->client, a->proc, + (xdrproc_t) xdr_void, 0, + (xdrproc_t) xdr_void, 0, tout); + if (result == RPC_SUCCESS) + puts ("success"); + else + { + clnt_perrno (result); + putchar ('\n'); + exitcode = 1; + } +} + +static void * +thread_wrapper (void *arg) +{ + struct rpc_arg a; + + a.client = (CLIENT *)arg; + a.proc = PROCNUM; + test_one_call (&a); + a.client = (CLIENT *)arg; + a.proc = PROCQUIT; + test_one_call (&a); + return 0; +} + +int +main (void) +{ + pthread_t tid; + pid_t pid; + int err; + SVCXPRT *svx; + CLIENT *clnt; + struct sockaddr_in sin; + struct timeval wait = { 5, 0 }; + int sock = RPC_ANYSOCK; + struct rpc_arg a; + + svx = svcudp_create (RPC_ANYSOCK); + svc_register (svx, PROGNUM, VERSNUM, dispatch, 0); + + pid = fork (); + if (pid == -1) + { + perror ("fork"); + return 1; + } + if (pid == 0) + svc_run (); + + inet_aton ("127.0.0.1", &sin.sin_addr); + sin.sin_port = htons (svx->xp_port); + sin.sin_family = AF_INET; + + clnt = clntudp_create (&sin, PROGNUM, VERSNUM, wait, &sock); + + a.client = clnt; + a.proc = PROCNUM; + + /* Test in this thread */ + test_one_call (&a); + + /* Test in a child thread */ + err = pthread_create (&tid, 0, thread_wrapper, (void *) clnt); + if (err) + fprintf (stderr, "pthread_create: %s\n", strerror (err)); + err = pthread_join (tid, 0); + if (err) + fprintf (stderr, "pthread_join: %s\n", strerror (err)); + + return exitcode; +} diff --git a/REORG.TODO/sunrpc/tst-getmyaddr.c b/REORG.TODO/sunrpc/tst-getmyaddr.c new file mode 100644 index 0000000000..1eaf9b22ca --- /dev/null +++ b/REORG.TODO/sunrpc/tst-getmyaddr.c @@ -0,0 +1,24 @@ +#include <stdio.h> +#include <string.h> +#include <arpa/inet.h> +#include <netinet/in.h> +#include <rpc/clnt.h> + + +static int +do_test (void) +{ + struct sockaddr_in ad; + struct sockaddr_in ad2; + memset (&ad, '\0', sizeof (ad)); + memset (&ad2, '\0', sizeof (ad2)); + + get_myaddress (&ad); + + printf ("addr = %s:%d\n", inet_ntoa (ad.sin_addr), ad.sin_port); + + return memcmp (&ad, &ad2, sizeof (ad)) == 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/sunrpc/tst-svc_register.c b/REORG.TODO/sunrpc/tst-svc_register.c new file mode 100644 index 0000000000..8934094c99 --- /dev/null +++ b/REORG.TODO/sunrpc/tst-svc_register.c @@ -0,0 +1,299 @@ +/* Test svc_register/svc_unregister rpcbind interaction (bug 5010). + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +/* This test uses a stub rpcbind server (implemented in a child + process using rpcbind_dispatch/run_rpcbind) to check how RPC + services are registered and unregistered using the rpcbind + protocol. For each subtest, a separate rpcbind test server is + spawned and terminated. */ + +#include <errno.h> +#include <netinet/in.h> +#include <rpc/clnt.h> +#include <rpc/pmap_prot.h> +#include <rpc/svc.h> +#include <signal.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/test-driver.h> +#include <support/xsocket.h> +#include <support/xthread.h> +#include <support/xunistd.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <unistd.h> + +#include <libc-symbols.h> +#include <shlib-compat.h> + +/* These functions are only available as compat symbols. */ +compat_symbol_reference (libc, xdr_pmap, xdr_pmap, GLIBC_2_0); +compat_symbol_reference (libc, svc_unregister, svc_unregister, GLIBC_2_0); + +/* Server callback for the unused RPC service which is registered and + unregistered. */ +static void +server_dispatch (struct svc_req *request, SVCXPRT *transport) +{ + FAIL_EXIT1 ("server_dispatch called"); +} + +/* The port on which rpcbind listens for incoming requests. */ +static inline const struct sockaddr_in +rpcbind_address (void) +{ + return (struct sockaddr_in) + { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + .sin_port = htons (PMAPPORT) + }; +} + +/* Data provided by the test server after running the test, to see + that the expected calls (and only those) happened. */ +struct test_state +{ + bool_t set_called; + bool_t unset_called; +}; + +static bool_t +xdr_test_state (XDR *xdrs, void *data, ...) +{ + struct test_state *p = data; + return xdr_bool (xdrs, &p->set_called) + && xdr_bool (xdrs, &p->unset_called); +} + +enum +{ + /* Coordinates of our test service. These numbers are + arbitrary. */ + PROGNUM = 123, + VERSNUM = 456, + + /* Extension for this test. */ + PROC_GET_STATE_AND_EXIT = 10760 +}; + +/* Dummy implementation of the rpcbind service, with the + PROC_GET_STATE_AND_EXIT extension. */ +static void +rpcbind_dispatch (struct svc_req *request, SVCXPRT *transport) +{ + static struct test_state state = { 0, }; + + if (test_verbose) + printf ("info: rpcbind request %lu\n", request->rq_proc); + + switch (request->rq_proc) + { + case PMAPPROC_SET: + case PMAPPROC_UNSET: + TEST_VERIFY (state.set_called == (request->rq_proc == PMAPPROC_UNSET)); + TEST_VERIFY (!state.unset_called); + + struct pmap query = { 0, }; + TEST_VERIFY + (svc_getargs (transport, (xdrproc_t) xdr_pmap, (void *) &query)); + if (test_verbose) + printf (" pm_prog=%lu pm_vers=%lu pm_prot=%lu pm_port=%lu\n", + query.pm_prog, query.pm_vers, query.pm_prot, query.pm_port); + TEST_VERIFY (query.pm_prog == PROGNUM); + TEST_VERIFY (query.pm_vers == VERSNUM); + + if (request->rq_proc == PMAPPROC_SET) + state.set_called = TRUE; + else + state.unset_called = TRUE; + + bool_t result = TRUE; + TEST_VERIFY (svc_sendreply (transport, + (xdrproc_t) xdr_bool, (void *) &result)); + break; + + case PROC_GET_STATE_AND_EXIT: + TEST_VERIFY (svc_sendreply (transport, + xdr_test_state, (void *) &state)); + _exit (0); + break; + + default: + FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc); + } +} + +/* Run the rpcbind test server. */ +static void +run_rpcbind (int rpcbind_sock) +{ + SVCXPRT *rpcbind_transport = svcudp_create (rpcbind_sock); + TEST_VERIFY (svc_register (rpcbind_transport, PMAPPROG, PMAPVERS, + rpcbind_dispatch, + /* Do not register with rpcbind. */ + 0)); + svc_run (); +} + +/* Call out to the rpcbind test server to retrieve the test status + information. */ +static struct test_state +get_test_state (void) +{ + int socket = RPC_ANYSOCK; + struct sockaddr_in address = rpcbind_address (); + CLIENT *client = clntudp_create + (&address, PMAPPROG, PMAPVERS, (struct timeval) { 1, 0}, &socket); + struct test_state result = { 0 }; + TEST_VERIFY (clnt_call (client, PROC_GET_STATE_AND_EXIT, + (xdrproc_t) xdr_void, NULL, + xdr_test_state, (void *) &result, + ((struct timeval) { 3, 0})) + == RPC_SUCCESS); + clnt_destroy (client); + return result; +} + +/* Used by test_server_thread to receive test parameters. */ +struct test_server_args +{ + bool use_rpcbind; + bool use_unregister; +}; + +/* RPC test server. Used to verify the svc_unregister behavior during + thread cleanup. */ +static void * +test_server_thread (void *closure) +{ + struct test_server_args *args = closure; + SVCXPRT *transport = svcudp_create (RPC_ANYSOCK); + int protocol; + if (args->use_rpcbind) + protocol = IPPROTO_UDP; + else + /* Do not register with rpcbind. */ + protocol = 0; + TEST_VERIFY (svc_register (transport, PROGNUM, VERSNUM, + server_dispatch, protocol)); + if (args->use_unregister) + svc_unregister (PROGNUM, VERSNUM); + SVC_DESTROY (transport); + return NULL; +} + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + + /* Try to bind to the rpcbind port. */ + int rpcbind_sock = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + { + struct sockaddr_in sin = rpcbind_address (); + if (bind (rpcbind_sock, (struct sockaddr *) &sin, sizeof (sin)) != 0) + { + /* If the port is not available, we cannot run this test. */ + printf ("warning: could not bind to rpcbind port %d: %m\n", + (int) PMAPPORT); + return EXIT_UNSUPPORTED; + } + } + + for (int use_thread = 0; use_thread < 2; ++use_thread) + for (int use_rpcbind = 0; use_rpcbind < 2; ++use_rpcbind) + for (int use_unregister = 0; use_unregister < 2; ++use_unregister) + { + if (test_verbose) + printf ("info: * use_thread=%d use_rpcbind=%d use_unregister=%d\n", + use_thread, use_rpcbind, use_unregister); + + /* Create the subprocess which runs the actual test. The + kernel will queue the UDP packets to the rpcbind + process. */ + pid_t svc_pid = xfork (); + if (svc_pid == 0) + { + struct test_server_args args = + { + .use_rpcbind = use_rpcbind, + .use_unregister = use_unregister, + }; + if (use_thread) + xpthread_join (xpthread_create + (NULL, test_server_thread, &args)); + else + test_server_thread (&args); + /* We cannnot use _exit here because we want to test the + process cleanup. */ + exit (0); + } + + /* Create the subprocess for the rpcbind test server. */ + pid_t rpcbind_pid = xfork (); + if (rpcbind_pid == 0) + run_rpcbind (rpcbind_sock); + + int status; + xwaitpid (svc_pid, &status, 0); + TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == 0); + + if (!use_rpcbind) + /* Wait a bit, to see if the packet arrives on the rpcbind + port. The choice is of the timeout is arbitrary, but + should be long enough even for slow/busy systems. For + the use_rpcbind case, waiting on svc_pid above makes + sure that the test server has responded because + svc_register/svc_unregister are supposed to wait for a + reply. */ + usleep (300 * 1000); + + struct test_state state = get_test_state (); + if (use_rpcbind) + { + TEST_VERIFY (state.set_called); + if (use_thread || use_unregister) + /* Thread cleanup or explicit svc_unregister will + result in a rpcbind unset RPC call. */ + TEST_VERIFY (state.unset_called); + else + /* This is arguably a bug: Regular process termination + does not unregister the service with rpcbind. The + unset rpcbind call happens from a __libc_subfreeres + callback, and this only happens when running under + memory debuggers such as valgrind. */ + TEST_VERIFY (!state.unset_called); + } + else + { + /* If rpcbind registration is not requested, we do not + expect any rpcbind calls. */ + TEST_VERIFY (!state.set_called); + TEST_VERIFY (!state.unset_called); + } + + xwaitpid (rpcbind_pid, &status, 0); + TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == 0); + } + + return 0; +} + +#include <support/test-driver.c> diff --git a/REORG.TODO/sunrpc/tst-udp-error.c b/REORG.TODO/sunrpc/tst-udp-error.c new file mode 100644 index 0000000000..1efc02f5c6 --- /dev/null +++ b/REORG.TODO/sunrpc/tst-udp-error.c @@ -0,0 +1,62 @@ +/* Check for use-after-free in clntudp_call (bug 21115). + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <rpc/clnt.h> +#include <rpc/svc.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/xsocket.h> +#include <unistd.h> + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + + /* Obtain a likely-unused port number. */ + struct sockaddr_in sin = + { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + }; + { + int fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0); + xbind (fd, (struct sockaddr *) &sin, sizeof (sin)); + socklen_t sinlen = sizeof (sin); + xgetsockname (fd, (struct sockaddr *) &sin, &sinlen); + /* Close the socket, so that we will receive an error below. */ + close (fd); + } + + int sock = RPC_ANYSOCK; + CLIENT *clnt = clntudp_create + (&sin, 1, 2, (struct timeval) { 1, 0 }, &sock); + TEST_VERIFY_EXIT (clnt != NULL); + TEST_VERIFY (clnt_call (clnt, 3, + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, + ((struct timeval) { 3, 0 })) + == RPC_CANTRECV); + clnt_destroy (clnt); + + return 0; +} + +#include <support/test-driver.c> diff --git a/REORG.TODO/sunrpc/tst-udp-garbage.c b/REORG.TODO/sunrpc/tst-udp-garbage.c new file mode 100644 index 0000000000..4abda93f08 --- /dev/null +++ b/REORG.TODO/sunrpc/tst-udp-garbage.c @@ -0,0 +1,104 @@ +/* Test that garbage packets do not affect timeout handling. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <rpc/clnt.h> +#include <rpc/svc.h> +#include <stdbool.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/xsocket.h> +#include <support/xthread.h> +#include <sys/socket.h> +#include <unistd.h> + +/* Descriptor for the server UDP socket. */ +static int server_fd; + +static void * +garbage_sender_thread (void *unused) +{ + while (true) + { + struct sockaddr_storage sa; + socklen_t salen = sizeof (sa); + char buf[1]; + if (recvfrom (server_fd, buf, sizeof (buf), 0, + (struct sockaddr *) &sa, &salen) < 0) + FAIL_EXIT1 ("recvfrom: %m"); + + /* Send garbage packets indefinitely. */ + buf[0] = 0; + while (true) + { + /* sendto can fail if the client closed the socket. */ + if (sendto (server_fd, buf, sizeof (buf), 0, + (struct sockaddr *) &sa, salen) < 0) + break; + + /* Wait a bit, to avoid burning too many CPU cycles in a + tight loop. The wait period must be much shorter than + the client timeouts configured below. */ + usleep (50 * 1000); + } + } +} + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + + server_fd = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); + struct sockaddr_in server_address = + { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + }; + xbind (server_fd, + (struct sockaddr *) &server_address, sizeof (server_address)); + { + socklen_t sinlen = sizeof (server_address); + xgetsockname (server_fd, (struct sockaddr *) &server_address, &sinlen); + TEST_VERIFY (sizeof (server_address) == sinlen); + } + + /* Garbage packet source. */ + xpthread_detach (xpthread_create (NULL, garbage_sender_thread, NULL)); + + /* Test client. Use an arbitrary timeout of one second, which is + much longer than the garbage packet interval, but still + reasonably short, so that the test completes quickly. */ + int client_fd = RPC_ANYSOCK; + CLIENT *clnt = clntudp_create (&server_address, + 1, 2, /* Arbitrary RPC endpoint numbers. */ + (struct timeval) { 1, 0 }, + &client_fd); + if (clnt == NULL) + FAIL_EXIT1 ("clntudp_create: %m"); + + TEST_VERIFY (clnt_call (clnt, 3, /* Arbitrary RPC procedure number. */ + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, + ((struct timeval) { 1, 0 }))); + + return 0; +} + +#include <support/test-driver.c> diff --git a/REORG.TODO/sunrpc/tst-udp-nonblocking.c b/REORG.TODO/sunrpc/tst-udp-nonblocking.c new file mode 100644 index 0000000000..1d6a7f4b56 --- /dev/null +++ b/REORG.TODO/sunrpc/tst-udp-nonblocking.c @@ -0,0 +1,333 @@ +/* Test non-blocking use of the UDP client. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <rpc/clnt.h> +#include <rpc/svc.h> +#include <stdbool.h> +#include <string.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/test-driver.h> +#include <support/xsocket.h> +#include <support/xunistd.h> +#include <sys/socket.h> +#include <time.h> +#include <unistd.h> + +/* Test data serialization and deserialization. */ + +struct test_query +{ + uint32_t a; + uint32_t b; + uint32_t timeout_ms; +}; + +static bool_t +xdr_test_query (XDR *xdrs, void *data, ...) +{ + struct test_query *p = data; + return xdr_uint32_t (xdrs, &p->a) + && xdr_uint32_t (xdrs, &p->b) + && xdr_uint32_t (xdrs, &p->timeout_ms); +} + +struct test_response +{ + uint32_t server_id; + uint32_t seq; + uint32_t sum; +}; + +static bool_t +xdr_test_response (XDR *xdrs, void *data, ...) +{ + struct test_response *p = data; + return xdr_uint32_t (xdrs, &p->server_id) + && xdr_uint32_t (xdrs, &p->seq) + && xdr_uint32_t (xdrs, &p->sum); +} + +/* Implementation of the test server. */ + +enum + { + /* Number of test servers to run. */ + SERVER_COUNT = 3, + + /* RPC parameters, chosen at random. */ + PROGNUM = 8242, + VERSNUM = 19654, + + /* Main RPC operation. */ + PROC_ADD = 1, + + /* Request process termination. */ + PROC_EXIT, + + /* Special exit status to mark successful processing. */ + EXIT_MARKER = 55, + }; + +/* Set by the parent process to tell test servers apart. */ +static int server_id; + +/* Implementation of the test server. */ +static void +server_dispatch (struct svc_req *request, SVCXPRT *transport) +{ + /* Query sequence number. */ + static uint32_t seq = 0; + ++seq; + static bool proc_add_seen; + + if (test_verbose) + printf ("info: server_dispatch server_id=%d seq=%u rq_proc=%lu\n", + server_id, seq, request->rq_proc); + + switch (request->rq_proc) + { + case PROC_ADD: + { + struct test_query query; + memset (&query, 0xc0, sizeof (query)); + TEST_VERIFY_EXIT + (svc_getargs (transport, xdr_test_query, + (void *) &query)); + + if (test_verbose) + printf (" a=%u b=%u timeout_ms=%u\n", + query.a, query.b, query.timeout_ms); + + usleep (query.timeout_ms * 1000); + + struct test_response response = + { + .server_id = server_id, + .seq = seq, + .sum = query.a + query.b, + }; + TEST_VERIFY (svc_sendreply (transport, xdr_test_response, + (void *) &response)); + if (test_verbose) + printf (" server id %d response seq=%u sent\n", server_id, seq); + proc_add_seen = true; + } + break; + + case PROC_EXIT: + TEST_VERIFY (proc_add_seen); + TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL)); + _exit (EXIT_MARKER); + break; + + default: + FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc); + break; + } +} + +/* Return the number seconds since an arbitrary point in time. */ +static double +get_ticks (void) +{ + { + struct timespec ts; + if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) + return ts.tv_sec + ts.tv_nsec * 1e-9; + } + { + struct timeval tv; + TEST_VERIFY_EXIT (gettimeofday (&tv, NULL) == 0); + return tv.tv_sec + tv.tv_usec * 1e-6; + } +} + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + + /* Information about the test servers. */ + struct + { + SVCXPRT *transport; + struct sockaddr_in address; + pid_t pid; + uint32_t xid; + } servers[SERVER_COUNT]; + + /* Spawn the test servers. */ + for (int i = 0; i < SERVER_COUNT; ++i) + { + servers[i].transport = svcudp_create (RPC_ANYSOCK); + TEST_VERIFY_EXIT (servers[i].transport != NULL); + servers[i].address = (struct sockaddr_in) + { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + .sin_port = htons (servers[i].transport->xp_port), + }; + servers[i].xid = 0xabcd0101 + i; + if (test_verbose) + printf ("info: setting up server %d xid=%x on port %d\n", + i, servers[i].xid, servers[i].transport->xp_port); + + server_id = i; + servers[i].pid = xfork (); + if (servers[i].pid == 0) + { + TEST_VERIFY (svc_register (servers[i].transport, + PROGNUM, VERSNUM, server_dispatch, 0)); + svc_run (); + FAIL_EXIT1 ("supposed to be unreachable"); + } + /* We need to close the socket so that we do not accidentally + consume the request. */ + TEST_VERIFY (close (servers[i].transport->xp_sock) == 0); + } + + + /* The following code mirrors what ypbind does. */ + + /* Copied from clnt_udp.c (like ypbind). */ + struct cu_data + { + int cu_sock; + bool_t cu_closeit; + struct sockaddr_in cu_raddr; + int cu_rlen; + struct timeval cu_wait; + struct timeval cu_total; + struct rpc_err cu_error; + XDR cu_outxdrs; + u_int cu_xdrpos; + u_int cu_sendsz; + char *cu_outbuf; + u_int cu_recvsz; + char cu_inbuf[1]; + }; + + int client_socket = xsocket (AF_INET, SOCK_DGRAM | SOCK_NONBLOCK, 0); + CLIENT *clnt = clntudp_create (&servers[0].address, PROGNUM, VERSNUM, + /* 5 seconds per-response timeout. */ + ((struct timeval) { 5, 0 }), + &client_socket); + TEST_VERIFY (clnt != NULL); + clnt->cl_auth = authunix_create_default (); + { + struct timeval zero = { 0, 0 }; + TEST_VERIFY (clnt_control (clnt, CLSET_TIMEOUT, (void *) &zero)); + } + + /* Poke at internal data structures (like ypbind). */ + struct cu_data *cu = (struct cu_data *) clnt->cl_private; + + /* Send a ping to each server. */ + double before_pings = get_ticks (); + for (int i = 0; i < SERVER_COUNT; ++i) + { + if (test_verbose) + printf ("info: sending server %d ping\n", i); + /* Reset the xid because it is changed by each invocation of + clnt_call. Subtract one to compensate for the xid update + during the call. */ + *((u_int32_t *) (cu->cu_outbuf)) = servers[i].xid - 1; + cu->cu_raddr = servers[i].address; + + struct test_query query = { .a = 100, .b = i + 1 }; + if (i == 1) + /* Shorter timeout to prefer this server. These timeouts must + be much shorter than the 5-second per-response timeout + configured with clntudp_create. */ + query.timeout_ms = 700; + else + query.timeout_ms = 1400; + struct test_response response = { 0 }; + /* NB: Do not check the return value. The server reply will + prove that the call worked. */ + double before_one_ping = get_ticks (); + clnt_call (clnt, PROC_ADD, + xdr_test_query, (void *) &query, + xdr_test_response, (void *) &response, + ((struct timeval) { 0, 0 })); + double after_one_ping = get_ticks (); + if (test_verbose) + printf ("info: non-blocking send took %f seconds\n", + after_one_ping - before_one_ping); + /* clnt_call should return immediately. Accept some delay in + case the process is descheduled. */ + TEST_VERIFY (after_one_ping - before_one_ping < 0.3); + } + + /* Collect the non-blocking response. */ + if (test_verbose) + printf ("info: collecting response\n"); + struct test_response response = { 0 }; + TEST_VERIFY + (clnt_call (clnt, PROC_ADD, NULL, NULL, + xdr_test_response, (void *) &response, + ((struct timeval) { 0, 0 })) == RPC_SUCCESS); + double after_pings = get_ticks (); + if (test_verbose) + printf ("info: send/receive took %f seconds\n", + after_pings - before_pings); + /* Expected timeout is 0.7 seconds. */ + TEST_VERIFY (0.7 <= after_pings - before_pings); + TEST_VERIFY (after_pings - before_pings < 1.2); + + uint32_t xid; + memcpy (&xid, &cu->cu_inbuf, sizeof (xid)); + if (test_verbose) + printf ("info: non-blocking response: xid=%x server_id=%u seq=%u sum=%u\n", + xid, response.server_id, response.seq, response.sum); + /* Check that the reply from the preferred server was used. */ + TEST_VERIFY (servers[1].xid == xid); + TEST_VERIFY (response.server_id == 1); + TEST_VERIFY (response.seq == 1); + TEST_VERIFY (response.sum == 102); + + auth_destroy (clnt->cl_auth); + clnt_destroy (clnt); + + for (int i = 0; i < SERVER_COUNT; ++i) + { + if (test_verbose) + printf ("info: requesting server %d termination\n", i); + client_socket = RPC_ANYSOCK; + clnt = clntudp_create (&servers[i].address, PROGNUM, VERSNUM, + ((struct timeval) { 5, 0 }), + &client_socket); + TEST_VERIFY_EXIT (clnt != NULL); + TEST_VERIFY (clnt_call (clnt, PROC_EXIT, + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, + ((struct timeval) { 3, 0 })) == RPC_SUCCESS); + clnt_destroy (clnt); + + int status; + xwaitpid (servers[i].pid, &status, 0); + TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_MARKER); + } + + return 0; +} + +#include <support/test-driver.c> diff --git a/REORG.TODO/sunrpc/tst-udp-timeout.c b/REORG.TODO/sunrpc/tst-udp-timeout.c new file mode 100644 index 0000000000..db9943a03e --- /dev/null +++ b/REORG.TODO/sunrpc/tst-udp-timeout.c @@ -0,0 +1,402 @@ +/* Test timeout handling in the UDP client. + Copyright (C) 2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <netinet/in.h> +#include <rpc/clnt.h> +#include <rpc/svc.h> +#include <stdbool.h> +#include <string.h> +#include <support/check.h> +#include <support/namespace.h> +#include <support/test-driver.h> +#include <support/xsocket.h> +#include <support/xunistd.h> +#include <sys/socket.h> +#include <time.h> +#include <unistd.h> + +/* Test data serialization and deserialization. */ + +struct test_query +{ + uint32_t a; + uint32_t b; + uint32_t timeout_ms; + uint32_t wait_for_seq; + uint32_t garbage_packets; +}; + +static bool_t +xdr_test_query (XDR *xdrs, void *data, ...) +{ + struct test_query *p = data; + return xdr_uint32_t (xdrs, &p->a) + && xdr_uint32_t (xdrs, &p->b) + && xdr_uint32_t (xdrs, &p->timeout_ms) + && xdr_uint32_t (xdrs, &p->wait_for_seq) + && xdr_uint32_t (xdrs, &p->garbage_packets); +} + +struct test_response +{ + uint32_t seq; + uint32_t sum; +}; + +static bool_t +xdr_test_response (XDR *xdrs, void *data, ...) +{ + struct test_response *p = data; + return xdr_uint32_t (xdrs, &p->seq) + && xdr_uint32_t (xdrs, &p->sum); +} + +/* Implementation of the test server. */ + +enum + { + /* RPC parameters, chosen at random. */ + PROGNUM = 15717, + VERSNUM = 13689, + + /* Main RPC operation. */ + PROC_ADD = 1, + + /* Reset the sequence number. */ + PROC_RESET_SEQ, + + /* Request process termination. */ + PROC_EXIT, + + /* Special exit status to mark successful processing. */ + EXIT_MARKER = 55, + }; + +static void +server_dispatch (struct svc_req *request, SVCXPRT *transport) +{ + /* Query sequence number. */ + static uint32_t seq = 0; + ++seq; + + if (test_verbose) + printf ("info: server_dispatch seq=%u rq_proc=%lu\n", + seq, request->rq_proc); + + switch (request->rq_proc) + { + case PROC_ADD: + { + struct test_query query; + memset (&query, 0xc0, sizeof (query)); + TEST_VERIFY_EXIT + (svc_getargs (transport, xdr_test_query, + (void *) &query)); + + if (test_verbose) + printf (" a=%u b=%u timeout_ms=%u wait_for_seq=%u" + " garbage_packets=%u\n", + query.a, query.b, query.timeout_ms, query.wait_for_seq, + query.garbage_packets); + + if (seq < query.wait_for_seq) + { + /* No response at this point. */ + if (test_verbose) + printf (" skipped response\n"); + break; + } + + if (query.garbage_packets > 0) + { + int per_packet_timeout; + if (query.timeout_ms > 0) + per_packet_timeout + = query.timeout_ms * 1000 / query.garbage_packets; + else + per_packet_timeout = 0; + + char buf[20]; + memset (&buf, 0xc0, sizeof (buf)); + for (int i = 0; i < query.garbage_packets; ++i) + { + /* 13 is relatively prime to 20 = sizeof (buf) + 1, so + the len variable will cover the entire interval + [0, 20] if query.garbage_packets is sufficiently + large. */ + size_t len = (i * 13 + 1) % (sizeof (buf) + 1); + TEST_VERIFY (sendto (transport->xp_sock, + buf, len, MSG_NOSIGNAL, + (struct sockaddr *) &transport->xp_raddr, + transport->xp_addrlen) == len); + if (per_packet_timeout > 0) + usleep (per_packet_timeout); + } + } + else if (query.timeout_ms > 0) + usleep (query.timeout_ms * 1000); + + struct test_response response = + { + .seq = seq, + .sum = query.a + query.b, + }; + TEST_VERIFY (svc_sendreply (transport, xdr_test_response, + (void *) &response)); + } + break; + + case PROC_RESET_SEQ: + seq = 0; + TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL)); + break; + + case PROC_EXIT: + TEST_VERIFY (svc_sendreply (transport, (xdrproc_t) xdr_void, NULL)); + _exit (EXIT_MARKER); + break; + + default: + FAIL_EXIT1 ("invalid rq_proc value: %lu", request->rq_proc); + break; + } +} + +/* Implementation of the test client. */ + +static struct test_response +test_call (CLIENT *clnt, int proc, struct test_query query, + struct timeval timeout) +{ + if (test_verbose) + printf ("info: test_call proc=%d timeout=%lu.%06lu\n", + proc, (unsigned long) timeout.tv_sec, + (unsigned long) timeout.tv_usec); + struct test_response response; + TEST_VERIFY_EXIT (clnt_call (clnt, proc, + xdr_test_query, (void *) &query, + xdr_test_response, (void *) &response, + timeout) + == RPC_SUCCESS); + return response; +} + +static void +test_call_timeout (CLIENT *clnt, int proc, struct test_query query, + struct timeval timeout) +{ + struct test_response response; + TEST_VERIFY (clnt_call (clnt, proc, + xdr_test_query, (void *) &query, + xdr_test_response, (void *) &response, + timeout) + == RPC_TIMEDOUT); +} + +/* Complete one regular RPC call to drain the server socket + buffer. Resets the sequence number. */ +static void +test_call_flush (CLIENT *clnt) +{ + /* This needs a longer timeout to flush out all pending requests. + The choice of 5 seconds is larger than the per-response timeouts + requested via the timeout_ms field. */ + if (test_verbose) + printf ("info: flushing pending queries\n"); + TEST_VERIFY_EXIT (clnt_call (clnt, PROC_RESET_SEQ, + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, + ((struct timeval) { 5, 0 })) + == RPC_SUCCESS); +} + +/* Return the number seconds since an arbitrary point in time. */ +static double +get_ticks (void) +{ + { + struct timespec ts; + if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0) + return ts.tv_sec + ts.tv_nsec * 1e-9; + } + { + struct timeval tv; + TEST_VERIFY_EXIT (gettimeofday (&tv, NULL) == 0); + return tv.tv_sec + tv.tv_usec * 1e-6; + } +} + +static void +test_udp_server (int port) +{ + struct sockaddr_in sin = + { + .sin_family = AF_INET, + .sin_addr.s_addr = htonl (INADDR_LOOPBACK), + .sin_port = htons (port) + }; + int sock = RPC_ANYSOCK; + + /* The client uses a 1.5 second timeout for retries. The timeouts + are arbitrary, but chosen so that there is a substantial gap + between them, but the total time spent waiting is not too + large. */ + CLIENT *clnt = clntudp_create (&sin, PROGNUM, VERSNUM, + (struct timeval) { 1, 500 * 1000 }, + &sock); + TEST_VERIFY_EXIT (clnt != NULL); + + /* Basic call/response test. */ + struct test_response response = test_call + (clnt, PROC_ADD, + (struct test_query) { .a = 17, .b = 4 }, + (struct timeval) { 3, 0 }); + TEST_VERIFY (response.sum == 21); + TEST_VERIFY (response.seq == 1); + + /* Check that garbage packets do not interfere with timeout + processing. */ + double before = get_ticks (); + response = test_call + (clnt, PROC_ADD, + (struct test_query) { + .a = 19, .b = 4, .timeout_ms = 500, .garbage_packets = 21, + }, + (struct timeval) { 3, 0 }); + TEST_VERIFY (response.sum == 23); + TEST_VERIFY (response.seq == 2); + double after = get_ticks (); + if (test_verbose) + printf ("info: 21 garbage packets took %f seconds\n", after - before); + /* Expected timeout is 0.5 seconds. Add some slack in case process + scheduling delays processing the query or response, but do not + accept a retry (which would happen at 1.5 seconds). */ + TEST_VERIFY (0.5 <= after - before); + TEST_VERIFY (after - before < 1.2); + test_call_flush (clnt); + + /* Check that missing a response introduces a 1.5 second timeout, as + requested when calling clntudp_create. */ + before = get_ticks (); + response = test_call + (clnt, PROC_ADD, + (struct test_query) { .a = 170, .b = 40, .wait_for_seq = 2 }, + (struct timeval) { 3, 0 }); + TEST_VERIFY (response.sum == 210); + TEST_VERIFY (response.seq == 2); + after = get_ticks (); + if (test_verbose) + printf ("info: skipping one response took %f seconds\n", + after - before); + /* Expected timeout is 1.5 seconds. Do not accept a second retry + (which would happen at 3 seconds). */ + TEST_VERIFY (1.5 <= after - before); + TEST_VERIFY (after - before < 2.9); + test_call_flush (clnt); + + /* Check that the overall timeout wins against the per-query + timeout. */ + before = get_ticks (); + test_call_timeout + (clnt, PROC_ADD, + (struct test_query) { .a = 170, .b = 41, .wait_for_seq = 2 }, + (struct timeval) { 0, 750 * 1000 }); + after = get_ticks (); + if (test_verbose) + printf ("info: 0.75 second timeout took %f seconds\n", + after - before); + TEST_VERIFY (0.75 <= after - before); + TEST_VERIFY (after - before < 1.4); + test_call_flush (clnt); + + for (int with_garbage = 0; with_garbage < 2; ++with_garbage) + { + /* Check that no response at all causes the client to bail out. */ + before = get_ticks (); + test_call_timeout + (clnt, PROC_ADD, + (struct test_query) { + .a = 170, .b = 40, .timeout_ms = 1200, + .garbage_packets = with_garbage * 21 + }, + (struct timeval) { 0, 750 * 1000 }); + after = get_ticks (); + if (test_verbose) + printf ("info: test_udp_server: 0.75 second timeout took %f seconds" + " (garbage %d)\n", + after - before, with_garbage); + TEST_VERIFY (0.75 <= after - before); + TEST_VERIFY (after - before < 1.4); + test_call_flush (clnt); + + /* As above, but check the total timeout. */ + before = get_ticks (); + test_call_timeout + (clnt, PROC_ADD, + (struct test_query) { + .a = 170, .b = 40, .timeout_ms = 3000, + .garbage_packets = with_garbage * 30 + }, + (struct timeval) { 2, 300 * 1000 }); + after = get_ticks (); + if (test_verbose) + printf ("info: test_udp_server: 2.3 second timeout took %f seconds" + " (garbage %d)\n", + after - before, with_garbage); + TEST_VERIFY (2.3 <= after - before); + TEST_VERIFY (after - before < 3.0); + test_call_flush (clnt); + } + + TEST_VERIFY_EXIT (clnt_call (clnt, PROC_EXIT, + (xdrproc_t) xdr_void, NULL, + (xdrproc_t) xdr_void, NULL, + ((struct timeval) { 5, 0 })) + == RPC_SUCCESS); + clnt_destroy (clnt); +} + +static int +do_test (void) +{ + support_become_root (); + support_enter_network_namespace (); + + SVCXPRT *transport = svcudp_create (RPC_ANYSOCK); + TEST_VERIFY_EXIT (transport != NULL); + TEST_VERIFY (svc_register (transport, PROGNUM, VERSNUM, server_dispatch, 0)); + + pid_t pid = xfork (); + if (pid == 0) + { + svc_run (); + FAIL_EXIT1 ("supposed to be unreachable"); + } + test_udp_server (transport->xp_port); + + int status; + xwaitpid (pid, &status, 0); + TEST_VERIFY (WIFEXITED (status) && WEXITSTATUS (status) == EXIT_MARKER); + + SVC_DESTROY (transport); + return 0; +} + +/* The minimum run time is around 17 seconds. */ +#define TIMEOUT 25 +#include <support/test-driver.c> diff --git a/REORG.TODO/sunrpc/tst-xdrmem.c b/REORG.TODO/sunrpc/tst-xdrmem.c new file mode 100644 index 0000000000..c5c9f1fd27 --- /dev/null +++ b/REORG.TODO/sunrpc/tst-xdrmem.c @@ -0,0 +1,204 @@ +/* Copyright (C) 2005-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2005. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <rpc/rpc.h> + +static int +do_test (void) +{ + XDR xdrs; + unsigned char buf[8192]; + int v_int; + u_int v_u_int; + long v_long; + u_long v_u_long; + quad_t v_hyper; + u_quad_t v_u_hyper; + quad_t v_longlong_t; + u_quad_t v_u_longlong_t; + short v_short; + u_short v_u_short; + char v_char; + u_char v_u_char; + bool_t v_bool; + enum_t v_enum; + char *v_wrapstring; + + xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_ENCODE); + +#define TESTS \ + T(int, 0) \ + T(int, CHAR_MAX) \ + T(int, CHAR_MIN) \ + T(int, SHRT_MAX) \ + T(int, SHRT_MIN) \ + T(int, INT_MAX) \ + T(int, INT_MIN) \ + T(int, 0x123) \ + T(u_int, 0) \ + T(u_int, UCHAR_MAX) \ + T(u_int, USHRT_MAX) \ + T(u_int, UINT_MAX) \ + T(u_int, 0xdeadbeef) \ + T(u_int, 0x12345678) \ + T(long, 0) \ + T(long, 2147483647L) \ + T(long, -2147483648L) \ + T(long, -305419896L) \ + T(long, -305419896L) \ + T(u_long, 0) \ + T(u_long, 0xffffffffUL) \ + T(u_long, 0xdeadbeefUL) \ + T(u_long, 0x12345678UL) \ + T(hyper, 0) \ + T(hyper, CHAR_MAX) \ + T(hyper, CHAR_MIN) \ + T(hyper, SHRT_MAX) \ + T(hyper, SHRT_MIN) \ + T(hyper, INT_MAX) \ + T(hyper, INT_MIN) \ + T(hyper, LONG_MAX) \ + T(hyper, LONG_MIN) \ + T(hyper, LONG_LONG_MAX) \ + T(hyper, LONG_LONG_MIN) \ + T(hyper, 0x12312345678LL) \ + T(hyper, 0x12387654321LL) \ + T(u_hyper, 0) \ + T(u_hyper, UCHAR_MAX) \ + T(u_hyper, USHRT_MAX) \ + T(u_hyper, UINT_MAX) \ + T(u_hyper, ULONG_MAX) \ + T(u_hyper, ULONG_LONG_MAX) \ + T(u_hyper, 0xdeadbeefdeadbeefULL) \ + T(u_hyper, 0x12312345678ULL) \ + T(u_hyper, 0x12387654321ULL) \ + T(longlong_t, 0) \ + T(longlong_t, CHAR_MAX) \ + T(longlong_t, CHAR_MIN) \ + T(longlong_t, SHRT_MAX) \ + T(longlong_t, SHRT_MIN) \ + T(longlong_t, INT_MAX) \ + T(longlong_t, INT_MIN) \ + T(longlong_t, LONG_MAX) \ + T(longlong_t, LONG_MIN) \ + T(longlong_t, LONG_LONG_MAX) \ + T(longlong_t, LONG_LONG_MIN) \ + T(longlong_t, 0x12312345678LL) \ + T(longlong_t, 0x12387654321LL) \ + T(u_longlong_t, 0) \ + T(u_longlong_t, UCHAR_MAX) \ + T(u_longlong_t, USHRT_MAX) \ + T(u_longlong_t, UINT_MAX) \ + T(u_longlong_t, ULONG_MAX) \ + T(u_longlong_t, ULONG_LONG_MAX) \ + T(u_longlong_t, 0xdeadbeefdeadbeefULL)\ + T(u_longlong_t, 0x12312345678ULL) \ + T(u_longlong_t, 0x12387654321ULL) \ + T(short, CHAR_MAX) \ + T(short, CHAR_MIN) \ + T(short, SHRT_MAX) \ + T(short, SHRT_MIN) \ + T(short, 0x123) \ + T(u_short, 0) \ + T(u_short, UCHAR_MAX) \ + T(u_short, USHRT_MAX) \ + T(u_short, 0xbeef) \ + T(u_short, 0x5678) \ + T(char, CHAR_MAX) \ + T(char, CHAR_MIN) \ + T(char, 0x23) \ + T(u_char, 0) \ + T(u_char, UCHAR_MAX) \ + T(u_char, 0xef) \ + T(u_char, 0x78) \ + T(bool, 0) \ + T(bool, 1) \ + T(enum, 0) \ + T(enum, CHAR_MAX) \ + T(enum, CHAR_MIN) \ + T(enum, SHRT_MAX) \ + T(enum, SHRT_MIN) \ + T(enum, INT_MAX) \ + T(enum, INT_MIN) \ + T(enum, 0x123) \ + S(wrapstring, (char *) "") \ + S(wrapstring, (char *) "hello, world") + +#define T(type, val) \ + v_##type = val; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("encoding of " #type \ + " " #val " failed"); \ + return 1; \ + } +#define S(type, val) T(type, val) + + TESTS +#undef T +#undef S + + xdr_destroy (&xdrs); + + xdrmem_create (&xdrs, (char *) buf, sizeof (buf), XDR_DECODE); + +#define T(type, val) \ + v_##type = 0x15; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (v_##type != val) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } +#define S(type, val) \ + v_##type = NULL; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (strcmp (v_##type, val)) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } \ + free (v_##type); \ + v_##type = NULL; + + TESTS +#undef T +#undef S + + xdr_destroy (&xdrs); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/sunrpc/tst-xdrmem2.c b/REORG.TODO/sunrpc/tst-xdrmem2.c new file mode 100644 index 0000000000..fa28ad04f4 --- /dev/null +++ b/REORG.TODO/sunrpc/tst-xdrmem2.c @@ -0,0 +1,114 @@ +/* Copyright (C) 2006-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Jakub Jelinek <jakub@redhat.com>, 2006. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <limits.h> +#include <stdio.h> +#include <string.h> +#include <rpc/rpc.h> +#include <sys/mman.h> +#include <unistd.h> +#include <stdint.h> + +static int +do_test (void) +{ + XDR xdrs; + void *buf; + size_t ps = sysconf (_SC_PAGESIZE); + uintptr_t half = -1; + int v_int; + u_short v_u_short; + + half = (half >> 1) & ~(uintptr_t) (ps - 1); + buf = mmap ((void *) half, 2 * ps, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, -1, 0); + if (buf == MAP_FAILED || buf != (void *) half) + { + puts ("Couldn't mmap 2 pages in the middle of address space"); + return 0; + } + + xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_ENCODE); + +#define T(type, val) \ + v_##type = val; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("encoding of " #type \ + " " #val " failed"); \ + return 1; \ + } + + T(int, 127) + + u_int pos = xdr_getpos (&xdrs); + + T(u_short, 31) + + if (! xdr_setpos (&xdrs, pos)) + { + puts ("xdr_setpos during encoding failed"); + return 1; + } + + T(u_short, 36) + +#undef T + + xdr_destroy (&xdrs); + + xdrmem_create (&xdrs, (char *) buf, 2 * ps, XDR_DECODE); + +#define T(type, val) \ + v_##type = 0x15; \ + if (! xdr_##type (&xdrs, &v_##type)) \ + { \ + puts ("decoding of " #type \ + " " #val " failed"); \ + return 1; \ + } \ + if (v_##type != val) \ + { \ + puts ("decoded value differs, " \ + "type " #type " " #val); \ + return 1; \ + } + + T(int, 127) + + pos = xdr_getpos (&xdrs); + + T(u_short, 36) + + if (! xdr_setpos (&xdrs, pos)) + { + puts ("xdr_setpos during encoding failed"); + return 1; + } + + T(u_short, 36) + +#undef T + + xdr_destroy (&xdrs); + + return 0; +} + +#define TEST_FUNCTION do_test () +#include "../test-skeleton.c" diff --git a/REORG.TODO/sunrpc/xcrypt.c b/REORG.TODO/sunrpc/xcrypt.c new file mode 100644 index 0000000000..da7c4e66b9 --- /dev/null +++ b/REORG.TODO/sunrpc/xcrypt.c @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#if 0 +#ident "@(#)xcrypt.c 1.11 94/08/23 SMI" +#endif + +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)xcrypt.c 1.3 89/03/24 Copyr 1986 Sun Micro"; +#endif + +/* + * xcrypt.c: Hex encryption/decryption and utility routines + */ + +#include <ctype.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include <rpc/des_crypt.h> +#include <shlib-compat.h> + +static const char hex[16] = +{ + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', +}; + + +#ifdef _LIBC +# define hexval(c) \ + (c >= '0' && c <= '9' \ + ? c - '0' \ + : ({ int upp = toupper (c); \ + upp >= 'A' && upp <= 'Z' ? upp - 'A' + 10 : -1; })) +#else +static char hexval (char) internal_function; +#endif + +static void hex2bin (int, char *, char *) internal_function; +static void bin2hex (int, unsigned char *, char *) internal_function; +void passwd2des_internal (char *pw, char *key); +#ifdef _LIBC +libc_hidden_proto (passwd2des_internal) +#endif + +/* + * Turn password into DES key + */ +void +passwd2des_internal (char *pw, char *key) +{ + int i; + + memset (key, 0, 8); + for (i = 0; *pw && i < 8; ++i) + key[i] ^= *pw++ << 1; + + des_setparity (key); +} + +#ifdef _LIBC +libc_hidden_def (passwd2des_internal) +libc_sunrpc_symbol(passwd2des_internal, passwd2des, GLIBC_2_1) +#else +void passwd2des (char *pw, char *key) +{ + return passwd2des_internal (pw, key); +} +#endif + +/* + * Encrypt a secret key given passwd + * The secret key is passed and returned in hex notation. + * Its length must be a multiple of 16 hex digits (64 bits). + */ +int +xencrypt (char *secret, char *passwd) +{ + char key[8]; + char ivec[8]; + char *buf; + int err; + int len; + + len = strlen (secret) / 2; + buf = malloc ((unsigned) len); + hex2bin (len, secret, buf); + passwd2des_internal (passwd, key); + memset (ivec, 0, 8); + + err = cbc_crypt (key, buf, len, DES_ENCRYPT | DES_HW, ivec); + if (DES_FAILED (err)) + { + free (buf); + return 0; + } + bin2hex (len, (unsigned char *) buf, secret); + free (buf); + return 1; +} +libc_hidden_nolink_sunrpc (xencrypt, GLIBC_2_0) + +/* + * Decrypt secret key using passwd + * The secret key is passed and returned in hex notation. + * Once again, the length is a multiple of 16 hex digits + */ +int +xdecrypt (char *secret, char *passwd) +{ + char key[8]; + char ivec[8]; + char *buf; + int err; + int len; + + len = strlen (secret) / 2; + buf = malloc ((unsigned) len); + + hex2bin (len, secret, buf); + passwd2des_internal (passwd, key); + memset (ivec, 0, 8); + + err = cbc_crypt (key, buf, len, DES_DECRYPT | DES_HW, ivec); + if (DES_FAILED (err)) + { + free (buf); + return 0; + } + bin2hex (len, (unsigned char *) buf, secret); + free (buf); + return 1; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdecrypt) +#else +libc_hidden_nolink_sunrpc (xdecrypt, GLIBC_2_1) +#endif + +/* + * Hex to binary conversion + */ +static void +internal_function +hex2bin (int len, char *hexnum, char *binnum) +{ + int i; + + for (i = 0; i < len; i++) + *binnum++ = 16 * hexval (hexnum[2 * i]) + hexval (hexnum[2 * i + 1]); +} + +/* + * Binary to hex conversion + */ +static void +internal_function +bin2hex (int len, unsigned char *binnum, char *hexnum) +{ + int i; + unsigned val; + + for (i = 0; i < len; i++) + { + val = binnum[i]; + hexnum[i * 2] = hex[val >> 4]; + hexnum[i * 2 + 1] = hex[val & 0xf]; + } + hexnum[len * 2] = 0; +} + +#ifndef _LIBC +static char +hexval (char c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'z') + return (c - 'a' + 10); + else if (c >= 'A' && c <= 'Z') + return (c - 'A' + 10); + else + return -1; +} +#endif diff --git a/REORG.TODO/sunrpc/xdr.c b/REORG.TODO/sunrpc/xdr.c new file mode 100644 index 0000000000..8b0b91995b --- /dev/null +++ b/REORG.TODO/sunrpc/xdr.c @@ -0,0 +1,827 @@ +/* + * xdr.c, Generic XDR routines implementation. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <limits.h> +#include <string.h> +#include <libintl.h> +#include <wchar.h> +#include <stdint.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <shlib-compat.h> + + +/* + * constants specific to the xdr "protocol" + */ +#define XDR_FALSE ((long) 0) +#define XDR_TRUE ((long) 1) +#define LASTUNSIGNED ((u_int) 0-1) + +/* + * for unit alignment + */ +static const 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 (xdrproc_t proc, char *objp) +{ + XDR x; + + x.x_op = XDR_FREE; + (*proc) (&x, objp); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_free) +#else +libc_hidden_nolink_sunrpc (xdr_free, GLIBC_2_0) +#endif + +/* + * XDR nothing + */ +bool_t +xdr_void (void) +{ + return TRUE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_void) +#else +libc_hidden_nolink_sunrpc (xdr_void, GLIBC_2_0) +#endif + +/* + * XDR integers + */ +bool_t +xdr_int (XDR *xdrs, int *ip) +{ + +#if INT_MAX < LONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (long) *ip; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *ip = (int) l; + case XDR_FREE: + return TRUE; + } + return FALSE; +#elif INT_MAX == LONG_MAX + return xdr_long (xdrs, (long *) ip); +#elif INT_MAX == SHRT_MAX + return xdr_short (xdrs, (short *) ip); +#else +#error unexpected integer sizes in_xdr_int() +#endif +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_int) +#else +libc_hidden_nolink_sunrpc (xdr_int, GLIBC_2_0) +#endif + +/* + * XDR unsigned integers + */ +bool_t +xdr_u_int (XDR *xdrs, u_int *up) +{ +#if UINT_MAX < ULONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (u_long) * up; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *up = (u_int) (u_long) l; + case XDR_FREE: + return TRUE; + } + return FALSE; +#elif UINT_MAX == ULONG_MAX + return xdr_u_long (xdrs, (u_long *) up); +#elif UINT_MAX == USHRT_MAX + return xdr_short (xdrs, (short *) up); +#else +#error unexpected integer sizes in_xdr_u_int() +#endif +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_u_int) +#else +libc_hidden_nolink_sunrpc (xdr_u_int, GLIBC_2_0) +#endif + +/* + * XDR long integers + * The definition of xdr_long() is kept for backward + * compatibility. Instead xdr_int() should be used. + */ +bool_t +xdr_long (XDR *xdrs, long *lp) +{ + + if (xdrs->x_op == XDR_ENCODE + && (sizeof (int32_t) == sizeof (long) + || (int32_t) *lp == *lp)) + 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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_long) +#else +libc_hidden_nolink_sunrpc (xdr_long, GLIBC_2_0) +#endif + +/* + * XDR unsigned long integers + * The definition of xdr_u_long() is kept for backward + * compatibility. Instead xdr_u_int() should be used. + */ +bool_t +xdr_u_long (XDR *xdrs, u_long *ulp) +{ + switch (xdrs->x_op) + { + case XDR_DECODE: + { + long int tmp; + + if (XDR_GETLONG (xdrs, &tmp) == FALSE) + return FALSE; + + *ulp = (uint32_t) tmp; + return TRUE; + } + + case XDR_ENCODE: + if (sizeof (uint32_t) != sizeof (u_long) + && (uint32_t) *ulp != *ulp) + return FALSE; + + return XDR_PUTLONG (xdrs, (long *) ulp); + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_u_long) +#else +libc_hidden_nolink_sunrpc (xdr_u_long, GLIBC_2_0) +#endif + +/* + * XDR hyper integers + * same as xdr_u_hyper - open coded to save a proc call! + */ +bool_t +xdr_hyper (XDR *xdrs, quad_t *llp) +{ + long int t1, t2; + + if (xdrs->x_op == XDR_ENCODE) + { + t1 = (long) ((*llp) >> 32); + t2 = (long) (*llp); + return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); + } + + if (xdrs->x_op == XDR_DECODE) + { + if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) + return FALSE; + *llp = ((quad_t) t1) << 32; + *llp |= (uint32_t) t2; + return TRUE; + } + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_hyper) +#else +libc_hidden_nolink_sunrpc (xdr_hyper, GLIBC_2_1_1) +#endif + +/* + * XDR hyper integers + * same as xdr_hyper - open coded to save a proc call! + */ +bool_t +xdr_u_hyper (XDR *xdrs, u_quad_t *ullp) +{ + long int t1, t2; + + if (xdrs->x_op == XDR_ENCODE) + { + t1 = (unsigned long) ((*ullp) >> 32); + t2 = (unsigned long) (*ullp); + return (XDR_PUTLONG(xdrs, &t1) && XDR_PUTLONG(xdrs, &t2)); + } + + if (xdrs->x_op == XDR_DECODE) + { + if (!XDR_GETLONG(xdrs, &t1) || !XDR_GETLONG(xdrs, &t2)) + return FALSE; + *ullp = ((u_quad_t) t1) << 32; + *ullp |= (uint32_t) t2; + return TRUE; + } + + if (xdrs->x_op == XDR_FREE) + return TRUE; + + return FALSE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_u_hyper) +#else +libc_hidden_nolink_sunrpc (xdr_u_hyper, GLIBC_2_1_1) +#endif + +bool_t +xdr_longlong_t (XDR *xdrs, quad_t *llp) +{ + return xdr_hyper (xdrs, llp); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_longlong_t) +#else +libc_hidden_nolink_sunrpc (xdr_longlong_t, GLIBC_2_1_1) +#endif + +bool_t +xdr_u_longlong_t (XDR *xdrs, u_quad_t *ullp) +{ + return xdr_u_hyper (xdrs, ullp); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_u_longlong_t) +#else +libc_hidden_nolink_sunrpc (xdr_u_longlong_t, GLIBC_2_1_1) +#endif + +/* + * XDR short integers + */ +bool_t +xdr_short (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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_short) +#else +libc_hidden_nolink_sunrpc (xdr_short, GLIBC_2_0) +#endif + +/* + * XDR unsigned short integers + */ +bool_t +xdr_u_short (XDR *xdrs, u_short *usp) +{ + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = (u_long) * usp; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *usp = (u_short) (u_long) l; + return TRUE; + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_u_short) +#else +libc_hidden_nolink_sunrpc (xdr_u_short, GLIBC_2_0) +#endif + + +/* + * XDR a char + */ +bool_t +xdr_char (XDR *xdrs, char *cp) +{ + int i; + + i = (*cp); + if (!xdr_int (xdrs, &i)) + { + return FALSE; + } + *cp = i; + return TRUE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_char) +#else +libc_hidden_nolink_sunrpc (xdr_char, GLIBC_2_0) +#endif + +/* + * XDR an unsigned char + */ +bool_t +xdr_u_char (XDR *xdrs, u_char *cp) +{ + u_int u; + + u = (*cp); + if (!xdr_u_int (xdrs, &u)) + { + return FALSE; + } + *cp = u; + return TRUE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_u_char) +#else +libc_hidden_nolink_sunrpc (xdr_u_char, GLIBC_2_0) +#endif + +/* + * XDR booleans + */ +bool_t +xdr_bool (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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_bool) +#else +libc_hidden_nolink_sunrpc (xdr_bool, GLIBC_2_0) +#endif + +/* + * XDR enumerations + */ +bool_t +xdr_enum (XDR *xdrs, enum_t *ep) +{ + enum sizecheck + { + SIZEVAL + }; /* used to find the size of an enum */ + + /* + * enums are treated as ints + */ + if (sizeof (enum sizecheck) == 4) + { +#if INT_MAX < LONG_MAX + long l; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + l = *ep; + return XDR_PUTLONG (xdrs, &l); + + case XDR_DECODE: + if (!XDR_GETLONG (xdrs, &l)) + { + return FALSE; + } + *ep = l; + case XDR_FREE: + return TRUE; + + } + return FALSE; +#else + return xdr_long (xdrs, (long *) ep); +#endif + } + else if (sizeof (enum sizecheck) == sizeof (short)) + { + return xdr_short (xdrs, (short *) ep); + } + else + { + return FALSE; + } +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_enum) +#else +libc_hidden_nolink_sunrpc (xdr_enum, GLIBC_2_0) +#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 (XDR *xdrs, caddr_t cp, u_int cnt) +{ + u_int rndup; + static char 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; + + switch (xdrs->x_op) + { + case XDR_DECODE: + if (!XDR_GETBYTES (xdrs, cp, cnt)) + { + return FALSE; + } + if (rndup == 0) + return TRUE; + return XDR_GETBYTES (xdrs, (caddr_t)crud, rndup); + + case XDR_ENCODE: + if (!XDR_PUTBYTES (xdrs, cp, cnt)) + { + return FALSE; + } + if (rndup == 0) + return TRUE; + return XDR_PUTBYTES (xdrs, xdr_zero, rndup); + + case XDR_FREE: + return TRUE; + } + return FALSE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_opaque) +#else +libc_hidden_nolink_sunrpc (xdr_opaque, GLIBC_2_0) +#endif + +/* + * 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 (XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + u_int nodesize; + + /* + * first deal with the length since xdr bytes are counted + */ + if (!xdr_u_int (xdrs, sizep)) + { + return FALSE; + } + nodesize = *sizep; + if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) + { + return FALSE; + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) + { + case XDR_DECODE: + if (nodesize == 0) + { + return TRUE; + } + if (sp == NULL) + { + *cpp = sp = (char *) mem_alloc (nodesize); + } + if (sp == NULL) + { + (void) __fxprintf (NULL, "%s: %s", __func__, _("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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_bytes) +#else +libc_hidden_nolink_sunrpc (xdr_bytes, GLIBC_2_0) +#endif + +/* + * Implemented here due to commonality of the object. + */ +bool_t +xdr_netobj (XDR *xdrs, struct netobj *np) +{ + + return xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_netobj) +#else +libc_hidden_nolink_sunrpc (xdr_netobj, GLIBC_2_0) +#endif + +/* + * XDR a discriminated 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 (XDR *xdrs, + /* enum to decide which arm to work on */ + enum_t *dscmp, + /* the union itself */ + char *unp, + /* [value, xdr proc] for each arm */ + const struct xdr_discrim *choices, + /* default xdr routine */ + xdrproc_t dfault) +{ + 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)); +} +libc_hidden_nolink_sunrpc (xdr_union, GLIBC_2_0) + + +/* + * 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 (XDR *xdrs, char **cpp, u_int maxsize) +{ + char *sp = *cpp; /* sp is the actual string pointer */ + /* Initialize to silence the compiler. It is not really needed because SIZE + never actually gets used without being initialized. */ + u_int size = 0; + u_int nodesize; + + /* + * first deal with the length since xdr strings are counted-strings + */ + switch (xdrs->x_op) + { + case XDR_FREE: + if (sp == NULL) + { + return TRUE; /* already free */ + } + /* fall through... */ + case XDR_ENCODE: + if (sp == NULL) + return FALSE; + size = strlen (sp); + break; + case XDR_DECODE: + break; + } + if (!xdr_u_int (xdrs, &size)) + { + return FALSE; + } + if (size > maxsize) + { + return FALSE; + } + nodesize = size + 1; + if (nodesize == 0) + { + /* This means an overflow. It a bug in the caller which + provided a too large maxsize but nevertheless catch it + here. */ + return FALSE; + } + + /* + * now deal with the actual bytes + */ + switch (xdrs->x_op) + { + case XDR_DECODE: + if (sp == NULL) + *cpp = sp = (char *) mem_alloc (nodesize); + if (sp == NULL) + { + (void) __fxprintf (NULL, "%s: %s", __func__, _("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; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_string) +#else +libc_hidden_nolink_sunrpc (xdr_string, GLIBC_2_0) +#endif + +/* + * Wrapper for xdr_string that can be called directly from + * routines like clnt_call + */ +bool_t +xdr_wrapstring (XDR *xdrs, char **cpp) +{ + if (xdr_string (xdrs, cpp, LASTUNSIGNED)) + { + return TRUE; + } + return FALSE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_wrapstring) +#else +libc_hidden_nolink_sunrpc (xdr_wrapstring, GLIBC_2_0) +#endif diff --git a/REORG.TODO/sunrpc/xdr_array.c b/REORG.TODO/sunrpc/xdr_array.c new file mode 100644 index 0000000000..18383d437e --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_array.c @@ -0,0 +1,166 @@ +/* + * xdr_array.c, Generic XDR routines implementation. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <string.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <libintl.h> +#include <limits.h> +#include <wchar.h> +#include <shlib-compat.h> + +#define LASTUNSIGNED ((u_int)0-1) + + +/* + * XDR an array of arbitrary elements + * *addrp is a pointer to the array, *sizep is the number of elements. + * If addrp is NULL (*sizep * elsize) bytes are allocated. + * elsize is the size (in bytes) of each element, and elproc is the + * xdr procedure to call to handle each element of the array. + */ +bool_t +xdr_array (XDR *xdrs, + /* array pointer */ + caddr_t *addrp, + /* number of elements */ + u_int *sizep, + /* max numberof elements */ + u_int maxsize, + /* size in bytes of each element */ + u_int elsize, + /* xdr routine to handle each element */ + xdrproc_t elproc) +{ + u_int i; + caddr_t target = *addrp; + u_int c; /* the actual element count */ + bool_t stat = TRUE; + + /* like strings, arrays are really counted arrays */ + if (!xdr_u_int (xdrs, sizep)) + { + return FALSE; + } + c = *sizep; + /* + * XXX: Let the overflow possibly happen with XDR_FREE because mem_free() + * doesn't actually use its second argument anyway. + */ + if ((c > maxsize || c > UINT_MAX / elsize) && (xdrs->x_op != XDR_FREE)) + { + return FALSE; + } + + /* + * 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 = calloc (c, elsize); + if (target == NULL) + { + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + return FALSE; + } + break; + + case XDR_FREE: + return TRUE; + default: + break; + } + + /* + * 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, c * elsize); + *addrp = NULL; + } + return stat; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_array) +#else +libc_hidden_nolink_sunrpc (xdr_array, GLIBC_2_0) +#endif + +/* + * 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 (XDR *xdrs, char *basep, u_int nelem, u_int elemsize, + xdrproc_t xdr_elem) +{ + u_int i; + char *elptr; + + elptr = basep; + for (i = 0; i < nelem; i++) + { + if (!(*xdr_elem) (xdrs, elptr, LASTUNSIGNED)) + { + return FALSE; + } + elptr += elemsize; + } + return TRUE; +} +libc_hidden_nolink_sunrpc (xdr_vector, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/xdr_float.c b/REORG.TODO/sunrpc/xdr_float.c new file mode 100644 index 0000000000..844a96e56e --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_float.c @@ -0,0 +1,300 @@ +/* + * xdr_float.c, Generic XDR routines implementation. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <endian.h> + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <shlib-compat.h> + +/* + * NB: Not portable. + * This routine works on Suns (Sky / 68000's) and Vaxen. + */ + +#define LSW (__FLOAT_WORD_ORDER == __BIG_ENDIAN) + +#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 (XDR *xdrs, float *fp) +{ +#ifdef vax + struct ieee_single is; + struct vax_single vs, *vsp; + struct sgl_limits *lim; + int i; +#endif + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef vax + vs = *((struct vax_single *)fp); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((vs.mantissa2 == lim->s.mantissa2) && + (vs.exp == lim->s.exp) && + (vs.mantissa1 == lim->s.mantissa1)) { + is = lim->ieee; + goto shipit; + } + } + is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS; + is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2; + shipit: + is.sign = vs.sign; + return (XDR_PUTLONG(xdrs, (long *)&is)); +#else + if (sizeof(float) == sizeof(long)) + return (XDR_PUTLONG(xdrs, (long *)fp)); + else if (sizeof(float) == sizeof(int)) { + long tmp = *(int *)fp; + return (XDR_PUTLONG(xdrs, &tmp)); + } + break; +#endif + + case XDR_DECODE: +#ifdef vax + vsp = (struct vax_single *)fp; + if (!XDR_GETLONG(xdrs, (long *)&is)) + return (FALSE); + for (i = 0, lim = sgl_limits; + i < sizeof(sgl_limits)/sizeof(struct sgl_limits); + i++, lim++) { + if ((is.exp == lim->ieee.exp) && + (is.mantissa == lim->ieee.mantissa)) { + *vsp = lim->s; + goto doneit; + } + } + vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS; + vsp->mantissa2 = is.mantissa; + vsp->mantissa1 = (is.mantissa >> 16); + doneit: + vsp->sign = is.sign; + return (TRUE); +#else + if (sizeof(float) == sizeof(long)) + return (XDR_GETLONG(xdrs, (long *)fp)); + else if (sizeof(float) == sizeof(int)) { + long tmp; + if (XDR_GETLONG(xdrs, &tmp)) { + *(int *)fp = tmp; + return (TRUE); + } + } + break; +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} +libc_hidden_nolink_sunrpc (xdr_float, GLIBC_2_0) + +/* + * 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 (XDR *xdrs, double *dp) +{ +#ifdef vax + struct ieee_double id; + struct vax_double vd; + register struct dbl_limits *lim; + int i; +#endif + + switch (xdrs->x_op) { + + case XDR_ENCODE: +#ifdef vax + 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; + dp = (double *)&id; +#endif + if (2*sizeof(long) == sizeof(double)) { + long *lp = (long *)dp; + return (XDR_PUTLONG(xdrs, lp+!LSW) && + XDR_PUTLONG(xdrs, lp+LSW)); + } else if (2*sizeof(int) == sizeof(double)) { + int *ip = (int *)dp; + long tmp[2]; + tmp[0] = ip[!LSW]; + tmp[1] = ip[LSW]; + return (XDR_PUTLONG(xdrs, tmp) && + XDR_PUTLONG(xdrs, tmp+1)); + } + break; + + case XDR_DECODE: +#ifdef vax + lp = (long *)&id; + if (!XDR_GETLONG(xdrs, lp++) || !XDR_GETLONG(xdrs, lp)) + return (FALSE); + for (i = 0, lim = dbl_limits; + i < sizeof(dbl_limits)/sizeof(struct dbl_limits); + i++, lim++) { + if ((id.mantissa2 == lim->ieee.mantissa2) && + (id.mantissa1 == lim->ieee.mantissa1) && + (id.exp == lim->ieee.exp)) { + vd = lim->d; + goto doneit; + } + } + vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS; + vd.mantissa1 = (id.mantissa1 >> 13); + vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) | + (id.mantissa2 >> 29); + vd.mantissa3 = (id.mantissa2 >> 13); + vd.mantissa4 = (id.mantissa2 << 3); + doneit: + vd.sign = id.sign; + *dp = *((double *)&vd); + return (TRUE); +#else + if (2*sizeof(long) == sizeof(double)) { + long *lp = (long *)dp; + return (XDR_GETLONG(xdrs, lp+!LSW) && + XDR_GETLONG(xdrs, lp+LSW)); + } else if (2*sizeof(int) == sizeof(double)) { + int *ip = (int *)dp; + long tmp[2]; + if (XDR_GETLONG(xdrs, tmp+!LSW) && + XDR_GETLONG(xdrs, tmp+LSW)) { + ip[0] = tmp[0]; + ip[1] = tmp[1]; + return (TRUE); + } + } + break; +#endif + + case XDR_FREE: + return (TRUE); + } + return (FALSE); +} +libc_hidden_nolink_sunrpc (xdr_double, GLIBC_2_0) diff --git a/REORG.TODO/sunrpc/xdr_intXX_t.c b/REORG.TODO/sunrpc/xdr_intXX_t.c new file mode 100644 index 0000000000..4fd9ada687 --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_intXX_t.c @@ -0,0 +1,230 @@ +/* Copyright (c) 1998-2017 Free Software Foundation, Inc. + This file is part of the GNU C Library. + Contributed by Thorsten Kukuk <kukuk@vt.uni-paderborn.de>, 1998. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <http://www.gnu.org/licenses/>. */ + +#include <rpc/types.h> + +/* We play dirty tricks with aliases. */ +#include <rpc/xdr.h> + +#include <stdint.h> +#include <shlib-compat.h> + +/* XDR 64bit integers */ +bool_t +xdr_int64_t (XDR *xdrs, int64_t *ip) +{ + int32_t t1, t2; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t1 = (int32_t) ((*ip) >> 32); + t2 = (int32_t) (*ip); + return (XDR_PUTINT32(xdrs, &t1) && XDR_PUTINT32(xdrs, &t2)); + case XDR_DECODE: + if (!XDR_GETINT32(xdrs, &t1) || !XDR_GETINT32(xdrs, &t2)) + return FALSE; + *ip = ((int64_t) t1) << 32; + *ip |= (uint32_t) t2; /* Avoid sign extension. */ + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_int64_t, GLIBC_2_1_1) + +bool_t +xdr_quad_t (XDR *xdrs, quad_t *ip) +{ + return xdr_int64_t (xdrs, (int64_t *) ip); +} +libc_hidden_nolink_sunrpc (xdr_quad_t, GLIBC_2_3_4) + +/* XDR 64bit unsigned integers */ +bool_t +xdr_uint64_t (XDR *xdrs, uint64_t *uip) +{ + uint32_t t1; + uint32_t t2; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t1 = (uint32_t) ((*uip) >> 32); + t2 = (uint32_t) (*uip); + return (XDR_PUTINT32 (xdrs, (int32_t *) &t1) && + XDR_PUTINT32(xdrs, (int32_t *) &t2)); + case XDR_DECODE: + if (!XDR_GETINT32(xdrs, (int32_t *) &t1) || + !XDR_GETINT32(xdrs, (int32_t *) &t2)) + return FALSE; + *uip = ((uint64_t) t1) << 32; + *uip |= t2; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_uint64_t, GLIBC_2_1_1) + +bool_t +xdr_u_quad_t (XDR *xdrs, u_quad_t *ip) +{ + return xdr_uint64_t (xdrs, (uint64_t *) ip); +} +libc_hidden_nolink_sunrpc (xdr_u_quad_t, GLIBC_2_3_4) + +/* XDR 32bit integers */ +bool_t +xdr_int32_t (XDR *xdrs, int32_t *lp) +{ + switch (xdrs->x_op) + { + case XDR_ENCODE: + return XDR_PUTINT32 (xdrs, lp); + case XDR_DECODE: + return XDR_GETINT32 (xdrs, lp); + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_int32_t, GLIBC_2_1) + +/* XDR 32bit unsigned integers */ +bool_t +xdr_uint32_t (XDR *xdrs, uint32_t *ulp) +{ + switch (xdrs->x_op) + { + case XDR_ENCODE: + return XDR_PUTINT32 (xdrs, (int32_t *) ulp); + case XDR_DECODE: + return XDR_GETINT32 (xdrs, (int32_t *) ulp); + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_uint32_t) +#else +libc_hidden_nolink_sunrpc (xdr_uint32_t, GLIBC_2_1) +#endif + +/* XDR 16bit integers */ +bool_t +xdr_int16_t (XDR *xdrs, int16_t *ip) +{ + int32_t t; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t = (int32_t) *ip; + return XDR_PUTINT32 (xdrs, &t); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, &t)) + return FALSE; + *ip = (int16_t) t; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_int16_t, GLIBC_2_1) + +/* XDR 16bit unsigned integers */ +bool_t +xdr_uint16_t (XDR *xdrs, uint16_t *uip) +{ + uint32_t ut; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + ut = (uint32_t) *uip; + return XDR_PUTINT32 (xdrs, (int32_t *) &ut); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, (int32_t *) &ut)) + return FALSE; + *uip = (uint16_t) ut; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_uint16_t, GLIBC_2_1) + +/* XDR 8bit integers */ +bool_t +xdr_int8_t (XDR *xdrs, int8_t *ip) +{ + int32_t t; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + t = (int32_t) *ip; + return XDR_PUTINT32 (xdrs, &t); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, &t)) + return FALSE; + *ip = (int8_t) t; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_int8_t, GLIBC_2_1) + +/* XDR 8bit unsigned integers */ +bool_t +xdr_uint8_t (XDR *xdrs, uint8_t *uip) +{ + uint32_t ut; + + switch (xdrs->x_op) + { + case XDR_ENCODE: + ut = (uint32_t) *uip; + return XDR_PUTINT32 (xdrs, (int32_t *) &ut); + case XDR_DECODE: + if (!XDR_GETINT32 (xdrs, (int32_t *) &ut)) + return FALSE; + *uip = (uint8_t) ut; + return TRUE; + case XDR_FREE: + return TRUE; + default: + return FALSE; + } +} +libc_hidden_nolink_sunrpc (xdr_uint8_t, GLIBC_2_1) diff --git a/REORG.TODO/sunrpc/xdr_mem.c b/REORG.TODO/sunrpc/xdr_mem.c new file mode 100644 index 0000000000..46a1f6f190 --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_mem.c @@ -0,0 +1,239 @@ +/* + * xdr_mem.c, XDR implementation using memory buffers. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <string.h> +#include <limits.h> +#include <rpc/rpc.h> +#include <shlib-compat.h> + +static bool_t xdrmem_getlong (XDR *, long *); +static bool_t xdrmem_putlong (XDR *, const long *); +static bool_t xdrmem_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrmem_putbytes (XDR *, const char *, u_int); +static u_int xdrmem_getpos (const XDR *); +static bool_t xdrmem_setpos (XDR *, u_int); +static int32_t *xdrmem_inline (XDR *, u_int); +static void xdrmem_destroy (XDR *); +static bool_t xdrmem_getint32 (XDR *, int32_t *); +static bool_t xdrmem_putint32 (XDR *, const int32_t *); + +static const struct xdr_ops xdrmem_ops = +{ + xdrmem_getlong, + xdrmem_putlong, + xdrmem_getbytes, + xdrmem_putbytes, + xdrmem_getpos, + xdrmem_setpos, + xdrmem_inline, + xdrmem_destroy, + xdrmem_getint32, + xdrmem_putint32 +}; + +/* + * The procedure xdrmem_create initializes a stream descriptor for a + * memory buffer. + */ +void +xdrmem_create (XDR *xdrs, const caddr_t addr, u_int size, enum xdr_op op) +{ + xdrs->x_op = op; + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrmem_ops; + xdrs->x_private = xdrs->x_base = addr; + xdrs->x_handy = size; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdrmem_create) +#else +libc_hidden_nolink_sunrpc (xdrmem_create, GLIBC_2_0) +#endif + +/* + * Nothing needs to be done for the memory case. The argument is clearly + * const. + */ + +static void +xdrmem_destroy (XDR *xdrs) +{ +} + +/* + * Gets the next word from the memory referenced by xdrs and places it + * in the long pointed to by lp. It then increments the private word to + * point at the next element. Neither object pointed to is const + */ +static bool_t +xdrmem_getlong (XDR *xdrs, long *lp) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *lp = (int32_t) ntohl ((*((int32_t *) (xdrs->x_private)))); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Puts the long pointed to by lp in the memory referenced by xdrs. It + * then increments the private word to point at the next element. The + * long pointed at is const + */ +static bool_t +xdrmem_putlong (XDR *xdrs, const long *lp) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *(int32_t *) xdrs->x_private = htonl (*lp); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Gets an unaligned number of bytes from the xdrs structure and writes them + * to the address passed in addr. Be very careful when calling this routine + * as it could leave the xdrs pointing to an unaligned structure which is not + * a good idea. None of the things pointed to are const. + */ +static bool_t +xdrmem_getbytes (XDR *xdrs, caddr_t addr, u_int len) +{ + if (xdrs->x_handy < len) + return FALSE; + xdrs->x_handy -= len; + memcpy (addr, xdrs->x_private, len); + xdrs->x_private += len; + return TRUE; +} + +/* + * The complementary function to the above. The same warnings apply about + * unaligned data. The source address is const. + */ +static bool_t +xdrmem_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + if (xdrs->x_handy < len) + return FALSE; + xdrs->x_handy -= len; + memcpy (xdrs->x_private, addr, len); + xdrs->x_private += len; + return TRUE; +} + +/* + * Not sure what this one does. But it clearly doesn't modify the contents + * of xdrs. **FIXME** does this not assume u_int == u_long? + */ +static u_int +xdrmem_getpos (const XDR *xdrs) +{ + return (u_long) xdrs->x_private - (u_long) xdrs->x_base; +} + +/* + * xdrs modified + */ +static bool_t +xdrmem_setpos (XDR *xdrs, u_int pos) +{ + caddr_t newaddr = xdrs->x_base + pos; + caddr_t lastaddr = xdrs->x_private + xdrs->x_handy; + size_t handy = lastaddr - newaddr; + + if (newaddr > lastaddr + || newaddr < xdrs->x_base + || handy != (u_int) handy) + return FALSE; + + xdrs->x_private = newaddr; + xdrs->x_handy = (u_int) handy; + return TRUE; +} + +/* + * xdrs modified + */ +static int32_t * +xdrmem_inline (XDR *xdrs, u_int len) +{ + int32_t *buf = 0; + + if (xdrs->x_handy >= len) + { + xdrs->x_handy -= len; + buf = (int32_t *) xdrs->x_private; + xdrs->x_private += len; + } + return buf; +} + +/* + * Gets the next word from the memory referenced by xdrs and places it + * in the int pointed to by ip. It then increments the private word to + * point at the next element. Neither object pointed to is const + */ +static bool_t +xdrmem_getint32 (XDR *xdrs, int32_t *ip) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *ip = ntohl ((*((int32_t *) (xdrs->x_private)))); + xdrs->x_private += 4; + return TRUE; +} + +/* + * Puts the long pointed to by lp in the memory referenced by xdrs. It + * then increments the private word to point at the next element. The + * long pointed at is const + */ +static bool_t +xdrmem_putint32 (XDR *xdrs, const int32_t *ip) +{ + if (xdrs->x_handy < 4) + return FALSE; + xdrs->x_handy -= 4; + *(int32_t *) xdrs->x_private = htonl (*ip); + xdrs->x_private += 4; + return TRUE; +} diff --git a/REORG.TODO/sunrpc/xdr_rec.c b/REORG.TODO/sunrpc/xdr_rec.c new file mode 100644 index 0000000000..fafa591c7c --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_rec.c @@ -0,0 +1,655 @@ +/* + * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking" + * layer above tcp (for rpc's use). + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * These routines interface XDRSTREAMS to a tcp/ip connection. + * There is a record marking layer between the xdr stream + * and the tcp transport level. A record is composed on one or more + * record fragments. A record fragment is a thirty-two bit header followed + * by n bytes of data, where n is contained in the header. The header + * is represented as a htonl(u_long). The high 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 <string.h> +#include <unistd.h> +#include <stdint.h> +#include <rpc/rpc.h> +#include <libintl.h> +#include <wchar.h> +#include <libio/iolibio.h> +#include <shlib-compat.h> + +static bool_t xdrrec_getlong (XDR *, long *); +static bool_t xdrrec_putlong (XDR *, const long *); +static bool_t xdrrec_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrrec_putbytes (XDR *, const char *, u_int); +static u_int xdrrec_getpos (const XDR *); +static bool_t xdrrec_setpos (XDR *, u_int); +static int32_t *xdrrec_inline (XDR *, u_int); +static void xdrrec_destroy (XDR *); +static bool_t xdrrec_getint32 (XDR *, int32_t *); +static bool_t xdrrec_putint32 (XDR *, const int32_t *); + +static const struct xdr_ops xdrrec_ops = { + xdrrec_getlong, + xdrrec_putlong, + xdrrec_getbytes, + xdrrec_putbytes, + xdrrec_getpos, + xdrrec_setpos, + xdrrec_inline, + xdrrec_destroy, + xdrrec_getint32, + xdrrec_putint32 +}; + +/* + * A record is composed of one or more record fragments. + * A record fragment is a two-byte header followed by zero to + * 2**32-1 bytes. The header is treated as a long unsigned and is + * encode/decoded to the network via htonl/ntohl. The low order 31 bits + * are a byte count of the fragment. The highest order bit is a boolean: + * 1 => this fragment is the last fragment of the record, + * 0 => this fragment is followed by more fragment(s). + * + * The fragment/record machinery is not general; it is constructed to + * meet the needs of xdr and rpc based on tcp. + */ + +#define LAST_FRAG (1UL << 31) + +typedef struct rec_strm + { + caddr_t tcp_handle; + caddr_t the_buffer; + /* + * out-going bits + */ + int (*writeit) (char *, char *, int); + caddr_t out_base; /* output buffer (points to frag header) */ + caddr_t out_finger; /* next output position */ + caddr_t out_boundry; /* data cannot up to this address */ + u_int32_t *frag_header; /* beginning of curren fragment */ + bool_t frag_sent; /* true if buffer sent in middle of record */ + /* + * in-coming bits + */ + int (*readit) (char *, char *, int); + u_long in_size; /* fixed size of the input buffer */ + caddr_t in_base; + caddr_t in_finger; /* location of next byte to be had */ + caddr_t in_boundry; /* can read up to this location */ + long fbtbc; /* fragment bytes to be consumed */ + bool_t last_frag; + u_int sendsize; + u_int recvsize; + } +RECSTREAM; + +static u_int fix_buf_size (u_int) internal_function; +static bool_t skip_input_bytes (RECSTREAM *, long) internal_function; +static bool_t flush_out (RECSTREAM *, bool_t) internal_function; +static bool_t set_input_fragment (RECSTREAM *) internal_function; +static bool_t get_input_bytes (RECSTREAM *, caddr_t, int) internal_function; + +/* + * 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 (XDR *xdrs, u_int sendsize, + u_int recvsize, caddr_t tcp_handle, + int (*readit) (char *, char *, int), + int (*writeit) (char *, char *, int)) +{ + RECSTREAM *rstrm = (RECSTREAM *) mem_alloc (sizeof (RECSTREAM)); + caddr_t tmp; + char *buf; + + sendsize = fix_buf_size (sendsize); + recvsize = fix_buf_size (recvsize); + buf = mem_alloc (sendsize + recvsize + BYTES_PER_XDR_UNIT); + + if (rstrm == NULL || buf == NULL) + { + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + mem_free (rstrm, sizeof (RECSTREAM)); + mem_free (buf, sendsize + recvsize + BYTES_PER_XDR_UNIT); + /* + * 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; + rstrm->recvsize = recvsize; + rstrm->the_buffer = buf; + tmp = rstrm->the_buffer; + if ((size_t)tmp % BYTES_PER_XDR_UNIT) + tmp += BYTES_PER_XDR_UNIT - (size_t)tmp % BYTES_PER_XDR_UNIT; + rstrm->out_base = tmp; + rstrm->in_base = tmp + sendsize; + /* + * now the rest ... + */ + /* We have to add the cast since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_ops *) &xdrrec_ops; + xdrs->x_private = (caddr_t) rstrm; + rstrm->tcp_handle = tcp_handle; + rstrm->readit = readit; + rstrm->writeit = writeit; + rstrm->out_finger = rstrm->out_boundry = rstrm->out_base; + rstrm->frag_header = (u_int32_t *) rstrm->out_base; + rstrm->out_finger += 4; + 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; +} +libc_hidden_nolink_sunrpc (xdrrec_create, GLIBC_2_0) + + +/* + * The routines defined below are the xdr ops which will go into the + * xdr handle filled in by xdrrec_create. + */ + +static bool_t +xdrrec_getlong (XDR *xdrs, long *lp) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *buflp = (int32_t *) rstrm->in_finger; + int32_t mylong; + + /* first try the inline, fast case */ + if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && + rstrm->in_boundry - (char *) buflp >= BYTES_PER_XDR_UNIT) + { + *lp = (int32_t) ntohl (*buflp); + rstrm->fbtbc -= BYTES_PER_XDR_UNIT; + rstrm->in_finger += BYTES_PER_XDR_UNIT; + } + else + { + if (!xdrrec_getbytes (xdrs, (caddr_t) & mylong, + BYTES_PER_XDR_UNIT)) + return FALSE; + *lp = (int32_t) ntohl (mylong); + } + return TRUE; +} + +static bool_t +xdrrec_putlong (XDR *xdrs, const long *lp) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *dest_lp = (int32_t *) rstrm->out_finger; + + if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) + { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= BYTES_PER_XDR_UNIT; + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + dest_lp = (int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + } + *dest_lp = htonl (*lp); + return TRUE; +} + +static bool_t /* must manage buffers, fragments, and records */ +xdrrec_getbytes (XDR *xdrs, caddr_t addr, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_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 (XDR *xdrs, const char *addr, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int current; + + while (len > 0) + { + current = rstrm->out_boundry - rstrm->out_finger; + current = (len < current) ? len : current; + memcpy (rstrm->out_finger, addr, current); + rstrm->out_finger += current; + addr += current; + len -= current; + if (rstrm->out_finger == rstrm->out_boundry && len > 0) + { + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + } + } + return TRUE; +} + +static u_int +xdrrec_getpos (const XDR *xdrs) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + long pos; + + pos = __lseek ((int) (long) rstrm->tcp_handle, (long) 0, 1); + if (pos != -1) + switch (xdrs->x_op) + { + + case XDR_ENCODE: + pos += rstrm->out_finger - rstrm->out_base; + break; + + case XDR_DECODE: + pos -= rstrm->in_boundry - rstrm->in_finger; + break; + + default: + pos = (u_int) - 1; + break; + } + return (u_int) pos; +} + +static bool_t +xdrrec_setpos (XDR *xdrs, u_int pos) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_int currpos = xdrrec_getpos (xdrs); + int delta = currpos - pos; + caddr_t newpos; + + if ((int) currpos != -1) + switch (xdrs->x_op) + { + + case XDR_ENCODE: + newpos = rstrm->out_finger - delta; + if (newpos > (caddr_t) rstrm->frag_header && + newpos < rstrm->out_boundry) + { + rstrm->out_finger = newpos; + return TRUE; + } + break; + + case XDR_DECODE: + newpos = rstrm->in_finger - delta; + if ((delta < (int) (rstrm->fbtbc)) && + (newpos <= rstrm->in_boundry) && + (newpos >= rstrm->in_base)) + { + rstrm->in_finger = newpos; + rstrm->fbtbc -= delta; + return TRUE; + } + break; + + default: + break; + } + return FALSE; +} + +static int32_t * +xdrrec_inline (XDR *xdrs, u_int len) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *buf = NULL; + + switch (xdrs->x_op) + { + + case XDR_ENCODE: + if ((rstrm->out_finger + len) <= rstrm->out_boundry) + { + buf = (int32_t *) rstrm->out_finger; + rstrm->out_finger += len; + } + break; + + case XDR_DECODE: + if ((len <= rstrm->fbtbc) && + ((rstrm->in_finger + len) <= rstrm->in_boundry)) + { + buf = (int32_t *) rstrm->in_finger; + rstrm->fbtbc -= len; + rstrm->in_finger += len; + } + break; + + default: + break; + } + return buf; +} + +static void +xdrrec_destroy (XDR *xdrs) +{ + 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)); +} + +static bool_t +xdrrec_getint32 (XDR *xdrs, int32_t *ip) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *bufip = (int32_t *) rstrm->in_finger; + int32_t mylong; + + /* first try the inline, fast case */ + if (rstrm->fbtbc >= BYTES_PER_XDR_UNIT && + rstrm->in_boundry - (char *) bufip >= BYTES_PER_XDR_UNIT) + { + *ip = ntohl (*bufip); + rstrm->fbtbc -= BYTES_PER_XDR_UNIT; + rstrm->in_finger += BYTES_PER_XDR_UNIT; + } + else + { + if (!xdrrec_getbytes (xdrs, (caddr_t) &mylong, + BYTES_PER_XDR_UNIT)) + return FALSE; + *ip = ntohl (mylong); + } + return TRUE; +} + +static bool_t +xdrrec_putint32 (XDR *xdrs, const int32_t *ip) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + int32_t *dest_ip = (int32_t *) rstrm->out_finger; + + if ((rstrm->out_finger += BYTES_PER_XDR_UNIT) > rstrm->out_boundry) + { + /* + * this case should almost never happen so the code is + * inefficient + */ + rstrm->out_finger -= BYTES_PER_XDR_UNIT; + rstrm->frag_sent = TRUE; + if (!flush_out (rstrm, FALSE)) + return FALSE; + dest_ip = (int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + } + *dest_ip = htonl (*ip); + return TRUE; +} + +/* + * 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 (XDR *xdrs) +{ + 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; +} +libc_hidden_nolink_sunrpc (xdrrec_skiprecord, GLIBC_2_0) + +/* + * Lookahead function. + * Returns TRUE iff there is no more input in the buffer + * after consuming the rest of the current record. + */ +bool_t +xdrrec_eof (XDR *xdrs) +{ + 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; +} +libc_hidden_nolink_sunrpc (xdrrec_eof, GLIBC_2_0) + +/* + * The client must tell the package when an end-of-record has occurred. + * The second parameter tells whether the record should be flushed to the + * (output) tcp stream. (This lets the package support batched or + * pipelined procedure calls.) TRUE => immediate flush to tcp connection. + */ +bool_t +xdrrec_endofrecord (XDR *xdrs, bool_t sendnow) +{ + RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; + u_long len; /* fragment length */ + + if (sendnow || rstrm->frag_sent + || rstrm->out_finger + BYTES_PER_XDR_UNIT >= rstrm->out_boundry) + { + rstrm->frag_sent = FALSE; + return flush_out (rstrm, TRUE); + } + len = (rstrm->out_finger - (char *) rstrm->frag_header + - BYTES_PER_XDR_UNIT); + *rstrm->frag_header = htonl ((u_long) len | LAST_FRAG); + rstrm->frag_header = (u_int32_t *) rstrm->out_finger; + rstrm->out_finger += BYTES_PER_XDR_UNIT; + return TRUE; +} +libc_hidden_nolink_sunrpc (xdrrec_endofrecord, GLIBC_2_0) + + +/* + * Internal useful routines + */ +static bool_t +internal_function +flush_out (RECSTREAM *rstrm, bool_t eor) +{ + u_long eormask = (eor == TRUE) ? LAST_FRAG : 0; + u_long len = (rstrm->out_finger - (char *) rstrm->frag_header + - BYTES_PER_XDR_UNIT); + + *rstrm->frag_header = htonl (len | eormask); + len = rstrm->out_finger - rstrm->out_base; + if ((*(rstrm->writeit)) (rstrm->tcp_handle, rstrm->out_base, (int) len) + != (int) len) + return FALSE; + rstrm->frag_header = (u_int32_t *) rstrm->out_base; + rstrm->out_finger = (caddr_t) rstrm->out_base + BYTES_PER_XDR_UNIT; + return TRUE; +} + +static bool_t /* knows nothing about records! Only about input buffers */ +fill_input_buf (RECSTREAM *rstrm) +{ + caddr_t where; + size_t i; + int len; + + where = rstrm->in_base; + i = (size_t) 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 */ +internal_function +get_input_bytes (RECSTREAM *rstrm, caddr_t addr, int len) +{ + int current; + + while (len > 0) + { + current = rstrm->in_boundry - rstrm->in_finger; + if (current == 0) + { + if (!fill_input_buf (rstrm)) + return FALSE; + continue; + } + current = (len < current) ? len : current; + memcpy (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 */ +internal_function +set_input_fragment (RECSTREAM *rstrm) +{ + uint32_t header; + + if (! get_input_bytes (rstrm, (caddr_t)&header, BYTES_PER_XDR_UNIT)) + return FALSE; + header = ntohl (header); + rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE; + /* + * Sanity check. Try not to accept wildly incorrect fragment + * sizes. Unfortunately, only a size of zero can be identified as + * 'wildely incorrect', and this only, if it is not the last + * fragment of a message. Ridiculously large fragment sizes may look + * wrong, but we don't have any way to be certain that they aren't + * what the client actually intended to send us. Many existing RPC + * implementations may sent a fragment of size zero as the last + * fragment of a message. + */ + if (header == 0) + return FALSE; + rstrm->fbtbc = header & ~LAST_FRAG; + return TRUE; +} + +static bool_t /* consumes input bytes; knows nothing about records! */ +internal_function +skip_input_bytes (RECSTREAM *rstrm, long cnt) +{ + int current; + + while (cnt > 0) + { + current = rstrm->in_boundry - rstrm->in_finger; + if (current == 0) + { + if (!fill_input_buf (rstrm)) + return FALSE; + continue; + } + current = (cnt < current) ? cnt : current; + rstrm->in_finger += current; + cnt -= current; + } + return TRUE; +} + +static u_int +internal_function +fix_buf_size (u_int s) +{ + if (s < 100) + s = 4000; + return RNDUP (s); +} diff --git a/REORG.TODO/sunrpc/xdr_ref.c b/REORG.TODO/sunrpc/xdr_ref.c new file mode 100644 index 0000000000..eab3b74227 --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_ref.c @@ -0,0 +1,140 @@ +/* + * xdr_reference.c, Generic XDR routines implementation. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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 <string.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <libintl.h> +#include <wchar.h> +#include <libio/iolibio.h> +#include <shlib-compat.h> + +#define LASTUNSIGNED ((u_int)0-1) + +/* + * XDR an indirect pointer + * xdr_reference is for recursively translating a structure that is + * referenced by a pointer inside the structure that is currently being + * translated. pp references a pointer to storage. If *pp is null + * the necessary storage is allocated. + * size is the size of the referneced structure. + * proc is the routine to handle the referenced structure. + */ +bool_t +xdr_reference (XDR *xdrs, + /* the pointer to work on */ + caddr_t *pp, + /* size of the object pointed to */ + u_int size, + /* xdr routine to handle the object */ + xdrproc_t proc) +{ + caddr_t loc = *pp; + bool_t stat; + + if (loc == NULL) + switch (xdrs->x_op) + { + case XDR_FREE: + return TRUE; + + case XDR_DECODE: + *pp = loc = (caddr_t) calloc (1, size); + if (loc == NULL) + { + (void) __fxprintf (NULL, "%s: %s", __func__, _("out of memory\n")); + return FALSE; + } + break; + default: + break; + } + + stat = (*proc) (xdrs, loc, LASTUNSIGNED); + + if (xdrs->x_op == XDR_FREE) + { + mem_free (loc, size); + *pp = NULL; + } + return stat; +} +libc_hidden_nolink_sunrpc (xdr_reference, GLIBC_2_0) + + +/* + * xdr_pointer(): + * + * XDR a pointer to a possibly recursive data structure. This + * differs with xdr_reference in that it can serialize/deserialize + * 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 (XDR *xdrs, char **objpp, u_int obj_size, xdrproc_t xdr_obj) +{ + + bool_t more_data; + + more_data = (*objpp != NULL); + if (!xdr_bool (xdrs, &more_data)) + { + return FALSE; + } + if (!more_data) + { + *objpp = NULL; + return TRUE; + } + return xdr_reference (xdrs, objpp, obj_size, xdr_obj); +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_pointer) +#else +libc_hidden_nolink_sunrpc (xdr_pointer, GLIBC_2_0) +#endif diff --git a/REORG.TODO/sunrpc/xdr_sizeof.c b/REORG.TODO/sunrpc/xdr_sizeof.c new file mode 100644 index 0000000000..1592406d64 --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_sizeof.c @@ -0,0 +1,166 @@ +/* + * xdr_sizeof.c + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * General purpose routine to see how much space something will use + * when serialized using XDR. + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <sys/types.h> +#include <stdlib.h> +#include <shlib-compat.h> + +/* ARGSUSED */ +static bool_t +x_putlong (XDR *xdrs, const long *longp) +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return TRUE; +} + +/* ARGSUSED */ +static bool_t +x_putbytes (XDR *xdrs, const char *bp, u_int len) +{ + xdrs->x_handy += len; + return TRUE; +} + +static u_int +x_getpostn (const XDR *xdrs) +{ + return xdrs->x_handy; +} + +/* ARGSUSED */ +static bool_t +x_setpostn (XDR *xdrs, u_int len) +{ + /* This is not allowed */ + return FALSE; +} + +static int32_t * +x_inline (XDR *xdrs, u_int len) +{ + if (len == 0) + return NULL; + if (xdrs->x_op != XDR_ENCODE) + return NULL; + if (len < (u_int) (long int) xdrs->x_base) + { + /* x_private was already allocated */ + xdrs->x_handy += len; + return (int32_t *) xdrs->x_private; + } + else + { + /* Free the earlier space and allocate new area */ + free (xdrs->x_private); + if ((xdrs->x_private = (caddr_t) malloc (len)) == NULL) + { + xdrs->x_base = 0; + return NULL; + } + xdrs->x_base = (void *) (long) len; + xdrs->x_handy += len; + return (int32_t *) xdrs->x_private; + } +} + +static int +harmless (void) +{ + /* Always return FALSE/NULL, as the case may be */ + return 0; +} + +static void +x_destroy (XDR *xdrs) +{ + xdrs->x_handy = 0; + xdrs->x_base = 0; + if (xdrs->x_private) + { + free (xdrs->x_private); + xdrs->x_private = NULL; + } + return; +} + +static bool_t +x_putint32 (XDR *xdrs, const int32_t *int32p) +{ + xdrs->x_handy += BYTES_PER_XDR_UNIT; + return TRUE; +} + +unsigned long +xdr_sizeof (xdrproc_t func, void *data) +{ + XDR x; + struct xdr_ops ops; + bool_t stat; + /* to stop ANSI-C compiler from complaining */ + typedef bool_t (*dummyfunc1) (XDR *, long *); + typedef bool_t (*dummyfunc2) (XDR *, caddr_t, u_int); + typedef bool_t (*dummyfunc3) (XDR *, int32_t *); + + ops.x_putlong = x_putlong; + ops.x_putbytes = x_putbytes; + ops.x_inline = x_inline; + ops.x_getpostn = x_getpostn; + ops.x_setpostn = x_setpostn; + ops.x_destroy = x_destroy; + ops.x_putint32 = x_putint32; + + /* the other harmless ones */ + ops.x_getlong = (dummyfunc1) harmless; + ops.x_getbytes = (dummyfunc2) harmless; + ops.x_getint32 = (dummyfunc3) harmless; + + x.x_op = XDR_ENCODE; + x.x_ops = &ops; + x.x_handy = 0; + x.x_private = (caddr_t) NULL; + x.x_base = (caddr_t) 0; + + stat = func (&x, data); + free (x.x_private); + return stat == TRUE ? x.x_handy : 0; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdr_sizeof) +#else +libc_hidden_nolink_sunrpc (xdr_sizeof, GLIBC_2_1) +#endif diff --git a/REORG.TODO/sunrpc/xdr_stdio.c b/REORG.TODO/sunrpc/xdr_stdio.c new file mode 100644 index 0000000000..6ab514b664 --- /dev/null +++ b/REORG.TODO/sunrpc/xdr_stdio.c @@ -0,0 +1,197 @@ +/* + * xdr_stdio.c, XDR implementation on standard i/o file. + * + * Copyright (c) 2010, Oracle America, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials + * provided with the distribution. + * * Neither the name of the "Oracle America, Inc." nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * 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> + +#include <libio/iolibio.h> +#include <shlib-compat.h> + +#define fflush(s) _IO_fflush (s) +#define fread(p, m, n, s) _IO_fread (p, m, n, s) +#define ftell(s) _IO_ftell (s) +#define fwrite(p, m, n, s) _IO_fwrite (p, m, n, s) + +static bool_t xdrstdio_getlong (XDR *, long *); +static bool_t xdrstdio_putlong (XDR *, const long *); +static bool_t xdrstdio_getbytes (XDR *, caddr_t, u_int); +static bool_t xdrstdio_putbytes (XDR *, const char *, u_int); +static u_int xdrstdio_getpos (const XDR *); +static bool_t xdrstdio_setpos (XDR *, u_int); +static int32_t *xdrstdio_inline (XDR *, u_int); +static void xdrstdio_destroy (XDR *); +static bool_t xdrstdio_getint32 (XDR *, int32_t *); +static bool_t xdrstdio_putint32 (XDR *, const int32_t *); + +/* + * Ops vector for stdio type XDR + */ +static const struct xdr_ops xdrstdio_ops = +{ + xdrstdio_getlong, /* deserialize a long int */ + xdrstdio_putlong, /* serialize 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 */ + xdrstdio_getint32, /* deserialize a int */ + xdrstdio_putint32 /* serialize a int */ +}; + +/* + * 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 (XDR *xdrs, FILE *file, enum xdr_op op) +{ + xdrs->x_op = op; + /* We have to add the const since the `struct xdr_ops' in `struct XDR' + is not `const'. */ + xdrs->x_ops = (struct xdr_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 (XDR *xdrs) +{ + (void) fflush ((FILE *) xdrs->x_private); + /* xx should we close the file ?? */ +}; + +static bool_t +xdrstdio_getlong (XDR *xdrs, long *lp) +{ + u_int32_t mycopy; + + if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + *lp = (long) ntohl (mycopy); + return TRUE; +} + +static bool_t +xdrstdio_putlong (XDR *xdrs, const long *lp) +{ + int32_t mycopy = htonl ((u_int32_t) *lp); + + if (fwrite ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + return TRUE; +} + +static bool_t +xdrstdio_getbytes (XDR *xdrs, const caddr_t addr, u_int len) +{ + if ((len != 0) && (fread (addr, (int) len, 1, + (FILE *) xdrs->x_private) != 1)) + return FALSE; + return TRUE; +} + +static bool_t +xdrstdio_putbytes (XDR *xdrs, const char *addr, u_int len) +{ + if ((len != 0) && (fwrite (addr, (int) len, 1, + (FILE *) xdrs->x_private) != 1)) + return FALSE; + return TRUE; +} + +static u_int +xdrstdio_getpos (const XDR *xdrs) +{ + return (u_int) ftell ((FILE *) xdrs->x_private); +} + +static bool_t +xdrstdio_setpos (XDR *xdrs, u_int pos) +{ + return fseek ((FILE *) xdrs->x_private, (long) pos, 0) < 0 ? FALSE : TRUE; +} + +static int32_t * +xdrstdio_inline (XDR *xdrs, u_int len) +{ + /* + * Must do some work to implement this: must insure + * enough data in the underlying stdio buffer, + * that the buffer is aligned so that we can indirect through a + * long *, and stuff this pointer in xdrs->x_buf. Doing + * a fread or fwrite to a scratch buffer would defeat + * most of the gains to be had here and require storage + * management on this buffer, so we don't do this. + */ + return NULL; +} + +static bool_t +xdrstdio_getint32 (XDR *xdrs, int32_t *ip) +{ + int32_t mycopy; + + if (fread ((caddr_t) &mycopy, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + *ip = ntohl (mycopy); + return TRUE; +} + +static bool_t +xdrstdio_putint32 (XDR *xdrs, const int32_t *ip) +{ + int32_t mycopy = htonl (*ip); + + ip = &mycopy; + if (fwrite ((caddr_t) ip, 4, 1, (FILE *) xdrs->x_private) != 1) + return FALSE; + return TRUE; +} +#ifdef EXPORT_RPC_SYMBOLS +libc_hidden_def (xdrstdio_create) +#else +libc_hidden_nolink_sunrpc (xdrstdio_create, GLIBC_2_0) +#endif |