Full switch to clang/ELF. Drop ack. Simplify.
There is important information about booting non-ack images in docs/UPDATING. ack/aout-format images can't be built any more, and booting clang/ELF-format ones is a little different. Updating to the new boot monitor is recommended. Changes in this commit: . drop boot monitor -> allowing dropping ack support . facility to copy ELF boot files to /boot so that old boot monitor can still boot fairly easily, see UPDATING . no more ack-format libraries -> single-case libraries . some cleanup of OBJECT_FMT, COMPILER_TYPE, etc cases . drop several ack toolchain commands, but not all support commands (e.g. aal is gone but acksize is not yet). . a few libc files moved to netbsd libc dir . new /bin/date as minix date used code in libc/ . test compile fix . harmonize includes . /usr/lib is no longer special: without ack, /usr/lib plays no kind of special bootstrapping role any more and bootstrapping is done exclusively through packages, so releases depend even less on the state of the machine making them now. . rename nbsd_lib* to lib* . reduce mtree
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
/* $NetBSD: DISCLAIMER,v 1.2 1998/01/09 04:11:51 perry Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
@@ -0,0 +1,168 @@
|
||||
# $NetBSD: Makefile.inc,v 1.17 2008/10/25 19:07:26 mrg Exp $
|
||||
|
||||
# librpc sources
|
||||
.PATH: ${.CURDIR}/rpc
|
||||
|
||||
SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c \
|
||||
clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c \
|
||||
clnt_raw.c clnt_simple.c \
|
||||
clnt_vc.c rpc_dtablesize.c \
|
||||
getnetconfig.c getnetpath.c getrpcent.c getrpcport.c \
|
||||
mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \
|
||||
pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \
|
||||
rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c \
|
||||
svc.c svc_auth.c svc_dg.c svc_auth_unix.c svc_generic.c svc_raw.c \
|
||||
svc_run.c svc_simple.c svc_vc.c \
|
||||
xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c \
|
||||
xdr_stdio.c __rpc_getxid.c
|
||||
|
||||
CPPFLAGS+= -DPORTMAP
|
||||
|
||||
MAN+= bindresvport.3 getnetconfig.3 getnetpath.3 getrpcent.3 getrpcport.3 \
|
||||
rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 rpc_clnt_create.3 \
|
||||
rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 rpc_svc_reg.3 \
|
||||
rpc_xdr.3 rpcbind.3 xdr.3
|
||||
MLINKS+= bindresvport.3 bindresvport_sa.3 \
|
||||
getnetconfig.3 setnetconfig.3 \
|
||||
getnetconfig.3 getnetconfigent.3 \
|
||||
getnetconfig.3 endnetconfig.3 \
|
||||
getnetconfig.3 nc_perror.3 \
|
||||
getnetconfig.3 nc_sperror.3 \
|
||||
getnetpath.3 setnetpath.3 \
|
||||
getnetpath.3 endnetpath.3 \
|
||||
getrpcent.3 getrpcbyname.3 \
|
||||
getrpcent.3 getrpcbynumber.3 \
|
||||
getrpcent.3 endrpcent.3 \
|
||||
getrpcent.3 setrpcent.3 \
|
||||
rpc_clnt_auth.3 auth_destroy.3 \
|
||||
rpc_clnt_auth.3 authnone_create.3 \
|
||||
rpc_clnt_auth.3 authsys_create.3 \
|
||||
rpc_clnt_auth.3 authsys_create_default.3 \
|
||||
rpc_clnt_calls.3 clnt_call.3 \
|
||||
rpc_clnt_calls.3 clnt_perrno.3 \
|
||||
rpc_clnt_calls.3 clnt_perror.3 \
|
||||
rpc_clnt_calls.3 clnt_sperrno.3 \
|
||||
rpc_clnt_calls.3 clnt_sperror.3 \
|
||||
rpc_clnt_calls.3 rpc_call.3 \
|
||||
rpc_clnt_calls.3 rpc_broadcast.3 \
|
||||
rpc_clnt_calls.3 rpc_broadcast_exp.3 \
|
||||
rpc_clnt_calls.3 clnt_freeres.3 \
|
||||
rpc_clnt_calls.3 clnt_geterr.3 \
|
||||
rpc_clnt_create.3 clnt_control.3 \
|
||||
rpc_clnt_create.3 clnt_create.3 \
|
||||
rpc_clnt_create.3 clnt_create_vers.3 \
|
||||
rpc_clnt_create.3 clnt_destroy.3 \
|
||||
rpc_clnt_create.3 clnt_pcreateerror.3 \
|
||||
rpc_clnt_create.3 clnt_spcreateerror.3 \
|
||||
rpc_clnt_create.3 clnt_dg_create.3 \
|
||||
rpc_clnt_create.3 clnt_raw_create.3 \
|
||||
rpc_clnt_create.3 clnt_tli_create.3 \
|
||||
rpc_clnt_create.3 clnt_tp_create.3 \
|
||||
rpc_clnt_create.3 clnt_vc_create.3 \
|
||||
rpc_svc_calls.3 svc_dg_enablecache.3 \
|
||||
rpc_svc_calls.3 svc_exit.3 \
|
||||
rpc_svc_calls.3 svc_freeargs.3 \
|
||||
rpc_svc_calls.3 svc_getargs.3 \
|
||||
rpc_svc_calls.3 svc_getreq_common.3 \
|
||||
rpc_svc_calls.3 svc_getreq_poll.3 \
|
||||
rpc_svc_calls.3 svc_getreqset.3 \
|
||||
rpc_svc_calls.3 svc_getrpccaller.3 \
|
||||
rpc_svc_calls.3 __svc_getcallercreds.3 \
|
||||
rpc_svc_calls.3 svc_pollset.3 \
|
||||
rpc_svc_calls.3 svc_run.3 \
|
||||
rpc_svc_calls.3 svc_sendreply.3 \
|
||||
rpc_svc_create.3 svc_control.3 \
|
||||
rpc_svc_create.3 svc_create.3 \
|
||||
rpc_svc_create.3 svc_dg_create.3 \
|
||||
rpc_svc_create.3 svc_destroy.3 \
|
||||
rpc_svc_create.3 svc_fd_create.3 \
|
||||
rpc_svc_create.3 svc_raw_create.3 \
|
||||
rpc_svc_create.3 svc_tli_create.3 \
|
||||
rpc_svc_create.3 svc_tp_create.3 \
|
||||
rpc_svc_create.3 svc_vc_create.3 \
|
||||
rpc_svc_err.3 svcerr_auth.3 \
|
||||
rpc_svc_err.3 svcerr_decode.3 \
|
||||
rpc_svc_err.3 svcerr_noproc.3 \
|
||||
rpc_svc_err.3 svcerr_noprog.3 \
|
||||
rpc_svc_err.3 svcerr_progvers.3 \
|
||||
rpc_svc_err.3 svcerr_systemerr.3 \
|
||||
rpc_svc_err.3 svcerr_weakauth.3 \
|
||||
rpc_svc_reg.3 rpc_reg.3 \
|
||||
rpc_svc_reg.3 svc_reg.3 \
|
||||
rpc_svc_reg.3 svc_unreg.3 \
|
||||
rpc_svc_reg.3 svc_auth_reg.3 \
|
||||
rpc_svc_reg.3 xprt_register.3 \
|
||||
rpc_svc_reg.3 xprt_unregister.3 \
|
||||
rpc_xdr.3 xdr_accepted_reply.3 \
|
||||
rpc_xdr.3 xdr_authsys_parms.3 \
|
||||
rpc_xdr.3 xdr_callhdr.3 \
|
||||
rpc_xdr.3 xdr_callmsg.3 \
|
||||
rpc_xdr.3 xdr_opaque_auth.3 \
|
||||
rpc_xdr.3 xdr_rejected_reply.3 \
|
||||
rpc_xdr.3 xdr_replymsg.3 \
|
||||
rpcbind.3 rpcb_getmaps.3 \
|
||||
rpcbind.3 rpcb_getaddr.3 \
|
||||
rpcbind.3 rpcb_gettime.3 \
|
||||
rpcbind.3 rpcb_rmtcall.3 \
|
||||
rpcbind.3 rpcb_set.3 \
|
||||
rpcbind.3 rpcb_unset.3 \
|
||||
rpc_soc.3 authunix_create.3 \
|
||||
rpc_soc.3 authunix_create_default.3 \
|
||||
rpc_soc.3 callrpc.3 \
|
||||
rpc_soc.3 clnt_broadcast.3 \
|
||||
rpc_soc.3 clntraw_create.3 \
|
||||
rpc_soc.3 clnttcp_create.3 \
|
||||
rpc_soc.3 clntudp_bufcreate.3 \
|
||||
rpc_soc.3 clntudp_create.3 \
|
||||
rpc_soc.3 get_myaddress.3 \
|
||||
rpc_soc.3 pmap_getmaps.3 \
|
||||
rpc_soc.3 pmap_getport.3 \
|
||||
rpc_soc.3 pmap_rmtcall.3 \
|
||||
rpc_soc.3 pmap_set.3 \
|
||||
rpc_soc.3 pmap_unset.3 \
|
||||
rpc_soc.3 registerrpc.3 \
|
||||
rpc_soc.3 rpc_createerr.3 \
|
||||
rpc_soc.3 svc_fds.3 \
|
||||
rpc_soc.3 svc_fdset.3 \
|
||||
rpc_soc.3 svc_getcaller.3 \
|
||||
rpc_soc.3 svc_register.3 \
|
||||
rpc_soc.3 svc_unregister.3 \
|
||||
rpc_soc.3 svcfd_create.3 \
|
||||
rpc_soc.3 svcraw_create.3 \
|
||||
rpc_soc.3 svctcp_create.3 \
|
||||
rpc_soc.3 svcudp_create.3 \
|
||||
rpc_soc.3 svcudp_bufcreate.3 \
|
||||
rpc_soc.3 xdr_pmap.3 \
|
||||
rpc_soc.3 xdr_pmaplist.3 \
|
||||
xdr.3 xdr_array.3 \
|
||||
xdr.3 xdr_bool.3 \
|
||||
xdr.3 xdr_bytes.3 \
|
||||
xdr.3 xdr_char.3 \
|
||||
xdr.3 xdr_destroy.3 \
|
||||
xdr.3 xdr_double.3 \
|
||||
xdr.3 xdr_enum.3 \
|
||||
xdr.3 xdr_float.3 \
|
||||
xdr.3 xdr_free.3 \
|
||||
xdr.3 xdr_getpos.3 \
|
||||
xdr.3 xdr_inline.3 \
|
||||
xdr.3 xdr_int.3 \
|
||||
xdr.3 xdr_long.3 \
|
||||
xdr.3 xdrmem_create.3 \
|
||||
xdr.3 xdr_opaque.3 \
|
||||
xdr.3 xdr_pointer.3 \
|
||||
xdr.3 xdrrec_create.3 \
|
||||
xdr.3 xdrrec_endofrecord.3 \
|
||||
xdr.3 xdrrec_eof.3 \
|
||||
xdr.3 xdrrec_skiprecord.3 \
|
||||
xdr.3 xdr_reference.3 \
|
||||
xdr.3 xdr_setpos.3 \
|
||||
xdr.3 xdr_short.3 \
|
||||
xdr.3 xdrstdio_create.3 \
|
||||
xdr.3 xdr_string.3 \
|
||||
xdr.3 xdr_u_char.3 \
|
||||
xdr.3 xdr_u_long.3 \
|
||||
xdr.3 xdr_u_short.3 \
|
||||
xdr.3 xdr_union.3 \
|
||||
xdr.3 xdr_vector.3 \
|
||||
xdr.3 xdr_void.3 \
|
||||
xdr.3 xdr_wrapstring.3
|
||||
@@ -0,0 +1,235 @@
|
||||
# $NetBSD: README,v 1.2 1998/01/09 04:11:52 perry Exp $
|
||||
|
||||
RPCSRC 4.0 7/11/89
|
||||
|
||||
This distribution contains Sun Microsystem's implementation of the
|
||||
RPC and XDR protocols and is compatible with 4.2BSD and 4.3BSD. Also
|
||||
included is complete documentation, utilities, RPC service
|
||||
specification files, and demonstration services in the format used by
|
||||
the RPC protocol compiler (rpcgen). See WHAT'S NEW below for
|
||||
details.
|
||||
|
||||
NOTE ABOUT SECURE RPC:
|
||||
|
||||
This release of RPCSRC contains most of the code needed to implement
|
||||
Secure RPC (see "DES Authentication" in the RPC Protocol Specification,
|
||||
doc/rpc.rfc.ms). Due to legal considerations, we are unable to
|
||||
distribute an implementation of DES, the Data Encryption Standard, which
|
||||
Secure RPC requires. For this reason, all of the files, documentation, and
|
||||
programs associated with Secure RPC have been placed into a separate
|
||||
directory, secure_rpc. The RPC library contained in the main body of this
|
||||
release *DOES NOT* support Secure RPC. See secure_rpc/README for more
|
||||
details. (A DES library was posted in Volume 18 of comp.sources.unix.)
|
||||
|
||||
If you wish to report bugs found in this release, send mail to:
|
||||
|
||||
Portable ONC/NFS
|
||||
Sun Microsystems, Inc
|
||||
MS 12-33
|
||||
2550 Garcia Avenue
|
||||
Mountain View, CA 94043
|
||||
|
||||
or send Email to nfsnet@sun.com (the Internet) or sun!nfsnet (Usenet).
|
||||
|
||||
ROADMAP
|
||||
|
||||
The directory hierarchy is as follows:
|
||||
|
||||
demo/ Various demonstration services
|
||||
demo/dir Remote directory lister
|
||||
demo/msg Remote console message delivery service
|
||||
demo/sort Remote sort service
|
||||
|
||||
doc/ Documentation for RPC, XDR and NFS in "-ms" format.
|
||||
|
||||
etc/ Utilities (rpcinfo and portmap). portmap must be
|
||||
started by root before any other RPC network services are
|
||||
used. SEE BELOW FOR BUGFIX TO 4.3BSD COMPILER.
|
||||
|
||||
man/ Manual pages for RPC library, rpcgen, and utilities.
|
||||
|
||||
rpc/ The RPC and XDR library. SEE BELOW
|
||||
FOR BUGFIX TO 4.2BSD COMPILER.
|
||||
|
||||
rpcgen/ The RPC Language compiler (for .x files)
|
||||
|
||||
rpcsvc/ Service definition files for various services and the
|
||||
server and client code for the Remote Status service.
|
||||
|
||||
secure_rpc/ The files in this directory are used to build a version of
|
||||
the RPC library with DES Authentication. See the README
|
||||
file in that directory for more details.
|
||||
|
||||
BUILD INSTRUCTIONS
|
||||
|
||||
Makefiles can be found in all directories except for man. The
|
||||
Makefile in the top directory will cause these others to be invoked
|
||||
(except for in the doc, man and demo directories), in turn building the
|
||||
entire release.
|
||||
|
||||
WARNING! THE DEFAULT INSTALLATION PROCEDURES WILL INSTALL FILES
|
||||
IN /usr/include, /usr/lib, /usr/bin and /etc.
|
||||
|
||||
The master RPC include file, rpc/rpc.h, is used by all programs and
|
||||
routines that use RPC. It includes other RPC and system include files
|
||||
needed by the RPC system. PLEASE NOTE: If your system has NFS, it
|
||||
may have been based on Sun's NFS Source. The include files installed
|
||||
by this package may duplicate include files you will find on your NFS
|
||||
system. The RPCSRC 4.0 include files are upwardly compatible to all
|
||||
NFS Source include files as of the date of this distribution (not
|
||||
including any new definitions or declarations added by your system
|
||||
vendor). HOWEVER: Please read the comments towards the end of
|
||||
rpc/rpc.h regarding rpc/netdb.h. You may need to uncomment the
|
||||
inclusion of that file if the structures it defines are already
|
||||
defined by your system's include files.
|
||||
|
||||
After making any compiler fixes that are needed (see below), at
|
||||
the top directory, type:
|
||||
|
||||
make install
|
||||
|
||||
For all installations, the Makefile macro DESTDIR is prepended to the
|
||||
installation path. It is defined to be null in the Makefiles, so
|
||||
installations are relative to root. (You will probably need root
|
||||
privileges for installing the files under the default path.) To
|
||||
install the files under some other tree (e.g., /usr/local), use the
|
||||
command:
|
||||
|
||||
make install DESTDIR=/usr/local
|
||||
|
||||
This will place the include files in /usr/local/usr/include, the RPC
|
||||
library in /usr/local/usr/lib, rpcgen in /usr/local/usr/bin, and the
|
||||
utilities in /usr/local/etc. You'll have to edit the Makefiles or
|
||||
install the files by hand if you want to do anything other than this
|
||||
kind of relocation of the installation tree.
|
||||
|
||||
The RPC library will be built and installed first. By default it is
|
||||
installed in /usr/lib as "librpclib.a". The directory
|
||||
/usr/include/rpc will also be created, and several header files will
|
||||
be installed there. ALL RPC SERVICES INCLUDE THESE HEADER FILES.
|
||||
|
||||
The programs in etc/ link in routines from librpclib.a. If you change
|
||||
where it is installed, be sure to edit etc/'s Makefile to reflect this.
|
||||
These programs are installed in /etc. PORTMAP MUST BE RUNNING ON
|
||||
YOUR SYSTEM BEFORE YOU START ANY OTHER RPC SERVICE.
|
||||
|
||||
rpcgen is installed in /usr/bin. This program is required to build
|
||||
the demonstration services in demo and the rstat client and server in
|
||||
rpcsvc/.
|
||||
|
||||
The rpcsvc/ directory will install its files in the directory
|
||||
/usr/include/rpcsvc. The Remote Status service (rstat_svc) will be
|
||||
compiled and installed in /etc. If you wish to make this service
|
||||
available, you should either start this service when needed or have
|
||||
it started at boot time by invoking it in your /etc/rc.local script.
|
||||
(Be sure that portmap is started first!) Sun has modified its
|
||||
version of inetd to automatically start RPC services. (Use "make
|
||||
LIB=" when building rstat on a Sun Workstation.) The Remote Status
|
||||
client (rstat) will be installed in /usr/bin. This program queries
|
||||
the rstat_svc on a remote host and prints a system status summary
|
||||
similar to the one printed by "uptime".
|
||||
|
||||
The documentation is not built during the "make install" command.
|
||||
Typing "make" in the doc directory will cause all of the manuals to
|
||||
be formatted using nroff into a single file. We have had a report
|
||||
that certain "troff" equivalents have trouble processing the full
|
||||
manual. If you have trouble, try building the manuals individually
|
||||
(see the Makefile).
|
||||
|
||||
The demonstration services in the demo directory are not built by the
|
||||
top-level "make install" command. To build these, cd to the demo
|
||||
directory and enter "make". The three services will be built.
|
||||
RPCGEN MUST BE INSTALLED in a path that make can find. To run the
|
||||
services, start the portmap program as root and invoke the service
|
||||
(you probably will want to put it in the background). rpcinfo can be
|
||||
used to check that the service succeeded in getting registered with
|
||||
portmap, and to ping the service (see rpcinfo's man page). You can
|
||||
then use the corresponding client program to exercise the service.
|
||||
To build these services on a Sun workstation, you must prevent the
|
||||
Makefile from trying to link the RPC library (as these routines are
|
||||
already a part of Sun's libc). Use: "make LIB=".
|
||||
|
||||
BUGFIX FOR 4.3BSD COMPILER
|
||||
|
||||
The use of a 'void *' declaration for one of the arguments in
|
||||
the reply_proc() procedure in etc/rpcinfo.c will trigger a bug
|
||||
in the 4.3BSD compiler. The bug is fixed by the following change to
|
||||
the compiler file mip/manifest.h:
|
||||
|
||||
*** manifest.h.r1.1 Thu Apr 30 13:52:25 1987
|
||||
--- manifest.h.r1.2 Mon Nov 23 18:58:17 1987
|
||||
***************
|
||||
*** 21,27 ****
|
||||
/*
|
||||
* Bogus type values
|
||||
*/
|
||||
! #define TNULL PTR /* pointer to UNDEF */
|
||||
#define TVOID FTN /* function returning UNDEF (for void) */
|
||||
|
||||
/*
|
||||
--- 21,27 ----
|
||||
/*
|
||||
* Bogus type values
|
||||
*/
|
||||
! #define TNULL INCREF(MOETY) /* pointer to MOETY -- impossible type */
|
||||
#define TVOID FTN /* function returning UNDEF (for void) */
|
||||
|
||||
/*
|
||||
|
||||
If you cannot fix your compiler, change the declaration in reply_proc()
|
||||
from 'void *' to 'char *'.
|
||||
|
||||
BUGFIX FOR 4.2BSD COMPILER
|
||||
|
||||
Unpatched 4.2BSD compilers complain about valid C. You can make old
|
||||
compilers happy by changing some voids to ints. However, the fix to
|
||||
the 4.2 VAX compiler is as follows (to mip/trees.c):
|
||||
|
||||
*** trees.c.r1.1 Mon May 11 13:47:58 1987
|
||||
--- trees.c.r1.2 Wed Jul 2 18:28:52 1986
|
||||
***************
|
||||
*** 1247,1253 ****
|
||||
if(o==CAST && mt1==0)return(TYPL+TYMATCH);
|
||||
if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
|
||||
else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
|
||||
! else if( mt12 == 0 ) break;
|
||||
else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
|
||||
else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
|
||||
break;
|
||||
--- 1261,1269 ----
|
||||
if(o==CAST && mt1==0)return(TYPL+TYMATCH);
|
||||
if( mt12 & MDBI ) return( TYPL+LVAL+TYMATCH );
|
||||
else if( (mt1&MENU)||(mt2&MENU) ) return( LVAL+NCVT+TYPL+PTMATCH+PUN );
|
||||
! /* if right is TVOID and looks like a CALL, is not ok */
|
||||
! else if (mt2 == 0 && (p->in.right->in.op == CALL || p->in.right->in.op == UNARY CALL))
|
||||
! break;
|
||||
else if( mt1 & MPTR ) return( LVAL+PTMATCH+PUN );
|
||||
else if( mt12 & MPTI ) return( TYPL+LVAL+TYMATCH+PUN );
|
||||
break;
|
||||
|
||||
WHAT'S NEW IN THIS RELEASE: RPCSRC 4.0
|
||||
|
||||
The previous release was RPCSRC 3.9. As with all previous releases,
|
||||
this release is based directly on files from Sun Microsystem's
|
||||
implementation.
|
||||
|
||||
Upgrade from RPCSRC 3.9
|
||||
|
||||
1) RPCSRC 4.0 upgrades RPCSRC 3.9. Improvements from SunOS 4.0 have
|
||||
been integrated into this release.
|
||||
|
||||
Secure RPC (in the secure_rpc/ directory)
|
||||
|
||||
2) DES Authentication routines and programs are provided.
|
||||
3) A new manual, "Secure NFS" is provided, which describes Secure RPC
|
||||
and Secure NFS.
|
||||
4) Skeleton routines and manual pages are provided which describe the
|
||||
DES encryption procedures required by Secure RPC. HOWEVER, NO DES
|
||||
ROUTINE IS PROVIDED.
|
||||
|
||||
New Functionality
|
||||
|
||||
5) rpcinfo can now be used to de-register services from the portmapper
|
||||
which may have terminated abnormally.
|
||||
6) A new client, rstat, is provided which queries the rstat_svc and
|
||||
prints a status line similar to the one displayed by "uptime".
|
||||
@@ -0,0 +1,59 @@
|
||||
/* $NetBSD: __rpc_getxid.c,v 1.3 2003/09/13 21:27:46 itojun Exp $ */
|
||||
/* $OpenBSD: ip_id.c,v 1.6 2002/03/15 18:19:52 millert Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2003 WIDE Project.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
* 3. Neither the name of the project 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 PROJECT 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 PROJECT 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/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: __rpc_getxid.c,v 1.3 2003/09/13 21:27:46 itojun Exp $");
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <randomid.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include "rpc_internal.h"
|
||||
|
||||
u_int32_t
|
||||
__rpc_getxid(void)
|
||||
{
|
||||
static randomid_t ctx = NULL;
|
||||
|
||||
if (!ctx) {
|
||||
ctx = randomid_new(32, RANDOMID_TIMEO_DEFAULT);
|
||||
if (!ctx)
|
||||
abort();
|
||||
}
|
||||
|
||||
return randomid(ctx);
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
/* $NetBSD: auth_none.c,v 1.14 2001/01/16 15:46:52 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: auth_none.c,v 1.14 2001/01/16 15:46:52 lukem Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* auth_none.c
|
||||
* Creates a client authentication handle for passing "null"
|
||||
* credentials and verifiers to remote systems.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/auth.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(authnone_create,_authnone_create)
|
||||
#endif
|
||||
|
||||
#define MAX_MARSHAL_SIZE 20
|
||||
|
||||
/*
|
||||
* Authenticator operations routines
|
||||
*/
|
||||
|
||||
static bool_t authnone_marshal __P((AUTH *, XDR *));
|
||||
static void authnone_verf __P((AUTH *));
|
||||
static bool_t authnone_validate __P((AUTH *, struct opaque_auth *));
|
||||
static bool_t authnone_refresh __P((AUTH *));
|
||||
static void authnone_destroy __P((AUTH *));
|
||||
|
||||
static const struct auth_ops ops = {
|
||||
authnone_verf,
|
||||
authnone_marshal,
|
||||
authnone_validate,
|
||||
authnone_refresh,
|
||||
authnone_destroy
|
||||
};
|
||||
|
||||
static struct authnone_private {
|
||||
AUTH no_client;
|
||||
char marshalled_client[MAX_MARSHAL_SIZE];
|
||||
u_int mcnt;
|
||||
} *authnone_private;
|
||||
|
||||
AUTH *
|
||||
authnone_create()
|
||||
{
|
||||
struct authnone_private *ap = authnone_private;
|
||||
XDR xdr_stream;
|
||||
XDR *xdrs;
|
||||
|
||||
if (ap == 0) {
|
||||
ap = (struct authnone_private *)calloc(1, sizeof (*ap));
|
||||
if (ap == 0)
|
||||
return (0);
|
||||
authnone_private = ap;
|
||||
}
|
||||
if (!ap->mcnt) {
|
||||
ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
|
||||
ap->no_client.ah_ops = &ops;
|
||||
xdrs = &xdr_stream;
|
||||
xdrmem_create(xdrs, ap->marshalled_client,
|
||||
(u_int)MAX_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);
|
||||
}
|
||||
return (&ap->no_client);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
authnone_marshal(client, xdrs)
|
||||
AUTH *client;
|
||||
XDR *xdrs;
|
||||
{
|
||||
struct authnone_private *ap = authnone_private;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
|
||||
if (ap == 0)
|
||||
return (0);
|
||||
return ((*xdrs->x_ops->x_putbytes)(xdrs,
|
||||
ap->marshalled_client, ap->mcnt));
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
authnone_verf(client)
|
||||
AUTH *client;
|
||||
{
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
authnone_validate(client, auth)
|
||||
AUTH *client;
|
||||
struct opaque_auth *auth;
|
||||
{
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
authnone_refresh(client)
|
||||
AUTH *client;
|
||||
{
|
||||
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
authnone_destroy(client)
|
||||
AUTH *client;
|
||||
{
|
||||
}
|
||||
@@ -0,0 +1,384 @@
|
||||
/* $NetBSD: auth_unix.c,v 1.22 2009/01/11 02:46:29 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: auth_unix.c,v 1.22 2009/01/11 02:46:29 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* auth_unix.c, Implements UNIX style authentication parameters.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* The system is very weak. The client uses no encryption for it's
|
||||
* credentials and only sends null verifiers. The server sends backs
|
||||
* null verifiers or optionally a verifier that suggests a new short hand
|
||||
* for the credentials.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/auth.h>
|
||||
#include <rpc/auth_unix.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(authunix_create,_authunix_create)
|
||||
__weak_alias(authunix_create_default,_authunix_create_default)
|
||||
#endif
|
||||
|
||||
|
||||
/* auth_unix.c */
|
||||
static void authunix_nextverf __P((AUTH *));
|
||||
static bool_t authunix_marshal __P((AUTH *, XDR *));
|
||||
static bool_t authunix_validate __P((AUTH *, struct opaque_auth *));
|
||||
static bool_t authunix_refresh __P((AUTH *));
|
||||
static void authunix_destroy __P((AUTH *));
|
||||
static void marshal_new_auth __P((AUTH *));
|
||||
static const struct auth_ops *authunix_ops __P((void));
|
||||
|
||||
/*
|
||||
* 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)
|
||||
|
||||
/*
|
||||
* Create a unix style authenticator.
|
||||
* Returns an auth handle with the given stuff in it.
|
||||
*/
|
||||
AUTH *
|
||||
authunix_create(machname, uid, gid, len, aup_gids)
|
||||
char *machname;
|
||||
int uid;
|
||||
int gid;
|
||||
int len;
|
||||
int *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
|
||||
*/
|
||||
au = NULL;
|
||||
auth = mem_alloc(sizeof(*auth));
|
||||
#ifndef KERNEL
|
||||
if (auth == NULL) {
|
||||
warnx("authunix_create: out of memory");
|
||||
goto cleanup_authunix_create;
|
||||
}
|
||||
#endif
|
||||
au = mem_alloc(sizeof(*au));
|
||||
#ifndef KERNEL
|
||||
if (au == NULL) {
|
||||
warnx("authunix_create: out of memory");
|
||||
goto cleanup_authunix_create;
|
||||
}
|
||||
#endif
|
||||
auth->ah_ops = authunix_ops();
|
||||
auth->ah_private = au;
|
||||
auth->ah_verf = au->au_shcred = _null_auth;
|
||||
au->au_shfaults = 0;
|
||||
au->au_origcred.oa_base = NULL;
|
||||
|
||||
/*
|
||||
* fill in param struct from the given params
|
||||
*/
|
||||
(void)gettimeofday(&now, NULL);
|
||||
aup.aup_time = (u_long)now.tv_sec; /* XXX: truncate on 32 bit */
|
||||
aup.aup_machname = machname;
|
||||
aup.aup_uid = uid;
|
||||
aup.aup_gid = gid;
|
||||
aup.aup_len = (u_int)len;
|
||||
aup.aup_gids = aup_gids;
|
||||
|
||||
/*
|
||||
* Serialize the parameters into origcred
|
||||
*/
|
||||
xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
|
||||
if (! xdr_authunix_parms(&xdrs, &aup))
|
||||
abort();
|
||||
au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
|
||||
au->au_origcred.oa_flavor = AUTH_UNIX;
|
||||
#ifdef KERNEL
|
||||
au->au_origcred.oa_base = mem_alloc((size_t)len);
|
||||
#else
|
||||
if ((au->au_origcred.oa_base = mem_alloc((size_t)len)) == NULL) {
|
||||
warnx("authunix_create: out of memory");
|
||||
goto cleanup_authunix_create;
|
||||
}
|
||||
#endif
|
||||
memmove(au->au_origcred.oa_base, mymem, (size_t)len);
|
||||
|
||||
/*
|
||||
* set auth handle to reflect new cred.
|
||||
*/
|
||||
auth->ah_cred = au->au_origcred;
|
||||
marshal_new_auth(auth);
|
||||
return (auth);
|
||||
#ifndef KERNEL
|
||||
cleanup_authunix_create:
|
||||
if (auth)
|
||||
mem_free(auth, sizeof(*auth));
|
||||
if (au) {
|
||||
if (au->au_origcred.oa_base)
|
||||
mem_free(au->au_origcred.oa_base, (u_int)len);
|
||||
mem_free(au, sizeof(*au));
|
||||
}
|
||||
return (NULL);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns an auth handle with parameters determined by doing lots of
|
||||
* syscalls.
|
||||
*/
|
||||
AUTH *
|
||||
authunix_create_default()
|
||||
{
|
||||
int len;
|
||||
char machname[MAXHOSTNAMELEN + 1];
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
gid_t gids[NGRPS];
|
||||
|
||||
if (gethostname(machname, sizeof machname) == -1)
|
||||
abort();
|
||||
machname[sizeof(machname) - 1] = 0;
|
||||
uid = geteuid();
|
||||
gid = getegid();
|
||||
if ((len = getgroups(NGRPS, gids)) < 0)
|
||||
abort();
|
||||
/* XXX: interface problem; those should all have been unsigned */
|
||||
return (authunix_create(machname, (int)uid, (int)gid, len,
|
||||
(int *)gids));
|
||||
}
|
||||
|
||||
/*
|
||||
* authunix operations
|
||||
*/
|
||||
|
||||
/* ARGSUSED */
|
||||
static void
|
||||
authunix_nextverf(auth)
|
||||
AUTH *auth;
|
||||
{
|
||||
/* no action necessary */
|
||||
}
|
||||
|
||||
static bool_t
|
||||
authunix_marshal(auth, xdrs)
|
||||
AUTH *auth;
|
||||
XDR *xdrs;
|
||||
{
|
||||
struct audata *au;
|
||||
|
||||
_DIAGASSERT(auth != NULL);
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
|
||||
au = AUTH_PRIVATE(auth);
|
||||
return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
|
||||
}
|
||||
|
||||
static bool_t
|
||||
authunix_validate(auth, verf)
|
||||
AUTH *auth;
|
||||
struct opaque_auth *verf;
|
||||
{
|
||||
struct audata *au;
|
||||
XDR xdrs;
|
||||
|
||||
_DIAGASSERT(auth != NULL);
|
||||
_DIAGASSERT(verf != NULL);
|
||||
|
||||
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 *auth;
|
||||
{
|
||||
struct audata *au = AUTH_PRIVATE(auth);
|
||||
struct authunix_parms aup;
|
||||
struct timeval now;
|
||||
XDR xdrs;
|
||||
int stat;
|
||||
|
||||
_DIAGASSERT(auth != NULL);
|
||||
|
||||
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 = 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, NULL);
|
||||
aup.aup_time = (u_long)now.tv_sec; /* XXX: truncate on 32 bit */
|
||||
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 *auth;
|
||||
{
|
||||
struct audata *au;
|
||||
|
||||
_DIAGASSERT(auth != NULL);
|
||||
|
||||
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(auth, sizeof(*auth));
|
||||
}
|
||||
|
||||
/*
|
||||
* Marshals (pre-serializes) an auth struct.
|
||||
* sets private data, au_marshed and au_mpos
|
||||
*/
|
||||
static void
|
||||
marshal_new_auth(auth)
|
||||
AUTH *auth;
|
||||
{
|
||||
XDR xdr_stream;
|
||||
XDR *xdrs = &xdr_stream;
|
||||
struct audata *au;
|
||||
|
||||
_DIAGASSERT(auth != NULL);
|
||||
|
||||
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))))
|
||||
warnx("auth_none.c - Fatal marshalling problem");
|
||||
else
|
||||
au->au_mpos = XDR_GETPOS(xdrs);
|
||||
XDR_DESTROY(xdrs);
|
||||
}
|
||||
|
||||
static const struct auth_ops *
|
||||
authunix_ops()
|
||||
{
|
||||
static struct auth_ops ops;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
#endif
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops */
|
||||
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.ah_nextverf == NULL) {
|
||||
ops.ah_nextverf = authunix_nextverf;
|
||||
ops.ah_marshal = authunix_marshal;
|
||||
ops.ah_validate = authunix_validate;
|
||||
ops.ah_refresh = authunix_refresh;
|
||||
ops.ah_destroy = authunix_destroy;
|
||||
}
|
||||
mutex_unlock(&ops_lock);
|
||||
return (&ops);
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/* $NetBSD: authunix_prot.c,v 1.13 2006/05/11 17:11:57 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: authunix_prot.c,v 1.13 2006/05/11 17:11:57 mrg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* authunix_prot.c
|
||||
* XDR for UNIX style authentication parameters for RPC
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/auth.h>
|
||||
#include <rpc/auth_unix.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_authunix_parms,_xdr_authunix_parms)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XDR for unix authentication parameters.
|
||||
*/
|
||||
bool_t
|
||||
xdr_authunix_parms(xdrs, p)
|
||||
XDR *xdrs;
|
||||
struct authunix_parms *p;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(p != NULL);
|
||||
|
||||
if (xdr_u_long(xdrs, &(p->aup_time))
|
||||
&& xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
|
||||
&& xdr_int(xdrs, &(p->aup_uid))
|
||||
&& xdr_int(xdrs, &(p->aup_gid))
|
||||
&& xdr_array(xdrs, (char **)(void *)&(p->aup_gids),
|
||||
&(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) {
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
|
||||
.\" $NetBSD: bindresvport.3,v 1.13 2007/01/27 07:58:47 cbiere Exp $
|
||||
.\"
|
||||
.Dd January 27, 2007
|
||||
.Dt BINDRESVPORT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm bindresvport ,
|
||||
.Nm bindresvport_sa
|
||||
.Nd bind a socket to a reserved privileged IP port
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/types.h
|
||||
.In rpc/rpc.h
|
||||
.Ft int
|
||||
.Fn bindresvport "int sd" "struct sockaddr_in *sin"
|
||||
.Ft int
|
||||
.Fn bindresvport_sa "int sd" "struct sockaddr *sa"
|
||||
.Sh DESCRIPTION
|
||||
.Fn bindresvport
|
||||
and
|
||||
.Fn bindresvport_sa
|
||||
are used to bind a socket descriptor to a reserved privileged
|
||||
.Tn IP
|
||||
port, that is, a
|
||||
port number in the range 0-1023.
|
||||
The routine returns 0 if it is successful,
|
||||
otherwise -1 is returned and
|
||||
.Va errno
|
||||
set to reflect the cause of the error.
|
||||
.Pp
|
||||
If
|
||||
.Fa sin
|
||||
is a pointer to a
|
||||
.Ft "struct sockaddr_in"
|
||||
then the appropriate fields in the structure should be defined.
|
||||
Note that
|
||||
.Fa sin-\*[Gt]sin_family
|
||||
must be initialized to the address family of the socket, passed by
|
||||
.Fa sd .
|
||||
If
|
||||
.Fa sin-\*[Gt]sin_port
|
||||
is
|
||||
.Sq 0
|
||||
then a port (in the range 600-1023) will be
|
||||
chosen, and if
|
||||
.Xr bind 2
|
||||
is successful, the
|
||||
.Fa sin-\*[Gt]sin_port
|
||||
will be updated to contain the allocated port.
|
||||
.Pp
|
||||
If
|
||||
.Fa sin
|
||||
is the
|
||||
.Dv NULL
|
||||
pointer,
|
||||
a port will be allocated (as above).
|
||||
However, there is no way for
|
||||
.Fn bindresvport
|
||||
to return the allocated port in this case.
|
||||
.Xr getsockname 2
|
||||
can be used to determine the assigned port.
|
||||
.Pp
|
||||
Only root can bind to a privileged port; this call will fail for any
|
||||
other users.
|
||||
.Pp
|
||||
Function prototype of
|
||||
.Fn bindresvport
|
||||
is biased to
|
||||
.Dv AF_INET
|
||||
socket.
|
||||
.Fn bindresvport_sa
|
||||
acts exactly the same, with more neutral function prototype.
|
||||
Note that both functions behave exactly the same, and
|
||||
both support
|
||||
.Dv AF_INET6
|
||||
sockets as well as
|
||||
.Dv AF_INET
|
||||
sockets.
|
||||
.Sh RETURN VALUES
|
||||
If the bind is successful, a 0 value is returned.
|
||||
A return value of -1 indicates an error, which is
|
||||
further specified in the global
|
||||
.Va errno .
|
||||
.Sh ERRORS
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EPFNOSUPPORT
|
||||
If second argument was supplied,
|
||||
and address family did not match between arguments.
|
||||
.El
|
||||
.Pp
|
||||
.Fn bindresvport
|
||||
may also fail and set
|
||||
.Va errno
|
||||
for any of the errors specified for the calls
|
||||
.Xr bind 2 ,
|
||||
.Xr getsockopt 2 ,
|
||||
or
|
||||
.Xr setsockopt 2 .
|
||||
.Sh SEE ALSO
|
||||
.Xr bind 2 ,
|
||||
.Xr getsockname 2 ,
|
||||
.Xr getsockopt 2 ,
|
||||
.Xr setsockopt 2 ,
|
||||
.Xr ip 4
|
||||
@@ -0,0 +1,164 @@
|
||||
/* $NetBSD: bindresvport.c,v 1.21 2003/01/18 11:29:03 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)bindresvport.c 1.8 88/02/08 SMI";
|
||||
static char *sccsid = "@(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: bindresvport.c,v 1.21 2003/01/18 11:29:03 thorpej Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1987 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(bindresvport,_bindresvport)
|
||||
__weak_alias(bindresvport_sa,_bindresvport_sa)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Bind a socket to a privileged IP port
|
||||
*/
|
||||
int
|
||||
bindresvport(sd, brsin)
|
||||
int sd;
|
||||
struct sockaddr_in *brsin;
|
||||
{
|
||||
return bindresvport_sa(sd, (struct sockaddr *)(void *)brsin);
|
||||
}
|
||||
|
||||
/*
|
||||
* Bind a socket to a privileged IP port
|
||||
*/
|
||||
int
|
||||
bindresvport_sa(sd, sa)
|
||||
int sd;
|
||||
struct sockaddr *sa;
|
||||
{
|
||||
int error, old;
|
||||
struct sockaddr_storage myaddr;
|
||||
struct sockaddr_in *brsin;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *brsin6;
|
||||
#endif
|
||||
int proto, portrange, portlow;
|
||||
u_int16_t *portp;
|
||||
socklen_t salen;
|
||||
int af;
|
||||
|
||||
if (sa == NULL) {
|
||||
salen = sizeof(myaddr);
|
||||
sa = (struct sockaddr *)(void *)&myaddr;
|
||||
|
||||
if (getsockname(sd, sa, &salen) == -1)
|
||||
return -1; /* errno is correctly set */
|
||||
|
||||
af = sa->sa_family;
|
||||
memset(sa, 0, salen);
|
||||
} else
|
||||
af = sa->sa_family;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
proto = IPPROTO_IP;
|
||||
portrange = IP_PORTRANGE;
|
||||
portlow = IP_PORTRANGE_LOW;
|
||||
brsin = (struct sockaddr_in *)(void *)sa;
|
||||
salen = sizeof(struct sockaddr_in);
|
||||
portp = &brsin->sin_port;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
proto = IPPROTO_IPV6;
|
||||
portrange = IPV6_PORTRANGE;
|
||||
portlow = IPV6_PORTRANGE_LOW;
|
||||
brsin6 = (struct sockaddr_in6 *)(void *)sa;
|
||||
salen = sizeof(struct sockaddr_in6);
|
||||
portp = &brsin6->sin6_port;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
errno = EPFNOSUPPORT;
|
||||
return (-1);
|
||||
}
|
||||
sa->sa_family = af;
|
||||
sa->sa_len = salen;
|
||||
|
||||
if (*portp == 0) {
|
||||
socklen_t oldlen = sizeof(old);
|
||||
|
||||
error = getsockopt(sd, proto, portrange, &old, &oldlen);
|
||||
if (error < 0)
|
||||
return (error);
|
||||
error = setsockopt(sd, proto, portrange, &portlow,
|
||||
sizeof(portlow));
|
||||
if (error < 0)
|
||||
return (error);
|
||||
}
|
||||
|
||||
error = bind(sd, sa, salen);
|
||||
|
||||
if (*portp == 0) {
|
||||
int saved_errno = errno;
|
||||
|
||||
if (error < 0) {
|
||||
if (setsockopt(sd, proto, portrange, &old,
|
||||
sizeof(old)) < 0)
|
||||
errno = saved_errno;
|
||||
return (error);
|
||||
}
|
||||
|
||||
if (sa != (struct sockaddr *)(void *)&myaddr) {
|
||||
/* What did the kernel assign? */
|
||||
if (getsockname(sd, sa, &salen) < 0)
|
||||
errno = saved_errno;
|
||||
return (error);
|
||||
}
|
||||
}
|
||||
return (error);
|
||||
}
|
||||
@@ -0,0 +1,686 @@
|
||||
/* $NetBSD: clnt_bcast.c,v 1.22 2010/03/07 23:49:14 dholland Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)clnt_bcast.c 1.18 94/05/03 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)clnt_bcast.c 1.15 89/04/21 Copyr 1988 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_bcast.c,v 1.22 2010/03/07 23:49:14 dholland Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clnt_bcast.c
|
||||
* Client interface to broadcast service.
|
||||
*
|
||||
* Copyright (C) 1988, Sun Microsystems, Inc.
|
||||
*
|
||||
* The following is kludged-up support for simple rpc broadcasts.
|
||||
* Someday a large, complicated system will replace these routines.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/queue.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/poll.h>
|
||||
#include <rpc/rpc.h>
|
||||
#ifdef PORTMAP
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
#include <rpc/pmap_rmt.h>
|
||||
#endif
|
||||
#include <rpc/nettype.h>
|
||||
#include <arpa/inet.h>
|
||||
#ifdef RPC_DEBUG
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
#include <err.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#define MAXBCAST 20 /* Max no of broadcasting transports */
|
||||
#define INITTIME 4000 /* Time to wait initially */
|
||||
#define WAITTIME 8000 /* Maximum time to wait */
|
||||
|
||||
/*
|
||||
* If nettype is NULL, it broadcasts on all the available
|
||||
* datagram_n transports. May potentially lead to broadacst storms
|
||||
* and hence should be used with caution, care and courage.
|
||||
*
|
||||
* The current parameter xdr packet size is limited by the max tsdu
|
||||
* size of the transport. If the max tsdu size of any transport is
|
||||
* smaller than the parameter xdr packet, then broadcast is not
|
||||
* sent on that transport.
|
||||
*
|
||||
* Also, the packet size should be less the packet size of
|
||||
* the data link layer (for ethernet it is 1400 bytes). There is
|
||||
* no easy way to find out the max size of the data link layer and
|
||||
* we are assuming that the args would be smaller than that.
|
||||
*
|
||||
* The result size has to be smaller than the transport tsdu size.
|
||||
*
|
||||
* If PORTMAP has been defined, we send two packets for UDP, one for
|
||||
* rpcbind and one for portmap. For those machines which support
|
||||
* both rpcbind and portmap, it will cause them to reply twice, and
|
||||
* also here it will get two responses ... inefficient and clumsy.
|
||||
*/
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(rpc_broadcast_exp,_rpc_broadcast_exp)
|
||||
__weak_alias(rpc_broadcast,_rpc_broadcast)
|
||||
#endif
|
||||
|
||||
struct broadif {
|
||||
int index;
|
||||
struct sockaddr_storage broadaddr;
|
||||
TAILQ_ENTRY(broadif) link;
|
||||
};
|
||||
|
||||
typedef TAILQ_HEAD(, broadif) broadlist_t;
|
||||
|
||||
int __rpc_getbroadifs __P((int, int, int, broadlist_t *));
|
||||
void __rpc_freebroadifs __P((broadlist_t *));
|
||||
int __rpc_broadenable __P((int, int, struct broadif *));
|
||||
|
||||
int __rpc_lowvers = 0;
|
||||
|
||||
int
|
||||
__rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list)
|
||||
{
|
||||
int count = 0;
|
||||
struct broadif *bip;
|
||||
struct ifaddrs *ifap, *ifp;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
struct sockaddr_in *gbsin;
|
||||
struct addrinfo hints, *res;
|
||||
|
||||
_DIAGASSERT(list != NULL);
|
||||
|
||||
if (getifaddrs(&ifp) < 0)
|
||||
return 0;
|
||||
|
||||
memset(&hints, 0, sizeof hints);
|
||||
|
||||
hints.ai_family = af;
|
||||
hints.ai_protocol = proto;
|
||||
hints.ai_socktype = socktype;
|
||||
|
||||
if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) {
|
||||
freeifaddrs(ifp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
|
||||
if (ifap->ifa_addr->sa_family != af ||
|
||||
!(ifap->ifa_flags & IFF_UP))
|
||||
continue;
|
||||
bip = malloc(sizeof(*bip));
|
||||
if (bip == NULL)
|
||||
break;
|
||||
bip->index = if_nametoindex(ifap->ifa_name);
|
||||
if (
|
||||
#ifdef INET6
|
||||
af != AF_INET6 &&
|
||||
#endif
|
||||
(ifap->ifa_flags & IFF_BROADCAST) &&
|
||||
ifap->ifa_broadaddr) {
|
||||
memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
|
||||
(size_t)ifap->ifa_broadaddr->sa_len);
|
||||
gbsin = (struct sockaddr_in *)(void *)&bip->broadaddr;
|
||||
gbsin->sin_port =
|
||||
((struct sockaddr_in *)
|
||||
(void *)res->ai_addr)->sin_port;
|
||||
} else
|
||||
#ifdef INET6
|
||||
if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) {
|
||||
sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr;
|
||||
inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr);
|
||||
sin6->sin6_family = af;
|
||||
sin6->sin6_len = sizeof *sin6;
|
||||
sin6->sin6_port =
|
||||
((struct sockaddr_in6 *)
|
||||
(void *)res->ai_addr)->sin6_port;
|
||||
sin6->sin6_scope_id = bip->index;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
free(bip);
|
||||
continue;
|
||||
}
|
||||
TAILQ_INSERT_TAIL(list, bip, link);
|
||||
count++;
|
||||
}
|
||||
freeifaddrs(ifp);
|
||||
freeaddrinfo(res);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void
|
||||
__rpc_freebroadifs(broadlist_t *list)
|
||||
{
|
||||
struct broadif *bip, *next;
|
||||
|
||||
_DIAGASSERT(list != NULL);
|
||||
|
||||
bip = TAILQ_FIRST(list);
|
||||
|
||||
while (bip != NULL) {
|
||||
next = TAILQ_NEXT(bip, link);
|
||||
free(bip);
|
||||
bip = next;
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
/*ARGSUSED*/
|
||||
__rpc_broadenable(int af, int s, struct broadif *bip)
|
||||
{
|
||||
int o = 1;
|
||||
|
||||
#if 0
|
||||
_DIAGASSERT(bip != NULL);
|
||||
|
||||
if (af == AF_INET6) {
|
||||
fprintf(stderr, "set v6 multicast if to %d\n", bip->index);
|
||||
if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index,
|
||||
sizeof bip->index) < 0)
|
||||
return -1;
|
||||
} else
|
||||
#endif
|
||||
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
enum clnt_stat
|
||||
rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
|
||||
eachresult, inittime, waittime, nettype)
|
||||
rpcprog_t prog; /* program number */
|
||||
rpcvers_t vers; /* version number */
|
||||
rpcproc_t proc; /* procedure number */
|
||||
xdrproc_t xargs; /* xdr routine for args */
|
||||
const char * argsp; /* pointer to args */
|
||||
xdrproc_t xresults; /* xdr routine for results */
|
||||
caddr_t resultsp; /* pointer to results */
|
||||
resultproc_t eachresult; /* call with each result obtained */
|
||||
int inittime; /* how long to wait initially */
|
||||
int waittime; /* maximum time to wait */
|
||||
const char *nettype; /* transport type */
|
||||
{
|
||||
enum clnt_stat stat = RPC_SUCCESS; /* Return status */
|
||||
XDR xdr_stream; /* XDR stream */
|
||||
XDR *xdrs = &xdr_stream;
|
||||
struct rpc_msg msg; /* RPC message */
|
||||
char *outbuf = NULL; /* Broadcast msg buffer */
|
||||
char *inbuf = NULL; /* Reply buf */
|
||||
ssize_t inlen;
|
||||
u_int maxbufsize = 0;
|
||||
AUTH *sys_auth = authunix_create_default();
|
||||
size_t i;
|
||||
void *handle;
|
||||
char uaddress[1024]; /* A self imposed limit */
|
||||
char *uaddrp = uaddress;
|
||||
int pmap_reply_flag; /* reply recvd from PORTMAP */
|
||||
/* An array of all the suitable broadcast transports */
|
||||
struct {
|
||||
int fd; /* File descriptor */
|
||||
int af;
|
||||
int proto;
|
||||
struct netconfig *nconf; /* Netconfig structure */
|
||||
u_int asize; /* Size of the addr buf */
|
||||
u_int dsize; /* Size of the data buf */
|
||||
struct sockaddr_storage raddr; /* Remote address */
|
||||
broadlist_t nal;
|
||||
} fdlist[MAXBCAST];
|
||||
struct pollfd pfd[MAXBCAST];
|
||||
size_t fdlistno = 0;
|
||||
struct r_rpcb_rmtcallargs barg; /* Remote arguments */
|
||||
struct r_rpcb_rmtcallres bres; /* Remote results */
|
||||
size_t outlen;
|
||||
struct netconfig *nconf;
|
||||
int msec;
|
||||
int pollretval;
|
||||
int fds_found;
|
||||
struct timespec ts;
|
||||
|
||||
#ifdef PORTMAP
|
||||
size_t outlen_pmap = 0;
|
||||
u_long port; /* Remote port number */
|
||||
int pmap_flag = 0; /* UDP exists ? */
|
||||
char *outbuf_pmap = NULL;
|
||||
struct rmtcallargs barg_pmap; /* Remote arguments */
|
||||
struct rmtcallres bres_pmap; /* Remote results */
|
||||
u_int udpbufsz = 0;
|
||||
#endif /* PORTMAP */
|
||||
|
||||
if (sys_auth == NULL) {
|
||||
return (RPC_SYSTEMERROR);
|
||||
}
|
||||
/*
|
||||
* initialization: create a fd, a broadcast address, and send the
|
||||
* request on the broadcast transport.
|
||||
* Listen on all of them and on replies, call the user supplied
|
||||
* function.
|
||||
*/
|
||||
|
||||
if (nettype == NULL)
|
||||
nettype = "datagram_n";
|
||||
if ((handle = __rpc_setconf(nettype)) == NULL) {
|
||||
AUTH_DESTROY(sys_auth);
|
||||
return (RPC_UNKNOWNPROTO);
|
||||
}
|
||||
while ((nconf = __rpc_getconf(handle)) != NULL) {
|
||||
int fd;
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
continue;
|
||||
if (fdlistno >= MAXBCAST)
|
||||
break; /* No more slots available */
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si))
|
||||
continue;
|
||||
|
||||
TAILQ_INIT(&fdlist[fdlistno].nal);
|
||||
if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype,
|
||||
&fdlist[fdlistno].nal) == 0)
|
||||
continue;
|
||||
|
||||
fd = socket(si.si_af, si.si_socktype, si.si_proto);
|
||||
if (fd < 0) {
|
||||
stat = RPC_CANTSEND;
|
||||
continue;
|
||||
}
|
||||
fdlist[fdlistno].af = si.si_af;
|
||||
fdlist[fdlistno].proto = si.si_proto;
|
||||
fdlist[fdlistno].fd = fd;
|
||||
fdlist[fdlistno].nconf = nconf;
|
||||
fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af);
|
||||
pfd[fdlistno].events = POLLIN | POLLPRI |
|
||||
POLLRDNORM | POLLRDBAND;
|
||||
pfd[fdlistno].fd = fdlist[fdlistno].fd = fd;
|
||||
fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto,
|
||||
0);
|
||||
|
||||
if (maxbufsize <= fdlist[fdlistno].dsize)
|
||||
maxbufsize = fdlist[fdlistno].dsize;
|
||||
|
||||
#ifdef PORTMAP
|
||||
if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) {
|
||||
udpbufsz = fdlist[fdlistno].dsize;
|
||||
if ((outbuf_pmap = malloc(udpbufsz)) == NULL) {
|
||||
close(fd);
|
||||
stat = RPC_SYSTEMERROR;
|
||||
goto done_broad;
|
||||
}
|
||||
pmap_flag = 1;
|
||||
}
|
||||
#endif
|
||||
fdlistno++;
|
||||
}
|
||||
|
||||
if (fdlistno == 0) {
|
||||
if (stat == RPC_SUCCESS)
|
||||
stat = RPC_UNKNOWNPROTO;
|
||||
goto done_broad;
|
||||
}
|
||||
if (maxbufsize == 0) {
|
||||
if (stat == RPC_SUCCESS)
|
||||
stat = RPC_CANTSEND;
|
||||
goto done_broad;
|
||||
}
|
||||
inbuf = malloc(maxbufsize);
|
||||
outbuf = malloc(maxbufsize);
|
||||
if ((inbuf == NULL) || (outbuf == NULL)) {
|
||||
stat = RPC_SYSTEMERROR;
|
||||
goto done_broad;
|
||||
}
|
||||
|
||||
/* Serialize all the arguments which have to be sent */
|
||||
msg.rm_xid = __RPC_GETXID();
|
||||
msg.rm_direction = CALL;
|
||||
msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
|
||||
msg.rm_call.cb_prog = RPCBPROG;
|
||||
msg.rm_call.cb_vers = RPCBVERS;
|
||||
msg.rm_call.cb_proc = RPCBPROC_CALLIT;
|
||||
barg.prog = prog;
|
||||
barg.vers = vers;
|
||||
barg.proc = proc;
|
||||
barg.args.args_val = argsp;
|
||||
barg.xdr_args = xargs;
|
||||
bres.addr = uaddrp;
|
||||
bres.results.results_val = resultsp;
|
||||
bres.xdr_res = xresults;
|
||||
msg.rm_call.cb_cred = sys_auth->ah_cred;
|
||||
msg.rm_call.cb_verf = sys_auth->ah_verf;
|
||||
xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE);
|
||||
if ((!xdr_callmsg(xdrs, &msg)) ||
|
||||
(!xdr_rpcb_rmtcallargs(xdrs,
|
||||
(struct rpcb_rmtcallargs *)(void *)&barg))) {
|
||||
stat = RPC_CANTENCODEARGS;
|
||||
goto done_broad;
|
||||
}
|
||||
outlen = xdr_getpos(xdrs);
|
||||
xdr_destroy(xdrs);
|
||||
|
||||
#ifdef PORTMAP
|
||||
/* Prepare the packet for version 2 PORTMAP */
|
||||
if (pmap_flag) {
|
||||
msg.rm_xid++; /* One way to distinguish */
|
||||
msg.rm_call.cb_prog = PMAPPROG;
|
||||
msg.rm_call.cb_vers = PMAPVERS;
|
||||
msg.rm_call.cb_proc = PMAPPROC_CALLIT;
|
||||
barg_pmap.prog = prog;
|
||||
barg_pmap.vers = vers;
|
||||
barg_pmap.proc = proc;
|
||||
barg_pmap.args_ptr = argsp;
|
||||
barg_pmap.xdr_args = xargs;
|
||||
bres_pmap.port_ptr = &port;
|
||||
bres_pmap.xdr_results = xresults;
|
||||
bres_pmap.results_ptr = resultsp;
|
||||
xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE);
|
||||
if ((! xdr_callmsg(xdrs, &msg)) ||
|
||||
(! xdr_rmtcall_args(xdrs, &barg_pmap))) {
|
||||
stat = RPC_CANTENCODEARGS;
|
||||
goto done_broad;
|
||||
}
|
||||
outlen_pmap = xdr_getpos(xdrs);
|
||||
xdr_destroy(xdrs);
|
||||
}
|
||||
#endif /* PORTMAP */
|
||||
|
||||
/*
|
||||
* Basic loop: broadcast the packets to transports which
|
||||
* support data packets of size such that one can encode
|
||||
* all the arguments.
|
||||
* Wait a while for response(s).
|
||||
* The response timeout grows larger per iteration.
|
||||
*/
|
||||
for (msec = inittime; msec <= waittime; msec += msec) {
|
||||
struct broadif *bip;
|
||||
|
||||
/* Broadcast all the packets now */
|
||||
for (i = 0; i < fdlistno; i++) {
|
||||
if (fdlist[i].dsize < outlen) {
|
||||
stat = RPC_CANTSEND;
|
||||
continue;
|
||||
}
|
||||
for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL;
|
||||
bip = TAILQ_NEXT(bip, link)) {
|
||||
void *addr;
|
||||
|
||||
addr = &bip->broadaddr;
|
||||
|
||||
__rpc_broadenable(fdlist[i].af, fdlist[i].fd,
|
||||
bip);
|
||||
|
||||
/*
|
||||
* Only use version 3 if lowvers is not set
|
||||
*/
|
||||
|
||||
if (!__rpc_lowvers)
|
||||
if ((size_t)sendto(fdlist[i].fd, outbuf,
|
||||
outlen, 0, (struct sockaddr*)addr,
|
||||
(size_t)fdlist[i].asize) !=
|
||||
outlen) {
|
||||
warn("clnt_bcast: cannot send"
|
||||
" broadcast packet");
|
||||
stat = RPC_CANTSEND;
|
||||
continue;
|
||||
}
|
||||
#ifdef RPC_DEBUG
|
||||
if (!__rpc_lowvers)
|
||||
fprintf(stderr, "Broadcast packet sent "
|
||||
"for %s\n",
|
||||
fdlist[i].nconf->nc_netid);
|
||||
#endif
|
||||
#ifdef PORTMAP
|
||||
/*
|
||||
* Send the version 2 packet also
|
||||
* for UDP/IP
|
||||
*/
|
||||
if (pmap_flag &&
|
||||
fdlist[i].proto == IPPROTO_UDP) {
|
||||
if ((size_t)sendto(fdlist[i].fd,
|
||||
outbuf_pmap, outlen_pmap, 0, addr,
|
||||
(size_t)fdlist[i].asize) !=
|
||||
outlen_pmap) {
|
||||
warnx("clnt_bcast: "
|
||||
"Cannot send "
|
||||
"broadcast packet");
|
||||
stat = RPC_CANTSEND;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
#ifdef RPC_DEBUG
|
||||
fprintf(stderr, "PMAP Broadcast packet "
|
||||
"sent for %s\n",
|
||||
fdlist[i].nconf->nc_netid);
|
||||
#endif
|
||||
#endif /* PORTMAP */
|
||||
}
|
||||
/* End for sending all packets on this transport */
|
||||
} /* End for sending on all transports */
|
||||
|
||||
if (eachresult == NULL) {
|
||||
stat = RPC_SUCCESS;
|
||||
goto done_broad;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get all the replies from these broadcast requests
|
||||
*/
|
||||
recv_again:
|
||||
ts.tv_sec = msec / 1000;
|
||||
ts.tv_nsec = (msec % 1000) * 1000000;
|
||||
|
||||
switch (pollretval = pollts(pfd, fdlistno, &ts, NULL)) {
|
||||
case 0: /* timed out */
|
||||
stat = RPC_TIMEDOUT;
|
||||
continue;
|
||||
case -1: /* some kind of error - we ignore it */
|
||||
goto recv_again;
|
||||
} /* end of poll results switch */
|
||||
|
||||
for (i = fds_found = 0;
|
||||
i < fdlistno && fds_found < pollretval; i++) {
|
||||
bool_t done = FALSE;
|
||||
|
||||
if (pfd[i].revents == 0)
|
||||
continue;
|
||||
else if (pfd[i].revents & POLLNVAL) {
|
||||
/*
|
||||
* Something bad has happened to this descri-
|
||||
* ptor. We can cause pollts() to ignore
|
||||
* it simply by using a negative fd. We do that
|
||||
* rather than compacting the pfd[] and fdlist[]
|
||||
* arrays.
|
||||
*/
|
||||
pfd[i].fd = -1;
|
||||
fds_found++;
|
||||
continue;
|
||||
} else
|
||||
fds_found++;
|
||||
#ifdef RPC_DEBUG
|
||||
fprintf(stderr, "response for %s\n",
|
||||
fdlist[i].nconf->nc_netid);
|
||||
#endif
|
||||
try_again:
|
||||
inlen = recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize,
|
||||
0, (struct sockaddr *)(void *)&fdlist[i].raddr,
|
||||
&fdlist[i].asize);
|
||||
if (inlen < 0) {
|
||||
if (errno == EINTR)
|
||||
goto try_again;
|
||||
warnx("clnt_bcast: Cannot receive reply to "
|
||||
"broadcast");
|
||||
stat = RPC_CANTRECV;
|
||||
continue;
|
||||
}
|
||||
if (inlen < (ssize_t)sizeof(u_int32_t))
|
||||
continue; /* Drop that and go ahead */
|
||||
/*
|
||||
* see if reply transaction id matches sent id.
|
||||
* If so, decode the results. If return id is xid + 1
|
||||
* it was a PORTMAP reply
|
||||
*/
|
||||
if (*((u_int32_t *)(void *)(inbuf)) ==
|
||||
*((u_int32_t *)(void *)(outbuf))) {
|
||||
pmap_reply_flag = 0;
|
||||
msg.acpted_rply.ar_verf = _null_auth;
|
||||
msg.acpted_rply.ar_results.where =
|
||||
(caddr_t)(void *)&bres;
|
||||
msg.acpted_rply.ar_results.proc =
|
||||
(xdrproc_t)xdr_rpcb_rmtcallres;
|
||||
#ifdef PORTMAP
|
||||
} else if (pmap_flag &&
|
||||
*((u_int32_t *)(void *)(inbuf)) ==
|
||||
*((u_int32_t *)(void *)(outbuf_pmap))) {
|
||||
pmap_reply_flag = 1;
|
||||
msg.acpted_rply.ar_verf = _null_auth;
|
||||
msg.acpted_rply.ar_results.where =
|
||||
(caddr_t)(void *)&bres_pmap;
|
||||
msg.acpted_rply.ar_results.proc =
|
||||
(xdrproc_t)xdr_rmtcallres;
|
||||
#endif /* PORTMAP */
|
||||
} else
|
||||
continue;
|
||||
xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
|
||||
if (xdr_replymsg(xdrs, &msg)) {
|
||||
if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
|
||||
(msg.acpted_rply.ar_stat == SUCCESS)) {
|
||||
struct netbuf taddr, *np;
|
||||
struct sockaddr_in *bsin;
|
||||
|
||||
#ifdef PORTMAP
|
||||
if (pmap_flag && pmap_reply_flag) {
|
||||
bsin = (struct sockaddr_in *)
|
||||
(void *)&fdlist[i].raddr;
|
||||
bsin->sin_port =
|
||||
htons((u_short)port);
|
||||
taddr.len = taddr.maxlen =
|
||||
fdlist[i].raddr.ss_len;
|
||||
taddr.buf = &fdlist[i].raddr;
|
||||
done = (*eachresult)(resultsp,
|
||||
&taddr, fdlist[i].nconf);
|
||||
} else {
|
||||
#endif
|
||||
#ifdef RPC_DEBUG
|
||||
fprintf(stderr, "uaddr %s\n",
|
||||
uaddrp);
|
||||
#endif
|
||||
np = uaddr2taddr(
|
||||
fdlist[i].nconf, uaddrp);
|
||||
done = (*eachresult)(resultsp,
|
||||
np, fdlist[i].nconf);
|
||||
free(np);
|
||||
#ifdef PORTMAP
|
||||
}
|
||||
#endif
|
||||
}
|
||||
/* otherwise, we just ignore the errors ... */
|
||||
}
|
||||
/* else some kind of deserialization problem ... */
|
||||
|
||||
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;
|
||||
}
|
||||
} /* The recv for loop */
|
||||
} /* The giant for loop */
|
||||
|
||||
done_broad:
|
||||
if (inbuf)
|
||||
(void) free(inbuf);
|
||||
if (outbuf)
|
||||
(void) free(outbuf);
|
||||
#ifdef PORTMAP
|
||||
if (outbuf_pmap)
|
||||
(void) free(outbuf_pmap);
|
||||
#endif
|
||||
for (i = 0; i < fdlistno; i++) {
|
||||
(void) close(fdlist[i].fd);
|
||||
__rpc_freebroadifs(&fdlist[i].nal);
|
||||
}
|
||||
AUTH_DESTROY(sys_auth);
|
||||
(void) __rpc_endconf(handle);
|
||||
|
||||
return (stat);
|
||||
}
|
||||
|
||||
|
||||
enum clnt_stat
|
||||
rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
|
||||
eachresult, nettype)
|
||||
rpcprog_t prog; /* program number */
|
||||
rpcvers_t vers; /* version number */
|
||||
rpcproc_t proc; /* procedure number */
|
||||
xdrproc_t xargs; /* xdr routine for args */
|
||||
const char * argsp; /* pointer to args */
|
||||
xdrproc_t xresults; /* xdr routine for results */
|
||||
caddr_t resultsp; /* pointer to results */
|
||||
resultproc_t eachresult; /* call with each result obtained */
|
||||
const char *nettype; /* transport type */
|
||||
{
|
||||
enum clnt_stat dummy;
|
||||
|
||||
dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp,
|
||||
xresults, resultsp, eachresult,
|
||||
INITTIME, WAITTIME, nettype);
|
||||
return (dummy);
|
||||
}
|
||||
@@ -0,0 +1,769 @@
|
||||
/* $NetBSD: clnt_dg.c,v 1.24 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)clnt_dg.c 1.23 94/04/22 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_dg.c,v 1.24 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Implements a connectionless client side RPC.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/poll.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(clnt_dg_create,_clnt_dg_create)
|
||||
#endif
|
||||
|
||||
#define RPC_MAX_BACKOFF 30 /* seconds */
|
||||
|
||||
|
||||
static struct clnt_ops *clnt_dg_ops __P((void));
|
||||
static bool_t time_not_ok __P((struct timeval *));
|
||||
static enum clnt_stat clnt_dg_call __P((CLIENT *, rpcproc_t, xdrproc_t,
|
||||
const char *, xdrproc_t, caddr_t, struct timeval));
|
||||
static void clnt_dg_geterr __P((CLIENT *, struct rpc_err *));
|
||||
static bool_t clnt_dg_freeres __P((CLIENT *, xdrproc_t, caddr_t));
|
||||
static void clnt_dg_abort __P((CLIENT *));
|
||||
static bool_t clnt_dg_control __P((CLIENT *, u_int, char *));
|
||||
static void clnt_dg_destroy __P((CLIENT *));
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* This machinery implements per-fd locks for MT-safety. It is not
|
||||
* sufficient to do per-CLIENT handle locks for MT-safety because a
|
||||
* user may create more than one CLIENT handle with the same fd behind
|
||||
* it. Therfore, we allocate an array of flags (dg_fd_locks), protected
|
||||
* by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
|
||||
* similarly protected. Dg_fd_lock[fd] == 1 => a call is activte on some
|
||||
* CLIENT handle created for that fd.
|
||||
* The current implementation holds locks across the entire RPC and reply,
|
||||
* including retransmissions. Yes, this is silly, and as soon as this
|
||||
* code is proven to work, this should be the first thing fixed. One step
|
||||
* at a time.
|
||||
*/
|
||||
static int *dg_fd_locks;
|
||||
#ifdef _REENTRANT
|
||||
#define __rpc_lock_value __isthreaded;
|
||||
extern mutex_t clnt_fd_lock;
|
||||
static cond_t *dg_cv;
|
||||
#define release_fd_lock(fd, mask) { \
|
||||
mutex_lock(&clnt_fd_lock); \
|
||||
dg_fd_locks[fd] = 0; \
|
||||
mutex_unlock(&clnt_fd_lock); \
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
|
||||
cond_signal(&dg_cv[fd]); \
|
||||
}
|
||||
#else
|
||||
#define release_fd_lock(fd,mask)
|
||||
#define __rpc_lock_value 0
|
||||
#endif
|
||||
|
||||
static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
|
||||
|
||||
/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
|
||||
|
||||
/*
|
||||
* Private data kept per client handle
|
||||
*/
|
||||
struct cu_data {
|
||||
int cu_fd; /* connections fd */
|
||||
bool_t cu_closeit; /* opened by library */
|
||||
struct sockaddr_storage cu_raddr; /* remote address */
|
||||
int cu_rlen;
|
||||
struct timeval cu_wait; /* retransmit interval */
|
||||
struct timeval cu_total; /* total time for the call */
|
||||
struct rpc_err cu_error;
|
||||
XDR cu_outxdrs;
|
||||
u_int cu_xdrpos;
|
||||
u_int cu_sendsz; /* send size */
|
||||
char *cu_outbuf;
|
||||
u_int cu_recvsz; /* recv size */
|
||||
struct pollfd cu_pfdp;
|
||||
char cu_inbuf[1];
|
||||
};
|
||||
|
||||
/*
|
||||
* Connection less client creation returns with client handle parameters.
|
||||
* Default options are set, which the user can change using clnt_control().
|
||||
* fd should be open and bound.
|
||||
* NB: The rpch->cl_auth is initialized to null authentication.
|
||||
* Caller may wish to set this something more useful.
|
||||
*
|
||||
* sendsz and recvsz are the maximum allowable packet sizes that can be
|
||||
* sent and received. Normally they are the same, but they can be
|
||||
* changed to improve the program efficiency and buffer allocation.
|
||||
* If they are 0, use the transport default.
|
||||
*
|
||||
* If svcaddr is NULL, returns NULL.
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
|
||||
int fd; /* open file descriptor */
|
||||
const struct netbuf *svcaddr; /* servers address */
|
||||
rpcprog_t program; /* program number */
|
||||
rpcvers_t version; /* version number */
|
||||
u_int sendsz; /* buffer recv size */
|
||||
u_int recvsz; /* buffer send size */
|
||||
{
|
||||
CLIENT *cl = NULL; /* client handle */
|
||||
struct cu_data *cu = NULL; /* private data */
|
||||
struct rpc_msg call_msg;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
struct __rpc_sockinfo si;
|
||||
int one = 1;
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
if (dg_fd_locks == NULL) {
|
||||
#ifdef _REENTRANT
|
||||
size_t cv_allocsz;
|
||||
#endif
|
||||
size_t fd_allocsz;
|
||||
int dtbsize = __rpc_dtbsize();
|
||||
|
||||
fd_allocsz = dtbsize * sizeof (int);
|
||||
dg_fd_locks = mem_alloc(fd_allocsz);
|
||||
if (dg_fd_locks == NULL) {
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
goto err1;
|
||||
} else
|
||||
memset(dg_fd_locks, '\0', fd_allocsz);
|
||||
|
||||
#ifdef _REENTRANT
|
||||
cv_allocsz = dtbsize * sizeof (cond_t);
|
||||
dg_cv = mem_alloc(cv_allocsz);
|
||||
if (dg_cv == NULL) {
|
||||
mem_free(dg_fd_locks, fd_allocsz);
|
||||
dg_fd_locks = NULL;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
goto err1;
|
||||
} else {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dtbsize; i++)
|
||||
cond_init(&dg_cv[i], 0, (void *) 0);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
|
||||
if (svcaddr == NULL) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (!__rpc_fd2sockinfo(fd, &si)) {
|
||||
rpc_createerr.cf_stat = RPC_TLIERROR;
|
||||
rpc_createerr.cf_error.re_errno = 0;
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* Find the receive and the send size
|
||||
*/
|
||||
sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
|
||||
recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
|
||||
if ((sendsz == 0) || (recvsz == 0)) {
|
||||
rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
|
||||
rpc_createerr.cf_error.re_errno = 0;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
|
||||
goto err1;
|
||||
/*
|
||||
* Should be multiple of 4 for XDR.
|
||||
*/
|
||||
sendsz = ((sendsz + 3) / 4) * 4;
|
||||
recvsz = ((recvsz + 3) / 4) * 4;
|
||||
cu = malloc(sizeof (*cu) + sendsz + recvsz);
|
||||
if (cu == NULL)
|
||||
goto err1;
|
||||
memset(cu, 0, sizeof(*cu));
|
||||
(void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
|
||||
cu->cu_rlen = svcaddr->len;
|
||||
cu->cu_outbuf = &cu->cu_inbuf[recvsz];
|
||||
/* Other values can also be set through clnt_control() */
|
||||
cu->cu_wait.tv_sec = 15; /* heuristically chosen */
|
||||
cu->cu_wait.tv_usec = 0;
|
||||
cu->cu_total.tv_sec = -1;
|
||||
cu->cu_total.tv_usec = -1;
|
||||
cu->cu_sendsz = sendsz;
|
||||
cu->cu_recvsz = recvsz;
|
||||
call_msg.rm_xid = __RPC_GETXID();
|
||||
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)) {
|
||||
rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */
|
||||
rpc_createerr.cf_error.re_errno = 0;
|
||||
goto err2;
|
||||
}
|
||||
cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
|
||||
|
||||
/* XXX fvdl - do we still want this? */
|
||||
#if 0
|
||||
(void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
|
||||
#endif
|
||||
ioctl(fd, FIONBIO, (char *)(void *)&one);
|
||||
|
||||
/*
|
||||
* By default, closeit is always FALSE. It is users responsibility
|
||||
* to do a close on it, else the user may use clnt_control
|
||||
* to let clnt_destroy do it for him/her.
|
||||
*/
|
||||
cu->cu_closeit = FALSE;
|
||||
cu->cu_fd = fd;
|
||||
cu->cu_pfdp.fd = cu->cu_fd;
|
||||
cu->cu_pfdp.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND;
|
||||
cl->cl_ops = clnt_dg_ops();
|
||||
cl->cl_private = (caddr_t)(void *)cu;
|
||||
cl->cl_auth = authnone_create();
|
||||
cl->cl_tp = NULL;
|
||||
cl->cl_netid = NULL;
|
||||
return (cl);
|
||||
err1:
|
||||
warnx(mem_err_clnt_dg);
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
err2:
|
||||
if (cl) {
|
||||
mem_free(cl, sizeof (CLIENT));
|
||||
if (cu)
|
||||
mem_free(cu, sizeof (*cu) + sendsz + recvsz);
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static enum clnt_stat
|
||||
clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
|
||||
CLIENT *cl; /* client handle */
|
||||
rpcproc_t proc; /* procedure number */
|
||||
xdrproc_t xargs; /* xdr routine for args */
|
||||
const char * argsp; /* pointer to args */
|
||||
xdrproc_t xresults; /* xdr routine for results */
|
||||
caddr_t resultsp; /* pointer to results */
|
||||
struct timeval utimeout; /* seconds to wait before giving up */
|
||||
{
|
||||
struct cu_data *cu;
|
||||
XDR *xdrs;
|
||||
size_t outlen;
|
||||
struct rpc_msg reply_msg;
|
||||
XDR reply_xdrs;
|
||||
bool_t ok;
|
||||
int nrefreshes = 2; /* number of times to refresh cred */
|
||||
struct timeval timeout;
|
||||
struct timeval retransmit_time;
|
||||
struct timeval next_sendtime, starttime, time_waited, tv;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask, *maskp = &mask;
|
||||
#else
|
||||
sigset_t *maskp = NULL;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
ssize_t recvlen = 0;
|
||||
struct timespec ts;
|
||||
int n;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
|
||||
cu = (struct cu_data *)cl->cl_private;
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
while (dg_fd_locks[cu->cu_fd])
|
||||
cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
|
||||
dg_fd_locks[cu->cu_fd] = __rpc_lock_value;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
if (cu->cu_total.tv_usec == -1) {
|
||||
timeout = utimeout; /* use supplied timeout */
|
||||
} else {
|
||||
timeout = cu->cu_total; /* use default timeout */
|
||||
}
|
||||
|
||||
time_waited.tv_sec = 0;
|
||||
time_waited.tv_usec = 0;
|
||||
retransmit_time = next_sendtime = cu->cu_wait;
|
||||
gettimeofday(&starttime, NULL);
|
||||
|
||||
call_again:
|
||||
xdrs = &(cu->cu_outxdrs);
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
XDR_SETPOS(xdrs, cu->cu_xdrpos);
|
||||
/*
|
||||
* the transaction is the first thing in the out buffer
|
||||
*/
|
||||
(*(u_int32_t *)(void *)(cu->cu_outbuf))++;
|
||||
if ((! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
|
||||
(! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
|
||||
(! (*xargs)(xdrs, __UNCONST(argsp)))) {
|
||||
cu->cu_error.re_status = RPC_CANTENCODEARGS;
|
||||
goto out;
|
||||
}
|
||||
outlen = (size_t)XDR_GETPOS(xdrs);
|
||||
|
||||
send_again:
|
||||
if ((size_t)sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0,
|
||||
(struct sockaddr *)(void *)&cu->cu_raddr, (socklen_t)cu->cu_rlen)
|
||||
!= outlen) {
|
||||
cu->cu_error.re_errno = errno;
|
||||
cu->cu_error.re_status = RPC_CANTSEND;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hack to provide rpc-based message passing
|
||||
*/
|
||||
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
|
||||
cu->cu_error.re_status = RPC_TIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
/*
|
||||
* sub-optimal code appears here because we have
|
||||
* some clock time to spare while the packets are in flight.
|
||||
* (We assume that this is actually only executed once.)
|
||||
*/
|
||||
reply_msg.acpted_rply.ar_verf = _null_auth;
|
||||
reply_msg.acpted_rply.ar_results.where = resultsp;
|
||||
reply_msg.acpted_rply.ar_results.proc = xresults;
|
||||
|
||||
|
||||
for (;;) {
|
||||
/* Decide how long to wait. */
|
||||
if (timercmp(&next_sendtime, &timeout, <))
|
||||
timersub(&next_sendtime, &time_waited, &tv);
|
||||
else
|
||||
timersub(&timeout, &time_waited, &tv);
|
||||
if (tv.tv_sec < 0 || tv.tv_usec < 0)
|
||||
tv.tv_sec = tv.tv_usec = 0;
|
||||
TIMEVAL_TO_TIMESPEC(&tv, &ts);
|
||||
|
||||
n = pollts(&cu->cu_pfdp, 1, &ts, maskp);
|
||||
if (n == 1) {
|
||||
/* We have some data now */
|
||||
do {
|
||||
recvlen = recvfrom(cu->cu_fd, cu->cu_inbuf,
|
||||
cu->cu_recvsz, 0, NULL, NULL);
|
||||
} while (recvlen < 0 && errno == EINTR);
|
||||
|
||||
if (recvlen < 0 && errno != EWOULDBLOCK) {
|
||||
cu->cu_error.re_errno = errno;
|
||||
cu->cu_error.re_status = RPC_CANTRECV;
|
||||
goto out;
|
||||
}
|
||||
if (recvlen >= (ssize_t)sizeof(uint32_t) &&
|
||||
(*((uint32_t *)(void *)(cu->cu_inbuf)) ==
|
||||
*((uint32_t *)(void *)(cu->cu_outbuf)))) {
|
||||
/* We now assume we have the proper reply. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (n == -1) {
|
||||
cu->cu_error.re_errno = errno;
|
||||
cu->cu_error.re_status = RPC_CANTRECV;
|
||||
goto out;
|
||||
}
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
timersub(&tv, &starttime, &time_waited);
|
||||
|
||||
/* Check for timeout. */
|
||||
if (timercmp(&time_waited, &timeout, >)) {
|
||||
cu->cu_error.re_status = RPC_TIMEDOUT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Retransmit if necessary. */
|
||||
if (timercmp(&time_waited, &next_sendtime, >)) {
|
||||
/* update retransmit_time */
|
||||
if (retransmit_time.tv_sec < RPC_MAX_BACKOFF)
|
||||
timeradd(&retransmit_time, &retransmit_time,
|
||||
&retransmit_time);
|
||||
timeradd(&next_sendtime, &retransmit_time,
|
||||
&next_sendtime);
|
||||
goto send_again;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* now decode and validate the response
|
||||
*/
|
||||
|
||||
xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, XDR_DECODE);
|
||||
ok = xdr_replymsg(&reply_xdrs, &reply_msg);
|
||||
/* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
|
||||
if (ok) {
|
||||
if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
|
||||
(reply_msg.acpted_rply.ar_stat == SUCCESS))
|
||||
cu->cu_error.re_status = RPC_SUCCESS;
|
||||
else
|
||||
_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 */
|
||||
/*
|
||||
* If unsuccesful AND error is an authentication error
|
||||
* then refresh credentials and try again, else break
|
||||
*/
|
||||
else if (cu->cu_error.re_status == RPC_AUTHERROR)
|
||||
/* 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;
|
||||
|
||||
}
|
||||
out:
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (cu->cu_error.re_status);
|
||||
}
|
||||
|
||||
static void
|
||||
clnt_dg_geterr(cl, errp)
|
||||
CLIENT *cl;
|
||||
struct rpc_err *errp;
|
||||
{
|
||||
struct cu_data *cu;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
_DIAGASSERT(errp != NULL);
|
||||
|
||||
cu = (struct cu_data *)cl->cl_private;
|
||||
*errp = cu->cu_error;
|
||||
}
|
||||
|
||||
static bool_t
|
||||
clnt_dg_freeres(cl, xdr_res, res_ptr)
|
||||
CLIENT *cl;
|
||||
xdrproc_t xdr_res;
|
||||
caddr_t res_ptr;
|
||||
{
|
||||
struct cu_data *cu;
|
||||
XDR *xdrs;
|
||||
bool_t dummy;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
cu = (struct cu_data *)cl->cl_private;
|
||||
xdrs = &(cu->cu_outxdrs);
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
while (dg_fd_locks[cu->cu_fd])
|
||||
cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
|
||||
xdrs->x_op = XDR_FREE;
|
||||
dummy = (*xdr_res)(xdrs, res_ptr);
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
|
||||
cond_signal(&dg_cv[cu->cu_fd]);
|
||||
return (dummy);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
clnt_dg_abort(h)
|
||||
CLIENT *h;
|
||||
{
|
||||
}
|
||||
|
||||
static bool_t
|
||||
clnt_dg_control(cl, request, info)
|
||||
CLIENT *cl;
|
||||
u_int request;
|
||||
char *info;
|
||||
{
|
||||
struct cu_data *cu;
|
||||
struct netbuf *addr;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
/* info is handled below */
|
||||
|
||||
cu = (struct cu_data *)cl->cl_private;
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
while (dg_fd_locks[cu->cu_fd])
|
||||
cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
|
||||
dg_fd_locks[cu->cu_fd] = __rpc_lock_value;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
switch (request) {
|
||||
case CLSET_FD_CLOSE:
|
||||
cu->cu_closeit = TRUE;
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (TRUE);
|
||||
case CLSET_FD_NCLOSE:
|
||||
cu->cu_closeit = FALSE;
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* for other requests which use info */
|
||||
if (info == NULL) {
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
switch (request) {
|
||||
case CLSET_TIMEOUT:
|
||||
if (time_not_ok((struct timeval *)(void *)info)) {
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
cu->cu_total = *(struct timeval *)(void *)info;
|
||||
break;
|
||||
case CLGET_TIMEOUT:
|
||||
*(struct timeval *)(void *)info = cu->cu_total;
|
||||
break;
|
||||
case CLGET_SERVER_ADDR: /* Give him the fd address */
|
||||
/* Now obsolete. Only for backward compatibility */
|
||||
(void) memcpy(info, &cu->cu_raddr, (size_t)cu->cu_rlen);
|
||||
break;
|
||||
case CLSET_RETRY_TIMEOUT:
|
||||
if (time_not_ok((struct timeval *)(void *)info)) {
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
cu->cu_wait = *(struct timeval *)(void *)info;
|
||||
break;
|
||||
case CLGET_RETRY_TIMEOUT:
|
||||
*(struct timeval *)(void *)info = cu->cu_wait;
|
||||
break;
|
||||
case CLGET_FD:
|
||||
*(int *)(void *)info = cu->cu_fd;
|
||||
break;
|
||||
case CLGET_SVC_ADDR:
|
||||
addr = (struct netbuf *)(void *)info;
|
||||
addr->buf = &cu->cu_raddr;
|
||||
addr->len = cu->cu_rlen;
|
||||
addr->maxlen = sizeof cu->cu_raddr;
|
||||
break;
|
||||
case CLSET_SVC_ADDR: /* set to new address */
|
||||
addr = (struct netbuf *)(void *)info;
|
||||
if (addr->len < sizeof cu->cu_raddr) {
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
(void) memcpy(&cu->cu_raddr, addr->buf, (size_t)addr->len);
|
||||
cu->cu_rlen = addr->len;
|
||||
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
|
||||
*/
|
||||
*(u_int32_t *)(void *)info =
|
||||
ntohl(*(u_int32_t *)(void *)cu->cu_outbuf);
|
||||
break;
|
||||
|
||||
case CLSET_XID:
|
||||
/* This will set the xid of the NEXT call */
|
||||
*(u_int32_t *)(void *)cu->cu_outbuf =
|
||||
htonl(*(u_int32_t *)(void *)info - 1);
|
||||
/* decrement by 1 as clnt_dg_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
|
||||
* begining of the RPC header. MUST be changed if the
|
||||
* call_struct is changed
|
||||
*/
|
||||
*(u_int32_t *)(void *)info =
|
||||
ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf +
|
||||
4 * BYTES_PER_XDR_UNIT));
|
||||
break;
|
||||
|
||||
case CLSET_VERS:
|
||||
*(u_int32_t *)(void *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT)
|
||||
= htonl(*(u_int32_t *)(void *)info);
|
||||
break;
|
||||
|
||||
case CLGET_PROG:
|
||||
/*
|
||||
* This RELIES on the information that, in the call body,
|
||||
* the program number field is the fourth field from the
|
||||
* begining of the RPC header. MUST be changed if the
|
||||
* call_struct is changed
|
||||
*/
|
||||
*(u_int32_t *)(void *)info =
|
||||
ntohl(*(u_int32_t *)(void *)(cu->cu_outbuf +
|
||||
3 * BYTES_PER_XDR_UNIT));
|
||||
break;
|
||||
|
||||
case CLSET_PROG:
|
||||
*(u_int32_t *)(void *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT)
|
||||
= htonl(*(u_int32_t *)(void *)info);
|
||||
break;
|
||||
|
||||
default:
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
release_fd_lock(cu->cu_fd, mask);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
clnt_dg_destroy(cl)
|
||||
CLIENT *cl;
|
||||
{
|
||||
struct cu_data *cu;
|
||||
int cu_fd;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
|
||||
cu = (struct cu_data *)cl->cl_private;
|
||||
cu_fd = cu->cu_fd;
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
while (dg_fd_locks[cu_fd])
|
||||
cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
|
||||
if (cu->cu_closeit)
|
||||
(void) close(cu_fd);
|
||||
XDR_DESTROY(&(cu->cu_outxdrs));
|
||||
mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
|
||||
if (cl->cl_netid && cl->cl_netid[0])
|
||||
mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
|
||||
if (cl->cl_tp && cl->cl_tp[0])
|
||||
mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
|
||||
mem_free(cl, sizeof (CLIENT));
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
|
||||
cond_signal(&dg_cv[cu_fd]);
|
||||
}
|
||||
|
||||
static struct clnt_ops *
|
||||
clnt_dg_ops()
|
||||
{
|
||||
static struct clnt_ops ops;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops */
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.cl_call == NULL) {
|
||||
ops.cl_call = clnt_dg_call;
|
||||
ops.cl_abort = clnt_dg_abort;
|
||||
ops.cl_geterr = clnt_dg_geterr;
|
||||
ops.cl_freeres = clnt_dg_freeres;
|
||||
ops.cl_destroy = clnt_dg_destroy;
|
||||
ops.cl_control = clnt_dg_control;
|
||||
}
|
||||
mutex_unlock(&ops_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &mask, NULL);
|
||||
return (&ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the time is not garbage. -1 value is allowed.
|
||||
*/
|
||||
static bool_t
|
||||
time_not_ok(t)
|
||||
struct timeval *t;
|
||||
{
|
||||
|
||||
_DIAGASSERT(t != NULL);
|
||||
|
||||
return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
|
||||
t->tv_usec < -1 || t->tv_usec > 1000000);
|
||||
}
|
||||
@@ -0,0 +1,379 @@
|
||||
/* $NetBSD: clnt_generic.c,v 1.27 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)clnt_generic.c 1.20 94/05/03 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)clnt_generic.c 1.32 89/03/16 Copyr 1988 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_generic.c,v 1.27 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/nettype.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(clnt_create_vers,_clnt_create_vers)
|
||||
__weak_alias(clnt_create,_clnt_create)
|
||||
__weak_alias(clnt_tp_create,_clnt_tp_create)
|
||||
__weak_alias(clnt_tli_create,_clnt_tli_create)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Generic client creation with version checking the value of
|
||||
* vers_out is set to the highest server supported value
|
||||
* vers_low <= vers_out <= vers_high AND an error results
|
||||
* if this can not be done.
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_create_vers(hostname, prog, vers_out, vers_low, vers_high, nettype)
|
||||
const char *hostname;
|
||||
rpcprog_t prog;
|
||||
rpcvers_t *vers_out;
|
||||
rpcvers_t vers_low;
|
||||
rpcvers_t vers_high;
|
||||
const char *nettype;
|
||||
{
|
||||
CLIENT *clnt;
|
||||
struct timeval to;
|
||||
enum clnt_stat rpc_stat;
|
||||
struct rpc_err rpcerr;
|
||||
|
||||
_DIAGASSERT(hostname != NULL);
|
||||
_DIAGASSERT(vers_out != NULL);
|
||||
/* XXX: nettype appears to support being NULL */
|
||||
|
||||
clnt = clnt_create(hostname, prog, vers_high, nettype);
|
||||
if (clnt == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
to.tv_sec = 10;
|
||||
to.tv_usec = 0;
|
||||
rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void,
|
||||
NULL, (xdrproc_t) xdr_void, NULL, to);
|
||||
if (rpc_stat == RPC_SUCCESS) {
|
||||
*vers_out = vers_high;
|
||||
return (clnt);
|
||||
}
|
||||
if (rpc_stat == RPC_PROGVERSMISMATCH) {
|
||||
unsigned long minvers, maxvers;
|
||||
|
||||
clnt_geterr(clnt, &rpcerr);
|
||||
minvers = rpcerr.re_vers.low;
|
||||
maxvers = rpcerr.re_vers.high;
|
||||
if (maxvers < vers_high)
|
||||
vers_high = (rpcvers_t)maxvers;
|
||||
if (minvers > vers_low)
|
||||
vers_low = (rpcvers_t)minvers;
|
||||
if (vers_low > vers_high) {
|
||||
goto error;
|
||||
}
|
||||
CLNT_CONTROL(clnt, CLSET_VERS, (char *)(void *)&vers_high);
|
||||
rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void,
|
||||
NULL, (xdrproc_t) xdr_void, NULL, to);
|
||||
if (rpc_stat == RPC_SUCCESS) {
|
||||
*vers_out = vers_high;
|
||||
return (clnt);
|
||||
}
|
||||
}
|
||||
clnt_geterr(clnt, &rpcerr);
|
||||
|
||||
error:
|
||||
rpc_createerr.cf_stat = rpc_stat;
|
||||
rpc_createerr.cf_error = rpcerr;
|
||||
clnt_destroy(clnt);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Top level client creation routine.
|
||||
* Generic client creation: takes (servers name, program-number, nettype) and
|
||||
* returns client handle. Default options are set, which the user can
|
||||
* change using the rpc equivalent of ioctl()'s.
|
||||
*
|
||||
* It tries for all the netids in that particular class of netid until
|
||||
* it succeeds.
|
||||
* XXX The error message in the case of failure will be the one
|
||||
* pertaining to the last create error.
|
||||
*
|
||||
* It calls clnt_tp_create();
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_create(hostname, prog, vers, nettype)
|
||||
const char *hostname; /* server name */
|
||||
rpcprog_t prog; /* program number */
|
||||
rpcvers_t vers; /* version number */
|
||||
const char *nettype; /* net type */
|
||||
{
|
||||
struct netconfig *nconf;
|
||||
CLIENT *clnt = NULL;
|
||||
void *handle;
|
||||
enum clnt_stat save_cf_stat = RPC_SUCCESS;
|
||||
struct rpc_err save_cf_error;
|
||||
|
||||
_DIAGASSERT(hostname != NULL);
|
||||
/* XXX: nettype appears to support being NULL */
|
||||
|
||||
if ((handle = __rpc_setconf(nettype)) == NULL) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
return (NULL);
|
||||
}
|
||||
rpc_createerr.cf_stat = RPC_SUCCESS;
|
||||
while (clnt == NULL) {
|
||||
if ((nconf = __rpc_getconf(handle)) == NULL) {
|
||||
if (rpc_createerr.cf_stat == RPC_SUCCESS)
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
break;
|
||||
}
|
||||
#ifdef CLNT_DEBUG
|
||||
printf("trying netid %s\n", nconf->nc_netid);
|
||||
#endif
|
||||
clnt = clnt_tp_create(hostname, prog, vers, nconf);
|
||||
if (clnt)
|
||||
break;
|
||||
else
|
||||
/*
|
||||
* Since we didn't get a name-to-address
|
||||
* translation failure here, we remember
|
||||
* this particular error. The object of
|
||||
* this is to enable us to return to the
|
||||
* caller a more-specific error than the
|
||||
* unhelpful ``Name to address translation
|
||||
* failed'' which might well occur if we
|
||||
* merely returned the last error (because
|
||||
* the local loopbacks are typically the
|
||||
* last ones in /etc/netconfig and the most
|
||||
* likely to be unable to translate a host
|
||||
* name).
|
||||
*/
|
||||
if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE) {
|
||||
save_cf_stat = rpc_createerr.cf_stat;
|
||||
save_cf_error = rpc_createerr.cf_error;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Attempt to return an error more specific than ``Name to address
|
||||
* translation failed''
|
||||
*/
|
||||
if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE) &&
|
||||
(save_cf_stat != RPC_SUCCESS)) {
|
||||
rpc_createerr.cf_stat = save_cf_stat;
|
||||
rpc_createerr.cf_error = save_cf_error;
|
||||
}
|
||||
__rpc_endconf(handle);
|
||||
return (clnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic client creation: takes (servers name, program-number, netconf) and
|
||||
* returns client handle. Default options are set, which the user can
|
||||
* change using the rpc equivalent of ioctl()'s : clnt_control()
|
||||
* It finds out the server address from rpcbind and calls clnt_tli_create()
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_tp_create(hostname, prog, vers, nconf)
|
||||
const char *hostname; /* server name */
|
||||
rpcprog_t prog; /* program number */
|
||||
rpcvers_t vers; /* version number */
|
||||
const struct netconfig *nconf; /* net config struct */
|
||||
{
|
||||
struct netbuf *svcaddr; /* servers address */
|
||||
CLIENT *cl = NULL; /* client handle */
|
||||
|
||||
_DIAGASSERT(hostname != NULL);
|
||||
/* nconf is handled below */
|
||||
|
||||
if (nconf == NULL) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the address of the server
|
||||
*/
|
||||
if ((svcaddr = __rpcb_findaddr(prog, vers, nconf, hostname,
|
||||
&cl)) == NULL) {
|
||||
/* appropriate error number is set by rpcbind libraries */
|
||||
return (NULL);
|
||||
}
|
||||
if (cl == NULL) {
|
||||
cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
|
||||
prog, vers, 0, 0);
|
||||
} else {
|
||||
/* Reuse the CLIENT handle and change the appropriate fields */
|
||||
if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
|
||||
if (cl->cl_netid == NULL) {
|
||||
cl->cl_netid = strdup(nconf->nc_netid);
|
||||
if (cl->cl_netid == NULL)
|
||||
goto out;
|
||||
}
|
||||
if (cl->cl_tp == NULL) {
|
||||
cl->cl_tp = strdup(nconf->nc_device);
|
||||
if (cl->cl_tp == NULL)
|
||||
goto out;
|
||||
}
|
||||
(void) CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog);
|
||||
(void) CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers);
|
||||
} else {
|
||||
CLNT_DESTROY(cl);
|
||||
cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
|
||||
prog, vers, 0, 0);
|
||||
}
|
||||
}
|
||||
free(svcaddr->buf);
|
||||
free(svcaddr);
|
||||
return (cl);
|
||||
out:
|
||||
clnt_destroy(cl);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generic client creation: returns client handle.
|
||||
* Default options are set, which the user can
|
||||
* change using the rpc equivalent of ioctl()'s : clnt_control().
|
||||
* If fd is RPC_ANYFD, it will be opened using nconf.
|
||||
* It will be bound if not so.
|
||||
* If sizes are 0; appropriate defaults will be chosen.
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_tli_create(fd, nconf, svcaddr, prog, vers, sendsz, recvsz)
|
||||
int fd; /* fd */
|
||||
const struct netconfig *nconf; /* netconfig structure */
|
||||
const struct netbuf *svcaddr; /* servers address */
|
||||
rpcprog_t prog; /* program number */
|
||||
rpcvers_t vers; /* version number */
|
||||
u_int sendsz; /* send size */
|
||||
u_int recvsz; /* recv size */
|
||||
{
|
||||
CLIENT *cl; /* client handle */
|
||||
bool_t madefd = FALSE; /* whether fd opened here */
|
||||
long servtype;
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
/* nconf is handled below */
|
||||
_DIAGASSERT(svcaddr != NULL);
|
||||
|
||||
if (fd == RPC_ANYFD) {
|
||||
if (nconf == NULL) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
fd = __rpc_nconf2fd(nconf);
|
||||
|
||||
if (fd == -1)
|
||||
goto err;
|
||||
|
||||
madefd = TRUE;
|
||||
servtype = nconf->nc_semantics;
|
||||
if (!__rpc_fd2sockinfo(fd, &si))
|
||||
goto err;
|
||||
|
||||
bindresvport(fd, NULL);
|
||||
} else {
|
||||
if (!__rpc_fd2sockinfo(fd, &si))
|
||||
goto err;
|
||||
servtype = __rpc_socktype2seman(si.si_socktype);
|
||||
if (servtype == -1) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNHOST; /* XXX */
|
||||
goto err1;
|
||||
}
|
||||
|
||||
switch (servtype) {
|
||||
case NC_TPI_COTS_ORD:
|
||||
cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
|
||||
if (!nconf || !cl)
|
||||
break;
|
||||
__rpc_setnodelay(fd, &si);
|
||||
break;
|
||||
case NC_TPI_CLTS:
|
||||
cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
|
||||
break;
|
||||
default:
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (cl == NULL)
|
||||
goto err1; /* borrow errors from clnt_dg/vc creates */
|
||||
if (nconf) {
|
||||
cl->cl_netid = strdup(nconf->nc_netid);
|
||||
if (cl->cl_netid == NULL)
|
||||
goto err0;
|
||||
cl->cl_tp = strdup(nconf->nc_device);
|
||||
if (cl->cl_tp == NULL)
|
||||
goto err0;
|
||||
} else {
|
||||
cl->cl_netid = __UNCONST("");
|
||||
cl->cl_tp = __UNCONST("");
|
||||
}
|
||||
if (madefd) {
|
||||
(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
|
||||
/* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */
|
||||
};
|
||||
|
||||
return (cl);
|
||||
|
||||
err0:
|
||||
clnt_destroy(cl);
|
||||
err:
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
err1: if (madefd)
|
||||
(void) close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
/* $NetBSD: clnt_perror.c,v 1.28 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_perror.c,v 1.28 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clnt_perror.c
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
*/
|
||||
#include "namespace.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/auth.h>
|
||||
#include <rpc/clnt.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(clnt_pcreateerror,_clnt_pcreateerror)
|
||||
__weak_alias(clnt_perrno,_clnt_perrno)
|
||||
__weak_alias(clnt_perror,_clnt_perror)
|
||||
__weak_alias(clnt_spcreateerror,_clnt_spcreateerror)
|
||||
__weak_alias(clnt_sperrno,_clnt_sperrno)
|
||||
__weak_alias(clnt_sperror,_clnt_sperror)
|
||||
#endif
|
||||
|
||||
static char *buf;
|
||||
static size_t buflen;
|
||||
|
||||
static char *_buf __P((void));
|
||||
static char *auth_errmsg __P((enum auth_stat));
|
||||
|
||||
static char *
|
||||
_buf()
|
||||
{
|
||||
|
||||
buflen = 256;
|
||||
if (buf == 0)
|
||||
buf = malloc(buflen);
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Print reply error info
|
||||
*/
|
||||
char *
|
||||
clnt_sperror(rpch, s)
|
||||
CLIENT *rpch;
|
||||
const char *s;
|
||||
{
|
||||
struct rpc_err e;
|
||||
char *err;
|
||||
char *str;
|
||||
char *strstart;
|
||||
size_t len, i;
|
||||
|
||||
_DIAGASSERT(rpch != NULL);
|
||||
_DIAGASSERT(s != NULL);
|
||||
|
||||
str = _buf(); /* side effect: sets "buflen" */
|
||||
if (str == 0)
|
||||
return (0);
|
||||
len = buflen;
|
||||
strstart = str;
|
||||
CLNT_GETERR(rpch, &e);
|
||||
|
||||
i = snprintf(str, len, "%s: ", s);
|
||||
str += i;
|
||||
len -= i;
|
||||
|
||||
(void)strncpy(str, clnt_sperrno(e.re_status), len - 1);
|
||||
i = strlen(str);
|
||||
str += i;
|
||||
len -= i;
|
||||
|
||||
switch (e.re_status) {
|
||||
case RPC_SUCCESS:
|
||||
case RPC_CANTENCODEARGS:
|
||||
case RPC_CANTDECODERES:
|
||||
case RPC_TIMEDOUT:
|
||||
case RPC_PROGUNAVAIL:
|
||||
case RPC_PROCUNAVAIL:
|
||||
case RPC_CANTDECODEARGS:
|
||||
case RPC_SYSTEMERROR:
|
||||
case RPC_UNKNOWNHOST:
|
||||
case RPC_UNKNOWNPROTO:
|
||||
case RPC_PMAPFAILURE:
|
||||
case RPC_PROGNOTREGISTERED:
|
||||
case RPC_FAILED:
|
||||
break;
|
||||
|
||||
case RPC_CANTSEND:
|
||||
case RPC_CANTRECV:
|
||||
i = snprintf(str, len, "; errno = %s", strerror(e.re_errno));
|
||||
str += i;
|
||||
len -= i;
|
||||
break;
|
||||
|
||||
case RPC_VERSMISMATCH:
|
||||
i = snprintf(str, len, "; low version = %u, high version = %u",
|
||||
e.re_vers.low, e.re_vers.high);
|
||||
str += i;
|
||||
len -= i;
|
||||
break;
|
||||
|
||||
case RPC_AUTHERROR:
|
||||
err = auth_errmsg(e.re_why);
|
||||
i = snprintf(str, len, "; why = ");
|
||||
str += i;
|
||||
len -= i;
|
||||
if (err != NULL) {
|
||||
i = snprintf(str, len, "%s",err);
|
||||
} else {
|
||||
i = snprintf(str, len,
|
||||
"(unknown authentication error - %d)",
|
||||
(int) e.re_why);
|
||||
}
|
||||
str += i;
|
||||
len -= i;
|
||||
break;
|
||||
|
||||
case RPC_PROGVERSMISMATCH:
|
||||
i = snprintf(str, len, "; low version = %u, high version = %u",
|
||||
e.re_vers.low, e.re_vers.high);
|
||||
str += i;
|
||||
len -= i;
|
||||
break;
|
||||
|
||||
default: /* unknown */
|
||||
i = snprintf(str, len, "; s1 = %u, s2 = %u",
|
||||
e.re_lb.s1, e.re_lb.s2);
|
||||
str += i;
|
||||
len -= i;
|
||||
break;
|
||||
}
|
||||
return(strstart) ;
|
||||
}
|
||||
|
||||
void
|
||||
clnt_perror(rpch, s)
|
||||
CLIENT *rpch;
|
||||
const char *s;
|
||||
{
|
||||
|
||||
_DIAGASSERT(rpch != NULL);
|
||||
_DIAGASSERT(s != NULL);
|
||||
|
||||
(void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
|
||||
}
|
||||
|
||||
static const char *const rpc_errlist[] = {
|
||||
[RPC_SUCCESS] = "RPC: Success",
|
||||
[RPC_CANTENCODEARGS] = "RPC: Can't encode arguments",
|
||||
[RPC_CANTDECODERES] = "RPC: Can't decode result",
|
||||
[RPC_CANTSEND] = "RPC: Unable to send",
|
||||
[RPC_CANTRECV] = "RPC: Unable to receive",
|
||||
[RPC_TIMEDOUT] = "RPC: Timed out",
|
||||
[RPC_VERSMISMATCH] = "RPC: Incompatible versions of RPC",
|
||||
[RPC_AUTHERROR] = "RPC: Authentication error",
|
||||
[RPC_PROGUNAVAIL] = "RPC: Program unavailable",
|
||||
[RPC_PROGVERSMISMATCH] = "RPC: Program/version mismatch",
|
||||
[RPC_PROCUNAVAIL] = "RPC: Procedure unavailable",
|
||||
[RPC_CANTDECODEARGS] = "RPC: Server can't decode arguments",
|
||||
[RPC_SYSTEMERROR] = "RPC: Remote system error",
|
||||
[RPC_UNKNOWNHOST] = "RPC: Unknown host",
|
||||
[RPC_PMAPFAILURE] = "RPC: Port mapper failure",
|
||||
[RPC_PROGNOTREGISTERED] = "RPC: Program not registered",
|
||||
[RPC_FAILED] = "RPC: Failed (unspecified error)",
|
||||
[RPC_UNKNOWNPROTO] = "RPC: Unknown protocol",
|
||||
[RPC_UNKNOWNADDR] = "RPC: Remote address unknown",
|
||||
[RPC_TLIERROR] = "RPC: Misc error in the TLI library",
|
||||
[RPC_NOBROADCAST] = "RPC: Broadcasting not supported",
|
||||
[RPC_N2AXLATEFAILURE] = "RPC: Name -> addr translation failed",
|
||||
[RPC_INPROGRESS] = "RPC: In progress",
|
||||
[RPC_STALERACHANDLE] = "RPC: Stale handle",
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* This interface for use by clntrpc
|
||||
*/
|
||||
char *
|
||||
clnt_sperrno(stat)
|
||||
enum clnt_stat stat;
|
||||
{
|
||||
unsigned int errnum = stat;
|
||||
const char *msg;
|
||||
|
||||
msg = NULL;
|
||||
if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) {
|
||||
msg = rpc_errlist[errnum];
|
||||
}
|
||||
if (msg == NULL) {
|
||||
msg = "RPC: (unknown error code)";
|
||||
}
|
||||
return __UNCONST(msg);
|
||||
}
|
||||
|
||||
void
|
||||
clnt_perrno(num)
|
||||
enum clnt_stat num;
|
||||
{
|
||||
(void) fprintf(stderr, "%s\n", clnt_sperrno(num));
|
||||
}
|
||||
|
||||
|
||||
char *
|
||||
clnt_spcreateerror(s)
|
||||
const char *s;
|
||||
{
|
||||
char *str;
|
||||
size_t len, i;
|
||||
|
||||
_DIAGASSERT(s != NULL);
|
||||
|
||||
str = _buf(); /* side effect: sets "buflen" */
|
||||
if (str == 0)
|
||||
return(0);
|
||||
len = buflen;
|
||||
i = snprintf(str, len, "%s: ", s);
|
||||
len -= i;
|
||||
(void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
|
||||
switch (rpc_createerr.cf_stat) {
|
||||
case RPC_PMAPFAILURE:
|
||||
(void) strncat(str, " - ", len - 1);
|
||||
(void) strncat(str,
|
||||
clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4);
|
||||
break;
|
||||
|
||||
case RPC_SYSTEMERROR:
|
||||
(void)strncat(str, " - ", len - 1);
|
||||
(void)strncat(str, strerror(rpc_createerr.cf_error.re_errno),
|
||||
len - 4);
|
||||
break;
|
||||
|
||||
case RPC_CANTSEND:
|
||||
case RPC_CANTDECODERES:
|
||||
case RPC_CANTENCODEARGS:
|
||||
case RPC_SUCCESS:
|
||||
case RPC_UNKNOWNPROTO:
|
||||
case RPC_PROGNOTREGISTERED:
|
||||
case RPC_FAILED:
|
||||
case RPC_UNKNOWNHOST:
|
||||
case RPC_CANTDECODEARGS:
|
||||
case RPC_PROCUNAVAIL:
|
||||
case RPC_PROGVERSMISMATCH:
|
||||
case RPC_PROGUNAVAIL:
|
||||
case RPC_AUTHERROR:
|
||||
case RPC_VERSMISMATCH:
|
||||
case RPC_TIMEDOUT:
|
||||
case RPC_CANTRECV:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return (str);
|
||||
}
|
||||
|
||||
void
|
||||
clnt_pcreateerror(s)
|
||||
const char *s;
|
||||
{
|
||||
|
||||
_DIAGASSERT(s != NULL);
|
||||
|
||||
(void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
|
||||
}
|
||||
|
||||
static const char *const auth_errlist[] = {
|
||||
"Authentication OK", /* 0 - AUTH_OK */
|
||||
"Invalid client credential", /* 1 - AUTH_BADCRED */
|
||||
"Server rejected credential", /* 2 - AUTH_REJECTEDCRED */
|
||||
"Invalid client verifier", /* 3 - AUTH_BADVERF */
|
||||
"Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */
|
||||
"Client credential too weak", /* 5 - AUTH_TOOWEAK */
|
||||
"Invalid server verifier", /* 6 - AUTH_INVALIDRESP */
|
||||
"Failed (unspecified error)" /* 7 - AUTH_FAILED */
|
||||
};
|
||||
|
||||
static char *
|
||||
auth_errmsg(stat)
|
||||
enum auth_stat stat;
|
||||
{
|
||||
unsigned int errnum = stat;
|
||||
|
||||
if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
|
||||
return __UNCONST(auth_errlist[errnum]);
|
||||
|
||||
return(NULL);
|
||||
}
|
||||
@@ -0,0 +1,331 @@
|
||||
/* $NetBSD: clnt_raw.c,v 1.29 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_raw.c,v 1.29 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clnt_raw.c
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* Memory based rpc for simple testing and timing.
|
||||
* Interface to create an rpc client and server in the same process.
|
||||
* This lets us similate rpc and get round trip overhead, without
|
||||
* any interference from the kernel.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/raw.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(clntraw_create,_clntraw_create)
|
||||
__weak_alias(clnt_raw_create,_clnt_raw_create)
|
||||
#endif
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t clntraw_lock;
|
||||
#endif
|
||||
|
||||
#define MCALL_MSG_SIZE 24
|
||||
|
||||
/*
|
||||
* This is the "network" we will be moving stuff over.
|
||||
*/
|
||||
static struct clntraw_private {
|
||||
CLIENT client_object;
|
||||
XDR xdr_stream;
|
||||
char *_raw_buf;
|
||||
union {
|
||||
struct rpc_msg mashl_rpcmsg;
|
||||
char mashl_callmsg[MCALL_MSG_SIZE];
|
||||
} u;
|
||||
u_int mcnt;
|
||||
} *clntraw_private;
|
||||
|
||||
static enum clnt_stat clnt_raw_call __P((CLIENT *, rpcproc_t, xdrproc_t,
|
||||
const char *, xdrproc_t, caddr_t, struct timeval));
|
||||
static void clnt_raw_geterr __P((CLIENT *, struct rpc_err *));
|
||||
static bool_t clnt_raw_freeres __P((CLIENT *, xdrproc_t, caddr_t));
|
||||
static void clnt_raw_abort __P((CLIENT *));
|
||||
static bool_t clnt_raw_control __P((CLIENT *, u_int, char *));
|
||||
static void clnt_raw_destroy __P((CLIENT *));
|
||||
static struct clnt_ops *clnt_raw_ops __P((void));
|
||||
|
||||
/*
|
||||
* Create a client handle for memory based rpc.
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_raw_create(prog, vers)
|
||||
rpcprog_t prog;
|
||||
rpcvers_t vers;
|
||||
{
|
||||
struct clntraw_private *clp = clntraw_private;
|
||||
struct rpc_msg call_msg;
|
||||
XDR *xdrs = &clp->xdr_stream;
|
||||
CLIENT *client = &clp->client_object;
|
||||
|
||||
mutex_lock(&clntraw_lock);
|
||||
if (clp == NULL) {
|
||||
clp = calloc((size_t)1, sizeof (*clp));
|
||||
if (clp == NULL)
|
||||
goto out;
|
||||
if (__rpc_rawcombuf == NULL)
|
||||
__rpc_rawcombuf =
|
||||
malloc(UDPMSGSIZE);
|
||||
if (__rpc_rawcombuf == NULL)
|
||||
goto out;
|
||||
clp->_raw_buf = __rpc_rawcombuf;
|
||||
clntraw_private = clp;
|
||||
}
|
||||
/*
|
||||
* 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;
|
||||
/* XXX: prog and vers have been long historically :-( */
|
||||
call_msg.rm_call.cb_prog = (u_int32_t)prog;
|
||||
call_msg.rm_call.cb_vers = (u_int32_t)vers;
|
||||
xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
|
||||
if (! xdr_callhdr(xdrs, &call_msg))
|
||||
warnx("clntraw_create - 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 = clnt_raw_ops();
|
||||
client->cl_auth = authnone_create();
|
||||
mutex_unlock(&clntraw_lock);
|
||||
return (client);
|
||||
out:
|
||||
if (clp)
|
||||
free(clp);
|
||||
mutex_unlock(&clntraw_lock);
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static enum clnt_stat
|
||||
clnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
|
||||
CLIENT *h;
|
||||
rpcproc_t proc;
|
||||
xdrproc_t xargs;
|
||||
const char *argsp;
|
||||
xdrproc_t xresults;
|
||||
caddr_t resultsp;
|
||||
struct timeval timeout;
|
||||
{
|
||||
struct clntraw_private *clp = clntraw_private;
|
||||
XDR *xdrs = &clp->xdr_stream;
|
||||
struct rpc_msg msg;
|
||||
enum clnt_stat status;
|
||||
struct rpc_err error;
|
||||
|
||||
_DIAGASSERT(h != NULL);
|
||||
|
||||
mutex_lock(&clntraw_lock);
|
||||
if (clp == NULL) {
|
||||
mutex_unlock(&clntraw_lock);
|
||||
return (RPC_FAILED);
|
||||
}
|
||||
mutex_unlock(&clntraw_lock);
|
||||
|
||||
call_again:
|
||||
/*
|
||||
* send request
|
||||
*/
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
XDR_SETPOS(xdrs, 0);
|
||||
clp->u.mashl_rpcmsg.rm_xid ++ ;
|
||||
if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
|
||||
(! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
|
||||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
|
||||
(! (*xargs)(xdrs, __UNCONST(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_common(FD_SETSIZE);
|
||||
|
||||
/*
|
||||
* 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)) {
|
||||
/*
|
||||
* It's possible for xdr_replymsg() to fail partway
|
||||
* through its attempt to decode the result from the
|
||||
* server. If this happens, it will leave the reply
|
||||
* structure partially populated with dynamically
|
||||
* allocated memory. (This can happen if someone uses
|
||||
* clntudp_bufcreate() to create a CLIENT handle and
|
||||
* specifies a receive buffer size that is too small.)
|
||||
* This memory must be free()ed to avoid a leak.
|
||||
*/
|
||||
int op = xdrs->x_op;
|
||||
xdrs->x_op = XDR_FREE;
|
||||
xdr_replymsg(xdrs, &msg);
|
||||
xdrs->x_op = op;
|
||||
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);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
clnt_raw_geterr(cl, error)
|
||||
CLIENT *cl;
|
||||
struct rpc_err *error;
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
clnt_raw_freeres(cl, xdr_res, res_ptr)
|
||||
CLIENT *cl;
|
||||
xdrproc_t xdr_res;
|
||||
caddr_t res_ptr;
|
||||
{
|
||||
struct clntraw_private *clp = clntraw_private;
|
||||
XDR *xdrs = &clp->xdr_stream;
|
||||
bool_t rval;
|
||||
|
||||
mutex_lock(&clntraw_lock);
|
||||
if (clp == NULL) {
|
||||
rval = (bool_t) RPC_FAILED;
|
||||
mutex_unlock(&clntraw_lock);
|
||||
return (rval);
|
||||
}
|
||||
mutex_unlock(&clntraw_lock);
|
||||
xdrs->x_op = XDR_FREE;
|
||||
return ((*xdr_res)(xdrs, res_ptr));
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
clnt_raw_abort(cl)
|
||||
CLIENT *cl;
|
||||
{
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
clnt_raw_control(cl, ui, str)
|
||||
CLIENT *cl;
|
||||
u_int ui;
|
||||
char *str;
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
clnt_raw_destroy(cl)
|
||||
CLIENT *cl;
|
||||
{
|
||||
}
|
||||
|
||||
static struct clnt_ops *
|
||||
clnt_raw_ops()
|
||||
{
|
||||
static struct clnt_ops ops;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
#endif
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops */
|
||||
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.cl_call == NULL) {
|
||||
ops.cl_call = clnt_raw_call;
|
||||
ops.cl_abort = clnt_raw_abort;
|
||||
ops.cl_geterr = clnt_raw_geterr;
|
||||
ops.cl_freeres = clnt_raw_freeres;
|
||||
ops.cl_destroy = clnt_raw_destroy;
|
||||
ops.cl_control = clnt_raw_control;
|
||||
}
|
||||
mutex_unlock(&ops_lock);
|
||||
return (&ops);
|
||||
}
|
||||
@@ -0,0 +1,216 @@
|
||||
/* $NetBSD: clnt_simple.c,v 1.30 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)clnt_simple.c 1.17 94/04/24 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)clnt_simple.c 1.49 89/01/31 Copyr 1984 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_simple.c,v 1.30 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clnt_simple.c
|
||||
* Simplified front end to client rpc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/param.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(rpc_call,_rpc_call)
|
||||
#endif
|
||||
|
||||
#ifndef MAXHOSTNAMELEN
|
||||
#define MAXHOSTNAMELEN 64
|
||||
#endif
|
||||
|
||||
#ifndef NETIDLEN
|
||||
#define NETIDLEN 32
|
||||
#endif
|
||||
|
||||
struct rpc_call_private {
|
||||
int valid; /* Is this entry valid ? */
|
||||
CLIENT *client; /* Client handle */
|
||||
pid_t pid; /* process-id at moment of creation */
|
||||
rpcprog_t prognum; /* Program */
|
||||
rpcvers_t versnum; /* Version */
|
||||
char host[MAXHOSTNAMELEN]; /* Servers host */
|
||||
char nettype[NETIDLEN]; /* Network type */
|
||||
};
|
||||
static struct rpc_call_private *rpc_call_private_main;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
static void rpc_call_destroy __P((void *));
|
||||
|
||||
static void
|
||||
rpc_call_destroy(void *vp)
|
||||
{
|
||||
struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
|
||||
|
||||
if (rcp) {
|
||||
if (rcp->client)
|
||||
CLNT_DESTROY(rcp->client);
|
||||
free(rcp);
|
||||
}
|
||||
}
|
||||
static thread_key_t rpc_call_key;
|
||||
static once_t rpc_call_once = ONCE_INITIALIZER;
|
||||
|
||||
static void
|
||||
rpc_call_setup(void)
|
||||
{
|
||||
|
||||
thr_keycreate(&rpc_call_key, rpc_call_destroy);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* This is the simplified interface to the client rpc layer.
|
||||
* The client handle is not destroyed here and is reused for
|
||||
* the future calls to same prog, vers, host and nettype combination.
|
||||
*
|
||||
* The total time available is 25 seconds.
|
||||
*/
|
||||
enum clnt_stat
|
||||
rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
|
||||
const char *host; /* host name */
|
||||
rpcprog_t prognum; /* program number */
|
||||
rpcvers_t versnum; /* version number */
|
||||
rpcproc_t procnum; /* procedure number */
|
||||
xdrproc_t inproc, outproc; /* in/out XDR procedures */
|
||||
const char *in;
|
||||
char *out; /* recv/send data */
|
||||
const char *nettype; /* nettype */
|
||||
{
|
||||
struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
|
||||
enum clnt_stat clnt_stat;
|
||||
struct timeval timeout, tottimeout;
|
||||
|
||||
_DIAGASSERT(host != NULL);
|
||||
/* XXX: in may be NULL ??? */
|
||||
/* XXX: out may be NULL ??? */
|
||||
/* XXX: nettype may be NULL ??? */
|
||||
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0) {
|
||||
rcp = rpc_call_private_main;
|
||||
} else {
|
||||
thr_once(&rpc_call_once, rpc_call_setup);
|
||||
rcp = thr_getspecific(rpc_call_key);
|
||||
}
|
||||
#else
|
||||
rcp = rpc_call_private_main;
|
||||
#endif
|
||||
if (rcp == NULL) {
|
||||
rcp = malloc(sizeof (*rcp));
|
||||
if (rcp == NULL) {
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
return (rpc_createerr.cf_stat);
|
||||
}
|
||||
if (__isthreaded == 0)
|
||||
rpc_call_private_main = rcp;
|
||||
else
|
||||
thr_setspecific(rpc_call_key, (void *) rcp);
|
||||
rcp->valid = 0;
|
||||
rcp->client = NULL;
|
||||
}
|
||||
if ((nettype == NULL) || (nettype[0] == 0))
|
||||
nettype = "netpath";
|
||||
if (!(rcp->valid && rcp->pid == getpid() &&
|
||||
(rcp->prognum == prognum) &&
|
||||
(rcp->versnum == versnum) &&
|
||||
(!strcmp(rcp->host, host)) &&
|
||||
(!strcmp(rcp->nettype, nettype)))) {
|
||||
int fd;
|
||||
|
||||
rcp->valid = 0;
|
||||
if (rcp->client)
|
||||
CLNT_DESTROY(rcp->client);
|
||||
/*
|
||||
* Using the first successful transport for that type
|
||||
*/
|
||||
rcp->client = clnt_create(host, prognum, versnum, nettype);
|
||||
rcp->pid = getpid();
|
||||
if (rcp->client == NULL) {
|
||||
return (rpc_createerr.cf_stat);
|
||||
}
|
||||
/*
|
||||
* Set time outs for connectionless case. Do it
|
||||
* unconditionally. Faster than doing a t_getinfo()
|
||||
* and then doing the right thing.
|
||||
*/
|
||||
timeout.tv_usec = 0;
|
||||
timeout.tv_sec = 5;
|
||||
(void) CLNT_CONTROL(rcp->client,
|
||||
CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
|
||||
if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
|
||||
(void)fcntl(fd, F_SETFD, FD_CLOEXEC);
|
||||
rcp->prognum = prognum;
|
||||
rcp->versnum = versnum;
|
||||
if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
|
||||
(strlen(nettype) < (size_t)NETIDLEN)) {
|
||||
(void) strcpy(rcp->host, host);
|
||||
(void) strcpy(rcp->nettype, nettype);
|
||||
rcp->valid = 1;
|
||||
} else {
|
||||
rcp->valid = 0;
|
||||
}
|
||||
} /* else reuse old client */
|
||||
tottimeout.tv_sec = 25;
|
||||
tottimeout.tv_usec = 0;
|
||||
clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, in,
|
||||
outproc, out, tottimeout);
|
||||
/*
|
||||
* if call failed, empty cache
|
||||
*/
|
||||
if (clnt_stat != RPC_SUCCESS)
|
||||
rcp->valid = 0;
|
||||
return (clnt_stat);
|
||||
}
|
||||
@@ -0,0 +1,783 @@
|
||||
/* $NetBSD: clnt_vc.c,v 1.17 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
static char sccsid[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: clnt_vc.c,v 1.17 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* clnt_tcp.c, Implements a TCP/IP based, client side RPC.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* TCP based RPC supports 'batched calls'.
|
||||
* A sequence of calls may be batched-up in a send buffer. The rpc call
|
||||
* return immediately to the client even though the call was not necessarily
|
||||
* sent. The batching occurs if the results' xdr routine is NULL (0) AND
|
||||
* the rpc timeout value is zero (see clnt.h, rpc).
|
||||
*
|
||||
* Clients should NOT casually batch calls that in fact return results; that is,
|
||||
* the server side should be aware that a call is batched and not produce any
|
||||
* return message. Batched calls that produce many result messages can
|
||||
* deadlock (netlock) the client and the server....
|
||||
*
|
||||
* Now go hang yourself.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(clnt_vc_create,_clnt_vc_create)
|
||||
#endif
|
||||
|
||||
#define MCALL_MSG_SIZE 24
|
||||
|
||||
static enum clnt_stat clnt_vc_call __P((CLIENT *, rpcproc_t, xdrproc_t,
|
||||
const char *, xdrproc_t, caddr_t, struct timeval));
|
||||
static void clnt_vc_geterr __P((CLIENT *, struct rpc_err *));
|
||||
static bool_t clnt_vc_freeres __P((CLIENT *, xdrproc_t, caddr_t));
|
||||
static void clnt_vc_abort __P((CLIENT *));
|
||||
static bool_t clnt_vc_control __P((CLIENT *, u_int, char *));
|
||||
static void clnt_vc_destroy __P((CLIENT *));
|
||||
static struct clnt_ops *clnt_vc_ops __P((void));
|
||||
static bool_t time_not_ok __P((struct timeval *));
|
||||
static int read_vc __P((caddr_t, caddr_t, int));
|
||||
static int write_vc __P((caddr_t, caddr_t, int));
|
||||
|
||||
struct ct_data {
|
||||
int ct_fd;
|
||||
bool_t ct_closeit;
|
||||
struct timeval ct_wait;
|
||||
bool_t ct_waitset; /* wait set by clnt_control? */
|
||||
struct netbuf ct_addr;
|
||||
struct rpc_err ct_error;
|
||||
union {
|
||||
char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */
|
||||
u_int32_t ct_mcalli;
|
||||
} ct_u;
|
||||
u_int ct_mpos; /* pos after marshal */
|
||||
XDR ct_xdrs;
|
||||
};
|
||||
|
||||
/*
|
||||
* This machinery implements per-fd locks for MT-safety. It is not
|
||||
* sufficient to do per-CLIENT handle locks for MT-safety because a
|
||||
* user may create more than one CLIENT handle with the same fd behind
|
||||
* it. Therfore, we allocate an array of flags (vc_fd_locks), protected
|
||||
* by the clnt_fd_lock mutex, and an array (vc_cv) of condition variables
|
||||
* similarly protected. Vc_fd_lock[fd] == 1 => a call is activte on some
|
||||
* CLIENT handle created for that fd.
|
||||
* The current implementation holds locks across the entire RPC and reply.
|
||||
* Yes, this is silly, and as soon as this code is proven to work, this
|
||||
* should be the first thing fixed. One step at a time.
|
||||
*/
|
||||
#ifdef _REENTRANT
|
||||
static int *vc_fd_locks;
|
||||
#define __rpc_lock_value __isthreaded;
|
||||
extern mutex_t clnt_fd_lock;
|
||||
static cond_t *vc_cv;
|
||||
#define release_fd_lock(fd, mask) { \
|
||||
mutex_lock(&clnt_fd_lock); \
|
||||
vc_fd_locks[fd] = 0; \
|
||||
mutex_unlock(&clnt_fd_lock); \
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
|
||||
cond_signal(&vc_cv[fd]); \
|
||||
}
|
||||
#else
|
||||
#define release_fd_lock(fd,mask)
|
||||
#define __rpc_lock_value 0
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* Create a client handle for a connection.
|
||||
* Default options are set, which the user can change using clnt_control()'s.
|
||||
* The rpc/vc package does buffering similar to stdio, so the client
|
||||
* must pick send and receive buffer sizes, 0 => use the default.
|
||||
* NB: fd is copied into a private area.
|
||||
* NB: The rpch->cl_auth is set null authentication. Caller may wish to
|
||||
* set this something more useful.
|
||||
*
|
||||
* fd should be an open socket
|
||||
*/
|
||||
CLIENT *
|
||||
clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
|
||||
int fd;
|
||||
const struct netbuf *raddr;
|
||||
rpcprog_t prog;
|
||||
rpcvers_t vers;
|
||||
u_int sendsz;
|
||||
u_int recvsz;
|
||||
{
|
||||
CLIENT *h;
|
||||
struct ct_data *ct = NULL;
|
||||
struct rpc_msg call_msg;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t slen;
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
_DIAGASSERT(raddr != NULL);
|
||||
|
||||
h = mem_alloc(sizeof(*h));
|
||||
if (h == NULL) {
|
||||
warnx("clnt_vc_create: out of memory");
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
goto fooy;
|
||||
}
|
||||
ct = mem_alloc(sizeof(*ct));
|
||||
if (ct == NULL) {
|
||||
warnx("clnt_vc_create: out of memory");
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
goto fooy;
|
||||
}
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
#ifdef _REENTRANT
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
if (vc_fd_locks == NULL) {
|
||||
size_t cv_allocsz, fd_allocsz;
|
||||
int dtbsize = __rpc_dtbsize();
|
||||
|
||||
fd_allocsz = dtbsize * sizeof (int);
|
||||
vc_fd_locks = mem_alloc(fd_allocsz);
|
||||
if (vc_fd_locks == NULL) {
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
goto fooy;
|
||||
} else
|
||||
memset(vc_fd_locks, '\0', fd_allocsz);
|
||||
|
||||
_DIAGASSERT(vc_cv == NULL);
|
||||
cv_allocsz = dtbsize * sizeof (cond_t);
|
||||
vc_cv = mem_alloc(cv_allocsz);
|
||||
if (vc_cv == NULL) {
|
||||
mem_free(vc_fd_locks, fd_allocsz);
|
||||
vc_fd_locks = NULL;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
goto fooy;
|
||||
} else {
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dtbsize; i++)
|
||||
cond_init(&vc_cv[i], 0, (void *) 0);
|
||||
}
|
||||
} else
|
||||
_DIAGASSERT(vc_cv != NULL);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX - fvdl connecting while holding a mutex?
|
||||
*/
|
||||
slen = sizeof ss;
|
||||
if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
|
||||
if (errno != ENOTCONN) {
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
goto fooy;
|
||||
}
|
||||
if (connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
goto fooy;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
if (!__rpc_fd2sockinfo(fd, &si))
|
||||
goto fooy;
|
||||
|
||||
ct->ct_closeit = FALSE;
|
||||
|
||||
/*
|
||||
* Set up private data struct
|
||||
*/
|
||||
ct->ct_fd = fd;
|
||||
ct->ct_wait.tv_usec = 0;
|
||||
ct->ct_waitset = FALSE;
|
||||
ct->ct_addr.buf = malloc((size_t)raddr->maxlen);
|
||||
if (ct->ct_addr.buf == NULL)
|
||||
goto fooy;
|
||||
memcpy(ct->ct_addr.buf, &raddr->buf, (size_t)raddr->len);
|
||||
ct->ct_addr.len = raddr->maxlen;
|
||||
ct->ct_addr.maxlen = raddr->maxlen;
|
||||
|
||||
/*
|
||||
* Initialize call message
|
||||
*/
|
||||
call_msg.rm_xid = __RPC_GETXID();
|
||||
call_msg.rm_direction = CALL;
|
||||
call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
|
||||
call_msg.rm_call.cb_prog = (u_int32_t)prog;
|
||||
call_msg.rm_call.cb_vers = (u_int32_t)vers;
|
||||
|
||||
/*
|
||||
* pre-serialize the static part of the call msg and stash it away
|
||||
*/
|
||||
xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE,
|
||||
XDR_ENCODE);
|
||||
if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
|
||||
if (ct->ct_closeit) {
|
||||
(void)close(fd);
|
||||
}
|
||||
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.
|
||||
*/
|
||||
h->cl_ops = clnt_vc_ops();
|
||||
h->cl_private = ct;
|
||||
h->cl_auth = authnone_create();
|
||||
sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
|
||||
recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
|
||||
xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
|
||||
h->cl_private, read_vc, write_vc);
|
||||
return (h);
|
||||
|
||||
fooy:
|
||||
/*
|
||||
* Something goofed, free stuff and barf
|
||||
*/
|
||||
if (ct)
|
||||
mem_free(ct, sizeof(struct ct_data));
|
||||
if (h)
|
||||
mem_free(h, sizeof(CLIENT));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
static enum clnt_stat
|
||||
clnt_vc_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
|
||||
CLIENT *h;
|
||||
rpcproc_t proc;
|
||||
xdrproc_t xdr_args;
|
||||
const char *args_ptr;
|
||||
xdrproc_t xdr_results;
|
||||
caddr_t results_ptr;
|
||||
struct timeval timeout;
|
||||
{
|
||||
struct ct_data *ct;
|
||||
XDR *xdrs;
|
||||
struct rpc_msg reply_msg;
|
||||
u_int32_t x_id;
|
||||
u_int32_t *msg_x_id;
|
||||
bool_t shipnow;
|
||||
int refreshes = 2;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask, newmask;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(h != NULL);
|
||||
|
||||
ct = (struct ct_data *) h->cl_private;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
while (vc_fd_locks[ct->ct_fd])
|
||||
cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
|
||||
vc_fd_locks[ct->ct_fd] = __rpc_lock_value;
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
#endif
|
||||
|
||||
xdrs = &(ct->ct_xdrs);
|
||||
msg_x_id = &ct->ct_u.ct_mcalli;
|
||||
|
||||
if (!ct->ct_waitset) {
|
||||
if (time_not_ok(&timeout) == FALSE)
|
||||
ct->ct_wait = timeout;
|
||||
}
|
||||
|
||||
shipnow =
|
||||
(xdr_results == NULL && timeout.tv_sec == 0
|
||||
&& timeout.tv_usec == 0) ? FALSE : TRUE;
|
||||
|
||||
call_again:
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
ct->ct_error.re_status = RPC_SUCCESS;
|
||||
x_id = ntohl(--(*msg_x_id));
|
||||
if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) ||
|
||||
(! XDR_PUTINT32(xdrs, (int32_t *)&proc)) ||
|
||||
(! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
|
||||
(! (*xdr_args)(xdrs, __UNCONST(args_ptr)))) {
|
||||
if (ct->ct_error.re_status == RPC_SUCCESS)
|
||||
ct->ct_error.re_status = RPC_CANTENCODEARGS;
|
||||
(void)xdrrec_endofrecord(xdrs, TRUE);
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (ct->ct_error.re_status);
|
||||
}
|
||||
if (! xdrrec_endofrecord(xdrs, shipnow)) {
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (ct->ct_error.re_status = RPC_CANTSEND);
|
||||
}
|
||||
if (! shipnow) {
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (RPC_SUCCESS);
|
||||
}
|
||||
/*
|
||||
* Hack to provide rpc-based message passing
|
||||
*/
|
||||
if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return(ct->ct_error.re_status = RPC_TIMEDOUT);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Keep receiving until we get a valid transaction id
|
||||
*/
|
||||
xdrs->x_op = XDR_DECODE;
|
||||
for (;;) {
|
||||
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)) {
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
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;
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
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 */
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (ct->ct_error.re_status);
|
||||
}
|
||||
|
||||
static void
|
||||
clnt_vc_geterr(h, errp)
|
||||
CLIENT *h;
|
||||
struct rpc_err *errp;
|
||||
{
|
||||
struct ct_data *ct;
|
||||
|
||||
_DIAGASSERT(h != NULL);
|
||||
_DIAGASSERT(errp != NULL);
|
||||
|
||||
ct = (struct ct_data *) h->cl_private;
|
||||
*errp = ct->ct_error;
|
||||
}
|
||||
|
||||
static bool_t
|
||||
clnt_vc_freeres(cl, xdr_res, res_ptr)
|
||||
CLIENT *cl;
|
||||
xdrproc_t xdr_res;
|
||||
caddr_t res_ptr;
|
||||
{
|
||||
struct ct_data *ct;
|
||||
XDR *xdrs;
|
||||
bool_t dummy;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
|
||||
ct = (struct ct_data *)cl->cl_private;
|
||||
xdrs = &(ct->ct_xdrs);
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
#ifdef _REENTRANT
|
||||
while (vc_fd_locks[ct->ct_fd])
|
||||
cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
|
||||
#endif
|
||||
|
||||
xdrs->x_op = XDR_FREE;
|
||||
dummy = (*xdr_res)(xdrs, res_ptr);
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
cond_signal(&vc_cv[ct->ct_fd]);
|
||||
|
||||
return dummy;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
clnt_vc_abort(cl)
|
||||
CLIENT *cl;
|
||||
{
|
||||
}
|
||||
|
||||
static bool_t
|
||||
clnt_vc_control(cl, request, info)
|
||||
CLIENT *cl;
|
||||
u_int request;
|
||||
char *info;
|
||||
{
|
||||
struct ct_data *ct;
|
||||
void *infop = info;
|
||||
#ifdef _REENTRANT
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
|
||||
ct = (struct ct_data *)cl->cl_private;
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
#ifdef _REENTRANT
|
||||
while (vc_fd_locks[ct->ct_fd])
|
||||
cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
|
||||
vc_fd_locks[ct->ct_fd] = __rpc_lock_value;
|
||||
#endif
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
|
||||
switch (request) {
|
||||
case CLSET_FD_CLOSE:
|
||||
ct->ct_closeit = TRUE;
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (TRUE);
|
||||
case CLSET_FD_NCLOSE:
|
||||
ct->ct_closeit = FALSE;
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (TRUE);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* for other requests which use info */
|
||||
if (info == NULL) {
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
switch (request) {
|
||||
case CLSET_TIMEOUT:
|
||||
if (time_not_ok((struct timeval *)(void *)info)) {
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
ct->ct_wait = *(struct timeval *)infop;
|
||||
ct->ct_waitset = TRUE;
|
||||
break;
|
||||
case CLGET_TIMEOUT:
|
||||
*(struct timeval *)infop = ct->ct_wait;
|
||||
break;
|
||||
case CLGET_SERVER_ADDR:
|
||||
(void) memcpy(info, ct->ct_addr.buf, (size_t)ct->ct_addr.len);
|
||||
break;
|
||||
case CLGET_FD:
|
||||
*(int *)(void *)info = ct->ct_fd;
|
||||
break;
|
||||
case CLGET_SVC_ADDR:
|
||||
/* The caller should not free this memory area */
|
||||
*(struct netbuf *)(void *)info = ct->ct_addr;
|
||||
break;
|
||||
case CLSET_SVC_ADDR: /* set to new address */
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (FALSE);
|
||||
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
|
||||
*/
|
||||
*(u_int32_t *)(void *)info =
|
||||
ntohl(*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli);
|
||||
break;
|
||||
case CLSET_XID:
|
||||
/* This will set the xid of the NEXT call */
|
||||
*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli =
|
||||
htonl(*((u_int32_t *)(void *)info) + 1);
|
||||
/* increment by 1 as clnt_vc_call() decrements 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
|
||||
* begining of the RPC header. MUST be changed if the
|
||||
* call_struct is changed
|
||||
*/
|
||||
*(u_int32_t *)(void *)info =
|
||||
ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
|
||||
4 * BYTES_PER_XDR_UNIT));
|
||||
break;
|
||||
|
||||
case CLSET_VERS:
|
||||
*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
|
||||
4 * BYTES_PER_XDR_UNIT) =
|
||||
htonl(*(u_int32_t *)(void *)info);
|
||||
break;
|
||||
|
||||
case CLGET_PROG:
|
||||
/*
|
||||
* This RELIES on the information that, in the call body,
|
||||
* the program number field is the fourth field from the
|
||||
* begining of the RPC header. MUST be changed if the
|
||||
* call_struct is changed
|
||||
*/
|
||||
*(u_int32_t *)(void *)info =
|
||||
ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
|
||||
3 * BYTES_PER_XDR_UNIT));
|
||||
break;
|
||||
|
||||
case CLSET_PROG:
|
||||
*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
|
||||
3 * BYTES_PER_XDR_UNIT) =
|
||||
htonl(*(u_int32_t *)(void *)info);
|
||||
break;
|
||||
|
||||
default:
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (FALSE);
|
||||
}
|
||||
release_fd_lock(ct->ct_fd, mask);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
clnt_vc_destroy(cl)
|
||||
CLIENT *cl;
|
||||
{
|
||||
struct ct_data *ct;
|
||||
#ifdef _REENTRANT
|
||||
int ct_fd;
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
_DIAGASSERT(cl != NULL);
|
||||
|
||||
ct = (struct ct_data *) cl->cl_private;
|
||||
ct_fd = ct->ct_fd;
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&clnt_fd_lock);
|
||||
#ifdef _REENTRANT
|
||||
while (vc_fd_locks[ct_fd])
|
||||
cond_wait(&vc_cv[ct_fd], &clnt_fd_lock);
|
||||
#endif
|
||||
if (ct->ct_closeit && ct->ct_fd != -1) {
|
||||
(void)close(ct->ct_fd);
|
||||
}
|
||||
XDR_DESTROY(&(ct->ct_xdrs));
|
||||
if (ct->ct_addr.buf)
|
||||
free(ct->ct_addr.buf);
|
||||
mem_free(ct, sizeof(struct ct_data));
|
||||
mem_free(cl, sizeof(CLIENT));
|
||||
mutex_unlock(&clnt_fd_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
|
||||
cond_signal(&vc_cv[ct_fd]);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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
|
||||
read_vc(ctp, buf, len)
|
||||
caddr_t ctp;
|
||||
caddr_t buf;
|
||||
int len;
|
||||
{
|
||||
struct ct_data *ct = (struct ct_data *)(void *)ctp;
|
||||
struct pollfd fd;
|
||||
struct timespec ts;
|
||||
|
||||
if (len == 0)
|
||||
return (0);
|
||||
|
||||
TIMEVAL_TO_TIMESPEC(&ct->ct_wait, &ts);
|
||||
fd.fd = ct->ct_fd;
|
||||
fd.events = POLLIN;
|
||||
for (;;) {
|
||||
switch (pollts(&fd, 1, &ts, NULL)) {
|
||||
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_fd, buf, (size_t)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
|
||||
write_vc(ctp, buf, len)
|
||||
caddr_t ctp;
|
||||
caddr_t buf;
|
||||
int len;
|
||||
{
|
||||
struct ct_data *ct = (struct ct_data *)(void *)ctp;
|
||||
int i, cnt;
|
||||
|
||||
for (cnt = len; cnt > 0; cnt -= i, buf += i) {
|
||||
if ((i = write(ct->ct_fd, buf, (size_t)cnt)) == -1) {
|
||||
ct->ct_error.re_errno = errno;
|
||||
ct->ct_error.re_status = RPC_CANTSEND;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
static struct clnt_ops *
|
||||
clnt_vc_ops()
|
||||
{
|
||||
static struct clnt_ops ops;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
sigset_t mask;
|
||||
#endif
|
||||
sigset_t newmask;
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops */
|
||||
|
||||
sigfillset(&newmask);
|
||||
thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.cl_call == NULL) {
|
||||
ops.cl_call = clnt_vc_call;
|
||||
ops.cl_abort = clnt_vc_abort;
|
||||
ops.cl_geterr = clnt_vc_geterr;
|
||||
ops.cl_freeres = clnt_vc_freeres;
|
||||
ops.cl_destroy = clnt_vc_destroy;
|
||||
ops.cl_control = clnt_vc_control;
|
||||
}
|
||||
mutex_unlock(&ops_lock);
|
||||
thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
|
||||
return (&ops);
|
||||
}
|
||||
|
||||
/*
|
||||
* Make sure that the time is not garbage. -1 value is disallowed.
|
||||
* Note this is different from time_not_ok in clnt_dg.c
|
||||
*/
|
||||
static bool_t
|
||||
time_not_ok(t)
|
||||
struct timeval *t;
|
||||
{
|
||||
|
||||
_DIAGASSERT(t != NULL);
|
||||
|
||||
return (t->tv_sec <= -1 || t->tv_sec > 100000000 ||
|
||||
t->tv_usec <= -1 || t->tv_usec > 1000000);
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
.\" @(#)getnetconfig.3n 1.28 93/06/02 SMI; from SVr4
|
||||
.\" $NetBSD: getnetconfig.3,v 1.7 2003/04/16 13:34:43 wiz Exp $
|
||||
.\" Copyright 1989 AT&T
|
||||
.Dd April 22, 2000
|
||||
.Dt GETNETCONFIG 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm getnetconfig ,
|
||||
.Nm setnetconfig ,
|
||||
.Nm endnetconfig ,
|
||||
.Nm getnetconfigent ,
|
||||
.Nm freenetconfigent ,
|
||||
.Nm nc_perror ,
|
||||
.Nm nc_sperror
|
||||
.Nd get network configuration database entry
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In netconfig.h
|
||||
.Ft struct netconfig *
|
||||
.Fn getnetconfig "void *handlep"
|
||||
.Ft void *
|
||||
.Fn setnetconfig "void"
|
||||
.Ft int
|
||||
.Fn endnetconfig "void *handlep"
|
||||
.Ft struct netconfig *
|
||||
.Fn getnetconfigent "const char *netid"
|
||||
.Ft void
|
||||
.Fn freenetconfigent "struct netconfig *netconfigp"
|
||||
.Ft void
|
||||
.Fn nc_perror "const char *msg"
|
||||
.Ft char *
|
||||
.Fn nc_sperror "void"
|
||||
.Sh DESCRIPTION
|
||||
The library routines described on this page
|
||||
provide the application access to
|
||||
the system network configuration database,
|
||||
.Pa /etc/netconfig .
|
||||
.Bd -literal
|
||||
struct netconfig {
|
||||
char *nc_netid; /* Network ID */
|
||||
unsigned long nc_semantics; /* Semantics */
|
||||
unsigned long nc_flag; /* Flags */
|
||||
char *nc_protofmly; /* Protocol family */
|
||||
char *nc_proto; /* Protocol name */
|
||||
char *nc_device; /* Network device pathname */
|
||||
unsigned long nc_nlookups; /* Number of directory lookup libs */
|
||||
char **nc_lookups; /* Names of the libraries */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
.Fn getnetconfig
|
||||
returns a pointer to the
|
||||
current entry in the
|
||||
.Pa netconfig
|
||||
database, formatted as a struct netconfig.
|
||||
Successive calls will return successive netconfig
|
||||
entries in the netconfig database.
|
||||
.Fn getnetconfig
|
||||
can be used to search the entire netconfig
|
||||
file.
|
||||
.Fn getnetconfig
|
||||
returns
|
||||
.Dv NULL
|
||||
at the end of the file.
|
||||
.Fa handlep
|
||||
is the handle obtained through
|
||||
.Fn setnetconfig .
|
||||
.Pp
|
||||
A call to
|
||||
.Fn setnetconfig
|
||||
has the effect of ``binding'' to or
|
||||
``rewinding'' the netconfig database.
|
||||
.Fn setnetconfig
|
||||
must be called before the first call to
|
||||
.Fn getnetconfig
|
||||
and may be called at any other time.
|
||||
.Fn setnetconfig
|
||||
need not be called before a call to
|
||||
.Fn getnetconfigent .
|
||||
.Fn setnetconfig
|
||||
returns a unique handle to be used by
|
||||
.Fn getnetconfig .
|
||||
.Pp
|
||||
.Fn endnetconfig
|
||||
should be called when processing is complete to release resources for reuse.
|
||||
.Fa handlep
|
||||
is the handle obtained through
|
||||
.Fn setnetconfig .
|
||||
Programmers should be aware, however, that the last call to
|
||||
.Fn endnetconfig
|
||||
frees all memory allocated by
|
||||
.Fn getnetconfig
|
||||
for the
|
||||
struct netconfig data structure.
|
||||
.Fn endnetconfig
|
||||
may not be called before
|
||||
.Fn setnetconfig .
|
||||
.Pp
|
||||
.Fn getnetconfigent
|
||||
returns a pointer
|
||||
to the netconfig structure corresponding
|
||||
to
|
||||
.Fa netid .
|
||||
It returns
|
||||
.Dv NULL
|
||||
if
|
||||
.Fa netid
|
||||
is invalid
|
||||
(that is, does not name an entry in the netconfig database).
|
||||
.Pp
|
||||
.Fn freenetconfigent
|
||||
frees the netconfig structure pointed to by
|
||||
.Fa netconfigp
|
||||
(previously returned by
|
||||
.Fn getnetconfigent ) .
|
||||
.Pp
|
||||
.Fn nc_perror
|
||||
prints a message to the standard error indicating why any of the
|
||||
above routines failed.
|
||||
The message is prepended with the string
|
||||
.Fa msg
|
||||
and a colon.
|
||||
A newline character is appended at the end of the message.
|
||||
.Pp
|
||||
.Fn nc_sperror
|
||||
is similar to
|
||||
.Fn nc_perror
|
||||
but instead of sending the message
|
||||
to the standard error, will return a pointer to a string that
|
||||
contains the error message.
|
||||
.Pp
|
||||
.Fn nc_perror
|
||||
and
|
||||
.Fn nc_sperror
|
||||
can also be used with the
|
||||
.Va NETPATH
|
||||
access routines defined in
|
||||
.Xr getnetpath 3 .
|
||||
.Sh RETURN VALUES
|
||||
.Fn setnetconfig
|
||||
returns a unique handle to be used by
|
||||
.Fn getnetconfig .
|
||||
In the case of an error,
|
||||
.Fn setnetconfig
|
||||
returns NULL and
|
||||
.Fn nc_perror
|
||||
or
|
||||
.Fn nc_sperror
|
||||
can be used to print the reason for failure.
|
||||
.Pp
|
||||
.Fn getnetconfig
|
||||
returns a pointer to the current entry in the netconfig
|
||||
database, formatted as a struct netconfig.
|
||||
.Fn getnetconfig
|
||||
returns NULL
|
||||
at the end of the file, or upon failure.
|
||||
.Pp
|
||||
.Fn endnetconfig
|
||||
returns 0 on success and -1 on failure
|
||||
(for example, if
|
||||
.Fn setnetconfig
|
||||
was not called previously).
|
||||
.Pp
|
||||
On success,
|
||||
.Fn getnetconfigent
|
||||
returns a pointer to the
|
||||
.Li struct netconfig
|
||||
structure corresponding to
|
||||
.Ar netid ;
|
||||
otherwise it returns
|
||||
.Dv NULL .
|
||||
.Pp
|
||||
.Fn nc_sperror
|
||||
returns a pointer to a buffer which contains the error message string.
|
||||
This buffer is overwritten on each call.
|
||||
In multithreaded applications, this buffer is
|
||||
implemented as thread-specific data.
|
||||
.Sh FILES
|
||||
.Pa /etc/netconfig
|
||||
.Sh SEE ALSO
|
||||
.Xr getnetpath 3 ,
|
||||
.Xr netconfig 5
|
||||
@@ -0,0 +1,695 @@
|
||||
/* $NetBSD: getnetconfig.c,v 1.18 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user or with the express written consent of
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)getnetconfig.c 1.12 91/12/19 SMI";
|
||||
#else
|
||||
__RCSID("$NetBSD: getnetconfig.c,v 1.18 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <netconfig.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getnetconfig,_getnetconfig)
|
||||
__weak_alias(setnetconfig,_setnetconfig)
|
||||
__weak_alias(endnetconfig,_endnetconfig)
|
||||
__weak_alias(getnetconfigent,_getnetconfigent)
|
||||
__weak_alias(freenetconfigent,_freenetconfigent)
|
||||
__weak_alias(nc_perror,_nc_perror)
|
||||
__weak_alias(nc_sperror,_nc_sperror)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The five library routines in this file provide application access to the
|
||||
* system network configuration database, /etc/netconfig. In addition to the
|
||||
* netconfig database and the routines for accessing it, the environment
|
||||
* variable NETPATH and its corresponding routines in getnetpath.c may also be
|
||||
* used to specify the network transport to be used.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* netconfig errors
|
||||
*/
|
||||
|
||||
#define NC_NONETCONFIG ENOENT
|
||||
#define NC_NOMEM ENOMEM
|
||||
#define NC_NOTINIT EINVAL /* setnetconfig was not called first */
|
||||
#define NC_BADFILE EBADF /* format for netconfig file is bad */
|
||||
|
||||
/*
|
||||
* semantics as strings (should be in netconfig.h)
|
||||
*/
|
||||
#define NC_TPI_CLTS_S "tpi_clts"
|
||||
#define NC_TPI_COTS_S "tpi_cots"
|
||||
#define NC_TPI_COTS_ORD_S "tpi_cots_ord"
|
||||
#define NC_TPI_RAW_S "tpi_raw"
|
||||
|
||||
/*
|
||||
* flags as characters (also should be in netconfig.h)
|
||||
*/
|
||||
#define NC_NOFLAG_C '-'
|
||||
#define NC_VISIBLE_C 'v'
|
||||
#define NC_BROADCAST_C 'b'
|
||||
|
||||
/*
|
||||
* Character used to indicate there is no name-to-address lookup library
|
||||
*/
|
||||
#define NC_NOLOOKUP "-"
|
||||
|
||||
static const char * const _nc_errors[] = {
|
||||
"Netconfig database not found",
|
||||
"Not enough memory",
|
||||
"Not initialized",
|
||||
"Netconfig database has invalid format"
|
||||
};
|
||||
|
||||
struct netconfig_info {
|
||||
int eof; /* all entries has been read */
|
||||
int ref; /* # of times setnetconfig() has been called */
|
||||
struct netconfig_list *head; /* head of the list */
|
||||
struct netconfig_list *tail; /* last of the list */
|
||||
};
|
||||
|
||||
struct netconfig_list {
|
||||
char *linep; /* hold line read from netconfig */
|
||||
struct netconfig *ncp;
|
||||
struct netconfig_list *next;
|
||||
};
|
||||
|
||||
struct netconfig_vars {
|
||||
int valid; /* token that indicates valid netconfig_vars */
|
||||
int flag; /* first time flag */
|
||||
struct netconfig_list *nc_configs;
|
||||
/* pointer to the current netconfig entry */
|
||||
};
|
||||
|
||||
#define NC_VALID 0xfeed
|
||||
#define NC_STORAGE 0xf00d
|
||||
#define NC_INVALID 0
|
||||
|
||||
|
||||
static int *__nc_error __P((void));
|
||||
static int parse_ncp __P((char *, struct netconfig *));
|
||||
static struct netconfig *dup_ncp __P((struct netconfig *));
|
||||
|
||||
|
||||
static FILE *nc_file; /* for netconfig db */
|
||||
static struct netconfig_info ni = { 0, 0, NULL, NULL};
|
||||
|
||||
#define MAXNETCONFIGLINE 1000
|
||||
|
||||
#ifdef _REENTRANT
|
||||
static thread_key_t nc_key;
|
||||
static once_t nc_once = ONCE_INITIALIZER;
|
||||
|
||||
static void
|
||||
__nc_error_setup(void)
|
||||
{
|
||||
thr_keycreate(&nc_key, free);
|
||||
}
|
||||
#endif
|
||||
|
||||
static int *
|
||||
__nc_error()
|
||||
{
|
||||
#ifdef _REENTRANT
|
||||
int *nc_addr = NULL;
|
||||
#endif
|
||||
static int nc_error = 0;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0)
|
||||
return &nc_error;
|
||||
thr_once(&nc_once, __nc_error_setup);
|
||||
nc_addr = thr_getspecific(nc_key) ;
|
||||
if (nc_addr == NULL) {
|
||||
nc_addr = malloc(sizeof (int));
|
||||
if (nc_addr == NULL)
|
||||
return &nc_error;
|
||||
if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
|
||||
if (nc_addr)
|
||||
free(nc_addr);
|
||||
return &nc_error;
|
||||
}
|
||||
*nc_addr = 0;
|
||||
}
|
||||
return nc_addr;
|
||||
#else
|
||||
return &nc_error;
|
||||
#endif
|
||||
}
|
||||
|
||||
#define nc_error (*(__nc_error()))
|
||||
/*
|
||||
* A call to setnetconfig() establishes a /etc/netconfig "session". A session
|
||||
* "handle" is returned on a successful call. At the start of a session (after
|
||||
* a call to setnetconfig()) searches through the /etc/netconfig database will
|
||||
* proceed from the start of the file. The session handle must be passed to
|
||||
* getnetconfig() to parse the file. Each call to getnetconfig() using the
|
||||
* current handle will process one subsequent entry in /etc/netconfig.
|
||||
* setnetconfig() must be called before the first call to getnetconfig().
|
||||
* (Handles are used to allow for nested calls to setnetpath()).
|
||||
*
|
||||
* A new session is established with each call to setnetconfig(), with a new
|
||||
* handle being returned on each call. Previously established sessions remain
|
||||
* active until endnetconfig() is called with that session's handle as an
|
||||
* argument.
|
||||
*
|
||||
* setnetconfig() need *not* be called before a call to getnetconfigent().
|
||||
* setnetconfig() returns a NULL pointer on failure (for example, if
|
||||
* the netconfig database is not present).
|
||||
*/
|
||||
void *
|
||||
setnetconfig()
|
||||
{
|
||||
struct netconfig_vars *nc_vars;
|
||||
|
||||
if ((nc_vars = malloc(sizeof(*nc_vars))) == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* For multiple calls, i.e. nc_file is not NULL, we just return the
|
||||
* handle without reopening the netconfig db.
|
||||
*/
|
||||
ni.ref++;
|
||||
if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
|
||||
nc_vars->valid = NC_VALID;
|
||||
nc_vars->flag = 0;
|
||||
nc_vars->nc_configs = ni.head;
|
||||
return ((void *)nc_vars);
|
||||
}
|
||||
ni.ref--;
|
||||
nc_error = NC_NONETCONFIG;
|
||||
free(nc_vars);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* When first called, getnetconfig() returns a pointer to the first entry in
|
||||
* the netconfig database, formatted as a struct netconfig. On each subsequent
|
||||
* call, getnetconfig() returns a pointer to the next entry in the database.
|
||||
* getnetconfig() can thus be used to search the entire netconfig file.
|
||||
* getnetconfig() returns NULL at end of file.
|
||||
*/
|
||||
|
||||
struct netconfig *
|
||||
getnetconfig(handlep)
|
||||
void *handlep;
|
||||
{
|
||||
struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
|
||||
char *stringp; /* tmp string pointer */
|
||||
struct netconfig_list *list;
|
||||
struct netconfig *np;
|
||||
|
||||
/*
|
||||
* Verify that handle is valid
|
||||
*/
|
||||
if (ncp == NULL || nc_file == NULL) {
|
||||
nc_error = NC_NOTINIT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
switch (ncp->valid) {
|
||||
case NC_VALID:
|
||||
/*
|
||||
* If entry has already been read into the list,
|
||||
* we return the entry in the linked list.
|
||||
* If this is the first time call, check if there are any
|
||||
* entries in linked list. If no entries, we need to read the
|
||||
* netconfig db.
|
||||
* If we have been here and the next entry is there, we just
|
||||
* return it.
|
||||
*/
|
||||
if (ncp->flag == 0) { /* first time */
|
||||
ncp->flag = 1;
|
||||
ncp->nc_configs = ni.head;
|
||||
if (ncp->nc_configs != NULL) /* entry already exist */
|
||||
return(ncp->nc_configs->ncp);
|
||||
}
|
||||
else if (ncp->nc_configs != NULL &&
|
||||
ncp->nc_configs->next != NULL) {
|
||||
ncp->nc_configs = ncp->nc_configs->next;
|
||||
return(ncp->nc_configs->ncp);
|
||||
}
|
||||
|
||||
/*
|
||||
* If we cannot find the entry in the list and is end of file,
|
||||
* we give up.
|
||||
*/
|
||||
if (ni.eof == 1)
|
||||
return(NULL);
|
||||
break;
|
||||
default:
|
||||
nc_error = NC_NOTINIT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
stringp = malloc(MAXNETCONFIGLINE);
|
||||
if (stringp == NULL)
|
||||
return (NULL);
|
||||
|
||||
#ifdef MEM_CHK
|
||||
if (malloc_verify() == 0) {
|
||||
fprintf(stderr, "memory heap corrupted in getnetconfig\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Read a line from netconfig file.
|
||||
*/
|
||||
do {
|
||||
if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
|
||||
free(stringp);
|
||||
ni.eof = 1;
|
||||
return (NULL);
|
||||
}
|
||||
} while (*stringp == '#');
|
||||
|
||||
list = malloc(sizeof(*list));
|
||||
if (list == NULL) {
|
||||
free(stringp);
|
||||
return(NULL);
|
||||
}
|
||||
np = malloc(sizeof(*np));
|
||||
if (np == NULL) {
|
||||
free(stringp);
|
||||
free(list);
|
||||
return(NULL);
|
||||
}
|
||||
list->ncp = np;
|
||||
list->next = NULL;
|
||||
list->ncp->nc_lookups = NULL;
|
||||
list->linep = stringp;
|
||||
if (parse_ncp(stringp, list->ncp) == -1) {
|
||||
free(stringp);
|
||||
free(np);
|
||||
free(list);
|
||||
return (NULL);
|
||||
} else {
|
||||
/*
|
||||
* If this is the first entry that's been read, it is the
|
||||
* head of the list. If not, put the entry at the end of
|
||||
* the list. Reposition the current pointer of the handle to
|
||||
* the last entry in the list.
|
||||
*/
|
||||
if (ni.head == NULL) /* first entry */
|
||||
ni.head = ni.tail = list;
|
||||
else {
|
||||
ni.tail->next = list;
|
||||
ni.tail = ni.tail->next;
|
||||
}
|
||||
ncp->nc_configs = ni.tail;
|
||||
return(ni.tail->ncp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* endnetconfig() may be called to "unbind" or "close" the netconfig database
|
||||
* when processing is complete, releasing resources for reuse. endnetconfig()
|
||||
* may not be called before setnetconfig(). endnetconfig() returns 0 on
|
||||
* success and -1 on failure (for example, if setnetconfig() was not called
|
||||
* previously).
|
||||
*/
|
||||
int
|
||||
endnetconfig(handlep)
|
||||
void *handlep;
|
||||
{
|
||||
struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
|
||||
|
||||
struct netconfig_list *q, *p;
|
||||
|
||||
/*
|
||||
* Verify that handle is valid
|
||||
*/
|
||||
if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
|
||||
nc_handlep->valid != NC_STORAGE)) {
|
||||
nc_error = NC_NOTINIT;
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return 0 if anyone still needs it.
|
||||
*/
|
||||
nc_handlep->valid = NC_INVALID;
|
||||
nc_handlep->flag = 0;
|
||||
nc_handlep->nc_configs = NULL;
|
||||
if (--ni.ref > 0) {
|
||||
free(nc_handlep);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Noone needs these entries anymore, then frees them.
|
||||
* Make sure all info in netconfig_info structure has been
|
||||
* reinitialized.
|
||||
*/
|
||||
q = p = ni.head;
|
||||
ni.eof = ni.ref = 0;
|
||||
ni.head = NULL;
|
||||
ni.tail = NULL;
|
||||
while (q) {
|
||||
p = q->next;
|
||||
if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
|
||||
free(q->ncp);
|
||||
free(q->linep);
|
||||
free(q);
|
||||
q = p;
|
||||
}
|
||||
free(nc_handlep);
|
||||
|
||||
fclose(nc_file);
|
||||
nc_file = NULL;
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* getnetconfigent(netid) returns a pointer to the struct netconfig structure
|
||||
* corresponding to netid. It returns NULL if netid is invalid (that is, does
|
||||
* not name an entry in the netconfig database). It returns NULL and sets
|
||||
* errno in case of failure (for example, if the netconfig database cannot be
|
||||
* opened).
|
||||
*/
|
||||
|
||||
struct netconfig *
|
||||
getnetconfigent(netid)
|
||||
const char *netid;
|
||||
{
|
||||
FILE *file; /* NETCONFIG db's file pointer */
|
||||
char *linep; /* holds current netconfig line */
|
||||
char *stringp; /* temporary string pointer */
|
||||
struct netconfig *ncp = NULL; /* returned value */
|
||||
struct netconfig_list *list; /* pointer to cache list */
|
||||
|
||||
if (netid == NULL || strlen(netid) == 0)
|
||||
return (NULL);
|
||||
|
||||
/*
|
||||
* Look up table if the entries have already been read and parsed in
|
||||
* getnetconfig(), then copy this entry into a buffer and return it.
|
||||
* If we cannot find the entry in the current list and there are more
|
||||
* entries in the netconfig db that has not been read, we then read the
|
||||
* db and try find the match netid.
|
||||
* If all the netconfig db has been read and placed into the list and
|
||||
* there is no match for the netid, return NULL.
|
||||
*/
|
||||
if (ni.head != NULL) {
|
||||
for (list = ni.head; list; list = list->next) {
|
||||
if (strcmp(list->ncp->nc_netid, netid) == 0)
|
||||
return(dup_ncp(list->ncp));
|
||||
}
|
||||
if (ni.eof == 1) /* that's all the entries */
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if ((file = fopen(NETCONFIG, "r")) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
|
||||
fclose(file);
|
||||
return (NULL);
|
||||
}
|
||||
do {
|
||||
ptrdiff_t len;
|
||||
char *tmpp; /* tmp string pointer */
|
||||
|
||||
do {
|
||||
if ((stringp = fgets(linep, MAXNETCONFIGLINE, file))
|
||||
== NULL)
|
||||
break;
|
||||
} while (*stringp == '#');
|
||||
if (stringp == NULL) /* eof */
|
||||
break;
|
||||
if ((tmpp = strpbrk(stringp, "\t ")) == NULL) {
|
||||
/* can't parse file */
|
||||
nc_error = NC_BADFILE;
|
||||
break;
|
||||
}
|
||||
if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */
|
||||
strncmp(stringp, netid, (size_t)len) == 0) {
|
||||
if ((ncp = malloc(sizeof(*ncp))) == NULL)
|
||||
break;
|
||||
ncp->nc_lookups = NULL;
|
||||
if (parse_ncp(linep, ncp) == -1) {
|
||||
free(ncp);
|
||||
ncp = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} while (stringp != NULL);
|
||||
if (ncp == NULL)
|
||||
free(linep);
|
||||
fclose(file);
|
||||
return(ncp);
|
||||
}
|
||||
|
||||
/*
|
||||
* freenetconfigent(netconfigp) frees the netconfig structure pointed to by
|
||||
* netconfigp (previously returned by getnetconfigent()).
|
||||
*/
|
||||
|
||||
void
|
||||
freenetconfigent(netconfigp)
|
||||
struct netconfig *netconfigp;
|
||||
{
|
||||
if (netconfigp != NULL) {
|
||||
/* holds all netconfigp's strings */
|
||||
free(netconfigp->nc_netid);
|
||||
if (netconfigp->nc_lookups != NULL)
|
||||
free(netconfigp->nc_lookups);
|
||||
free(netconfigp);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse line and stuff it in a struct netconfig
|
||||
* Typical line might look like:
|
||||
* udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
|
||||
*
|
||||
* We return -1 if any of the tokens don't parse, or malloc fails.
|
||||
*
|
||||
* Note that we modify stringp (putting NULLs after tokens) and
|
||||
* we set the ncp's string field pointers to point to these tokens within
|
||||
* stringp.
|
||||
*/
|
||||
|
||||
static int
|
||||
parse_ncp(stringp, ncp)
|
||||
char *stringp; /* string to parse */
|
||||
struct netconfig *ncp; /* where to put results */
|
||||
{
|
||||
char *tokenp; /* for processing tokens */
|
||||
char *lasts;
|
||||
|
||||
_DIAGASSERT(stringp != NULL);
|
||||
_DIAGASSERT(ncp != NULL);
|
||||
|
||||
nc_error = NC_BADFILE;
|
||||
/* nearly anything that breaks is for this reason */
|
||||
stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */
|
||||
/* netid */
|
||||
if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
|
||||
/* semantics */
|
||||
if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
|
||||
ncp->nc_semantics = NC_TPI_COTS_ORD;
|
||||
else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
|
||||
ncp->nc_semantics = NC_TPI_COTS;
|
||||
else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
|
||||
ncp->nc_semantics = NC_TPI_CLTS;
|
||||
else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
|
||||
ncp->nc_semantics = NC_TPI_RAW;
|
||||
else
|
||||
return (-1);
|
||||
|
||||
/* flags */
|
||||
if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0'; tokenp++) {
|
||||
switch (*tokenp) {
|
||||
case NC_NOFLAG_C:
|
||||
break;
|
||||
case NC_VISIBLE_C:
|
||||
ncp->nc_flag |= NC_VISIBLE;
|
||||
break;
|
||||
case NC_BROADCAST_C:
|
||||
ncp->nc_flag |= NC_BROADCAST;
|
||||
break;
|
||||
default:
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
/* protocol family */
|
||||
if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
/* protocol name */
|
||||
if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
/* network device */
|
||||
if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL)
|
||||
return (-1);
|
||||
if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
|
||||
ncp->nc_nlookups = 0;
|
||||
ncp->nc_lookups = NULL;
|
||||
} else {
|
||||
char *cp; /* tmp string */
|
||||
|
||||
if (ncp->nc_lookups != NULL) /* from last visit */
|
||||
free(ncp->nc_lookups);
|
||||
/* preallocate one string pointer */
|
||||
ncp->nc_lookups = malloc(sizeof(*ncp->nc_lookups));
|
||||
ncp->nc_nlookups = 0;
|
||||
while ((cp = tokenp) != NULL) {
|
||||
tokenp = _get_next_token(cp, ',');
|
||||
ncp->nc_lookups[(size_t)ncp->nc_nlookups++] = cp;
|
||||
ncp->nc_lookups = (char **)
|
||||
realloc(ncp->nc_lookups,
|
||||
(size_t)(ncp->nc_nlookups+1) *sizeof(char *));
|
||||
/* for next loop */
|
||||
}
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns a string describing the reason for failure.
|
||||
*/
|
||||
char *
|
||||
nc_sperror()
|
||||
{
|
||||
const char *message;
|
||||
|
||||
switch(nc_error) {
|
||||
case NC_NONETCONFIG:
|
||||
message = _nc_errors[0];
|
||||
break;
|
||||
case NC_NOMEM:
|
||||
message = _nc_errors[1];
|
||||
break;
|
||||
case NC_NOTINIT:
|
||||
message = _nc_errors[2];
|
||||
break;
|
||||
case NC_BADFILE:
|
||||
message = _nc_errors[3];
|
||||
break;
|
||||
default:
|
||||
message = "Unknown network selection error";
|
||||
}
|
||||
return __UNCONST(message);
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints a message onto standard error describing the reason for failure.
|
||||
*/
|
||||
void
|
||||
nc_perror(s)
|
||||
const char *s;
|
||||
{
|
||||
|
||||
_DIAGASSERT(s != NULL);
|
||||
|
||||
fprintf(stderr, "%s: %s", s, nc_sperror());
|
||||
}
|
||||
|
||||
/*
|
||||
* Duplicates the matched netconfig buffer.
|
||||
*/
|
||||
static struct netconfig *
|
||||
dup_ncp(ncp)
|
||||
struct netconfig *ncp;
|
||||
{
|
||||
struct netconfig *p;
|
||||
char *tmp;
|
||||
u_int i;
|
||||
|
||||
_DIAGASSERT(ncp != NULL);
|
||||
|
||||
if ((tmp = malloc(MAXNETCONFIGLINE)) == NULL)
|
||||
return(NULL);
|
||||
if ((p = malloc(sizeof(*p))) == NULL) {
|
||||
free(tmp);
|
||||
return(NULL);
|
||||
}
|
||||
/*
|
||||
* First we dup all the data from matched netconfig buffer. Then we
|
||||
* adjust some of the member pointer to a pre-allocated buffer where
|
||||
* contains part of the data.
|
||||
* To follow the convention used in parse_ncp(), we store all the
|
||||
* necessary information in the pre-allocated buffer and let each
|
||||
* of the netconfig char pointer member point to the right address
|
||||
* in the buffer.
|
||||
*/
|
||||
*p = *ncp;
|
||||
p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
|
||||
tmp = strchr(tmp, '\0') + 1;
|
||||
p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
|
||||
tmp = strchr(tmp, '\0') + 1;
|
||||
p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
|
||||
tmp = strchr(tmp, '\0') + 1;
|
||||
p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
|
||||
p->nc_lookups = malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
|
||||
if (p->nc_lookups == NULL) {
|
||||
free(p->nc_netid);
|
||||
free(p);
|
||||
return(NULL);
|
||||
}
|
||||
for (i=0; i < p->nc_nlookups; i++) {
|
||||
tmp = strchr(tmp, '\0') + 1;
|
||||
p->nc_lookups[i] = strcpy(tmp,ncp->nc_lookups[i]);
|
||||
}
|
||||
return(p);
|
||||
}
|
||||
@@ -0,0 +1,124 @@
|
||||
.\" @(#)getnetpath.3n 1.26 93/05/07 SMI; from SVr4
|
||||
.\" $NetBSD: getnetpath.3,v 1.6 2003/04/16 13:34:43 wiz Exp $
|
||||
.\" Copyright 1989 AT&T
|
||||
.Dd April 22, 2000
|
||||
.Dt GETNETPATH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm getnetpath ,
|
||||
.Nm setnetpath ,
|
||||
.Nm endnetpath
|
||||
.Nd get /etc/netconfig entry corresponding to NETPATH component
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In netconfig.h
|
||||
.Ft struct netconfig *
|
||||
.Fn getnetpath "void *handlep"
|
||||
.Ft void *
|
||||
.Fn setnetpath "void"
|
||||
.Ft int
|
||||
.Fn endnetpath "void *handlep"
|
||||
.Sh DESCRIPTION
|
||||
The routines described in this page provide the application access to the system
|
||||
network configuration database,
|
||||
.Pa /etc/netconfig ,
|
||||
as it is
|
||||
.Dq filtered
|
||||
by the NETPATH
|
||||
environment variable (see
|
||||
.Xr environ 7 ) .
|
||||
See
|
||||
.Xr getnetconfig 3
|
||||
for other routines that also access the
|
||||
network configuration database directly.
|
||||
The NETPATH variable is a list of colon-separated network identifiers.
|
||||
.Pp
|
||||
.Fn getnetpath
|
||||
returns a pointer to the
|
||||
netconfig database entry corresponding to the first valid
|
||||
NETPATH component.
|
||||
The netconfig entry is formatted as a struct netconfig.
|
||||
On each subsequent call,
|
||||
.Fn getnetpath
|
||||
returns a pointer to the netconfig entry that corresponds to the next
|
||||
valid NETPATH component.
|
||||
.Fn getnetpath
|
||||
can thus be used to search the netconfig database for all networks
|
||||
included in the NETPATH variable.
|
||||
When NETPATH has been exhausted,
|
||||
.Fn getnetpath
|
||||
returns NULL.
|
||||
.Pp
|
||||
A call to
|
||||
.Fn setnetpath
|
||||
.Dq binds
|
||||
to or
|
||||
.Dq rewinds
|
||||
NETPATH.
|
||||
.Fn setnetpath
|
||||
must be called before the first call to
|
||||
.Fn getnetpath
|
||||
and may be called at any other time.
|
||||
It returns a handle that is used by
|
||||
.Fn getnetpath .
|
||||
.Pp
|
||||
.Fn getnetpath
|
||||
silently ignores invalid NETPATH
|
||||
components.
|
||||
A NETPATH component is invalid if there is no corresponding
|
||||
entry in the netconfig database.
|
||||
.Pp
|
||||
If the NETPATH variable is unset,
|
||||
.Fn getnetpath
|
||||
behaves as if NETPATH
|
||||
were set to the sequence of
|
||||
.Dq default
|
||||
or
|
||||
.Dq visible
|
||||
networks in the netconfig database, in the
|
||||
order in which they are listed.
|
||||
.\"This proviso holds also for this
|
||||
.\"whole manpage.
|
||||
.Pp
|
||||
.Fn endnetpath
|
||||
may be called to
|
||||
.Dq unbind
|
||||
from NETPATH
|
||||
when processing is complete, releasing resources for reuse.
|
||||
Programmers should be aware, however, that
|
||||
.Fn endnetpath
|
||||
frees all memory allocated by
|
||||
.Fn getnetpath
|
||||
for the struct netconfig data structure.
|
||||
.Sh RETURN VALUES
|
||||
.Fn setnetpath
|
||||
returns a handle that is used by
|
||||
.Fn getnetpath .
|
||||
In case of an error,
|
||||
.Fn setnetpath
|
||||
returns NULL.
|
||||
.Pp
|
||||
.Fn endnetpath
|
||||
returns 0 on success and -1 on failure
|
||||
(for example, if
|
||||
.Fn setnetpath
|
||||
was not called previously).
|
||||
.Fn nc_perror
|
||||
or
|
||||
.Fn nc_sperror
|
||||
can be used to print out the reason for failure.
|
||||
See
|
||||
.Xr getnetconfig 3 .
|
||||
.Pp
|
||||
When first called,
|
||||
.Fn getnetpath
|
||||
returns a pointer to the netconfig database entry corresponding to the first
|
||||
valid NETPATH component.
|
||||
When NETPATH has been exhausted,
|
||||
.Fn getnetpath
|
||||
returns NULL.
|
||||
.Sh SEE ALSO
|
||||
.Xr getnetconfig 3 ,
|
||||
.Xr netconfig 5 ,
|
||||
.Xr environ 7
|
||||
@@ -0,0 +1,287 @@
|
||||
/* $NetBSD: getnetpath.c,v 1.14 2008/05/24 16:04:15 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user or with the express written consent of
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)getnetpath.c 1.11 91/12/19 SMI";
|
||||
#else
|
||||
__RCSID("$NetBSD: getnetpath.c,v 1.14 2008/05/24 16:04:15 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <netconfig.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getnetpath,_getnetpath)
|
||||
__weak_alias(setnetpath,_setnetpath)
|
||||
__weak_alias(endnetpath,_endnetpath)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* internal structure to keep track of a netpath "session"
|
||||
*/
|
||||
struct netpath_chain {
|
||||
struct netconfig *ncp; /* an nconf entry */
|
||||
struct netpath_chain *nchain_next; /* next nconf entry allocated */
|
||||
};
|
||||
|
||||
|
||||
struct netpath_vars {
|
||||
int valid; /* token that indicates a valid netpath_vars */
|
||||
void *nc_handlep; /* handle for current netconfig "session" */
|
||||
char *netpath; /* pointer to current view-point in NETPATH */
|
||||
char *netpath_start; /* pointer to start of our copy of NETPATH */
|
||||
struct netpath_chain *ncp_list; /* list of nconfs allocated this session*/
|
||||
};
|
||||
|
||||
#define NP_VALID 0xf00d
|
||||
#define NP_INVALID 0
|
||||
|
||||
char *_get_next_token __P((char *, int));
|
||||
|
||||
|
||||
/*
|
||||
* A call to setnetpath() establishes a NETPATH "session". setnetpath()
|
||||
* must be called before the first call to getnetpath(). A "handle" is
|
||||
* returned to distinguish the session; this handle should be passed
|
||||
* subsequently to getnetpath(). (Handles are used to allow for nested calls
|
||||
* to setnetpath()).
|
||||
* If setnetpath() is unable to establish a session (due to lack of memory
|
||||
* resources, or the absence of the /etc/netconfig file), a NULL pointer is
|
||||
* returned.
|
||||
*/
|
||||
|
||||
void *
|
||||
setnetpath()
|
||||
{
|
||||
struct netpath_vars *np_sessionp; /* this session's variables */
|
||||
char *npp; /* NETPATH env variable */
|
||||
|
||||
#ifdef MEM_CHK
|
||||
malloc_debug(1);
|
||||
#endif
|
||||
|
||||
if ((np_sessionp = malloc(sizeof(*np_sessionp))) == NULL)
|
||||
return (NULL);
|
||||
if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
|
||||
free(np_sessionp);
|
||||
syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
|
||||
return (NULL);
|
||||
}
|
||||
np_sessionp->valid = NP_VALID;
|
||||
np_sessionp->ncp_list = NULL;
|
||||
if ((npp = getenv(NETPATH)) == NULL)
|
||||
np_sessionp->netpath = NULL;
|
||||
else {
|
||||
(void) endnetconfig(np_sessionp->nc_handlep);
|
||||
/* won't need nc session*/
|
||||
np_sessionp->nc_handlep = NULL;
|
||||
if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL) {
|
||||
free(np_sessionp);
|
||||
return (NULL);
|
||||
} else
|
||||
(void) strcpy(np_sessionp->netpath, npp);
|
||||
}
|
||||
np_sessionp->netpath_start = np_sessionp->netpath;
|
||||
return ((void *)np_sessionp);
|
||||
}
|
||||
|
||||
/*
|
||||
* When first called, getnetpath() returns a pointer to the netconfig
|
||||
* database entry corresponding to the first valid NETPATH component. The
|
||||
* netconfig entry is formatted as a struct netconfig.
|
||||
* On each subsequent call, getnetpath returns a pointer to the netconfig
|
||||
* entry that corresponds to the next valid NETPATH component. getnetpath
|
||||
* can thus be used to search the netconfig database for all networks
|
||||
* included in the NETPATH variable.
|
||||
* When NETPATH has been exhausted, getnetpath() returns NULL. It returns
|
||||
* NULL and sets errno in case of an error (e.g., setnetpath was not called
|
||||
* previously).
|
||||
* getnetpath() silently ignores invalid NETPATH components. A NETPATH
|
||||
* compnent is invalid if there is no corresponding entry in the netconfig
|
||||
* database.
|
||||
* If the NETPATH variable is unset, getnetpath() behaves as if NETPATH
|
||||
* were set to the sequence of default or visible networks in the netconfig
|
||||
* database, in the order in which they are listed.
|
||||
*/
|
||||
|
||||
struct netconfig *
|
||||
getnetpath(handlep)
|
||||
void *handlep;
|
||||
{
|
||||
struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
|
||||
struct netconfig *ncp = NULL; /* temp. holds a netconfig session */
|
||||
struct netpath_chain *chainp; /* holds chain of ncp's we alloc */
|
||||
char *npp; /* holds current NETPATH */
|
||||
|
||||
if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
|
||||
errno = EINVAL;
|
||||
return (NULL);
|
||||
}
|
||||
if (np_sessionp->netpath_start == NULL) { /* NETPATH was not set */
|
||||
do { /* select next visible network */
|
||||
if (np_sessionp->nc_handlep == NULL) {
|
||||
np_sessionp->nc_handlep = setnetconfig();
|
||||
if (np_sessionp->nc_handlep == NULL)
|
||||
syslog (LOG_ERR,
|
||||
"rpc: failed to open " NETCONFIG);
|
||||
}
|
||||
if ((ncp = getnetconfig(np_sessionp->nc_handlep))
|
||||
== NULL)
|
||||
return(NULL);
|
||||
} while ((ncp->nc_flag & NC_VISIBLE) == 0);
|
||||
return (ncp);
|
||||
}
|
||||
/*
|
||||
* Find first valid network ID in netpath.
|
||||
*/
|
||||
while ((npp = np_sessionp->netpath) != NULL && strlen(npp) != 0) {
|
||||
np_sessionp->netpath = _get_next_token(npp, ':');
|
||||
/*
|
||||
* npp is a network identifier.
|
||||
*/
|
||||
if ((ncp = getnetconfigent(npp)) != NULL) {
|
||||
/* cobble alloc chain entry */
|
||||
chainp = malloc(sizeof (struct netpath_chain));
|
||||
if (chainp == NULL) {
|
||||
freenetconfigent(ncp);
|
||||
return NULL;
|
||||
}
|
||||
chainp->ncp = ncp;
|
||||
chainp->nchain_next = NULL;
|
||||
if (np_sessionp->ncp_list == NULL)
|
||||
np_sessionp->ncp_list = chainp;
|
||||
else
|
||||
np_sessionp->ncp_list->nchain_next = chainp;
|
||||
return (ncp);
|
||||
}
|
||||
/* couldn't find this token in the database; go to next one. */
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* endnetpath() may be called to unbind NETPATH when processing is complete,
|
||||
* releasing resources for reuse. It returns 0 on success and -1 on failure
|
||||
* (e.g. if setnetpath() was not called previously.
|
||||
*/
|
||||
int
|
||||
endnetpath(handlep)
|
||||
void *handlep;
|
||||
{
|
||||
struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
|
||||
struct netpath_chain *chainp, *lastp;
|
||||
|
||||
if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (np_sessionp->nc_handlep != NULL)
|
||||
endnetconfig(np_sessionp->nc_handlep);
|
||||
if (np_sessionp->netpath_start != NULL)
|
||||
free(np_sessionp->netpath_start);
|
||||
for (chainp = np_sessionp->ncp_list; chainp != NULL;
|
||||
lastp=chainp, chainp=chainp->nchain_next, free(lastp)) {
|
||||
freenetconfigent(chainp->ncp);
|
||||
}
|
||||
free(np_sessionp);
|
||||
#ifdef MEM_CHK
|
||||
if (malloc_verify() == 0) {
|
||||
fprintf(stderr, "memory heap corrupted in endnetpath\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Returns pointer to the rest-of-the-string after the current token.
|
||||
* The token itself starts at arg, and we null terminate it. We return NULL
|
||||
* if either the arg is empty, or if this is the last token.
|
||||
*/
|
||||
|
||||
char *
|
||||
_get_next_token(
|
||||
char *npp, /* string */
|
||||
int token /* char to parse string for */
|
||||
)
|
||||
{
|
||||
char *cp; /* char pointer */
|
||||
char *np; /* netpath pointer */
|
||||
char *ep; /* escape pointer */
|
||||
|
||||
_DIAGASSERT(npp != NULL);
|
||||
|
||||
if ((cp = strchr(npp, token)) == NULL)
|
||||
return (NULL);
|
||||
/*
|
||||
* did find a token, but it might be escaped.
|
||||
*/
|
||||
if ((cp > npp) && (cp[-1] == '\\')) {
|
||||
/*
|
||||
* if slash was also escaped, carry on, otherwise find
|
||||
* next token
|
||||
*/
|
||||
if ((cp > npp + 1) && (cp[-2] != '\\')) {
|
||||
/* shift r-o-s onto the escaped token */
|
||||
strcpy(&cp[-1], cp); /* XXX: overlapping string copy */
|
||||
/*
|
||||
* Do a recursive call.
|
||||
* We don't know how many escaped tokens there might be.
|
||||
*/
|
||||
return (_get_next_token(cp, token));
|
||||
}
|
||||
}
|
||||
|
||||
*cp++ = '\0'; /* null-terminate token */
|
||||
/* get rid of any backslash escapes */
|
||||
ep = npp;
|
||||
while ((np = strchr(ep, '\\')) != 0) {
|
||||
if (np[1] == '\\')
|
||||
np++;
|
||||
strcpy(np, (ep = &np[1])); /* XXX: overlapping string copy */
|
||||
}
|
||||
return (cp); /* return ptr to r-o-s */
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
|
||||
.\" $NetBSD: getrpcent.3,v 1.14 2004/08/16 10:18:27 wiz Exp $
|
||||
.\"
|
||||
.Dd August 16, 2004
|
||||
.Dt GETRPCENT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm getrpcent ,
|
||||
.Nm getrpcbyname ,
|
||||
.Nm getrpcbynumber ,
|
||||
.Nm endrpcent ,
|
||||
.Nm setrpcent
|
||||
.Nd get RPC entry
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft struct rpcent *
|
||||
.Fn getrpcent void
|
||||
.Ft struct rpcent *
|
||||
.Fn getrpcbyname "const char *name"
|
||||
.Ft struct rpcent *
|
||||
.Fn getrpcbynumber "int number"
|
||||
.Ft void
|
||||
.Fn setrpcent "int stayopen"
|
||||
.Ft void
|
||||
.Fn endrpcent void
|
||||
.Sh DESCRIPTION
|
||||
.Fn getrpcent ,
|
||||
.Fn getrpcbyname ,
|
||||
and
|
||||
.Fn getrpcbynumber ,
|
||||
each return a pointer to an object with the
|
||||
following structure
|
||||
containing the broken-out
|
||||
fields of a line in the rpc program number data base,
|
||||
.Pa /etc/rpc :
|
||||
.Bd -literal -offset indent
|
||||
struct rpcent {
|
||||
char *r_name; /* name of server for this rpc program */
|
||||
char **r_aliases; /* alias list */
|
||||
long r_number; /* rpc program number */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
The members of this structure are:
|
||||
.Bl -tag -width r_aliases -offset indent
|
||||
.It r_name
|
||||
The name of the server for this rpc program.
|
||||
.It r_aliases
|
||||
A zero terminated list of alternative names for the rpc program.
|
||||
.It r_number
|
||||
The rpc program number for this service.
|
||||
.El
|
||||
.Pp
|
||||
.Fn getrpcent
|
||||
reads the next line of the file, opening the file if necessary.
|
||||
.Pp
|
||||
.Fn setrpcent
|
||||
opens and rewinds the file.
|
||||
If the
|
||||
.Fa stayopen
|
||||
flag is non-zero,
|
||||
the net data base will not be closed after each call to
|
||||
.Fn getrpcent
|
||||
(either directly, or indirectly through one of
|
||||
the other
|
||||
.Dq getrpc
|
||||
calls).
|
||||
.Pp
|
||||
.Fn endrpcent
|
||||
closes the file.
|
||||
.Pp
|
||||
.Fn getrpcbyname
|
||||
and
|
||||
.Fn getrpcbynumber
|
||||
sequentially search from the beginning
|
||||
of the file until a matching rpc program name or
|
||||
program number is found, or until end-of-file is encountered.
|
||||
.Sh FILES
|
||||
.Pa /etc/rpc
|
||||
.Sh DIAGNOSTICS
|
||||
A
|
||||
.Dv NULL
|
||||
pointer is returned on
|
||||
.Dv EOF
|
||||
or error.
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 5 ,
|
||||
.Xr rpcinfo 8 ,
|
||||
.Xr ypserv 8
|
||||
.Sh BUGS
|
||||
All information
|
||||
is contained in a static area
|
||||
so it must be copied if it is
|
||||
to be saved.
|
||||
@@ -0,0 +1,222 @@
|
||||
/* $NetBSD: getrpcent.c,v 1.21 2004/08/16 02:47:54 ginsbach Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user or with the express written consent of
|
||||
* Sun Microsystems, Inc.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: getrpcent.c,v 1.21 2004/08/16 02:47:54 ginsbach Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1984 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(endrpcent,_endrpcent)
|
||||
__weak_alias(getrpcbyname,_getrpcbyname)
|
||||
__weak_alias(getrpcbynumber,_getrpcbynumber)
|
||||
__weak_alias(getrpcent,_getrpcent)
|
||||
__weak_alias(setrpcent,_setrpcent)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Internet version.
|
||||
*/
|
||||
static struct rpcdata {
|
||||
FILE *rpcf;
|
||||
int stayopen;
|
||||
#define MAXALIASES 35
|
||||
char *rpc_aliases[MAXALIASES];
|
||||
struct rpcent rpc;
|
||||
char line[BUFSIZ+1];
|
||||
} *rpcdata;
|
||||
|
||||
static struct rpcent *interpret(char *val, size_t len);
|
||||
|
||||
#define RPCDB "/etc/rpc"
|
||||
|
||||
static struct rpcdata *_rpcdata(void);
|
||||
|
||||
static struct rpcdata *
|
||||
_rpcdata(void)
|
||||
{
|
||||
struct rpcdata *d = rpcdata;
|
||||
|
||||
if (d == 0) {
|
||||
d = (struct rpcdata *)calloc(1, sizeof (struct rpcdata));
|
||||
rpcdata = d;
|
||||
}
|
||||
return (d);
|
||||
}
|
||||
|
||||
struct rpcent *
|
||||
getrpcbynumber(int number)
|
||||
{
|
||||
struct rpcent *rpc;
|
||||
|
||||
setrpcent(0);
|
||||
while ((rpc = getrpcent()) != NULL) {
|
||||
if (rpc->r_number == number)
|
||||
break;
|
||||
}
|
||||
endrpcent();
|
||||
return (rpc);
|
||||
}
|
||||
|
||||
struct rpcent *
|
||||
getrpcbyname(const char *name)
|
||||
{
|
||||
struct rpcent *rpc;
|
||||
char **rp;
|
||||
|
||||
_DIAGASSERT(name != NULL);
|
||||
|
||||
setrpcent(0);
|
||||
while ((rpc = getrpcent()) != NULL) {
|
||||
if (strcmp(rpc->r_name, name) == 0)
|
||||
break;
|
||||
for (rp = rpc->r_aliases; *rp != NULL; rp++) {
|
||||
if (strcmp(*rp, name) == 0)
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
found:
|
||||
endrpcent();
|
||||
return (rpc);
|
||||
}
|
||||
|
||||
void
|
||||
setrpcent(int f)
|
||||
{
|
||||
struct rpcdata *d = _rpcdata();
|
||||
|
||||
if (d == 0)
|
||||
return;
|
||||
if (d->rpcf == NULL)
|
||||
d->rpcf = fopen(RPCDB, "r");
|
||||
else
|
||||
rewind(d->rpcf);
|
||||
d->stayopen |= f;
|
||||
}
|
||||
|
||||
void
|
||||
endrpcent(void)
|
||||
{
|
||||
struct rpcdata *d = _rpcdata();
|
||||
|
||||
if (d == 0)
|
||||
return;
|
||||
if (d->rpcf && !d->stayopen) {
|
||||
fclose(d->rpcf);
|
||||
d->rpcf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct rpcent *
|
||||
getrpcent(void)
|
||||
{
|
||||
struct rpcdata *d = _rpcdata();
|
||||
|
||||
if (d == 0)
|
||||
return(NULL);
|
||||
if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)
|
||||
return (NULL);
|
||||
if (fgets(d->line, BUFSIZ, d->rpcf) == NULL)
|
||||
return (NULL);
|
||||
return (interpret(d->line, strlen(d->line)));
|
||||
}
|
||||
|
||||
static struct rpcent *
|
||||
interpret(char *val, size_t len)
|
||||
{
|
||||
struct rpcdata *d = _rpcdata();
|
||||
char *p;
|
||||
char *cp, **q;
|
||||
|
||||
_DIAGASSERT(val != NULL);
|
||||
|
||||
if (d == 0)
|
||||
return (0);
|
||||
(void) strncpy(d->line, val, len);
|
||||
p = d->line;
|
||||
d->line[len] = '\n';
|
||||
if (*p == '#')
|
||||
return (getrpcent());
|
||||
cp = strpbrk(p, "#\n");
|
||||
if (cp == NULL)
|
||||
return (getrpcent());
|
||||
*cp = '\0';
|
||||
cp = strpbrk(p, " \t");
|
||||
if (cp == NULL)
|
||||
return (getrpcent());
|
||||
*cp++ = '\0';
|
||||
/* THIS STUFF IS INTERNET SPECIFIC */
|
||||
d->rpc.r_name = d->line;
|
||||
while (*cp == ' ' || *cp == '\t')
|
||||
cp++;
|
||||
d->rpc.r_number = atoi(cp);
|
||||
q = d->rpc.r_aliases = d->rpc_aliases;
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
while (cp && *cp) {
|
||||
if (*cp == ' ' || *cp == '\t') {
|
||||
cp++;
|
||||
continue;
|
||||
}
|
||||
if (q < &(d->rpc_aliases[MAXALIASES - 1]))
|
||||
*q++ = cp;
|
||||
cp = strpbrk(cp, " \t");
|
||||
if (cp != NULL)
|
||||
*cp++ = '\0';
|
||||
}
|
||||
*q = NULL;
|
||||
return (&d->rpc);
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI
|
||||
.\" $NetBSD: getrpcport.3,v 1.5 2003/01/18 11:29:04 thorpej Exp $
|
||||
.\"
|
||||
.Dd October 6, 1987
|
||||
.Dt GETRPCPORT 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm getrpcport
|
||||
.Nd get RPC port number
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.Ft int
|
||||
.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto"
|
||||
.Sh DESCRIPTION
|
||||
.Fn getrpcport
|
||||
returns the port number for version
|
||||
.Fa versnum
|
||||
of the RPC program
|
||||
.Fa prognum
|
||||
running on
|
||||
.Fa host
|
||||
and using protocol
|
||||
.Fa proto .
|
||||
It returns 0 if it cannot contact the portmapper, or if
|
||||
.Fa prognum
|
||||
is not registered.
|
||||
If
|
||||
.Fa prognum
|
||||
is registered but not with version
|
||||
.Fa versnum ,
|
||||
it will still return a port number (for some version of the program)
|
||||
indicating that the program is indeed registered.
|
||||
The version mismatch will be detected upon the first call to the service.
|
||||
@@ -0,0 +1,85 @@
|
||||
/* $NetBSD: getrpcport.c,v 1.16 2000/01/22 22:19:18 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)getrpcport.c 1.3 87/08/11 SMI";
|
||||
static char *sccsid = "@(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: getrpcport.c,v 1.16 2000/01/22 22:19:18 mycroft Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Copyright (c) 1985 by Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(getrpcport,_getrpcport)
|
||||
#endif
|
||||
|
||||
int
|
||||
getrpcport(host, prognum, versnum, proto)
|
||||
char *host;
|
||||
int prognum, versnum, proto;
|
||||
{
|
||||
struct sockaddr_in addr;
|
||||
struct hostent *hp;
|
||||
|
||||
_DIAGASSERT(host != NULL);
|
||||
|
||||
if ((hp = gethostbyname(host)) == NULL)
|
||||
return (0);
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_len = sizeof(struct sockaddr_in);
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = 0;
|
||||
if (hp->h_length > addr.sin_len)
|
||||
hp->h_length = addr.sin_len;
|
||||
memcpy(&addr.sin_addr.s_addr, hp->h_addr, (size_t)hp->h_length);
|
||||
/* Inconsistent interfaces need casts! :-( */
|
||||
return (pmap_getport(&addr, (u_long)prognum, (u_long)versnum,
|
||||
(u_int)proto));
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/* $NetBSD: mt_misc.c,v 1.8 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Frank van der Linden.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Define and initialize MT data for libnsl.
|
||||
* The _libnsl_lock_init() function below is the library's .init handler.
|
||||
*/
|
||||
|
||||
/* #pragma ident "@(#)mt_misc.c 1.24 93/04/29 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: mt_misc.c,v 1.8 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <rpc/rpc.h>
|
||||
#include <sys/time.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef _REENTRANT
|
||||
|
||||
/* protects the services list (svc.c) */
|
||||
rwlock_t svc_lock = RWLOCK_INITIALIZER;
|
||||
/* protects svc_fdset and the xports[] array */
|
||||
rwlock_t svc_fd_lock = RWLOCK_INITIALIZER;
|
||||
/* protects the RPCBIND address cache */
|
||||
rwlock_t rpcbaddr_cache_lock = RWLOCK_INITIALIZER;
|
||||
|
||||
/* protects authdes cache (svcauth_des.c) */
|
||||
mutex_t authdes_lock = MUTEX_INITIALIZER;
|
||||
/* auth_none.c serialization */
|
||||
mutex_t authnone_lock = MUTEX_INITIALIZER;
|
||||
/* protects the Auths list (svc_auth.c) */
|
||||
mutex_t authsvc_lock = MUTEX_INITIALIZER;
|
||||
/* protects client-side fd lock array */
|
||||
mutex_t clnt_fd_lock = MUTEX_INITIALIZER;
|
||||
/* clnt_raw.c serialization */
|
||||
mutex_t clntraw_lock = MUTEX_INITIALIZER;
|
||||
/* domainname and domain_fd (getdname.c) and default_domain (rpcdname.c) */
|
||||
mutex_t dname_lock = MUTEX_INITIALIZER;
|
||||
/* dupreq variables (svc_dg.c) */
|
||||
mutex_t dupreq_lock = MUTEX_INITIALIZER;
|
||||
/* protects first_time and hostname (key_call.c) */
|
||||
mutex_t keyserv_lock = MUTEX_INITIALIZER;
|
||||
/* serializes rpc_trace() (rpc_trace.c) */
|
||||
mutex_t libnsl_trace_lock = MUTEX_INITIALIZER;
|
||||
/* loopnconf (rpcb_clnt.c) */
|
||||
mutex_t loopnconf_lock = MUTEX_INITIALIZER;
|
||||
/* serializes ops initializations */
|
||||
mutex_t ops_lock = MUTEX_INITIALIZER;
|
||||
/* protects ``port'' static in bindresvport() */
|
||||
mutex_t portnum_lock = MUTEX_INITIALIZER;
|
||||
/* protects proglst list (svc_simple.c) */
|
||||
mutex_t proglst_lock = MUTEX_INITIALIZER;
|
||||
/* serializes clnt_com_create() (rpc_soc.c) */
|
||||
mutex_t rpcsoc_lock = MUTEX_INITIALIZER;
|
||||
/* svc_raw.c serialization */
|
||||
mutex_t svcraw_lock = MUTEX_INITIALIZER;
|
||||
/* xprtlist (svc_generic.c) */
|
||||
mutex_t xprtlist_lock = MUTEX_INITIALIZER;
|
||||
/* serializes calls to public key routines */
|
||||
mutex_t serialize_pkey = MUTEX_INITIALIZER;
|
||||
|
||||
#endif /* _REENTRANT */
|
||||
|
||||
|
||||
#undef rpc_createerr
|
||||
|
||||
struct rpc_createerr rpc_createerr;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
static thread_key_t rce_key;
|
||||
static once_t rce_once = ONCE_INITIALIZER;
|
||||
|
||||
static void
|
||||
__rpc_createerr_setup(void)
|
||||
{
|
||||
|
||||
thr_keycreate(&rce_key, free);
|
||||
}
|
||||
#endif /* _REENTRANT */
|
||||
|
||||
struct rpc_createerr*
|
||||
__rpc_createerr()
|
||||
{
|
||||
#ifdef _REENTRANT
|
||||
struct rpc_createerr *rce_addr = 0;
|
||||
|
||||
if (__isthreaded == 0)
|
||||
return (&rpc_createerr);
|
||||
thr_once(&rce_once, __rpc_createerr_setup);
|
||||
rce_addr = thr_getspecific(rce_key);
|
||||
if (rce_addr == NULL) {
|
||||
rce_addr = malloc(sizeof(*rce_addr));
|
||||
if (rce_addr == NULL)
|
||||
return &rpc_createerr;
|
||||
thr_setspecific(rce_key, (void *) rce_addr);
|
||||
memset(rce_addr, 0, sizeof (struct rpc_createerr));
|
||||
}
|
||||
|
||||
return (rce_addr);
|
||||
#else
|
||||
return &rpc_createerr;
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -0,0 +1,125 @@
|
||||
/* $NetBSD: pmap_clnt.c,v 1.18 2003/01/18 11:29:05 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: pmap_clnt.c,v 1.18 2003/01/18 11:29:05 thorpej Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_clnt.c
|
||||
* Client interface to pmap rpc service.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
#include <rpc/nettype.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(pmap_set,_pmap_set)
|
||||
__weak_alias(pmap_unset,_pmap_unset)
|
||||
#endif
|
||||
|
||||
bool_t
|
||||
pmap_set(u_long program, u_long version, int protocol, int port)
|
||||
{
|
||||
bool_t rslt;
|
||||
struct netbuf *na;
|
||||
struct netconfig *nconf;
|
||||
char buf[32];
|
||||
|
||||
if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
|
||||
return (FALSE);
|
||||
}
|
||||
nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
|
||||
if (nconf == NULL) {
|
||||
return (FALSE);
|
||||
}
|
||||
snprintf(buf, sizeof buf, "0.0.0.0.%d.%d",
|
||||
(((u_int32_t)port) >> 8) & 0xff, port & 0xff);
|
||||
na = uaddr2taddr(nconf, buf);
|
||||
if (na == NULL) {
|
||||
freenetconfigent(nconf);
|
||||
return (FALSE);
|
||||
}
|
||||
rslt = rpcb_set((rpcprog_t)program, (rpcvers_t)version, nconf, na);
|
||||
free(na);
|
||||
freenetconfigent(nconf);
|
||||
return (rslt);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 netconfig *nconf;
|
||||
bool_t udp_rslt = FALSE;
|
||||
bool_t tcp_rslt = FALSE;
|
||||
|
||||
nconf = __rpc_getconfip("udp");
|
||||
if (nconf != NULL) {
|
||||
udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
|
||||
nconf);
|
||||
freenetconfigent(nconf);
|
||||
}
|
||||
nconf = __rpc_getconfip("tcp");
|
||||
if (nconf != NULL) {
|
||||
tcp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
|
||||
nconf);
|
||||
freenetconfigent(nconf);
|
||||
}
|
||||
/*
|
||||
* XXX: The call may still succeed even if only one of the
|
||||
* calls succeeded. This was the best that could be
|
||||
* done for backward compatibility.
|
||||
*/
|
||||
return (tcp_rslt || udp_rslt);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
/* $NetBSD: pmap_getmaps.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: pmap_getmaps.c,v 1.16 2000/07/06 03:10:34 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_getmap.c
|
||||
* Client interface to pmap rpc service.
|
||||
* contains pmap_getmaps, which is only tcp service involved
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(pmap_getmaps,_pmap_getmaps)
|
||||
#endif
|
||||
|
||||
#define NAMELEN 255
|
||||
#define MAX_BROADCAST_SIZE 1400
|
||||
|
||||
/*
|
||||
* Get a copy of the current port maps.
|
||||
* Calls the pmap service remotely to do get the maps.
|
||||
*/
|
||||
struct pmaplist *
|
||||
pmap_getmaps(address)
|
||||
struct sockaddr_in *address;
|
||||
{
|
||||
struct pmaplist *head = NULL;
|
||||
int sock = -1;
|
||||
struct timeval minutetimeout;
|
||||
CLIENT *client;
|
||||
|
||||
_DIAGASSERT(address != NULL);
|
||||
|
||||
minutetimeout.tv_sec = 60;
|
||||
minutetimeout.tv_usec = 0;
|
||||
address->sin_port = htons(PMAPPORT);
|
||||
client = clnttcp_create(address, PMAPPROG,
|
||||
PMAPVERS, &sock, 50, 500);
|
||||
if (client != NULL) {
|
||||
if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_DUMP,
|
||||
(xdrproc_t)xdr_void, NULL,
|
||||
(xdrproc_t)xdr_pmaplist, &head, minutetimeout) !=
|
||||
RPC_SUCCESS) {
|
||||
clnt_perror(client, "pmap_getmaps rpc problem");
|
||||
}
|
||||
CLNT_DESTROY(client);
|
||||
}
|
||||
address->sin_port = 0;
|
||||
return (head);
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
/* $NetBSD: pmap_getport.c,v 1.18 2008/01/28 01:10:22 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: pmap_getport.c,v 1.18 2008/01/28 01:10:22 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_getport.c
|
||||
* Client interface to pmap rpc service.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(pmap_getport,_pmap_getport)
|
||||
#endif
|
||||
|
||||
static const struct timeval timeout = { 5, 0 };
|
||||
static const struct timeval tottimeout = { 60, 0 };
|
||||
|
||||
/*
|
||||
* Find the mapped port for program,version.
|
||||
* Calls the pmap service remotely to do the lookup.
|
||||
* Returns 0 if no map exists.
|
||||
*/
|
||||
|
||||
static void
|
||||
remote_pmap_getport(CLIENT *client, struct pmap *parms, u_short *port)
|
||||
{
|
||||
if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT, (xdrproc_t)xdr_pmap,
|
||||
parms, (xdrproc_t)xdr_u_short, port, tottimeout) != RPC_SUCCESS) {
|
||||
rpc_createerr.cf_stat = RPC_PMAPFAILURE;
|
||||
clnt_geterr(client, &rpc_createerr.cf_error);
|
||||
} else if (*port == 0) {
|
||||
rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
|
||||
clnt_geterr(client, &rpc_createerr.cf_error);
|
||||
}
|
||||
CLNT_DESTROY(client);
|
||||
}
|
||||
|
||||
static CLIENT *
|
||||
get_client(struct sockaddr_in *address, int tcp)
|
||||
{
|
||||
int sock = -1;
|
||||
if (tcp)
|
||||
return clnttcp_create(address, PMAPPROG, PMAPVERS, &sock, 0, 0);
|
||||
else
|
||||
return clntudp_bufcreate(address, PMAPPROG, PMAPVERS, timeout,
|
||||
&sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
|
||||
}
|
||||
|
||||
u_short
|
||||
pmap_getport(struct sockaddr_in *address, u_long program, u_long version,
|
||||
u_int protocol)
|
||||
{
|
||||
u_short port = 0;
|
||||
CLIENT *client;
|
||||
struct pmap parms;
|
||||
|
||||
_DIAGASSERT(address != NULL);
|
||||
|
||||
parms.pm_prog = program;
|
||||
parms.pm_vers = version;
|
||||
parms.pm_prot = protocol;
|
||||
parms.pm_port = 0; /* not needed or used */
|
||||
|
||||
address->sin_port = htons(PMAPPORT);
|
||||
|
||||
client = get_client(address, protocol == IPPROTO_TCP);
|
||||
if (client != NULL)
|
||||
remote_pmap_getport(client, &parms, &port);
|
||||
|
||||
if (port == 0) {
|
||||
client = get_client(address, protocol != IPPROTO_TCP);
|
||||
if (client != NULL)
|
||||
remote_pmap_getport(client, &parms, &port);
|
||||
}
|
||||
|
||||
address->sin_port = 0;
|
||||
return port;
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
/* $NetBSD: pmap_prot.c,v 1.10 2000/01/22 22:19:18 mycroft Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: pmap_prot.c,v 1.10 2000/01/22 22:19:18 mycroft Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_prot.c
|
||||
* Protocol for the local binder service, or pmap.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_pmap,_xdr_pmap)
|
||||
#endif
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_pmap(xdrs, regs)
|
||||
XDR *xdrs;
|
||||
struct pmap *regs;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(regs != NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/* $NetBSD: pmap_prot2.c,v 1.15 2001/01/04 14:42:20 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: pmap_prot2.c,v 1.15 2001/01/04 14:42:20 lukem Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_prot2.c
|
||||
* Protocol for the local binder service, or pmap.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_pmaplist,_xdr_pmaplist)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* What is going on with linked lists? (!)
|
||||
* First recall the link list declaration from pmap_prot.h:
|
||||
*
|
||||
* struct pmaplist {
|
||||
* struct pmap pml_map;
|
||||
* struct pmaplist *pml_map;
|
||||
* };
|
||||
*
|
||||
* Compare that declaration with a corresponding xdr declaration that
|
||||
* is (a) pointer-less, and (b) recursive:
|
||||
*
|
||||
* typedef union switch (bool_t) {
|
||||
*
|
||||
* case TRUE: struct {
|
||||
* struct pmap;
|
||||
* pmaplist_t foo;
|
||||
* };
|
||||
*
|
||||
* case FALSE: struct {};
|
||||
* } pmaplist_t;
|
||||
*
|
||||
* Notice that the xdr declaration has no nxt pointer while
|
||||
* the C declaration has no bool_t variable. The bool_t can be
|
||||
* interpreted as ``more data follows me''; if FALSE then nothing
|
||||
* follows this bool_t; if TRUE then the bool_t is followed by
|
||||
* an actual struct pmap, and then (recursively) by the
|
||||
* xdr union, pamplist_t.
|
||||
*
|
||||
* This could be implemented via the xdr_union primitive, though this
|
||||
* would cause a one recursive call per element in the list. Rather than do
|
||||
* that we can ``unwind'' the recursion
|
||||
* into a while loop and do the union arms in-place.
|
||||
*
|
||||
* The head of the list is what the C programmer wishes to past around
|
||||
* the net, yet is the data that the pointer points to which is interesting;
|
||||
* this sounds like a job for xdr_reference!
|
||||
*/
|
||||
bool_t
|
||||
xdr_pmaplist(xdrs, rp)
|
||||
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;
|
||||
struct pmaplist **next = NULL; /* pacify gcc */
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(rp != NULL);
|
||||
|
||||
freeing = (xdrs->x_op == XDR_FREE);
|
||||
|
||||
for (;;) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in
|
||||
* functionality to xdr_pmaplist().
|
||||
*/
|
||||
bool_t
|
||||
xdr_pmaplist_ptr(xdrs, rp)
|
||||
XDR *xdrs;
|
||||
struct pmaplist *rp;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(rp != NULL);
|
||||
|
||||
return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp);
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/* $NetBSD: pmap_rmt.c,v 1.30 2010/03/23 20:28:59 drochner Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: pmap_rmt.c,v 1.30 2010/03/23 20:28:59 drochner Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* pmap_rmt.c
|
||||
* Client interface to pmap rpc service.
|
||||
* remote call and broadcast service
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
#include <net/if.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
#include <rpc/pmap_rmt.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_rmtcall_args,_xdr_rmtcall_args)
|
||||
__weak_alias(xdr_rmtcallres,_xdr_rmtcallres)
|
||||
#endif
|
||||
|
||||
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(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout,
|
||||
port_ptr)
|
||||
struct sockaddr_in *addr;
|
||||
u_long prog, vers, proc;
|
||||
xdrproc_t xdrargs, xdrres;
|
||||
caddr_t argsp, resp;
|
||||
struct timeval tout;
|
||||
u_long *port_ptr;
|
||||
{
|
||||
int sock = -1;
|
||||
CLIENT *client;
|
||||
struct rmtcallargs a;
|
||||
struct rmtcallres r;
|
||||
enum clnt_stat stat;
|
||||
|
||||
_DIAGASSERT(addr != NULL);
|
||||
_DIAGASSERT(port_ptr != NULL);
|
||||
|
||||
addr->sin_port = htons(PMAPPORT);
|
||||
client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
|
||||
if (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, (rpcproc_t)PMAPPROC_CALLIT,
|
||||
(xdrproc_t)xdr_rmtcall_args, &a, (xdrproc_t)xdr_rmtcallres,
|
||||
&r, tout);
|
||||
CLNT_DESTROY(client);
|
||||
} else {
|
||||
stat = RPC_FAILED;
|
||||
}
|
||||
addr->sin_port = 0;
|
||||
return (stat);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* XDR remote call arguments
|
||||
* written for XDR_ENCODE direction only
|
||||
*/
|
||||
bool_t
|
||||
xdr_rmtcall_args(xdrs, cap)
|
||||
XDR *xdrs;
|
||||
struct rmtcallargs *cap;
|
||||
{
|
||||
u_int lenposition, argposition, position;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(cap != NULL);
|
||||
|
||||
if (xdr_u_long(xdrs, &(cap->prog)) &&
|
||||
xdr_u_long(xdrs, &(cap->vers)) &&
|
||||
xdr_u_long(xdrs, &(cap->proc))) {
|
||||
lenposition = XDR_GETPOS(xdrs);
|
||||
if (! xdr_u_long(xdrs, &(cap->arglen)))
|
||||
return (FALSE);
|
||||
argposition = XDR_GETPOS(xdrs);
|
||||
if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
|
||||
return (FALSE);
|
||||
position = XDR_GETPOS(xdrs);
|
||||
cap->arglen = (u_long)position - (u_long)argposition;
|
||||
XDR_SETPOS(xdrs, lenposition);
|
||||
if (! xdr_u_long(xdrs, &(cap->arglen)))
|
||||
return (FALSE);
|
||||
XDR_SETPOS(xdrs, position);
|
||||
return (TRUE);
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR remote call results
|
||||
* written for XDR_DECODE direction only
|
||||
*/
|
||||
bool_t
|
||||
xdr_rmtcallres(xdrs, crp)
|
||||
XDR *xdrs;
|
||||
struct rmtcallres *crp;
|
||||
{
|
||||
caddr_t port_ptr;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(crp != NULL);
|
||||
|
||||
port_ptr = (caddr_t)(void *)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 *)(void *)port_ptr;
|
||||
return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -0,0 +1,417 @@
|
||||
.\" @(#)rpc.3n 1.31 93/08/31 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" $NetBSD: rpc.3,v 1.22 2010/03/22 19:30:54 joerg Exp $
|
||||
.Dd May 7, 1993
|
||||
.Dt RPC 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpc
|
||||
.Nd library routines for remote procedure calls
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.In netconfig.h
|
||||
.Sh DESCRIPTION
|
||||
These
|
||||
routines allow C language programs to make procedure
|
||||
calls on other machines across a network.
|
||||
First, the client sends a request to the server.
|
||||
On receipt of the request, the server calls a dispatch routine
|
||||
to perform the requested service, and then sends back a reply.
|
||||
.Pp
|
||||
All
|
||||
RPC routines require the header
|
||||
.In rpc/rpc.h .
|
||||
Routines that take a
|
||||
.Fa netconfig
|
||||
structure also require that
|
||||
.In netconfig.h
|
||||
be included.
|
||||
.Ss Nettype
|
||||
Some of the high-level
|
||||
RPC interface routines take a
|
||||
.Fa nettype
|
||||
string as one of the parameters
|
||||
(for example,
|
||||
.Fn clnt_create ,
|
||||
.Fn svc_create ,
|
||||
.Fn rpc_reg ,
|
||||
.Fn rpc_call .
|
||||
This string defines a class of transports which can be used
|
||||
for a particular application.
|
||||
.Pp
|
||||
.Fa nettype
|
||||
can be one of the following:
|
||||
.Bl -tag -width datagram_v
|
||||
.It netpath
|
||||
Choose from the transports which have been
|
||||
indicated by their token names in the
|
||||
.Ev NETPATH
|
||||
environment variable.
|
||||
If
|
||||
.Ev NETPATH
|
||||
is unset or
|
||||
.Dv NULL
|
||||
, it defaults to
|
||||
.Fa visible .
|
||||
.Fa netpath
|
||||
is the default
|
||||
.Fa nettype .
|
||||
.It visible
|
||||
Choose the transports which have the visible flag (v)
|
||||
set in the
|
||||
.Pa /etc/netconfig
|
||||
file.
|
||||
.It circuit_v
|
||||
This is same as
|
||||
.Fa visible
|
||||
except that it chooses only the connection oriented transports
|
||||
(semantics
|
||||
.Fa tpi_cots
|
||||
or
|
||||
.Fa tpi_cots_ord )
|
||||
from the entries in the
|
||||
.Pa /etc/netconfig
|
||||
file.
|
||||
.It datagram_v
|
||||
This is same as
|
||||
.Fa visible
|
||||
except that it chooses only the connectionless datagram transports
|
||||
(semantics
|
||||
.Fa tpi_clts )
|
||||
from the entries in the
|
||||
.Pa /etc/netconfig
|
||||
file.
|
||||
.It circuit_n
|
||||
This is same as
|
||||
.Fa netpath
|
||||
except that it chooses only the connection oriented datagram transports
|
||||
(semantics
|
||||
.Fa tpi_cots
|
||||
or
|
||||
.Fa tpi_cots_ord ) .
|
||||
.It datagram_n
|
||||
This is same as
|
||||
.Fa netpath
|
||||
except that it chooses only the connectionless datagram transports
|
||||
(semantics
|
||||
.Fa tpi_clts ) .
|
||||
.It udp
|
||||
This refers to Internet UDP, both version 4 and 6.
|
||||
.It tcp
|
||||
This refers to Internet TCP, both version 4 and 6.
|
||||
.El
|
||||
.Pp
|
||||
If
|
||||
.Fa nettype
|
||||
is
|
||||
.Dv NULL ,
|
||||
it defaults to
|
||||
.Fa netpath .
|
||||
The transports are tried in left to right order in the
|
||||
.Ev NETPATH
|
||||
variable or in top to down order in the
|
||||
.Pa /etc/netconfig
|
||||
file.
|
||||
.Ss Derived Types
|
||||
The derived types used in the RPC interfaces are defined as follows:
|
||||
.Bd -literal
|
||||
typedef uint32_t rpcprog_t;
|
||||
typedef uint32_t rpcvers_t;
|
||||
typedef uint32_t rpcproc_t;
|
||||
typedef uint32_t rpcprot_t;
|
||||
typedef uint32_t rpcport_t;
|
||||
typedef int32_t rpc_inline_t;
|
||||
.Ed
|
||||
.Ss Data Structures
|
||||
Some of the data structures used by the
|
||||
RPC package are shown below.
|
||||
.Ss The AUTH Structure
|
||||
.Bd -literal
|
||||
/*
|
||||
* Authentication info. Opaque to client.
|
||||
*/
|
||||
struct opaque_auth {
|
||||
enum_t oa_flavor; /* flavor of auth */
|
||||
caddr_t oa_base; /* address of more auth stuff */
|
||||
u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
|
||||
};
|
||||
|
||||
/*
|
||||
* Auth handle, interface to client side authenticators.
|
||||
*/
|
||||
typedef struct {
|
||||
struct opaque_auth ah_cred;
|
||||
struct opaque_auth ah_verf;
|
||||
struct auth_ops {
|
||||
void (*ah_nextverf)(\|);
|
||||
int (*ah_marshal)(\|); /* nextverf \*[Am] serialize */
|
||||
int (*ah_validate)(\|); /* validate verifier */
|
||||
int (*ah_refresh)(\|); /* refresh credentials */
|
||||
void (*ah_destroy)(\|); /* destroy this structure */
|
||||
} *ah_ops;
|
||||
caddr_t ah_private;
|
||||
} AUTH;
|
||||
.Ed
|
||||
.Ss The CLIENT Structure
|
||||
.Bd -literal
|
||||
/*
|
||||
* Client rpc handle.
|
||||
* Created by individual implementations.
|
||||
* Client is responsible for initializing auth.
|
||||
*/
|
||||
|
||||
typedef struct {
|
||||
AUTH *cl_auth; /* authenticator */
|
||||
struct clnt_ops {
|
||||
enum clnt_stat (*cl_call)(); /* call remote procedure */
|
||||
void (*cl_abort)(); /* abort a call */
|
||||
void (*cl_geterr)(); /* get specific error code */
|
||||
bool_t (*cl_freeres)(); /* frees results */
|
||||
void (*cl_destroy)(); /* destroy this structure */
|
||||
bool_t (*cl_control)(); /* the ioctl() of rpc */
|
||||
} *cl_ops;
|
||||
caddr_t cl_private; /* private stuff */
|
||||
char *cl_netid; /* network identifier */
|
||||
char *cl_tp; /* device name */
|
||||
} CLIENT;
|
||||
.Ed
|
||||
.Ss The SVCXPRT structure
|
||||
.Bd -literal
|
||||
enum xprt_stat {
|
||||
XPRT_DIED,
|
||||
XPRT_MOREREQS,
|
||||
XPRT_IDLE
|
||||
};
|
||||
|
||||
/*
|
||||
* Server side transport handle
|
||||
*/
|
||||
typedef struct {
|
||||
int xp_fd; /* file descriptor for the server handle */
|
||||
u_short xp_port; /* obsolete */
|
||||
const struct xp_ops {
|
||||
bool_t (*xp_recv)(); /* receive incoming requests */
|
||||
enum xprt_stat (*xp_stat)(); /* get transport status */
|
||||
bool_t (*xp_getargs)(); /* get arguments */
|
||||
bool_t (*xp_reply)(); /* send reply */
|
||||
bool_t (*xp_freeargs)(); /* free mem allocated for args */
|
||||
void (*xp_destroy)(); /* destroy this struct */
|
||||
} *xp_ops;
|
||||
int xp_addrlen; /* length of remote addr. Obsolete */
|
||||
struct sockaddr_in xp_raddr; /* Obsolete */
|
||||
const struct xp_ops2 {
|
||||
bool_t (*xp_control)(); /* catch-all function */
|
||||
} *xp_ops2;
|
||||
char *xp_tp; /* transport provider device name */
|
||||
char *xp_netid; /* network identifier */
|
||||
struct netbuf xp_ltaddr; /* local transport address */
|
||||
struct netbuf xp_rtaddr; /* remote transport address */
|
||||
struct opaque_auth xp_verf; /* raw response verifier */
|
||||
caddr_t xp_p1; /* private: for use by svc ops */
|
||||
caddr_t xp_p2; /* private: for use by svc ops */
|
||||
caddr_t xp_p3; /* private: for use by svc lib */
|
||||
int xp_type /* transport type */
|
||||
} SVCXPRT;
|
||||
.Ed
|
||||
.Ss The svc_req structure
|
||||
.Bd -literal
|
||||
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 */
|
||||
};
|
||||
.Ed
|
||||
.Ss The XDR structure
|
||||
.Bd -literal
|
||||
/*
|
||||
* XDR operations.
|
||||
* XDR_ENCODE causes the type to be encoded into the stream.
|
||||
* XDR_DECODE causes the type to be extracted from the stream.
|
||||
* XDR_FREE can be used to release the space allocated by an XDR_DECODE
|
||||
* request.
|
||||
*/
|
||||
enum xdr_op {
|
||||
XDR_ENCODE=0,
|
||||
XDR_DECODE=1,
|
||||
XDR_FREE=2
|
||||
};
|
||||
/*
|
||||
* This is the number of bytes per unit of external data.
|
||||
*/
|
||||
#define BYTES_PER_XDR_UNIT (4)
|
||||
#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) /
|
||||
BYTES_PER_XDR_UNIT) \e * BYTES_PER_XDR_UNIT)
|
||||
|
||||
/*
|
||||
* A xdrproc_t exists for each data type which is to be encoded or
|
||||
* decoded. The second argument to the xdrproc_t is a pointer to
|
||||
* an opaque pointer. The opaque pointer generally points to a
|
||||
* structure of the data type to be decoded. If this points to 0,
|
||||
* then the type routines should allocate dynamic storage of the
|
||||
* appropriate size and return it.
|
||||
* bool_t (*xdrproc_t)(XDR *, caddr_t *);
|
||||
*/
|
||||
typedef bool_t (*xdrproc_t)();
|
||||
|
||||
/*
|
||||
* The XDR handle.
|
||||
* Contains operation which is being applied to the stream,
|
||||
* an operations vector for the particular implementation
|
||||
*/
|
||||
typedef struct {
|
||||
enum xdr_op x_op; /* operation; fast additional param */
|
||||
struct xdr_ops {
|
||||
bool_t (*x_getlong)(); /* get a long from underlying stream */
|
||||
bool_t (*x_putlong)(); /* put a long to underlying stream */
|
||||
bool_t (*x_getbytes)(); /* get bytes from underlying stream */
|
||||
bool_t (*x_putbytes)(); /* put bytes to underlying stream */
|
||||
u_int (*x_getpostn)(); /* returns bytes off from beginning */
|
||||
bool_t (*x_setpostn)(); /* lets you reposition the stream */
|
||||
long * (*x_inline)(); /* buf quick ptr to buffered data */
|
||||
void (*x_destroy)(); /* free privates of this xdr_stream */
|
||||
} *x_ops;
|
||||
caddr_t x_public; /* users' data */
|
||||
caddr_t x_private; /* pointer to private data */
|
||||
caddr_t x_base; /* private used for position info */
|
||||
int x_handy; /* extra private word */
|
||||
} XDR;
|
||||
|
||||
/*
|
||||
* The netbuf structure. This structure is defined in \*[Lt]xti.h\*[Gt] on SysV
|
||||
* systems, but NetBSD does not use XTI.
|
||||
*
|
||||
* Usually, buf will point to a struct sockaddr, and len and maxlen
|
||||
* will contain the length and maximum length of that socket address,
|
||||
* respectively.
|
||||
*/
|
||||
struct netbuf {
|
||||
unsigned int maxlen;
|
||||
unsigned int len;
|
||||
void *buf;
|
||||
};
|
||||
|
||||
/*
|
||||
* The format of the address and options arguments of the XTI t_bind call.
|
||||
* Only provided for compatibility, it should not be used other than
|
||||
* as an argument to svc_tli_create().
|
||||
*/
|
||||
|
||||
struct t_bind {
|
||||
struct netbuf addr;
|
||||
unsigned int qlen;
|
||||
};
|
||||
.Ed
|
||||
.Ss Index to Routines
|
||||
The following table lists RPC routines and the manual reference
|
||||
pages on which they are described:
|
||||
.Bl -column "authunix_create_default()" "rpc_clnt_create(3)"
|
||||
.It Em "RPC Routine" Ta Em "Manual Reference Page"
|
||||
.Pp
|
||||
.It Fn auth_destroy Ta Xr rpc_clnt_auth 3 ,
|
||||
.It Fn authdes_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn authnone_create Ta Xr rpc_clnt_auth 3 ,
|
||||
.It Fn authsys_create Ta Xr rpc_clnt_auth 3 ,
|
||||
.It Fn authsys_create_default Ta Xr rpc_clnt_auth 3 ,
|
||||
.It Fn authunix_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn authunix_create_default Ta Xr rpc_soc 3 ,
|
||||
.It Fn callrpc Ta Xr rpc_soc 3 ,
|
||||
.It Fn clnt_broadcast Ta Xr rpc_soc 3 ,
|
||||
.It Fn clnt_call Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_control Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_create Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_destroy Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_dg_create Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_freeres Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_geterr Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_pcreateerror Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_perrno Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_perror Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_raw_create Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_spcreateerror Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_sperrno Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_sperror Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn clnt_tli_create Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_tp_create Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clnt_udpcreate Ta Xr rpc_soc 3 ,
|
||||
.It Fn clnt_vc_create Ta Xr rpc_clnt_create 3 ,
|
||||
.It Fn clntraw_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn clnttcp_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn clntudp_bufcreate Ta Xr rpc_soc 3 ,
|
||||
.It Fn get_myaddress Ta Xr rpc_soc 3 ,
|
||||
.It Fn pmap_getmaps Ta Xr rpc_soc 3 ,
|
||||
.It Fn pmap_getport Ta Xr rpc_soc 3 ,
|
||||
.It Fn pmap_rmtcall Ta Xr rpc_soc 3 ,
|
||||
.It Fn pmap_set Ta Xr rpc_soc 3 ,
|
||||
.It Fn pmap_unset Ta Xr rpc_soc 3 ,
|
||||
.It Fn registerrpc Ta Xr rpc_soc 3 ,
|
||||
.It Fn rpc_broadcast Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn rpc_broadcast_exp Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn rpc_call Ta Xr rpc_clnt_calls 3 ,
|
||||
.It Fn rpc_reg Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn svc_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_destroy Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_dg_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_dg_enablecache Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn svc_fd_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_fds Ta Xr rpc_soc 3 ,
|
||||
.It Fn svc_freeargs Ta Xr rpc_svc_reg 3 ,
|
||||
.It Fn svc_getargs Ta Xr rpc_svc_reg 3 ,
|
||||
.It Fn svc_getcaller Ta Xr rpc_soc 3 ,
|
||||
.It Fn svc_getreq Ta Xr rpc_soc 3 ,
|
||||
.It Fn svc_getreqset Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn svc_getrpccaller Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn svc_kerb_reg Ta Xr kerberos_rpc 3 ,
|
||||
.It Fn svc_raw_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_reg Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn svc_register Ta Xr rpc_soc 3 ,
|
||||
.It Fn svc_run Ta Xr rpc_svc_reg 3 ,
|
||||
.It Fn svc_sendreply Ta Xr rpc_svc_reg 3 ,
|
||||
.It Fn svc_tli_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_tp_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svc_unreg Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn svc_unregister Ta Xr rpc_soc 3 ,
|
||||
.It Fn svc_vc_create Ta Xr rpc_svc_create 3 ,
|
||||
.It Fn svcerr_auth Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcerr_decode Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcerr_noproc Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcerr_noprog Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcerr_progvers Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcerr_systemerr Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcerr_weakauth Ta Xr rpc_svc_err 3 ,
|
||||
.It Fn svcfd_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn svcraw_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn svctcp_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn svcudp_bufcreate Ta Xr rpc_soc 3 ,
|
||||
.It Fn svcudp_create Ta Xr rpc_soc 3 ,
|
||||
.It Fn xdr_accepted_reply Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xdr_authsys_parms Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xdr_authunix_parms Ta Xr rpc_soc 3 ,
|
||||
.It Fn xdr_callhdr Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xdr_callmsg Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xdr_opaque_auth Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xdr_rejected_reply Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xdr_replymsg Ta Xr rpc_xdr 3 ,
|
||||
.It Fn xprt_register Ta Xr rpc_svc_calls 3 ,
|
||||
.It Fn xprt_unregister Ta Xr rpc_svc_calls 3 ,
|
||||
.El
|
||||
.Sh FILES
|
||||
.Pa /etc/netconfig
|
||||
.Sh SEE ALSO
|
||||
.Xr getnetconfig 3 ,
|
||||
.Xr getnetpath 3 ,
|
||||
.Xr rpc_clnt_auth 3 ,
|
||||
.Xr rpc_clnt_calls 3 ,
|
||||
.Xr rpc_clnt_create 3 ,
|
||||
.Xr rpc_svc_calls 3 ,
|
||||
.Xr rpc_svc_create 3 ,
|
||||
.Xr rpc_svc_err 3 ,
|
||||
.Xr rpc_svc_reg 3 ,
|
||||
.Xr rpc_xdr 3 ,
|
||||
.Xr rpcbind 3 ,
|
||||
.Xr xdr 3 ,
|
||||
.Xr netconfig 5
|
||||
@@ -0,0 +1,212 @@
|
||||
/* $NetBSD: rpc_callmsg.c,v 1.18 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: rpc_callmsg.c,v 1.18 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rpc_callmsg.c
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_callmsg,_xdr_callmsg)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XDR a call message
|
||||
*/
|
||||
bool_t
|
||||
xdr_callmsg(xdrs, cmsg)
|
||||
XDR *xdrs;
|
||||
struct rpc_msg *cmsg;
|
||||
{
|
||||
int32_t *buf;
|
||||
struct opaque_auth *oa;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(cmsg != NULL);
|
||||
|
||||
if (xdrs->x_op == XDR_ENCODE) {
|
||||
if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
|
||||
return (FALSE);
|
||||
}
|
||||
buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
|
||||
+ RNDUP(cmsg->rm_call.cb_cred.oa_length)
|
||||
+ 2 * BYTES_PER_XDR_UNIT
|
||||
+ RNDUP(cmsg->rm_call.cb_verf.oa_length));
|
||||
if (buf != NULL) {
|
||||
IXDR_PUT_INT32(buf, cmsg->rm_xid);
|
||||
IXDR_PUT_ENUM(buf, cmsg->rm_direction);
|
||||
if (cmsg->rm_direction != CALL) {
|
||||
return (FALSE);
|
||||
}
|
||||
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers);
|
||||
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
|
||||
return (FALSE);
|
||||
}
|
||||
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog);
|
||||
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers);
|
||||
IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc);
|
||||
oa = &cmsg->rm_call.cb_cred;
|
||||
IXDR_PUT_ENUM(buf, oa->oa_flavor);
|
||||
IXDR_PUT_INT32(buf, oa->oa_length);
|
||||
if (oa->oa_length) {
|
||||
memmove(buf, oa->oa_base, oa->oa_length);
|
||||
buf += RNDUP(oa->oa_length) / sizeof (int32_t);
|
||||
}
|
||||
oa = &cmsg->rm_call.cb_verf;
|
||||
IXDR_PUT_ENUM(buf, oa->oa_flavor);
|
||||
IXDR_PUT_INT32(buf, oa->oa_length);
|
||||
if (oa->oa_length) {
|
||||
memmove(buf, oa->oa_base, oa->oa_length);
|
||||
/* no real need....
|
||||
buf += RNDUP(oa->oa_length) / sizeof (int32_t);
|
||||
*/
|
||||
}
|
||||
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_U_INT32(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_U_INT32(buf);
|
||||
if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
|
||||
return (FALSE);
|
||||
}
|
||||
cmsg->rm_call.cb_prog = IXDR_GET_U_INT32(buf);
|
||||
cmsg->rm_call.cb_vers = IXDR_GET_U_INT32(buf);
|
||||
cmsg->rm_call.cb_proc = IXDR_GET_U_INT32(buf);
|
||||
oa = &cmsg->rm_call.cb_cred;
|
||||
oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
|
||||
oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
|
||||
if (oa->oa_length) {
|
||||
if (oa->oa_length > MAX_AUTH_BYTES) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (oa->oa_base == NULL) {
|
||||
oa->oa_base = mem_alloc(oa->oa_length);
|
||||
if (oa->oa_base == NULL)
|
||||
return (FALSE);
|
||||
}
|
||||
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 {
|
||||
memmove(oa->oa_base, buf,
|
||||
oa->oa_length);
|
||||
/* no real need....
|
||||
buf += RNDUP(oa->oa_length) /
|
||||
sizeof (int32_t);
|
||||
*/
|
||||
}
|
||||
}
|
||||
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 = (u_int)IXDR_GET_U_INT32(buf);
|
||||
}
|
||||
if (oa->oa_length) {
|
||||
if (oa->oa_length > MAX_AUTH_BYTES) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (oa->oa_base == NULL) {
|
||||
oa->oa_base = mem_alloc(oa->oa_length);
|
||||
if (oa->oa_base == NULL)
|
||||
return (FALSE);
|
||||
}
|
||||
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 {
|
||||
memmove(oa->oa_base, buf,
|
||||
oa->oa_length);
|
||||
/* no real need...
|
||||
buf += RNDUP(oa->oa_length) /
|
||||
sizeof (int32_t);
|
||||
*/
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
}
|
||||
if (
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
|
||||
xdr_enum(xdrs, (enum_t *)(void *)&(cmsg->rm_direction)) &&
|
||||
(cmsg->rm_direction == CALL) &&
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
|
||||
(cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
|
||||
xdr_u_int32_t(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);
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
.\" @(#)rpc_clnt_auth.3n 1.21 93/05/07 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_clnt_auth 1.4 89/07/20 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_clnt_auth.3,v 1.6 2003/04/16 13:34:43 wiz Exp $
|
||||
.Dd May 7, 1993
|
||||
.Dt RPC_CLNT_AUTH 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm auth_destroy ,
|
||||
.Nm authnone_create ,
|
||||
.Nm authsys_create ,
|
||||
.Nm authsys_create_default
|
||||
.Nd library routines for client side remote procedure call authentication
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft "void"
|
||||
.Fn auth_destroy "AUTH *auth"
|
||||
.Ft "AUTH *"
|
||||
.Fn authnone_create "void"
|
||||
.Ft "AUTH *"
|
||||
.Fn authsys_create "const char *host" "const uid_t uid" "const gid_t gid" "const int len" "const gid_t *aup_gids"
|
||||
.Ft "AUTH *"
|
||||
.Fn authsys_create_default "void"
|
||||
.Sh DESCRIPTION
|
||||
These routines are part of the
|
||||
RPC library that allows C language programs to make procedure
|
||||
calls on other machines across the network,
|
||||
with desired authentication.
|
||||
.Pp
|
||||
These routines are normally called after creating the
|
||||
.Dv CLIENT
|
||||
handle.
|
||||
The
|
||||
.Fa cl_auth
|
||||
field of the
|
||||
.Dv CLIENT
|
||||
structure should be initialized by the
|
||||
.Dv AUTH
|
||||
structure returned by some of the following routines.
|
||||
The client's authentication information
|
||||
is passed to the server when the
|
||||
RPC
|
||||
call is made.
|
||||
.Pp
|
||||
Only the
|
||||
.Dv NULL
|
||||
and the
|
||||
.Dv SYS
|
||||
style of authentication is discussed here.
|
||||
.Sh ROUTINES
|
||||
.Bl -tag -width authsys_create_default()
|
||||
.It Fn auth_destroy
|
||||
A function macro that destroys the authentication
|
||||
information associated with
|
||||
.Fa auth .
|
||||
Destruction usually involves deallocation
|
||||
of private data structures.
|
||||
The use of
|
||||
.Fn auth
|
||||
is undefined after calling
|
||||
.Fn auth_destroy .
|
||||
.Pp
|
||||
.It Fn authnone_create
|
||||
Create and return an RPC
|
||||
authentication handle that passes nonusable
|
||||
authentication information with each remote procedure call.
|
||||
This is the default authentication used by RPC.
|
||||
.Pp
|
||||
.It Fn authsys_create
|
||||
Create and return an RPC authentication handle that contains
|
||||
.Dv AUTH_SYS
|
||||
authentication information.
|
||||
The parameter
|
||||
.Fa host
|
||||
is the name of the machine on which the information was
|
||||
created;
|
||||
.Fa uid
|
||||
is the user's user ID;
|
||||
.Fa gid
|
||||
is the user's current group ID;
|
||||
.Fa len
|
||||
and
|
||||
.Fa aup_gids
|
||||
refer to a counted array of groups to which the user belongs.
|
||||
.Pp
|
||||
.It Fn authsys_create_default
|
||||
Call
|
||||
.Fn authsys_create
|
||||
with the appropriate parameters.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_clnt_calls 3 ,
|
||||
.Xr rpc_clnt_create 3
|
||||
@@ -0,0 +1,296 @@
|
||||
.\" @(#)rpc_clnt_calls.3n 1.30 93/08/31 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_clnt_calls 1.4 89/07/20 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_clnt_calls.3,v 1.7 2005/12/03 15:16:19 yamt Exp $
|
||||
.Dd December 4, 2005
|
||||
.Dt RPC_CLNT_CALLS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpc_clnt_calls ,
|
||||
.Nm clnt_call ,
|
||||
.Nm clnt_freeres ,
|
||||
.Nm clnt_geterr ,
|
||||
.Nm clnt_perrno ,
|
||||
.Nm clnt_perror ,
|
||||
.Nm clnt_sperrno ,
|
||||
.Nm clnt_sperror ,
|
||||
.Nm rpc_broadcast ,
|
||||
.Nm rpc_broadcast_exp ,
|
||||
.Nm rpc_call
|
||||
.Nd library routines for client side calls
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft "enum clnt_stat"
|
||||
.Fn clnt_call "CLIENT *clnt" "const rpcproc_t procnum" "const xdrproc_t inproc" "const char *in" "const xdrproc_t outproc" "caddr_t out" "const struct timeval tout"
|
||||
.Ft bool_t
|
||||
.Fn clnt_freeres "CLIENT *clnt" "const xdrproc_t outproc" "caddr_t out"
|
||||
.Ft void
|
||||
.Fn clnt_geterr "const CLIENT * clnt" "struct rpc_err * errp"
|
||||
.Ft void
|
||||
.Fn clnt_perrno "const enum clnt_stat stat"
|
||||
.Ft void
|
||||
.Fn clnt_perror "const CLIENT * clnt" "const char *s"
|
||||
.Ft "char *"
|
||||
.Fn clnt_sperrno "const enum clnt_stat stat"
|
||||
.Ft "char *"
|
||||
.Fn clnt_sperror "const CLIENT *clnt" "const char * s"
|
||||
.\" Note the clustered Fn arguments. It can't take more than 9. XXX
|
||||
.Ft "enum clnt_stat"
|
||||
.Fn rpc_broadcast "const rpcprog_t prognum, const rpcvers_t versnum" "const rpcproc_t procnum" "const xdrproc_t inproc" "const char *in" "const xdrproc_t outproc" "caddr_t out" "const resultproc_t eachresult" "const char *nettype"
|
||||
.Ft "enum clnt_stat"
|
||||
.Fn rpc_broadcast_exp "rpcprog_t prognum, const rpcvers_t versnum" "const rpcproc_t procnum, const xdrproc_t xargs" "caddr_t argsp, const xdrproc_t xresults" "caddr_t resultsp" "const int inittime" "const int waittime" "const resultproc_t eachresult" "const char * nettype"
|
||||
.Ft "enum clnt_stat"
|
||||
.Fn rpc_call "const char *host, const rpcprog_t prognum" "const rpcvers_t versnum" "const rpcproc_t procnum, const xdrproc_t inproc" "const char *in" "const xdrproc_t outproc" "char *out" "const char *nettype"
|
||||
.Sh DESCRIPTION
|
||||
RPC library routines allow C language programs to make procedure
|
||||
calls on other machines across the network.
|
||||
First, the client calls a procedure to send a request to the server.
|
||||
Upon receipt of the request, the server calls a dispatch routine
|
||||
to perform the requested service, and then sends back a reply.
|
||||
.Pp
|
||||
The
|
||||
.Fn clnt_call ,
|
||||
.Fn rpc_call ,
|
||||
and
|
||||
.Fn rpc_broadcast
|
||||
routines handle the client side of the procedure call.
|
||||
The remaining routines deal with error handling in the case of errors.
|
||||
.Pp
|
||||
Some of the routines take a
|
||||
.Dv CLIENT
|
||||
handle as one of the parameters.
|
||||
A
|
||||
.Dv CLIENT
|
||||
handle can be created by an RPC creation routine such as
|
||||
.Fn clnt_create
|
||||
(see
|
||||
.Xr rpc_clnt_create 3 ) .
|
||||
.Pp
|
||||
These routines are safe for use in multithreaded applications.
|
||||
.Dv CLIENT
|
||||
handles can be shared between threads, however in this implementation
|
||||
requests by different threads are serialized (that is, the first request will
|
||||
receive its results before the second request is sent).
|
||||
.Sh ROUTINES
|
||||
See
|
||||
.Xr rpc 3
|
||||
for the definition of the
|
||||
.Dv CLIENT
|
||||
data structure.
|
||||
.Pp
|
||||
.Bl -tag -width XXXXX
|
||||
.It Fn clnt_call
|
||||
A function macro that calls the remote procedure
|
||||
.Fa procnum
|
||||
associated with the client handle,
|
||||
.Fa clnt ,
|
||||
which is obtained with an RPC
|
||||
client creation routine such as
|
||||
.Fn clnt_create
|
||||
(see
|
||||
.Xr rpc_clnt_create 3 ) .
|
||||
The parameter
|
||||
.Fn inproc
|
||||
is the XDR function used to encode the procedure's parameters, and
|
||||
.Fn outproc
|
||||
is the XDR function used to decode the procedure's results;
|
||||
.Fn in
|
||||
is the address of the procedure's argument(s), and
|
||||
.Fn out
|
||||
is the address of where to place the result(s).
|
||||
.Fn tout
|
||||
is the time allowed for results to be returned, which is overridden by
|
||||
a time-out set explicitly through
|
||||
.Fn clnt_control ,
|
||||
see
|
||||
.Xr rpc_clnt_create 3 .
|
||||
If the remote call succeeds, the status returned is
|
||||
.Dv RPC_SUCCESS ,
|
||||
otherwise an appropriate status is returned.
|
||||
.Pp
|
||||
.It Fn clnt_freeres
|
||||
A function macro that frees any data allocated by the
|
||||
RPC/XDR system when it decoded the results of an RPC call.
|
||||
The parameter
|
||||
.Fa out
|
||||
is the address of the results, and
|
||||
.Fa outproc
|
||||
is the XDR routine describing the results.
|
||||
This routine returns 1 if the results were successfully freed,
|
||||
and 0 otherwise.
|
||||
.Pp
|
||||
.It Fn clnt_geterr
|
||||
A function macro that copies the error structure out of the client
|
||||
handle to the structure at address
|
||||
.Fa errp .
|
||||
.Pp
|
||||
.It Fn clnt_perrno
|
||||
Print a message to standard error corresponding
|
||||
to the condition indicated by
|
||||
.Fa stat .
|
||||
A newline is appended.
|
||||
Normally used after a procedure call fails for a routine
|
||||
for which a client handle is not needed, for instance
|
||||
.Fn rpc_call .
|
||||
.Pp
|
||||
.It Fn clnt_perror
|
||||
Print a message to the standard error indicating why an
|
||||
RPC call failed;
|
||||
.Fa clnt
|
||||
is the handle used to do the call.
|
||||
The message is prepended with string
|
||||
.Fa s
|
||||
and a colon.
|
||||
A newline is appended.
|
||||
Normally used after a remote procedure call fails
|
||||
for a routine which requires a client handle,
|
||||
for instance
|
||||
.Fn clnt_call .
|
||||
.Pp
|
||||
.It Fn clnt_sperrno
|
||||
Take the same arguments as
|
||||
.Fn clnt_perrno ,
|
||||
but instead of sending a message to the standard error
|
||||
indicating why an RPC
|
||||
call failed, return a pointer to a string which contains the message.
|
||||
.Fn clnt_sperrno
|
||||
is normally used instead of
|
||||
.Fn clnt_perrno
|
||||
when the program does not have a standard error (as a program
|
||||
running as a server quite likely does not), or if the programmer
|
||||
does not want the message to be output with
|
||||
.Fn printf
|
||||
(see
|
||||
.Xr printf 3 ) ,
|
||||
or if a message format different than that supported by
|
||||
.Fn clnt_perrno
|
||||
is to be used.
|
||||
Note:
|
||||
unlike
|
||||
.Fn clnt_sperror
|
||||
and
|
||||
.Fn clnt_spcreaterror
|
||||
(see
|
||||
.Xr rpc_clnt_create 3 ) ,
|
||||
.Fn clnt_sperrno
|
||||
does not return pointer to static data so the
|
||||
result will not get overwritten on each call.
|
||||
.Pp
|
||||
.It Fn clnt_sperror
|
||||
Like
|
||||
.Fn clnt_perror ,
|
||||
except that (like
|
||||
.Fn clnt_sperrno )
|
||||
it returns a string instead of printing to standard error.
|
||||
However,
|
||||
.Fn clnt_sperror
|
||||
does not append a newline at the end of the message.
|
||||
Warning:
|
||||
returns pointer to a buffer that is overwritten
|
||||
on each call.
|
||||
.Pp
|
||||
.It Fn rpc_broadcast
|
||||
Like
|
||||
.Fn rpc_call ,
|
||||
except the call message is broadcast to
|
||||
all the connectionless transports specified by
|
||||
.Fa nettype .
|
||||
If
|
||||
.Fa nettype
|
||||
is
|
||||
.Dv NULL ,
|
||||
it defaults to
|
||||
.Dq netpath .
|
||||
Each time it receives a response,
|
||||
this routine calls
|
||||
.Fn eachresult ,
|
||||
whose form is:
|
||||
.Ft bool_t
|
||||
.Fn eachresult "caddr_t out" "const struct netbuf * addr" "const struct netconfig * netconf"
|
||||
where
|
||||
.Fa out
|
||||
is the same as
|
||||
.Fa out
|
||||
passed to
|
||||
.Fn rpc_broadcast ,
|
||||
except that the remote procedure's output is decoded there;
|
||||
.Fa addr
|
||||
points to the address of the machine that sent the results, and
|
||||
.Fa netconf
|
||||
is the netconfig structure of the transport on which the remote
|
||||
server responded.
|
||||
If
|
||||
.Fn eachresult
|
||||
returns 0,
|
||||
.Fn rpc_broadcast
|
||||
waits for more replies;
|
||||
otherwise it returns with appropriate status.
|
||||
Warning:
|
||||
broadcast file descriptors are limited in size to the
|
||||
maximum transfer size of that transport.
|
||||
For Ethernet, this value is 1500 bytes.
|
||||
.Fn rpc_broadcast
|
||||
uses
|
||||
.Dv AUTH_SYS
|
||||
credentials by default (see
|
||||
.Xr rpc_clnt_auth 3 ) .
|
||||
.Pp
|
||||
.It Fn rpc_broadcast_exp
|
||||
Like
|
||||
.Fn rpc_broadcast ,
|
||||
except that the initial timeout,
|
||||
.Fa inittime
|
||||
and the maximum timeout,
|
||||
.Fa waittime
|
||||
are specified in milliseconds.
|
||||
.Fa inittime
|
||||
is the initial time that
|
||||
.Fn rpc_broadcast_exp
|
||||
waits before resending the request.
|
||||
After the first resend, the re-transmission interval
|
||||
increases exponentially until it exceeds
|
||||
.Fa waittime .
|
||||
.Pp
|
||||
.It Fn rpc_call
|
||||
Call the remote procedure associated with
|
||||
.Fa prognum ,
|
||||
.Fa versnum ,
|
||||
and
|
||||
.Fa procnum
|
||||
on the machine,
|
||||
.Fa host .
|
||||
The parameter
|
||||
.Fa inproc
|
||||
is used to encode the procedure's parameters, and
|
||||
.Fa outproc
|
||||
is used to decode the procedure's results;
|
||||
.Fa in
|
||||
is the address of the procedure's argument(s), and
|
||||
.Fa out
|
||||
is the address of where to place the result(s).
|
||||
.Fa nettype
|
||||
can be any of the values listed on
|
||||
.Xr rpc 3 .
|
||||
This routine returns
|
||||
.Dv RPC_SUCCESS
|
||||
if it succeeds, or an appropriate status is returned.
|
||||
Use the
|
||||
.Fn clnt_perrno
|
||||
routine to translate failure status into error messages.
|
||||
Warning:
|
||||
.Fn rpc_call
|
||||
uses the first available transport belonging
|
||||
to the class
|
||||
.Fa nettype ,
|
||||
on which it can create a connection.
|
||||
You do not have control of timeouts or authentication
|
||||
using this routine.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr printf 3 ,
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_clnt_auth 3 ,
|
||||
.Xr rpc_clnt_create 3
|
||||
@@ -0,0 +1,443 @@
|
||||
.\" @(#)rpc_clnt_create.3n 1.36 93/08/31 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_clnt_create 1.5 89/07/24 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_clnt_create.3,v 1.11 2009/05/23 18:57:25 christos Exp $
|
||||
.Dd May 23, 2009
|
||||
.Dt RPC_CLNT_CREATE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpc_clnt_create ,
|
||||
.Nm clnt_control ,
|
||||
.Nm clnt_create ,
|
||||
.Nm clnt_create_vers ,
|
||||
.Nm clnt_destroy ,
|
||||
.Nm clnt_dg_create ,
|
||||
.Nm clnt_pcreateerror ,
|
||||
.Nm clnt_raw_create ,
|
||||
.Nm clnt_spcreateerror ,
|
||||
.Nm clnt_tli_create ,
|
||||
.Nm clnt_tp_create ,
|
||||
.Nm clnt_vc_create ,
|
||||
.Nm rpc_createerr
|
||||
.Nd "library routines for dealing with creation and manipulation of CLIENT handles"
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft bool_t
|
||||
.Fn clnt_control "CLIENT *clnt" "const u_int req" "char *info"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_create_vers "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "char *nettype"
|
||||
.Ft void
|
||||
.Fn clnt_destroy "CLIENT * clnt"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_dg_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
|
||||
.Ft void
|
||||
.Fn clnt_pcreateerror "const char *s"
|
||||
.Ft "char *"
|
||||
.Fn clnt_spcreateerror "const char *s"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_raw_create "const rpcprog_t prognum" "const rpcvers_t versnum"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_tli_create "const int fildes" "const struct netconfig *netconf" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_tp_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
|
||||
.Ft "CLIENT *"
|
||||
.Fn clnt_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
|
||||
.Sh DESCRIPTION
|
||||
RPC library routines allow C language programs to make procedure
|
||||
calls on other machines across the network.
|
||||
First a
|
||||
.Dv CLIENT
|
||||
handle is created and then the client calls a procedure to send a
|
||||
request to the server.
|
||||
On receipt of the request, the server calls a dispatch routine
|
||||
to perform the requested service, and then sends a reply.
|
||||
.Sh ROUTINES
|
||||
.Bl -tag -width YYYYYYY
|
||||
.It Fn clnt_control
|
||||
A function macro to change or retrieve various information
|
||||
about a client object.
|
||||
.Fa req
|
||||
indicates the type of operation, and
|
||||
.Fa info
|
||||
is a pointer to the information.
|
||||
For both connectionless and connection-oriented transports,
|
||||
the supported values of
|
||||
.Fa req
|
||||
and their argument types and what they do are:
|
||||
.Bl -column "CLSET_FD_NCLOSE" "struct timeval *" "set total timeout"
|
||||
.It Dv CLSET_TIMEOUT Ta "struct timeval *" Ta "set total timeout"
|
||||
.It Dv CLGET_TIMEOUT Ta "struct timeval *" Ta "get total timeout"
|
||||
.El
|
||||
.Pp
|
||||
Note:
|
||||
if you set the timeout using
|
||||
.Fn clnt_control ,
|
||||
the timeout argument passed by
|
||||
.Fn clnt_call
|
||||
is ignored in all subsequent calls.
|
||||
.Pp
|
||||
Note:
|
||||
If you set the timeout value to 0
|
||||
.Fn clnt_control
|
||||
immediately returns an error (
|
||||
.Dv RPC_TIMEDOUT ) .
|
||||
Set the timeout parameter to 0 for batching calls.
|
||||
.Bl -column CLSET_FD_NCLOSE "struct timeval *" "do not close fd on destroy"
|
||||
.It Dv CLGET_SVC_ADDR Ta "struct netbuf *" Ta "get servers address"
|
||||
.It Dv CLGET_FD Ta "int *" Ta "get fd from handle"
|
||||
.It Dv CLSET_FD_CLOSE Ta "void" Ta "close fd on destroy"
|
||||
.It Dv CLSET_FD_NCLOSE Ta void Ta "don't close fd on destroy"
|
||||
.It Dv CLGET_VERS Ta "unsigned long *" Ta "get RPC program version"
|
||||
.It Dv CLSET_VERS Ta "unsigned long *" Ta "set RPC program version"
|
||||
.It Dv CLGET_XID Ta "unsigned long *" Ta "get XID of previous call"
|
||||
.It Dv CLSET_XID Ta "unsigned long *" Ta "set XID of next call"
|
||||
.El
|
||||
.Pp
|
||||
The following operations are valid for connectionless transports only:
|
||||
.Bl -column CLSET_RETRY_TIMEOUT "struct timeval *" "set total timeout"
|
||||
.It Dv CLSET_RETRY_TIMEOUT Ta "struct timeval *" Ta "set the retry timeout"
|
||||
.It Dv CLGET_RETRY_TIMEOUT Ta "struct timeval *" Ta "get the retry timeout"
|
||||
.El
|
||||
.Pp
|
||||
The retry timeout is the time that RPC
|
||||
waits for the server to reply before retransmitting the request.
|
||||
.Fn clnt_control
|
||||
returns
|
||||
.Dv TRUE
|
||||
on success and
|
||||
.Dv FALSE
|
||||
on failure.
|
||||
.Pp
|
||||
.It Fn clnt_create
|
||||
Generic client creation routine for program
|
||||
.Fa prognum
|
||||
and version
|
||||
.Fa versnum .
|
||||
.Fa host
|
||||
identifies the name of the remote host where the server
|
||||
is located.
|
||||
.Fa nettype
|
||||
indicates the class of transport protocol to use.
|
||||
The transports are tried in left to right order in
|
||||
.Ev NETPATH
|
||||
environment variable or in top to bottom order in
|
||||
the netconfig database.
|
||||
.Fn clnt_create
|
||||
tries all the transports of the
|
||||
.Fa nettype
|
||||
class available from the
|
||||
.Ev NETPATH
|
||||
environment variable and the netconfig database,
|
||||
and chooses the first successful one.
|
||||
A default timeout is set and can be modified using
|
||||
.Fn clnt_control .
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
The
|
||||
.Fn clnt_pcreateerror
|
||||
routine can be used to print the reason for failure.
|
||||
.Pp
|
||||
Note:
|
||||
.Fn clnt_create
|
||||
returns a valid client handle even
|
||||
if the particular version number supplied to
|
||||
.Fn clnt_create
|
||||
is not registered with the
|
||||
.Xr rpcbind 8
|
||||
service.
|
||||
This mismatch will be discovered by a
|
||||
.Fn clnt_call
|
||||
later (see
|
||||
.Xr rpc_clnt_calls 3 ) .
|
||||
.Pp
|
||||
.It Fn clnt_create_vers
|
||||
Generic client creation routine which is similar to
|
||||
.Fn clnt_create
|
||||
but which also checks for the
|
||||
version availability.
|
||||
.Fa host
|
||||
identifies the name of the remote host where the server
|
||||
is located.
|
||||
.Fa nettype
|
||||
indicates the class transport protocols to be used.
|
||||
If the routine is successful it returns a client handle created for
|
||||
the highest version between
|
||||
.Fa vers_low
|
||||
and
|
||||
.Fa vers_high
|
||||
that is supported by the server.
|
||||
.Fa vers_outp
|
||||
is set to this value.
|
||||
That is, after a successful return
|
||||
.Fa vers_low
|
||||
\*[Le]
|
||||
.Fa *vers_outp
|
||||
\*[Le]
|
||||
.Fa vers_high .
|
||||
If no version between
|
||||
.Fa vers_low
|
||||
and
|
||||
.Fa vers_high
|
||||
is supported by the server then the routine fails and returns
|
||||
.Dv NULL .
|
||||
A default timeout is set and can be modified using
|
||||
.Fn clnt_control .
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
The
|
||||
.Fn clnt_pcreateerror
|
||||
routine can be used to print the reason for failure.
|
||||
Note:
|
||||
.Fn clnt_create
|
||||
returns a valid client handle even
|
||||
if the particular version number supplied to
|
||||
.Fn clnt_create
|
||||
is not registered with the
|
||||
.Xr rpcbind 8
|
||||
service.
|
||||
This mismatch will be discovered by a
|
||||
.Fn clnt_call
|
||||
later (see
|
||||
.Xr rpc_clnt_calls 3 ) .
|
||||
However,
|
||||
.Fn clnt_create_vers
|
||||
does this for you and returns a valid handle
|
||||
only if a version within
|
||||
the range supplied is supported by the server.
|
||||
.Pp
|
||||
.It Fn clnt_destroy
|
||||
A function macro that destroys the client's RPC handle.
|
||||
Destruction usually involves deallocation
|
||||
of private data structures, including
|
||||
.Fa clnt
|
||||
itself.
|
||||
Use of
|
||||
.Fa clnt
|
||||
is undefined after calling
|
||||
.Fn clnt_destroy .
|
||||
If the RPC library opened the associated file descriptor, or
|
||||
.Dv CLSET_FD_CLOSE
|
||||
was set using
|
||||
.Fn clnt_control ,
|
||||
the file descriptor will be closed.
|
||||
The caller should call
|
||||
.Fn auth_destroy "clnt-\*[Gt]cl_auth"
|
||||
(before calling
|
||||
.Fn clnt_destroy )
|
||||
to destroy the associated
|
||||
.Dv AUTH
|
||||
structure (see
|
||||
.Xr rpc_clnt_auth 3 ) .
|
||||
.Pp
|
||||
.It Fn clnt_dg_create
|
||||
This routine creates an RPC client for the remote program
|
||||
.Fa prognum
|
||||
and version
|
||||
.Fa versnum ;
|
||||
the client uses a connectionless transport.
|
||||
The remote program is located at address
|
||||
.Fa svcaddr .
|
||||
The parameter
|
||||
.Fa fildes
|
||||
is an open and bound file descriptor.
|
||||
This routine will resend the call message in intervals of
|
||||
15 seconds until a response is received or until the
|
||||
call times out.
|
||||
The total time for the call to time out is specified by
|
||||
.Fn clnt_call
|
||||
(see
|
||||
.Fn clnt_call
|
||||
in
|
||||
.Xr rpc_clnt_calls 3 ) .
|
||||
The retry time out and the total time out periods can
|
||||
be changed using
|
||||
.Fn clnt_control .
|
||||
The user may set the size of the send and receive
|
||||
buffers with the parameters
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz ;
|
||||
values of 0 choose suitable defaults.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
.Pp
|
||||
.It Fn clnt_pcreateerror
|
||||
Print a message to standard error indicating
|
||||
why a client RPC handle could not be created.
|
||||
The message is prepended with the string
|
||||
.Fa s
|
||||
and a colon, and appended with a newline.
|
||||
.Pp
|
||||
.It Fn clnt_spcreateerror
|
||||
Like
|
||||
.Fn clnt_pcreateerror ,
|
||||
except that it returns a string
|
||||
instead of printing to the standard error.
|
||||
A newline is not appended to the message in this case.
|
||||
Warning:
|
||||
returns a pointer to a buffer that is overwritten
|
||||
on each call.
|
||||
.Pp
|
||||
.It Fn clnt_raw_create
|
||||
This routine creates an RPC
|
||||
client handle for the remote program
|
||||
.Fa prognum
|
||||
and version
|
||||
.Fa versnum .
|
||||
The transport used to pass messages to the service is
|
||||
a buffer within the process's address space,
|
||||
so the corresponding RPC
|
||||
server should live in the same address space;
|
||||
(see
|
||||
.Fn svc_raw_create
|
||||
in
|
||||
.Xr rpc_svc_create 3 ) .
|
||||
This allows simulation of RPC and measurement of
|
||||
RPC overheads, such as round trip times,
|
||||
without any kernel or networking interference.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
.Fn clnt_raw_create
|
||||
should be called after
|
||||
.Fn svc_raw_create .
|
||||
.Pp
|
||||
.It Fn clnt_tli_create
|
||||
This routine creates an RPC
|
||||
client handle for the remote program
|
||||
.Fa prognum
|
||||
and version
|
||||
.Fa versnum .
|
||||
The remote program is located at address
|
||||
.Fa svcaddr .
|
||||
If
|
||||
.Fa svcaddr
|
||||
is
|
||||
.Dv NULL
|
||||
and it is connection-oriented, it is assumed that the file descriptor
|
||||
is connected.
|
||||
For connectionless transports, if
|
||||
.Fa svcaddr
|
||||
is
|
||||
.Dv NULL ,
|
||||
.Dv RPC_UNKNOWNADDR
|
||||
error is set.
|
||||
.Fa fildes
|
||||
is a file descriptor which may be open, bound and connected.
|
||||
If it is
|
||||
.Dv RPC_ANYFD ,
|
||||
it opens a file descriptor on the transport specified by
|
||||
.Fa netconf .
|
||||
If
|
||||
.Fa fildes
|
||||
is
|
||||
.Dv RPC_ANYFD
|
||||
and
|
||||
.Fa netconf
|
||||
is
|
||||
.Dv NULL ,
|
||||
a
|
||||
.Dv RPC_UNKNOWNPROTO
|
||||
error is set.
|
||||
If
|
||||
.Fa fildes
|
||||
is unbound, then it will attempt to bind the descriptor.
|
||||
The user may specify the size of the buffers with the parameters
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz ;
|
||||
values of 0 choose suitable defaults.
|
||||
Depending upon the type of the transport (connection-oriented
|
||||
or connectionless),
|
||||
.Fn clnt_tli_create
|
||||
calls appropriate client creation routines.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
The
|
||||
.Fn clnt_pcreateerror
|
||||
routine can be used to print the reason for failure.
|
||||
The remote rpcbind
|
||||
service (see
|
||||
.Xr rpcbind 8 )
|
||||
is not consulted for the address of the remote
|
||||
service.
|
||||
.Pp
|
||||
.It Fn clnt_tp_create
|
||||
Like
|
||||
.Fn clnt_create
|
||||
except
|
||||
.Fn clnt_tp_create
|
||||
tries only one transport specified through
|
||||
.Fa netconf .
|
||||
.Fn clnt_tp_create
|
||||
creates a client handle for the program
|
||||
.Fa prognum ,
|
||||
the version
|
||||
.Fa versnum ,
|
||||
and for the transport specified by
|
||||
.Fa netconf .
|
||||
Default options are set,
|
||||
which can be changed using
|
||||
.Fn clnt_control
|
||||
calls.
|
||||
The remote rpcbind service on the host
|
||||
.Fa host
|
||||
is consulted for the address of the remote service.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
The
|
||||
.Fn clnt_pcreateerror
|
||||
routine can be used to print the reason for failure.
|
||||
.Pp
|
||||
.It Fn clnt_vc_create
|
||||
This routine creates an RPC
|
||||
client for the remote program
|
||||
.Fa prognum
|
||||
and version
|
||||
.Fa versnum ;
|
||||
the client uses a connection-oriented transport.
|
||||
The remote program is located at address
|
||||
.Fa svcaddr .
|
||||
The parameter
|
||||
.Fa fildes
|
||||
is an open and bound file descriptor.
|
||||
The user may specify the size of the send and receive buffers
|
||||
with the parameters
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz ;
|
||||
values of 0 choose suitable defaults.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails.
|
||||
The address
|
||||
.Fa svcaddr
|
||||
should not be
|
||||
.Dv NULL
|
||||
and should point to the actual address of the remote program.
|
||||
.Fn clnt_vc_create
|
||||
does not consult the remote rpcbind service for this information.
|
||||
.Pp
|
||||
.It struct rpc_createerr rpc_createerr;
|
||||
A global variable whose value is set by any RPC
|
||||
client handle creation routine
|
||||
that fails.
|
||||
It is used by the routine
|
||||
.Fn clnt_pcreateerror
|
||||
to print the reason for the failure.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_clnt_auth 3 ,
|
||||
.Xr rpc_clnt_calls 3 ,
|
||||
.Xr rpcbind 8
|
||||
@@ -0,0 +1,53 @@
|
||||
/* $NetBSD: rpc_commondata.c,v 1.8 2003/01/18 11:29:05 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: rpc_commondata.c,v 1.8 2003/01/18 11:29:05 thorpej Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
/*
|
||||
* This file should only contain common data (global data) that is exported
|
||||
* by public interfaces
|
||||
*/
|
||||
struct opaque_auth _null_auth;
|
||||
fd_set svc_fdset;
|
||||
int svc_maxfd = -1;
|
||||
#ifndef _REENTRANT
|
||||
#undef rpc_createerr
|
||||
struct rpc_createerr rpc_createerr;
|
||||
#endif
|
||||
@@ -0,0 +1,59 @@
|
||||
/* $NetBSD: rpc_dtablesize.c,v 1.14 1998/11/15 17:32:43 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
|
||||
static char *sccsid = "@(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: rpc_dtablesize.c,v 1.14 1998/11/15 17:32:43 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
int _rpc_dtablesize __P((void)); /* XXX */
|
||||
|
||||
/*
|
||||
* Cache the result of sysconf(_SC_OPEN_MAX), so we don't have to do an
|
||||
* expensive system call every time.
|
||||
*/
|
||||
int
|
||||
_rpc_dtablesize()
|
||||
{
|
||||
static int size;
|
||||
if (size == 0)
|
||||
size = (int)sysconf(_SC_OPEN_MAX);
|
||||
return (size);
|
||||
}
|
||||
@@ -0,0 +1,897 @@
|
||||
/* $NetBSD: rpc_generic.c,v 1.24 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */
|
||||
|
||||
/*
|
||||
* rpc_generic.c, Miscl routines for RPC.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: rpc_generic.c,v 1.24 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/resource.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <netdb.h>
|
||||
#include <netconfig.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <rpc/nettype.h>
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(taddr2uaddr,_taddr2uaddr)
|
||||
__weak_alias(uaddr2taddr,_uaddr2taddr)
|
||||
#endif
|
||||
|
||||
struct handle {
|
||||
NCONF_HANDLE *nhandle;
|
||||
int nflag; /* Whether NETPATH or NETCONFIG */
|
||||
int nettype;
|
||||
};
|
||||
|
||||
static const struct _rpcnettype {
|
||||
const char *name;
|
||||
const int type;
|
||||
} _rpctypelist[] = {
|
||||
{ "netpath", _RPC_NETPATH },
|
||||
{ "visible", _RPC_VISIBLE },
|
||||
{ "circuit_v", _RPC_CIRCUIT_V },
|
||||
{ "datagram_v", _RPC_DATAGRAM_V },
|
||||
{ "circuit_n", _RPC_CIRCUIT_N },
|
||||
{ "datagram_n", _RPC_DATAGRAM_N },
|
||||
{ "tcp", _RPC_TCP },
|
||||
{ "udp", _RPC_UDP },
|
||||
{ 0, _RPC_NONE }
|
||||
};
|
||||
|
||||
struct netid_af {
|
||||
const char *netid;
|
||||
int af;
|
||||
int protocol;
|
||||
};
|
||||
|
||||
static const struct netid_af na_cvt[] = {
|
||||
{ "udp", AF_INET, IPPROTO_UDP },
|
||||
{ "tcp", AF_INET, IPPROTO_TCP },
|
||||
#ifdef INET6
|
||||
{ "udp6", AF_INET6, IPPROTO_UDP },
|
||||
{ "tcp6", AF_INET6, IPPROTO_TCP },
|
||||
#endif
|
||||
{ "local", AF_LOCAL, 0 }
|
||||
};
|
||||
|
||||
#if 0
|
||||
static char *strlocase __P((char *));
|
||||
#endif
|
||||
static int getnettype __P((const char *));
|
||||
|
||||
/*
|
||||
* Cache the result of getrlimit(), so we don't have to do an
|
||||
* expensive call every time.
|
||||
*/
|
||||
int
|
||||
__rpc_dtbsize()
|
||||
{
|
||||
static int tbsize;
|
||||
struct rlimit rl;
|
||||
|
||||
if (tbsize) {
|
||||
return (tbsize);
|
||||
}
|
||||
if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
|
||||
return (tbsize = (int)rl.rlim_max);
|
||||
}
|
||||
/*
|
||||
* Something wrong. I'll try to save face by returning a
|
||||
* pessimistic number.
|
||||
*/
|
||||
return (32);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Find the appropriate buffer size
|
||||
*/
|
||||
u_int
|
||||
/*ARGSUSED*/
|
||||
__rpc_get_t_size(af, proto, size)
|
||||
int af, proto;
|
||||
int size; /* Size requested */
|
||||
{
|
||||
int maxsize, defsize;
|
||||
|
||||
maxsize = 256 * 1024; /* XXX */
|
||||
switch (proto) {
|
||||
case IPPROTO_TCP:
|
||||
defsize = 64 * 1024; /* XXX */
|
||||
break;
|
||||
case IPPROTO_UDP:
|
||||
defsize = UDPMSGSIZE;
|
||||
break;
|
||||
default:
|
||||
defsize = RPC_MAXDATASIZE;
|
||||
break;
|
||||
}
|
||||
if (size == 0)
|
||||
return defsize;
|
||||
|
||||
/* Check whether the value is within the upper max limit */
|
||||
return (size > maxsize ? (u_int)maxsize : (u_int)size);
|
||||
}
|
||||
|
||||
/*
|
||||
* Find the appropriate address buffer size
|
||||
*/
|
||||
u_int
|
||||
__rpc_get_a_size(af)
|
||||
int af;
|
||||
{
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
return sizeof (struct sockaddr_in);
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
return sizeof (struct sockaddr_in6);
|
||||
#endif
|
||||
case AF_LOCAL:
|
||||
return sizeof (struct sockaddr_un);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return ((u_int)RPC_MAXADDRSIZE);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static char *
|
||||
strlocase(p)
|
||||
char *p;
|
||||
{
|
||||
char *t = p;
|
||||
|
||||
_DIAGASSERT(p != NULL);
|
||||
|
||||
for (; *p; p++)
|
||||
if (isupper(*p))
|
||||
*p = tolower(*p);
|
||||
return (t);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Returns the type of the network as defined in <rpc/nettype.h>
|
||||
* If nettype is NULL, it defaults to NETPATH.
|
||||
*/
|
||||
static int
|
||||
getnettype(nettype)
|
||||
const char *nettype;
|
||||
{
|
||||
int i;
|
||||
|
||||
if ((nettype == NULL) || (nettype[0] == 0)) {
|
||||
return (_RPC_NETPATH); /* Default */
|
||||
}
|
||||
|
||||
#if 0
|
||||
nettype = strlocase(nettype);
|
||||
#endif
|
||||
for (i = 0; _rpctypelist[i].name; i++)
|
||||
if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
|
||||
return (_rpctypelist[i].type);
|
||||
}
|
||||
return (_rpctypelist[i].type);
|
||||
}
|
||||
|
||||
/*
|
||||
* For the given nettype (tcp or udp only), return the first structure found.
|
||||
* This should be freed by calling freenetconfigent()
|
||||
*/
|
||||
|
||||
#ifdef _REENTRANT
|
||||
static thread_key_t tcp_key, udp_key;
|
||||
static once_t __rpc_getconfigp_once = ONCE_INITIALIZER;
|
||||
|
||||
static void
|
||||
__rpc_getconfigp_setup(void)
|
||||
{
|
||||
|
||||
thr_keycreate(&tcp_key, free);
|
||||
thr_keycreate(&udp_key, free);
|
||||
}
|
||||
#endif
|
||||
|
||||
struct netconfig *
|
||||
__rpc_getconfip(nettype)
|
||||
const char *nettype;
|
||||
{
|
||||
char *netid;
|
||||
char *netid_tcp = NULL;
|
||||
char *netid_udp = NULL;
|
||||
static char *netid_tcp_main;
|
||||
static char *netid_udp_main;
|
||||
struct netconfig *dummy;
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0) {
|
||||
netid_udp = netid_udp_main;
|
||||
netid_tcp = netid_tcp_main;
|
||||
} else {
|
||||
thr_once(&__rpc_getconfigp_once, __rpc_getconfigp_setup);
|
||||
netid_tcp = thr_getspecific(tcp_key);
|
||||
netid_udp = thr_getspecific(udp_key);
|
||||
}
|
||||
#else
|
||||
netid_udp = netid_udp_main;
|
||||
netid_tcp = netid_tcp_main;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(nettype != NULL);
|
||||
|
||||
if (!netid_udp && !netid_tcp) {
|
||||
struct netconfig *nconf;
|
||||
void *confighandle;
|
||||
|
||||
if (!(confighandle = setnetconfig())) {
|
||||
syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
|
||||
return (NULL);
|
||||
}
|
||||
while ((nconf = getnetconfig(confighandle)) != NULL) {
|
||||
if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
|
||||
if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
|
||||
netid_tcp = strdup(nconf->nc_netid);
|
||||
if (netid_tcp == NULL)
|
||||
return NULL;
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0)
|
||||
netid_tcp_main = netid_tcp;
|
||||
else
|
||||
thr_setspecific(tcp_key,
|
||||
(void *) netid_tcp);
|
||||
#else
|
||||
netid_tcp_main = netid_tcp;
|
||||
#endif
|
||||
} else
|
||||
if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
|
||||
netid_udp = strdup(nconf->nc_netid);
|
||||
if (netid_udp == NULL)
|
||||
return NULL;
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0)
|
||||
netid_udp_main = netid_udp;
|
||||
else
|
||||
thr_setspecific(udp_key,
|
||||
(void *) netid_udp);
|
||||
#else
|
||||
netid_udp_main = netid_udp;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
endnetconfig(confighandle);
|
||||
}
|
||||
if (strcmp(nettype, "udp") == 0)
|
||||
netid = netid_udp;
|
||||
else if (strcmp(nettype, "tcp") == 0)
|
||||
netid = netid_tcp;
|
||||
else {
|
||||
return (NULL);
|
||||
}
|
||||
if ((netid == NULL) || (netid[0] == 0)) {
|
||||
return (NULL);
|
||||
}
|
||||
dummy = getnetconfigent(netid);
|
||||
return (dummy);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the type of the nettype, which should then be used with
|
||||
* __rpc_getconf().
|
||||
*/
|
||||
void *
|
||||
__rpc_setconf(nettype)
|
||||
const char *nettype;
|
||||
{
|
||||
struct handle *handle;
|
||||
|
||||
/* nettype may be NULL; getnettype() supports that */
|
||||
|
||||
handle = malloc(sizeof(*handle));
|
||||
if (handle == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
switch (handle->nettype = getnettype(nettype)) {
|
||||
case _RPC_NETPATH:
|
||||
case _RPC_CIRCUIT_N:
|
||||
case _RPC_DATAGRAM_N:
|
||||
if (!(handle->nhandle = setnetpath())) {
|
||||
free(handle);
|
||||
return (NULL);
|
||||
}
|
||||
handle->nflag = TRUE;
|
||||
break;
|
||||
case _RPC_VISIBLE:
|
||||
case _RPC_CIRCUIT_V:
|
||||
case _RPC_DATAGRAM_V:
|
||||
case _RPC_TCP:
|
||||
case _RPC_UDP:
|
||||
if (!(handle->nhandle = setnetconfig())) {
|
||||
syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
|
||||
free(handle);
|
||||
return (NULL);
|
||||
}
|
||||
handle->nflag = FALSE;
|
||||
break;
|
||||
default:
|
||||
free(handle);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
return (handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Returns the next netconfig struct for the given "net" type.
|
||||
* __rpc_setconf() should have been called previously.
|
||||
*/
|
||||
struct netconfig *
|
||||
__rpc_getconf(vhandle)
|
||||
void *vhandle;
|
||||
{
|
||||
struct handle *handle;
|
||||
struct netconfig *nconf;
|
||||
|
||||
handle = (struct handle *)vhandle;
|
||||
if (handle == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
for (;;) {
|
||||
if (handle->nflag)
|
||||
nconf = getnetpath(handle->nhandle);
|
||||
else
|
||||
nconf = getnetconfig(handle->nhandle);
|
||||
if (nconf == NULL)
|
||||
break;
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
continue;
|
||||
switch (handle->nettype) {
|
||||
case _RPC_VISIBLE:
|
||||
if (!(nconf->nc_flag & NC_VISIBLE))
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
case _RPC_NETPATH: /* Be happy */
|
||||
break;
|
||||
case _RPC_CIRCUIT_V:
|
||||
if (!(nconf->nc_flag & NC_VISIBLE))
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
case _RPC_CIRCUIT_N:
|
||||
if ((nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD))
|
||||
continue;
|
||||
break;
|
||||
case _RPC_DATAGRAM_V:
|
||||
if (!(nconf->nc_flag & NC_VISIBLE))
|
||||
continue;
|
||||
/* FALLTHROUGH */
|
||||
case _RPC_DATAGRAM_N:
|
||||
if (nconf->nc_semantics != NC_TPI_CLTS)
|
||||
continue;
|
||||
break;
|
||||
case _RPC_TCP:
|
||||
if (((nconf->nc_semantics != NC_TPI_COTS) &&
|
||||
(nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
|
||||
(strcmp(nconf->nc_protofmly, NC_INET)
|
||||
#ifdef INET6
|
||||
&& strcmp(nconf->nc_protofmly, NC_INET6))
|
||||
#else
|
||||
)
|
||||
#endif
|
||||
||
|
||||
strcmp(nconf->nc_proto, NC_TCP))
|
||||
continue;
|
||||
break;
|
||||
case _RPC_UDP:
|
||||
if ((nconf->nc_semantics != NC_TPI_CLTS) ||
|
||||
(strcmp(nconf->nc_protofmly, NC_INET)
|
||||
#ifdef INET6
|
||||
&& strcmp(nconf->nc_protofmly, NC_INET6))
|
||||
#else
|
||||
)
|
||||
#endif
|
||||
||
|
||||
strcmp(nconf->nc_proto, NC_UDP))
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return (nconf);
|
||||
}
|
||||
|
||||
void
|
||||
__rpc_endconf(vhandle)
|
||||
void * vhandle;
|
||||
{
|
||||
struct handle *handle;
|
||||
|
||||
handle = (struct handle *) vhandle;
|
||||
if (handle == NULL) {
|
||||
return;
|
||||
}
|
||||
if (handle->nflag) {
|
||||
endnetpath(handle->nhandle);
|
||||
} else {
|
||||
endnetconfig(handle->nhandle);
|
||||
}
|
||||
free(handle);
|
||||
}
|
||||
|
||||
/*
|
||||
* Used to ping the NULL procedure for clnt handle.
|
||||
* Returns NULL if fails, else a non-NULL pointer.
|
||||
*/
|
||||
void *
|
||||
rpc_nullproc(clnt)
|
||||
CLIENT *clnt;
|
||||
{
|
||||
struct timeval TIMEOUT = {25, 0};
|
||||
|
||||
if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
|
||||
(xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
|
||||
return (NULL);
|
||||
}
|
||||
return ((void *) clnt);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try all possible transports until
|
||||
* one succeeds in finding the netconf for the given fd.
|
||||
*/
|
||||
struct netconfig *
|
||||
__rpcgettp(fd)
|
||||
int fd;
|
||||
{
|
||||
const char *netid;
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
if (!__rpc_fd2sockinfo(fd, &si))
|
||||
return NULL;
|
||||
|
||||
if (!__rpc_sockinfo2netid(&si, &netid))
|
||||
return NULL;
|
||||
|
||||
return getnetconfigent(__UNCONST(netid));
|
||||
}
|
||||
|
||||
int
|
||||
__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
|
||||
{
|
||||
socklen_t len;
|
||||
int type, proto;
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
_DIAGASSERT(sip != NULL);
|
||||
|
||||
len = sizeof ss;
|
||||
if (getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
|
||||
return 0;
|
||||
sip->si_alen = len;
|
||||
|
||||
len = sizeof type;
|
||||
if (getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
|
||||
return 0;
|
||||
|
||||
/* XXX */
|
||||
if (ss.ss_family != AF_LOCAL) {
|
||||
if (type == SOCK_STREAM)
|
||||
proto = IPPROTO_TCP;
|
||||
else if (type == SOCK_DGRAM)
|
||||
proto = IPPROTO_UDP;
|
||||
else
|
||||
return 0;
|
||||
} else
|
||||
proto = 0;
|
||||
|
||||
sip->si_af = ss.ss_family;
|
||||
sip->si_proto = proto;
|
||||
sip->si_socktype = type;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Linear search, but the number of entries is small.
|
||||
*/
|
||||
int
|
||||
__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
_DIAGASSERT(nconf != NULL);
|
||||
_DIAGASSERT(sip != NULL);
|
||||
|
||||
for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
|
||||
if (!strcmp(na_cvt[i].netid, nconf->nc_netid)) {
|
||||
sip->si_af = na_cvt[i].af;
|
||||
sip->si_proto = na_cvt[i].protocol;
|
||||
sip->si_socktype =
|
||||
__rpc_seman2socktype((int)nconf->nc_semantics);
|
||||
if (sip->si_socktype == -1)
|
||||
return 0;
|
||||
sip->si_alen = __rpc_get_a_size(sip->si_af);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
__rpc_nconf2fd(const struct netconfig *nconf)
|
||||
{
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
_DIAGASSERT(nconf != NULL);
|
||||
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si))
|
||||
return 0;
|
||||
|
||||
return socket(si.si_af, si.si_socktype, si.si_proto);
|
||||
}
|
||||
|
||||
int
|
||||
__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
_DIAGASSERT(sip != NULL);
|
||||
/* netid may be NULL */
|
||||
|
||||
for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
|
||||
if (na_cvt[i].af == sip->si_af &&
|
||||
na_cvt[i].protocol == sip->si_proto) {
|
||||
if (netid)
|
||||
*netid = na_cvt[i].netid;
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *
|
||||
taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
|
||||
{
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
_DIAGASSERT(nconf != NULL);
|
||||
_DIAGASSERT(nbuf != NULL);
|
||||
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si))
|
||||
return NULL;
|
||||
return __rpc_taddr2uaddr_af(si.si_af, nbuf);
|
||||
}
|
||||
|
||||
struct netbuf *
|
||||
uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
|
||||
{
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
_DIAGASSERT(nconf != NULL);
|
||||
_DIAGASSERT(uaddr != NULL);
|
||||
|
||||
if (!__rpc_nconf2sockinfo(nconf, &si))
|
||||
return NULL;
|
||||
return __rpc_uaddr2taddr_af(si.si_af, uaddr);
|
||||
}
|
||||
|
||||
char *
|
||||
__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
|
||||
{
|
||||
char *ret;
|
||||
struct sockaddr_in *sinp;
|
||||
struct sockaddr_un *sun;
|
||||
char namebuf[INET_ADDRSTRLEN];
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
char namebuf6[INET6_ADDRSTRLEN];
|
||||
#endif
|
||||
u_int16_t port;
|
||||
|
||||
_DIAGASSERT(nbuf != NULL);
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
sinp = nbuf->buf;
|
||||
if (inet_ntop(af, &sinp->sin_addr, namebuf, sizeof namebuf)
|
||||
== NULL)
|
||||
return NULL;
|
||||
port = ntohs(sinp->sin_port);
|
||||
if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
|
||||
port & 0xff) < 0)
|
||||
return NULL;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = nbuf->buf;
|
||||
if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
|
||||
== NULL)
|
||||
return NULL;
|
||||
port = ntohs(sin6->sin6_port);
|
||||
if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
|
||||
port & 0xff) < 0)
|
||||
return NULL;
|
||||
break;
|
||||
#endif
|
||||
case AF_LOCAL:
|
||||
sun = nbuf->buf;
|
||||
sun->sun_path[sizeof(sun->sun_path) - 1] = '\0'; /* safety */
|
||||
ret = strdup(sun->sun_path);
|
||||
break;
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct netbuf *
|
||||
__rpc_uaddr2taddr_af(int af, const char *uaddr)
|
||||
{
|
||||
struct netbuf *ret = NULL;
|
||||
char *addrstr, *p;
|
||||
unsigned port, portlo, porthi;
|
||||
struct sockaddr_in *sinp;
|
||||
#ifdef INET6
|
||||
struct sockaddr_in6 *sin6;
|
||||
#endif
|
||||
struct sockaddr_un *sun;
|
||||
|
||||
_DIAGASSERT(uaddr != NULL);
|
||||
|
||||
addrstr = strdup(uaddr);
|
||||
if (addrstr == NULL)
|
||||
return NULL;
|
||||
|
||||
/*
|
||||
* AF_LOCAL addresses are expected to be absolute
|
||||
* pathnames, anything else will be AF_INET or AF_INET6.
|
||||
*/
|
||||
port = 0;
|
||||
if (*addrstr != '/') {
|
||||
p = strrchr(addrstr, '.');
|
||||
if (p == NULL)
|
||||
goto out;
|
||||
portlo = (unsigned)atoi(p + 1);
|
||||
*p = '\0';
|
||||
|
||||
p = strrchr(addrstr, '.');
|
||||
if (p == NULL)
|
||||
goto out;
|
||||
porthi = (unsigned)atoi(p + 1);
|
||||
*p = '\0';
|
||||
port = (porthi << 8) | portlo;
|
||||
}
|
||||
|
||||
ret = malloc(sizeof(*ret));
|
||||
if (ret == NULL)
|
||||
goto out;
|
||||
|
||||
switch (af) {
|
||||
case AF_INET:
|
||||
sinp = malloc(sizeof(*sinp));
|
||||
if (sinp == NULL)
|
||||
goto out;
|
||||
memset(sinp, 0, sizeof *sinp);
|
||||
sinp->sin_family = AF_INET;
|
||||
sinp->sin_port = htons(port);
|
||||
if (inet_pton(AF_INET, addrstr, &sinp->sin_addr) <= 0) {
|
||||
free(sinp);
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
sinp->sin_len = ret->maxlen = ret->len = sizeof *sinp;
|
||||
ret->buf = sinp;
|
||||
break;
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
sin6 = malloc(sizeof(*sin6));
|
||||
if (sin6 == NULL)
|
||||
goto out;
|
||||
memset(sin6, 0, sizeof *sin6);
|
||||
sin6->sin6_family = AF_INET6;
|
||||
sin6->sin6_port = htons(port);
|
||||
if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
|
||||
free(sin6);
|
||||
free(ret);
|
||||
ret = NULL;
|
||||
goto out;
|
||||
}
|
||||
sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
|
||||
ret->buf = sin6;
|
||||
break;
|
||||
#endif
|
||||
case AF_LOCAL:
|
||||
sun = malloc(sizeof(*sun));
|
||||
if (sun == NULL)
|
||||
goto out;
|
||||
memset(sun, 0, sizeof *sun);
|
||||
sun->sun_family = AF_LOCAL;
|
||||
strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
|
||||
ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
|
||||
ret->buf = sun;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
out:
|
||||
free(addrstr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
__rpc_seman2socktype(int semantics)
|
||||
{
|
||||
switch (semantics) {
|
||||
case NC_TPI_CLTS:
|
||||
return SOCK_DGRAM;
|
||||
case NC_TPI_COTS_ORD:
|
||||
return SOCK_STREAM;
|
||||
case NC_TPI_RAW:
|
||||
return SOCK_RAW;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int
|
||||
__rpc_socktype2seman(int socktype)
|
||||
{
|
||||
switch (socktype) {
|
||||
case SOCK_DGRAM:
|
||||
return NC_TPI_CLTS;
|
||||
case SOCK_STREAM:
|
||||
return NC_TPI_COTS_ORD;
|
||||
case SOCK_RAW:
|
||||
return NC_TPI_RAW;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* XXXX - IPv6 scope IDs can't be handled in universal addresses.
|
||||
* Here, we compare the original server address to that of the RPC
|
||||
* service we just received back from a call to rpcbind on the remote
|
||||
* machine. If they are both "link local" or "site local", copy
|
||||
* the scope id of the server address over to the service address.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
int
|
||||
__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
|
||||
{
|
||||
#ifdef INET6
|
||||
struct sockaddr *sa_new, *sa_svc;
|
||||
struct sockaddr_in6 *sin6_new, *sin6_svc;
|
||||
|
||||
_DIAGASSERT(new != NULL);
|
||||
_DIAGASSERT(svc != NULL);
|
||||
|
||||
sa_svc = (struct sockaddr *)svc->buf;
|
||||
sa_new = (struct sockaddr *)new->buf;
|
||||
|
||||
if (sa_new->sa_family == sa_svc->sa_family &&
|
||||
sa_new->sa_family == AF_INET6) {
|
||||
sin6_new = (struct sockaddr_in6 *)new->buf;
|
||||
sin6_svc = (struct sockaddr_in6 *)svc->buf;
|
||||
|
||||
if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
|
||||
IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
|
||||
(IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
|
||||
IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
|
||||
sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
int
|
||||
__rpc_sockisbound(int fd)
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t slen;
|
||||
|
||||
slen = sizeof (struct sockaddr_storage);
|
||||
if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
|
||||
return 0;
|
||||
|
||||
switch (ss.ss_family) {
|
||||
case AF_INET:
|
||||
return (((struct sockaddr_in *)
|
||||
(void *)&ss)->sin_port != 0);
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
return (((struct sockaddr_in6 *)
|
||||
(void *)&ss)->sin6_port != 0);
|
||||
#endif
|
||||
case AF_LOCAL:
|
||||
/* XXX check this */
|
||||
return (((struct sockaddr_un *)
|
||||
(void *)&ss)->sun_path[0] != '\0');
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* For TCP transport, Host Requirements RFCs mandate
|
||||
* Nagle (RFC-896) processing. But for RPC, Nagle
|
||||
* processing adds adds unwanted latency to the last,
|
||||
* partial TCP segment of each RPC message. See:
|
||||
* R. W. Scheifler and J. Gettys, The X Window System,
|
||||
* ACM Transactions on Graphics 16:8 (Aug. 1983), pp. 57-69.
|
||||
* So for TCP transport, disable Nagle via TCP_NODELAY.
|
||||
* XXX: moral equivalent for non-TCP protocols?
|
||||
*/
|
||||
int
|
||||
__rpc_setnodelay(int fd, const struct __rpc_sockinfo *si)
|
||||
{
|
||||
int one = 1;
|
||||
if (si->si_proto != IPPROTO_TCP)
|
||||
return 0;
|
||||
return setsockopt(fd, si->si_proto, TCP_NODELAY, &one, sizeof(one));
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/* $NetBSD: rpc_internal.h,v 1.6 2009/04/04 15:31:08 christos Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2004 The NetBSD Foundation, Inc.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This code is derived from software contributed to The NetBSD Foundation
|
||||
* by Frank van der Linden.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. 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.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
|
||||
*/
|
||||
/*
|
||||
* Private include file for XDR functions only used internally in libc.
|
||||
* These are not exported interfaces.
|
||||
*/
|
||||
|
||||
bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t);
|
||||
bool_t __xdrrec_setnonblock(XDR *, int);
|
||||
void __xprt_unregister_unlocked(SVCXPRT *);
|
||||
bool_t __svc_clean_idle(fd_set *, int, bool_t);
|
||||
|
||||
u_int __rpc_get_a_size(int);
|
||||
int __rpc_dtbsize(void);
|
||||
struct netconfig *__rpcgettp(int);
|
||||
int __rpc_get_default_domain(char **);
|
||||
|
||||
char *__rpc_taddr2uaddr_af(int, const struct netbuf *);
|
||||
struct netbuf *__rpc_uaddr2taddr_af(int, const char *);
|
||||
int __rpc_fixup_addr(struct netbuf *, const struct netbuf *);
|
||||
int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **);
|
||||
int __rpc_seman2socktype(int);
|
||||
int __rpc_socktype2seman(int);
|
||||
void *rpc_nullproc(CLIENT *);
|
||||
int __rpc_sockisbound(int);
|
||||
|
||||
struct netbuf *__rpcb_findaddr(rpcprog_t, rpcvers_t, const struct netconfig *,
|
||||
const char *, CLIENT **);
|
||||
bool_t __rpc_control(int, void *);
|
||||
|
||||
char *_get_next_token(char *, int);
|
||||
|
||||
u_int32_t __rpc_getxid(void);
|
||||
#define __RPC_GETXID() (__rpc_getxid())
|
||||
|
||||
extern SVCXPRT **__svc_xports;
|
||||
extern int __svc_maxrec;
|
||||
@@ -0,0 +1,364 @@
|
||||
/* $NetBSD: rpc_prot.c,v 1.18 2003/05/29 18:15:25 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: rpc_prot.c,v 1.18 2003/05/29 18:15:25 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rpc_prot.c
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* This set of routines implements the rpc message definition,
|
||||
* its serializer and some common rpc utility routines.
|
||||
* The routines are meant for various implementations of rpc -
|
||||
* they are NOT for the rpc client or rpc service implementations!
|
||||
* Because authentication stuff is easy and is part of rpc, the opaque
|
||||
* routines are also in this program.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_accepted_reply,_xdr_accepted_reply)
|
||||
__weak_alias(xdr_callhdr,_xdr_callhdr)
|
||||
__weak_alias(xdr_des_block,_xdr_des_block)
|
||||
__weak_alias(xdr_opaque_auth,_xdr_opaque_auth)
|
||||
__weak_alias(xdr_rejected_reply,_xdr_rejected_reply)
|
||||
__weak_alias(xdr_replymsg,_xdr_replymsg)
|
||||
#endif
|
||||
|
||||
static void accepted __P((enum accept_stat, struct rpc_err *));
|
||||
static void rejected __P((enum reject_stat, struct rpc_err *));
|
||||
|
||||
/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
|
||||
|
||||
/*
|
||||
* XDR an opaque authentication struct
|
||||
* (see auth.h)
|
||||
*/
|
||||
bool_t
|
||||
xdr_opaque_auth(xdrs, ap)
|
||||
XDR *xdrs;
|
||||
struct opaque_auth *ap;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(ap != NULL);
|
||||
|
||||
if (xdr_enum(xdrs, &(ap->oa_flavor)))
|
||||
return (xdr_bytes(xdrs, &ap->oa_base,
|
||||
&ap->oa_length, MAX_AUTH_BYTES));
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR a DES block
|
||||
*/
|
||||
bool_t
|
||||
xdr_des_block(xdrs, blkp)
|
||||
XDR *xdrs;
|
||||
des_block *blkp;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(blkp != NULL);
|
||||
|
||||
return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
|
||||
|
||||
/*
|
||||
* XDR the MSG_ACCEPTED part of a reply message union
|
||||
*/
|
||||
bool_t
|
||||
xdr_accepted_reply(xdrs, ar)
|
||||
XDR *xdrs;
|
||||
struct accepted_reply *ar;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(ar != NULL);
|
||||
|
||||
/* personalized union, rather than calling xdr_union */
|
||||
if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
|
||||
return (FALSE);
|
||||
if (! xdr_enum(xdrs, (enum_t *)(void *)&(ar->ar_stat)))
|
||||
return (FALSE);
|
||||
switch (ar->ar_stat) {
|
||||
|
||||
case SUCCESS:
|
||||
return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
|
||||
|
||||
case PROG_MISMATCH:
|
||||
if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
|
||||
return (FALSE);
|
||||
return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
|
||||
|
||||
case GARBAGE_ARGS:
|
||||
case SYSTEM_ERR:
|
||||
case PROC_UNAVAIL:
|
||||
case PROG_UNAVAIL:
|
||||
break;
|
||||
}
|
||||
return (TRUE); /* TRUE => open ended set of problems */
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR the MSG_DENIED part of a reply message union
|
||||
*/
|
||||
bool_t
|
||||
xdr_rejected_reply(xdrs, rr)
|
||||
XDR *xdrs;
|
||||
struct rejected_reply *rr;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(rr != NULL);
|
||||
|
||||
/* personalized union, rather than calling xdr_union */
|
||||
if (! xdr_enum(xdrs, (enum_t *)(void *)&(rr->rj_stat)))
|
||||
return (FALSE);
|
||||
switch (rr->rj_stat) {
|
||||
|
||||
case RPC_MISMATCH:
|
||||
if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
|
||||
return (FALSE);
|
||||
return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
|
||||
|
||||
case AUTH_ERROR:
|
||||
return (xdr_enum(xdrs, (enum_t *)(void *)&(rr->rj_why)));
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
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(xdrs, rmsg)
|
||||
XDR *xdrs;
|
||||
struct rpc_msg *rmsg;
|
||||
{
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(rmsg != NULL);
|
||||
|
||||
if (
|
||||
xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
|
||||
xdr_enum(xdrs, (enum_t *)(void *)&(rmsg->rm_direction)) &&
|
||||
(rmsg->rm_direction == REPLY) )
|
||||
return (xdr_union(xdrs, (enum_t *)(void *)&(rmsg->rm_reply.rp_stat),
|
||||
(caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
|
||||
NULL_xdrproc_t));
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Serializes the "static part" of a call message header.
|
||||
* The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
|
||||
* The rm_xid is not really static, but the user can easily munge on the fly.
|
||||
*/
|
||||
bool_t
|
||||
xdr_callhdr(xdrs, cmsg)
|
||||
XDR *xdrs;
|
||||
struct rpc_msg *cmsg;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(cmsg != NULL);
|
||||
|
||||
cmsg->rm_direction = CALL;
|
||||
cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
|
||||
if (
|
||||
(xdrs->x_op == XDR_ENCODE) &&
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
|
||||
xdr_enum(xdrs, (enum_t *)(void *)&(cmsg->rm_direction)) &&
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
|
||||
xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
|
||||
return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/* ************************** Client utility routine ************* */
|
||||
|
||||
static void
|
||||
accepted(acpt_stat, error)
|
||||
enum accept_stat acpt_stat;
|
||||
struct rpc_err *error;
|
||||
{
|
||||
|
||||
_DIAGASSERT(error != NULL);
|
||||
|
||||
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;
|
||||
}
|
||||
/* NOTREACHED */
|
||||
/* something's wrong, but we don't know what ... */
|
||||
error->re_status = RPC_FAILED;
|
||||
error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
|
||||
error->re_lb.s2 = (int32_t)acpt_stat;
|
||||
}
|
||||
|
||||
static void
|
||||
rejected(rjct_stat, error)
|
||||
enum reject_stat rjct_stat;
|
||||
struct rpc_err *error;
|
||||
{
|
||||
|
||||
_DIAGASSERT(error != NULL);
|
||||
|
||||
switch (rjct_stat) {
|
||||
case RPC_MISMATCH:
|
||||
error->re_status = RPC_VERSMISMATCH;
|
||||
return;
|
||||
|
||||
case AUTH_ERROR:
|
||||
error->re_status = RPC_AUTHERROR;
|
||||
return;
|
||||
}
|
||||
/* something's wrong, but we don't know what ... */
|
||||
/* NOTREACHED */
|
||||
error->re_status = RPC_FAILED;
|
||||
error->re_lb.s1 = (int32_t)MSG_DENIED;
|
||||
error->re_lb.s2 = (int32_t)rjct_stat;
|
||||
}
|
||||
|
||||
/*
|
||||
* given a reply message, fills in the error
|
||||
*/
|
||||
void
|
||||
_seterr_reply(msg, error)
|
||||
struct rpc_msg *msg;
|
||||
struct rpc_err *error;
|
||||
{
|
||||
|
||||
_DIAGASSERT(msg != NULL);
|
||||
_DIAGASSERT(error != NULL);
|
||||
|
||||
/* 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 = (int32_t)(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;
|
||||
|
||||
case RPC_FAILED:
|
||||
case RPC_SUCCESS:
|
||||
case RPC_PROGNOTREGISTERED:
|
||||
case RPC_PMAPFAILURE:
|
||||
case RPC_UNKNOWNPROTO:
|
||||
case RPC_UNKNOWNHOST:
|
||||
case RPC_SYSTEMERROR:
|
||||
case RPC_CANTDECODEARGS:
|
||||
case RPC_PROCUNAVAIL:
|
||||
case RPC_PROGUNAVAIL:
|
||||
case RPC_TIMEDOUT:
|
||||
case RPC_CANTRECV:
|
||||
case RPC_CANTSEND:
|
||||
case RPC_CANTDECODERES:
|
||||
case RPC_CANTENCODEARGS:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,457 @@
|
||||
/* $NetBSD: rpc_soc.c,v 1.13 2010/12/08 02:06:38 joerg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/* #ident "@(#)rpc_soc.c 1.17 94/04/24 SMI" */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
* In addition, portions of such source code were derived from Berkeley
|
||||
* 4.3 BSD under license from the Regents of the University of
|
||||
* California.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: rpc_soc.c,v 1.13 2010/12/08 02:06:38 joerg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef PORTMAP
|
||||
/*
|
||||
* rpc_soc.c
|
||||
*
|
||||
* The backward compatibility routines for the earlier implementation
|
||||
* of RPC, where the only transports supported were tcp/ip and udp/ip.
|
||||
* Based on berkeley socket abstraction, now implemented on the top
|
||||
* of TLI/Streams
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <stdio.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/pmap_clnt.h>
|
||||
#include <rpc/pmap_prot.h>
|
||||
#include <rpc/nettype.h>
|
||||
#include <netinet/in.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <syslog.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(clntudp_bufcreate,_clntudp_bufcreate)
|
||||
__weak_alias(clntudp_create,_clntudp_create)
|
||||
__weak_alias(clnttcp_create,_clnttcp_create)
|
||||
__weak_alias(clntraw_create,_clntraw_create)
|
||||
__weak_alias(get_myaddress,_get_myaddress)
|
||||
__weak_alias(svcfd_create,_svcfd_create)
|
||||
__weak_alias(svcudp_bufcreate,_svcudp_bufcreate)
|
||||
__weak_alias(svcudp_create,_svcudp_create)
|
||||
__weak_alias(svctcp_create,_svctcp_create)
|
||||
__weak_alias(svcraw_create,_svcraw_create)
|
||||
__weak_alias(callrpc,_callrpc)
|
||||
__weak_alias(registerrpc,_registerrpc)
|
||||
__weak_alias(clnt_broadcast,_clnt_broadcast)
|
||||
#endif
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t rpcsoc_lock;
|
||||
#endif
|
||||
|
||||
static CLIENT *clnt_com_create __P((struct sockaddr_in *, rpcprog_t, rpcvers_t,
|
||||
int *, u_int, u_int, const char *));
|
||||
static SVCXPRT *svc_com_create __P((int, u_int, u_int, const char *));
|
||||
static bool_t rpc_wrap_bcast __P((char *, struct netbuf *, struct netconfig *));
|
||||
|
||||
/*
|
||||
* A common clnt create routine
|
||||
*/
|
||||
static CLIENT *
|
||||
clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
|
||||
struct sockaddr_in *raddr;
|
||||
rpcprog_t prog;
|
||||
rpcvers_t vers;
|
||||
int *sockp;
|
||||
u_int sendsz;
|
||||
u_int recvsz;
|
||||
const char *tp;
|
||||
{
|
||||
CLIENT *cl;
|
||||
int madefd = FALSE;
|
||||
int fd;
|
||||
struct netconfig *nconf;
|
||||
struct netbuf bindaddr;
|
||||
|
||||
_DIAGASSERT(raddr != NULL);
|
||||
_DIAGASSERT(sockp != NULL);
|
||||
_DIAGASSERT(tp != NULL);
|
||||
|
||||
fd = *sockp;
|
||||
|
||||
mutex_lock(&rpcsoc_lock);
|
||||
if ((nconf = __rpc_getconfip(tp)) == NULL) {
|
||||
rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
|
||||
mutex_unlock(&rpcsoc_lock);
|
||||
return (NULL);
|
||||
}
|
||||
if (fd == RPC_ANYSOCK) {
|
||||
fd = __rpc_nconf2fd(nconf);
|
||||
if (fd == -1)
|
||||
goto syserror;
|
||||
madefd = TRUE;
|
||||
}
|
||||
|
||||
if (raddr->sin_port == 0) {
|
||||
u_int proto;
|
||||
u_short sport;
|
||||
|
||||
mutex_unlock(&rpcsoc_lock); /* pmap_getport is recursive */
|
||||
proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
|
||||
sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
|
||||
proto);
|
||||
if (sport == 0) {
|
||||
goto err;
|
||||
}
|
||||
raddr->sin_port = htons(sport);
|
||||
mutex_lock(&rpcsoc_lock); /* pmap_getport is recursive */
|
||||
}
|
||||
|
||||
/* Transform sockaddr_in to netbuf */
|
||||
bindaddr.maxlen = bindaddr.len = sizeof (struct sockaddr_in);
|
||||
bindaddr.buf = raddr;
|
||||
|
||||
bindresvport(fd, NULL);
|
||||
cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
|
||||
sendsz, recvsz);
|
||||
if (cl) {
|
||||
if (madefd == TRUE) {
|
||||
/*
|
||||
* The fd should be closed while destroying the handle.
|
||||
*/
|
||||
(void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
|
||||
*sockp = fd;
|
||||
}
|
||||
(void) freenetconfigent(nconf);
|
||||
mutex_unlock(&rpcsoc_lock);
|
||||
return (cl);
|
||||
}
|
||||
goto err;
|
||||
|
||||
syserror:
|
||||
rpc_createerr.cf_stat = RPC_SYSTEMERROR;
|
||||
rpc_createerr.cf_error.re_errno = errno;
|
||||
|
||||
err: if (madefd == TRUE)
|
||||
(void) close(fd);
|
||||
(void) freenetconfigent(nconf);
|
||||
mutex_unlock(&rpcsoc_lock);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
CLIENT *
|
||||
clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
|
||||
struct sockaddr_in *raddr;
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
struct timeval wait;
|
||||
int *sockp;
|
||||
u_int sendsz;
|
||||
u_int recvsz;
|
||||
{
|
||||
CLIENT *cl;
|
||||
|
||||
_DIAGASSERT(raddr != NULL);
|
||||
_DIAGASSERT(sockp != NULL);
|
||||
|
||||
cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
|
||||
sendsz, recvsz, "udp");
|
||||
if (cl == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
(void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, (char *)(void *)&wait);
|
||||
return (cl);
|
||||
}
|
||||
|
||||
CLIENT *
|
||||
clntudp_create(raddr, program, version, wait, sockp)
|
||||
struct sockaddr_in *raddr;
|
||||
u_long program;
|
||||
u_long version;
|
||||
struct timeval wait;
|
||||
int *sockp;
|
||||
{
|
||||
return clntudp_bufcreate(raddr, program, version, wait, sockp,
|
||||
UDPMSGSIZE, UDPMSGSIZE);
|
||||
}
|
||||
|
||||
CLIENT *
|
||||
clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
|
||||
struct sockaddr_in *raddr;
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
int *sockp;
|
||||
u_int sendsz;
|
||||
u_int recvsz;
|
||||
{
|
||||
return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
|
||||
sendsz, recvsz, "tcp");
|
||||
}
|
||||
|
||||
CLIENT *
|
||||
clntraw_create(prog, vers)
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
{
|
||||
return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
|
||||
}
|
||||
|
||||
/*
|
||||
* A common server create routine
|
||||
*/
|
||||
static SVCXPRT *
|
||||
svc_com_create(fd, sendsize, recvsize, netid)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
const char *netid;
|
||||
{
|
||||
struct netconfig *nconf;
|
||||
SVCXPRT *svc;
|
||||
int madefd = FALSE;
|
||||
int port;
|
||||
struct sockaddr_in sccsin;
|
||||
|
||||
_DIAGASSERT(netid != NULL);
|
||||
|
||||
if ((nconf = __rpc_getconfip(netid)) == NULL) {
|
||||
(void) syslog(LOG_ERR, "Could not get %s transport", netid);
|
||||
return (NULL);
|
||||
}
|
||||
if (fd == RPC_ANYSOCK) {
|
||||
fd = __rpc_nconf2fd(nconf);
|
||||
if (fd == -1) {
|
||||
(void) freenetconfigent(nconf);
|
||||
(void) syslog(LOG_ERR,
|
||||
"svc%s_create: could not open connection", netid);
|
||||
return (NULL);
|
||||
}
|
||||
madefd = TRUE;
|
||||
}
|
||||
|
||||
memset(&sccsin, 0, sizeof sccsin);
|
||||
sccsin.sin_family = AF_INET;
|
||||
bindresvport(fd, &sccsin);
|
||||
listen(fd, SOMAXCONN);
|
||||
svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
|
||||
(void) freenetconfigent(nconf);
|
||||
if (svc == NULL) {
|
||||
if (madefd)
|
||||
(void) close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
|
||||
svc->xp_port = ntohs(port);
|
||||
return (svc);
|
||||
}
|
||||
|
||||
SVCXPRT *
|
||||
svctcp_create(fd, sendsize, recvsize)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
{
|
||||
return svc_com_create(fd, sendsize, recvsize, "tcp");
|
||||
}
|
||||
|
||||
SVCXPRT *
|
||||
svcudp_bufcreate(fd, sendsz, recvsz)
|
||||
int fd;
|
||||
u_int sendsz, recvsz;
|
||||
{
|
||||
return svc_com_create(fd, sendsz, recvsz, "udp");
|
||||
}
|
||||
|
||||
SVCXPRT *
|
||||
svcfd_create(fd, sendsize, recvsize)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
{
|
||||
return svc_fd_create(fd, sendsize, recvsize);
|
||||
}
|
||||
|
||||
|
||||
SVCXPRT *
|
||||
svcudp_create(fd)
|
||||
int fd;
|
||||
{
|
||||
return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
|
||||
}
|
||||
|
||||
SVCXPRT *
|
||||
svcraw_create()
|
||||
{
|
||||
return svc_raw_create();
|
||||
}
|
||||
|
||||
int
|
||||
get_myaddress(addr)
|
||||
struct sockaddr_in *addr;
|
||||
{
|
||||
|
||||
_DIAGASSERT(addr != NULL);
|
||||
|
||||
memset((void *) addr, 0, sizeof(*addr));
|
||||
addr->sin_family = AF_INET;
|
||||
addr->sin_port = htons(PMAPPORT);
|
||||
addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* For connectionless "udp" transport. Obsoleted by rpc_call().
|
||||
*/
|
||||
int
|
||||
callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
|
||||
char *host;
|
||||
int prognum, versnum, procnum;
|
||||
xdrproc_t inproc, outproc;
|
||||
char *in, *out;
|
||||
{
|
||||
return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
|
||||
(rpcproc_t)procnum, inproc, in, outproc, out, "udp");
|
||||
}
|
||||
|
||||
/*
|
||||
* For connectionless kind of transport. Obsoleted by rpc_reg()
|
||||
*/
|
||||
int
|
||||
registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
|
||||
int prognum, versnum, procnum;
|
||||
char *(*progname) __P((char [UDPMSGSIZE]));
|
||||
xdrproc_t inproc, outproc;
|
||||
{
|
||||
return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
|
||||
(rpcproc_t)procnum, progname, inproc, outproc, __UNCONST("udp"));
|
||||
}
|
||||
|
||||
/*
|
||||
* All the following clnt_broadcast stuff is convulated; it supports
|
||||
* the earlier calling style of the callback function
|
||||
*/
|
||||
#ifdef _REENTRANT
|
||||
static thread_key_t clnt_broadcast_key;
|
||||
#endif
|
||||
static resultproc_t clnt_broadcast_result_main;
|
||||
|
||||
/*
|
||||
* Need to translate the netbuf address into sockaddr_in address.
|
||||
* Dont care about netid here.
|
||||
*/
|
||||
/* ARGSUSED */
|
||||
static bool_t
|
||||
rpc_wrap_bcast(resultp, addr, nconf)
|
||||
char *resultp; /* results of the call */
|
||||
struct netbuf *addr; /* address of the guy who responded */
|
||||
struct netconfig *nconf; /* Netconf of the transport */
|
||||
{
|
||||
resultproc_t clnt_broadcast_result;
|
||||
|
||||
_DIAGASSERT(resultp != NULL);
|
||||
_DIAGASSERT(addr != NULL);
|
||||
_DIAGASSERT(nconf != NULL);
|
||||
|
||||
if (strcmp(nconf->nc_netid, "udp"))
|
||||
return (FALSE);
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0)
|
||||
clnt_broadcast_result = clnt_broadcast_result_main;
|
||||
else
|
||||
clnt_broadcast_result = thr_getspecific(clnt_broadcast_key);
|
||||
#else
|
||||
clnt_broadcast_result = clnt_broadcast_result_main;
|
||||
#endif
|
||||
return (*clnt_broadcast_result)(resultp,
|
||||
(struct sockaddr_in *)addr->buf);
|
||||
}
|
||||
|
||||
#ifdef _REENTRANT
|
||||
static once_t clnt_broadcast_once = ONCE_INITIALIZER;
|
||||
|
||||
static void
|
||||
clnt_broadcast_setup(void)
|
||||
{
|
||||
|
||||
thr_keycreate(&clnt_broadcast_key, free);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
|
||||
*/
|
||||
enum clnt_stat
|
||||
clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
|
||||
u_long prog; /* program number */
|
||||
u_long vers; /* version number */
|
||||
u_long proc; /* procedure number */
|
||||
xdrproc_t xargs; /* xdr routine for args */
|
||||
caddr_t argsp; /* pointer to args */
|
||||
xdrproc_t xresults; /* xdr routine for results */
|
||||
caddr_t resultsp; /* pointer to results */
|
||||
resultproc_t eachresult; /* call with each result obtained */
|
||||
{
|
||||
#ifdef _REENTRANT
|
||||
if (__isthreaded == 0)
|
||||
clnt_broadcast_result_main = eachresult;
|
||||
else {
|
||||
thr_once(&clnt_broadcast_once, clnt_broadcast_setup);
|
||||
thr_setspecific(clnt_broadcast_key, (void *) eachresult);
|
||||
}
|
||||
#else
|
||||
clnt_broadcast_result_main = eachresult;
|
||||
#endif
|
||||
return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
|
||||
(rpcproc_t)proc, xargs, argsp, xresults, resultsp,
|
||||
(resultproc_t) rpc_wrap_bcast, "udp");
|
||||
}
|
||||
|
||||
#endif /* PORTMAP */
|
||||
@@ -0,0 +1,261 @@
|
||||
.\" @(#)rpc_svc_calls.3n 1.28 93/05/10 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_svc_calls 1.5 89/07/25 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_svc_calls.3,v 1.12 2010/03/22 19:30:54 joerg Exp $
|
||||
.Dd May 3, 1993
|
||||
.Dt RPC_SVC_CALLS 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm svc_dg_enablecache ,
|
||||
.Nm svc_exit ,
|
||||
.Nm svc_fdset ,
|
||||
.Nm svc_freeargs ,
|
||||
.Nm svc_getargs ,
|
||||
.Nm svc_getreq_common ,
|
||||
.Nm svc_getreq_poll ,
|
||||
.Nm svc_getreqset ,
|
||||
.Nm svc_getrpccaller ,
|
||||
.Nm svc_pollset ,
|
||||
.Nm svc_run ,
|
||||
.Nm svc_sendreply
|
||||
.Nd library routines for RPC servers
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft int
|
||||
.Fn svc_dg_enablecache "SVCXPRT *xprt" "const unsigned cache_size"
|
||||
.Ft void
|
||||
.Fn svc_exit "void"
|
||||
.Ft bool_t
|
||||
.Fn svc_freeargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in"
|
||||
.Ft bool_t
|
||||
.Fn svc_getargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in"
|
||||
.Ft void
|
||||
.Fn svc_getreq_common "const int fd"
|
||||
.Ft void
|
||||
.Fn svc_getreq_poll "struct pollfd *pfdp" "const int pollretval"
|
||||
.Ft void
|
||||
.Fn svc_getreqset "fd_set * rdfds"
|
||||
.Ft "struct netbuf *"
|
||||
.Fn svc_getrpccaller "const SVCXPRT *xprt"
|
||||
.Ft "struct sockcred *"
|
||||
.Fn __svc_getcallercreds "const SVCXPRT *xprt"
|
||||
.Vt struct pollfd svc_pollset[FD_SETSIZE];
|
||||
.Ft void
|
||||
.Fn svc_run "void"
|
||||
.Ft bool_t
|
||||
.Fn svc_sendreply "const SVCXPRT *xprt" "const xdrproc_t outproc" "const caddr_t *out"
|
||||
.Sh DESCRIPTION
|
||||
These routines are part of the
|
||||
RPC
|
||||
library which allows C language programs to make procedure
|
||||
calls on other machines across the network.
|
||||
.Pp
|
||||
These routines are associated with the server side of the
|
||||
RPC mechanism.
|
||||
Some of them are called by the server side dispatch function,
|
||||
while others
|
||||
(such as
|
||||
.Fn svc_run )
|
||||
are called when the server is initiated.
|
||||
.\" .Pp
|
||||
.\" In the current implementation, the service transport handle,
|
||||
.\" .Dv SVCXPRT ,
|
||||
.\" contains a single data area for decoding arguments and encoding results.
|
||||
.\" Therefore, this structure cannot be freely shared between threads that call
|
||||
.\" functions that do this. Routines on this page that are affected by this
|
||||
.\" restriction are marked as unsafe for MT applications.
|
||||
.Sh ROUTINES
|
||||
See
|
||||
.Xr rpc 3
|
||||
for the definition of the
|
||||
.Dv SVCXPRT
|
||||
data structure.
|
||||
.Pp
|
||||
.Bl -tag -width __svc_getcallercreds()
|
||||
.It Fn svc_dg_enablecache
|
||||
This function allocates a duplicate request cache for the
|
||||
service endpoint
|
||||
.Fa xprt ,
|
||||
large enough to hold
|
||||
.Fa cache_size
|
||||
entries.
|
||||
Once enabled, there is no way to disable caching.
|
||||
This routine returns 0 if space necessary for a cache of the given size
|
||||
was successfully allocated, and 1 otherwise.
|
||||
.It Fn svc_exit
|
||||
This function when called by any of the RPC server procedure or
|
||||
otherwise, causes
|
||||
.Fn svc_run
|
||||
to return.
|
||||
.Pp
|
||||
As currently implemented,
|
||||
.Fn svc_exit
|
||||
zeroes the
|
||||
.Dv svc_fdset
|
||||
global variable.
|
||||
If RPC server activity is to be resumed,
|
||||
services must be reregistered with the RPC library
|
||||
either through one of the
|
||||
.Fn rpc_svc_create
|
||||
functions, or using
|
||||
.Fn xprt_register .
|
||||
.Fn svc_exit
|
||||
has global scope and ends all RPC server activity.
|
||||
.Ft "fd_set svc_fdset"
|
||||
A global variable reflecting the
|
||||
RPC server's read file descriptor bit mask; it is suitable as a parameter
|
||||
to the
|
||||
.Xr select 2
|
||||
system call.
|
||||
This is only of interest
|
||||
if service implementors do not call
|
||||
.Fn svc_run ,
|
||||
but rather do their own asynchronous event processing.
|
||||
This variable is read-only (do not pass its address to
|
||||
.Xr select 2 ! ) ,
|
||||
yet it may change after calls to
|
||||
.Fn svc_getreqset
|
||||
or any creation routines.
|
||||
.Pp
|
||||
.It Fn svc_freeargs
|
||||
A function macro that frees any data allocated by the
|
||||
RPC/XDR system when it decoded the arguments to a service procedure
|
||||
using
|
||||
.Fn svc_getargs .
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if the results were successfully
|
||||
freed, and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.Pp
|
||||
.It Fn svc_getargs
|
||||
A function macro that decodes the arguments of an
|
||||
RPC request associated with the RPC
|
||||
service transport handle
|
||||
.Fa xprt .
|
||||
The parameter
|
||||
.Fa in
|
||||
is the address where the arguments will be placed;
|
||||
.Fa inproc
|
||||
is the XDR
|
||||
routine used to decode the arguments.
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if decoding succeeds, and
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.It Fn svc_getreq_common
|
||||
This routine is called to handle a request on the given
|
||||
file descriptor.
|
||||
.Pp
|
||||
.It Fn svc_getreq_poll
|
||||
This routine is only of interest if a service implementor
|
||||
does not call
|
||||
.Fn svc_run ,
|
||||
but instead implements custom asynchronous event processing.
|
||||
It is called when
|
||||
.Xr poll 2
|
||||
has determined that an RPC request has arrived on some RPC
|
||||
file descriptors;
|
||||
.Fn pollretval
|
||||
is the return value from
|
||||
.Xr poll 2
|
||||
and
|
||||
.Fa pfdp
|
||||
is the array of
|
||||
.Fa pollfd
|
||||
structures on which the
|
||||
.Xr poll 2
|
||||
was done.
|
||||
It is assumed to be an array large enough to
|
||||
contain the maximal number of descriptors allowed.
|
||||
.Pp
|
||||
.It Fn svc_getreqset
|
||||
This routine is only of interest if a service implementor
|
||||
does not call
|
||||
.Fn svc_run ,
|
||||
but instead implements custom asynchronous event processing.
|
||||
It is called when
|
||||
.Xr poll 2
|
||||
has determined that an RPC
|
||||
request has arrived on some RPC file descriptors;
|
||||
.Fa rdfds
|
||||
is the resultant read file descriptor bit mask.
|
||||
The routine returns when all file descriptors
|
||||
associated with the value of
|
||||
.Fa rdfds
|
||||
have been serviced.
|
||||
.Pp
|
||||
.It Fn svc_getrpccaller
|
||||
The approved way of getting the network address of the caller
|
||||
of a procedure associated with the
|
||||
RPC service transport handle
|
||||
.Fa xprt .
|
||||
.Pp
|
||||
.It Fn __svc_getcallercreds
|
||||
.Em Warning: this macro is specific to
|
||||
.Nx
|
||||
.Em and thus not portable.
|
||||
This macro returns a pointer to a sockcred structure, defined in
|
||||
.In sys/socket.h ,
|
||||
identifying the calling client.
|
||||
This only works if the client is calling the server over an
|
||||
.Dv AF_LOCAL
|
||||
socket.
|
||||
.It Fa struct pollfd svc_pollset[FD_SETSIZE];
|
||||
.Va svc_pollset
|
||||
is an array of
|
||||
.Vt pollfd
|
||||
structures derived from
|
||||
.Va svc_fdset[] .
|
||||
It is suitable as a parameter to the
|
||||
.Xr poll 2
|
||||
system call.
|
||||
The derivation of
|
||||
.Va svc_pollset
|
||||
from
|
||||
.Va svc_fdset
|
||||
is made in the current implementation in
|
||||
.Fn svc_run .
|
||||
Service implementors who do not call
|
||||
.Fn svc_run
|
||||
and who wish to use this array must perform this derivation themselves.
|
||||
.Pp
|
||||
.It Fn svc_run
|
||||
This routine never returns.
|
||||
It waits for RPC
|
||||
requests to arrive, and calls the appropriate service
|
||||
procedure using
|
||||
.Fn svc_getreq_poll
|
||||
when one arrives.
|
||||
This procedure is usually waiting for the
|
||||
.Xr poll 2
|
||||
system call to return.
|
||||
.Pp
|
||||
.It Fn svc_sendreply
|
||||
Called by an RPC service's dispatch routine to send the results of a
|
||||
remote procedure call.
|
||||
The parameter
|
||||
.Fa xprt
|
||||
is the request's associated transport handle;
|
||||
.Fa outproc
|
||||
is the XDR
|
||||
routine which is used to encode the results; and
|
||||
.Fa out
|
||||
is the address of the results.
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if it succeeds,
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr poll 2 ,
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_svc_create 3 ,
|
||||
.Xr rpc_svc_err 3 ,
|
||||
.Xr rpc_svc_reg 3
|
||||
@@ -0,0 +1,315 @@
|
||||
.\" @(#)rpc_svc_create.3n 1.26 93/08/26 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_svc_create 1.3 89/06/28 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_svc_create.3,v 1.11 2010/03/22 19:30:54 joerg Exp $
|
||||
.Dd May 3, 1993
|
||||
.Dt RPC_SVC_CREATE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpc_svc_create ,
|
||||
.Nm svc_control ,
|
||||
.Nm svc_create ,
|
||||
.Nm svc_destroy ,
|
||||
.Nm svc_dg_create ,
|
||||
.Nm svc_fd_create ,
|
||||
.Nm svc_raw_create ,
|
||||
.Nm svc_tli_create ,
|
||||
.Nm svc_tp_create ,
|
||||
.Nm svc_vc_create
|
||||
.Nd library routines for the creation of server handles
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft bool_t
|
||||
.Fn svc_control "SVCXPRT *svc" "const u_int req" "void *info"
|
||||
.Ft int
|
||||
.Fn svc_create "const void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
|
||||
.Ft SVCXPRT *"
|
||||
.Fn svc_dg_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
|
||||
.Ft void
|
||||
.Fn svc_destroy "SVCXPRT *xprt"
|
||||
.Ft "SVCXPRT *"
|
||||
.Fn svc_fd_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
|
||||
.Ft "SVCXPRT *"
|
||||
.Fn svc_raw_create "void"
|
||||
.Ft "SVCXPRT *"
|
||||
.Fn svc_tli_create "const int fildes" "const struct netconfig *netconf" "const struct t_bind *bindaddr" "const u_int sendsz" "const u_int recvsz"
|
||||
.Ft "SVCXPRT *"
|
||||
.Fn svc_tp_create "const void (*dispatch)(const struct svc_reg *, const SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
|
||||
.Ft "SVCXPRT *"
|
||||
.Fn svc_vc_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
|
||||
.Sh DESCRIPTION
|
||||
These routines are part of the RPC
|
||||
library which allows C language programs to make procedure
|
||||
calls on servers across the network.
|
||||
These routines deal with the creation of service handles.
|
||||
Once the handle is created, the server can be invoked by calling
|
||||
.Fn svc_run .
|
||||
.Sh ROUTINES
|
||||
See
|
||||
.Xr rpc 3
|
||||
for the definition of the
|
||||
.Dv SVCXPRT
|
||||
data structure.
|
||||
.Pp
|
||||
.Bl -tag -width XXXXX
|
||||
.It Fn svc_control
|
||||
A function to change or retrieve various information
|
||||
about a service object.
|
||||
.Fa req
|
||||
indicates the type of operation and
|
||||
.Fa info
|
||||
is a pointer to the information.
|
||||
The supported values of
|
||||
.Fa req ,
|
||||
their argument types, and what they do are:
|
||||
.Bl -tag -width SVCGET_XID
|
||||
.It Dv SVCGET_VERSQUIET
|
||||
If a request is received for a program number
|
||||
served by this server but the version number
|
||||
is outside the range registered with the server,
|
||||
an
|
||||
.Dv RPC_PROGVERSMISMATCH
|
||||
error will normally
|
||||
be returned.
|
||||
.Fa info
|
||||
should be a pointer to an integer.
|
||||
Upon successful completion of the
|
||||
.Dv SVCGET_VERSQUIET
|
||||
request,
|
||||
.Fa *info
|
||||
contains an
|
||||
integer which describes the server's current
|
||||
behavior: 0 indicates normal server behavior
|
||||
(that is, an
|
||||
.Dv RPC_PROGVERSMISMATCH
|
||||
error
|
||||
will be returned); 1 indicates that the out of
|
||||
range request will be silently ignored.
|
||||
.Pp
|
||||
.It Dv SVCSET_VERSQUIET
|
||||
If a request is received for a program number
|
||||
served by this server but the version number
|
||||
is outside the range registered with the server,
|
||||
an
|
||||
.Dv RPC_PROGVERSMISMATCH
|
||||
error will normally be returned.
|
||||
It is sometimes desirable to change this behavior.
|
||||
.Fa info
|
||||
should be a
|
||||
pointer to an integer which is either 0
|
||||
(indicating normal server behavior - an
|
||||
.Dv RPC_PROGVERSMISMATCH
|
||||
error will be returned),
|
||||
or 1 (indicating that the out of range request
|
||||
should be silently ignored).
|
||||
.El
|
||||
.Pp
|
||||
.It Fn svc_create
|
||||
.Fn svc_create
|
||||
creates server handles for all the transports
|
||||
belonging to the class
|
||||
.Fa nettype .
|
||||
.Fa nettype
|
||||
defines a class of transports which can be used
|
||||
for a particular application.
|
||||
The transports are tried in left to right order in
|
||||
.Ev NETPATH
|
||||
variable or in top to bottom order in the netconfig database.
|
||||
If
|
||||
.Fa nettype
|
||||
is
|
||||
.Dv NULL ,
|
||||
it defaults to
|
||||
.Dv netpath .
|
||||
.Pp
|
||||
.Fn svc_create
|
||||
registers itself with the rpcbind
|
||||
service (see
|
||||
.Xr rpcbind 8 ) .
|
||||
.Fa dispatch
|
||||
is called when there is a remote procedure call for the given
|
||||
.Fa prognum
|
||||
and
|
||||
.Fa versnum ;
|
||||
this requires calling
|
||||
.Fn svc_run
|
||||
(see
|
||||
.Fn svc_run
|
||||
in
|
||||
.Xr rpc_svc_reg 3 ) .
|
||||
If
|
||||
.Fn svc_create
|
||||
succeeds, it returns the number of server
|
||||
handles it created,
|
||||
otherwise it returns 0 and an error message is logged.
|
||||
.Pp
|
||||
.It Fn svc_destroy
|
||||
A function macro that destroys the RPC
|
||||
service handle
|
||||
.Fa xprt .
|
||||
Destruction usually involves deallocation
|
||||
of private data structures,
|
||||
including
|
||||
.Fa xprt
|
||||
itself.
|
||||
Use of
|
||||
.Fa xprt
|
||||
is undefined after calling this routine.
|
||||
.Pp
|
||||
.It Fn svc_dg_create
|
||||
This routine creates a connectionless RPC
|
||||
service handle, and returns a pointer to it.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails, and an error message is logged.
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz
|
||||
are parameters used to specify the size of the buffers.
|
||||
If they are 0, suitable defaults are chosen.
|
||||
The file descriptor
|
||||
.Fa fildes
|
||||
should be open and bound.
|
||||
The server is not registered with
|
||||
.Xr rpcbind 8 .
|
||||
.Em Warning :
|
||||
since connectionless-based RPC
|
||||
messages can only hold limited amount of encoded data,
|
||||
this transport cannot be used for procedures
|
||||
that take large arguments or return huge results.
|
||||
.Pp
|
||||
.It Fn svc_fd_create
|
||||
This routine creates a service on top of an open and bound file descriptor,
|
||||
and returns the handle to it.
|
||||
Typically, this descriptor is a connected file descriptor for a
|
||||
connection-oriented transport.
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz
|
||||
indicate sizes for the send and receive buffers.
|
||||
If they are 0, reasonable defaults are chosen.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails, and an error message is logged.
|
||||
.Pp
|
||||
.It Fn svc_raw_create
|
||||
This routine creates an RPC
|
||||
service handle and returns a pointer to it.
|
||||
The transport is really a buffer within the process's
|
||||
address space, so the corresponding RPC
|
||||
client should live in the same address space;
|
||||
(see
|
||||
.Fn clnt_raw_create
|
||||
in
|
||||
.Xr rpc_clnt_create 3 ) .
|
||||
This routine allows simulation of RPC and acquisition of
|
||||
RPC overheads (such as round trip times),
|
||||
without any kernel and networking interference.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails, and an error message is logged.
|
||||
.Em Note :
|
||||
.Fn svc_run
|
||||
should not be called when the raw interface is being used.
|
||||
.Pp
|
||||
.It Fn svc_tli_create
|
||||
This routine creates an RPC
|
||||
server handle, and returns a pointer to it.
|
||||
.Fa fildes
|
||||
is the file descriptor on which the service is listening.
|
||||
If
|
||||
.Fa fildes
|
||||
is
|
||||
.Dv RPC_ANYFD ,
|
||||
it opens a file descriptor on the transport specified by
|
||||
.Fa netconf .
|
||||
If the file descriptor is unbound and
|
||||
.Fa bindaddr
|
||||
is non-null
|
||||
.Fa fildes
|
||||
is bound to the address specified by
|
||||
.Fa bindaddr ,
|
||||
otherwise
|
||||
.Fa fildes
|
||||
is bound to a default address chosen by the transport.
|
||||
.Pp
|
||||
Note: the
|
||||
.Vt t_bind
|
||||
structure comes from the TLI/XTI SysV interface, which
|
||||
.Nx
|
||||
does not use.
|
||||
The structure is defined in
|
||||
.In rpc/types.h
|
||||
for compatibility as:
|
||||
.Bd -literal
|
||||
struct t_bind {
|
||||
struct netbuf addr; /* network address, see rpc(3) */
|
||||
unsigned int qlen; /* queue length (for listen(2)) */
|
||||
};
|
||||
.Ed
|
||||
.Pp
|
||||
In the case where the default address is chosen,
|
||||
the number of outstanding connect requests is set to 8
|
||||
for connection-oriented transports.
|
||||
The user may specify the size of the send and receive buffers
|
||||
with the parameters
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz ;
|
||||
values of 0 choose suitable defaults.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails,
|
||||
and an error message is logged.
|
||||
The server is not registered with the
|
||||
.Xr rpcbind 8
|
||||
service.
|
||||
.Pp
|
||||
.It Fn svc_tp_create
|
||||
.Fn svc_tp_create
|
||||
creates a server handle for the network
|
||||
specified by
|
||||
.Fa netconf ,
|
||||
and registers itself with the rpcbind service.
|
||||
.Fa dispatch
|
||||
is called when there is a remote procedure call
|
||||
for the given
|
||||
.Fa prognum
|
||||
and
|
||||
.Fa versnum ;
|
||||
this requires calling
|
||||
.Fn svc_run .
|
||||
.Fn svc_tp_create
|
||||
returns the service handle if it succeeds,
|
||||
otherwise a
|
||||
.Dv NULL
|
||||
is returned and an error message is logged.
|
||||
.Pp
|
||||
.It Fn svc_vc_create
|
||||
This routine creates a connection-oriented RPC
|
||||
service and returns a pointer to it.
|
||||
This routine returns
|
||||
.Dv NULL
|
||||
if it fails, and an error message is logged.
|
||||
The users may specify the size of the send and receive buffers
|
||||
with the parameters
|
||||
.Fa sendsz
|
||||
and
|
||||
.Fa recvsz ;
|
||||
values of 0 choose suitable defaults.
|
||||
The file descriptor
|
||||
.Fa fildes
|
||||
should be open and bound.
|
||||
The server is not registered with the
|
||||
.Xr rpcbind 8
|
||||
service.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_svc_calls 3 ,
|
||||
.Xr rpc_svc_err 3 ,
|
||||
.Xr rpc_svc_reg 3 ,
|
||||
.Xr rpcbind 8
|
||||
@@ -0,0 +1,101 @@
|
||||
.\" @(#)rpc_svc_err.3n 1.23 93/08/31 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_svc_err 1.4 89/06/28 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_svc_err.3,v 1.6 2003/04/16 13:34:43 wiz Exp $
|
||||
.Dd May 3, 1993
|
||||
.Dt RPC_SVC_ERR 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpc_svc_err ,
|
||||
.Nm svcerr_auth ,
|
||||
.Nm svcerr_decode ,
|
||||
.Nm svcerr_noproc ,
|
||||
.Nm svcerr_noprog ,
|
||||
.Nm svcerr_progvers ,
|
||||
.Nm svcerr_systemerr ,
|
||||
.Nm svcerr_weakauth
|
||||
.Nd library routines for server side remote procedure call errors
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft void
|
||||
.Fn svcerr_auth "const SVCXPRT1 *xprt" "const enum auth_stat why"
|
||||
.Ft void
|
||||
.Fn svcerr_decode "const SVCXPRT *xprt"
|
||||
.Ft void
|
||||
.Fn svcerr_noproc "const SVCXPRT *xprt"
|
||||
.Ft void
|
||||
.Fn svcerr_noprog "const SVCXPRT *xprt"
|
||||
.Ft void
|
||||
.Fn svcerr_progvers "const SVCXPRT *xprt" "rpcvers_t low_vers" "rpcvers_t high_vers"
|
||||
.Ft void
|
||||
.Fn svcerr_systemerr "const SVCXPRT *xprt"
|
||||
.Ft void
|
||||
.Fn svcerr_weakauth "const SVCXPRT *xprt"
|
||||
.Sh DESCRIPTION
|
||||
These routines are part of the RPC
|
||||
library which allows C language programs to make procedure
|
||||
calls on other machines across the network.
|
||||
.Pp
|
||||
These routines can be called by the server side
|
||||
dispatch function if there is any error in the
|
||||
transaction with the client.
|
||||
.Sh ROUTINES
|
||||
See
|
||||
.Xr rpc 3
|
||||
for the definition of the
|
||||
.Vt SVCXPRT
|
||||
data structure.
|
||||
.Pp
|
||||
.Bl -tag -width XXXXX
|
||||
.It Fn svcerr_auth
|
||||
Called by a service dispatch routine that refuses to perform
|
||||
a remote procedure call due to an authentication error.
|
||||
.Pp
|
||||
.Fn svcerr_decode
|
||||
Called by a service dispatch routine that cannot successfully
|
||||
decode the remote parameters
|
||||
(see
|
||||
.Fn svc_getargs
|
||||
in
|
||||
.Xr rpc_svc_reg 3 ) .
|
||||
.Pp
|
||||
.It Fn svcerr_noproc
|
||||
Called by a service dispatch routine that does not implement
|
||||
the procedure number that the caller requests.
|
||||
.Pp
|
||||
.It Fn svcerr_noprog
|
||||
Called when the desired program is not registered with the
|
||||
RPC package.
|
||||
Service implementors usually do not need this routine.
|
||||
.Pp
|
||||
.It Fn svcerr_progvers
|
||||
Called when the desired version of a program is not registered with the
|
||||
RPC package.
|
||||
.Fa low_vers
|
||||
is the lowest version number,
|
||||
and
|
||||
.Fa high_vers
|
||||
is the highest version number.
|
||||
Service implementors usually do not need this routine.
|
||||
.Pp
|
||||
.It Fn svcerr_systemerr
|
||||
Called by a service dispatch routine when it detects a system
|
||||
error not covered by any particular protocol.
|
||||
For example, if a service can no longer allocate storage,
|
||||
it may call this routine.
|
||||
.Pp
|
||||
.It Fn svcerr_weakauth
|
||||
Called by a service dispatch routine that refuses to perform
|
||||
a remote procedure call due to insufficient (but correct)
|
||||
authentication parameters.
|
||||
The routine calls
|
||||
.Fn svcerr_auth "xprt" "AUTH_TOOWEAK" .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_svc_calls 3 ,
|
||||
.Xr rpc_svc_create 3 ,
|
||||
.Xr rpc_svc_reg 3
|
||||
@@ -0,0 +1,196 @@
|
||||
.\" @(#)rpc_svc_reg.3n 1.32 93/08/31 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_svc_call 1.6 89/07/20 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_svc_reg.3,v 1.9 2009/03/11 13:36:01 joerg Exp $
|
||||
.Dd May 3, 1993
|
||||
.Dt RPC_SVC_REG 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpc_svc_reg ,
|
||||
.Nm rpc_reg ,
|
||||
.Nm svc_reg ,
|
||||
.Nm svc_unreg ,
|
||||
.Nm svc_auth_reg ,
|
||||
.Nm xprt_register ,
|
||||
.Nm xprt_unregister
|
||||
.Nd library routines for registering servers
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft bool_t
|
||||
.Fn rpc_reg "const rpcprog_t prognum" "const rpcvers_t versnum" "const rpcproc_t procnum" "const char *(*procname)()" "const xdrproc_t inproc" "const xdrproc_t outproc" "const char *nettype"
|
||||
.Ft int
|
||||
.Fn svc_reg "const SVCXPRT *xprt" "const rpcprog_t prognum" "const rpcvers_t versnum" "const void (*dispatch(struct svc_req *, SVCXPRT *)" "const struct netconfig *netconf"
|
||||
.Ft void
|
||||
.Fn svc_unreg "const rpcprog_t prognum" "const rpcvers_t versnum"
|
||||
.Ft int
|
||||
.Fn svc_auth_reg "const int cred_flavor" "const enum auth_stat (*handler(struct svc_req *, struct rpc_msg *))"
|
||||
.Ft void
|
||||
.Fn xprt_register "const SVCXPRT *xprt"
|
||||
.Ft void
|
||||
.Fn xprt_unregister "const SVCXPRT *xprt"
|
||||
.Sh DESCRIPTION
|
||||
These routines are a part of the RPC
|
||||
library which allows the RPC
|
||||
servers to register themselves with rpcbind
|
||||
(see
|
||||
.Xr rpcbind 8 ) ,
|
||||
and associate the given program and version
|
||||
number with the dispatch function.
|
||||
When the RPC server receives a RPC request, the library invokes the
|
||||
dispatch routine with the appropriate arguments.
|
||||
.Sh ROUTINES
|
||||
See
|
||||
.Xr rpc 3
|
||||
for the definition of the
|
||||
.Vt SVCXPRT
|
||||
data structure.
|
||||
.Pp
|
||||
.Bl -tag -width XXXXX
|
||||
.It Fn rpc_reg
|
||||
Register program
|
||||
.Fa prognum ,
|
||||
procedure
|
||||
.Fa procname ,
|
||||
and version
|
||||
.Fa versnum
|
||||
with the RPC
|
||||
service package.
|
||||
If a request arrives for program
|
||||
.Fa prognum ,
|
||||
version
|
||||
.Fa versnum ,
|
||||
and procedure
|
||||
.Fa procnum ,
|
||||
.Fa procname
|
||||
is called with a pointer to its parameter(s);
|
||||
.Fa procname
|
||||
should return a pointer to its static result(s);
|
||||
.Fa inproc
|
||||
is the XDR function used to decode the parameters while
|
||||
.Fa outproc
|
||||
is the XDR function used to encode the results.
|
||||
Procedures are registered on all available transports of the class
|
||||
.Fa nettype .
|
||||
See
|
||||
.Xr rpc 3 .
|
||||
This routine returns 0 if the registration succeeded,
|
||||
-1 otherwise.
|
||||
.Pp
|
||||
.It Fn svc_reg
|
||||
Associates
|
||||
.Fa prognum
|
||||
and
|
||||
.Fa versnum
|
||||
with the service dispatch procedure,
|
||||
.Fa dispatch .
|
||||
If
|
||||
.Fa netconf
|
||||
is
|
||||
.Dv NULL ,
|
||||
the service is not registered with the
|
||||
.Xr rpcbind 8
|
||||
service.
|
||||
If
|
||||
.Fa netconf
|
||||
is non-zero,
|
||||
then a mapping of the triple
|
||||
[
|
||||
.Fa prognum ,
|
||||
.Fa versnum ,
|
||||
.Fa netconf-\*[Gt]nc_netid ]
|
||||
to
|
||||
.Fa xprt-\*[Gt]xp_ltaddr
|
||||
is established with the local rpcbind
|
||||
service.
|
||||
.Pp
|
||||
The
|
||||
.Fn svc_reg
|
||||
routine returns 1 if it succeeds,
|
||||
and 0 otherwise.
|
||||
.Pp
|
||||
.It Fn svc_unreg
|
||||
Remove from the rpcbind
|
||||
service, all mappings of the triple
|
||||
[
|
||||
.Fa prognum ,
|
||||
.Fa versnum ,
|
||||
all-transports ]
|
||||
to network address
|
||||
and all mappings within the RPC service package
|
||||
of the double
|
||||
[
|
||||
.Fa prognum ,
|
||||
.Fa versnum ]
|
||||
to dispatch routines.
|
||||
.Pp
|
||||
.It Fn svc_auth_reg
|
||||
Registers the service authentication routine
|
||||
.Fa handler
|
||||
with the dispatch mechanism so that it can be
|
||||
invoked to authenticate RPC requests received
|
||||
with authentication type
|
||||
.Fa cred_flavor .
|
||||
This interface allows developers to add new authentication
|
||||
types to their RPC applications without needing to modify
|
||||
the libraries.
|
||||
Service implementors usually do not need this routine.
|
||||
.Pp
|
||||
Typical service application would call
|
||||
.Fn svc_auth_reg
|
||||
after registering the service and prior to calling
|
||||
.Fn svc_run .
|
||||
When needed to process an RPC credential of type
|
||||
.Fa cred_flavor ,
|
||||
the
|
||||
.Fa handler
|
||||
procedure will be called with two parameters
|
||||
.Fa "struct svc_req *rqst" ,
|
||||
and
|
||||
.Fa "struct rpc_msg * msg" ,
|
||||
and is expected to return a valid
|
||||
.Vt "enum auth_stat"
|
||||
value.
|
||||
There is no provision to change or delete an authentication handler
|
||||
once registered.
|
||||
.Pp
|
||||
The
|
||||
.Fn svc_auth_reg
|
||||
routine returns 0 if the registration is successful,
|
||||
1 if
|
||||
.Fa cred_flavor
|
||||
already has an authentication handler registered for it,
|
||||
and -1 otherwise.
|
||||
.Pp
|
||||
.It Fn xprt_register
|
||||
After RPC service transport handle
|
||||
.Fa xprt
|
||||
is created, it is registered with the RPC
|
||||
service package.
|
||||
This routine modifies the global variable
|
||||
.Va svc_fdset
|
||||
(see
|
||||
.Xr rpc_svc_calls 3 ) .
|
||||
Service implementors usually do not need this routine.
|
||||
.Pp
|
||||
.It Fn xprt_unregister
|
||||
Before an RPC service transport handle
|
||||
.Fa xprt
|
||||
is destroyed, it unregisters itself with the
|
||||
RPC service package.
|
||||
This routine modifies the global variable
|
||||
.Va svc_fdset
|
||||
(see
|
||||
.Xr rpc_svc_calls 3 ) .
|
||||
Service implementors usually do not need this routine.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr select 2 ,
|
||||
.Xr rpc 3 ,
|
||||
.Xr rpc_svc_calls 3 ,
|
||||
.Xr rpc_svc_create 3 ,
|
||||
.Xr rpc_svc_err 3 ,
|
||||
.Xr rpcbind 3 ,
|
||||
.Xr rpcbind 8
|
||||
@@ -0,0 +1,100 @@
|
||||
.\" @(#)rpc_xdr.3n 1.24 93/08/31 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" @(#)rpc_xdr.new 1.1 89/04/06 SMI;
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpc_xdr.3,v 1.8 2009/04/11 16:03:29 joerg Exp $
|
||||
.Dd May 3, 1993
|
||||
.Dt RPC_XDR 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm xdr_accepted_reply ,
|
||||
.Nm xdr_authsys_parms ,
|
||||
.Nm xdr_callhdr ,
|
||||
.Nm xdr_callmsg ,
|
||||
.Nm xdr_opaque_auth ,
|
||||
.Nm xdr_rejected_reply ,
|
||||
.Nm xdr_replymsg
|
||||
.Nd XDR library routines for remote procedure calls
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft bool_t
|
||||
.Fn xdr_accepted_reply "XDR *xdrs" "const struct accepted_reply *ar"
|
||||
.Ft bool_t
|
||||
.Fn xdr_authsys_parms "XDR *xdrs" "struct authsys_parms *aupp"
|
||||
.Ft void
|
||||
.Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr"
|
||||
.Ft bool_t
|
||||
.Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg"
|
||||
.Ft bool_t
|
||||
.Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap"
|
||||
.Ft bool_t
|
||||
.Fn xdr_rejected_reply "XDR *xdrs" "const struct rejected_reply *rr"
|
||||
.Ft bool_t
|
||||
.Fn xdr_replymsg "XDR *xdrs" "const struct rpc_msg *rmsg"
|
||||
.Sh DESCRIPTION
|
||||
These routines are used for describing the
|
||||
RPC messages in XDR language.
|
||||
They should normally be used by those who do not
|
||||
want to use the RPC
|
||||
package directly.
|
||||
These routines return TRUE if they succeed, FALSE otherwise.
|
||||
.Sh ROUTINES
|
||||
See
|
||||
.Xr rpc 3
|
||||
for the definition of the
|
||||
.Vt XDR
|
||||
data structure.
|
||||
.Pp
|
||||
.Bl -tag -width XXXXX
|
||||
.It Fn xdr_accepted_reply
|
||||
Used to translate between RPC
|
||||
reply messages and their external representation.
|
||||
It includes the status of the RPC
|
||||
call in the XDR language format.
|
||||
In the case of success, it also includes the call results.
|
||||
.Pp
|
||||
.It Fn xdr_authsys_parms
|
||||
Used for describing UNIX operating system credentials.
|
||||
It includes machine-name, uid, gid list, etc.
|
||||
.Pp
|
||||
.It Fn xdr_callhdr
|
||||
Used for describing RPC call header messages.
|
||||
It encodes the static part of the call message header in the
|
||||
XDR language format.
|
||||
It includes information such as transaction
|
||||
ID, RPC version number, program and version number.
|
||||
.Pp
|
||||
.It Fn xdr_callmsg
|
||||
Used for describing
|
||||
RPC call messages.
|
||||
This includes all the RPC
|
||||
call information such as transaction
|
||||
ID, RPC version number, program number, version number,
|
||||
authentication information, etc.
|
||||
This is normally used by servers to determine information about the client
|
||||
RPC call.
|
||||
.Pp
|
||||
.It Fn xdr_opaque_auth
|
||||
Used for describing RPC
|
||||
opaque authentication information messages.
|
||||
.Pp
|
||||
.It Fn xdr_rejected_reply
|
||||
Used for describing RPC reply messages.
|
||||
It encodes the rejected RPC message in the XDR language format.
|
||||
The message could be rejected either because of version
|
||||
number mis-match or because of authentication errors.
|
||||
.Pp
|
||||
.It Fn xdr_replymsg
|
||||
Used for describing RPC
|
||||
reply messages.
|
||||
It translates between the
|
||||
RPC reply message and its external representation.
|
||||
This reply could be either an acceptance,
|
||||
rejection or
|
||||
.Dv NULL .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 3 ,
|
||||
.Xr xdr 3
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,369 @@
|
||||
/* $NetBSD: rpcb_prot.c,v 1.9 2006/05/11 17:11:57 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)rpcb_prot.c 1.13 94/04/24 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: rpcb_prot.c,v 1.9 2006/05/11 17:11:57 mrg Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* rpcb_prot.c
|
||||
* XDR routines for the rpcbinder version 3.
|
||||
*
|
||||
* Copyright (C) 1984, 1988, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/rpcb_prot.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_rpcb,_xdr_rpcb)
|
||||
__weak_alias(xdr_rpcblist_ptr,_xdr_rpcblist_ptr)
|
||||
__weak_alias(xdr_rpcblist,_xdr_rpcblist)
|
||||
__weak_alias(xdr_rpcb_entry,_xdr_rpcb_entry)
|
||||
__weak_alias(xdr_rpcb_entry_list_ptr,_xdr_rpcb_entry_list_ptr)
|
||||
__weak_alias(xdr_rpcb_rmtcallargs,_xdr_rpcb_rmtcallargs)
|
||||
__weak_alias(xdr_rpcb_rmtcallres,_xdr_rpcb_rmtcallres)
|
||||
__weak_alias(xdr_netbuf,_xdr_netbuf)
|
||||
#endif
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_rpcb(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
RPCB *objp;
|
||||
{
|
||||
|
||||
_DIAGASSERT(objp != NULL);
|
||||
|
||||
if (!xdr_u_int32_t(xdrs, &objp->r_prog)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->r_vers)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* rpcblist_ptr implements a linked list. The RPCL definition from
|
||||
* rpcb_prot.x is:
|
||||
*
|
||||
* struct rpcblist {
|
||||
* rpcb rpcb_map;
|
||||
* struct rpcblist *rpcb_next;
|
||||
* };
|
||||
* typedef rpcblist *rpcblist_ptr;
|
||||
*
|
||||
* Recall that "pointers" in XDR are encoded as a boolean, indicating whether
|
||||
* there's any data behind the pointer, followed by the data (if any exists).
|
||||
* The boolean can be interpreted as ``more data follows me''; if FALSE then
|
||||
* nothing follows the boolean; if TRUE then the boolean is followed by an
|
||||
* actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
|
||||
* rpcblist *").
|
||||
*
|
||||
* This could be implemented via the xdr_pointer type, though this would
|
||||
* result in one recursive call per element in the list. Rather than do that
|
||||
* we can ``unwind'' the recursion into a while loop and use xdr_reference to
|
||||
* serialize the rpcb elements.
|
||||
*/
|
||||
|
||||
bool_t
|
||||
xdr_rpcblist_ptr(xdrs, rp)
|
||||
XDR *xdrs;
|
||||
rpcblist_ptr *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;
|
||||
rpcblist_ptr next;
|
||||
rpcblist_ptr next_copy;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
/* XXX: rp may be NULL ??? */
|
||||
|
||||
freeing = (xdrs->x_op == XDR_FREE);
|
||||
next = NULL;
|
||||
|
||||
for (;;) {
|
||||
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 && *rp)
|
||||
next = (*rp)->rpcb_next;
|
||||
if (! xdr_reference(xdrs, (caddr_t *)rp,
|
||||
(u_int)sizeof (rpcblist), (xdrproc_t)xdr_rpcb)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (freeing) {
|
||||
next_copy = next;
|
||||
rp = &next_copy;
|
||||
/*
|
||||
* Note that in the subsequent iteration, next_copy
|
||||
* gets nulled out by the xdr_reference
|
||||
* but next itself survives.
|
||||
*/
|
||||
} else if (*rp) {
|
||||
rp = &((*rp)->rpcb_next);
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
|
||||
* functionality to xdr_rpcblist_ptr().
|
||||
*/
|
||||
bool_t
|
||||
xdr_rpcblist(xdrs, rp)
|
||||
XDR *xdrs;
|
||||
RPCBLIST **rp;
|
||||
{
|
||||
bool_t dummy;
|
||||
|
||||
dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
|
||||
return (dummy);
|
||||
}
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_rpcb_entry(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcb_entry *objp;
|
||||
{
|
||||
|
||||
_DIAGASSERT(objp != NULL);
|
||||
|
||||
if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_rpcb_entry_list_ptr(xdrs, rp)
|
||||
XDR *xdrs;
|
||||
rpcb_entry_list_ptr *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;
|
||||
rpcb_entry_list_ptr next;
|
||||
rpcb_entry_list_ptr next_copy;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
/* XXX: rp is allowed to be NULL ??? */
|
||||
|
||||
freeing = (xdrs->x_op == XDR_FREE);
|
||||
next = NULL;
|
||||
|
||||
for (;;) {
|
||||
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 && *rp)
|
||||
next = (*rp)->rpcb_entry_next;
|
||||
if (! xdr_reference(xdrs, (caddr_t *)rp,
|
||||
(u_int)sizeof (rpcb_entry_list),
|
||||
(xdrproc_t)xdr_rpcb_entry)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (freeing) {
|
||||
next_copy = next;
|
||||
rp = &next_copy;
|
||||
/*
|
||||
* Note that in the subsequent iteration, next_copy
|
||||
* gets nulled out by the xdr_reference
|
||||
* but next itself survives.
|
||||
*/
|
||||
} else if (*rp) {
|
||||
rp = &((*rp)->rpcb_entry_next);
|
||||
}
|
||||
}
|
||||
/*NOTREACHED*/
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR remote call arguments
|
||||
* written for XDR_ENCODE direction only
|
||||
*/
|
||||
bool_t
|
||||
xdr_rpcb_rmtcallargs(xdrs, p)
|
||||
XDR *xdrs;
|
||||
struct rpcb_rmtcallargs *p;
|
||||
{
|
||||
struct r_rpcb_rmtcallargs *objp =
|
||||
(struct r_rpcb_rmtcallargs *)(void *)p;
|
||||
u_int lenposition, argposition, position;
|
||||
int32_t *buf;
|
||||
|
||||
_DIAGASSERT(p != NULL);
|
||||
|
||||
buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
|
||||
if (buf == NULL) {
|
||||
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
|
||||
return (FALSE);
|
||||
}
|
||||
} else {
|
||||
IXDR_PUT_U_INT32(buf, objp->prog);
|
||||
IXDR_PUT_U_INT32(buf, objp->vers);
|
||||
IXDR_PUT_U_INT32(buf, objp->proc);
|
||||
}
|
||||
|
||||
/*
|
||||
* All the jugglery for just getting the size of the arguments
|
||||
*/
|
||||
lenposition = XDR_GETPOS(xdrs);
|
||||
if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
|
||||
return (FALSE);
|
||||
}
|
||||
argposition = XDR_GETPOS(xdrs);
|
||||
if (! (*objp->xdr_args)(xdrs, objp->args.args_val)) {
|
||||
return (FALSE);
|
||||
}
|
||||
position = XDR_GETPOS(xdrs);
|
||||
objp->args.args_len = (u_int)((u_long)position - (u_long)argposition);
|
||||
XDR_SETPOS(xdrs, lenposition);
|
||||
if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
|
||||
return (FALSE);
|
||||
}
|
||||
XDR_SETPOS(xdrs, position);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* XDR remote call results
|
||||
* written for XDR_DECODE direction only
|
||||
*/
|
||||
bool_t
|
||||
xdr_rpcb_rmtcallres(xdrs, p)
|
||||
XDR *xdrs;
|
||||
struct rpcb_rmtcallres *p;
|
||||
{
|
||||
bool_t dummy;
|
||||
struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p;
|
||||
|
||||
_DIAGASSERT(p != NULL);
|
||||
|
||||
if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int(xdrs, &objp->results.results_len)) {
|
||||
return (FALSE);
|
||||
}
|
||||
dummy = (*(objp->xdr_res))(xdrs, objp->results.results_val);
|
||||
return (dummy);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_netbuf(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
struct netbuf *objp;
|
||||
{
|
||||
bool_t dummy;
|
||||
|
||||
_DIAGASSERT(objp != NULL);
|
||||
|
||||
if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) {
|
||||
return (FALSE);
|
||||
}
|
||||
dummy = xdr_bytes(xdrs, (char **)(void *)&(objp->buf),
|
||||
(u_int *)&(objp->len), objp->maxlen);
|
||||
return (dummy);
|
||||
}
|
||||
@@ -0,0 +1,287 @@
|
||||
/* $NetBSD: rpcb_st_xdr.c,v 1.7 2006/05/11 17:11:57 mrg Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright 1991 Sun Microsystems, Inc.
|
||||
* rpcb_stat_xdr.c
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file was generated from rpcb_prot.x, but includes only those
|
||||
* routines used with the rpcbind stats facility.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: rpcb_st_xdr.c,v 1.7 2006/05/11 17:11:57 mrg Exp $");
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
/* Link list of all the stats about getport and getaddr */
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_rpcbs_addrlist,_xdr_rpcbs_addrlist)
|
||||
__weak_alias(xdr_rpcbs_rmtcalllist,_xdr_rpcbs_rmtcalllist)
|
||||
__weak_alias(xdr_rpcbs_proc,_xdr_rpcbs_proc)
|
||||
__weak_alias(xdr_rpcbs_addrlist_ptr,_xdr_rpcbs_addrlist_ptr)
|
||||
__weak_alias(xdr_rpcbs_rmtcalllist_ptr,_xdr_rpcbs_rmtcalllist_ptr)
|
||||
__weak_alias(xdr_rpcb_stat,_xdr_rpcb_stat)
|
||||
__weak_alias(xdr_rpcb_stat_byvers,_xdr_rpcb_stat_byvers)
|
||||
#endif
|
||||
|
||||
bool_t
|
||||
xdr_rpcbs_addrlist(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcbs_addrlist *objp;
|
||||
{
|
||||
|
||||
_DIAGASSERT(objp != NULL);
|
||||
|
||||
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->success)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->failure)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if (!xdr_pointer(xdrs, (char **)(void *)&objp->next,
|
||||
sizeof (rpcbs_addrlist),
|
||||
(xdrproc_t)xdr_rpcbs_addrlist)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/* Link list of all the stats about rmtcall */
|
||||
|
||||
bool_t
|
||||
xdr_rpcbs_rmtcalllist(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcbs_rmtcalllist *objp;
|
||||
{
|
||||
int32_t *buf;
|
||||
|
||||
_DIAGASSERT(xdrs != NULL);
|
||||
_DIAGASSERT(objp != NULL);
|
||||
|
||||
if (xdrs->x_op == XDR_ENCODE) {
|
||||
buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
|
||||
if (buf == NULL) {
|
||||
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->success)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->failure)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->indirect)) {
|
||||
return (FALSE);
|
||||
}
|
||||
} else {
|
||||
IXDR_PUT_U_INT32(buf, objp->prog);
|
||||
IXDR_PUT_U_INT32(buf, objp->vers);
|
||||
IXDR_PUT_U_INT32(buf, objp->proc);
|
||||
IXDR_PUT_INT32(buf, objp->success);
|
||||
IXDR_PUT_INT32(buf, objp->failure);
|
||||
IXDR_PUT_INT32(buf, objp->indirect);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **)(void *)&objp->next,
|
||||
sizeof (rpcbs_rmtcalllist),
|
||||
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
} else if (xdrs->x_op == XDR_DECODE) {
|
||||
buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
|
||||
if (buf == NULL) {
|
||||
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->success)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->failure)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->indirect)) {
|
||||
return (FALSE);
|
||||
}
|
||||
} else {
|
||||
objp->prog = (rpcprog_t)IXDR_GET_U_INT32(buf);
|
||||
objp->vers = (rpcvers_t)IXDR_GET_U_INT32(buf);
|
||||
objp->proc = (rpcproc_t)IXDR_GET_U_INT32(buf);
|
||||
objp->success = (int)IXDR_GET_INT32(buf);
|
||||
objp->failure = (int)IXDR_GET_INT32(buf);
|
||||
objp->indirect = (int)IXDR_GET_INT32(buf);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **)(void *)&objp->next,
|
||||
sizeof (rpcbs_rmtcalllist),
|
||||
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->prog)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->vers)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_u_int32_t(xdrs, &objp->proc)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->success)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->failure)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->indirect)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_pointer(xdrs, (char **)(void *)&objp->next,
|
||||
sizeof (rpcbs_rmtcalllist),
|
||||
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_rpcbs_proc(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcbs_proc objp;
|
||||
{
|
||||
if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBSTAT_HIGHPROC,
|
||||
sizeof (int), (xdrproc_t)xdr_int)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_rpcbs_addrlist_ptr(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcbs_addrlist_ptr *objp;
|
||||
{
|
||||
if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_addrlist),
|
||||
(xdrproc_t)xdr_rpcbs_addrlist)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_rpcbs_rmtcalllist_ptr(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcbs_rmtcalllist_ptr *objp;
|
||||
{
|
||||
if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_rmtcalllist),
|
||||
(xdrproc_t)xdr_rpcbs_rmtcalllist)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
bool_t
|
||||
xdr_rpcb_stat(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcb_stat *objp;
|
||||
{
|
||||
|
||||
_DIAGASSERT(objp != NULL);
|
||||
|
||||
if (!xdr_rpcbs_proc(xdrs, objp->info)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->setinfo)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_int(xdrs, &objp->unsetinfo)) {
|
||||
return (FALSE);
|
||||
}
|
||||
if (!xdr_rpcbs_addrlist_ptr(xdrs, &objp->addrinfo)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* One rpcb_stat structure is returned for each version of rpcbind
|
||||
* being monitored.
|
||||
*/
|
||||
bool_t
|
||||
xdr_rpcb_stat_byvers(xdrs, objp)
|
||||
XDR *xdrs;
|
||||
rpcb_stat_byvers objp;
|
||||
{
|
||||
if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBVERS_STAT,
|
||||
sizeof (rpcb_stat), (xdrproc_t)xdr_rpcb_stat)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
.\" @(#)rpcbind.3n 1.25 93/05/07 SMI; from SVr4
|
||||
.\" Copyright 1989 AT&T
|
||||
.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
|
||||
.\" $NetBSD: rpcbind.3,v 1.11 2009/04/11 16:07:20 joerg Exp $
|
||||
.Dd December 4, 2005
|
||||
.Dt RPCBIND 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm rpcb_getmaps ,
|
||||
.Nm rpcb_getaddr ,
|
||||
.Nm rpcb_gettime ,
|
||||
.Nm rpcb_rmtcall ,
|
||||
.Nm rpcb_set ,
|
||||
.Nm rpcb_unset
|
||||
.Nd library routines for RPC bind service
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In rpc/rpc.h
|
||||
.Ft "struct rpcblist *"
|
||||
.Fn rpcb_getmaps "const struct netconfig *netconf" "const char *host"
|
||||
.Ft bool_t
|
||||
.Fn rpcb_getaddr "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "struct netbuf *svcaddr" "const char *host"
|
||||
.Ft bool_t
|
||||
.Fn rpcb_gettime "const char *host" "time_t * timep"
|
||||
.Ft "enum clnt_stat"
|
||||
.Fn rpcb_rmtcall "const struct netconfig *netconf" "const char *host" "const rpcprog_t prognum, const rpcvers_t versnum" "const rpcproc_t procnum, const xdrproc_t inproc" "const char *in" "const xdrproc_t outproc" "caddr_t out" "const struct timeval tout, struct netbuf *svcaddr"
|
||||
.Ft bool_t
|
||||
.Fn rpcb_set "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct netbuf *svcaddr"
|
||||
.Ft bool_t
|
||||
.Fn rpcb_unset "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
|
||||
.Sh DESCRIPTION
|
||||
These routines allow client C programs to make procedure
|
||||
calls to the RPC binder service.
|
||||
(see
|
||||
.Xr rpcbind 8 )
|
||||
maintains a list of mappings between programs
|
||||
and their universal addresses.
|
||||
.Sh ROUTINES
|
||||
.Bl -tag -width XXXXX
|
||||
.It Fn rpcb_getmaps
|
||||
An interface to the rpcbind service,
|
||||
which returns a list of the current
|
||||
RPC program-to-address mappings on
|
||||
.Fa host .
|
||||
It uses the transport specified through
|
||||
.Fa netconf
|
||||
to contact the remote rpcbind
|
||||
service on
|
||||
.Fa host .
|
||||
This routine will return
|
||||
.Dv NULL ,
|
||||
if the remote rpcbind could not be contacted.
|
||||
.Pp
|
||||
.It Fn rpcb_getaddr
|
||||
An interface to the rpcbind
|
||||
service, which finds the address of the service on
|
||||
.Fa host
|
||||
that is registered with program number
|
||||
.Fa prognum ,
|
||||
version
|
||||
.Fa versnum ,
|
||||
and speaks the transport protocol associated with
|
||||
.Fa netconf .
|
||||
The address found is returned in
|
||||
.Fa svcaddr .
|
||||
.Fa svcaddr
|
||||
should be preallocated.
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if it succeeds.
|
||||
A return value of
|
||||
.Dv FALSE
|
||||
means that the mapping does not exist
|
||||
or that the RPC
|
||||
system failed to contact the remote
|
||||
rpcbind service.
|
||||
In the latter case, the global variable
|
||||
.Va rpc_createerr
|
||||
(see
|
||||
.Xr rpc_clnt_create 3
|
||||
contains the
|
||||
RPC status.
|
||||
.Pp
|
||||
.It Fn rpcb_gettime
|
||||
This routine returns the time on
|
||||
.Fa host
|
||||
in
|
||||
.Fa timep .
|
||||
If
|
||||
.Fa host
|
||||
is
|
||||
.Dv NULL ,
|
||||
.Fn rpcb_gettime
|
||||
returns the time on its own machine.
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if it succeeds,
|
||||
.Dv FALSE
|
||||
if it fails.
|
||||
.Fn rpcb_gettime
|
||||
can be used to synchronize the time between the
|
||||
client and the remote server.
|
||||
.Pp
|
||||
.It Fn rpcb_rmtcall
|
||||
An interface to the rpcbind service, which instructs
|
||||
rpcbind on
|
||||
.Fa host
|
||||
to make an RPC
|
||||
call on your behalf to a procedure on that host.
|
||||
The
|
||||
.Fn netconfig
|
||||
structure should correspond to a connectionless transport.
|
||||
The parameter
|
||||
.Fa svcaddr
|
||||
will be modified to the server's address if the procedure succeeds
|
||||
(see
|
||||
.Fn rpc_call
|
||||
and
|
||||
.Fn clnt_call
|
||||
in
|
||||
.Xr rpc_clnt_calls 3
|
||||
for the definitions of other parameters).
|
||||
.Pp
|
||||
This procedure should normally be used for a
|
||||
``ping'' and nothing else.
|
||||
This routine allows programs to do lookup and call, all in one step.
|
||||
.Pp
|
||||
Note: Even if the server is not running
|
||||
.Fn rpcb_rmtcall
|
||||
does not return any error messages to the caller.
|
||||
In such a case, the caller times out.
|
||||
.Pp
|
||||
Note:
|
||||
.Fn rpcb_rmtcall
|
||||
is only available for connectionless transports.
|
||||
.Pp
|
||||
.It Fn rpcb_set
|
||||
An interface to the rpcbind
|
||||
service, which establishes a mapping between the triple
|
||||
[
|
||||
.Fa prognum ,
|
||||
.Fa versnum ,
|
||||
.Fa netconf-\*[Gt]nc_netid ]
|
||||
and
|
||||
.Fa svcaddr
|
||||
on the machine's rpcbind
|
||||
service.
|
||||
The value of
|
||||
.Fa nc_netid
|
||||
must correspond to a network identifier that is defined by the
|
||||
netconfig database.
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if it succeeds,
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
(See also
|
||||
.Fn svc_reg
|
||||
in
|
||||
.Xr rpc_svc_calls 3 .
|
||||
If there already exists such an entry with rpcbind,
|
||||
.Fn rpcb_set
|
||||
will fail.
|
||||
.Pp
|
||||
.It Fn rpcb_unset
|
||||
An interface to the rpcbind
|
||||
service, which destroys the mapping between the triple
|
||||
[
|
||||
.Fa prognum ,
|
||||
.Fa versnum ,
|
||||
.Fa netconf-\*[Gt]nc_netid ]
|
||||
and the address on the machine's rpcbind
|
||||
service.
|
||||
If
|
||||
.Fa netconf
|
||||
is
|
||||
.Dv NULL ,
|
||||
.Fn rpcb_unset
|
||||
destroys all mapping between the triple
|
||||
[
|
||||
.Fa prognum ,
|
||||
.Fa versnum ,
|
||||
.Fa all-transports ]
|
||||
and the addresses on the machine's rpcbind service.
|
||||
This routine returns
|
||||
.Dv TRUE
|
||||
if it succeeds,
|
||||
.Dv FALSE
|
||||
otherwise.
|
||||
Only the owner of the service or the super-user can destroy the mapping.
|
||||
(See also
|
||||
.Fn svc_unreg
|
||||
in
|
||||
.Xr rpc_svc_calls 3 .
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc_clnt_calls 3 ,
|
||||
.Xr rpc_svc_calls 3 ,
|
||||
.Xr rpcbind 8 ,
|
||||
.Xr rpcinfo 8
|
||||
@@ -0,0 +1,799 @@
|
||||
/* $NetBSD: svc.c,v 1.30 2010/07/08 20:12:37 tron Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc.c,v 1.30 2010/07/08 20:12:37 tron Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* svc.c, Server-side remote procedure call interface.
|
||||
*
|
||||
* There are two sets of procedures here. The xprt routines are
|
||||
* for handling transport handles. The svc routines handle the
|
||||
* list of service routines.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/poll.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <err.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
#ifdef PORTMAP
|
||||
#include <rpc/pmap_clnt.h>
|
||||
#endif
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_getreq,_svc_getreq)
|
||||
__weak_alias(svc_getreqset,_svc_getreqset)
|
||||
__weak_alias(svc_getreq_common,_svc_getreq_common)
|
||||
__weak_alias(svc_register,_svc_register)
|
||||
__weak_alias(svc_reg,_svc_reg)
|
||||
__weak_alias(svc_unreg,_svc_unreg)
|
||||
__weak_alias(svc_sendreply,_svc_sendreply)
|
||||
__weak_alias(svc_unregister,_svc_unregister)
|
||||
__weak_alias(svcerr_auth,_svcerr_auth)
|
||||
__weak_alias(svcerr_decode,_svcerr_decode)
|
||||
__weak_alias(svcerr_noproc,_svcerr_noproc)
|
||||
__weak_alias(svcerr_noprog,_svcerr_noprog)
|
||||
__weak_alias(svcerr_progvers,_svcerr_progvers)
|
||||
__weak_alias(svcerr_systemerr,_svcerr_systemerr)
|
||||
__weak_alias(svcerr_weakauth,_svcerr_weakauth)
|
||||
__weak_alias(xprt_register,_xprt_register)
|
||||
__weak_alias(xprt_unregister,_xprt_unregister)
|
||||
__weak_alias(rpc_control,_rpc_control)
|
||||
#endif
|
||||
|
||||
SVCXPRT **__svc_xports;
|
||||
int __svc_maxrec;
|
||||
|
||||
#define RQCRED_SIZE 400 /* this size is excessive */
|
||||
|
||||
#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */
|
||||
#define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET)
|
||||
|
||||
#define max(a, b) (a > b ? a : b)
|
||||
|
||||
/*
|
||||
* The services list
|
||||
* Each entry represents a set of procedures (an rpc program).
|
||||
* The dispatch routine takes request structs and runs the
|
||||
* apropriate procedure.
|
||||
*/
|
||||
static struct svc_callout {
|
||||
struct svc_callout *sc_next;
|
||||
rpcprog_t sc_prog;
|
||||
rpcvers_t sc_vers;
|
||||
char *sc_netid;
|
||||
void (*sc_dispatch) __P((struct svc_req *, SVCXPRT *));
|
||||
} *svc_head;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t svc_lock;
|
||||
extern rwlock_t svc_fd_lock;
|
||||
#endif
|
||||
|
||||
static struct svc_callout *svc_find __P((rpcprog_t, rpcvers_t,
|
||||
struct svc_callout **, char *));
|
||||
static void __xprt_do_unregister __P((SVCXPRT *xprt, bool_t dolock));
|
||||
|
||||
/* *************** SVCXPRT related stuff **************** */
|
||||
|
||||
/*
|
||||
* Activate a transport handle.
|
||||
*/
|
||||
void
|
||||
xprt_register(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
int sock;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
sock = xprt->xp_fd;
|
||||
|
||||
rwlock_wrlock(&svc_fd_lock);
|
||||
if (__svc_xports == NULL) {
|
||||
__svc_xports = mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
|
||||
if (__svc_xports == NULL) {
|
||||
warn("xprt_register");
|
||||
goto out;
|
||||
}
|
||||
memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *));
|
||||
}
|
||||
if (sock < FD_SETSIZE) {
|
||||
__svc_xports[sock] = xprt;
|
||||
FD_SET(sock, &svc_fdset);
|
||||
svc_maxfd = max(svc_maxfd, sock);
|
||||
}
|
||||
out:
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
}
|
||||
|
||||
void
|
||||
xprt_unregister(SVCXPRT *xprt)
|
||||
{
|
||||
__xprt_do_unregister(xprt, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
__xprt_unregister_unlocked(SVCXPRT *xprt)
|
||||
{
|
||||
__xprt_do_unregister(xprt, FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* De-activate a transport handle.
|
||||
*/
|
||||
static void
|
||||
__xprt_do_unregister(xprt, dolock)
|
||||
SVCXPRT *xprt;
|
||||
bool_t dolock;
|
||||
{
|
||||
int sock;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
sock = xprt->xp_fd;
|
||||
|
||||
if (dolock)
|
||||
rwlock_wrlock(&svc_fd_lock);
|
||||
if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) {
|
||||
__svc_xports[sock] = NULL;
|
||||
FD_CLR(sock, &svc_fdset);
|
||||
if (sock >= svc_maxfd) {
|
||||
for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--)
|
||||
if (__svc_xports[svc_maxfd])
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (dolock)
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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_reg(xprt, prog, vers, dispatch, nconf)
|
||||
SVCXPRT *xprt;
|
||||
const rpcprog_t prog;
|
||||
const rpcvers_t vers;
|
||||
void (*dispatch) __P((struct svc_req *, SVCXPRT *));
|
||||
const struct netconfig *nconf;
|
||||
{
|
||||
bool_t dummy;
|
||||
struct svc_callout *prev;
|
||||
struct svc_callout *s;
|
||||
struct netconfig *tnconf;
|
||||
char *netid = NULL;
|
||||
int flag = 0;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
/* XXX: dispatch may be NULL ??? */
|
||||
|
||||
/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */
|
||||
|
||||
if (xprt->xp_netid) {
|
||||
netid = strdup(xprt->xp_netid);
|
||||
flag = 1;
|
||||
} else if (nconf && nconf->nc_netid) {
|
||||
netid = strdup(nconf->nc_netid);
|
||||
flag = 1;
|
||||
} else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) {
|
||||
netid = strdup(tnconf->nc_netid);
|
||||
flag = 1;
|
||||
freenetconfigent(tnconf);
|
||||
} /* must have been created with svc_raw_create */
|
||||
if ((netid == NULL) && (flag == 1)) {
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
rwlock_wrlock(&svc_lock);
|
||||
if ((s = svc_find(prog, vers, &prev, netid)) != NULL) {
|
||||
if (netid)
|
||||
free(netid);
|
||||
if (s->sc_dispatch == dispatch)
|
||||
goto rpcb_it; /* he is registering another xptr */
|
||||
rwlock_unlock(&svc_lock);
|
||||
return (FALSE);
|
||||
}
|
||||
s = mem_alloc(sizeof (struct svc_callout));
|
||||
if (s == NULL) {
|
||||
if (netid)
|
||||
free(netid);
|
||||
rwlock_unlock(&svc_lock);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
if ((xprt->xp_netid == NULL) && (flag == 1) && netid)
|
||||
if ((((SVCXPRT *) xprt)->xp_netid = strdup(netid)) == NULL) {
|
||||
warn("svc_reg");
|
||||
mem_free(s, sizeof(struct svc_callout));
|
||||
rwlock_unlock(&svc_lock);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
s->sc_prog = prog;
|
||||
s->sc_vers = vers;
|
||||
s->sc_dispatch = dispatch;
|
||||
s->sc_netid = netid;
|
||||
s->sc_next = svc_head;
|
||||
svc_head = s;
|
||||
|
||||
rpcb_it:
|
||||
rwlock_unlock(&svc_lock);
|
||||
/* now register the information with the local binder service */
|
||||
if (nconf) {
|
||||
dummy = rpcb_set(prog, vers, __UNCONST(nconf),
|
||||
&((SVCXPRT *) xprt)->xp_ltaddr);
|
||||
return (dummy);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a service program from the callout list.
|
||||
*/
|
||||
void
|
||||
svc_unreg(prog, vers)
|
||||
const rpcprog_t prog;
|
||||
const rpcvers_t vers;
|
||||
{
|
||||
struct svc_callout *prev;
|
||||
struct svc_callout *s;
|
||||
|
||||
/* unregister the information anyway */
|
||||
(void) rpcb_unset(prog, vers, NULL);
|
||||
rwlock_wrlock(&svc_lock);
|
||||
while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) {
|
||||
if (prev == NULL) {
|
||||
svc_head = s->sc_next;
|
||||
} else {
|
||||
prev->sc_next = s->sc_next;
|
||||
}
|
||||
s->sc_next = NULL;
|
||||
if (s->sc_netid)
|
||||
mem_free(s->sc_netid, sizeof (s->sc_netid) + 1);
|
||||
mem_free(s, sizeof (struct svc_callout));
|
||||
}
|
||||
rwlock_unlock(&svc_lock);
|
||||
}
|
||||
|
||||
/* ********************** CALLOUT list related stuff ************* */
|
||||
|
||||
#ifdef PORTMAP
|
||||
/*
|
||||
* Add a service program to the callout list.
|
||||
* The dispatch routine will be called when a rpc request for this
|
||||
* program number comes in.
|
||||
*/
|
||||
bool_t
|
||||
svc_register(xprt, prog, vers, dispatch, protocol)
|
||||
SVCXPRT *xprt;
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
void (*dispatch) __P((struct svc_req *, SVCXPRT *));
|
||||
int protocol;
|
||||
{
|
||||
struct svc_callout *prev;
|
||||
struct svc_callout *s;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(dispatch != NULL);
|
||||
|
||||
if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) !=
|
||||
NULL) {
|
||||
if (s->sc_dispatch == dispatch)
|
||||
goto pmap_it; /* he is registering another xptr */
|
||||
return (FALSE);
|
||||
}
|
||||
s = mem_alloc(sizeof(struct svc_callout));
|
||||
if (s == NULL) {
|
||||
return (FALSE);
|
||||
}
|
||||
s->sc_prog = (rpcprog_t)prog;
|
||||
s->sc_vers = (rpcvers_t)vers;
|
||||
s->sc_dispatch = dispatch;
|
||||
s->sc_next = svc_head;
|
||||
svc_head = s;
|
||||
pmap_it:
|
||||
/* now register the information with the local binder service */
|
||||
if (protocol) {
|
||||
return (pmap_set(prog, vers, protocol, xprt->xp_port));
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove a service program from the callout list.
|
||||
*/
|
||||
void
|
||||
svc_unregister(prog, vers)
|
||||
u_long prog;
|
||||
u_long vers;
|
||||
{
|
||||
struct svc_callout *prev;
|
||||
struct svc_callout *s;
|
||||
|
||||
if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) ==
|
||||
NULL)
|
||||
return;
|
||||
if (prev == NULL) {
|
||||
svc_head = s->sc_next;
|
||||
} else {
|
||||
prev->sc_next = s->sc_next;
|
||||
}
|
||||
s->sc_next = NULL;
|
||||
mem_free(s, sizeof(struct svc_callout));
|
||||
/* now unregister the information with the local binder service */
|
||||
(void)pmap_unset(prog, vers);
|
||||
}
|
||||
#endif /* PORTMAP */
|
||||
|
||||
/*
|
||||
* Search the callout list for a program number, return the callout
|
||||
* struct.
|
||||
*/
|
||||
static struct svc_callout *
|
||||
svc_find(prog, vers, prev, netid)
|
||||
rpcprog_t prog;
|
||||
rpcvers_t vers;
|
||||
struct svc_callout **prev;
|
||||
char *netid;
|
||||
{
|
||||
struct svc_callout *s, *p;
|
||||
|
||||
_DIAGASSERT(prev != NULL);
|
||||
/* netid is handled below */
|
||||
|
||||
p = NULL;
|
||||
for (s = svc_head; s != NULL; s = s->sc_next) {
|
||||
if (((s->sc_prog == prog) && (s->sc_vers == vers)) &&
|
||||
((netid == NULL) || (s->sc_netid == NULL) ||
|
||||
(strcmp(netid, s->sc_netid) == 0)))
|
||||
break;
|
||||
p = s;
|
||||
}
|
||||
*prev = p;
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* ******************* REPLY GENERATION ROUTINES ************ */
|
||||
|
||||
/*
|
||||
* Send a reply to an rpc request
|
||||
*/
|
||||
bool_t
|
||||
svc_sendreply(xprt, xdr_results, xdr_location)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_results;
|
||||
const char *xdr_location;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
rply.rm_direction = REPLY;
|
||||
rply.rm_reply.rp_stat = MSG_ACCEPTED;
|
||||
rply.acpted_rply.ar_verf = xprt->xp_verf;
|
||||
rply.acpted_rply.ar_stat = SUCCESS;
|
||||
rply.acpted_rply.ar_results.where = xdr_location;
|
||||
rply.acpted_rply.ar_results.proc = xdr_results;
|
||||
return (SVC_REPLY(xprt, &rply));
|
||||
}
|
||||
|
||||
/*
|
||||
* No procedure error reply
|
||||
*/
|
||||
void
|
||||
svcerr_noproc(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
rply.rm_direction = REPLY;
|
||||
rply.rm_reply.rp_stat = MSG_ACCEPTED;
|
||||
rply.acpted_rply.ar_verf = xprt->xp_verf;
|
||||
rply.acpted_rply.ar_stat = PROC_UNAVAIL;
|
||||
SVC_REPLY(xprt, &rply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Can't decode args error reply
|
||||
*/
|
||||
void
|
||||
svcerr_decode(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
rply.rm_direction = REPLY;
|
||||
rply.rm_reply.rp_stat = MSG_ACCEPTED;
|
||||
rply.acpted_rply.ar_verf = xprt->xp_verf;
|
||||
rply.acpted_rply.ar_stat = GARBAGE_ARGS;
|
||||
SVC_REPLY(xprt, &rply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Some system error
|
||||
*/
|
||||
void
|
||||
svcerr_systemerr(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/*
|
||||
* Tell RPC package to not complain about version errors to the client. This
|
||||
* is useful when revving broadcast protocols that sit on a fixed address.
|
||||
* There is really one (or should be only one) example of this kind of
|
||||
* protocol: the portmapper (or rpc binder).
|
||||
*/
|
||||
void
|
||||
__svc_versquiet_on(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
u_long tmp;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET;
|
||||
xprt->xp_p3 = (caddr_t) tmp;
|
||||
}
|
||||
|
||||
void
|
||||
__svc_versquiet_off(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
u_long tmp;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET;
|
||||
xprt->xp_p3 = (caddr_t) tmp;
|
||||
}
|
||||
|
||||
void
|
||||
svc_versquiet(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
__svc_versquiet_on(xprt);
|
||||
}
|
||||
|
||||
int
|
||||
__svc_versquiet_get(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
return ((int) xprt->xp_p3) & SVC_VERSQUIET;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Authentication error reply
|
||||
*/
|
||||
void
|
||||
svcerr_auth(xprt, why)
|
||||
SVCXPRT *xprt;
|
||||
enum auth_stat why;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
rply.rm_direction = REPLY;
|
||||
rply.rm_reply.rp_stat = MSG_DENIED;
|
||||
rply.rjcted_rply.rj_stat = AUTH_ERROR;
|
||||
rply.rjcted_rply.rj_why = why;
|
||||
SVC_REPLY(xprt, &rply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Auth too weak error reply
|
||||
*/
|
||||
void
|
||||
svcerr_weakauth(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
svcerr_auth(xprt, AUTH_TOOWEAK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Program unavailable error reply
|
||||
*/
|
||||
void
|
||||
svcerr_noprog(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
rply.rm_direction = REPLY;
|
||||
rply.rm_reply.rp_stat = MSG_ACCEPTED;
|
||||
rply.acpted_rply.ar_verf = xprt->xp_verf;
|
||||
rply.acpted_rply.ar_stat = PROG_UNAVAIL;
|
||||
SVC_REPLY(xprt, &rply);
|
||||
}
|
||||
|
||||
/*
|
||||
* Program version mismatch error reply
|
||||
*/
|
||||
void
|
||||
svcerr_progvers(xprt, low_vers, high_vers)
|
||||
SVCXPRT *xprt;
|
||||
rpcvers_t low_vers;
|
||||
rpcvers_t high_vers;
|
||||
{
|
||||
struct rpc_msg rply;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
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 = (u_int32_t)low_vers;
|
||||
rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers;
|
||||
SVC_REPLY(xprt, &rply);
|
||||
}
|
||||
|
||||
/* ******************* SERVER INPUT STUFF ******************* */
|
||||
|
||||
/*
|
||||
* Get server side input from some transport.
|
||||
*
|
||||
* Statement of authentication parameters management:
|
||||
* This function owns and manages all authentication parameters, specifically
|
||||
* the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
|
||||
* the "cooked" credentials (rqst->rq_clntcred).
|
||||
* However, this function does not know the structure of the cooked
|
||||
* credentials, so it make the following assumptions:
|
||||
* a) the structure is contiguous (no pointers), and
|
||||
* b) the cred structure size does not exceed RQCRED_SIZE bytes.
|
||||
* In all events, all three parameters are freed upon exit from this routine.
|
||||
* The storage is trivially management on the call stack in user land, but
|
||||
* is mallocated in kernel land.
|
||||
*/
|
||||
|
||||
void
|
||||
svc_getreq(rdfds)
|
||||
int rdfds;
|
||||
{
|
||||
fd_set readfds;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
readfds.fds_bits[0] = (unsigned int)rdfds;
|
||||
svc_getreqset(&readfds);
|
||||
}
|
||||
|
||||
void
|
||||
svc_getreqset(readfds)
|
||||
fd_set *readfds;
|
||||
{
|
||||
uint32_t mask, *maskp;
|
||||
int sock, bit, fd;
|
||||
|
||||
_DIAGASSERT(readfds != NULL);
|
||||
|
||||
maskp = readfds->fds_bits;
|
||||
for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) {
|
||||
for (mask = *maskp++; (bit = ffs((int)mask)) != 0;
|
||||
mask ^= (1 << (bit - 1))) {
|
||||
/* sock has input waiting */
|
||||
fd = sock + bit - 1;
|
||||
svc_getreq_common(fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
svc_getreq_common(fd)
|
||||
int fd;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
struct svc_req r;
|
||||
struct rpc_msg msg;
|
||||
int prog_found;
|
||||
rpcvers_t low_vers;
|
||||
rpcvers_t high_vers;
|
||||
enum xprt_stat stat;
|
||||
char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
|
||||
|
||||
msg.rm_call.cb_cred.oa_base = cred_area;
|
||||
msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
|
||||
r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
|
||||
|
||||
rwlock_rdlock(&svc_fd_lock);
|
||||
xprt = __svc_xports[fd];
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
if (xprt == NULL)
|
||||
/* But do we control sock? */
|
||||
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;
|
||||
enum auth_stat why;
|
||||
|
||||
r.rq_xprt = xprt;
|
||||
r.rq_prog = msg.rm_call.cb_prog;
|
||||
r.rq_vers = msg.rm_call.cb_vers;
|
||||
r.rq_proc = msg.rm_call.cb_proc;
|
||||
r.rq_cred = msg.rm_call.cb_cred;
|
||||
/* first authenticate the message */
|
||||
if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
|
||||
svcerr_auth(xprt, why);
|
||||
goto call_done;
|
||||
}
|
||||
/* now match message with a registered service*/
|
||||
prog_found = FALSE;
|
||||
low_vers = (rpcvers_t) -1L;
|
||||
high_vers = (rpcvers_t) 0L;
|
||||
for (s = svc_head; s != NULL; 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 ... */
|
||||
}
|
||||
/*
|
||||
* Check if the xprt has been disconnected in a
|
||||
* recursive call in the service dispatch routine.
|
||||
* If so, then break.
|
||||
*/
|
||||
rwlock_rdlock(&svc_fd_lock);
|
||||
if (xprt != __svc_xports[fd]) {
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
break;
|
||||
}
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
call_done:
|
||||
if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
|
||||
SVC_DESTROY(xprt);
|
||||
break;
|
||||
}
|
||||
} while (stat == XPRT_MOREREQS);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
svc_getreq_poll(pfdp, pollretval)
|
||||
struct pollfd *pfdp;
|
||||
int pollretval;
|
||||
{
|
||||
int i;
|
||||
int fds_found;
|
||||
|
||||
_DIAGASSERT(pfdp != NULL);
|
||||
|
||||
for (i = fds_found = 0; fds_found < pollretval; i++) {
|
||||
struct pollfd *p = &pfdp[i];
|
||||
|
||||
if (p->revents) {
|
||||
/* fd has input waiting */
|
||||
fds_found++;
|
||||
/*
|
||||
* We assume that this function is only called
|
||||
* via someone select()ing from svc_fdset or
|
||||
* pollts()ing from svc_pollset[]. Thus it's safe
|
||||
* to handle the POLLNVAL event by simply turning
|
||||
* the corresponding bit off in svc_fdset. The
|
||||
* svc_pollset[] array is derived from svc_fdset
|
||||
* and so will also be updated eventually.
|
||||
*
|
||||
* XXX Should we do an xprt_unregister() instead?
|
||||
*/
|
||||
if (p->revents & POLLNVAL) {
|
||||
rwlock_wrlock(&svc_fd_lock);
|
||||
FD_CLR(p->fd, &svc_fdset);
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
} else
|
||||
svc_getreq_common(p->fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool_t
|
||||
rpc_control(int what, void *arg)
|
||||
{
|
||||
int val;
|
||||
|
||||
switch (what) {
|
||||
case RPC_SVC_CONNMAXREC_SET:
|
||||
val = *(int *)arg;
|
||||
if (val <= 0)
|
||||
return FALSE;
|
||||
__svc_maxrec = val;
|
||||
return TRUE;
|
||||
case RPC_SVC_CONNMAXREC_GET:
|
||||
*(int *)arg = __svc_maxrec;
|
||||
return TRUE;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -0,0 +1,226 @@
|
||||
/* $NetBSD: svc_auth.c,v 1.15 2003/09/09 03:56:40 itojun Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)svc_auth.c 1.16 94/04/24 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc_auth.c,v 1.15 2003/09/09 03:56:40 itojun Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* svc_auth.c, Server-side rpc authenticator interface.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_auth_reg,_svc_auth_reg)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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)
|
||||
* struct svc_req *rqst;
|
||||
* struct rpc_msg *msg;
|
||||
*
|
||||
*/
|
||||
|
||||
/* declarations to allow servers to specify new authentication flavors */
|
||||
struct authsvc {
|
||||
int flavor;
|
||||
enum auth_stat (*handler) __P((struct svc_req *, struct rpc_msg *));
|
||||
struct authsvc *next;
|
||||
};
|
||||
static struct authsvc *Auths = NULL;
|
||||
|
||||
/*
|
||||
* The call rpc message, msg has been obtained from the wire. The msg contains
|
||||
* the raw form of credentials and verifiers. authenticate returns AUTH_OK
|
||||
* if the msg is successfully authenticated. If AUTH_OK then the routine also
|
||||
* does the following things:
|
||||
* set rqst->rq_xprt->verf to the appropriate response verifier;
|
||||
* sets rqst->rq_client_cred to the "cooked" form of the credentials.
|
||||
*
|
||||
* NB: rqst->rq_cxprt->verf must be pre-alloctaed;
|
||||
* its length is set appropriately.
|
||||
*
|
||||
* The caller still owns and is responsible for msg->u.cmb.cred and
|
||||
* msg->u.cmb.verf. The authentication system retains ownership of
|
||||
* rqst->rq_client_cred, the cooked credentials.
|
||||
*
|
||||
* There is an assumption that any flavour less than AUTH_NULL is
|
||||
* invalid.
|
||||
*/
|
||||
enum auth_stat
|
||||
_authenticate(rqst, msg)
|
||||
struct svc_req *rqst;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
int cred_flavor;
|
||||
struct authsvc *asp;
|
||||
enum auth_stat dummy;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t authsvc_lock;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(rqst != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
/* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */
|
||||
|
||||
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;
|
||||
switch (cred_flavor) {
|
||||
case AUTH_NULL:
|
||||
dummy = _svcauth_null(rqst, msg);
|
||||
return (dummy);
|
||||
case AUTH_SYS:
|
||||
dummy = _svcauth_unix(rqst, msg);
|
||||
return (dummy);
|
||||
case AUTH_SHORT:
|
||||
dummy = _svcauth_short(rqst, msg);
|
||||
return (dummy);
|
||||
#if 0
|
||||
case AUTH_DES:
|
||||
dummy = __svcauth_des(rqst, msg);
|
||||
return (dummy);
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* flavor doesn't match any of the builtin types, so try new ones */
|
||||
mutex_lock(&authsvc_lock);
|
||||
for (asp = Auths; asp; asp = asp->next) {
|
||||
if (asp->flavor == cred_flavor) {
|
||||
enum auth_stat as;
|
||||
|
||||
as = (*asp->handler)(rqst, msg);
|
||||
mutex_unlock(&authsvc_lock);
|
||||
return (as);
|
||||
}
|
||||
}
|
||||
mutex_unlock(&authsvc_lock);
|
||||
|
||||
return (AUTH_REJECTEDCRED);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
enum auth_stat
|
||||
_svcauth_null(rqst, msg)
|
||||
struct svc_req *rqst;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
return (AUTH_OK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Allow the rpc service to register new authentication types that it is
|
||||
* prepared to handle. When an authentication flavor is registered,
|
||||
* the flavor is checked against already registered values. If not
|
||||
* registered, then a new Auths entry is added on the list.
|
||||
*
|
||||
* There is no provision to delete a registration once registered.
|
||||
*
|
||||
* This routine returns:
|
||||
* 0 if registration successful
|
||||
* 1 if flavor already registered
|
||||
* -1 if can't register (errno set)
|
||||
*/
|
||||
|
||||
int
|
||||
svc_auth_reg(cred_flavor, handler)
|
||||
int cred_flavor;
|
||||
enum auth_stat (*handler) __P((struct svc_req *, struct rpc_msg *));
|
||||
{
|
||||
struct authsvc *asp;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t authsvc_lock;
|
||||
#endif
|
||||
|
||||
switch (cred_flavor) {
|
||||
case AUTH_NULL:
|
||||
case AUTH_SYS:
|
||||
case AUTH_SHORT:
|
||||
#if 0
|
||||
case AUTH_DES:
|
||||
#endif
|
||||
/* already registered */
|
||||
return (1);
|
||||
|
||||
default:
|
||||
mutex_lock(&authsvc_lock);
|
||||
for (asp = Auths; asp; asp = asp->next) {
|
||||
if (asp->flavor == cred_flavor) {
|
||||
/* already registered */
|
||||
mutex_unlock(&authsvc_lock);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
|
||||
/* this is a new one, so go ahead and register it */
|
||||
asp = mem_alloc(sizeof (*asp));
|
||||
if (asp == NULL) {
|
||||
mutex_unlock(&authsvc_lock);
|
||||
return (-1);
|
||||
}
|
||||
asp->flavor = cred_flavor;
|
||||
asp->handler = handler;
|
||||
asp->next = Auths;
|
||||
Auths = asp;
|
||||
mutex_unlock(&authsvc_lock);
|
||||
break;
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1,149 @@
|
||||
/* $NetBSD: svc_auth_unix.c,v 1.18 2003/01/18 11:29:06 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc_auth_unix.c,v 1.18 2003/01/18 11:29:06 thorpej Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* svc_auth_unix.c
|
||||
* Handles UNIX flavor authentication parameters on the service side of rpc.
|
||||
* There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
|
||||
* _svcauth_unix does full blown unix style uid,gid+gids auth,
|
||||
* _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
|
||||
* Note: the shorthand has been gutted for efficiency.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
/*
|
||||
* Unix longhand authenticator
|
||||
*/
|
||||
enum auth_stat
|
||||
_svcauth_unix(rqst, msg)
|
||||
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];
|
||||
int area_gids[NGRPS];
|
||||
} *area;
|
||||
u_int auth_len;
|
||||
size_t str_len, gid_len, i;
|
||||
|
||||
_DIAGASSERT(rqst != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
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_INT32(buf);
|
||||
str_len = (size_t)IXDR_GET_U_INT32(buf);
|
||||
if (str_len > MAX_MACHINE_NAME) {
|
||||
stat = AUTH_BADCRED;
|
||||
goto done;
|
||||
}
|
||||
memmove(aup->aup_machname, buf, str_len);
|
||||
aup->aup_machname[str_len] = 0;
|
||||
str_len = RNDUP(str_len);
|
||||
buf += str_len / sizeof (int32_t);
|
||||
aup->aup_uid = (int)IXDR_GET_INT32(buf);
|
||||
aup->aup_gid = (int)IXDR_GET_INT32(buf);
|
||||
gid_len = (size_t)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] = (int)IXDR_GET_INT32(buf);
|
||||
}
|
||||
/*
|
||||
* five is the smallest unix credentials structure -
|
||||
* timestamp, hostname len (0), uid, gid, and gids len (0).
|
||||
*/
|
||||
if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
|
||||
(void) printf("bad auth_len gid %ld str %ld auth %u\n",
|
||||
(long)gid_len, (long)str_len, auth_len);
|
||||
stat = AUTH_BADCRED;
|
||||
goto done;
|
||||
}
|
||||
} else if (! xdr_authunix_parms(&xdrs, aup)) {
|
||||
xdrs.x_op = XDR_FREE;
|
||||
(void)xdr_authunix_parms(&xdrs, aup);
|
||||
stat = AUTH_BADCRED;
|
||||
goto done;
|
||||
}
|
||||
rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
|
||||
rqst->rq_xprt->xp_verf.oa_length = 0;
|
||||
stat = AUTH_OK;
|
||||
done:
|
||||
XDR_DESTROY(&xdrs);
|
||||
return (stat);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Shorthand unix authenticator
|
||||
* Looks up longhand in a cache.
|
||||
*/
|
||||
/*ARGSUSED*/
|
||||
enum auth_stat
|
||||
_svcauth_short(rqst, msg)
|
||||
struct svc_req *rqst;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
return (AUTH_REJECTEDCRED);
|
||||
}
|
||||
@@ -0,0 +1,652 @@
|
||||
/* $NetBSD: svc_dg.c,v 1.12 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)svc_dg.c 1.17 94/04/24 SMI" */
|
||||
|
||||
|
||||
/*
|
||||
* svc_dg.c, Server side for connectionless RPC.
|
||||
*
|
||||
* Does some caching in the hopes of achieving execute-at-most-once semantics.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: svc_dg.c,v 1.12 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#ifdef RPC_CACHE_DEBUG
|
||||
#include <netconfig.h>
|
||||
#include <netdir.h>
|
||||
#endif
|
||||
#include <err.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
#include "svc_dg.h"
|
||||
|
||||
#define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2))
|
||||
#define rpc_buffer(xprt) ((xprt)->xp_p1)
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_dg_create,_svc_dg_create)
|
||||
#endif
|
||||
|
||||
#ifndef MAX
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
static void svc_dg_ops __P((SVCXPRT *));
|
||||
static enum xprt_stat svc_dg_stat __P((SVCXPRT *));
|
||||
static bool_t svc_dg_recv __P((SVCXPRT *, struct rpc_msg *));
|
||||
static bool_t svc_dg_reply __P((SVCXPRT *, struct rpc_msg *));
|
||||
static bool_t svc_dg_getargs __P((SVCXPRT *, xdrproc_t, caddr_t));
|
||||
static bool_t svc_dg_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t));
|
||||
static void svc_dg_destroy __P((SVCXPRT *));
|
||||
static bool_t svc_dg_control __P((SVCXPRT *, const u_int, void *));
|
||||
static int cache_get __P((SVCXPRT *, struct rpc_msg *, char **, size_t *));
|
||||
static void cache_set __P((SVCXPRT *, size_t));
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
* xprt = svc_dg_create(sock, sendsize, recvsize);
|
||||
* Does other connectionless specific initializations.
|
||||
* Once *xprt is initialized, it is registered.
|
||||
* see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
|
||||
* system defaults are chosen.
|
||||
* The routines returns NULL if a problem occurred.
|
||||
*/
|
||||
static const char svc_dg_str[] = "svc_dg_create: %s";
|
||||
static const char svc_dg_err1[] = "could not get transport information";
|
||||
static const char svc_dg_err2[] = " transport does not support data transfer";
|
||||
static const char __no_mem_str[] = "out of memory";
|
||||
|
||||
SVCXPRT *
|
||||
svc_dg_create(fd, sendsize, recvsize)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
struct svc_dg_data *su = NULL;
|
||||
struct __rpc_sockinfo si;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t slen;
|
||||
|
||||
if (!__rpc_fd2sockinfo(fd, &si)) {
|
||||
warnx(svc_dg_str, svc_dg_err1);
|
||||
return (NULL);
|
||||
}
|
||||
/*
|
||||
* Find the receive and the send size
|
||||
*/
|
||||
sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
|
||||
recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
|
||||
if ((sendsize == 0) || (recvsize == 0)) {
|
||||
warnx(svc_dg_str, svc_dg_err2);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
xprt = mem_alloc(sizeof (SVCXPRT));
|
||||
if (xprt == NULL)
|
||||
goto freedata;
|
||||
memset(xprt, 0, sizeof (SVCXPRT));
|
||||
|
||||
su = mem_alloc(sizeof (*su));
|
||||
if (su == NULL)
|
||||
goto freedata;
|
||||
su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4;
|
||||
if ((rpc_buffer(xprt) = malloc(su->su_iosz)) == NULL)
|
||||
goto freedata;
|
||||
xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
|
||||
XDR_DECODE);
|
||||
su->su_cache = NULL;
|
||||
xprt->xp_fd = fd;
|
||||
xprt->xp_p2 = (caddr_t)(void *)su;
|
||||
xprt->xp_verf.oa_base = su->su_verfbody;
|
||||
svc_dg_ops(xprt);
|
||||
xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
|
||||
|
||||
slen = sizeof ss;
|
||||
if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
|
||||
goto freedata;
|
||||
xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
|
||||
xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage);
|
||||
xprt->xp_ltaddr.len = slen;
|
||||
memcpy(xprt->xp_ltaddr.buf, &ss, slen);
|
||||
|
||||
xprt_register(xprt);
|
||||
return (xprt);
|
||||
freedata:
|
||||
(void) warnx(svc_dg_str, __no_mem_str);
|
||||
if (xprt) {
|
||||
if (su)
|
||||
(void) mem_free(su, sizeof (*su));
|
||||
(void) mem_free(xprt, sizeof (SVCXPRT));
|
||||
}
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static enum xprt_stat
|
||||
svc_dg_stat(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
return (XPRT_IDLE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_dg_recv(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
struct svc_dg_data *su;
|
||||
XDR *xdrs;
|
||||
char *reply;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t alen;
|
||||
size_t replylen;
|
||||
ssize_t rlen;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
su = su_data(xprt);
|
||||
xdrs = &(su->su_xdrs);
|
||||
|
||||
again:
|
||||
alen = sizeof (struct sockaddr_storage);
|
||||
rlen = recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz, 0,
|
||||
(struct sockaddr *)(void *)&ss, &alen);
|
||||
if (rlen == -1 && errno == EINTR)
|
||||
goto again;
|
||||
if (rlen == -1 || (rlen < (ssize_t)(4 * sizeof (u_int32_t))))
|
||||
return (FALSE);
|
||||
if (xprt->xp_rtaddr.len < alen) {
|
||||
if (xprt->xp_rtaddr.len != 0)
|
||||
mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.len);
|
||||
xprt->xp_rtaddr.buf = mem_alloc(alen);
|
||||
xprt->xp_rtaddr.len = alen;
|
||||
}
|
||||
memcpy(xprt->xp_rtaddr.buf, &ss, alen);
|
||||
#ifdef PORTMAP
|
||||
if (ss.ss_family == AF_INET) {
|
||||
xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf;
|
||||
xprt->xp_addrlen = sizeof (struct sockaddr_in);
|
||||
}
|
||||
#endif
|
||||
xdrs->x_op = XDR_DECODE;
|
||||
XDR_SETPOS(xdrs, 0);
|
||||
if (! xdr_callmsg(xdrs, msg)) {
|
||||
return (FALSE);
|
||||
}
|
||||
su->su_xid = msg->rm_xid;
|
||||
if (su->su_cache != NULL) {
|
||||
if (cache_get(xprt, msg, &reply, &replylen)) {
|
||||
(void)sendto(xprt->xp_fd, reply, replylen, 0,
|
||||
(struct sockaddr *)(void *)&ss, alen);
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_dg_reply(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
struct svc_dg_data *su;
|
||||
XDR *xdrs;
|
||||
bool_t stat = FALSE;
|
||||
size_t slen;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
su = su_data(xprt);
|
||||
xdrs = &(su->su_xdrs);
|
||||
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
XDR_SETPOS(xdrs, 0);
|
||||
msg->rm_xid = su->su_xid;
|
||||
if (xdr_replymsg(xdrs, msg)) {
|
||||
slen = XDR_GETPOS(xdrs);
|
||||
if (sendto(xprt->xp_fd, rpc_buffer(xprt), slen, 0,
|
||||
(struct sockaddr *)xprt->xp_rtaddr.buf,
|
||||
(socklen_t)xprt->xp_rtaddr.len) == (ssize_t) slen) {
|
||||
stat = TRUE;
|
||||
if (su->su_cache)
|
||||
cache_set(xprt, slen);
|
||||
}
|
||||
}
|
||||
return (stat);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_dg_getargs(xprt, xdr_args, args_ptr)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_args;
|
||||
caddr_t args_ptr;
|
||||
{
|
||||
return (*xdr_args)(&(su_data(xprt)->su_xdrs), args_ptr);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_dg_freeargs(xprt, xdr_args, args_ptr)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_args;
|
||||
caddr_t args_ptr;
|
||||
{
|
||||
XDR *xdrs;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
xdrs = &(su_data(xprt)->su_xdrs);
|
||||
xdrs->x_op = XDR_FREE;
|
||||
return (*xdr_args)(xdrs, args_ptr);
|
||||
}
|
||||
|
||||
static void
|
||||
svc_dg_destroy(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct svc_dg_data *su;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
su = su_data(xprt);
|
||||
|
||||
xprt_unregister(xprt);
|
||||
if (xprt->xp_fd != -1)
|
||||
(void)close(xprt->xp_fd);
|
||||
XDR_DESTROY(&(su->su_xdrs));
|
||||
(void) mem_free(rpc_buffer(xprt), su->su_iosz);
|
||||
(void) mem_free(su, sizeof (*su));
|
||||
if (xprt->xp_rtaddr.buf)
|
||||
(void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
|
||||
if (xprt->xp_ltaddr.buf)
|
||||
(void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
|
||||
if (xprt->xp_tp)
|
||||
(void) free(xprt->xp_tp);
|
||||
(void) mem_free(xprt, sizeof (SVCXPRT));
|
||||
}
|
||||
|
||||
static bool_t
|
||||
/*ARGSUSED*/
|
||||
svc_dg_control(xprt, rq, in)
|
||||
SVCXPRT *xprt;
|
||||
const u_int rq;
|
||||
void *in;
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
svc_dg_ops(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
static struct xp_ops ops;
|
||||
static struct xp_ops2 ops2;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops */
|
||||
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.xp_recv == NULL) {
|
||||
ops.xp_recv = svc_dg_recv;
|
||||
ops.xp_stat = svc_dg_stat;
|
||||
ops.xp_getargs = svc_dg_getargs;
|
||||
ops.xp_reply = svc_dg_reply;
|
||||
ops.xp_freeargs = svc_dg_freeargs;
|
||||
ops.xp_destroy = svc_dg_destroy;
|
||||
ops2.xp_control = svc_dg_control;
|
||||
}
|
||||
xprt->xp_ops = &ops;
|
||||
xprt->xp_ops2 = &ops2;
|
||||
mutex_unlock(&ops_lock);
|
||||
}
|
||||
|
||||
/* The CACHING COMPONENT */
|
||||
|
||||
/*
|
||||
* Could have been a separate file, but some part of it depends upon the
|
||||
* private structure of the client handle.
|
||||
*
|
||||
* Fifo cache for cl server
|
||||
* Copies pointers to reply buffers into fifo cache
|
||||
* Buffers are sent again if retransmissions are detected.
|
||||
*/
|
||||
|
||||
#define SPARSENESS 4 /* 75% sparse */
|
||||
|
||||
#define ALLOC(type, size) \
|
||||
mem_alloc((sizeof (type) * (size)))
|
||||
|
||||
#define MEMZERO(addr, type, size) \
|
||||
(void) memset((void *) (addr), 0, sizeof (type) * (int) (size))
|
||||
|
||||
#define FREE(addr, type, size) \
|
||||
mem_free((addr), (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_int32_t cache_xid;
|
||||
rpcproc_t cache_proc;
|
||||
rpcvers_t cache_vers;
|
||||
rpcprog_t cache_prog;
|
||||
struct netbuf cache_addr;
|
||||
/*
|
||||
* The cached reply and length
|
||||
*/
|
||||
char *cache_reply;
|
||||
size_t cache_replylen;
|
||||
/*
|
||||
* Next node on the list, if there is a collision
|
||||
*/
|
||||
cache_ptr cache_next;
|
||||
};
|
||||
|
||||
/*
|
||||
* The entire cache
|
||||
*/
|
||||
struct cl_cache {
|
||||
u_int 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_int uc_nextvictim; /* points to next victim in fifo list */
|
||||
rpcprog_t uc_prog; /* saved program number */
|
||||
rpcvers_t uc_vers; /* saved version number */
|
||||
rpcproc_t uc_proc; /* saved procedure number */
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* the hashing function
|
||||
*/
|
||||
#define CACHE_LOC(transp, xid) \
|
||||
(xid % (SPARSENESS * ((struct cl_cache *) \
|
||||
su_data(transp)->su_cache)->uc_size))
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t dupreq_lock;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Enable use of the cache. Returns 1 on success, 0 on failure.
|
||||
* Note: there is no disable.
|
||||
*/
|
||||
static const char cache_enable_str[] = "svc_enablecache: %s %s";
|
||||
static const char alloc_err[] = "could not allocate cache ";
|
||||
static const char enable_err[] = "cache already enabled";
|
||||
|
||||
int
|
||||
svc_dg_enablecache(transp, size)
|
||||
SVCXPRT *transp;
|
||||
u_int size;
|
||||
{
|
||||
struct svc_dg_data *su;
|
||||
struct cl_cache *uc;
|
||||
|
||||
_DIAGASSERT(transp != NULL);
|
||||
|
||||
su = su_data(transp);
|
||||
|
||||
mutex_lock(&dupreq_lock);
|
||||
if (su->su_cache != NULL) {
|
||||
(void) warnx(cache_enable_str, enable_err, " ");
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return (0);
|
||||
}
|
||||
uc = ALLOC(struct cl_cache, 1);
|
||||
if (uc == NULL) {
|
||||
warnx(cache_enable_str, alloc_err, " ");
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return (0);
|
||||
}
|
||||
uc->uc_size = size;
|
||||
uc->uc_nextvictim = 0;
|
||||
uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
|
||||
if (uc->uc_entries == NULL) {
|
||||
warnx(cache_enable_str, alloc_err, "data");
|
||||
FREE(uc, struct cl_cache, 1);
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return (0);
|
||||
}
|
||||
MEMZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
|
||||
uc->uc_fifo = ALLOC(cache_ptr, size);
|
||||
if (uc->uc_fifo == NULL) {
|
||||
warnx(cache_enable_str, alloc_err, "fifo");
|
||||
FREE(uc->uc_entries, cache_ptr, size * SPARSENESS);
|
||||
FREE(uc, struct cl_cache, 1);
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return (0);
|
||||
}
|
||||
MEMZERO(uc->uc_fifo, cache_ptr, size);
|
||||
su->su_cache = (char *)(void *)uc;
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set an entry in the cache. It assumes that the uc entry is set from
|
||||
* the earlier call to cache_get() for the same procedure. This will always
|
||||
* happen because cache_get() is calle by svc_dg_recv and cache_set() is called
|
||||
* by svc_dg_reply(). All this hoopla because the right RPC parameters are
|
||||
* not available at svc_dg_reply time.
|
||||
*/
|
||||
|
||||
static const char cache_set_str[] = "cache_set: %s";
|
||||
static const char cache_set_err1[] = "victim not found";
|
||||
static const char cache_set_err2[] = "victim alloc failed";
|
||||
static const char cache_set_err3[] = "could not allocate new rpc buffer";
|
||||
|
||||
static void
|
||||
cache_set(xprt, replylen)
|
||||
SVCXPRT *xprt;
|
||||
size_t replylen;
|
||||
{
|
||||
cache_ptr victim;
|
||||
cache_ptr *vicp;
|
||||
struct svc_dg_data *su;
|
||||
struct cl_cache *uc;
|
||||
u_int loc;
|
||||
char *newbuf;
|
||||
#ifdef RPC_CACHE_DEBUG
|
||||
struct netconfig *nconf;
|
||||
char *uaddr;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
su = su_data(xprt);
|
||||
uc = (struct cl_cache *) su->su_cache;
|
||||
|
||||
mutex_lock(&dupreq_lock);
|
||||
/*
|
||||
* 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) {
|
||||
warnx(cache_set_str, cache_set_err1);
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return;
|
||||
}
|
||||
*vicp = victim->cache_next; /* remove from cache */
|
||||
newbuf = victim->cache_reply;
|
||||
} else {
|
||||
victim = ALLOC(struct cache_node, 1);
|
||||
if (victim == NULL) {
|
||||
warnx(cache_set_str, cache_set_err2);
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return;
|
||||
}
|
||||
newbuf = mem_alloc(su->su_iosz);
|
||||
if (newbuf == NULL) {
|
||||
warnx(cache_set_str, cache_set_err3);
|
||||
FREE(victim, struct cache_node, 1);
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Store it away
|
||||
*/
|
||||
#ifdef RPC_CACHE_DEBUG
|
||||
if (nconf = getnetconfigent(xprt->xp_netid)) {
|
||||
uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
|
||||
freenetconfigent(nconf);
|
||||
printf(
|
||||
"cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
|
||||
su->su_xid, uc->uc_prog, uc->uc_vers,
|
||||
uc->uc_proc, uaddr);
|
||||
free(uaddr);
|
||||
}
|
||||
#endif
|
||||
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 = xprt->xp_rtaddr;
|
||||
victim->cache_addr.buf = ALLOC(char, xprt->xp_rtaddr.len);
|
||||
(void) memcpy(victim->cache_addr.buf, xprt->xp_rtaddr.buf,
|
||||
(size_t)xprt->xp_rtaddr.len);
|
||||
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;
|
||||
mutex_unlock(&dupreq_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to get an entry from the cache
|
||||
* return 1 if found, 0 if not found and set the stage for cache_set()
|
||||
*/
|
||||
static int
|
||||
cache_get(xprt, msg, replyp, replylenp)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
char **replyp;
|
||||
size_t *replylenp;
|
||||
{
|
||||
u_int loc;
|
||||
cache_ptr ent;
|
||||
struct svc_dg_data *su;
|
||||
struct cl_cache *uc;
|
||||
#ifdef RPC_CACHE_DEBUG
|
||||
struct netconfig *nconf;
|
||||
char *uaddr;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
_DIAGASSERT(replyp != NULL);
|
||||
_DIAGASSERT(replylenp != NULL);
|
||||
|
||||
su = su_data(xprt);
|
||||
uc = (struct cl_cache *) su->su_cache;
|
||||
|
||||
mutex_lock(&dupreq_lock);
|
||||
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 == msg->rm_call.cb_proc &&
|
||||
ent->cache_vers == msg->rm_call.cb_vers &&
|
||||
ent->cache_prog == msg->rm_call.cb_prog &&
|
||||
ent->cache_addr.len == xprt->xp_rtaddr.len &&
|
||||
(memcmp(ent->cache_addr.buf, xprt->xp_rtaddr.buf,
|
||||
xprt->xp_rtaddr.len) == 0)) {
|
||||
#ifdef RPC_CACHE_DEBUG
|
||||
if (nconf = getnetconfigent(xprt->xp_netid)) {
|
||||
uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
|
||||
freenetconfigent(nconf);
|
||||
printf(
|
||||
"cache entry found for xid=%x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
|
||||
su->su_xid, msg->rm_call.cb_prog,
|
||||
msg->rm_call.cb_vers,
|
||||
msg->rm_call.cb_proc, uaddr);
|
||||
free(uaddr);
|
||||
}
|
||||
#endif
|
||||
*replyp = ent->cache_reply;
|
||||
*replylenp = ent->cache_replylen;
|
||||
mutex_unlock(&dupreq_lock);
|
||||
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;
|
||||
mutex_unlock(&dupreq_lock);
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
/* $NetBSD: svc_dg.h,v 1.1 2000/06/02 23:11:16 fvdl Exp $ */
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* XXX - this file exists only so that the rpcbind code can pull it in.
|
||||
* This should go away. It should only be include by svc_dg.c and
|
||||
* rpcb_svc_com.c in the rpcbind code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* kept in xprt->xp_p2
|
||||
*/
|
||||
struct svc_dg_data {
|
||||
/* XXX: optbuf should be the first field, used by ti_opts.c code */
|
||||
size_t su_iosz; /* size of send.recv buffer */
|
||||
u_int32_t su_xid; /* transaction id */
|
||||
XDR su_xdrs; /* XDR handle */
|
||||
char su_verfbody[MAX_AUTH_BYTES]; /* verifier body */
|
||||
void *su_cache; /* cached data, NULL if none */
|
||||
};
|
||||
|
||||
#define __rpcb_get_dg_xidp(x) (&((struct svc_dg_data *)(x)->xp_p2)->su_xid)
|
||||
@@ -0,0 +1,320 @@
|
||||
/* $NetBSD: svc_generic.c,v 1.10 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)svc_generic.c 1.19 94/04/24 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc_generic.c,v 1.10 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* svc_generic.c, Server side for RPC.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/nettype.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <err.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_create,_svc_create)
|
||||
__weak_alias(svc_tp_create,_svc_tp_create)
|
||||
__weak_alias(svc_tli_create,_svc_tli_create)
|
||||
#endif
|
||||
|
||||
extern int __svc_vc_setflag __P((SVCXPRT *, int));
|
||||
|
||||
/*
|
||||
* The highest level interface for server creation.
|
||||
* It tries for all the nettokens in that particular class of token
|
||||
* and returns the number of handles it can create and/or find.
|
||||
*
|
||||
* It creates a link list of all the handles it could create.
|
||||
* If svc_create() is called multiple times, it uses the handle
|
||||
* created earlier instead of creating a new handle every time.
|
||||
*/
|
||||
int
|
||||
svc_create(dispatch, prognum, versnum, nettype)
|
||||
void (*dispatch) __P((struct svc_req *, SVCXPRT *));
|
||||
rpcprog_t prognum; /* Program number */
|
||||
rpcvers_t versnum; /* Version number */
|
||||
const char *nettype; /* Networktype token */
|
||||
{
|
||||
struct xlist {
|
||||
SVCXPRT *xprt; /* Server handle */
|
||||
struct xlist *next; /* Next item */
|
||||
} *l;
|
||||
static struct xlist *xprtlist; /* A link list of all the handles */
|
||||
int num = 0;
|
||||
SVCXPRT *xprt;
|
||||
struct netconfig *nconf;
|
||||
void *handle;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t xprtlist_lock;
|
||||
#endif
|
||||
|
||||
/* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
|
||||
|
||||
if ((handle = __rpc_setconf(nettype)) == NULL) {
|
||||
warnx("svc_create: unknown protocol");
|
||||
return (0);
|
||||
}
|
||||
while ((nconf = __rpc_getconf(handle)) != NULL) {
|
||||
mutex_lock(&xprtlist_lock);
|
||||
for (l = xprtlist; l; l = l->next) {
|
||||
if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) {
|
||||
/* Found an old one, use it */
|
||||
(void) rpcb_unset(prognum, versnum, nconf);
|
||||
if (svc_reg(l->xprt, prognum, versnum,
|
||||
dispatch, nconf) == FALSE)
|
||||
warnx(
|
||||
"svc_create: could not register prog %u vers %u on %s",
|
||||
(unsigned)prognum, (unsigned)versnum,
|
||||
nconf->nc_netid);
|
||||
else
|
||||
num++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (l == NULL) {
|
||||
/* It was not found. Now create a new one */
|
||||
xprt = svc_tp_create(dispatch, prognum, versnum, nconf);
|
||||
if (xprt) {
|
||||
l = malloc(sizeof(*l));
|
||||
if (l == NULL) {
|
||||
warnx("svc_create: no memory");
|
||||
mutex_unlock(&xprtlist_lock);
|
||||
return (0);
|
||||
}
|
||||
l->xprt = xprt;
|
||||
l->next = xprtlist;
|
||||
xprtlist = l;
|
||||
num++;
|
||||
}
|
||||
}
|
||||
mutex_unlock(&xprtlist_lock);
|
||||
}
|
||||
__rpc_endconf(handle);
|
||||
/*
|
||||
* In case of num == 0; the error messages are generated by the
|
||||
* underlying layers; and hence not needed here.
|
||||
*/
|
||||
return (num);
|
||||
}
|
||||
|
||||
/*
|
||||
* The high level interface to svc_tli_create().
|
||||
* It tries to create a server for "nconf" and registers the service
|
||||
* with the rpcbind. It calls svc_tli_create();
|
||||
*/
|
||||
SVCXPRT *
|
||||
svc_tp_create(dispatch, prognum, versnum, nconf)
|
||||
void (*dispatch) __P((struct svc_req *, SVCXPRT *));
|
||||
rpcprog_t prognum; /* Program number */
|
||||
rpcvers_t versnum; /* Version number */
|
||||
const struct netconfig *nconf; /* Netconfig structure for the network */
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
|
||||
if (nconf == NULL) {
|
||||
warnx(
|
||||
"svc_tp_create: invalid netconfig structure for prog %u vers %u",
|
||||
(unsigned)prognum, (unsigned)versnum);
|
||||
return (NULL);
|
||||
}
|
||||
xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
|
||||
if (xprt == NULL) {
|
||||
return (NULL);
|
||||
}
|
||||
(void) rpcb_unset(prognum, versnum, __UNCONST(nconf));
|
||||
if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
|
||||
warnx(
|
||||
"svc_tp_create: Could not register prog %u vers %u on %s",
|
||||
(unsigned)prognum, (unsigned)versnum,
|
||||
nconf->nc_netid);
|
||||
SVC_DESTROY(xprt);
|
||||
return (NULL);
|
||||
}
|
||||
return (xprt);
|
||||
}
|
||||
|
||||
/*
|
||||
* If fd is RPC_ANYFD, then it opens a fd for the given transport
|
||||
* provider (nconf cannot be NULL then). If the t_state is T_UNBND and
|
||||
* bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
|
||||
* NULL bindadr and Connection oriented transports, the value of qlen
|
||||
* is set to 8.
|
||||
*
|
||||
* If sendsz or recvsz are zero, their default values are chosen.
|
||||
*/
|
||||
SVCXPRT *
|
||||
svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
|
||||
int fd; /* Connection end point */
|
||||
const struct netconfig *nconf; /* Netconfig struct for nettoken */
|
||||
const struct t_bind *bindaddr; /* Local bind address */
|
||||
u_int sendsz; /* Max sendsize */
|
||||
u_int recvsz; /* Max recvsize */
|
||||
{
|
||||
SVCXPRT *xprt = NULL; /* service handle */
|
||||
bool_t madefd = FALSE; /* whether fd opened here */
|
||||
struct __rpc_sockinfo si;
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t slen;
|
||||
|
||||
if (fd == RPC_ANYFD) {
|
||||
if (nconf == NULL) {
|
||||
warnx("svc_tli_create: invalid netconfig");
|
||||
return (NULL);
|
||||
}
|
||||
fd = __rpc_nconf2fd(nconf);
|
||||
if (fd == -1) {
|
||||
warnx(
|
||||
"svc_tli_create: could not open connection for %s",
|
||||
nconf->nc_netid);
|
||||
return (NULL);
|
||||
}
|
||||
__rpc_nconf2sockinfo(nconf, &si);
|
||||
madefd = TRUE;
|
||||
} else {
|
||||
/*
|
||||
* It is an open descriptor. Get the transport info.
|
||||
*/
|
||||
if (!__rpc_fd2sockinfo(fd, &si)) {
|
||||
warnx(
|
||||
"svc_tli_create: could not get transport information");
|
||||
return (NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* If the fd is unbound, try to bind it.
|
||||
*/
|
||||
if (madefd || !__rpc_sockisbound(fd)) {
|
||||
if (bindaddr == NULL) {
|
||||
if (bindresvport(fd, NULL) < 0) {
|
||||
memset(&ss, 0, sizeof ss);
|
||||
ss.ss_family = si.si_af;
|
||||
ss.ss_len = si.si_alen;
|
||||
if (bind(fd, (struct sockaddr *)(void *)&ss,
|
||||
(socklen_t)si.si_alen) < 0) {
|
||||
warnx(
|
||||
"svc_tli_create: could not bind to anonymous port");
|
||||
goto freedata;
|
||||
}
|
||||
}
|
||||
listen(fd, SOMAXCONN);
|
||||
} else {
|
||||
if (bind(fd,
|
||||
(struct sockaddr *)bindaddr->addr.buf,
|
||||
(socklen_t)si.si_alen) < 0) {
|
||||
warnx(
|
||||
"svc_tli_create: could not bind to requested address");
|
||||
goto freedata;
|
||||
}
|
||||
listen(fd, (int)bindaddr->qlen);
|
||||
}
|
||||
|
||||
}
|
||||
/*
|
||||
* call transport specific function.
|
||||
*/
|
||||
switch (si.si_socktype) {
|
||||
case SOCK_STREAM:
|
||||
slen = sizeof ss;
|
||||
if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
|
||||
== 0) {
|
||||
/* accepted socket */
|
||||
xprt = svc_fd_create(fd, sendsz, recvsz);
|
||||
} else
|
||||
xprt = svc_vc_create(fd, sendsz, recvsz);
|
||||
if (!nconf || !xprt)
|
||||
break;
|
||||
#if 0
|
||||
/* XXX fvdl */
|
||||
if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
|
||||
strcmp(nconf->nc_protofmly, "inet6") == 0)
|
||||
(void) __svc_vc_setflag(xprt, TRUE);
|
||||
#endif
|
||||
break;
|
||||
case SOCK_DGRAM:
|
||||
xprt = svc_dg_create(fd, sendsz, recvsz);
|
||||
break;
|
||||
default:
|
||||
warnx("svc_tli_create: bad service type");
|
||||
goto freedata;
|
||||
}
|
||||
|
||||
if (xprt == NULL)
|
||||
/*
|
||||
* The error messages here are spitted out by the lower layers:
|
||||
* svc_vc_create(), svc_fd_create() and svc_dg_create().
|
||||
*/
|
||||
goto freedata;
|
||||
|
||||
/* Fill in type of service */
|
||||
xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
|
||||
|
||||
if (nconf) {
|
||||
xprt->xp_netid = strdup(nconf->nc_netid);
|
||||
xprt->xp_tp = strdup(nconf->nc_device);
|
||||
if (xprt->xp_netid == NULL || xprt->xp_tp == NULL) {
|
||||
svc_destroy(xprt);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return (xprt);
|
||||
|
||||
freedata:
|
||||
if (madefd)
|
||||
(void) close(fd);
|
||||
return (NULL);
|
||||
}
|
||||
@@ -0,0 +1,277 @@
|
||||
/* $NetBSD: svc_raw.c,v 1.21 2008/05/24 15:59:59 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #ident "@(#)svc_raw.c 1.16 94/04/24 SMI" */
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char sccsid[] = "@(#)svc_raw.c 1.25 89/01/31 Copyr 1984 Sun Micro";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc_raw.c,v 1.21 2008/05/24 15:59:59 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* svc_raw.c, This a toy for simple testing and timing.
|
||||
* Interface to create an rpc client and server in the same UNIX process.
|
||||
* This lets us similate rpc and get rpc (round trip) overhead, without
|
||||
* any interference from the kernel.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <rpc/rpc.h>
|
||||
#include <sys/types.h>
|
||||
#include <rpc/raw.h>
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_raw_create,_svc_raw_create)
|
||||
#endif
|
||||
|
||||
#ifndef UDPMSGSIZE
|
||||
#define UDPMSGSIZE 8800
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the "network" that we will be moving data over
|
||||
*/
|
||||
static struct svc_raw_private {
|
||||
char *raw_buf; /* should be shared with the cl handle */
|
||||
SVCXPRT server;
|
||||
XDR xdr_stream;
|
||||
char verf_body[MAX_AUTH_BYTES];
|
||||
} *svc_raw_private;
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t svcraw_lock;
|
||||
#endif
|
||||
|
||||
static enum xprt_stat svc_raw_stat __P((SVCXPRT *));
|
||||
static bool_t svc_raw_recv __P((SVCXPRT *, struct rpc_msg *));
|
||||
static bool_t svc_raw_reply __P((SVCXPRT *, struct rpc_msg *));
|
||||
static bool_t svc_raw_getargs __P((SVCXPRT *, xdrproc_t, caddr_t));
|
||||
static bool_t svc_raw_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t));
|
||||
static void svc_raw_destroy __P((SVCXPRT *));
|
||||
static void svc_raw_ops __P((SVCXPRT *));
|
||||
static bool_t svc_raw_control __P((SVCXPRT *, const u_int, void *));
|
||||
|
||||
char *__rpc_rawcombuf = NULL;
|
||||
|
||||
SVCXPRT *
|
||||
svc_raw_create()
|
||||
{
|
||||
struct svc_raw_private *srp;
|
||||
/* VARIABLES PROTECTED BY svcraw_lock: svc_raw_private, srp */
|
||||
|
||||
mutex_lock(&svcraw_lock);
|
||||
srp = svc_raw_private;
|
||||
if (srp == NULL) {
|
||||
srp = calloc(1, sizeof(*srp));
|
||||
if (srp == NULL)
|
||||
goto out;
|
||||
if (__rpc_rawcombuf == NULL)
|
||||
__rpc_rawcombuf = malloc(UDPMSGSIZE);
|
||||
if (__rpc_rawcombuf == NULL)
|
||||
goto out;
|
||||
srp->raw_buf = __rpc_rawcombuf; /* Share it with the client */
|
||||
svc_raw_private = srp;
|
||||
}
|
||||
srp->server.xp_fd = FD_SETSIZE;
|
||||
srp->server.xp_port = 0;
|
||||
srp->server.xp_p3 = NULL;
|
||||
svc_raw_ops(&srp->server);
|
||||
srp->server.xp_verf.oa_base = srp->verf_body;
|
||||
xdrmem_create(&srp->xdr_stream, srp->raw_buf, UDPMSGSIZE, XDR_DECODE);
|
||||
xprt_register(&srp->server);
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (&srp->server);
|
||||
out:
|
||||
if (srp != NULL)
|
||||
free(srp);
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static enum xprt_stat
|
||||
svc_raw_stat(xprt)
|
||||
SVCXPRT *xprt; /* args needed to satisfy ANSI-C typechecking */
|
||||
{
|
||||
return (XPRT_IDLE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_raw_recv(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
struct svc_raw_private *srp;
|
||||
XDR *xdrs;
|
||||
|
||||
mutex_lock(&svcraw_lock);
|
||||
srp = svc_raw_private;
|
||||
if (srp == NULL) {
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (FALSE);
|
||||
}
|
||||
mutex_unlock(&svcraw_lock);
|
||||
|
||||
xdrs = &srp->xdr_stream;
|
||||
xdrs->x_op = XDR_DECODE;
|
||||
(void) XDR_SETPOS(xdrs, 0);
|
||||
if (! xdr_callmsg(xdrs, msg)) {
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_raw_reply(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
struct svc_raw_private *srp;
|
||||
XDR *xdrs;
|
||||
|
||||
mutex_lock(&svcraw_lock);
|
||||
srp = svc_raw_private;
|
||||
if (srp == NULL) {
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (FALSE);
|
||||
}
|
||||
mutex_unlock(&svcraw_lock);
|
||||
|
||||
xdrs = &srp->xdr_stream;
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
(void) XDR_SETPOS(xdrs, 0);
|
||||
if (! xdr_replymsg(xdrs, msg)) {
|
||||
return (FALSE);
|
||||
}
|
||||
(void) XDR_GETPOS(xdrs); /* called just for overhead */
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_raw_getargs(xprt, xdr_args, args_ptr)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_args;
|
||||
caddr_t args_ptr;
|
||||
{
|
||||
struct svc_raw_private *srp;
|
||||
|
||||
mutex_lock(&svcraw_lock);
|
||||
srp = svc_raw_private;
|
||||
if (srp == NULL) {
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (FALSE);
|
||||
}
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (*xdr_args)(&srp->xdr_stream, args_ptr);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_raw_freeargs(xprt, xdr_args, args_ptr)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_args;
|
||||
caddr_t args_ptr;
|
||||
{
|
||||
struct svc_raw_private *srp;
|
||||
XDR *xdrs;
|
||||
|
||||
mutex_lock(&svcraw_lock);
|
||||
srp = svc_raw_private;
|
||||
if (srp == NULL) {
|
||||
mutex_unlock(&svcraw_lock);
|
||||
return (FALSE);
|
||||
}
|
||||
mutex_unlock(&svcraw_lock);
|
||||
|
||||
xdrs = &srp->xdr_stream;
|
||||
xdrs->x_op = XDR_FREE;
|
||||
return (*xdr_args)(xdrs, args_ptr);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
svc_raw_destroy(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_raw_control(xprt, rq, in)
|
||||
SVCXPRT *xprt;
|
||||
const u_int rq;
|
||||
void *in;
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
svc_raw_ops(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
static struct xp_ops ops;
|
||||
static struct xp_ops2 ops2;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops */
|
||||
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.xp_recv == NULL) {
|
||||
ops.xp_recv = svc_raw_recv;
|
||||
ops.xp_stat = svc_raw_stat;
|
||||
ops.xp_getargs = svc_raw_getargs;
|
||||
ops.xp_reply = svc_raw_reply;
|
||||
ops.xp_freeargs = svc_raw_freeargs;
|
||||
ops.xp_destroy = svc_raw_destroy;
|
||||
ops2.xp_control = svc_raw_control;
|
||||
}
|
||||
xprt->xp_ops = &ops;
|
||||
xprt->xp_ops2 = &ops2;
|
||||
mutex_unlock(&ops_lock);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/* $NetBSD: svc_run.c,v 1.19 2003/01/18 11:29:07 thorpej Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc_run.c,v 1.19 2003/01/18 11:29:07 thorpej Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is the rpc server side idle loop
|
||||
* Wait for input, call server program.
|
||||
*/
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_run,_svc_run)
|
||||
__weak_alias(svc_exit,_svc_exit)
|
||||
#endif
|
||||
|
||||
void
|
||||
svc_run()
|
||||
{
|
||||
fd_set readfds, cleanfds;
|
||||
struct timeval timeout;
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t svc_fd_lock;
|
||||
#endif
|
||||
|
||||
timeout.tv_sec = 30;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
for (;;) {
|
||||
rwlock_rdlock(&svc_fd_lock);
|
||||
readfds = svc_fdset;
|
||||
cleanfds = svc_fdset;
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
switch (select(svc_maxfd+1, &readfds, NULL, NULL, &timeout)) {
|
||||
case -1:
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
warn("svc_run: - select failed");
|
||||
return;
|
||||
case 0:
|
||||
__svc_clean_idle(&cleanfds, 30, FALSE);
|
||||
continue;
|
||||
default:
|
||||
svc_getreqset(&readfds);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This function causes svc_run() to exit by telling it that it has no
|
||||
* more work to do.
|
||||
*/
|
||||
void
|
||||
svc_exit()
|
||||
{
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t svc_fd_lock;
|
||||
#endif
|
||||
|
||||
rwlock_wrlock(&svc_fd_lock);
|
||||
FD_ZERO(&svc_fdset);
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
/* $NetBSD: svc_simple.c,v 1.30 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1986-1991 by Sun Microsystems Inc.
|
||||
*/
|
||||
|
||||
/* #pragma ident "@(#)svc_simple.c 1.18 94/04/24 SMI" */
|
||||
|
||||
/*
|
||||
* svc_simple.c
|
||||
* Simplified front end to rpc.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This interface creates a virtual listener for all the services
|
||||
* started thru rpc_reg(). It listens on the same endpoint for
|
||||
* all the services and then executes the corresponding service
|
||||
* for the given prognum and procnum.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
__RCSID("$NetBSD: svc_simple.c,v 1.30 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <rpc/rpc.h>
|
||||
#include <rpc/nettype.h>
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(rpc_reg,_rpc_reg)
|
||||
#endif
|
||||
|
||||
static void universal __P((struct svc_req *, SVCXPRT *));
|
||||
|
||||
static struct proglst {
|
||||
char *(*p_progname) __P((char *));
|
||||
rpcprog_t p_prognum;
|
||||
rpcvers_t p_versnum;
|
||||
rpcproc_t p_procnum;
|
||||
SVCXPRT *p_transp;
|
||||
char *p_netid;
|
||||
char *p_xdrbuf;
|
||||
int p_recvsz;
|
||||
xdrproc_t p_inproc, p_outproc;
|
||||
struct proglst *p_nxt;
|
||||
} *proglst;
|
||||
|
||||
static const char rpc_reg_err[] = "%s: %s";
|
||||
static const char rpc_reg_msg[] = "rpc_reg: ";
|
||||
static const char __reg_err1[] = "can't find appropriate transport";
|
||||
static const char __reg_err2[] = "can't get protocol info";
|
||||
static const char __reg_err3[] = "unsupported transport size";
|
||||
static const char __no_mem_str[] = "out of memory";
|
||||
|
||||
/*
|
||||
* For simplified, easy to use kind of rpc interfaces.
|
||||
* nettype indicates the type of transport on which the service will be
|
||||
* listening. Used for conservation of the system resource. Only one
|
||||
* handle is created for all the services (actually one of each netid)
|
||||
* and same xdrbuf is used for same netid. The size of the arguments
|
||||
* is also limited by the recvsize for that transport, even if it is
|
||||
* a COTS transport. This may be wrong, but for cases like these, they
|
||||
* should not use the simplified interfaces like this.
|
||||
*/
|
||||
|
||||
int
|
||||
rpc_reg(prognum, versnum, procnum, progname, inproc, outproc, nettype)
|
||||
rpcprog_t prognum; /* program number */
|
||||
rpcvers_t versnum; /* version number */
|
||||
rpcproc_t procnum; /* procedure number */
|
||||
char *(*progname) __P((char *)); /* Server routine */
|
||||
xdrproc_t inproc, outproc; /* in/out XDR procedures */
|
||||
char *nettype; /* nettype */
|
||||
{
|
||||
struct netconfig *nconf;
|
||||
int done = FALSE;
|
||||
void *handle;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t proglst_lock;
|
||||
#endif
|
||||
|
||||
if (procnum == NULLPROC) {
|
||||
warnx("%s can't reassign procedure number %u", rpc_reg_msg,
|
||||
NULLPROC);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
if (nettype == NULL)
|
||||
nettype = __UNCONST("netpath"); /* The default behavior */
|
||||
if ((handle = __rpc_setconf(nettype)) == NULL) {
|
||||
warnx(rpc_reg_err, rpc_reg_msg, __reg_err1);
|
||||
return (-1);
|
||||
}
|
||||
/* VARIABLES PROTECTED BY proglst_lock: proglst */
|
||||
mutex_lock(&proglst_lock);
|
||||
while ((nconf = __rpc_getconf(handle)) != NULL) {
|
||||
struct proglst *pl;
|
||||
SVCXPRT *svcxprt;
|
||||
int madenow;
|
||||
u_int recvsz;
|
||||
char *xdrbuf;
|
||||
char *netid;
|
||||
|
||||
madenow = FALSE;
|
||||
svcxprt = NULL;
|
||||
recvsz = 0;
|
||||
xdrbuf = NULL;
|
||||
netid = NULL;
|
||||
for (pl = proglst; pl; pl = pl->p_nxt)
|
||||
if (strcmp(pl->p_netid, nconf->nc_netid) == 0) {
|
||||
svcxprt = pl->p_transp;
|
||||
xdrbuf = pl->p_xdrbuf;
|
||||
recvsz = pl->p_recvsz;
|
||||
netid = pl->p_netid;
|
||||
break;
|
||||
}
|
||||
|
||||
if (svcxprt == NULL) {
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
|
||||
if (svcxprt == NULL)
|
||||
continue;
|
||||
if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) {
|
||||
warnx(rpc_reg_err, rpc_reg_msg, __reg_err2);
|
||||
SVC_DESTROY(svcxprt);
|
||||
continue;
|
||||
}
|
||||
recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0);
|
||||
if (recvsz == 0) {
|
||||
warnx(rpc_reg_err, rpc_reg_msg, __reg_err3);
|
||||
SVC_DESTROY(svcxprt);
|
||||
continue;
|
||||
}
|
||||
if (((xdrbuf = malloc((size_t)recvsz)) == NULL) ||
|
||||
((netid = strdup(nconf->nc_netid)) == NULL)) {
|
||||
warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
|
||||
if (xdrbuf != NULL)
|
||||
free(xdrbuf);
|
||||
if (netid != NULL)
|
||||
free(netid);
|
||||
SVC_DESTROY(svcxprt);
|
||||
break;
|
||||
}
|
||||
madenow = TRUE;
|
||||
}
|
||||
/*
|
||||
* Check if this (program, version, netid) had already been
|
||||
* registered. The check may save a few RPC calls to rpcbind
|
||||
*/
|
||||
for (pl = proglst; pl; pl = pl->p_nxt)
|
||||
if ((pl->p_prognum == prognum) &&
|
||||
(pl->p_versnum == versnum) &&
|
||||
(strcmp(pl->p_netid, netid) == 0))
|
||||
break;
|
||||
if (pl == NULL) { /* Not yet */
|
||||
(void) rpcb_unset(prognum, versnum, nconf);
|
||||
} else {
|
||||
/* so that svc_reg does not call rpcb_set() */
|
||||
nconf = NULL;
|
||||
}
|
||||
|
||||
if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) {
|
||||
warnx("%s couldn't register prog %u vers %u for %s",
|
||||
rpc_reg_msg, (unsigned)prognum,
|
||||
(unsigned)versnum, netid);
|
||||
if (madenow) {
|
||||
SVC_DESTROY(svcxprt);
|
||||
free(xdrbuf);
|
||||
free(netid);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
pl = malloc(sizeof(*pl));
|
||||
if (pl == NULL) {
|
||||
warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
|
||||
if (madenow) {
|
||||
SVC_DESTROY(svcxprt);
|
||||
free(xdrbuf);
|
||||
free(netid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pl->p_progname = progname;
|
||||
pl->p_prognum = prognum;
|
||||
pl->p_versnum = versnum;
|
||||
pl->p_procnum = procnum;
|
||||
pl->p_inproc = inproc;
|
||||
pl->p_outproc = outproc;
|
||||
pl->p_transp = svcxprt;
|
||||
pl->p_xdrbuf = xdrbuf;
|
||||
pl->p_recvsz = recvsz;
|
||||
pl->p_netid = netid;
|
||||
pl->p_nxt = proglst;
|
||||
proglst = pl;
|
||||
done = TRUE;
|
||||
}
|
||||
__rpc_endconf(handle);
|
||||
mutex_unlock(&proglst_lock);
|
||||
|
||||
if (done == FALSE) {
|
||||
warnx("%s cant find suitable transport for %s",
|
||||
rpc_reg_msg, nettype);
|
||||
return (-1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* The universal handler for the services registered using registerrpc.
|
||||
* It handles both the connectionless and the connection oriented cases.
|
||||
*/
|
||||
|
||||
static void
|
||||
universal(rqstp, transp)
|
||||
struct svc_req *rqstp;
|
||||
SVCXPRT *transp;
|
||||
{
|
||||
rpcprog_t prog;
|
||||
rpcvers_t vers;
|
||||
rpcproc_t proc;
|
||||
char *outdata;
|
||||
char *xdrbuf;
|
||||
struct proglst *pl;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t proglst_lock;
|
||||
#endif
|
||||
|
||||
_DIAGASSERT(rqstp != NULL);
|
||||
_DIAGASSERT(transp != NULL);
|
||||
|
||||
/*
|
||||
* enforce "procnum 0 is echo" convention
|
||||
*/
|
||||
if (rqstp->rq_proc == NULLPROC) {
|
||||
if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) ==
|
||||
FALSE) {
|
||||
warnx("svc_sendreply failed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
prog = rqstp->rq_prog;
|
||||
vers = rqstp->rq_vers;
|
||||
proc = rqstp->rq_proc;
|
||||
mutex_lock(&proglst_lock);
|
||||
for (pl = proglst; pl; pl = pl->p_nxt)
|
||||
if (pl->p_prognum == prog && pl->p_procnum == proc &&
|
||||
pl->p_versnum == vers &&
|
||||
(strcmp(pl->p_netid, transp->xp_netid) == 0)) {
|
||||
/* decode arguments into a CLEAN buffer */
|
||||
xdrbuf = pl->p_xdrbuf;
|
||||
/* Zero the arguments: reqd ! */
|
||||
(void) memset(xdrbuf, 0, (size_t)pl->p_recvsz);
|
||||
/*
|
||||
* Assuming that sizeof (xdrbuf) would be enough
|
||||
* for the arguments; if not then the program
|
||||
* may bomb. BEWARE!
|
||||
*/
|
||||
if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
|
||||
svcerr_decode(transp);
|
||||
mutex_unlock(&proglst_lock);
|
||||
return;
|
||||
}
|
||||
outdata = (*(pl->p_progname))(xdrbuf);
|
||||
if (outdata == NULL &&
|
||||
pl->p_outproc != (xdrproc_t) xdr_void){
|
||||
/* there was an error */
|
||||
mutex_unlock(&proglst_lock);
|
||||
return;
|
||||
}
|
||||
if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
|
||||
warnx(
|
||||
"rpc: rpc_reg trouble replying to prog %u vers %u",
|
||||
(unsigned)prog, (unsigned)vers);
|
||||
mutex_unlock(&proglst_lock);
|
||||
return;
|
||||
}
|
||||
/* free the decoded arguments */
|
||||
(void) svc_freeargs(transp, pl->p_inproc, xdrbuf);
|
||||
mutex_unlock(&proglst_lock);
|
||||
return;
|
||||
}
|
||||
mutex_unlock(&proglst_lock);
|
||||
/* This should never happen */
|
||||
warnx("rpc: rpc_reg: never registered prog %u vers %u",
|
||||
(unsigned)prog, (unsigned)vers);
|
||||
return;
|
||||
}
|
||||
@@ -0,0 +1,839 @@
|
||||
/* $NetBSD: svc_vc.c,v 1.22 2009/02/12 04:38:52 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: svc_vc.c,v 1.22 2009/02/12 04:38:52 lukem Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* svc_vc.c, Server side for Connection Oriented based RPC.
|
||||
*
|
||||
* Actually implements two flavors of transporter -
|
||||
* a tcp rendezvouser (a listner and connection establisher)
|
||||
* and a record/tcp stream.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
#include "reentrant.h"
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/poll.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/time.h>
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <rpc/rpc.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(svc_fd_create,_svc_fd_create)
|
||||
__weak_alias(svc_vc_create,_svc_vc_create)
|
||||
#endif
|
||||
|
||||
#ifdef _REENTRANT
|
||||
extern rwlock_t svc_fd_lock;
|
||||
#endif
|
||||
|
||||
static SVCXPRT *makefd_xprt __P((int, u_int, u_int));
|
||||
static bool_t rendezvous_request __P((SVCXPRT *, struct rpc_msg *));
|
||||
static enum xprt_stat rendezvous_stat __P((SVCXPRT *));
|
||||
static void svc_vc_destroy __P((SVCXPRT *));
|
||||
static void __svc_vc_dodestroy __P((SVCXPRT *));
|
||||
static int read_vc __P((caddr_t, caddr_t, int));
|
||||
static int write_vc __P((caddr_t, caddr_t, int));
|
||||
static enum xprt_stat svc_vc_stat __P((SVCXPRT *));
|
||||
static bool_t svc_vc_recv __P((SVCXPRT *, struct rpc_msg *));
|
||||
static bool_t svc_vc_getargs __P((SVCXPRT *, xdrproc_t, caddr_t));
|
||||
static bool_t svc_vc_freeargs __P((SVCXPRT *, xdrproc_t, caddr_t));
|
||||
static bool_t svc_vc_reply __P((SVCXPRT *, struct rpc_msg *));
|
||||
static void svc_vc_rendezvous_ops __P((SVCXPRT *));
|
||||
static void svc_vc_ops __P((SVCXPRT *));
|
||||
static bool_t svc_vc_control __P((SVCXPRT *, const u_int, void *));
|
||||
static bool_t svc_vc_rendezvous_control __P((SVCXPRT *, const u_int,
|
||||
void *));
|
||||
|
||||
struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
int maxrec;
|
||||
};
|
||||
|
||||
struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
|
||||
enum xprt_stat strm_stat;
|
||||
u_int32_t x_id;
|
||||
XDR xdrs;
|
||||
char verf_body[MAX_AUTH_BYTES];
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
int maxrec;
|
||||
bool_t nonblock;
|
||||
struct timeval last_recv_time;
|
||||
};
|
||||
|
||||
/*
|
||||
* Usage:
|
||||
* xprt = svc_vc_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.
|
||||
*
|
||||
* The filedescriptor passed in is expected to refer to a bound, but
|
||||
* not yet connected socket.
|
||||
*
|
||||
* Since 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 *
|
||||
svc_vc_create(fd, sendsize, recvsize)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
struct cf_rendezvous *r = NULL;
|
||||
struct __rpc_sockinfo si;
|
||||
struct sockaddr_storage sslocal;
|
||||
socklen_t slen;
|
||||
int one = 1;
|
||||
|
||||
if (!__rpc_fd2sockinfo(fd, &si))
|
||||
return NULL;
|
||||
|
||||
r = mem_alloc(sizeof(*r));
|
||||
if (r == NULL) {
|
||||
warnx("svc_vc_create: out of memory");
|
||||
return NULL;
|
||||
}
|
||||
r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
|
||||
r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
|
||||
r->maxrec = __svc_maxrec;
|
||||
xprt = mem_alloc(sizeof(SVCXPRT));
|
||||
if (xprt == NULL) {
|
||||
warnx("svc_vc_create: out of memory");
|
||||
goto cleanup_svc_vc_create;
|
||||
}
|
||||
xprt->xp_tp = NULL;
|
||||
xprt->xp_p1 = (caddr_t)(void *)r;
|
||||
xprt->xp_p2 = NULL;
|
||||
xprt->xp_p3 = NULL;
|
||||
xprt->xp_verf = _null_auth;
|
||||
svc_vc_rendezvous_ops(xprt);
|
||||
xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
|
||||
xprt->xp_fd = fd;
|
||||
|
||||
slen = sizeof (struct sockaddr_storage);
|
||||
if (getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
|
||||
warnx("svc_vc_create: could not retrieve local addr");
|
||||
goto cleanup_svc_vc_create;
|
||||
}
|
||||
|
||||
/*
|
||||
* We want to be able to check credentials on local sockets.
|
||||
*/
|
||||
if (sslocal.ss_family == AF_LOCAL)
|
||||
if (setsockopt(fd, 0, LOCAL_CREDS, &one, sizeof one) < 0)
|
||||
goto cleanup_svc_vc_create;
|
||||
|
||||
xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
|
||||
xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
|
||||
if (xprt->xp_ltaddr.buf == NULL) {
|
||||
warnx("svc_vc_create: no mem for local addr");
|
||||
goto cleanup_svc_vc_create;
|
||||
}
|
||||
memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
|
||||
|
||||
xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
|
||||
xprt_register(xprt);
|
||||
return (xprt);
|
||||
cleanup_svc_vc_create:
|
||||
if (xprt)
|
||||
mem_free(xprt, sizeof(*xprt));
|
||||
if (r != NULL)
|
||||
mem_free(r, sizeof(*r));
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Like svtcp_create(), except the routine takes any *open* UNIX file
|
||||
* descriptor as its first input.
|
||||
*/
|
||||
SVCXPRT *
|
||||
svc_fd_create(fd, sendsize, recvsize)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
{
|
||||
struct sockaddr_storage ss;
|
||||
socklen_t slen;
|
||||
SVCXPRT *ret;
|
||||
|
||||
_DIAGASSERT(fd != -1);
|
||||
|
||||
ret = makefd_xprt(fd, sendsize, recvsize);
|
||||
if (ret == NULL)
|
||||
return NULL;
|
||||
|
||||
slen = sizeof (struct sockaddr_storage);
|
||||
if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
|
||||
warnx("svc_fd_create: could not retrieve local addr");
|
||||
goto freedata;
|
||||
}
|
||||
ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
|
||||
ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
|
||||
if (ret->xp_ltaddr.buf == NULL) {
|
||||
warnx("svc_fd_create: no mem for local addr");
|
||||
goto freedata;
|
||||
}
|
||||
memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
|
||||
|
||||
slen = sizeof (struct sockaddr_storage);
|
||||
if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
|
||||
warnx("svc_fd_create: could not retrieve remote addr");
|
||||
goto freedata;
|
||||
}
|
||||
ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
|
||||
ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
|
||||
if (ret->xp_rtaddr.buf == NULL) {
|
||||
warnx("svc_fd_create: no mem for local addr");
|
||||
goto freedata;
|
||||
}
|
||||
memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
|
||||
#ifdef PORTMAP
|
||||
if (ss.ss_family == AF_INET) {
|
||||
ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
|
||||
ret->xp_addrlen = sizeof (struct sockaddr_in);
|
||||
}
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
|
||||
freedata:
|
||||
if (ret->xp_ltaddr.buf != NULL)
|
||||
mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static SVCXPRT *
|
||||
makefd_xprt(fd, sendsize, recvsize)
|
||||
int fd;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
struct cf_conn *cd;
|
||||
const char *netid;
|
||||
struct __rpc_sockinfo si;
|
||||
|
||||
_DIAGASSERT(fd != -1);
|
||||
|
||||
xprt = mem_alloc(sizeof(SVCXPRT));
|
||||
if (xprt == NULL)
|
||||
goto out;
|
||||
memset(xprt, 0, sizeof *xprt);
|
||||
cd = mem_alloc(sizeof(struct cf_conn));
|
||||
if (cd == NULL)
|
||||
goto out;
|
||||
cd->strm_stat = XPRT_IDLE;
|
||||
xdrrec_create(&(cd->xdrs), sendsize, recvsize,
|
||||
(caddr_t)(void *)xprt, read_vc, write_vc);
|
||||
xprt->xp_p1 = (caddr_t)(void *)cd;
|
||||
xprt->xp_verf.oa_base = cd->verf_body;
|
||||
svc_vc_ops(xprt); /* truely deals with calls */
|
||||
xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
|
||||
xprt->xp_fd = fd;
|
||||
if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
|
||||
if ((xprt->xp_netid = strdup(netid)) == NULL)
|
||||
goto out;
|
||||
|
||||
xprt_register(xprt);
|
||||
return (xprt);
|
||||
out:
|
||||
warn("svc_tcp: makefd_xprt");
|
||||
if (xprt)
|
||||
mem_free(xprt, sizeof(SVCXPRT));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
rendezvous_request(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
int sock, flags;
|
||||
struct cf_rendezvous *r;
|
||||
struct cf_conn *cd;
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t len;
|
||||
struct __rpc_sockinfo si;
|
||||
SVCXPRT *newxprt;
|
||||
fd_set cleanfds;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
r = (struct cf_rendezvous *)xprt->xp_p1;
|
||||
again:
|
||||
len = sizeof addr;
|
||||
if ((sock = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
|
||||
&len)) < 0) {
|
||||
if (errno == EINTR)
|
||||
goto again;
|
||||
/*
|
||||
* Clean out the most idle file descriptor when we're
|
||||
* running out.
|
||||
*/
|
||||
if (errno == EMFILE || errno == ENFILE) {
|
||||
cleanfds = svc_fdset;
|
||||
if (__svc_clean_idle(&cleanfds, 0, FALSE))
|
||||
goto again;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
/*
|
||||
* make a new transporter (re-uses xprt)
|
||||
*/
|
||||
newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
|
||||
if (newxprt == NULL)
|
||||
goto out;
|
||||
newxprt->xp_rtaddr.buf = mem_alloc(len);
|
||||
if (newxprt->xp_rtaddr.buf == NULL)
|
||||
goto out;
|
||||
memcpy(newxprt->xp_rtaddr.buf, &addr, len);
|
||||
newxprt->xp_rtaddr.len = len;
|
||||
#ifdef PORTMAP
|
||||
if (addr.ss_family == AF_INET) {
|
||||
newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
|
||||
newxprt->xp_addrlen = sizeof (struct sockaddr_in);
|
||||
}
|
||||
#endif
|
||||
if (__rpc_fd2sockinfo(sock, &si))
|
||||
__rpc_setnodelay(sock, &si);
|
||||
|
||||
cd = (struct cf_conn *)newxprt->xp_p1;
|
||||
|
||||
cd->recvsize = r->recvsize;
|
||||
cd->sendsize = r->sendsize;
|
||||
cd->maxrec = r->maxrec;
|
||||
|
||||
if (cd->maxrec != 0) {
|
||||
flags = fcntl(sock, F_GETFL, 0);
|
||||
if (flags == -1)
|
||||
goto out;
|
||||
if (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
|
||||
goto out;
|
||||
if (cd->recvsize > (u_int)cd->maxrec)
|
||||
cd->recvsize = cd->maxrec;
|
||||
cd->nonblock = TRUE;
|
||||
__xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
|
||||
} else
|
||||
cd->nonblock = FALSE;
|
||||
|
||||
(void)gettimeofday(&cd->last_recv_time, NULL);
|
||||
|
||||
return (FALSE); /* there is never an rpc msg to be processed */
|
||||
out:
|
||||
(void)close(sock);
|
||||
return (FALSE); /* there was an error */
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static enum xprt_stat
|
||||
rendezvous_stat(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
|
||||
return (XPRT_IDLE);
|
||||
}
|
||||
|
||||
static void
|
||||
svc_vc_destroy(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
xprt_unregister(xprt);
|
||||
__svc_vc_dodestroy(xprt);
|
||||
}
|
||||
|
||||
static void
|
||||
__svc_vc_dodestroy(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct cf_conn *cd;
|
||||
struct cf_rendezvous *r;
|
||||
|
||||
cd = (struct cf_conn *)xprt->xp_p1;
|
||||
|
||||
if (xprt->xp_fd != RPC_ANYFD)
|
||||
(void)close(xprt->xp_fd);
|
||||
if (xprt->xp_port != 0) {
|
||||
/* a rendezvouser socket */
|
||||
r = (struct cf_rendezvous *)xprt->xp_p1;
|
||||
mem_free(r, sizeof (struct cf_rendezvous));
|
||||
xprt->xp_port = 0;
|
||||
} else {
|
||||
/* an actual connection socket */
|
||||
XDR_DESTROY(&(cd->xdrs));
|
||||
mem_free(cd, sizeof(struct cf_conn));
|
||||
}
|
||||
if (xprt->xp_rtaddr.buf)
|
||||
mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
|
||||
if (xprt->xp_ltaddr.buf)
|
||||
mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
|
||||
if (xprt->xp_tp)
|
||||
free(xprt->xp_tp);
|
||||
if (xprt->xp_netid)
|
||||
free(xprt->xp_netid);
|
||||
mem_free(xprt, sizeof(SVCXPRT));
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_vc_control(xprt, rq, in)
|
||||
SVCXPRT *xprt;
|
||||
const u_int rq;
|
||||
void *in;
|
||||
{
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static bool_t
|
||||
svc_vc_rendezvous_control(xprt, rq, in)
|
||||
SVCXPRT *xprt;
|
||||
const u_int rq;
|
||||
void *in;
|
||||
{
|
||||
struct cf_rendezvous *cfp;
|
||||
|
||||
cfp = (struct cf_rendezvous *)xprt->xp_p1;
|
||||
if (cfp == NULL)
|
||||
return (FALSE);
|
||||
switch (rq) {
|
||||
case SVCGET_CONNMAXREC:
|
||||
*(int *)in = cfp->maxrec;
|
||||
break;
|
||||
case SVCSET_CONNMAXREC:
|
||||
cfp->maxrec = *(int *)in;
|
||||
break;
|
||||
default:
|
||||
return (FALSE);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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.)
|
||||
* All read operations timeout after 35 seconds. A timeout is
|
||||
* fatal for the connection.
|
||||
*/
|
||||
static int
|
||||
read_vc(xprtp, buf, len)
|
||||
caddr_t xprtp;
|
||||
caddr_t buf;
|
||||
int len;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
int sock;
|
||||
struct pollfd pollfd;
|
||||
struct sockaddr *sa;
|
||||
struct msghdr msg;
|
||||
struct cmsghdr *cmp;
|
||||
void *crmsg = NULL;
|
||||
struct sockcred *sc;
|
||||
socklen_t crmsgsize;
|
||||
struct cf_conn *cfp;
|
||||
static const struct timespec ts = { 35, 0 };
|
||||
|
||||
xprt = (SVCXPRT *)(void *)xprtp;
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
sock = xprt->xp_fd;
|
||||
|
||||
sa = (struct sockaddr *)xprt->xp_rtaddr.buf;
|
||||
if (sa->sa_family == AF_LOCAL && xprt->xp_p2 == NULL) {
|
||||
memset(&msg, 0, sizeof msg);
|
||||
crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS));
|
||||
crmsg = malloc(crmsgsize);
|
||||
if (crmsg == NULL)
|
||||
goto fatal_err;
|
||||
memset(crmsg, 0, crmsgsize);
|
||||
|
||||
msg.msg_control = crmsg;
|
||||
msg.msg_controllen = crmsgsize;
|
||||
|
||||
if (recvmsg(sock, &msg, 0) < 0)
|
||||
goto fatal_err;
|
||||
|
||||
if (msg.msg_controllen == 0 ||
|
||||
(msg.msg_flags & MSG_CTRUNC) != 0)
|
||||
goto fatal_err;
|
||||
|
||||
cmp = CMSG_FIRSTHDR(&msg);
|
||||
if (cmp->cmsg_level != SOL_SOCKET ||
|
||||
cmp->cmsg_type != SCM_CREDS)
|
||||
goto fatal_err;
|
||||
|
||||
sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
|
||||
|
||||
xprt->xp_p2 = mem_alloc(SOCKCREDSIZE(sc->sc_ngroups));
|
||||
if (xprt->xp_p2 == NULL)
|
||||
goto fatal_err;
|
||||
|
||||
memcpy(xprt->xp_p2, sc, SOCKCREDSIZE(sc->sc_ngroups));
|
||||
free(crmsg);
|
||||
crmsg = NULL;
|
||||
}
|
||||
|
||||
cfp = (struct cf_conn *)xprt->xp_p1;
|
||||
|
||||
if (cfp->nonblock) {
|
||||
len = read(sock, buf, (size_t)len);
|
||||
if (len < 0) {
|
||||
if (errno == EAGAIN)
|
||||
len = 0;
|
||||
else
|
||||
goto fatal_err;
|
||||
}
|
||||
if (len != 0)
|
||||
gettimeofday(&cfp->last_recv_time, NULL);
|
||||
return len;
|
||||
}
|
||||
|
||||
do {
|
||||
pollfd.fd = sock;
|
||||
pollfd.events = POLLIN;
|
||||
switch (pollts(&pollfd, 1, &ts, NULL)) {
|
||||
case -1:
|
||||
if (errno == EINTR) {
|
||||
continue;
|
||||
}
|
||||
/*FALLTHROUGH*/
|
||||
case 0:
|
||||
goto fatal_err;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} while ((pollfd.revents & POLLIN) == 0);
|
||||
|
||||
if ((len = read(sock, buf, (size_t)len)) > 0) {
|
||||
gettimeofday(&cfp->last_recv_time, NULL);
|
||||
return (len);
|
||||
}
|
||||
|
||||
fatal_err:
|
||||
if (crmsg != NULL)
|
||||
free(crmsg);
|
||||
((struct cf_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
|
||||
write_vc(xprtp, buf, len)
|
||||
caddr_t xprtp;
|
||||
caddr_t buf;
|
||||
int len;
|
||||
{
|
||||
SVCXPRT *xprt;
|
||||
int i, cnt;
|
||||
struct cf_conn *cd;
|
||||
struct timeval tv0, tv1;
|
||||
|
||||
xprt = (SVCXPRT *)(void *)xprtp;
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
cd = (struct cf_conn *)xprt->xp_p1;
|
||||
|
||||
if (cd->nonblock)
|
||||
gettimeofday(&tv0, NULL);
|
||||
|
||||
for (cnt = len; cnt > 0; cnt -= i, buf += i) {
|
||||
if ((i = write(xprt->xp_fd, buf, (size_t)cnt)) < 0) {
|
||||
if (errno != EAGAIN || !cd->nonblock) {
|
||||
cd->strm_stat = XPRT_DIED;
|
||||
return (-1);
|
||||
}
|
||||
if (cd->nonblock && i != cnt) {
|
||||
/*
|
||||
* For non-blocking connections, do not
|
||||
* take more than 2 seconds writing the
|
||||
* data out.
|
||||
*
|
||||
* XXX 2 is an arbitrary amount.
|
||||
*/
|
||||
gettimeofday(&tv1, NULL);
|
||||
if (tv1.tv_sec - tv0.tv_sec >= 2) {
|
||||
cd->strm_stat = XPRT_DIED;
|
||||
return (-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return (len);
|
||||
}
|
||||
|
||||
static enum xprt_stat
|
||||
svc_vc_stat(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
struct cf_conn *cd;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
|
||||
cd = (struct cf_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
|
||||
svc_vc_recv(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
struct cf_conn *cd;
|
||||
XDR *xdrs;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
cd = (struct cf_conn *)(xprt->xp_p1);
|
||||
xdrs = &(cd->xdrs);
|
||||
|
||||
if (cd->nonblock) {
|
||||
if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
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;
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_vc_getargs(xprt, xdr_args, args_ptr)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_args;
|
||||
caddr_t args_ptr;
|
||||
{
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
/* args_ptr may be NULL */
|
||||
|
||||
return ((*xdr_args)(&(((struct cf_conn *)(xprt->xp_p1))->xdrs),
|
||||
args_ptr));
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_vc_freeargs(xprt, xdr_args, args_ptr)
|
||||
SVCXPRT *xprt;
|
||||
xdrproc_t xdr_args;
|
||||
caddr_t args_ptr;
|
||||
{
|
||||
XDR *xdrs;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
/* args_ptr may be NULL */
|
||||
|
||||
xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
|
||||
|
||||
xdrs->x_op = XDR_FREE;
|
||||
return ((*xdr_args)(xdrs, args_ptr));
|
||||
}
|
||||
|
||||
static bool_t
|
||||
svc_vc_reply(xprt, msg)
|
||||
SVCXPRT *xprt;
|
||||
struct rpc_msg *msg;
|
||||
{
|
||||
struct cf_conn *cd;
|
||||
XDR *xdrs;
|
||||
bool_t rstat;
|
||||
|
||||
_DIAGASSERT(xprt != NULL);
|
||||
_DIAGASSERT(msg != NULL);
|
||||
|
||||
cd = (struct cf_conn *)(xprt->xp_p1);
|
||||
xdrs = &(cd->xdrs);
|
||||
|
||||
xdrs->x_op = XDR_ENCODE;
|
||||
msg->rm_xid = cd->x_id;
|
||||
rstat = xdr_replymsg(xdrs, msg);
|
||||
(void)xdrrec_endofrecord(xdrs, TRUE);
|
||||
return (rstat);
|
||||
}
|
||||
|
||||
static void
|
||||
svc_vc_ops(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
static struct xp_ops ops;
|
||||
static struct xp_ops2 ops2;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
#endif
|
||||
|
||||
/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
|
||||
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.xp_recv == NULL) {
|
||||
ops.xp_recv = svc_vc_recv;
|
||||
ops.xp_stat = svc_vc_stat;
|
||||
ops.xp_getargs = svc_vc_getargs;
|
||||
ops.xp_reply = svc_vc_reply;
|
||||
ops.xp_freeargs = svc_vc_freeargs;
|
||||
ops.xp_destroy = svc_vc_destroy;
|
||||
ops2.xp_control = svc_vc_control;
|
||||
}
|
||||
xprt->xp_ops = &ops;
|
||||
xprt->xp_ops2 = &ops2;
|
||||
mutex_unlock(&ops_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
svc_vc_rendezvous_ops(xprt)
|
||||
SVCXPRT *xprt;
|
||||
{
|
||||
static struct xp_ops ops;
|
||||
static struct xp_ops2 ops2;
|
||||
#ifdef _REENTRANT
|
||||
extern mutex_t ops_lock;
|
||||
#endif
|
||||
/* XXXGCC vax compiler unhappy otherwise */
|
||||
#ifdef __vax__
|
||||
extern void abort(void);
|
||||
#endif
|
||||
|
||||
mutex_lock(&ops_lock);
|
||||
if (ops.xp_recv == NULL) {
|
||||
ops.xp_recv = rendezvous_request;
|
||||
ops.xp_stat = rendezvous_stat;
|
||||
ops.xp_getargs =
|
||||
(bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort;
|
||||
ops.xp_reply =
|
||||
(bool_t (*) __P((SVCXPRT *, struct rpc_msg *)))abort;
|
||||
ops.xp_freeargs =
|
||||
(bool_t (*) __P((SVCXPRT *, xdrproc_t, caddr_t)))abort;
|
||||
ops.xp_destroy = svc_vc_destroy;
|
||||
ops2.xp_control = svc_vc_rendezvous_control;
|
||||
}
|
||||
xprt->xp_ops = &ops;
|
||||
xprt->xp_ops2 = &ops2;
|
||||
mutex_unlock(&ops_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy xprts that have not have had any activity in 'timeout' seconds.
|
||||
* If 'cleanblock' is true, blocking connections (the default) are also
|
||||
* cleaned. If timeout is 0, the least active connection is picked.
|
||||
*/
|
||||
bool_t
|
||||
__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
|
||||
{
|
||||
int i, ncleaned;
|
||||
SVCXPRT *xprt, *least_active;
|
||||
struct timeval tv, tdiff, tmax;
|
||||
struct cf_conn *cd;
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
tmax.tv_sec = tmax.tv_usec = 0;
|
||||
least_active = NULL;
|
||||
rwlock_wrlock(&svc_fd_lock);
|
||||
for (i = ncleaned = 0; i <= svc_maxfd; i++) {
|
||||
if (FD_ISSET(i, fds)) {
|
||||
xprt = __svc_xports[i];
|
||||
if (xprt == NULL || xprt->xp_ops == NULL ||
|
||||
xprt->xp_ops->xp_recv != svc_vc_recv)
|
||||
continue;
|
||||
cd = (struct cf_conn *)xprt->xp_p1;
|
||||
if (!cleanblock && !cd->nonblock)
|
||||
continue;
|
||||
if (timeout == 0) {
|
||||
timersub(&tv, &cd->last_recv_time, &tdiff);
|
||||
if (timercmp(&tdiff, &tmax, >)) {
|
||||
tmax = tdiff;
|
||||
least_active = xprt;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
|
||||
__xprt_unregister_unlocked(xprt);
|
||||
__svc_vc_dodestroy(xprt);
|
||||
ncleaned++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timeout == 0 && least_active != NULL) {
|
||||
__xprt_unregister_unlocked(least_active);
|
||||
__svc_vc_dodestroy(least_active);
|
||||
ncleaned++;
|
||||
}
|
||||
rwlock_unlock(&svc_fd_lock);
|
||||
return ncleaned > 0 ? TRUE : FALSE;
|
||||
}
|
||||
@@ -0,0 +1,514 @@
|
||||
.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI
|
||||
.\" $NetBSD: xdr.3,v 1.12 2009/10/13 21:39:55 joerg Exp $
|
||||
.\"
|
||||
.Dd April 17, 2003
|
||||
.Dt XDR 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm xdr ,
|
||||
.Nm xdr_array ,
|
||||
.Nm xdr_bool ,
|
||||
.Nm xdr_bytes ,
|
||||
.Nm xdr_char ,
|
||||
.Nm xdr_destroy ,
|
||||
.Nm xdr_double ,
|
||||
.Nm xdr_enum ,
|
||||
.Nm xdr_float ,
|
||||
.Nm xdr_free ,
|
||||
.Nm xdr_getpos ,
|
||||
.Nm xdr_hyper ,
|
||||
.Nm xdr_inline ,
|
||||
.Nm xdr_int ,
|
||||
.Nm xdr_long ,
|
||||
.Nm xdr_longlong_t ,
|
||||
.Nm xdrmem_create ,
|
||||
.Nm xdr_opaque ,
|
||||
.Nm xdr_pointer ,
|
||||
.Nm xdrrec_create ,
|
||||
.Nm xdrrec_endofrecord ,
|
||||
.Nm xdrrec_eof ,
|
||||
.Nm xdrrec_skiprecord ,
|
||||
.Nm xdr_reference ,
|
||||
.Nm xdr_setpos ,
|
||||
.Nm xdr_short ,
|
||||
.Nm xdrstdio_create ,
|
||||
.Nm xdr_string ,
|
||||
.Nm xdr_u_char ,
|
||||
.Nm xdr_u_hyper ,
|
||||
.Nm xdr_u_long ,
|
||||
.Nm xdr_u_longlong_t ,
|
||||
.Nm xdr_u_short ,
|
||||
.Nm xdr_union ,
|
||||
.Nm xdr_vector ,
|
||||
.Nm xdr_void ,
|
||||
.Nm xdr_wrapstring
|
||||
.Nd library routines for external data representation
|
||||
.Sh SYNOPSIS
|
||||
.Ft int
|
||||
.Fn xdr_array "XDR *xdrs" "char **arrp" "u_int *sizep" "u_int maxsize" \
|
||||
"u_int elsize" "xdrproc_t elproc"
|
||||
.Ft int
|
||||
.Fn xdr_bool "XDR *xdrs" "bool_t *bp"
|
||||
.Ft int
|
||||
.Fn xdr_bytes "XDR *xdrs" "char **sp" "u_int *sizep" "u_int maxsize"
|
||||
.Ft int
|
||||
.Fn xdr_char "XDR *xdrs" "char *cp"
|
||||
.Ft void
|
||||
.Fn xdr_destroy "XDR *xdrs"
|
||||
.Ft int
|
||||
.Fn xdr_double "XDR *xdrs" "double *dp"
|
||||
.Ft int
|
||||
.Fn xdr_enum "XDR *xdrs" "enum_t *ep"
|
||||
.Ft int
|
||||
.Fn xdr_float "XDR *xdrs" "float *fp"
|
||||
.Ft void
|
||||
.Fn xdr_free "xdrproc_t proc" "char *objp"
|
||||
.Ft u_int
|
||||
.Fn xdr_getpos "XDR *xdrs"
|
||||
.Ft int
|
||||
.Fn xdr_hyper "XDR *xdrs" "longlong_t *llp"
|
||||
.Ft long *
|
||||
.Fn xdr_inline "XDR *xdrs" "int len"
|
||||
.Ft int
|
||||
.Fn xdr_int "XDR *xdrs" "int *ip"
|
||||
.Ft int
|
||||
.Fn xdr_long "XDR *xdrs" "long *lp"
|
||||
.Ft int
|
||||
.Fn xdr_longlong_t "XDR *xdrs" "longlong_t *llp"
|
||||
.Ft void
|
||||
.Fn xdrmem_create "XDR *xdrs" "char *addr" "u_int size" \
|
||||
"enum xdr_op op"
|
||||
.Ft int
|
||||
.Fn xdr_opaque "XDR *xdrs" "char *cp" "u_int cnt"
|
||||
.Ft int
|
||||
.Fn xdr_pointer "XDR *xdrs" "char **objpp" "u_int objsize" \
|
||||
"xdrproc_t xdrobj"
|
||||
.Ft void
|
||||
.Fn xdrrec_create "XDR *xdrs" "u_int sendsize" "u_int recvsize" \
|
||||
"char *handle" "int (*readit)()" "int (*writeit)()"
|
||||
.Ft int
|
||||
.Fn xdrrec_endofrecord "XDR *xdrs" "int sendnow"
|
||||
.Ft int
|
||||
.Fn xdrrec_eof "XDR *xdrs"
|
||||
.Ft int
|
||||
.Fn xdrrec_skiprecord "XDR *xdrs"
|
||||
.Ft int
|
||||
.Fn xdr_reference "XDR *xdrs" "char **pp" "u_int size" \
|
||||
"xdrproc_t proc"
|
||||
.Ft int
|
||||
.Fn xdr_setpos "XDR *xdrs" "u_int pos"
|
||||
.Ft int
|
||||
.Fn xdr_short "XDR *xdrs" "short *sp"
|
||||
.Ft void
|
||||
.Fn xdrstdio_create "XDR *xdrs" "FILE *file" "enum xdr_op op"
|
||||
.Ft int
|
||||
.Fn xdr_string "XDR *xdrs" "char **sp" "u_int maxsize"
|
||||
.Ft int
|
||||
.Fn xdr_u_char "XDR *xdrs" "unsigned char *ucp"
|
||||
.Ft int
|
||||
.Fn xdr_u_hyper "XDR *xdrs" "u_longlong_t *ullp"
|
||||
.Ft int
|
||||
.Fn xdr_u_int "XDR *xdrs" "unsigned *up"
|
||||
.Ft int
|
||||
.Fn xdr_u_long "XDR *xdrs" "unsigned long *ulp"
|
||||
.Ft int
|
||||
.Fn xdr_u_longlong_t "XDR *xdrs" "u_longlong_t *ullp"
|
||||
.Ft int
|
||||
.Fn xdr_u_short "XDR *xdrs" "unsigned short *usp"
|
||||
.Ft int
|
||||
.Fn xdr_union "XDR *xdrs" "int *dscmp" "char *unp" \
|
||||
"struct xdr_discrim *choices" "bool_t (*defaultarm)(\|)"
|
||||
.Ft int
|
||||
.Fn xdr_vector "XDR *xdrs" "char *arrp" "u_int size" \
|
||||
"u_int elsize" "xdrproc_t elproc"
|
||||
.Ft int
|
||||
.Fn xdr_void "void"
|
||||
.Ft int
|
||||
.Fn xdr_wrapstring "XDR *xdrs" "char **sp"
|
||||
.Sh DESCRIPTION
|
||||
These routines allow C programmers to describe
|
||||
arbitrary data structures in a machine-independent fashion.
|
||||
Data for remote procedure calls are transmitted using these
|
||||
routines.
|
||||
.Bl -tag -width xxx
|
||||
.It Fn xdr_array
|
||||
A filter primitive that translates between variable-length
|
||||
arrays and their corresponding external representations.
|
||||
The parameter
|
||||
.Fa arrp
|
||||
is the address of the pointer to the array, while
|
||||
.Fa sizep
|
||||
is the address of the element count of the array;
|
||||
this element count cannot exceed
|
||||
.Fa maxsize .
|
||||
The parameter
|
||||
.Fa elsize
|
||||
is the
|
||||
.Em sizeof
|
||||
each of the array's elements, and
|
||||
.Fa elproc
|
||||
is an XDR filter that translates between the array elements' C form,
|
||||
and their external representation.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_bool
|
||||
A filter primitive that translates between booleans (C integers)
|
||||
and their external representations.
|
||||
When encoding data, this filter produces values of either one or
|
||||
zero.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_bytes
|
||||
A filter primitive that translates between counted byte
|
||||
strings and their external representations.
|
||||
The parameter
|
||||
.Fa sp
|
||||
is the address of the string pointer.
|
||||
The length of the string is located at address
|
||||
.Fa sizep ;
|
||||
strings cannot be longer than
|
||||
.Fa maxsize .
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_char
|
||||
A filter primitive that translates between C characters
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
Note: encoded characters are not packed, and occupy 4 bytes each.
|
||||
For arrays of characters, it is worthwhile to consider
|
||||
.Fn xdr_bytes ,
|
||||
.Fn xdr_opaque
|
||||
or
|
||||
.Fn xdr_string .
|
||||
.It Fn xdr_destroy
|
||||
A macro that invokes the destroy routine associated with the XDR
|
||||
stream,
|
||||
.Fa xdrs .
|
||||
Destruction usually involves freeing private data structures
|
||||
associated with the stream.
|
||||
Using
|
||||
.Fa xdrs
|
||||
after invoking
|
||||
.Fn xdr_destroy
|
||||
is undefined.
|
||||
.It Fn xdr_double
|
||||
A filter primitive that translates between C double precision numbers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_enum
|
||||
A filter primitive that translates between C enums (actually integers)
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_float
|
||||
A filter primitive that translates between C floats
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_free
|
||||
Generic freeing routine.
|
||||
The first argument is the XDR routine for the object being freed.
|
||||
The second argument is a pointer to the object itself.
|
||||
Note: the pointer passed to this routine is
|
||||
.Em not
|
||||
freed, but what it points to
|
||||
.Em is
|
||||
freed (recursively).
|
||||
.It Fn xdr_getpos
|
||||
A macro that invokes the get-position routine associated with the XDR
|
||||
stream,
|
||||
.Fa xdrs .
|
||||
The routine returns an unsigned integer, which indicates the position
|
||||
of the XDR byte stream.
|
||||
A desirable feature of XDR streams is that simple arithmetic works
|
||||
with this number, although the XDR stream instances need not guarantee
|
||||
this.
|
||||
.It Fn xdr_hyper
|
||||
A filter primitive that translates between ANSI C long long integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_inline
|
||||
A macro that invokes the in-line routine associated with the XDR
|
||||
stream,
|
||||
.Fa xdrs .
|
||||
The routine returns a pointer
|
||||
to a contiguous piece of the stream's buffer;
|
||||
.Fa len
|
||||
is the byte length of the desired buffer.
|
||||
Note: pointer is cast to
|
||||
.Vt "long *" .
|
||||
.Pp
|
||||
Warning:
|
||||
.Fn xdr_inline
|
||||
may return
|
||||
.Dv NULL
|
||||
if it cannot allocate a contiguous piece of a buffer.
|
||||
Therefore the behavior may vary among stream instances;
|
||||
it exists for the sake of efficiency.
|
||||
.It Fn xdr_int
|
||||
A filter primitive that translates between C integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_long
|
||||
A filter primitive that translates between C long integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_longlong_t
|
||||
A filter primitive that translates between ANSI C long long integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdrmem_create
|
||||
This routine initializes the XDR stream object pointed to by
|
||||
.Fa xdrs .
|
||||
The stream's data is written to, or read from,
|
||||
a chunk of memory at location
|
||||
.Fa addr
|
||||
whose length is no more than
|
||||
.Fa size
|
||||
bytes long.
|
||||
The
|
||||
.Fa op
|
||||
determines the direction of the XDR stream (either
|
||||
.Dv XDR_ENCODE ,
|
||||
.Dv XDR_DECODE ,
|
||||
or
|
||||
.Dv XDR_FREE ) .
|
||||
.It Fn xdr_opaque
|
||||
A filter primitive that translates between fixed size opaque data
|
||||
and its external representation.
|
||||
The parameter
|
||||
.Fa cp
|
||||
is the address of the opaque object, and
|
||||
.Fa cnt
|
||||
is its size in bytes.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_pointer
|
||||
Like
|
||||
.Fn xdr_reference
|
||||
except that it serializes
|
||||
.Dv NULL
|
||||
pointers, whereas
|
||||
.Fn xdr_reference
|
||||
does not.
|
||||
Thus,
|
||||
.Fn xdr_pointer
|
||||
can represent recursive data structures, such as binary trees or
|
||||
linked lists.
|
||||
.It Fn xdrrec_create
|
||||
This routine initializes the XDR stream object pointed to by
|
||||
.Fa xdrs .
|
||||
The stream's data is written to a buffer of size
|
||||
.Fa sendsize ;
|
||||
a value of zero indicates the system should use a suitable default.
|
||||
The stream's data is read from a buffer of size
|
||||
.Fa recvsize ;
|
||||
it too can be set to a suitable default by passing a zero value.
|
||||
When a stream's output buffer is full,
|
||||
.Fa writeit
|
||||
is called.
|
||||
Similarly, when a stream's input buffer is empty,
|
||||
.Fa readit
|
||||
is called.
|
||||
The behavior of these two routines is similar to the system calls
|
||||
.Xr read 2
|
||||
and
|
||||
.Xr write 2 ,
|
||||
except that
|
||||
.Fa handle
|
||||
is passed to the former routines as the first parameter.
|
||||
Note: the XDR stream's
|
||||
.Fa op
|
||||
field must be set by the caller.
|
||||
.Pp
|
||||
Warning: this XDR stream implements an intermediate record stream.
|
||||
Therefore there are additional bytes in the stream
|
||||
to provide record boundary information.
|
||||
.It Fn xdrrec_endofrecord
|
||||
This routine can be invoked only on streams created by
|
||||
.Fn xdrrec_create .
|
||||
The data in the output buffer is marked as a completed record,
|
||||
and the output buffer is optionally written out if
|
||||
.Fa sendnow
|
||||
is non-zero.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdrrec_eof
|
||||
This routine can be invoked only on streams created by
|
||||
.Fn xdrrec_create .
|
||||
After consuming the rest of the current record in the stream,
|
||||
this routine returns one if the stream has no more input,
|
||||
zero otherwise.
|
||||
.It Fn xdrrec_skiprecord
|
||||
This routine can be invoked only on streams created by
|
||||
.Fn xdrrec_create .
|
||||
It tells the XDR implementation that the rest of the current record
|
||||
in the stream's input buffer should be discarded.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_reference
|
||||
A primitive that provides pointer chasing within structures.
|
||||
The parameter
|
||||
.Fa pp
|
||||
is the address of the pointer;
|
||||
.Fa size
|
||||
is the
|
||||
.Em sizeof
|
||||
the structure that
|
||||
.Fa *pp
|
||||
points to; and
|
||||
.Fa proc
|
||||
is an XDR procedure that filters the structure
|
||||
between its C form and its external representation.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.Pp
|
||||
Warning: this routine does not understand
|
||||
.Dv NULL
|
||||
pointers.
|
||||
Use
|
||||
.Fn xdr_pointer
|
||||
instead.
|
||||
.It Fn xdr_setpos
|
||||
A macro that invokes the set position routine associated with the XDR
|
||||
stream
|
||||
.Fa xdrs .
|
||||
The parameter
|
||||
.Fa pos
|
||||
is a position value obtained from
|
||||
.Fn xdr_getpos .
|
||||
This routine returns one if the XDR stream could be repositioned,
|
||||
and zero otherwise.
|
||||
.Pp
|
||||
Warning: it is difficult to reposition some types of XDR streams, so
|
||||
this routine may fail with one type of stream and succeed with
|
||||
another.
|
||||
.It Fn xdr_short
|
||||
A filter primitive that translates between C short integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdrstdio_create
|
||||
This routine initializes the XDR stream object pointed to by
|
||||
.Fa xdrs .
|
||||
The XDR stream data is written to, or read from, the Standard I/O
|
||||
stream
|
||||
.Fa file .
|
||||
The parameter
|
||||
.Fa op
|
||||
determines the direction of the XDR stream (either
|
||||
.Dv XDR_ENCODE ,
|
||||
.Dv XDR_DECODE ,
|
||||
or
|
||||
.Dv XDR_FREE ) .
|
||||
.Pp
|
||||
Warning: the destroy routine associated with such XDR streams calls
|
||||
.Xr fflush 3
|
||||
on the file stream, but never
|
||||
.Xr fclose 3 .
|
||||
.It Fn xdr_string
|
||||
A filter primitive that translates between C strings and
|
||||
their corresponding external representations.
|
||||
Strings cannot be longer than
|
||||
.Fa maxsize .
|
||||
Note:
|
||||
.Fa sp
|
||||
is the address of the string's pointer.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_u_char
|
||||
A filter primitive that translates between unsigned C characters
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_u_hyper
|
||||
A filter primitive that translates between unsigned ANSI C long long
|
||||
integers and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_u_int
|
||||
A filter primitive that translates between C unsigned integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_u_long
|
||||
A filter primitive that translates between C unsigned long integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_u_longlong_t
|
||||
A filter primitive that translates between unsigned ANSI C long long
|
||||
integers and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_u_short
|
||||
A filter primitive that translates between C unsigned short integers
|
||||
and their external representations.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_union
|
||||
A filter primitive that translates between a discriminated C union
|
||||
and its corresponding external representation.
|
||||
It first translates the discriminant of the union located at
|
||||
.Fa dscmp .
|
||||
This discriminant is always an enum_t.
|
||||
Next the union located at
|
||||
.Fa unp
|
||||
is translated.
|
||||
The parameter
|
||||
.Fa choices
|
||||
is a pointer to an array of
|
||||
.Fn xdr_discrim
|
||||
structures.
|
||||
Each structure contains an ordered pair of
|
||||
.Fa [ value ,
|
||||
.Fa proc ] .
|
||||
If the union's discriminant is equal to the associated
|
||||
.Fa value ,
|
||||
then the
|
||||
.Fa proc
|
||||
is called to translate the union.
|
||||
The end of the
|
||||
.Fn xdr_discrim
|
||||
structure array is denoted by a routine of value
|
||||
.Dv NULL .
|
||||
If the discriminant is not found in the
|
||||
.Fa choices
|
||||
array, then the
|
||||
.Fa defaultarm
|
||||
procedure is called (if it is not
|
||||
.Dv NULL ) .
|
||||
Returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_vector
|
||||
A filter primitive that translates between fixed-length
|
||||
arrays and their corresponding external representations.
|
||||
The parameter
|
||||
.Fa arrp
|
||||
is the address of the pointer to the array, while
|
||||
.Fa size
|
||||
is the element count of the array.
|
||||
The parameter
|
||||
.Fa elsize
|
||||
is the
|
||||
.Em sizeof
|
||||
each of the array's elements, and
|
||||
.Fa elproc
|
||||
is an XDR filter that translates between the array elements' C form,
|
||||
and their external representation.
|
||||
This routine returns one if it succeeds, zero otherwise.
|
||||
.It Fn xdr_void
|
||||
This routine always returns one.
|
||||
It may be passed to RPC routines that require a function parameter,
|
||||
where nothing is to be done.
|
||||
.It Fn xdr_wrapstring
|
||||
A primitive that calls
|
||||
.Fn xdr_string "xdrs" "sp" "MAXUN.UNSIGNED" ;
|
||||
where
|
||||
.Dv MAXUN.UNSIGNED
|
||||
is the maximum value of an unsigned integer.
|
||||
.Fn xdr_wrapstring
|
||||
is handy because the RPC package passes a maximum of two XDR
|
||||
routines as parameters, and
|
||||
.Fn xdr_string ,
|
||||
one of the most frequently used primitives, requires three.
|
||||
Returns one if it succeeds, zero otherwise.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr rpc 3
|
||||
.Pp
|
||||
The following manuals:
|
||||
.Rs
|
||||
.%B "eXternal Data Representation Standard: Protocol Specification"
|
||||
.Re
|
||||
.Rs
|
||||
.%B "eXternal Data Representation: Sun Technical Notes"
|
||||
.Re
|
||||
.Rs
|
||||
.%A Sun Microsystems, Inc., USC-ISI
|
||||
.%T "XDR: External Data Representation Standard"
|
||||
.%R "RFC 1014, USC-ISI"
|
||||
.%V 1014
|
||||
.Re
|
||||
+1003
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,170 @@
|
||||
/* $NetBSD: xdr_array.c,v 1.16 2005/08/05 10:39:05 wiz Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: xdr_array.c,v 1.16 2005/08/05 10:39:05 wiz Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* xdr_array.c, Generic XDR routines implementation.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* These are the "non-trivial" xdr primitives used to serialize and de-serialize
|
||||
* arrays. See xdr.h for more info on the interface to xdr.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_array,_xdr_array)
|
||||
__weak_alias(xdr_vector,_xdr_vector)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XDR an array of arbitrary elements
|
||||
* *addrp is a pointer to the array, *sizep is the number of elements.
|
||||
* If addrp is NULL (*sizep * elsize) bytes are allocated.
|
||||
* elsize is the size (in bytes) of each element, and elproc is the
|
||||
* xdr procedure to call to handle each element of the array.
|
||||
*/
|
||||
bool_t
|
||||
xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
|
||||
XDR *xdrs;
|
||||
caddr_t *addrp; /* array pointer */
|
||||
u_int *sizep; /* number of elements */
|
||||
u_int maxsize; /* max numberof elements */
|
||||
u_int elsize; /* size in bytes of each element */
|
||||
xdrproc_t elproc; /* xdr routine to handle each element */
|
||||
{
|
||||
u_int i;
|
||||
caddr_t target = *addrp;
|
||||
u_int c; /* the actual element count */
|
||||
bool_t stat = TRUE;
|
||||
u_int nodesize;
|
||||
|
||||
/* like strings, arrays are really counted arrays */
|
||||
if (!xdr_u_int(xdrs, sizep))
|
||||
return (FALSE);
|
||||
|
||||
c = *sizep;
|
||||
if ((c > maxsize || UINT_MAX/elsize < c) &&
|
||||
(xdrs->x_op != XDR_FREE))
|
||||
return (FALSE);
|
||||
nodesize = c * elsize;
|
||||
|
||||
/*
|
||||
* if we are deserializing, we may need to allocate an array.
|
||||
* We also save time by checking for a null array if we are freeing.
|
||||
*/
|
||||
if (target == NULL)
|
||||
switch (xdrs->x_op) {
|
||||
case XDR_DECODE:
|
||||
if (c == 0)
|
||||
return (TRUE);
|
||||
*addrp = target = mem_alloc(nodesize);
|
||||
if (target == NULL) {
|
||||
warnx("xdr_array: out of memory");
|
||||
return (FALSE);
|
||||
}
|
||||
memset(target, 0, nodesize);
|
||||
break;
|
||||
|
||||
case XDR_FREE:
|
||||
return (TRUE);
|
||||
|
||||
case XDR_ENCODE:
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* now we xdr each element of array
|
||||
*/
|
||||
for (i = 0; (i < c) && stat; i++) {
|
||||
stat = (*elproc)(xdrs, target);
|
||||
target += elsize;
|
||||
}
|
||||
|
||||
/*
|
||||
* the array may need freeing
|
||||
*/
|
||||
if (xdrs->x_op == XDR_FREE) {
|
||||
mem_free(*addrp, nodesize);
|
||||
*addrp = NULL;
|
||||
}
|
||||
return (stat);
|
||||
}
|
||||
|
||||
/*
|
||||
* xdr_vector():
|
||||
*
|
||||
* XDR a fixed length array. Unlike variable-length arrays,
|
||||
* the storage of fixed length arrays is static and unfreeable.
|
||||
* > basep: base of the array
|
||||
* > size: size of the array
|
||||
* > elemsize: size of each element
|
||||
* > xdr_elem: routine to XDR each element
|
||||
*/
|
||||
bool_t
|
||||
xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
|
||||
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)) {
|
||||
return(FALSE);
|
||||
}
|
||||
elptr += elemsize;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/* $NetBSD: xdr_float.c,v 1.35 2009/02/14 06:26:42 lukem Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: xdr_float.c,v 1.35 2009/02/14 06:26:42 lukem Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* xdr_float.c, Generic XDR routines implementation.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* These are the "floating point" xdr routines used to (de)serialize
|
||||
* most common data items. See xdr.h for more info on the interface to
|
||||
* xdr.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_double,_xdr_double)
|
||||
__weak_alias(xdr_float,_xdr_float)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* NB: Not portable.
|
||||
* This routine works on machines with IEEE754 FP and Vaxen.
|
||||
*/
|
||||
|
||||
#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
|
||||
defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
|
||||
defined(__arm__) || defined(__powerpc__) || defined(__sh__) || \
|
||||
defined(__x86_64__) || defined(__hppa__) || defined(__ia64__)
|
||||
#include <machine/endian.h>
|
||||
#define IEEEFP
|
||||
#endif
|
||||
|
||||
#if defined(__vax__)
|
||||
|
||||
/* What IEEE single precision floating point looks like on a Vax */
|
||||
struct ieee_single {
|
||||
unsigned int mantissa: 23;
|
||||
unsigned int exp : 8;
|
||||
unsigned int sign : 1;
|
||||
};
|
||||
|
||||
/* Vax single precision floating point */
|
||||
struct vax_single {
|
||||
unsigned int mantissa1 : 7;
|
||||
unsigned int exp : 8;
|
||||
unsigned int sign : 1;
|
||||
unsigned int mantissa2 : 16;
|
||||
};
|
||||
|
||||
#define VAX_SNG_BIAS 0x81
|
||||
#define IEEE_SNG_BIAS 0x7f
|
||||
|
||||
static struct sgl_limits {
|
||||
struct vax_single s;
|
||||
struct ieee_single ieee;
|
||||
} sgl_limits[2] = {
|
||||
{{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
|
||||
{ 0x0, 0xff, 0x0 }}, /* Max IEEE */
|
||||
{{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
|
||||
{ 0x0, 0x0, 0x0 }} /* Min IEEE */
|
||||
};
|
||||
#endif /* vax */
|
||||
|
||||
bool_t
|
||||
xdr_float(xdrs, fp)
|
||||
XDR *xdrs;
|
||||
float *fp;
|
||||
{
|
||||
#ifndef IEEEFP
|
||||
struct ieee_single is;
|
||||
struct vax_single vs, *vsp;
|
||||
struct sgl_limits *lim;
|
||||
size_t i;
|
||||
#endif
|
||||
switch (xdrs->x_op) {
|
||||
|
||||
case XDR_ENCODE:
|
||||
#ifdef IEEEFP
|
||||
return (XDR_PUTINT32(xdrs, (int32_t *)(void *)fp));
|
||||
#else
|
||||
vs = *((struct vax_single *)fp);
|
||||
for (i = 0, lim = sgl_limits;
|
||||
i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
|
||||
i++, lim++) {
|
||||
if ((vs.mantissa2 == lim->s.mantissa2) &&
|
||||
(vs.exp == lim->s.exp) &&
|
||||
(vs.mantissa1 == lim->s.mantissa1)) {
|
||||
is = lim->ieee;
|
||||
goto shipit;
|
||||
}
|
||||
}
|
||||
is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
|
||||
is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
|
||||
shipit:
|
||||
is.sign = vs.sign;
|
||||
return (XDR_PUTINT32(xdrs, (int32_t *)(void *)&is));
|
||||
#endif
|
||||
|
||||
case XDR_DECODE:
|
||||
#ifdef IEEEFP
|
||||
return (XDR_GETINT32(xdrs, (int32_t *)(void *)fp));
|
||||
#else
|
||||
vsp = (struct vax_single *)fp;
|
||||
if (!XDR_GETINT32(xdrs, (int32_t *)(void *)&is))
|
||||
return (FALSE);
|
||||
for (i = 0, lim = sgl_limits;
|
||||
i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
|
||||
i++, lim++) {
|
||||
if ((is.exp == lim->ieee.exp) &&
|
||||
(is.mantissa == lim->ieee.mantissa)) {
|
||||
*vsp = lim->s;
|
||||
goto doneit;
|
||||
}
|
||||
}
|
||||
vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
|
||||
vsp->mantissa2 = is.mantissa;
|
||||
vsp->mantissa1 = (is.mantissa >> 16);
|
||||
doneit:
|
||||
vsp->sign = is.sign;
|
||||
return (TRUE);
|
||||
#endif
|
||||
|
||||
case XDR_FREE:
|
||||
return (TRUE);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
#if defined(__vax__)
|
||||
/* What IEEE double precision floating point looks like on a Vax */
|
||||
struct ieee_double {
|
||||
unsigned int mantissa1 : 20;
|
||||
unsigned int exp : 11;
|
||||
unsigned int sign : 1;
|
||||
unsigned int mantissa2 : 32;
|
||||
};
|
||||
|
||||
/* Vax double precision floating point */
|
||||
struct vax_double {
|
||||
unsigned int mantissa1 : 7;
|
||||
unsigned int exp : 8;
|
||||
unsigned int sign : 1;
|
||||
unsigned int mantissa2 : 16;
|
||||
unsigned int mantissa3 : 16;
|
||||
unsigned int mantissa4 : 16;
|
||||
};
|
||||
|
||||
#define VAX_DBL_BIAS 0x81
|
||||
#define IEEE_DBL_BIAS 0x3ff
|
||||
#define MASK(nbits) ((1 << nbits) - 1)
|
||||
|
||||
static struct dbl_limits {
|
||||
struct vax_double d;
|
||||
struct ieee_double ieee;
|
||||
} dbl_limits[2] = {
|
||||
{{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
|
||||
{ 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
|
||||
{{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
|
||||
{ 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
|
||||
};
|
||||
|
||||
#endif /* vax */
|
||||
|
||||
|
||||
bool_t
|
||||
xdr_double(xdrs, dp)
|
||||
XDR *xdrs;
|
||||
double *dp;
|
||||
{
|
||||
#ifdef IEEEFP
|
||||
int32_t *i32p;
|
||||
bool_t rv;
|
||||
#else
|
||||
int32_t *lp;
|
||||
struct ieee_double id;
|
||||
struct vax_double vd;
|
||||
struct dbl_limits *lim;
|
||||
size_t i;
|
||||
#endif
|
||||
|
||||
switch (xdrs->x_op) {
|
||||
|
||||
case XDR_ENCODE:
|
||||
#ifdef IEEEFP
|
||||
i32p = (int32_t *)(void *)dp;
|
||||
#if (BYTE_ORDER == BIG_ENDIAN) || \
|
||||
(defined(__arm__) && !defined(__VFP_FP__))
|
||||
rv = XDR_PUTINT32(xdrs, i32p);
|
||||
if (!rv)
|
||||
return (rv);
|
||||
rv = XDR_PUTINT32(xdrs, i32p+1);
|
||||
#else
|
||||
rv = XDR_PUTINT32(xdrs, i32p+1);
|
||||
if (!rv)
|
||||
return (rv);
|
||||
rv = XDR_PUTINT32(xdrs, i32p);
|
||||
#endif
|
||||
return (rv);
|
||||
#else
|
||||
vd = *((struct vax_double *)dp);
|
||||
for (i = 0, lim = dbl_limits;
|
||||
i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
|
||||
i++, lim++) {
|
||||
if ((vd.mantissa4 == lim->d.mantissa4) &&
|
||||
(vd.mantissa3 == lim->d.mantissa3) &&
|
||||
(vd.mantissa2 == lim->d.mantissa2) &&
|
||||
(vd.mantissa1 == lim->d.mantissa1) &&
|
||||
(vd.exp == lim->d.exp)) {
|
||||
id = lim->ieee;
|
||||
goto shipit;
|
||||
}
|
||||
}
|
||||
id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
|
||||
id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
|
||||
id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
|
||||
(vd.mantissa3 << 13) |
|
||||
((vd.mantissa4 >> 3) & MASK(13));
|
||||
shipit:
|
||||
id.sign = vd.sign;
|
||||
lp = (int32_t *)(void *)&id;
|
||||
return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
|
||||
#endif
|
||||
|
||||
case XDR_DECODE:
|
||||
#ifdef IEEEFP
|
||||
i32p = (int32_t *)(void *)dp;
|
||||
#if BYTE_ORDER == BIG_ENDIAN || \
|
||||
(defined(__arm__) && !defined(__VFP_FP__))
|
||||
rv = XDR_GETINT32(xdrs, i32p);
|
||||
if (!rv)
|
||||
return (rv);
|
||||
rv = XDR_GETINT32(xdrs, i32p+1);
|
||||
#else
|
||||
rv = XDR_GETINT32(xdrs, i32p+1);
|
||||
if (!rv)
|
||||
return (rv);
|
||||
rv = XDR_GETINT32(xdrs, i32p);
|
||||
#endif
|
||||
return (rv);
|
||||
#else
|
||||
lp = (int32_t *)(void *)&id;
|
||||
if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(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 *)(void *)&vd);
|
||||
return (TRUE);
|
||||
#endif
|
||||
|
||||
case XDR_FREE:
|
||||
return (TRUE);
|
||||
}
|
||||
/* NOTREACHED */
|
||||
return (FALSE);
|
||||
}
|
||||
@@ -0,0 +1,269 @@
|
||||
/* $NetBSD: xdr_mem.c,v 1.17 2006/10/15 16:14:46 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: xdr_mem.c,v 1.17 2006/10/15 16:14:46 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* xdr_mem.h, XDR implementation using memory buffers.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* If you have some data to be interpreted as external data representation
|
||||
* or to be converted to external data representation in a memory buffer,
|
||||
* then this is the package for you.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdrmem_create,_xdrmem_create)
|
||||
#endif
|
||||
|
||||
static void xdrmem_destroy __P((XDR *));
|
||||
static bool_t xdrmem_getlong_aligned __P((XDR *, long *));
|
||||
static bool_t xdrmem_putlong_aligned __P((XDR *, const long *));
|
||||
static bool_t xdrmem_getlong_unaligned __P((XDR *, long *));
|
||||
static bool_t xdrmem_putlong_unaligned __P((XDR *, const long *));
|
||||
static bool_t xdrmem_getbytes __P((XDR *, char *, u_int));
|
||||
static bool_t xdrmem_putbytes __P((XDR *, const char *, u_int));
|
||||
/* XXX: w/64-bit pointers, u_int not enough! */
|
||||
static u_int xdrmem_getpos __P((XDR *));
|
||||
static bool_t xdrmem_setpos __P((XDR *, u_int));
|
||||
static int32_t *xdrmem_inline_aligned __P((XDR *, u_int));
|
||||
static int32_t *xdrmem_inline_unaligned __P((XDR *, u_int));
|
||||
|
||||
static const struct xdr_ops xdrmem_ops_aligned = {
|
||||
xdrmem_getlong_aligned,
|
||||
xdrmem_putlong_aligned,
|
||||
xdrmem_getbytes,
|
||||
xdrmem_putbytes,
|
||||
xdrmem_getpos,
|
||||
xdrmem_setpos,
|
||||
xdrmem_inline_aligned,
|
||||
xdrmem_destroy,
|
||||
NULL, /* xdrmem_control */
|
||||
};
|
||||
|
||||
static const struct xdr_ops xdrmem_ops_unaligned = {
|
||||
xdrmem_getlong_unaligned,
|
||||
xdrmem_putlong_unaligned,
|
||||
xdrmem_getbytes,
|
||||
xdrmem_putbytes,
|
||||
xdrmem_getpos,
|
||||
xdrmem_setpos,
|
||||
xdrmem_inline_unaligned,
|
||||
xdrmem_destroy,
|
||||
NULL, /* xdrmem_control */
|
||||
};
|
||||
|
||||
/*
|
||||
* The procedure xdrmem_create initializes a stream descriptor for a
|
||||
* memory buffer.
|
||||
*/
|
||||
void
|
||||
xdrmem_create(xdrs, addr, size, op)
|
||||
XDR *xdrs;
|
||||
char *addr;
|
||||
u_int size;
|
||||
enum xdr_op op;
|
||||
{
|
||||
|
||||
xdrs->x_op = op;
|
||||
xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1))
|
||||
? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
|
||||
xdrs->x_private = xdrs->x_base = addr;
|
||||
xdrs->x_handy = size;
|
||||
}
|
||||
|
||||
/*ARGSUSED*/
|
||||
static void
|
||||
xdrmem_destroy(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_getlong_aligned(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
long *lp;
|
||||
{
|
||||
|
||||
if (xdrs->x_handy < sizeof(int32_t))
|
||||
return (FALSE);
|
||||
xdrs->x_handy -= sizeof(int32_t);
|
||||
*lp = ntohl(*(u_int32_t *)xdrs->x_private);
|
||||
xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_putlong_aligned(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
const long *lp;
|
||||
{
|
||||
|
||||
if (xdrs->x_handy < sizeof(int32_t))
|
||||
return (FALSE);
|
||||
xdrs->x_handy -= sizeof(int32_t);
|
||||
*(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp);
|
||||
xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_getlong_unaligned(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
long *lp;
|
||||
{
|
||||
u_int32_t l;
|
||||
|
||||
if (xdrs->x_handy < sizeof(int32_t))
|
||||
return (FALSE);
|
||||
xdrs->x_handy -= sizeof(int32_t);
|
||||
memmove(&l, xdrs->x_private, sizeof(int32_t));
|
||||
*lp = ntohl(l);
|
||||
xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_putlong_unaligned(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
const long *lp;
|
||||
{
|
||||
u_int32_t l;
|
||||
|
||||
if (xdrs->x_handy < sizeof(int32_t))
|
||||
return (FALSE);
|
||||
xdrs->x_handy -= sizeof(int32_t);
|
||||
l = htonl((u_int32_t)*lp);
|
||||
memmove(xdrs->x_private, &l, sizeof(int32_t));
|
||||
xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_getbytes(xdrs, addr, len)
|
||||
XDR *xdrs;
|
||||
char *addr;
|
||||
u_int len;
|
||||
{
|
||||
|
||||
if (xdrs->x_handy < len)
|
||||
return (FALSE);
|
||||
xdrs->x_handy -= len;
|
||||
memmove(addr, xdrs->x_private, len);
|
||||
xdrs->x_private = (char *)xdrs->x_private + len;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_putbytes(xdrs, addr, len)
|
||||
XDR *xdrs;
|
||||
const char *addr;
|
||||
u_int len;
|
||||
{
|
||||
|
||||
if (xdrs->x_handy < len)
|
||||
return (FALSE);
|
||||
xdrs->x_handy -= len;
|
||||
memmove(xdrs->x_private, addr, len);
|
||||
xdrs->x_private = (char *)xdrs->x_private + len;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static u_int
|
||||
xdrmem_getpos(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
|
||||
/* XXX w/64-bit pointers, u_int not enough! */
|
||||
return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrmem_setpos(xdrs, pos)
|
||||
XDR *xdrs;
|
||||
u_int pos;
|
||||
{
|
||||
char *newaddr = xdrs->x_base + pos;
|
||||
char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy;
|
||||
|
||||
if ((long)newaddr > (long)lastaddr)
|
||||
return (FALSE);
|
||||
xdrs->x_private = newaddr;
|
||||
xdrs->x_handy = (int)((long)lastaddr - (long)newaddr);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static int32_t *
|
||||
xdrmem_inline_aligned(xdrs, len)
|
||||
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 = (char *)xdrs->x_private + len;
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int32_t *
|
||||
xdrmem_inline_unaligned(xdrs, len)
|
||||
XDR *xdrs;
|
||||
u_int len;
|
||||
{
|
||||
|
||||
return (0);
|
||||
}
|
||||
@@ -0,0 +1,805 @@
|
||||
/* $NetBSD: xdr_rec.c,v 1.31 2010/11/23 14:02:01 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: xdr_rec.c,v 1.31 2010/11/23 14:02:01 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
|
||||
* layer above tcp (for rpc's use).
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* These routines interface XDRSTREAMS to a tcp/ip connection.
|
||||
* There is a record marking layer between the xdr stream
|
||||
* and the tcp transport level. A record is composed on one or more
|
||||
* record fragments. A record fragment is a thirty-two bit header followed
|
||||
* by n bytes of data, where n is contained in the header. The header
|
||||
* is represented as a htonl(u_long). Thegh order bit encodes
|
||||
* whether or not the fragment is the last fragment of the record
|
||||
* (1 => fragment is last, 0 => more fragments to follow.
|
||||
* The other 31 bits encode the byte length of the fragment.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <netinet/in.h>
|
||||
|
||||
#include <err.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
#include <rpc/auth.h>
|
||||
#include <rpc/svc.h>
|
||||
#include <rpc/clnt.h>
|
||||
|
||||
#include "rpc_internal.h"
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdrrec_create,_xdrrec_create)
|
||||
__weak_alias(xdrrec_endofrecord,_xdrrec_endofrecord)
|
||||
__weak_alias(xdrrec_eof,_xdrrec_eof)
|
||||
__weak_alias(xdrrec_skiprecord,_xdrrec_skiprecord)
|
||||
#endif
|
||||
|
||||
static bool_t xdrrec_getlong __P((XDR *, long *));
|
||||
static bool_t xdrrec_putlong __P((XDR *, const long *));
|
||||
static bool_t xdrrec_getbytes __P((XDR *, char *, u_int));
|
||||
|
||||
static bool_t xdrrec_putbytes __P((XDR *, const char *, u_int));
|
||||
static u_int xdrrec_getpos __P((XDR *));
|
||||
static bool_t xdrrec_setpos __P((XDR *, u_int));
|
||||
static int32_t *xdrrec_inline __P((XDR *, u_int));
|
||||
static void xdrrec_destroy __P((XDR *));
|
||||
|
||||
static const struct xdr_ops xdrrec_ops = {
|
||||
xdrrec_getlong,
|
||||
xdrrec_putlong,
|
||||
xdrrec_getbytes,
|
||||
xdrrec_putbytes,
|
||||
xdrrec_getpos,
|
||||
xdrrec_setpos,
|
||||
xdrrec_inline,
|
||||
xdrrec_destroy,
|
||||
NULL, /* xdrrec_control */
|
||||
};
|
||||
|
||||
/*
|
||||
* A record is composed of one or more record fragments.
|
||||
* A record fragment is a four-byte header followed by zero to
|
||||
* 2**32-1 bytes. The header is treated as a long unsigned and is
|
||||
* encode/decoded to the network via htonl/ntohl. The low order 31 bits
|
||||
* are a byte count of the fragment. The highest order bit is a boolean:
|
||||
* 1 => this fragment is the last fragment of the record,
|
||||
* 0 => this fragment is followed by more fragment(s).
|
||||
*
|
||||
* The fragment/record machinery is not general; it is constructed to
|
||||
* meet the needs of xdr and rpc based on tcp.
|
||||
*/
|
||||
|
||||
#define LAST_FRAG ((u_int32_t)(1 << 31))
|
||||
|
||||
typedef struct rec_strm {
|
||||
char *tcp_handle;
|
||||
/*
|
||||
* out-goung bits
|
||||
*/
|
||||
int (*writeit) __P((char *, char *, int));
|
||||
char *out_base; /* output buffer (points to frag header) */
|
||||
char *out_finger; /* next output position */
|
||||
char *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) __P((char *, char *, int));
|
||||
u_long in_size; /* fixed size of the input buffer */
|
||||
char *in_base;
|
||||
char *in_finger; /* location of next byte to be had */
|
||||
char *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;
|
||||
|
||||
bool_t nonblock;
|
||||
bool_t in_haveheader;
|
||||
u_int32_t in_header;
|
||||
char *in_hdrp;
|
||||
int in_hdrlen;
|
||||
int in_reclen;
|
||||
int in_received;
|
||||
int in_maxrec;
|
||||
} RECSTREAM;
|
||||
|
||||
static u_int fix_buf_size __P((u_int));
|
||||
static bool_t flush_out __P((RECSTREAM *, bool_t));
|
||||
static bool_t fill_input_buf __P((RECSTREAM *));
|
||||
static bool_t get_input_bytes __P((RECSTREAM *, char *, u_int));
|
||||
static bool_t set_input_fragment __P((RECSTREAM *));
|
||||
static bool_t skip_input_bytes __P((RECSTREAM *, long));
|
||||
static bool_t realloc_stream __P((RECSTREAM *, int));
|
||||
|
||||
|
||||
/*
|
||||
* Create an xdr handle for xdrrec
|
||||
* xdrrec_create fills in xdrs. Sendsize and recvsize are
|
||||
* send and recv buffer sizes (0 => use default).
|
||||
* tcp_handle is an opaque handle that is passed as the first parameter to
|
||||
* the procedures readit and writeit. Readit and writeit are read and
|
||||
* write respectively. They are like the system
|
||||
* calls expect that they take an opaque handle rather than an fd.
|
||||
*/
|
||||
void
|
||||
xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
|
||||
XDR *xdrs;
|
||||
u_int sendsize;
|
||||
u_int recvsize;
|
||||
char *tcp_handle;
|
||||
/* like read, but pass it a tcp_handle, not sock */
|
||||
int (*readit) __P((char *, char *, int));
|
||||
/* like write, but pass it a tcp_handle, not sock */
|
||||
int (*writeit) __P((char *, char *, int));
|
||||
{
|
||||
RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));
|
||||
|
||||
if (rstrm == NULL) {
|
||||
warnx("xdrrec_create: out of memory");
|
||||
/*
|
||||
* This is bad. Should rework xdrrec_create to
|
||||
* return a handle, and in this case return NULL
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
rstrm->sendsize = sendsize = fix_buf_size(sendsize);
|
||||
rstrm->out_base = malloc(rstrm->sendsize);
|
||||
if (rstrm->out_base == NULL) {
|
||||
warnx("xdrrec_create: out of memory");
|
||||
mem_free(rstrm, sizeof(RECSTREAM));
|
||||
return;
|
||||
}
|
||||
|
||||
rstrm->recvsize = recvsize = fix_buf_size(recvsize);
|
||||
rstrm->in_base = malloc(recvsize);
|
||||
if (rstrm->in_base == NULL) {
|
||||
warnx("xdrrec_create: out of memory");
|
||||
mem_free(rstrm->out_base, sendsize);
|
||||
mem_free(rstrm, sizeof(RECSTREAM));
|
||||
return;
|
||||
}
|
||||
/*
|
||||
* now the rest ...
|
||||
*/
|
||||
xdrs->x_ops = &xdrrec_ops;
|
||||
xdrs->x_private = 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 *)(void *)rstrm->out_base;
|
||||
rstrm->out_finger += sizeof(u_int32_t);
|
||||
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;
|
||||
rstrm->in_haveheader = FALSE;
|
||||
rstrm->in_hdrlen = 0;
|
||||
rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
|
||||
rstrm->nonblock = FALSE;
|
||||
rstrm->in_reclen = 0;
|
||||
rstrm->in_received = 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* The reoutines defined below are the xdr ops which will go into the
|
||||
* xdr handle filled in by xdrrec_create.
|
||||
*/
|
||||
|
||||
static bool_t
|
||||
xdrrec_getlong(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
long *lp;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
|
||||
int32_t mylong;
|
||||
|
||||
/* first try the inline, fast case */
|
||||
if ((rstrm->fbtbc >= (long)sizeof(int32_t)) &&
|
||||
(((uintptr_t)rstrm->in_boundry - (uintptr_t)buflp) >= sizeof(int32_t))) {
|
||||
*lp = (long)ntohl((u_int32_t)(*buflp));
|
||||
rstrm->fbtbc -= sizeof(int32_t);
|
||||
rstrm->in_finger += sizeof(int32_t);
|
||||
} else {
|
||||
if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong,
|
||||
sizeof(int32_t)))
|
||||
return (FALSE);
|
||||
*lp = (long)ntohl((u_int32_t)mylong);
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrrec_putlong(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
const long *lp;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
|
||||
|
||||
if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
|
||||
/*
|
||||
* this case should almost never happen so the code is
|
||||
* inefficient
|
||||
*/
|
||||
rstrm->out_finger -= sizeof(int32_t);
|
||||
rstrm->frag_sent = TRUE;
|
||||
if (! flush_out(rstrm, FALSE))
|
||||
return (FALSE);
|
||||
dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
|
||||
rstrm->out_finger += sizeof(int32_t);
|
||||
}
|
||||
*dest_lp = (int32_t)htonl((u_int32_t)(*lp));
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t /* must manage buffers, fragments, and records */
|
||||
xdrrec_getbytes(xdrs, addr, len)
|
||||
XDR *xdrs;
|
||||
char *addr;
|
||||
u_int len;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
u_int current;
|
||||
|
||||
while (len > 0) {
|
||||
current = (u_int)rstrm->fbtbc;
|
||||
if (current == 0) {
|
||||
if (rstrm->last_frag)
|
||||
return (FALSE);
|
||||
if (! set_input_fragment(rstrm))
|
||||
return (FALSE);
|
||||
continue;
|
||||
}
|
||||
current = (len < current) ? len : current;
|
||||
if (! get_input_bytes(rstrm, addr, current))
|
||||
return (FALSE);
|
||||
addr += current;
|
||||
rstrm->fbtbc -= current;
|
||||
len -= current;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrrec_putbytes(xdrs, addr, len)
|
||||
XDR *xdrs;
|
||||
const char *addr;
|
||||
u_int len;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
size_t current;
|
||||
|
||||
while (len > 0) {
|
||||
current = (size_t)((u_long)rstrm->out_boundry -
|
||||
(u_long)rstrm->out_finger);
|
||||
current = (len < current) ? len : current;
|
||||
memmove(rstrm->out_finger, addr, current);
|
||||
rstrm->out_finger += current;
|
||||
addr += current;
|
||||
len -= current;
|
||||
if (rstrm->out_finger == rstrm->out_boundry) {
|
||||
rstrm->frag_sent = TRUE;
|
||||
if (! flush_out(rstrm, FALSE))
|
||||
return (FALSE);
|
||||
}
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static u_int
|
||||
xdrrec_getpos(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
|
||||
off_t pos;
|
||||
|
||||
pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)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 = (off_t) -1;
|
||||
break;
|
||||
}
|
||||
return ((u_int) pos);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrrec_setpos(xdrs, pos)
|
||||
XDR *xdrs;
|
||||
u_int pos;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
|
||||
u_int currpos = xdrrec_getpos(xdrs);
|
||||
int delta = currpos - pos;
|
||||
char *newpos;
|
||||
|
||||
if ((int)currpos != -1)
|
||||
switch (xdrs->x_op) {
|
||||
|
||||
case XDR_ENCODE:
|
||||
newpos = rstrm->out_finger - delta;
|
||||
if ((newpos > (char *)(void *)(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;
|
||||
|
||||
case XDR_FREE:
|
||||
break;
|
||||
}
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
static int32_t *
|
||||
xdrrec_inline(xdrs, len)
|
||||
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 *)(void *)rstrm->out_finger;
|
||||
rstrm->out_finger += len;
|
||||
}
|
||||
break;
|
||||
|
||||
case XDR_DECODE:
|
||||
if ((len <= (u_int)rstrm->fbtbc) &&
|
||||
((rstrm->in_finger + len) <= rstrm->in_boundry)) {
|
||||
buf = (int32_t *)(void *)rstrm->in_finger;
|
||||
rstrm->fbtbc -= len;
|
||||
rstrm->in_finger += len;
|
||||
}
|
||||
break;
|
||||
|
||||
case XDR_FREE:
|
||||
break;
|
||||
}
|
||||
return (buf);
|
||||
}
|
||||
|
||||
static void
|
||||
xdrrec_destroy(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
|
||||
|
||||
mem_free(rstrm->out_base, rstrm->sendsize);
|
||||
mem_free(rstrm->in_base, rstrm->recvsize);
|
||||
mem_free(rstrm, sizeof(RECSTREAM));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Exported routines to manage xdr records
|
||||
*/
|
||||
|
||||
/*
|
||||
* Before reading (deserializing from the stream, one should always call
|
||||
* this procedure to guarantee proper record alignment.
|
||||
*/
|
||||
bool_t
|
||||
xdrrec_skiprecord(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
enum xprt_stat xstat;
|
||||
|
||||
if (rstrm->nonblock) {
|
||||
if (__xdrrec_getrec(xdrs, &xstat, FALSE)) {
|
||||
rstrm->fbtbc = 0;
|
||||
return TRUE;
|
||||
}
|
||||
if (rstrm->in_finger == rstrm->in_boundry &&
|
||||
xstat == XPRT_MOREREQS) {
|
||||
rstrm->fbtbc = 0;
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
|
||||
if (! skip_input_bytes(rstrm, rstrm->fbtbc))
|
||||
return (FALSE);
|
||||
rstrm->fbtbc = 0;
|
||||
if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
|
||||
return (FALSE);
|
||||
}
|
||||
rstrm->last_frag = FALSE;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Look ahead fuction.
|
||||
* Returns TRUE iff there is no more input in the buffer
|
||||
* after consuming the rest of the current record.
|
||||
*/
|
||||
bool_t
|
||||
xdrrec_eof(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
|
||||
while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
|
||||
if (!skip_input_bytes(rstrm, rstrm->fbtbc))
|
||||
return (TRUE);
|
||||
rstrm->fbtbc = 0;
|
||||
if ((!rstrm->last_frag) && (!set_input_fragment(rstrm)))
|
||||
return (TRUE);
|
||||
}
|
||||
if (rstrm->in_finger == rstrm->in_boundry)
|
||||
return (TRUE);
|
||||
return (FALSE);
|
||||
}
|
||||
|
||||
/*
|
||||
* The client must tell the package when an end-of-record has occurred.
|
||||
* The second paraemters tells whether the record should be flushed to the
|
||||
* (output) tcp stream. (This let's the package support batched or
|
||||
* pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
|
||||
*/
|
||||
bool_t
|
||||
xdrrec_endofrecord(xdrs, sendnow)
|
||||
XDR *xdrs;
|
||||
bool_t sendnow;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
u_long len; /* fragment length */
|
||||
|
||||
if (sendnow || rstrm->frag_sent ||
|
||||
((u_long)rstrm->out_finger + sizeof(u_int32_t) >=
|
||||
(u_long)rstrm->out_boundry)) {
|
||||
rstrm->frag_sent = FALSE;
|
||||
return (flush_out(rstrm, TRUE));
|
||||
}
|
||||
len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
|
||||
sizeof(u_int32_t);
|
||||
*(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG);
|
||||
rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger;
|
||||
rstrm->out_finger += sizeof(u_int32_t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill the stream buffer with a record for a non-blocking connection.
|
||||
* Return true if a record is available in the buffer, false if not.
|
||||
*/
|
||||
bool_t
|
||||
__xdrrec_getrec(xdrs, statp, expectdata)
|
||||
XDR *xdrs;
|
||||
enum xprt_stat *statp;
|
||||
bool_t expectdata;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
ssize_t n;
|
||||
int fraglen;
|
||||
|
||||
if (!rstrm->in_haveheader) {
|
||||
n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp,
|
||||
(int)sizeof (rstrm->in_header) - rstrm->in_hdrlen);
|
||||
if (n == 0) {
|
||||
*statp = expectdata ? XPRT_DIED : XPRT_IDLE;
|
||||
return FALSE;
|
||||
}
|
||||
if (n < 0) {
|
||||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
rstrm->in_hdrp += n;
|
||||
rstrm->in_hdrlen += n;
|
||||
if (rstrm->in_hdrlen < (int)sizeof(rstrm->in_header)) {
|
||||
*statp = XPRT_MOREREQS;
|
||||
return FALSE;
|
||||
}
|
||||
rstrm->in_header = ntohl(rstrm->in_header);
|
||||
fraglen = (int)(rstrm->in_header & ~LAST_FRAG);
|
||||
if (fraglen == 0 || fraglen > rstrm->in_maxrec ||
|
||||
(rstrm->in_reclen + fraglen) > rstrm->in_maxrec) {
|
||||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
rstrm->in_reclen += fraglen;
|
||||
if ((u_int)rstrm->in_reclen > rstrm->recvsize) {
|
||||
if (!realloc_stream(rstrm, rstrm->in_reclen)) {
|
||||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (rstrm->in_header & LAST_FRAG) {
|
||||
rstrm->in_header &= ~LAST_FRAG;
|
||||
rstrm->last_frag = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
n = rstrm->readit(rstrm->tcp_handle,
|
||||
rstrm->in_base + rstrm->in_received,
|
||||
(rstrm->in_reclen - rstrm->in_received));
|
||||
|
||||
if (n < 0) {
|
||||
*statp = XPRT_DIED;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (n == 0) {
|
||||
*statp = expectdata ? XPRT_DIED : XPRT_IDLE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
rstrm->in_received += n;
|
||||
|
||||
if (rstrm->in_received == rstrm->in_reclen) {
|
||||
rstrm->in_haveheader = FALSE;
|
||||
rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
|
||||
rstrm->in_hdrlen = 0;
|
||||
if (rstrm->last_frag) {
|
||||
rstrm->fbtbc = rstrm->in_reclen;
|
||||
rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
|
||||
rstrm->in_finger = rstrm->in_base;
|
||||
rstrm->in_reclen = rstrm->in_received = 0;
|
||||
*statp = XPRT_MOREREQS;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
*statp = XPRT_MOREREQS;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
bool_t
|
||||
__xdrrec_setnonblock(xdrs, maxrec)
|
||||
XDR *xdrs;
|
||||
int maxrec;
|
||||
{
|
||||
RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
|
||||
|
||||
rstrm->nonblock = TRUE;
|
||||
if (maxrec == 0)
|
||||
maxrec = rstrm->recvsize;
|
||||
rstrm->in_maxrec = maxrec;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Internal useful routines
|
||||
*/
|
||||
static bool_t
|
||||
flush_out(rstrm, eor)
|
||||
RECSTREAM *rstrm;
|
||||
bool_t eor;
|
||||
{
|
||||
u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
|
||||
u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) -
|
||||
(u_long)(rstrm->frag_header) - sizeof(u_int32_t));
|
||||
|
||||
*(rstrm->frag_header) = htonl(len | eormask);
|
||||
len = (u_int32_t)((u_long)(rstrm->out_finger) -
|
||||
(u_long)(rstrm->out_base));
|
||||
if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
|
||||
!= (int)len)
|
||||
return (FALSE);
|
||||
rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
|
||||
rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t /* knows nothing about records! Only about input buffers */
|
||||
fill_input_buf(rstrm)
|
||||
RECSTREAM *rstrm;
|
||||
{
|
||||
char *where;
|
||||
u_int32_t i;
|
||||
int len;
|
||||
|
||||
if (rstrm->nonblock)
|
||||
return FALSE;
|
||||
where = rstrm->in_base;
|
||||
i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
|
||||
where += i;
|
||||
len = (u_int32_t)(rstrm->in_size - i);
|
||||
if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
|
||||
return (FALSE);
|
||||
rstrm->in_finger = where;
|
||||
where += len;
|
||||
rstrm->in_boundry = where;
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t /* knows nothing about records! Only about input buffers */
|
||||
get_input_bytes(rstrm, addr, len)
|
||||
RECSTREAM *rstrm;
|
||||
char *addr;
|
||||
u_int len;
|
||||
{
|
||||
u_int current;
|
||||
|
||||
if (rstrm->nonblock) {
|
||||
if (len > ((uintptr_t)rstrm->in_boundry - (uintptr_t)rstrm->in_finger))
|
||||
return FALSE;
|
||||
memcpy(addr, rstrm->in_finger, len);
|
||||
rstrm->in_finger += len;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
while (len > 0) {
|
||||
current = ((uintptr_t)rstrm->in_boundry -
|
||||
(uintptr_t)rstrm->in_finger);
|
||||
if (current == 0) {
|
||||
if (! fill_input_buf(rstrm))
|
||||
return (FALSE);
|
||||
continue;
|
||||
}
|
||||
current = (len < current) ? len : current;
|
||||
memmove(addr, rstrm->in_finger, current);
|
||||
rstrm->in_finger += current;
|
||||
addr += current;
|
||||
len -= current;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t /* next two bytes of the input stream are treated as a header */
|
||||
set_input_fragment(rstrm)
|
||||
RECSTREAM *rstrm;
|
||||
{
|
||||
u_int32_t header;
|
||||
|
||||
if (rstrm->nonblock)
|
||||
return FALSE;
|
||||
if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header)))
|
||||
return (FALSE);
|
||||
header = ntohl(header);
|
||||
rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
|
||||
/*
|
||||
* Sanity check. Try not to accept wildly incorrect
|
||||
* record sizes. Unfortunately, the only record size
|
||||
* we can positively identify as being 'wildly incorrect'
|
||||
* is zero. Ridiculously large record 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.
|
||||
*/
|
||||
if (header == 0)
|
||||
return(FALSE);
|
||||
rstrm->fbtbc = header & (~LAST_FRAG);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t /* consumes input bytes; knows nothing about records! */
|
||||
skip_input_bytes(rstrm, cnt)
|
||||
RECSTREAM *rstrm;
|
||||
long cnt;
|
||||
{
|
||||
u_int32_t current;
|
||||
|
||||
while (cnt > 0) {
|
||||
current = (size_t)((long)rstrm->in_boundry -
|
||||
(long)rstrm->in_finger);
|
||||
if (current == 0) {
|
||||
if (! fill_input_buf(rstrm))
|
||||
return (FALSE);
|
||||
continue;
|
||||
}
|
||||
current = ((u_int32_t)cnt < current) ? (u_int32_t)cnt : current;
|
||||
rstrm->in_finger += current;
|
||||
cnt -= current;
|
||||
}
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static u_int
|
||||
fix_buf_size(s)
|
||||
u_int s;
|
||||
{
|
||||
|
||||
if (s < 100)
|
||||
s = 4000;
|
||||
return (RNDUP(s));
|
||||
}
|
||||
|
||||
/*
|
||||
* Reallocate the input buffer for a non-block stream.
|
||||
*/
|
||||
static bool_t
|
||||
realloc_stream(rstrm, size)
|
||||
RECSTREAM *rstrm;
|
||||
int size;
|
||||
{
|
||||
ptrdiff_t diff;
|
||||
char *buf;
|
||||
|
||||
if ((u_int)size > rstrm->recvsize) {
|
||||
buf = realloc(rstrm->in_base, (size_t)size);
|
||||
if (buf == NULL)
|
||||
return FALSE;
|
||||
diff = buf - rstrm->in_base;
|
||||
rstrm->in_finger += diff;
|
||||
rstrm->in_base = buf;
|
||||
rstrm->in_boundry = buf + size;
|
||||
rstrm->recvsize = size;
|
||||
rstrm->in_size = size;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/* $NetBSD: xdr_reference.c,v 1.15 2008/04/25 17:44:44 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
|
||||
static char *sccsid = "@(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: xdr_reference.c,v 1.15 2008/04/25 17:44:44 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* xdr_reference.c, Generic XDR routines implementation.
|
||||
*
|
||||
* Copyright (C) 1987, Sun Microsystems, Inc.
|
||||
*
|
||||
* These are the "non-trivial" xdr primitives used to serialize and de-serialize
|
||||
* "pointers". See xdr.h for more info on the interface to xdr.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdr_pointer,_xdr_pointer)
|
||||
__weak_alias(xdr_reference,_xdr_reference)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XDR an indirect pointer
|
||||
* xdr_reference is for recursively translating a structure that is
|
||||
* referenced by a pointer inside the structure that is currently being
|
||||
* translated. pp references a pointer to storage. If *pp is null
|
||||
* the necessary storage is allocated.
|
||||
* size is the sizeof the referneced structure.
|
||||
* proc is the routine to handle the referenced structure.
|
||||
*/
|
||||
bool_t
|
||||
xdr_reference(xdrs, pp, size, proc)
|
||||
XDR *xdrs;
|
||||
caddr_t *pp; /* the pointer to work on */
|
||||
u_int size; /* size of the object pointed to */
|
||||
xdrproc_t proc; /* xdr routine to handle the object */
|
||||
{
|
||||
caddr_t loc = *pp;
|
||||
bool_t stat;
|
||||
|
||||
if (loc == NULL)
|
||||
switch (xdrs->x_op) {
|
||||
case XDR_FREE:
|
||||
return (TRUE);
|
||||
|
||||
case XDR_DECODE:
|
||||
*pp = loc = mem_alloc(size);
|
||||
if (loc == NULL) {
|
||||
warnx("xdr_reference: out of memory");
|
||||
return (FALSE);
|
||||
}
|
||||
memset(loc, 0, size);
|
||||
break;
|
||||
|
||||
case XDR_ENCODE:
|
||||
break;
|
||||
}
|
||||
|
||||
stat = (*proc)(xdrs, loc);
|
||||
|
||||
if (xdrs->x_op == XDR_FREE) {
|
||||
mem_free(loc, size);
|
||||
*pp = NULL;
|
||||
}
|
||||
return (stat);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* xdr_pointer():
|
||||
*
|
||||
* XDR a pointer to a possibly recursive data structure. This
|
||||
* differs with xdr_reference in that it can serialize/deserialiaze
|
||||
* trees correctly.
|
||||
*
|
||||
* What's sent is actually a union:
|
||||
*
|
||||
* union object_pointer switch (boolean b) {
|
||||
* case TRUE: object_data data;
|
||||
* case FALSE: void nothing;
|
||||
* }
|
||||
*
|
||||
* > objpp: Pointer to the pointer to the object.
|
||||
* > obj_size: size of the object.
|
||||
* > xdr_obj: routine to XDR an object.
|
||||
*
|
||||
*/
|
||||
bool_t
|
||||
xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
|
||||
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));
|
||||
}
|
||||
@@ -0,0 +1,203 @@
|
||||
/* $NetBSD: xdr_stdio.c,v 1.17 2006/10/15 16:14:46 christos Exp $ */
|
||||
|
||||
/*
|
||||
* Sun RPC is a product of Sun Microsystems, Inc. and is provided for
|
||||
* unrestricted use provided that this legend is included on all tape
|
||||
* media and as a part of the software program in whole or part. Users
|
||||
* may copy or modify Sun RPC without charge, but are not authorized
|
||||
* to license or distribute it to anyone else except as part of a product or
|
||||
* program developed by the user.
|
||||
*
|
||||
* SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
|
||||
* WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun RPC is provided with no support and without any obligation on the
|
||||
* part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
#if defined(LIBC_SCCS) && !defined(lint)
|
||||
#if 0
|
||||
static char *sccsid = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
|
||||
static char *sccsid = "@(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";
|
||||
#else
|
||||
__RCSID("$NetBSD: xdr_stdio.c,v 1.17 2006/10/15 16:14:46 christos Exp $");
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* xdr_stdio.c, XDR implementation on standard i/o file.
|
||||
*
|
||||
* Copyright (C) 1984, Sun Microsystems, Inc.
|
||||
*
|
||||
* This set of routines implements a XDR on a stdio stream.
|
||||
* XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
|
||||
* from the stream.
|
||||
*/
|
||||
|
||||
#include "namespace.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <rpc/types.h>
|
||||
#include <rpc/xdr.h>
|
||||
|
||||
#ifdef __weak_alias
|
||||
__weak_alias(xdrstdio_create,_xdrstdio_create)
|
||||
#endif
|
||||
|
||||
static void xdrstdio_destroy __P((XDR *));
|
||||
static bool_t xdrstdio_getlong __P((XDR *, long *));
|
||||
static bool_t xdrstdio_putlong __P((XDR *, const long *));
|
||||
static bool_t xdrstdio_getbytes __P((XDR *, char *, u_int));
|
||||
static bool_t xdrstdio_putbytes __P((XDR *, const char *, u_int));
|
||||
static u_int xdrstdio_getpos __P((XDR *));
|
||||
static bool_t xdrstdio_setpos __P((XDR *, u_int));
|
||||
static int32_t *xdrstdio_inline __P((XDR *, u_int));
|
||||
|
||||
/*
|
||||
* Ops vector for stdio type XDR
|
||||
*/
|
||||
static const struct xdr_ops xdrstdio_ops = {
|
||||
xdrstdio_getlong, /* deseraialize a long int */
|
||||
xdrstdio_putlong, /* seraialize a long int */
|
||||
xdrstdio_getbytes, /* deserialize counted bytes */
|
||||
xdrstdio_putbytes, /* serialize counted bytes */
|
||||
xdrstdio_getpos, /* get offset in the stream */
|
||||
xdrstdio_setpos, /* set offset in the stream */
|
||||
xdrstdio_inline, /* prime stream for inline macros */
|
||||
xdrstdio_destroy, /* destroy stream */
|
||||
NULL, /* xdrstdio_control */
|
||||
};
|
||||
|
||||
/*
|
||||
* Initialize a stdio xdr stream.
|
||||
* Sets the xdr stream handle xdrs for use on the stream file.
|
||||
* Operation flag is set to op.
|
||||
*/
|
||||
void
|
||||
xdrstdio_create(xdrs, file, op)
|
||||
XDR *xdrs;
|
||||
FILE *file;
|
||||
enum xdr_op op;
|
||||
{
|
||||
|
||||
xdrs->x_op = op;
|
||||
xdrs->x_ops = &xdrstdio_ops;
|
||||
xdrs->x_private = file;
|
||||
xdrs->x_handy = 0;
|
||||
xdrs->x_base = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Destroy a stdio xdr stream.
|
||||
* Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
|
||||
*/
|
||||
static void
|
||||
xdrstdio_destroy(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
(void)fflush((FILE *)xdrs->x_private);
|
||||
/* XXX: should we close the file ?? */
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrstdio_getlong(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
long *lp;
|
||||
{
|
||||
u_int32_t temp;
|
||||
|
||||
if (fread(&temp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
|
||||
return (FALSE);
|
||||
*lp = (long)ntohl(temp);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrstdio_putlong(xdrs, lp)
|
||||
XDR *xdrs;
|
||||
const long *lp;
|
||||
{
|
||||
int32_t mycopy = htonl((u_int32_t)*lp);
|
||||
|
||||
if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrstdio_getbytes(xdrs, addr, len)
|
||||
XDR *xdrs;
|
||||
char *addr;
|
||||
u_int len;
|
||||
{
|
||||
|
||||
if ((len != 0) && (fread(addr, (size_t)len, 1, (FILE *)xdrs->x_private) != 1))
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrstdio_putbytes(xdrs, addr, len)
|
||||
XDR *xdrs;
|
||||
const char *addr;
|
||||
u_int len;
|
||||
{
|
||||
|
||||
if ((len != 0) && (fwrite(addr, (size_t)len, 1,
|
||||
(FILE *)xdrs->x_private) != 1))
|
||||
return (FALSE);
|
||||
return (TRUE);
|
||||
}
|
||||
|
||||
static u_int
|
||||
xdrstdio_getpos(xdrs)
|
||||
XDR *xdrs;
|
||||
{
|
||||
|
||||
return ((u_int) ftell((FILE *)xdrs->x_private));
|
||||
}
|
||||
|
||||
static bool_t
|
||||
xdrstdio_setpos(xdrs, pos)
|
||||
XDR *xdrs;
|
||||
u_int pos;
|
||||
{
|
||||
|
||||
return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
|
||||
FALSE : TRUE);
|
||||
}
|
||||
|
||||
/* ARGSUSED */
|
||||
static int32_t *
|
||||
xdrstdio_inline(xdrs, len)
|
||||
XDR *xdrs;
|
||||
u_int len;
|
||||
{
|
||||
|
||||
/*
|
||||
* Must do some work to implement this: must insure
|
||||
* enough data in the underlying stdio buffer,
|
||||
* that the buffer is aligned so that we can indirect through a
|
||||
* long *, and stuff this pointer in xdrs->x_buf. Doing
|
||||
* a fread or fwrite to a scratch buffer would defeat
|
||||
* most of the gains to be had here and require storage
|
||||
* management on this buffer, so we don't do this.
|
||||
*/
|
||||
return (NULL);
|
||||
}
|
||||
Reference in New Issue
Block a user