pax_global_header00006660000000000000000000000064126134504010014506gustar00rootroot0000000000000052 comment=e9cefd2ebfa0a5fc25932cc1088663d39c27e549 ntirpc-1.3.1/000077500000000000000000000000001261345040100130075ustar00rootroot00000000000000ntirpc-1.3.1/.gitignore000066400000000000000000000012351261345040100150000ustar00rootroot00000000000000# files generated by autoconf, automake, autoheader and libtoolize aclocal.m4 autom4te.cache compile config.guess config.log config.sub configure depcomp install-sh libtool ltmain.sh Makefile.in missing config.h.in m4/* # files generated by configure confdefs.h config.status conftest conftest.c conftest.cpp conftest.er1 conftest.err .deps Makefile config.h stamp-h1 libtirpc.pc # file generated during compilation *.o *.lo .libs lib*.a src/libtirpc.la src/libtirpc_la-*.lo libntirpc.pc *.la # # generic editor backup et al *~ # cscope database files cscope.* # files generated by patches *.patch *.rej *.orig # files generated by debugging .gdb_history .gdbinit core ntirpc-1.3.1/AUTHORS000066400000000000000000000001771261345040100140640ustar00rootroot00000000000000Gilles Quillard Antoine Fraticelli Matt Benjamin ntirpc-1.3.1/CMakeLists.txt000066400000000000000000000124031261345040100155470ustar00rootroot00000000000000# New TI-RPC Cmake # Current version as of Fedora 16. Not tested with earlier. cmake_minimum_required(VERSION 2.6.3) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/modules/") # Add maintainer mode for (mainly) strict builds include(${CMAKE_SOURCE_DIR}/cmake/maintainer_mode.cmake) project(NTIRPC C) # version numbers set(NTIRPC_MAJOR_VERSION 1) set(NTIRPC_MINOR_VERSION 3) set(NTIRPC_PATCH_LEVEL 1) set(VERSION_COMMENT "Full-duplex and bi-directional ONC RPC on TCP." ) # version string used for packaging set(NTIRPC_VERSION "${NTIRPC_MAJOR_VERSION}.${NTIRPC_MINOR_VERSION}.${NTIRPC_PATCH_LEVEL}") # Install destination, if built standalone get_property(USE_LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) if (USE_LIB64) set(LIB_INSTALL_DIR lib64 CACHE PATH "Specify name of libdir inside install path") else (USE_LIB64) set(LIB_INSTALL_DIR lib CACHE PATH "Specify name of libdir inside install path") endif (USE_LIB64) set(SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES}) include(GetGitRevisionDescription) get_git_head_revision(GIT_REFSPEC _GIT_HEAD_COMMIT) git_describe(_GIT_DESCRIBE) # Allow overriding of prefix if (OVERRIDE_INSTALL_PREFIX) set(CMAKE_INSTALL_PREFIX ${OVERRIDE_INSTALL_PREFIX} CACHE PATH "Install prefix" FORCE) endif(OVERRIDE_INSTALL_PREFIX) message(STATUS "OVERRIDE_INSTALL_PREFIX = ${OVERRIDE_INSTALL_PREFIX}") # Set default base directory set(NTIRPC_BASE_DIR ${PROJECT_SOURCE_DIR} CACHE PATH "Path to base source directory of NTIRPC") # Build configure options option (USE_GSS "enable RPCSEC_GSS support" ON) option(TIRPC_EPOLL "platform supports EPOLL or emulation" ON) option(USE_RPC_RDMA "platform supports RDMA" OFF) if (USE_RPC_RDMA) find_package(RDMA REQUIRED) include_directories(${RDMA_INCLUDE_DIR}) set(SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${RDMA_LIBRARY}) endif(USE_RPC_RDMA) # MSPAC support -lwbclient link flag option(_MSPAC_SUPPORT "enable mspac Winbind support" OFF) # Choose a shortcut build config IF(BUILD_CONFIG) INCLUDE( ${CMAKE_SOURCE_DIR}/cmake/build_configurations/${BUILD_CONFIG}.cmake) ENDIF() # Build source locations and parameters set(ALLOCATOR "jemalloc" CACHE STRING "specify the memory allocator to use: jemalloc|tcmalloc|libc") # Find packages and libs we need for building include(CheckIncludeFiles) include(TestBigEndian) if(${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(LINUX ON) endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux") if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") set(FREEBSD ON) endif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") if(${CMAKE_SYSTEM_NAME} MATCHES "Windows") set(WINDOWS ON) if(${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") set(MSVC ON) endif(${CMAKE_CXX_COMPILER_ID} MATCHES "MSVC") endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows") check_include_files(stdbool.h HAVE_STDBOOL_H) check_include_files(strings.h HAVE_STRINGS_H) check_include_files(string.h HAVE_STRING_H) TEST_BIG_ENDIAN(BIGENDIAN) if(${BIGENDIAN}) set(WORDS_BIGENDIAN ON) else() set(WORDS_BIGENDIAN OFF) endif(${BIGENDIAN}) find_package(Threads REQUIRED) find_package(Krb5 REQUIRED gssapi) if(KRB5_FOUND) set(HAVE_KRB5 ON) set(KRB5_VERSION 194) # hand code until we do krb5-config --version magic set(_HAVE_GSSAPI ON) endif(KRB5_FOUND) if(_MSPAC_SUPPORT) find_package(WBclient REQUIRED) set(SYSTEM_LIBRARIES ${WBclient_LIBRARIES} ${SYSTEM_LIBRARIES}) endif(_MSPAC_SUPPORT) if (FREEBSD) set(EXTRA_INCLUDE_DIR "/opt/ganesha/include") else() # workaround bug in some include_directories when no extra includes set(EXTRA_INCLUDE_DIR "${NTIRPC_BASE_DIR}/ntirpc/") endif(FREEBSD) add_definitions(-DHAVE_CONFIG_H) if (MSVC) add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif(MSVC) include_directories(BEFORE "${PROJECT_BINARY_DIR}" "${NTIRPC_BASE_DIR}/ntirpc/" "${EXTRA_INCLUDE_DIR}" ) # Find misc system libs find_library(LIBRT rt) # extended Pthreads functions find_library(LIBNSL nsl) # sockets set(SYSTEM_LIBRARIES ${LIBTIRPC_LIBRARIES} ${KRB5_LIBRARIES} gssapi_krb5 ${SYSTEM_LIBRARIES} ${LIBRT} ${LIBNSL} ) set(LIBNTIRPC_MAP "${PROJECT_BINARY_DIR}/src/libntirpc.map") # subst files (need add_custom_command for dependency, fyi) configure_file( "${NTIRPC_BASE_DIR}/src/libntirpc.map.in.cmake" "${PROJECT_BINARY_DIR}/libntirpc.map" ) add_subdirectory(src) # display configuration vars message(STATUS) message(STATUS "-------------------------------------------------------") message(STATUS "TIRPC_EPOLL = ${TIRPC_EPOLL}") message(STATUS "USE_RPC_RDMA = ${USE_RPC_RDMA}") #force command line options to be stored in cache set(_MSPAC_SUPPORT ${_MSPAC_SUPPORT} CACHE BOOL "compile with MSPAC extensions" FORCE) set(TIRPC_EPOLL ${TIRPC_EPOLL} CACHE BOOL "platform has EPOLL or emulation" FORCE) # grist files configure_file( "${NTIRPC_BASE_DIR}/config-h.in.cmake" "${PROJECT_BINARY_DIR}/config.h" ) configure_file( "${NTIRPC_BASE_DIR}/version-h.in.cmake" "${PROJECT_BINARY_DIR}/ntirpc/version.h" ) configure_file( "${NTIRPC_BASE_DIR}/libntirpc.pc.in.cmake" "${PROJECT_BINARY_DIR}/libntirpc.pc" ) ########### install files ############### install(FILES ${PROJECT_BINARY_DIR}/libntirpc.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) install(DIRECTORY ${NTIRPC_BASE_DIR}/ntirpc DESTINATION include) install(FILES ${PROJECT_BINARY_DIR}/ntirpc/version.h DESTINATION include/ntirpc) ntirpc-1.3.1/COPYING000066400000000000000000000027041261345040100140450ustar00rootroot00000000000000/* * Copyright (c) Copyright (c) Bull S.A. 2005 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. The name of the author may not be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ ntirpc-1.3.1/ChangeLog000066400000000000000000000163001261345040100145610ustar00rootroot000000000000002008-11-19 Steve Dickson * Version 0.1.10 released. commit 32ec5931e3debf208972d5146578f08dc113a9b6 Merge: 338af7f... 92cf0dd... Author: Steve Dickson Date: Mon Nov 17 12:26:22 2008 -0500 Merge branch 'master' of git://git.infradead.org/~steved/libtirpc commit 92cf0dde310ca341a2f29ff66b19eeb9994a649a Author: Ian Kent Date: Tue Oct 28 11:19:07 2008 -0400 Fixed a warings the IPV6 client routines Signed-off-by: Steve Dickson commit 338af7f9f00e096b65a6d823f885c4eeaf1d1f8c Author: Steve Dickson Date: Mon Oct 27 12:46:54 2008 -0400 __rpc_taddr2uaddr_af() assumes the netbuf to always have a non-zero data. This is a bad assumption and can lead to a seg-fault. This patch adds a check for zero length and returns NULL when found. Signed-off-by: Steve Dickson commit d9a5ae7079d001a9e3b9b384f9153f591a7158bd Author: Olaf Kirch Date: Tue Sep 30 15:10:43 2008 -0400 Fix __rpc_getconfip __rpc_getconfip is supposed to return the first netconf entry supporting tcp or udp, respectively. The code will currently return the *last* entry, plus it will leak memory when there is more than one such entry. This patch fixes this issue. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit 6c487efe74adb5c29f7bee5bd51b3ebef4968f7d Author: Olaf Kirch Date: Tue Sep 30 15:09:06 2008 -0400 Fix getpeereid getpeereid fails because it uses an incorrect getsockopt call to obtain the peer credentials on a AF_LOCAL socket. This in turn will cause all RPC services to be registered with rpcbind to show up as having been registered by "unknown". This has a serious impact on security - a service owned by "unknown" can essentially be unregistered (and thus replaced) by anyone. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit 851b0f5c6dca22d634603f03f0a5e3e35c6db867 Author: Olaf Kirch Date: Tue Sep 30 15:08:07 2008 -0400 svc_getcaller_netbuf macro seems broken I haven't found any documentation, but the comment in the header file seems to suggest that svc_getcaller_netbuf should return the xp_rtaddr netbuf. Returning the address of the socket descripor seems to be wrong at any rate. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit d94b92d5125242ce595c1baf42a1e6d1004b7756 Author: Olaf Kirch Date: Tue Sep 30 15:06:54 2008 -0400 Introduce __rpc_set_netbuf helper The RPC code contains a number of places where a netbuf is initialized with some data. All the mem_alloc/memcpy stuff is open-coded. Introduce a helper function and convert the code. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit da5f9861ea3bae59c8eead26d38334721caa9f0a Author: Olaf Kirch Date: Tue Sep 30 15:05:20 2008 -0400 Kill map_ipv4_to_ipv6 After the change to svc_vc.c performed in the previous patch, this function is no longer needed. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit 59c374c4b507aeca957ed0096d98006edf601375 Author: Olaf Kirch Date: Tue Sep 30 15:04:17 2008 -0400 Fix xp_raddr handling in svc_fd_create etc Currently svc_fd_create tries to do some clever tricks with IPv4/v6 address mapping. This is broken for several reasons. 1. We don't want IPv4 based transport to look like IPv6 transports. Old applications compiled against tirpc will expect AF_INET addresses, and are not equipped to deal with AF_INET6. 2. There's a buffer overflow. memcpy(&sin6, &ss, sizeof(ss)); copies a full struct sockaddr to a sockaddr_in6 on the stack. Unlikely to be exploitable, but I wonder if this ever worked.... Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit 628788c1cc84c86ee4cb36ee5d4fe8954e90fca5 Author: Steve Dickson Date: Tue Sep 16 11:32:31 2008 -0400 - Fixed version-info in src/Makefile.am to reflect the correct version - Fixed some of warnings in: src/auth_time.c, src/clnt_dg.c and src/clnt_raw.c - Added some #ifdef NOTUSED around some code in src/rpbc_clnt.c that was not being used... Signed-off-by: Steve Dickson commit 9e7ba0c7a02031294fefadfbca42b3dd5f2d841f Author: Olaf Kirch Date: Tue Sep 16 08:46:29 2008 -0400 Fix for taddr2addr conversion bug of local addresses When converting af_local socket addresses in taddr2uaddr, an incorrect sizeof() would result in a truncated path string. As a result, rpcbind will report the local /var/lib/rpcbind address to clients as "/v" on a 32bit machine. Signed-off-by: okir@suse.de Signed-off-by: Steve Dickson commit ea9f048761d0b9a2ab6310bffa07351f0b04d8c5 Author: Olaf Kirch Date: Tue Sep 2 12:11:15 2008 -0400 Always make IPv6 sockets V6ONLY Assume you have a netconfig file looking like this: udp tpi_clts v inet udp - - udp6 tpi_clts v inet6 udp - - ... a call to svc_tli_create(... &someaddr, "udp") will fail to create an IPv6 server socket. The problem is that on Linux, passive IPv6 sockets will also accept packets/connections from IPv4, and will simply map the sender's address to an IPv6 mapped IPv4 address. So if you want to bind both a UDPv4 and UDPv6 socket to the same port, this will fail with EADDRINUSE. The way to avoid this behavior is to change the socket to V6ONLY, which tells the kernel to avoid the autmatic mapping. The change proposed in the patch below does this. I *think* this is a good place to do this, as it will also fix applications that do not use svc_tli_create() - such as rpcbind, which creates the sockets on its own using __rpc_nconf2fd. I think this also improves portability, as BSD code assumes BSD behavior, where this mapping does not occur either. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson commit 95c8f7227e6b15f2e430d7b87dadc95b2acd4a61 Author: Olaf Kirch Date: Tue Sep 2 12:09:39 2008 -0400 Fix incorrect sizeof() in __rpc_getbroadifs __rpc_getbroadifs returns bad broadcast addresses on 32bit machines because when copying the broadcast addresses, ite applies the sizeof() operator to a pointer to a sockaddr, rather than the sockaddr itself. Signed-off-by: Olaf Kirch Signed-off-by: Steve Dickson 2004-10-13 Antoine Fraticelli * Version 0.1 released. 2005-01-07 Gilles Quillard * Version 0.1.5 Fix problems links to the use of Kerberos. ntirpc-1.3.1/INSTALL000066400000000000000000000363321261345040100140470ustar00rootroot00000000000000Installation Instructions ************************* Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Copying and distribution of this file, with or without modification, are permitted in any medium without royalty provided the copyright notice and this notice are preserved. This file is offered as-is, without warranty of any kind. Basic Installation ================== Briefly, the shell commands `./configure; make; make install' should configure, build, and install this package. The following more-detailed instructions are generic; see the `README' file for instructions specific to this package. Some packages provide this `INSTALL' file but do not implement all of the features documented below. The lack of an optional feature in a given package is not necessarily a bug. More recommendations for GNU packages can be found in *note Makefile Conventions: (standards)Makefile Conventions. The `configure' shell script attempts to guess correct values for various system-dependent variables used during compilation. It uses those values to create a `Makefile' in each directory of the package. It may also create one or more `.h' files containing system-dependent definitions. Finally, it creates a shell script `config.status' that you can run in the future to recreate the current configuration, and a file `config.log' containing compiler output (useful mainly for debugging `configure'). It can also use an optional file (typically called `config.cache' and enabled with `--cache-file=config.cache' or simply `-C') that saves the results of its tests to speed up reconfiguring. Caching is disabled by default to prevent problems with accidental use of stale cache files. If you need to do unusual things to compile the package, please try to figure out how `configure' could check whether to do them, and mail diffs or instructions to the address given in the `README' so they can be considered for the next release. If you are using the cache, and at some point `config.cache' contains results you don't want to keep, you may remove or edit it. The file `configure.ac' (or `configure.in') is used to create `configure' by a program called `autoconf'. You need `configure.ac' if you want to change it or regenerate `configure' using a newer version of `autoconf'. The simplest way to compile this package is: 1. `cd' to the directory containing the package's source code and type `./configure' to configure the package for your system. Running `configure' might take a while. While running, it prints some messages telling which features it is checking for. 2. Type `make' to compile the package. 3. Optionally, type `make check' to run any self-tests that come with the package, generally using the just-built uninstalled binaries. 4. Type `make install' to install the programs and any data files and documentation. When installing into a prefix owned by root, it is recommended that the package be configured and built as a regular user, and only the `make install' phase executed with root privileges. 5. Optionally, type `make installcheck' to repeat any self-tests, but this time using the binaries in their final installed location. This target does not install anything. Running this target as a regular user, particularly if the prior `make install' required root privileges, verifies that the installation completed correctly. 6. You can remove the program binaries and object files from the source code directory by typing `make clean'. To also remove the files that `configure' created (so you can compile the package for a different kind of computer), type `make distclean'. There is also a `make maintainer-clean' target, but that is intended mainly for the package's developers. If you use it, you may have to get all sorts of other programs in order to regenerate files that came with the distribution. 7. Often, you can also type `make uninstall' to remove the installed files again. In practice, not all packages have tested that uninstallation works correctly, even though it is required by the GNU Coding Standards. 8. Some packages, particularly those that use Automake, provide `make distcheck', which can by used by developers to test that all other targets like `make install' and `make uninstall' work correctly. This target is generally not run by end users. Compilers and Options ===================== Some systems require unusual options for compilation or linking that the `configure' script does not know about. Run `./configure --help' for details on some of the pertinent environment variables. You can give `configure' initial values for configuration parameters by setting variables in the command line or in the environment. Here is an example: ./configure CC=c99 CFLAGS=-g LIBS=-lposix *Note Defining Variables::, for more details. Compiling For Multiple Architectures ==================================== You can compile the package for more than one kind of computer at the same time, by placing the object files for each architecture in their own directory. To do this, you can use GNU `make'. `cd' to the directory where you want the object files and executables to go and run the `configure' script. `configure' automatically checks for the source code in the directory that `configure' is in and in `..'. This is known as a "VPATH" build. With a non-GNU `make', it is safer to compile the package for one architecture at a time in the source code directory. After you have installed the package for one architecture, use `make distclean' before reconfiguring for another architecture. On MacOS X 10.5 and later systems, you can create libraries and executables that work on multiple system types--known as "fat" or "universal" binaries--by specifying multiple `-arch' options to the compiler but only a single `-arch' option to the preprocessor. Like this: ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ CPP="gcc -E" CXXCPP="g++ -E" This is not guaranteed to produce working output in all cases, you may have to build one architecture at a time and combine the results using the `lipo' tool if you have problems. Installation Names ================== By default, `make install' installs the package's commands under `/usr/local/bin', include files under `/usr/local/include', etc. You can specify an installation prefix other than `/usr/local' by giving `configure' the option `--prefix=PREFIX', where PREFIX must be an absolute file name. You can specify separate installation prefixes for architecture-specific files and architecture-independent files. If you pass the option `--exec-prefix=PREFIX' to `configure', the package uses PREFIX as the prefix for installing programs and libraries. Documentation and other data files still use the regular prefix. In addition, if you use an unusual directory layout you can give options like `--bindir=DIR' to specify different values for particular kinds of files. Run `configure --help' for a list of the directories you can set and what kinds of files go in them. In general, the default for these options is expressed in terms of `${prefix}', so that specifying just `--prefix' will affect all of the other directory specifications that were not explicitly provided. The most portable way to affect installation locations is to pass the correct locations to `configure'; however, many packages provide one or both of the following shortcuts of passing variable assignments to the `make install' command line to change installation locations without having to reconfigure or recompile. The first method involves providing an override variable for each affected directory. For example, `make install prefix=/alternate/directory' will choose an alternate location for all directory configuration variables that were expressed in terms of `${prefix}'. Any directories that were specified during `configure', but not in terms of `${prefix}', must each be overridden at install time for the entire installation to be relocated. The approach of makefile variable overrides for each directory variable is required by the GNU Coding Standards, and ideally causes no recompilation. However, some platforms have known limitations with the semantics of shared libraries that end up requiring recompilation when using this method, particularly noticeable in packages that use GNU Libtool. The second method involves providing the `DESTDIR' variable. For example, `make install DESTDIR=/alternate/directory' will prepend `/alternate/directory' before all installation names. The approach of `DESTDIR' overrides is not required by the GNU Coding Standards, and does not work on platforms that have drive letters. On the other hand, it does better at avoiding recompilation issues, and works well even when some directory options were not specified in terms of `${prefix}' at `configure' time. Optional Features ================= If the package supports it, you can cause programs to be installed with an extra prefix or suffix on their names by giving `configure' the option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. Some packages pay attention to `--enable-FEATURE' options to `configure', where FEATURE indicates an optional part of the package. They may also pay attention to `--with-PACKAGE' options, where PACKAGE is something like `gnu-as' or `x' (for the X Window System). The `README' should mention any `--enable-' and `--with-' options that the package recognizes. For packages that use the X Window System, `configure' can usually find the X include and library files automatically, but if it doesn't, you can use the `configure' options `--x-includes=DIR' and `--x-libraries=DIR' to specify their locations. Some packages offer the ability to configure how verbose the execution of `make' will be. For these packages, running `./configure --enable-silent-rules' sets the default to minimal output, which can be overridden with `make V=1'; while running `./configure --disable-silent-rules' sets the default to verbose, which can be overridden with `make V=0'. Particular systems ================== On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC is not installed, it is recommended to use the following options in order to use an ANSI C compiler: ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" and if that doesn't work, install pre-built binaries of GCC for HP-UX. On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot parse its `' header file. The option `-nodtk' can be used as a workaround. If GNU CC is not installed, it is therefore recommended to try ./configure CC="cc" and if that doesn't work, try ./configure CC="cc -nodtk" On Solaris, don't put `/usr/ucb' early in your `PATH'. This directory contains several dysfunctional programs; working variants of these programs are available in `/usr/bin'. So, if you need `/usr/ucb' in your `PATH', put it _after_ `/usr/bin'. On Haiku, software installed for all users goes in `/boot/common', not `/usr/local'. It is recommended to use the following options: ./configure --prefix=/boot/common Specifying the System Type ========================== There may be some features `configure' cannot figure out automatically, but needs to determine by the type of machine the package will run on. Usually, assuming the package is built to be run on the _same_ architectures, `configure' can figure that out, but if it prints a message saying it cannot guess the machine type, give it the `--build=TYPE' option. TYPE can either be a short name for the system type, such as `sun4', or a canonical name which has the form: CPU-COMPANY-SYSTEM where SYSTEM can have one of these forms: OS KERNEL-OS See the file `config.sub' for the possible values of each field. If `config.sub' isn't included in this package, then this package doesn't need to know the machine type. If you are _building_ compiler tools for cross-compiling, you should use the option `--target=TYPE' to select the type of system they will produce code for. If you want to _use_ a cross compiler, that generates code for a platform different from the build platform, you should specify the "host" platform (i.e., that on which the generated programs will eventually be run) with `--host=TYPE'. Sharing Defaults ================ If you want to set default values for `configure' scripts to share, you can create a site shell script called `config.site' that gives default values for variables like `CC', `cache_file', and `prefix'. `configure' looks for `PREFIX/share/config.site' if it exists, then `PREFIX/etc/config.site' if it exists. Or, you can set the `CONFIG_SITE' environment variable to the location of the site script. A warning: not all `configure' scripts look for a site script. Defining Variables ================== Variables not defined in a site shell script can be set in the environment passed to `configure'. However, some packages may run configure again during the build, and the customized values of these variables may be lost. In order to avoid this problem, you should set them in the `configure' command line, using `VAR=value'. For example: ./configure CC=/usr/local2/bin/gcc causes the specified `gcc' to be used as the C compiler (unless it is overridden in the site shell script). Unfortunately, this technique does not work for `CONFIG_SHELL' due to an Autoconf bug. Until the bug is fixed you can use this workaround: CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash `configure' Invocation ====================== `configure' recognizes the following options to control how it operates. `--help' `-h' Print a summary of all of the options to `configure', and exit. `--help=short' `--help=recursive' Print a summary of the options unique to this package's `configure', and exit. The `short' variant lists options used only in the top level, while the `recursive' variant lists options also present in any nested packages. `--version' `-V' Print the version of Autoconf used to generate the `configure' script, and exit. `--cache-file=FILE' Enable the cache: use and save the results of the tests in FILE, traditionally `config.cache'. FILE defaults to `/dev/null' to disable caching. `--config-cache' `-C' Alias for `--cache-file=config.cache'. `--quiet' `--silent' `-q' Do not print messages saying which checks are being made. To suppress all normal output, redirect it to `/dev/null' (any error messages will still be shown). `--srcdir=DIR' Look for the package's source code in directory DIR. Usually `configure' can determine that directory automatically. `--prefix=DIR' Use DIR as the installation prefix. *note Installation Names:: for more details, including other options available for fine-tuning the installation locations. `--no-create' `-n' Run the configure checks, but stop before creating any output files. `configure' also accepts some other, not widely useful, options. Run `configure --help' for more details. ntirpc-1.3.1/NEWS000066400000000000000000000003101261345040100135000ustar00rootroot00000000000000New in 0.1: * Portage from FreeBSD 5.2.1 (security part to be completed) * Use autoconf/automake New in 0.7: * Renamed to libntirpc for now New in 0.8 * Added README.CONTRIBUTING * See git history. ntirpc-1.3.1/README000066400000000000000000000055771261345040100137050ustar00rootroot00000000000000NTIRPC - Transport-independent RPC (TI-RPC) To use this in a CMake-based project, copy cmake/modules/FindNTIRPC.cmake into your project, and add: find_package(NTIRPC [] [REQUIRED]) where is the minimum version needed (e.g. 1.3.0) and REQUIRED is added if ntirpc is not optional. LIBTIRPC 0.1 FROM SUN'S TIRPCSRC 2.3 29 Aug 1994 This package contains SunLib's implementation of transport-independent RPC (TI-RPC) documentation. This library forms a piece of the base of Open Network Computing (ONC), and is derived directly from the Solaris 2.3 source. TI-RPC is an enhanced version of TS-RPC that requires the UNIX System V Transport Layer Interface (TLI) or an equivalent X/Open Transport Interface (XTI). TI-RPC is on-the-wire compatible with the TS-RPC, which is supported by almost 70 vendors on all major operating systems. TS-RPC source code (RPCSRC 4.0) remains available from several internet sites. This release was a native source release, compatible for building on Solaris 2.3. It had been ported from FreeBSD 5.2.1 to GNU/Linux in 2004. Applications linked with this release's librpc must link with the United States domestic version of libcrypt in order to resolve the cbc_crypt() and ecb_crypt() functions. These routines are used with Secure RPC however all RPC programs that link with this release's librpc will need to link with the domestic libcrypt. WHAT'S NEW IN THIS RELEASE: TIRPCSRC 2.3 FROM SUN The previous release was TIRPCSRC 2.0. 1. This release is based on Solaris 2.3. The previous release was based on Solaris 2.0. This release contains a siginificant number of bug fixes and other enhancements over TIRPCSRC 2.0. 2. The RPC library is thread safe for all client-side interfaces (clnt_create, clnt_call, etc.). The server-side interfaces (svc_create, svc_run, etc.) are not thread safe in this release. The server-side interfaces will be made thread safe in the next release of TIRPCSRC. Please see the manual pages for details about which interfaces are thread safe. 3. As part of the work to make the RPC library thread-safe, rpcgen has been enhanced to generate thread-safe RPC stubs (the -M option). Note that this modifies the call-signature for the stub functions; the procedure calling the RPC stub must now pass to the stub a pointer to an allocated structure where results will be placed by the stub. See the rpcgen manual page and the rpcgen Programming Guide for details. What's New in ntirpc Non-cosmetic changes introduced in the ntirpc library include 1. Bi-directional operation 2. Full-duplex operation on the TCP (vc) transport 3. Thread-safe operating modes 3.1 new locking primitives and lock callouts (interface change) 3.2 stateless send/recv on the TCP transport (interface change) 4. Flexible server integration support 5. Event channels (remove static arrays of xprt handles, new EPOLL/KEVENT integration) ntirpc-1.3.1/THANKS000066400000000000000000000003341261345040100137220ustar00rootroot00000000000000 Thanks to for Aurelien Charbon TI-RPC portage from NetBSD BSD Communauty TI-RPC improvement from Sun implementation ntirpc-1.3.1/TODO000066400000000000000000000001201261345040100134700ustar00rootroot00000000000000* Support of DES & other security part * Provide tests * rpcgen command missing ntirpc-1.3.1/cmake/000077500000000000000000000000001261345040100140675ustar00rootroot00000000000000ntirpc-1.3.1/cmake/build_configurations/000077500000000000000000000000001261345040100203005ustar00rootroot00000000000000ntirpc-1.3.1/cmake/build_configurations/everything.cmake000066400000000000000000000003241261345040100234650ustar00rootroot00000000000000# Turn on everything in the options for a complete build #set(USE_TIRPC_IPV6 ON) # exports.c is broken here... set(_HANDLE_MAPPING ON) set(_NO_XATTRD OFF) set(USE_DBUS ON) message(STATUS "Building everything") ntirpc-1.3.1/cmake/maintainer_mode.cmake000066400000000000000000000021511261345040100202230ustar00rootroot00000000000000SET( CMAKE_CXX_FLAGS_MAINTAINER "-Wall -Wabi" CACHE STRING "Flags used by the C++ compiler during maintainer builds." FORCE ) SET( CMAKE_C_FLAGS_MAINTAINER "-Werror -Wall -Wimplicit -Wformat -Wmissing-braces -Wreturn-type -Wunused-variable -Wuninitialized -Wno-pointer-sign" CACHE STRING "Flags used by the C compiler during maintainer builds." FORCE ) SET( CMAKE_EXE_LINKER_FLAGS_MAINTAINER "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING "Flags used for linking binaries during maintainer builds." FORCE ) SET( CMAKE_SHARED_LINKER_FLAGS_MAINTAINER "-Wl,--warn-unresolved-symbols,--warn-once" CACHE STRING "Flags used by the shared libraries linker during maintainer builds." FORCE ) MARK_AS_ADVANCED( CMAKE_CXX_FLAGS_MAINTAINER CMAKE_C_FLAGS_MAINTAINER CMAKE_EXE_LINKER_FLAGS_MAINTAINER CMAKE_SHARED_LINKER_FLAGS_MAINTAINER ) # Update the documentation string of CMAKE_BUILD_TYPE for GUIs SET( CMAKE_BUILD_TYPE "${CMAKE_BUILD_TYPE}" CACHE STRING "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel Maintainer." FORCE ) ntirpc-1.3.1/cmake/modules/000077500000000000000000000000001261345040100155375ustar00rootroot00000000000000ntirpc-1.3.1/cmake/modules/COPYING-CMAKE-SCRIPTS000066400000000000000000000024601261345040100205370ustar00rootroot00000000000000Redistribution 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 copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. ntirpc-1.3.1/cmake/modules/FindJeMalloc.cmake000066400000000000000000000040571261345040100210360ustar00rootroot00000000000000# - Find JeMalloc library # Find the native JeMalloc includes and library # This module defines # JEMALLOC_INCLUDE_DIRS, where to find jemalloc.h, Set when # JEMALLOC_INCLUDE_DIR is found. # JEMALLOC_LIBRARIES, libraries to link against to use JeMalloc. # JEMALLOC_ROOT_DIR, The base directory to search for JeMalloc. # This can also be an environment variable. # JEMALLOC_FOUND, If false, do not try to use JeMalloc. # # also defined, but not for general use are # JEMALLOC_LIBRARY, where to find the JeMalloc library. #============================================================================= # Copyright 2011 Blender Foundation. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # If JEMALLOC_ROOT_DIR was defined in the environment, use it. IF(NOT JEMALLOC_ROOT_DIR AND NOT $ENV{JEMALLOC_ROOT_DIR} STREQUAL "") SET(JEMALLOC_ROOT_DIR $ENV{JEMALLOC_ROOT_DIR}) ENDIF() SET(_jemalloc_SEARCH_DIRS ${JEMALLOC_ROOT_DIR} /usr/local /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave ) FIND_PATH(JEMALLOC_INCLUDE_DIR NAMES jemalloc.h HINTS ${_jemalloc_SEARCH_DIRS} PATH_SUFFIXES include/jemalloc ) FIND_LIBRARY(JEMALLOC_LIBRARY NAMES jemalloc HINTS ${_jemalloc_SEARCH_DIRS} PATH_SUFFIXES lib64 lib ) # handle the QUIETLY and REQUIRED arguments and set JEMALLOC_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(JeMalloc DEFAULT_MSG JEMALLOC_LIBRARY JEMALLOC_INCLUDE_DIR) IF(JEMALLOC_FOUND) SET(JEMALLOC_LIBRARIES ${JEMALLOC_LIBRARY}) SET(JEMALLOC_INCLUDE_DIRS ${JEMALLOC_INCLUDE_DIR}) ENDIF(JEMALLOC_FOUND) MARK_AS_ADVANCED( JEMALLOC_INCLUDE_DIR JEMALLOC_LIBRARY ) ntirpc-1.3.1/cmake/modules/FindKrb5.cmake000066400000000000000000000125611261345040100201520ustar00rootroot00000000000000# - Find kerberos 5 # Find the native Kerberos 5 headers and libraries. # KRB5_INCLUDE_DIRS - where to find krb5.h, etc. # KRB5_LIBRARIES - List of libraries when using kerberos 5. # KRB5_FOUND - True if kerberos 5 found. # KRB5 modules may be specified as components for this find module. # Modules may be listed by running "krb5-config". Modules include: # krb5 Kerberos 5 application # gssapi GSSAPI application with Kerberos 5 bindings # krb4 Kerberos 4 application # kadm-client Kadmin client # kadm-server Kadmin server # kdb Application that accesses the kerberos database # Typical usage: # FIND_PACKAGE(KRB5 REQUIRED gssapi) # First find the config script from which to obtain other values. IF(KRB5_PREFIX) FIND_PROGRAM(KRB5_C_CONFIG NAMES krb5-config PATHS ${KRB5_PREFIX} NO_SYSTEM_ENVIRONMENT_PATH NO_DEFAULT_PATH ) ENDIF(KRB5_PREFIX) FIND_PROGRAM(KRB5_C_CONFIG NAMES krb5-config) MESSAGE(STATUS "found krb5-config here ${KRB5_C_CONFIG}") # Check whether we found anything. IF(KRB5_C_CONFIG) SET(KRB5_FOUND 1) ELSE(KRB5_C_CONFIG) SET(KRB5_FOUND 0) ENDIF(KRB5_C_CONFIG) # Lookup the include directories needed for the components requested. IF(KRB5_FOUND) # Use the newer EXECUTE_PROCESS command if it is available. IF(COMMAND EXECUTE_PROCESS) EXECUTE_PROCESS( COMMAND ${KRB5_C_CONFIG} ${KRB5_FIND_COMPONENTS} --cflags OUTPUT_VARIABLE KRB5_C_CONFIG_CFLAGS OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE KRB5_C_CONFIG_RESULT ) ELSE(COMMAND EXECUTE_PROCESS) EXEC_PROGRAM(${KRB5_C_CONFIG} ARGS "${KRB5_FIND_COMPONENTS} --cflags" OUTPUT_VARIABLE KRB5_C_CONFIG_CFLAGS RETURN_VALUE KRB5_C_CONFIG_RESULT ) ENDIF(COMMAND EXECUTE_PROCESS) # Parse the include flags. IF("${KRB5_C_CONFIG_RESULT}" MATCHES "^0$") # Convert the compile flags to a CMake list. STRING(REGEX REPLACE " +" ";" KRB5_C_CONFIG_CFLAGS "${KRB5_C_CONFIG_CFLAGS}") # Look for -I options. SET(KRB5_INCLUDE_DIRS) FOREACH(flag ${KRB5_C_CONFIG_CFLAGS}) IF("${flag}" MATCHES "^-I") STRING(REGEX REPLACE "^-I" "" DIR "${flag}") FILE(TO_CMAKE_PATH "${DIR}" DIR) SET(KRB5_INCLUDE_DIRS ${KRB5_INCLUDE_DIRS} "${DIR}") ENDIF("${flag}" MATCHES "^-I") ENDFOREACH(flag) ELSE("${KRB5_C_CONFIG_RESULT}" MATCHES "^0$") MESSAGE("Error running ${KRB5_C_CONFIG}: [${KRB5_C_CONFIG_RESULT}]") SET(KRB5_FOUND 0) ENDIF("${KRB5_C_CONFIG_RESULT}" MATCHES "^0$") ENDIF(KRB5_FOUND) # Lookup the libraries needed for the components requested. IF(KRB5_FOUND) # Use the newer EXECUTE_PROCESS command if it is available. IF(COMMAND EXECUTE_PROCESS) EXECUTE_PROCESS( COMMAND ${KRB5_C_CONFIG} ${KRB5_FIND_COMPONENTS} --libs OUTPUT_VARIABLE KRB5_C_CONFIG_LIBS OUTPUT_STRIP_TRAILING_WHITESPACE RESULT_VARIABLE KRB5_C_CONFIG_RESULT ) ELSE(COMMAND EXECUTE_PROCESS) EXEC_PROGRAM(${KRB5_C_CONFIG} ARGS "${KRB5_FIND_COMPONENTS} --libs" OUTPUT_VARIABLE KRB5_C_CONFIG_LIBS RETURN_VALUE KRB5_C_CONFIG_RESULT ) ENDIF(COMMAND EXECUTE_PROCESS) # Parse the library names and directories. IF("${KRB5_C_CONFIG_RESULT}" MATCHES "^0$") STRING(REGEX REPLACE " +" ";" KRB5_C_CONFIG_LIBS "${KRB5_C_CONFIG_LIBS}") # Look for -L flags for directories and -l flags for library names. SET(KRB5_LIBRARY_DIRS) SET(KRB5_LIBRARY_NAMES) FOREACH(flag ${KRB5_C_CONFIG_LIBS}) IF("${flag}" MATCHES "^-L") STRING(REGEX REPLACE "^-L" "" DIR "${flag}") FILE(TO_CMAKE_PATH "${DIR}" DIR) SET(KRB5_LIBRARY_DIRS ${KRB5_LIBRARY_DIRS} "${DIR}") ELSEIF("${flag}" MATCHES "^-l") STRING(REGEX REPLACE "^-l" "" NAME "${flag}") SET(KRB5_LIBRARY_NAMES ${KRB5_LIBRARY_NAMES} "${NAME}") ENDIF("${flag}" MATCHES "^-L") ENDFOREACH(flag) # add gssapi_krb5 (MIT) SET(KRB5_LIBRARY_NAMES ${KRB5_LIBRARY_NAMES} "gssapi_krb5") # Search for each library needed using the directories given. FOREACH(name ${KRB5_LIBRARY_NAMES}) # Look for this library. FIND_LIBRARY(KRB5_${name}_LIBRARY NAMES ${name} PATHS ${KRB5_LIBRARY_DIRS} NO_DEFAULT_PATH ) FIND_LIBRARY(KRB5_${name}_LIBRARY NAMES ${name}) MARK_AS_ADVANCED(KRB5_${name}_LIBRARY) # If any library is not found then the whole package is not found. IF(NOT KRB5_${name}_LIBRARY) SET(KRB5_FOUND 0) ENDIF(NOT KRB5_${name}_LIBRARY) # Build an ordered list of all the libraries needed. SET(KRB5_LIBRARIES ${KRB5_LIBRARIES} "${KRB5_${name}_LIBRARY}") ENDFOREACH(name) ELSE("${KRB5_C_CONFIG_RESULT}" MATCHES "^0$") MESSAGE("Error running ${KRB5_C_CONFIG}: [${KRB5_C_CONFIG_RESULT}]") SET(KRB5_FOUND 0) ENDIF("${KRB5_C_CONFIG_RESULT}" MATCHES "^0$") ENDIF(KRB5_FOUND) # Report the results. IF(NOT KRB5_FOUND) SET(KRB5_DIR_MESSAGE "KRB5 was not found. Make sure the entries KRB5_* are set.") IF(NOT KRB5_FIND_QUIETLY) MESSAGE(STATUS "${KRB5_DIR_MESSAGE}") ELSE(NOT KRB5_FIND_QUIETLY) IF(KRB5_FIND_REQUIRED) MESSAGE(FATAL_ERROR "${KRB5_DIR_MESSAGE}") ENDIF(KRB5_FIND_REQUIRED) ENDIF(NOT KRB5_FIND_QUIETLY) ELSE(NOT KRB5_FOUND) MESSAGE(STATUS "Found kerberos 5 headers: ${KRB5_INCLUDE_DIRS}") MESSAGE(STATUS "Found kerberos 5 libs: ${KRB5_LIBRARIES}") ENDIF(NOT KRB5_FOUND) ntirpc-1.3.1/cmake/modules/FindNTIRPC.cmake000066400000000000000000000025161261345040100203450ustar00rootroot00000000000000# - Find NTIRPC # Find the New TIRPC RPC library # # This module accepts the following optional variables: # NTIRPC_PATH_HINT = A hint on NTIRPC install path. # # This module defines the following variables: # NTIRPC_FOUND = Was NTIRPC found or not? # NTIRPC_LIBRARY = The list of libraries to link to when using NTIRPC # NTIRPC_INCLUDE_DIR = The path to NTIRPC include directory(s) # # On can set NTIRPC_PATH_HINT before using find_package(NTIRPC) and the # module with use the PATH as a hint to find NTIRPC. # # The hint can be given on the command line too: # cmake -DNTIRPC_PATH_HINT=/DATA/ERIC/NTIRPC /path/to/source include(LibFindMacros) libfind_pkg_detect(NTIRPC libntirpc FIND_PATH netconfig.h PATH_SUFFIXES ntirpc FIND_LIBRARY ntirpc) if (NTIRPC_LIBRARY) libfind_version_header(NTIRPC version.h NTIRPC_VERSION) endif (NTIRPC_LIBRARY) # handle the QUIETLY and REQUIRED arguments and set PRELUDE_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(NTIRPC REQUIRED_VARS NTIRPC_INCLUDE_DIR NTIRPC_LIBRARY VERSION_VAR NTIRPC_VERSION) # VERSION FPHSA options not handled by CMake version < 2.8.2) # VERSION_VAR) mark_as_advanced(NTIRPC_INCLUDE_DIR) mark_as_advanced(NTIRPC_LIBRARY) ntirpc-1.3.1/cmake/modules/FindRDMA.cmake000066400000000000000000000051131261345040100200650ustar00rootroot00000000000000# - Find RDMA # Find the New TIRPC RPC library # # This module accepts the following optional variables: # RDMA_PATH_HINT = A hint on RDMA install path. # # This module defines the following variables: # RDMA_FOUND = Was RDMA found or not? # RDMA_LIBRARY = The list of libraries to link to when using RDMA # RDMA_INCLUDE_DIR = The path to RDMA include directory(s) # # One can set RDMA_PATH_HINT before using find_package(RDMA) and the # module with use the PATH as a hint to find RDMA. # Alternatively, one can set LIBIBVERBS_PREFIX and LIBRDMACM_PREFIX to the individual # hints for those libraries. # # The hint can be given on the command line too: # cmake -DRDMA_PATH_HINT=/DATA/ERIC/RDMA /path/to/source include(LibFindMacros) # ibverbs if (LIBIBVERBS_PREFIX) set(IBVERBS_PKGCONF_INCLUDE_DIRS ${LIBIBVERBS_PREFIX}/include) set(IBVERBS_PKGCONF_LIBRARY_DIRS ${LIBIBVERBS_PREFIX}/lib64 ${LIBIBVERBS_PREFIX}/lib) else (LIBIBVERBS_PREFIX) set(IBVERBS_PKGCONF_INCLUDE_DIRS ${RDMA_PATH_HINT}/include) set(IBVERBS_PKGCONF_LIBRARY_DIRS ${RDMA_PATH_HINT}/lib64 ${RDMA_PATH_HINT}/lib) endif (LIBIBVERBS_PREFIX) libfind_pkg_detect(IBVERBS libibverbs FIND_PATH verbs.h PATH_SUFFIXES infiniband FIND_LIBRARY ibverbs) libfind_process(IBVERBS) # rdmacm if (LIBRDMACM_PREFIX) set(RDMACM_PKGCONF_INCLUDE_DIRS ${LIBRDMACM_PREFIX}/include) set(RDMACM_PKGCONF_LIBRARY_DIRS ${LIBRDMACM_PREFIX}/lib64 ${LIBRDMACM_PREFIX}/lib) else (LIBRDMACM_PREFIX) set(RDMACM_PKGCONF_INCLUDE_DIRS ${RDMA_PATH_HINT}/include) set(RDMACM_PKGCONF_LIBRARY_DIRS ${RDMA_PATH_HINT}/lib64 ${RDMA_PATH_HINT}/lib) endif (LIBRDMACM_PREFIX) libfind_pkg_detect(RDMACM librdmacm FIND_PATH rdma_cma.h PATH_SUFFIXES rdma FIND_LIBRARY rdmacm) libfind_process(RDMACM) if (IBVERBS_FOUND AND RDMACM_FOUND) set(RDMA_FOUND true) set(RDMA_LIBRARY ${IBVERBS_LIBRARY} ${RDMACM_LIBRARY}) set(RDMA_INCLUDE_DIR ${IBVERBS_INCLUDE_DIR} ${RDMACM_INCLUDE_DIR}) else (IBVERBS_FOUND AND RDMACM_FOUND) set(RDMA_NOTFOUND true) endif (IBVERBS_FOUND AND RDMACM_FOUND) #if (RDMA_LIBRARY) #libfind_version_header(RDMA version.h RDMA_VERSION) #endif (RDMA_LIBRARY) # handle the QUIETLY and REQUIRED arguments and set PRELUDE_FOUND to TRUE if # all listed variables are TRUE include(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(RDMA REQUIRED_VARS RDMA_INCLUDE_DIR RDMA_LIBRARY VERSION_VAR RDMA_VERSION) # VERSION FPHSA options not handled by CMake version < 2.8.2) # VERSION_VAR) mark_as_advanced(RDMA_INCLUDE_DIR) mark_as_advanced(RDMA_LIBRARY) ntirpc-1.3.1/cmake/modules/FindTcMalloc.cmake000066400000000000000000000042151261345040100210420ustar00rootroot00000000000000# - Find Tcmalloc library # Find the native Tcmalloc includes and library # This module defines # TCMALLOC_INCLUDE_DIRS, where to find tcmalloc.h, Set when # TCMALLOC_INCLUDE_DIR is found. # TCMALLOC_LIBRARIES, libraries to link against to use Tcmalloc. # TCMALLOC_ROOT_DIR, The base directory to search for Tcmalloc. # This can also be an environment variable. # TCMALLOC_FOUND, If false, do not try to use Tcmalloc. # # also defined, but not for general use are # TCMALLOC_LIBRARY, where to find the Tcmalloc library. #============================================================================= # Copyright 2011 Blender Foundation. # # Distributed under the OSI-approved BSD License (the "License"); # see accompanying file Copyright.txt for details. # # This software is distributed WITHOUT ANY WARRANTY; without even the # implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # See the License for more information. #============================================================================= # If TCMALLOC_ROOT_DIR was defined in the environment, use it. IF(NOT TCMALLOC_ROOT_DIR AND NOT $ENV{TCMALLOC_ROOT_DIR} STREQUAL "") SET(TCMALLOC_ROOT_DIR $ENV{TCMALLOC_ROOT_DIR}) ENDIF() SET(_tcmalloc_SEARCH_DIRS ${TCMALLOC_ROOT_DIR} /usr/local /sw # Fink /opt/local # DarwinPorts /opt/csw # Blastwave /usr/include/google # Debain tcmalloc minimal /usr/include/gperftools # Debian gperftools ) FIND_PATH(TCMALLOC_INCLUDE_DIR NAMES tcmalloc.h HINTS ${_tcmalloc_SEARCH_DIRS} PATH_SUFFIXES include/tcmalloc ) FIND_LIBRARY(TCMALLOC_LIBRARY NAMES tcmalloc HINTS ${_tcmalloc_SEARCH_DIRS} PATH_SUFFIXES lib64 lib ) # handle the QUIETLY and REQUIRED arguments and set TCMALLOC_FOUND to TRUE if # all listed variables are TRUE INCLUDE(FindPackageHandleStandardArgs) FIND_PACKAGE_HANDLE_STANDARD_ARGS(Tcmalloc DEFAULT_MSG TCMALLOC_LIBRARY TCMALLOC_INCLUDE_DIR) IF(TCMALLOC_FOUND) SET(TCMALLOC_LIBRARIES ${TCMALLOC_LIBRARY}) SET(TCMALLOC_INCLUDE_DIRS ${TCMALLOC_INCLUDE_DIR}) ENDIF(TCMALLOC_FOUND) MARK_AS_ADVANCED( TCMALLOC_INCLUDE_DIR TCMALLOC_LIBRARY ) ntirpc-1.3.1/cmake/modules/FindWBclient.cmake000066400000000000000000000026731261345040100210610ustar00rootroot00000000000000# Try to find a sufficiently recent wbclient if(SAMBA4_PREFIX) set(SAMBA4_INCLUDE_DIRS ${SAMBA4_PREFIX}/include) set(SAMBA4_LIBRARIES ${SAMBA4_PREFIX}/lib${LIB_SUFFIX}) endif() if(NOT WIN32) find_package(PkgConfig) if(PKG_CONFIG_FOUND) pkg_check_modules(_WBCLIENT_PC QUIET wbclient) endif(PKG_CONFIG_FOUND) endif(NOT WIN32) find_path(WBCLIENT_INCLUDE_DIR wbclient.h ${_WBCLIENT_PC_INCLUDE_DIRS} ${SAMBA4_INCLUDE_DIRS} /usr/include /usr/local/include ) set(CMAKE_REQUIRED_INCLUDES ${WBCLIENT_INCLUDE_DIR}) find_library(WBCLIENT_LIBRARIES NAMES wbclient PATHS ${_WBCLIENT_PC_LIBDIR} ) check_library_exists( wbclient wbcLookupSids ${WBCLIENT_LIBRARIES} WBCLIENT_LIB_OK ) # the stdint and stdbool includes are required (silly Cmake) check_include_files("stdint.h;stdbool.h;wbclient.h" WBCLIENT_H) # XXX this check is doing the heavy lifting set(CMAKE_REQUIRED_LIBRARIES ${WBCLIENT_LIBRARIES}) if(WBCLIENT_H) check_c_source_compiles(" /* do the enum */ #include #include #include #include int main(void) { enum wbcAuthUserLevel level = WBC_AUTH_USER_LEVEL_PAC; return (0); }" WBCLIENT4_H) endif(WBCLIENT_H) if(WBCLIENT_LIB_OK AND WBCLIENT4_H) set(WBCLIENT_FOUND 1) message(STATUS "Found Winbind4 client: ${WBCLIENT_LIB}") else(WBCLIENT_LIB_OK AND WBCLIENT4_H) message(STATUS "Winbind4 client not found ${SAMBA4_PREFIX}/lib") endif(WBCLIENT_LIB_OK AND WBCLIENT4_H) ntirpc-1.3.1/cmake/modules/GetGitRevisionDescription.cmake000066400000000000000000000072761261345040100236630ustar00rootroot00000000000000# - Returns a version string from Git # # These functions force a re-configure on each git commit so that you can # trust the values of the variables in your build system. # # get_git_head_revision( [ ...]) # # Returns the refspec and sha hash of the current head revision # # git_describe( [ ...]) # # Returns the results of git describe on the source tree, and adjusting # the output so that it tests false if an error occurs. # # git_get_exact_tag( [ ...]) # # Returns the results of git describe --exact-match on the source tree, # and adjusting the output so that it tests false if there was no exact # matching tag. # # Requires CMake 2.6 or newer (uses the 'function' command) # # Original Author: # 2009-2010 Ryan Pavlik # http://academic.cleardefinition.com # Iowa State University HCI Graduate Program/VRAC # # Copyright Iowa State University 2009-2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) if(__get_git_revision_description) return() endif() set(__get_git_revision_description YES) # We must run the following at "include" time, not at function call time, # to find the path to this module rather than the path to a calling list file get_filename_component(_gitdescmoddir ${CMAKE_CURRENT_LIST_FILE} PATH) function(get_git_head_revision _refspecvar _hashvar) set(GIT_PARENT_DIR "${CMAKE_SOURCE_DIR}") set(GIT_DIR "${GIT_PARENT_DIR}/.git") while(NOT EXISTS "${GIT_DIR}") # .git dir not found, search parent directories set(GIT_PREVIOUS_PARENT "${GIT_PARENT_DIR}") get_filename_component(GIT_PARENT_DIR ${GIT_PARENT_DIR} PATH) if(GIT_PARENT_DIR STREQUAL GIT_PREVIOUS_PARENT) # We have reached the root directory, we are not in git set(${_refspecvar} "GITDIR-NOTFOUND" PARENT_SCOPE) set(${_hashvar} "GITDIR-NOTFOUND" PARENT_SCOPE) return() endif() set(GIT_DIR "${GIT_PARENT_DIR}/.git") endwhile() set(GIT_DATA "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/git-data") if(NOT EXISTS "${GIT_DATA}") file(MAKE_DIRECTORY "${GIT_DATA}") endif() if(NOT EXISTS "${GIT_DIR}/HEAD") return() endif() set(HEAD_FILE "${GIT_DATA}/HEAD") configure_file("${GIT_DIR}/HEAD" "${HEAD_FILE}" COPYONLY) configure_file("${_gitdescmoddir}/GetGitRevisionDescription.cmake.in" "${GIT_DATA}/grabRef.cmake" @ONLY) include("${GIT_DATA}/grabRef.cmake") set(${_refspecvar} "${HEAD_REF}" PARENT_SCOPE) set(${_hashvar} "${HEAD_HASH}" PARENT_SCOPE) endfunction() function(git_describe _var) if(NOT GIT_FOUND) find_package(Git QUIET) endif() get_git_head_revision(refspec hash) if(NOT GIT_FOUND) set(${_var} "GIT-NOTFOUND" PARENT_SCOPE) return() endif() if(NOT hash) set(${_var} "HEAD-HASH-NOTFOUND" PARENT_SCOPE) return() endif() # TODO sanitize #if((${ARGN}" MATCHES "&&") OR # (ARGN MATCHES "||") OR # (ARGN MATCHES "\\;")) # message("Please report the following error to the project!") # message(FATAL_ERROR "Looks like someone's doing something nefarious with git_describe! Passed arguments ${ARGN}") #endif() #message(STATUS "Arguments to execute_process: ${ARGN}") execute_process(COMMAND "${GIT_EXECUTABLE}" describe ${hash} ${ARGN} WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}" RESULT_VARIABLE res OUTPUT_VARIABLE out ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) if(NOT res EQUAL 0) set(out "${out}-${res}-NOTFOUND") endif() set(${_var} "${out}" PARENT_SCOPE) endfunction() function(git_get_exact_tag _var) git_describe(out --exact-match ${ARGN}) set(${_var} "${out}" PARENT_SCOPE) endfunction() ntirpc-1.3.1/cmake/modules/GetGitRevisionDescription.cmake.in000066400000000000000000000022621261345040100242560ustar00rootroot00000000000000# # Internal file for GetGitRevisionDescription.cmake # # Requires CMake 2.6 or newer (uses the 'function' command) # # Original Author: # 2009-2010 Ryan Pavlik # http://academic.cleardefinition.com # Iowa State University HCI Graduate Program/VRAC # # Copyright Iowa State University 2009-2010. # Distributed under the Boost Software License, Version 1.0. # (See accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) set(HEAD_HASH) file(READ "@HEAD_FILE@" HEAD_CONTENTS LIMIT 1024) string(STRIP "${HEAD_CONTENTS}" HEAD_CONTENTS) if(HEAD_CONTENTS MATCHES "ref") # named branch string(REPLACE "ref: " "" HEAD_REF "${HEAD_CONTENTS}") if(EXISTS "@GIT_DIR@/${HEAD_REF}") configure_file("@GIT_DIR@/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) elseif(EXISTS "@GIT_DIR@/logs/${HEAD_REF}") configure_file("@GIT_DIR@/logs/${HEAD_REF}" "@GIT_DATA@/head-ref" COPYONLY) set(HEAD_HASH "${HEAD_REF}") endif() else() # detached HEAD configure_file("@GIT_DIR@/HEAD" "@GIT_DATA@/head-ref" COPYONLY) endif() if(NOT HEAD_HASH) file(READ "@GIT_DATA@/head-ref" HEAD_HASH LIMIT 1024) string(STRIP "${HEAD_HASH}" HEAD_HASH) endif() ntirpc-1.3.1/cmake/modules/LibFindMacros.cmake000066400000000000000000000247051261345040100212250ustar00rootroot00000000000000# Version 2.2 # Public Domain, originally written by Lasse Kärkkäinen # Maintained at https://github.com/Tronic/cmake-modules # Please send your improvements as pull requests on Github. # Find another package and make it a dependency of the current package. # This also automatically forwards the "REQUIRED" argument. # Usage: libfind_package( [extra args to find_package]) macro (libfind_package PREFIX PKG) set(${PREFIX}_args ${PKG} ${ARGN}) if (${PREFIX}_FIND_REQUIRED) set(${PREFIX}_args ${${PREFIX}_args} REQUIRED) endif() find_package(${${PREFIX}_args}) set(${PREFIX}_DEPENDENCIES ${${PREFIX}_DEPENDENCIES};${PKG}) unset(${PREFIX}_args) endmacro() # A simple wrapper to make pkg-config searches a bit easier. # Works the same as CMake's internal pkg_check_modules but is always quiet. macro (libfind_pkg_check_modules) find_package(PkgConfig QUIET) if (PKG_CONFIG_FOUND) pkg_check_modules(${ARGN} QUIET) endif() endmacro() # Avoid useless copy&pasta by doing what most simple libraries do anyway: # pkg-config, find headers, find library. # Usage: libfind_pkg_detect( FIND_PATH [other args] FIND_LIBRARY [other args]) # E.g. libfind_pkg_detect(SDL2 sdl2 FIND_PATH SDL.h PATH_SUFFIXES SDL2 FIND_LIBRARY SDL2) function (libfind_pkg_detect PREFIX) # Parse arguments set(argname pkgargs) foreach (i ${ARGN}) if ("${i}" STREQUAL "FIND_PATH") set(argname pathargs) elseif ("${i}" STREQUAL "FIND_LIBRARY") set(argname libraryargs) else() set(${argname} ${${argname}} ${i}) endif() endforeach() if (NOT pkgargs) message(FATAL_ERROR "libfind_pkg_detect requires at least a pkg_config package name to be passed.") endif() # Find library libfind_pkg_check_modules(${PREFIX}_PKGCONF ${pkgargs}) if (pathargs) find_path(${PREFIX}_INCLUDE_DIR NAMES ${pathargs} HINTS ${${PREFIX}_PKGCONF_INCLUDE_DIRS}) endif() if (libraryargs) find_library(${PREFIX}_LIBRARY NAMES ${libraryargs} HINTS ${${PREFIX}_PKGCONF_LIBRARY_DIRS}) endif() endfunction() # Extracts a version #define from a version.h file, output stored to _VERSION. # Usage: libfind_version_header(Foobar foobar/version.h FOOBAR_VERSION_STR) # Fourth argument "QUIET" may be used for silently testing different define names. # This function does nothing if the version variable is already defined. function (libfind_version_header PREFIX VERSION_H DEFINE_NAME) # Skip processing if we already have a version or if the include dir was not found if (${PREFIX}_VERSION OR NOT ${PREFIX}_INCLUDE_DIR) return() endif() set(quiet ${${PREFIX}_FIND_QUIETLY}) # Process optional arguments foreach(arg ${ARGN}) if (arg STREQUAL "QUIET") set(quiet TRUE) else() message(AUTHOR_WARNING "Unknown argument ${arg} to libfind_version_header ignored.") endif() endforeach() # Read the header and parse for version number set(filename "${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") if (NOT EXISTS ${filename}) if (NOT quiet) message(AUTHOR_WARNING "Unable to find ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") endif() return() endif() file(READ "${filename}" header) string(REGEX REPLACE ".*#[ \t]*define[ \t]*${DEFINE_NAME}[ \t]*\"([^\n]*)\".*" "\\1" match "${header}") # No regex match? if (match STREQUAL header) if (NOT quiet) message(AUTHOR_WARNING "Unable to find \#define ${DEFINE_NAME} \"\" from ${${PREFIX}_INCLUDE_DIR}/${VERSION_H}") endif() return() endif() # Export the version string set(${PREFIX}_VERSION "${match}" PARENT_SCOPE) endfunction() # Do the final processing once the paths have been detected. # If include dirs are needed, ${PREFIX}_PROCESS_INCLUDES should be set to contain # all the variables, each of which contain one include directory. # Ditto for ${PREFIX}_PROCESS_LIBS and library files. # Will set ${PREFIX}_FOUND, ${PREFIX}_INCLUDE_DIRS and ${PREFIX}_LIBRARIES. # Also handles errors in case library detection was required, etc. function (libfind_process PREFIX) # Skip processing if already processed during this configuration run if (${PREFIX}_FOUND) return() endif() set(found TRUE) # Start with the assumption that the package was found # Did we find any files? Did we miss includes? These are for formatting better error messages. set(some_files FALSE) set(missing_headers FALSE) # Shorthands for some variables that we need often set(quiet ${${PREFIX}_FIND_QUIETLY}) set(required ${${PREFIX}_FIND_REQUIRED}) set(exactver ${${PREFIX}_FIND_VERSION_EXACT}) set(findver "${${PREFIX}_FIND_VERSION}") set(version "${${PREFIX}_VERSION}") # Lists of config option names (all, includes, libs) unset(configopts) set(includeopts ${${PREFIX}_PROCESS_INCLUDES}) set(libraryopts ${${PREFIX}_PROCESS_LIBS}) # Process deps to add to foreach (i ${PREFIX} ${${PREFIX}_DEPENDENCIES}) if (DEFINED ${i}_INCLUDE_OPTS OR DEFINED ${i}_LIBRARY_OPTS) # The package seems to export option lists that we can use, woohoo! list(APPEND includeopts ${${i}_INCLUDE_OPTS}) list(APPEND libraryopts ${${i}_LIBRARY_OPTS}) else() # If plural forms don't exist or they equal singular forms if ((NOT DEFINED ${i}_INCLUDE_DIRS AND NOT DEFINED ${i}_LIBRARIES) OR ({i}_INCLUDE_DIR STREQUAL ${i}_INCLUDE_DIRS AND ${i}_LIBRARY STREQUAL ${i}_LIBRARIES)) # Singular forms can be used if (DEFINED ${i}_INCLUDE_DIR) list(APPEND includeopts ${i}_INCLUDE_DIR) endif() if (DEFINED ${i}_LIBRARY) list(APPEND libraryopts ${i}_LIBRARY) endif() else() # Oh no, we don't know the option names message(FATAL_ERROR "We couldn't determine config variable names for ${i} includes and libs. Aieeh!") endif() endif() endforeach() if (includeopts) list(REMOVE_DUPLICATES includeopts) endif() if (libraryopts) list(REMOVE_DUPLICATES libraryopts) endif() string(REGEX REPLACE ".*[ ;]([^ ;]*(_INCLUDE_DIRS|_LIBRARIES))" "\\1" tmp "${includeopts} ${libraryopts}") if (NOT tmp STREQUAL "${includeopts} ${libraryopts}") message(AUTHOR_WARNING "Plural form ${tmp} found in config options of ${PREFIX}. This works as before but is now deprecated. Please only use singular forms INCLUDE_DIR and LIBRARY, and update your find scripts for LibFindMacros > 2.0 automatic dependency system (most often you can simply remove the PROCESS variables entirely).") endif() # Include/library names separated by spaces (notice: not CMake lists) unset(includes) unset(libs) # Process all includes and set found false if any are missing foreach (i ${includeopts}) list(APPEND configopts ${i}) if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") list(APPEND includes "${${i}}") else() set(found FALSE) set(missing_headers TRUE) endif() endforeach() # Process all libraries and set found false if any are missing foreach (i ${libraryopts}) list(APPEND configopts ${i}) if (NOT "${${i}}" STREQUAL "${i}-NOTFOUND") list(APPEND libs "${${i}}") else() set (found FALSE) endif() endforeach() # Version checks if (found AND findver) if (NOT version) message(WARNING "The find module for ${PREFIX} does not provide version information, so we'll just assume that it is OK. Please fix the module or remove package version requirements to get rid of this warning.") elseif (version VERSION_LESS findver OR (exactver AND NOT version VERSION_EQUAL findver)) set(found FALSE) set(version_unsuitable TRUE) endif() endif() # If all-OK, hide all config options, export variables, print status and exit if (found) foreach (i ${configopts}) mark_as_advanced(${i}) endforeach() if (NOT quiet) message(STATUS "Found ${PREFIX} ${${PREFIX}_VERSION}") if (LIBFIND_DEBUG) message(STATUS " ${PREFIX}_DEPENDENCIES=${${PREFIX}_DEPENDENCIES}") message(STATUS " ${PREFIX}_INCLUDE_OPTS=${includeopts}") message(STATUS " ${PREFIX}_INCLUDE_DIRS=${includes}") message(STATUS " ${PREFIX}_LIBRARY_OPTS=${libraryopts}") message(STATUS " ${PREFIX}_LIBRARIES=${libs}") endif() set (${PREFIX}_INCLUDE_OPTS ${includeopts} PARENT_SCOPE) set (${PREFIX}_LIBRARY_OPTS ${libraryopts} PARENT_SCOPE) set (${PREFIX}_INCLUDE_DIRS ${includes} PARENT_SCOPE) set (${PREFIX}_LIBRARIES ${libs} PARENT_SCOPE) set (${PREFIX}_FOUND TRUE PARENT_SCOPE) endif() return() endif() # Format messages for debug info and the type of error set(vars "Relevant CMake configuration variables:\n") foreach (i ${configopts}) mark_as_advanced(CLEAR ${i}) set(val ${${i}}) if ("${val}" STREQUAL "${i}-NOTFOUND") set (val "") elseif (val AND NOT EXISTS ${val}) set (val "${val} (does not exist)") else() set(some_files TRUE) endif() set(vars "${vars} ${i}=${val}\n") endforeach() set(vars "${vars}You may use CMake GUI, cmake -D or ccmake to modify the values. Delete CMakeCache.txt to discard all values and force full re-detection if necessary.\n") if (version_unsuitable) set(msg "${PREFIX} ${${PREFIX}_VERSION} was found but") if (exactver) set(msg "${msg} only version ${findver} is acceptable.") else() set(msg "${msg} version ${findver} is the minimum requirement.") endif() else() if (missing_headers) set(msg "We could not find development headers for ${PREFIX}. Do you have the necessary dev package installed?") elseif (some_files) set(msg "We only found some files of ${PREFIX}, not all of them. Perhaps your installation is incomplete or maybe we just didn't look in the right place?") if(findver) set(msg "${msg} This could also be caused by incompatible version (if it helps, at least ${PREFIX} ${findver} should work).") endif() else() set(msg "We were unable to find package ${PREFIX}.") endif() endif() # Fatal error out if REQUIRED if (required) set(msg "REQUIRED PACKAGE NOT FOUND\n${msg} This package is REQUIRED and you need to install it or adjust CMake configuration in order to continue building ${CMAKE_PROJECT_NAME}.") message(FATAL_ERROR "${msg}\n${vars}") endif() # Otherwise just print a nasty warning if (NOT quiet) message(WARNING "WARNING: MISSING PACKAGE\n${msg} This package is NOT REQUIRED and you may ignore this warning but by doing so you may miss some functionality of ${CMAKE_PROJECT_NAME}. \n${vars}") endif() endfunction() ntirpc-1.3.1/config-h.in.cmake000066400000000000000000000015701261345040100161130ustar00rootroot00000000000000/* config.h file expanded by Cmake for build */ #include "ntirpc/version.h" #ifndef CONFIG_H #define CONFIG_H /* Build controls */ #cmakedefine _MSPAC_SUPPORT 1 #cmakedefine HAVE_STDBOOL_H 1 #cmakedefine HAVE_KRB5 1 #cmakedefine KRB5_VERSION @KRB5_VERSION@ #cmakedefine LINUX 1 #cmakedefine FREEBSD 1 #cmakedefine _HAVE_GSSAPI 1 #cmakedefine HAVE_STRING_H 1 #cmakedefine HAVE_STRINGS_H 1 #cmakedefine LITTLEEND 1 #cmakedefine BIGEND 1 #cmakedefine TIRPC_EPOLL 1 #cmakedefine USE_RPC_RDMA 1 /* Package stuff */ #define PACKAGE "libntirpc" #define PACKAGE_BUGREPORT "" #define PACKAGE_NAME "libntirpc" #define PACKAGE_STRING "libntirpc ${NTIRPC_VERSION_MAJOR}.${NTIRPC_VERSION_MINOR}.${NTIRPC_PATCH_LEVEL}" #define PACKAGE_TARNAME "libntirpc" #define PACKAGE_URL "" #define PACKAGE_VERSION "${NTIRPC_VERSION_MAJOR}.${NTIRPC_VERSION_MINOR}.${NTIRPC_PATCH_LEVEL}" #endif /* CONFIG_H */ ntirpc-1.3.1/libntirpc.pc.in.cmake000066400000000000000000000003631261345040100170070ustar00rootroot00000000000000prefix=@prefix@ exec_prefix=@exec_prefix@ libdir=@libdir@ includedir=@includedir@ Name: libntirpc Description: New Transport Independent RPC Library Requires: Version: @NTIRPC_VERSION@ Libs: -L@libdir@ -lintirpc Cflags: -I@includedir@/ntirpc ntirpc-1.3.1/man/000077500000000000000000000000001261345040100135625ustar00rootroot00000000000000ntirpc-1.3.1/man/bindresvport.3t000066400000000000000000000036631261345040100165630ustar00rootroot00000000000000.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI .\" .Dd November 22, 1987 .Dt BINDRESVPORT 3 .Os .Sh NAME .Nm bindresvport , .Nm bindresvport_sa .Nd bind a socket to a 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 The .Fn bindresvport and .Fn bindresvport_sa functions are used to bind a socket descriptor to a privileged .Tn IP port, that is, a port number in the range 0-1023. .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->sin_family must be initialized to the address family of the socket, passed by .Fa sd . If .Fa sin->sin_port is .Sq 0 then an anonymous port (in the range 600-1023) will be chosen, and if .Xr bind 2 is successful, the .Fa sin->sin_port will be updated to contain the allocated port. .Pp If .Fa sin is the .Dv NULL pointer, an anonymous port will be allocated (as above). However, there is no way for .Fn bindresvport to return the allocated port in this case. .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. The .Fn bindresvport_sa function 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 .Rv -std bindresvport .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 The .Fn bindresvport function 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 getsockopt 2 , .Xr setsockopt 2 , .Xr ip 4 ntirpc-1.3.1/man/des_crypt.3t000066400000000000000000000051771261345040100160400ustar00rootroot00000000000000.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI; .\" .Dd October 6, 1987 .Dt DES_CRYPT 3 .Os .Sh NAME .Nm des_crypt , ecb_crypt , cbc_crypt , des_setparity .Nd "fast DES encryption" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In rpc/des_crypt.h .Ft int .Fn ecb_crypt "char *key" "char *data" "unsigned datalen" "unsigned mode" .Ft int .Fn cbc_crypt "char *key" "char *data" "unsigned datalen" "unsigned mode" "char *ivec" .Ft void .Fn des_setparity "char *key" .Sh DESCRIPTION The .Fn ecb_crypt and .Fn cbc_crypt functions implement the .Tn NBS .Tn DES (Data Encryption Standard). These routines are faster and more general purpose than .Xr crypt 3 . They also are able to utilize .Tn DES hardware if it is available. The .Fn ecb_crypt function encrypts in .Tn ECB (Electronic Code Book) mode, which encrypts blocks of data independently. The .Fn cbc_crypt function encrypts in .Tn CBC (Cipher Block Chaining) mode, which chains together successive blocks. .Tn CBC mode protects against insertions, deletions and substitutions of blocks. Also, regularities in the clear text will not appear in the cipher text. .Pp Here is how to use these routines. The first argument, .Fa key , is the 8-byte encryption key with parity. To set the key's parity, which for .Tn DES is in the low bit of each byte, use .Fn des_setparity . The second argument, .Fa data , contains the data to be encrypted or decrypted. The third argument, .Fa datalen , is the length in bytes of .Fa data , which must be a multiple of 8. The fourth argument, .Fa mode , is formed by .Em OR Ns 'ing together some things. For the encryption direction .Em OR in either .Dv DES_ENCRYPT or .Dv DES_DECRYPT . For software versus hardware encryption, .Em OR in either .Dv DES_HW or .Dv DES_SW . If .Dv DES_HW is specified, and there is no hardware, then the encryption is performed in software and the routine returns .Er DESERR_NOHWDEVICE . For .Fn cbc_crypt , the .Fa ivec argument is the 8-byte initialization vector for the chaining. It is updated to the next initialization vector upon return. .Sh ERRORS .Bl -tag -width [DESERR_NOHWDEVICE] -compact .It Bq Er DESERR_NONE No error. .It Bq Er DESERR_NOHWDEVICE Encryption succeeded, but done in software instead of the requested hardware. .It Bq Er DESERR_HWERR An error occurred in the hardware or driver. .It Bq Er DESERR_BADPARAM Bad argument to routine. .El .Pp Given a result status .Va stat , the macro .Fn DES_FAILED stat is false only for the first two statuses. .Sh SEE ALSO .\" .Xr des 1 , .Xr crypt 3 .Sh RESTRICTIONS These routines are not available in RPCSRC 4.0. This information is provided to describe the .Tn DES interface expected by Secure RPC. ntirpc-1.3.1/man/getnetconfig.3t000066400000000000000000000101111261345040100165000ustar00rootroot00000000000000.\" @(#)getnetconfig.3n 1.28 93/06/02 SMI; from SVr4 .\" 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 . The .Fn getnetconfig function returns a pointer to the current entry in the netconfig database, formatted as a .Ft "struct netconfig" . Successive calls will return successive netconfig entries in the netconfig database. The .Fn getnetconfig function can be used to search the entire netconfig file. The .Fn getnetconfig function returns .Dv NULL at the end of the file. The .Fa handlep argument is the handle obtained through .Fn setnetconfig . .Pp A call to .Fn setnetconfig has the effect of .Dq binding to or .Dq rewinding the netconfig database. The .Fn setnetconfig function must be called before the first call to .Fn getnetconfig and may be called at any other time. The .Fn setnetconfig function need not be called before a call to .Fn getnetconfigent . The .Fn setnetconfig function returns a unique handle to be used by .Fn getnetconfig . .Pp The .Fn endnetconfig function should be called when processing is complete to release resources for reuse. The .Fa handlep argument 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 .Ft "struct netconfig" data structure. The .Fn endnetconfig function may not be called before .Fn setnetconfig . .Pp The .Fn getnetconfigent function 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 The .Fn freenetconfigent function frees the netconfig structure pointed to by .Fa netconfigp (previously returned by .Fn getnetconfigent ) . .Pp The .Fn nc_perror function 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 The .Fn nc_sperror function 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 The .Fn nc_perror and .Fn nc_sperror functions can also be used with the .Ev NETPATH access routines defined in .Xr getnetpath 3 . .Sh RETURN VALUES The .Fn setnetconfig function returns a unique handle to be used by .Fn getnetconfig . In the case of an error, .Fn setnetconfig returns .Dv NULL and .Fn nc_perror or .Fn nc_sperror can be used to print the reason for failure. .Pp The .Fn getnetconfig function returns a pointer to the current entry in the netconfig database, formatted as a .Ft "struct netconfig" . The .Fn getnetconfig function returns .Dv NULL at the end of the file, or upon failure. .Pp The .Fn endnetconfig function 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 .Ft "struct netconfig" structure corresponding to .Fa netid ; otherwise it returns .Dv NULL . .Pp The .Fn nc_sperror function 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 .Bl -tag -width /etc/netconfig -compact .It Pa /etc/netconfig .El .Sh SEE ALSO .Xr getnetpath 3 , .Xr netconfig 5 ntirpc-1.3.1/man/getnetpath.3t000066400000000000000000000057341261345040100162060ustar00rootroot00000000000000.\" @(#)getnetpath.3n 1.26 93/05/07 SMI; from SVr4 .\" Copyright 1989 AT&T .Dd April 22, 2000 .Dt GETNETPATH 3 .Os .Sh NAME .Nm getnetpath , .Nm setnetpath , .Nm endnetpath .Nd get .Pa /etc/netconfig entry corresponding to .Ev 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 .Ev NETPATH environment variable (see .Xr environ 7 ) . See .Xr getnetconfig 3 for other routines that also access the network configuration database directly. The .Ev NETPATH variable is a list of colon-separated network identifiers. .Pp The .Fn getnetpath function returns a pointer to the netconfig database entry corresponding to the first valid .Ev NETPATH component. The netconfig entry is formatted as a .Ft "struct netconfig" . On each subsequent call, .Fn getnetpath returns a pointer to the netconfig entry that corresponds to the next valid .Ev NETPATH component. The .Fn getnetpath function can thus be used to search the netconfig database for all networks included in the .Ev NETPATH variable. When .Ev NETPATH has been exhausted, .Fn getnetpath returns .Dv NULL . .Pp A call to .Fn setnetpath .Dq binds to or .Dq rewinds .Ev NETPATH . The .Fn setnetpath function 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 The .Fn getnetpath function silently ignores invalid .Ev NETPATH components. A .Ev NETPATH component is invalid if there is no corresponding entry in the netconfig database. .Pp If the .Ev NETPATH variable is unset, .Fn getnetpath behaves as if .Ev 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 The .Fn endnetpath function may be called to .Dq unbind from .Ev 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 The .Fn setnetpath function returns a handle that is used by .Fn getnetpath . In case of an error, .Fn setnetpath returns .Dv NULL . .Pp The .Fn endnetpath function returns 0 on success and \-1 on failure (for example, if .Fn setnetpath was not called previously). The .Fn nc_perror or .Fn nc_sperror function 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 .Ev NETPATH component. When .Ev NETPATH has been exhausted, .Fn getnetpath returns .Dv NULL . .Sh SEE ALSO .Xr getnetconfig 3 , .Xr netconfig 5 , .Xr environ 7 ntirpc-1.3.1/man/getrpcent.3t000066400000000000000000000040131261345040100160230ustar00rootroot00000000000000.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI .\" .Dd December 14, 1987 .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 "char *name" .Ft struct rpcent * .Fn getrpcbynumber "int number" .Ft void .Fn setrpcent "int stayopen" .Ft void .Fn endrpcent void .Sh DESCRIPTION The .Fn getrpcent , .Fn getrpcbyname , and .Fn getrpcbynumber functions 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 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 Va r_name The name of the server for this rpc program. .It Va r_aliases A zero terminated list of alternate names for the rpc program. .It Va r_number The rpc program number for this service. .El .Pp The .Fn getrpcent function reads the next line of the file, opening the file if necessary. .Pp The .Fn setrpcent function 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 The .Fn endrpcent function closes the file. .Pp The .Fn getrpcbyname and .Fn getrpcbynumber functions 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 .Bl -tag -width /etc/rpc -compact .It Pa /etc/rpc .El .Sh SEE ALSO .Xr rpc 5 , .Xr rpcinfo 8 , .Xr ypserv 8 .Sh DIAGNOSTICS A .Dv NULL pointer is returned on .Dv EOF or error. .Sh BUGS All information is contained in a static area so it must be copied if it is to be saved. ntirpc-1.3.1/man/getrpcport.3t000066400000000000000000000014301261345040100162210ustar00rootroot00000000000000.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI .\" .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 The .Fn getrpcport function 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. ntirpc-1.3.1/man/netconfig.5000066400000000000000000000060031261345040100156230ustar00rootroot00000000000000.Dd November 17, 2000 .Dt NETCONFIG 5 .Os .Sh NAME .Nm netconfig .Nd network configuration data base .Sh SYNOPSIS .Pa /etc/netconfig .Sh DESCRIPTION The .Nm file defines a list of .Dq transport names , describing their semantics and protocol. In .Fx , this file is only used by the RPC library code. .Pp Entries have the following format: .Pp .Ar network_id semantics flags family protoname device libraries .Pp Entries consist of the following fields: .Bl -tag -width network_id .It Ar network_id The name of the transport described. .It Ar semantics Describes the semantics of the transport. This can be one of: .Bl -tag -width tpi_cots_ord -offset indent .It Sy tpi_clts Connectionless transport. .It Sy tpi_cots Connection-oriented transport .It Sy tpi_cots_ord Connection-oriented, ordered transport. .It Sy tpi_raw A raw connection. .El .It Ar flags This field is either blank (specified by .Dq Li - ) , or contains a .Dq Li v , meaning visible to the .Xr getnetconfig 3 function. .It Ar family The protocol family of the transport. This is currently one of: .Bl -tag -width loopback -offset indent .It Sy inet6 The IPv6 .Pq Dv PF_INET6 family of protocols. .It Sy inet The IPv4 .Pq Dv PF_INET family of protocols. .It Sy loopback The .Dv PF_LOCAL protocol family. .El .It Ar protoname The name of the protocol used for this transport. Can currently be either .Sy udp , .Sy tcp or empty. .It Ar device This field is always empty in .Fx . .It Ar libraries This field is always empty in .Fx . .El .Pp The order of entries in this file will determine which transport will be preferred by the RPC library code, given a match on a specified network type. For example, if a sample network config file would look like this: .Bd -literal -offset indent udp6 tpi_clts v inet6 udp - - tcp6 tpi_cots_ord v inet6 tcp - - udp tpi_clts v inet udp - - tcp tpi_cots_ord v inet tcp - - rawip tpi_raw - inet - - - local tpi_cots_ord - loopback - - - .Ed .Pp then using the network type .Sy udp in calls to the RPC library function (see .Xr rpc 3 ) will make the code first try .Sy udp6 , and then .Sy udp . .Pp .Xr getnetconfig 3 and associated functions will parse this file and return structures of the following format: .Bd -literal struct netconfig { char *nc_netid; /* Network ID */ unsigned long nc_semantics; /* Semantics (see below) */ unsigned long nc_flag; /* Flags (see below) */ char *nc_protofmly; /* Protocol family */ char *nc_proto; /* Protocol name */ char *nc_device; /* Network device pathname (unused) */ unsigned long nc_nlookups; /* Number of lookup libs (unused) */ char **nc_lookups; /* Names of the libraries (unused) */ unsigned long nc_unused[9]; /* reserved */ }; .Ed .Sh FILES .Bl -tag -width /etc/netconfig -compact .It Pa /etc/netconfig .El .Sh SEE ALSO .Xr getnetconfig 3 , .Xr getnetpath 3 ntirpc-1.3.1/man/publickey.3t000066400000000000000000000021421261345040100160200ustar00rootroot00000000000000.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC .\" .Dd October 6, 1987 .Dt PUBLICKEY 3 .Os .Sh NAME .Nm publickey , getpublickey , getsecretkey .Nd "get public or secret key" .Sh LIBRARY .Lb librpcsvc .Sh SYNOPSIS .In rpc/rpc.h .In rpc/key_prot.h .Ft int .Fo getpublickey .Fa "char netname[MAXNETNAMELEN+1]" .Fa "char publickey[HEXKEYBYTES+1]" .Fc .Ft int .Fo getsecretkey .Fa "char netname[MAXNETNAMELEN+1]" .Fa "char secretkey[HEXKEYBYTES+1]" .Fa "char *passwd" .Fc .Sh DESCRIPTION These routines are used to get public and secret keys from the .Tn YP database. The .Fn getsecretkey function has an extra argument, .Fa passwd , which is used to decrypt the encrypted secret key stored in the database. Both routines return 1 if they are successful in finding the key, 0 otherwise. The keys are returned as .Dv NULL Ns \-terminated , hexadecimal strings. If the password supplied to .Fn getsecretkey fails to decrypt the secret key, the routine will return 1 but the .Fa secretkey argument will be a .Dv NULL string .Pq Dq . .Sh SEE ALSO .Xr publickey 5 .Pp .%T "RPC Programmer's Manual" in .Pa /usr/share/doc/psd/23.rpc . ntirpc-1.3.1/man/publickey.5000066400000000000000000000016421261345040100156420ustar00rootroot00000000000000.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI; .Dd October 19, 1987 .Dt PUBLICKEY 5 .Os .Sh NAME .Nm publickey .Nd "public key database" .Sh SYNOPSIS .Pa /etc/publickey .Sh DESCRIPTION .Pa /etc/publickey is the public key database used for secure RPC (Remote Procedure Calls). Each entry in the database consists of a network user name (which may either refer to a user or a hostname), followed by the user's public key (in hex notation), a colon, and then the user's secret key encrypted with its login password (also in hex notation). .Pp This file is altered either by the user through the .Xr chkey 1 command or by the system administrator through the .Xr newkey 8 command. The file .Pa /etc/publickey should only contain data on the .Tn NIS master machine, where it is converted into the .Tn NIS database .Pa publickey.byname . .Sh SEE ALSO .Xr chkey 1 , .Xr publickey 3 , .Xr newkey 8 , .Xr ypupdated 8 ntirpc-1.3.1/man/rpc.3t000066400000000000000000000313611261345040100146220ustar00rootroot00000000000000.\" @(#)rpc.3n 1.31 93/08/31 SMI; from SVr4 .\" Copyright 1989 AT&T .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 .Vt "struct netconfig" also require that .In netconfig.h be included. .Sh Nettype Some of the high-level RPC interface routines take a .Fa nettype string as one of the arguments (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 The .Fa nettype argument 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. .Ev NETPATH is unset or .Dv NULL , it defaults to .Qq visible . .Qq 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 .Qq visible except that it chooses only the connection oriented transports (semantics .Qq tpi_cots or .Qq tpi_cots_ord ) from the entries in the .Pa /etc/netconfig file. .It datagram_v This is same as .Qq visible except that it chooses only the connectionless datagram transports (semantics .Qq tpi_clts ) from the entries in the .Pa /etc/netconfig file. .It circuit_n This is same as .Qq netpath except that it chooses only the connection oriented datagram transports (semantics .Qq tpi_cots or .Qq tpi_cots_ord ) . .It datagram_n This is same as .Qq netpath except that it chooses only the connectionless datagram transports (semantics .Qq 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 .Qq 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. .Sh Derived Types The derived types used in the RPC interfaces are defined as follows: .Bd -literal typedef u_int32_t rpcprog_t; typedef u_int32_t rpcvers_t; typedef u_int32_t rpcproc_t; typedef u_int32_t rpcprot_t; typedef u_int32_t rpcport_t; typedef int32_t rpc_inline_t; .Ed .Sh "Data Structures" Some of the data structures used by the RPC package are shown below. .Sh "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 & 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 .Sh "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 .Sh "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 .Sh "The svc_reg 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 .Sh "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 */ u_int x_handy; /* extra private word */ } XDR; /* * The netbuf structure. This structure is defined in on SysV * systems, but NetBSD / FreeBSD do 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 .Sh "Index to Routines" The following table lists RPC routines and the manual reference pages on which they are described: .Pp .Bl -tag -width "authunix_create_default()" -compact .It Em "RPC Routine" .Em "Manual Reference Page" .Pp .It Fn auth_destroy .Xr rpc_clnt_auth 3 .It Fn authdes_create .Xr rpc_soc 3 .It Fn authnone_create .Xr rpc_clnt_auth 3 .It Fn authsys_create .Xr rpc_clnt_auth 3 .It Fn authsys_create_default .Xr rpc_clnt_auth 3 .It Fn authunix_create .Xr rpc_soc 3 .It Fn authunix_create_default .Xr rpc_soc 3 .It Fn callrpc .Xr rpc_soc 3 .It Fn clnt_broadcast .Xr rpc_soc 3 .It Fn clnt_call .Xr rpc_clnt_calls 3 .It Fn clnt_control .Xr rpc_clnt_create 3 .It Fn clnt_create .Xr rpc_clnt_create 3 .It Fn clnt_create_timed .Xr rpc_clnt_create 3 .It Fn clnt_create_vers .Xr rpc_clnt_create 3 .It Fn clnt_create_vers_timed .Xr rpc_clnt_create 3 .It Fn clnt_destroy .Xr rpc_clnt_create 3 .It Fn clnt_dg_create .Xr rpc_clnt_create 3 .It Fn clnt_freeres .Xr rpc_clnt_calls 3 .It Fn clnt_geterr .Xr rpc_clnt_calls 3 .It Fn clnt_pcreateerror .Xr rpc_clnt_create 3 .It Fn clnt_perrno .Xr rpc_clnt_calls 3 .It Fn clnt_perror .Xr rpc_clnt_calls 3 .It Fn clnt_raw_create .Xr rpc_clnt_create 3 .It Fn clnt_spcreateerror .Xr rpc_clnt_create 3 .It Fn clnt_sperrno .Xr rpc_clnt_calls 3 .It Fn clnt_sperror .Xr rpc_clnt_calls 3 .It Fn clnt_tli_create .Xr rpc_clnt_create 3 .It Fn clnt_tp_create .Xr rpc_clnt_create 3 .It Fn clnt_tp_create_timed .Xr rpc_clnt_create 3 .It Fn clnt_udpcreate .Xr rpc_soc 3 .It Fn clnt_vc_create .Xr rpc_clnt_create 3 .It Fn clntraw_create .Xr rpc_soc 3 .It Fn clnttcp_create .Xr rpc_soc 3 .It Fn clntudp_bufcreate .Xr rpc_soc 3 .It Fn get_myaddress .Xr rpc_soc 3 .It Fn pmap_getmaps .Xr rpc_soc 3 .It Fn pmap_getport .Xr rpc_soc 3 .It Fn pmap_rmtcall .Xr rpc_soc 3 .It Fn pmap_set .Xr rpc_soc 3 .It Fn pmap_unset .Xr rpc_soc 3 .It Fn registerrpc .Xr rpc_soc 3 .It Fn rpc_broadcast .Xr rpc_clnt_calls 3 .It Fn rpc_broadcast_exp .Xr rpc_clnt_calls 3 .It Fn rpc_call .Xr rpc_clnt_calls 3 .It Fn rpc_reg .Xr rpc_svc_calls 3 .It Fn svc_create .Xr rpc_svc_create 3 .It Fn svc_destroy .Xr rpc_svc_create 3 .It Fn svc_dg_create .Xr rpc_svc_create 3 .It Fn svc_dg_enablecache .Xr rpc_svc_calls 3 .It Fn svc_fd_create .Xr rpc_svc_create 3 .It Fn svc_fds .Xr rpc_soc 3 .It Fn svc_freeargs .Xr rpc_svc_reg 3 .It Fn svc_getargs .Xr rpc_svc_reg 3 .It Fn svc_getcaller .Xr rpc_soc 3 .It Fn svc_getreq .Xr rpc_soc 3 .It Fn svc_getreqset .Xr rpc_svc_calls 3 .It Fn svc_getrpccaller .Xr rpc_svc_calls 3 .It Fn svc_kerb_reg .Xr kerberos_rpc 3 .It Fn svc_raw_create .Xr rpc_svc_create 3 .It Fn svc_reg .Xr rpc_svc_calls 3 .It Fn svc_register .Xr rpc_soc 3 .It Fn svc_run .Xr rpc_svc_reg 3 .It Fn svc_sendreply .Xr rpc_svc_reg 3 .It Fn svc_tli_create .Xr rpc_svc_create 3 .It Fn svc_tp_create .Xr rpc_svc_create 3 .It Fn svc_unreg .Xr rpc_svc_calls 3 .It Fn svc_unregister .Xr rpc_soc 3 .It Fn svc_vc_create .Xr rpc_svc_create 3 .It Fn svcerr_auth .Xr rpc_svc_err 3 .It Fn svcerr_decode .Xr rpc_svc_err 3 .It Fn svcerr_noproc .Xr rpc_svc_err 3 .It Fn svcerr_noprog .Xr rpc_svc_err 3 .It Fn svcerr_progvers .Xr rpc_svc_err 3 .It Fn svcerr_systemerr .Xr rpc_svc_err 3 .It Fn svcerr_weakauth .Xr rpc_svc_err 3 .It Fn svcfd_create .Xr rpc_soc 3 .It Fn svcraw_create .Xr rpc_soc 3 .It Fn svctcp_create .Xr rpc_soc 3 .It Fn svcudp_bufcreate .Xr rpc_soc 3 .It Fn svcudp_create .Xr rpc_soc 3 .It Fn xdr_accepted_reply .Xr rpc_xdr 3 .It Fn xdr_authsys_parms .Xr rpc_xdr 3 .It Fn xdr_authunix_parms .Xr rpc_soc 3 .It Fn xdr_callhdr .Xr rpc_xdr 3 .It Fn xdr_callmsg .Xr rpc_xdr 3 .It Fn xdr_opaque_auth .Xr rpc_xdr 3 .It Fn xdr_rejected_reply .Xr rpc_xdr 3 .It Fn xdr_replymsg .Xr rpc_xdr 3 .It Fn xprt_register .Xr rpc_svc_calls 3 .It Fn xprt_unregister .Xr rpc_svc_calls 3 .El .Sh FILES .Bl -tag -width /etc/netconfig .It Pa /etc/netconfig .El .Sh SEE ALSO .Xr getnetconfig 3 , .Xr getnetpath 3 , .Xr rpcbind 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 xdr 3 , .Xr netconfig 5 ntirpc-1.3.1/man/rpc.5000066400000000000000000000021531261345040100144350ustar00rootroot00000000000000.\" @(#)rpc.4 1.17 93/08/30 SMI; from SVr4 .\" Copyright 1989 AT&T .Dd December 10, 1991 .Dt RPC 5 .Os .Sh NAME .Nm rpc .Nd rpc program number data base .Sh SYNOPSIS .Pa /etc/rpc .Sh DESCRIPTION The .Nm file contains user readable names that can be used in place of RPC program numbers. For each RPC program a single line should be present with the following information: .Pp .Bl -enum -compact .It name of the RPC program .It RPC program number .It aliases .El .Pp Items are separated by any number of blanks and/or tab characters. A hash .Pq Dq Li # indicates the beginning of a comment; characters up to the end of the line are not interpreted by routines which search the file. .Sh EXAMPLES Below is an example of an RPC database: .Bd -literal # # rpc # rpcbind 100000 portmap sunrpc portmapper rusersd 100002 rusers nfs 100003 nfsprog mountd 100005 mount showmount walld 100008 rwall shutdown sprayd 100012 spray llockmgr 100020 nlockmgr 100021 status 100024 bootparam 100026 keyserv 100029 keyserver .Ed .Sh FILES .Bl -tag -width /etc/nsswitch.conf -compact .It Pa /etc/nsswitch.conf .El .Sh SEE ALSO .Xr getrpcent 3 ntirpc-1.3.1/man/rpc_clnt_auth.3t000066400000000000000000000046231261345040100166640ustar00rootroot00000000000000.\" @(#)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.1 2000/06/03 09:29:50 fvdl Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_auth.3,v 1.5 2002/12/19 09:40:23 ru 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 .Vt CLIENT handle. The .Va cl_auth field of the .Vt CLIENT structure should be initialized by the .Vt 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 .Fa auth is undefined after calling .Fn auth_destroy . .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. .It Fn authsys_create Create and return an RPC authentication handle that contains .Dv AUTH_SYS authentication information. The .Fa host argument 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. .It Fn authsys_create_default Call .Fn authsys_create with the appropriate arguments. .El .Sh SEE ALSO .Xr rpc 3 , .Xr rpc_clnt_calls 3 , .Xr rpc_clnt_create 3 ntirpc-1.3.1/man/rpc_clnt_calls.3t000066400000000000000000000203001261345040100170070ustar00rootroot00000000000000.\" @(#)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. .\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_calls.3,v 1.7 2002/12/19 09:40:23 ru Exp $ .Dd May 7, 1993 .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 caddr_t 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 "CLIENT *clnt" "const char *s" .Ft "char *" .Fn clnt_sperrno "const enum clnt_stat stat" .Ft "char *" .Fn clnt_sperror "CLIENT *clnt" "const char * s" .Ft "enum clnt_stat" .Fo rpc_broadcast .Fa "const rpcprog_t prognum" "const rpcvers_t versnum" .Fa "const rpcproc_t procnum" "const xdrproc_t inproc" .Fa "const caddr_t in" "const xdrproc_t outproc" "caddr_t out" .Fa "const resultproc_t eachresult" "const char *nettype" .Fc .Ft "enum clnt_stat" .Fo rpc_broadcast_exp .Fa "const rpcprog_t prognum" "const rpcvers_t versnum" .Fa "const rpcproc_t procnum" "const xdrproc_t xargs" .Fa "caddr_t argsp" "const xdrproc_t xresults" .Fa "caddr_t resultsp" "const resultproc_t eachresult" .Fa "const int inittime" "const int waittime" .Fa "const char * nettype" .Fc .Ft "enum clnt_stat" .Fo rpc_call .Fa "const char *host" "const rpcprog_t prognum" .Fa "const rpcvers_t versnum" "const rpcproc_t procnum" .Fa "const xdrproc_t inproc" "const char *in" .Fa "const xdrproc_t outproc" "char *out" "const char *nettype" .Fc .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 .Vt CLIENT handle as one of the arguments. A .Vt 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. .Vt 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 .Vt CLIENT data structure. .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 .Fa inproc argument is the XDR function used to encode the procedure's arguments, and .Fa outproc is the XDR function 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). The .Fa tout argument 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. .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 .Fa out argument 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. .It Fn clnt_geterr A function macro that copies the error structure out of the client handle to the structure at address .Fa errp . .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 . .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 . .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. The .Fn clnt_sperrno function 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_spcreateerror (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. .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. .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 .Qq 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. The .Fn rpc_broadcast function uses .Dv AUTH_SYS credentials by default (see .Xr rpc_clnt_auth 3 ) . .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. The .Fa inittime argument 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 . .It Fn rpc_call Call the remote procedure associated with .Fa prognum , .Fa versnum , and .Fa procnum on the machine, .Fa host . The .Fa inproc argument is used to encode the procedure's arguments, 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). The .Fa nettype argument 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 ntirpc-1.3.1/man/rpc_clnt_create.3t000066400000000000000000000326121261345040100171650ustar00rootroot00000000000000.\" @(#)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.2 2000/06/20 00:53:08 fvdl Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpc_clnt_create.3,v 1.12 2003/09/14 13:41:56 ru Exp $ .Dd May 7, 1993 .Dt RPC_CLNT_CREATE 3 .Os .Sh NAME .Nm rpc_clnt_create , .Nm clnt_control , .Nm clnt_create , .Nm clnt_create_timed , .Nm clnt_create_vers , .Nm clnt_create_vers_timed , .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_tp_create_timed , .Nm clnt_vc_create , .Nm rpc_createerr .Nd "library routines for dealing with creation and manipulation of" .Vt 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_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" "const struct timeval *timeout" .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" "const char *nettype" .Ft "CLIENT *" .Fn clnt_create_vers_timed "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "char *nettype" "const struct timeval *timeout" .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_tp_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct timeval *timeout" .Ft "CLIENT *" .Fn clnt_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "u_int sendsz" "u_int recvsz" .Sh DESCRIPTION RPC library routines allow C language programs to make procedure calls on other machines across the network. First a .Vt 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. The .Fa req argument 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 .Pq Dv RPC_TIMEDOUT . Set the timeout argument 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 "u_int32_t *" Ta "get RPC program version" .It Dv CLSET_VERS Ta "u_int32_t *" Ta "set RPC program version" .It Dv CLGET_XID Ta "u_int32_t *" Ta "get XID of previous call" .It Dv CLSET_XID Ta "u_int32_t *" 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" .It Dv CLSET_CONNECT Ta Vt "int *" Ta use Xr connect 2 .El .Pp The retry timeout is the time that RPC waits for the server to reply before retransmitting the request. The .Fn clnt_control function returns .Dv TRUE on success and .Dv FALSE on failure. .It Fn clnt_create Generic client creation routine for program .Fa prognum and version .Fa versnum . The .Fa host argument identifies the name of the remote host where the server is located. The .Fa nettype argument 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. The .Fn clnt_create function 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 ) . .It Fn clnt_create_timed Generic client creation routine which is similar to .Fn clnt_create but which also has the additional argument .Fa timeout that specifies the maximum amount of time allowed for each transport class tried. In all other respects, the .Fn clnt_create_timed call behaves exactly like the .Fn clnt_create call. .It Fn clnt_create_vers Generic client creation routine which is similar to .Fn clnt_create but which also checks for the version availability. The .Fa host argument identifies the name of the remote host where the server is located. The .Fa nettype argument 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. The .Fa vers_outp argument is set to this value. That is, after a successful return .Fa vers_low <= .Fa *vers_outp <= .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. .It Fn clnt_create_vers_timed Generic client creation routine which is similar to .Fn clnt_create_vers but which also has the additional argument .Fa timeout that specifies the maximum amount of time allowed for each transport class tried. In all other respects, the .Fn clnt_create_vers_timed call behaves exactly like the .Fn clnt_create_vers call. .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->cl_auth" (before calling .Fn clnt_destroy ) to destroy the associated .Vt AUTH structure (see .Xr rpc_clnt_auth 3 ) . .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 .Fa fildes argument 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 .Fa sendsz and .Fa recvsz arguments; values of 0 choose suitable defaults. This routine returns .Dv NULL if it fails. .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. .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. .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. The .Fn clnt_raw_create function should be called after .Fn svc_raw_create . .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. The .Fa fildes argument 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 .Fa sendsz and .Fa recvsz arguments; 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. .It Fn clnt_tp_create Like .Fn clnt_create except .Fn clnt_tp_create tries only one transport specified through .Fa netconf . The .Fn clnt_tp_create function 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. .It Fn clnt_tp_create_timed Like .Fn clnt_tp_create except .Fn clnt_tp_create_timed has the extra argument .Fa timeout which specifies the maximum time allowed for the creation attempt to succeed. In all other respects, the .Fn clnt_tp_create_timed call behaves exactly like the .Fn clnt_tp_create call. .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 .Fa fildes argument is an open and bound file descriptor. The user may specify the size of the send and receive buffers with the .Fa sendsz and .Fa recvsz arguments; 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. The .Fn clnt_vc_create function does not consult the remote rpcbind service for this information. .It Xo .Vt "struct rpc_createerr" Va rpc_createerr ; .Xc 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 ntirpc-1.3.1/man/rpc_secure.3t000066400000000000000000000137411261345040100161720ustar00rootroot00000000000000.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI .\" $FreeBSD: src/lib/libc/rpc/rpc_secure.3,v 1.14 2002/12/19 09:40:23 ru Exp $ .\" .Dd February 16, 1988 .Dt RPC 3 .Os .Sh NAME .Nm rpc_secure .Nd library routines for secure remote procedure calls .Sh SYNOPSIS .In rpc/rpc.h .Ft AUTH * .Fo authdes_create .Fa "char *name" .Fa "unsigned window" .Fa "struct sockaddr *addr" .Fa "des_block *ckey" .Fc .Ft int .Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups" .Ft int .Fn getnetname "char *name" .Ft int .Fn host2netname "char *name" "const char *host" "const char *domain" .Ft int .Fn key_decryptsession "const char *remotename" "des_block *deskey" .Ft int .Fn key_encryptsession "const char *remotename" "des_block *deskey" .Ft int .Fn key_gendes "des_block *deskey" .Ft int .Fn key_setsecret "const char *key" .Ft int .Fn netname2host "char *name" "char *host" "int hostlen" .Ft int .Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist" .Ft int .Fn user2netname "char *name" "const uid_t uid" "const char *domain" .Sh DESCRIPTION These routines are part of the .Tn RPC library. They implement .Tn DES Authentication. See .Xr rpc 3 for further details about .Tn RPC . .Pp The .Fn authdes_create is the first of two routines which interface to the .Tn RPC secure authentication system, known as .Tn DES authentication. The second is .Fn authdes_getucred , below. .Pp Note: the keyserver daemon .Xr keyserv 8 must be running for the .Tn DES authentication system to work. .Pp The .Fn authdes_create function, used on the client side, returns an authentication handle that will enable the use of the secure authentication system. The first argument .Fa name is the network name, or .Fa netname , of the owner of the server process. This field usually represents a .Fa hostname derived from the utility routine .Fn host2netname , but could also represent a user name using .Fn user2netname . The second field is window on the validity of the client credential, given in seconds. A small window is more secure than a large one, but choosing too small of a window will increase the frequency of resynchronizations because of clock drift. The third argument .Fa addr is optional. If it is .Dv NULL , then the authentication system will assume that the local clock is always in sync with the server's clock, and will not attempt resynchronizations. If an address is supplied, however, then the system will use the address for consulting the remote time service whenever resynchronization is required. This argument is usually the address of the .Tn RPC server itself. The final argument .Fa ckey is also optional. If it is .Dv NULL , then the authentication system will generate a random .Tn DES key to be used for the encryption of credentials. If it is supplied, however, then it will be used instead. .Pp The .Fn authdes_getucred function, the second of the two .Tn DES authentication routines, is used on the server side for converting a .Tn DES credential, which is operating system independent, into a .Ux credential. This routine differs from utility routine .Fn netname2user in that .Fn authdes_getucred pulls its information from a cache, and does not have to do a Yellow Pages lookup every time it is called to get its information. .Pp The .Fn getnetname function installs the unique, operating-system independent netname of the caller in the fixed-length array .Fa name . Returns .Dv TRUE if it succeeds and .Dv FALSE if it fails. .Pp The .Fn host2netname function converts from a domain-specific hostname to an operating-system independent netname. Returns .Dv TRUE if it succeeds and .Dv FALSE if it fails. Inverse of .Fn netname2host . .Pp The .Fn key_decryptsession function is an interface to the keyserver daemon, which is associated with .Tn RPC Ns 's secure authentication system .Tn ( DES authentication). User programs rarely need to call it, or its associated routines .Fn key_encryptsession , .Fn key_gendes and .Fn key_setsecret . System commands such as .Xr login 1 and the .Tn RPC library are the main clients of these four routines. .Pp The .Fn key_decryptsession function takes a server netname and a .Tn DES key, and decrypts the key by using the public key of the server and the secret key associated with the effective uid of the calling process. It is the inverse of .Fn key_encryptsession . .Pp The .Fn key_encryptsession function is a keyserver interface routine. It takes a server netname and a des key, and encrypts it using the public key of the server and the secret key associated with the effective uid of the calling process. It is the inverse of .Fn key_decryptsession . .Pp The .Fn key_gendes function is a keyserver interface routine. It is used to ask the keyserver for a secure conversation key. Choosing one .Qq random is usually not good enough, because the common ways of choosing random numbers, such as using the current time, are very easy to guess. .Pp The .Fn key_setsecret function is a keyserver interface routine. It is used to set the key for the effective .Fa uid of the calling process. .Pp The .Fn netname2host function converts from an operating-system independent netname to a domain-specific hostname. Returns .Dv TRUE if it succeeds and .Dv FALSE if it fails. Inverse of .Fn host2netname . .Pp The .Fn netname2user function converts from an operating-system independent netname to a domain-specific user ID. Returns .Dv TRUE if it succeeds and .Dv FALSE if it fails. Inverse of .Fn user2netname . .Pp The .Fn user2netname function converts from a domain-specific username to an operating-system independent netname. Returns .Dv TRUE if it succeeds and .Dv FALSE if it fails. Inverse of .Fn netname2user . .Sh SEE ALSO .Xr rpc 3 , .Xr xdr 3 , .Xr keyserv 8 .Pp The following manuals: .Rs .%B Remote Procedure Calls: Protocol Specification .Re .Rs .%B Remote Procedure Call Programming Guide .Re .Rs .%B Rpcgen Programming Guide .Re .Rs .%B RPC: Remote Procedure Call Protocol Specification .%O RFC1050, Sun Microsystems Inc., USC-ISI .Re ntirpc-1.3.1/man/rpc_soc.3t000066400000000000000000000775351261345040100155030ustar00rootroot00000000000000.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI .\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpc_soc.3,v 1.12 2003/02/06 11:04:47 charnier Exp $ .\" .Dd February 16, 1988 .Dt RPC_SOC 3 .Os .Sh NAME .Nm rpc_soc , .Nm auth_destroy , .Nm authnone_create , .Nm authunix_create , .Nm authunix_create_default , .Nm callrpc , .Nm clnt_broadcast , .Nm clnt_call , .Nm clnt_control , .Nm clnt_create , .Nm clnt_destroy , .Nm clnt_freeres , .Nm clnt_geterr , .Nm clnt_pcreateerror , .Nm clnt_perrno , .Nm clnt_perror , .Nm clnt_spcreateerror , .Nm clnt_sperrno , .Nm clnt_sperror , .Nm clntraw_create , .Nm clnttcp_create , .Nm clntudp_bufcreate , .Nm clntudp_create , .Nm clntunix_create , .Nm get_myaddress , .Nm pmap_getmaps , .Nm pmap_getport , .Nm pmap_rmtcall , .Nm pmap_set , .Nm pmap_unset , .Nm registerrpc , .Nm rpc_createerr , .Nm svc_destroy , .Nm svc_fds , .Nm svc_fdset , .Nm svc_getargs , .Nm svc_getcaller , .Nm svc_getreq , .Nm svc_getreqset , .Nm svc_register , .Nm svc_run , .Nm svc_sendreply , .Nm svc_unregister , .Nm svcerr_auth , .Nm svcerr_decode , .Nm svcerr_noproc , .Nm svcerr_noprog , .Nm svcerr_progvers , .Nm svcerr_systemerr , .Nm svcerr_weakauth , .Nm svcfd_create , .Nm svcunixfd_create , .Nm svcraw_create , .Nm svcunix_create , .Nm xdr_accepted_reply , .Nm xdr_authunix_parms , .Nm xdr_callhdr , .Nm xdr_callmsg , .Nm xdr_opaque_auth , .Nm xdr_pmap , .Nm xdr_pmaplist , .Nm xdr_rejected_reply , .Nm xdr_replymsg , .Nm xprt_register , .Nm xprt_unregister .Nd "library routines for remote procedure calls" .Sh LIBRARY .Lb libc .Sh SYNOPSIS .In rpc/rpc.h .Pp See .Sx DESCRIPTION for function declarations. .Sh DESCRIPTION .Bf -symbolic The .Fn svc_* and .Fn clnt_* functions described in this page are the old, TS-RPC interface to the XDR and RPC library, and exist for backward compatibility. The new interface is described in the pages referenced from .Xr rpc 3 . .Ef .Pp These routines allow C programs to make procedure calls on other machines across the network. First, the client calls a procedure to send a data packet to the server. Upon receipt of the packet, the server calls a dispatch routine to perform the requested service, and then sends back a reply. Finally, the procedure call returns to the client. .Pp Routines that are used for Secure .Tn RPC ( DES authentication) are described in .Xr rpc_secure 3 . Secure .Tn RPC can be used only if .Tn DES encryption is available. .Bl -tag -width indent -compact .Pp .It Xo .Ft void .Xc .It Xo .Fn auth_destroy "AUTH *auth" .Xc .Pp A macro that destroys the authentication information associated with .Fa auth . Destruction usually involves deallocation of private data structures. The use of .Fa auth is undefined after calling .Fn auth_destroy . .Pp .It Xo .Ft "AUTH *" .Xc .It Xo .Fn authnone_create .Xc .Pp Create and return an .Tn RPC authentication handle that passes nonusable authentication information with each remote procedure call. This is the default authentication used by .Tn RPC . .Pp .It Xo .Ft "AUTH *" .Xc .It Xo .Fn authunix_create "char *host" "int uid" "int gid" "int len" "int *aup_gids" .Xc .Pp Create and return an .Tn RPC authentication handle that contains .Ux authentication information. The .Fa host argument 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. It is easy to impersonate a user. .Pp .It Xo .Ft "AUTH *" .Xc .It Xo .Fn authunix_create_default .Xc .Pp Calls .Fn authunix_create with the appropriate arguments. .Pp .It Xo .Ft int .Fo callrpc .Fa "char *host" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "u_long procnum" .Fa "xdrproc_t inproc" .Fa "void *in" .Fa "xdrproc_t outproc" .Fa "void *out" .Fc .Xc .Pp Call the remote procedure associated with .Fa prognum , .Fa versnum , and .Fa procnum on the machine .Fa host . The .Fa in argument is the address of the procedure's argument(s), and .Fa out is the address of where to place the result(s); .Fa inproc is used to encode the procedure's arguments, and .Fa outproc is used to decode the procedure's results. This routine returns zero if it succeeds, or the value of .Vt "enum clnt_stat" cast to an integer if it fails. The routine .Fn clnt_perrno is handy for translating failure statuses into messages. .Pp Warning: calling remote procedures with this routine uses .Tn UDP/IP as a transport; see .Fn clntudp_create for restrictions. You do not have control of timeouts or authentication using this routine. .Pp .It Xo .Ft "enum clnt_stat" .Xc .It Xo .Fo clnt_broadcast .Fa "u_long prognum" .Fa "u_long versnum" .Fa "u_long procnum" .Fa "xdrproc_t inproc" .Fa "char *in" .Fa "xdrproc_t outproc" .Fa "char *out" .Fa "bool_t (*eachresult)(caddr_t, struct sockaddr_in *)" .Fc .Xc .Pp Like .Fn callrpc , except the call message is broadcast to all locally connected broadcast nets. Each time it receives a response, this routine calls .Fn eachresult , whose form is: .Bd -ragged -offset indent .Ft bool_t .Fn eachresult "caddr_t out" "struct sockaddr_in *addr" .Ed .Pp where .Fa out is the same as .Fa out passed to .Fn clnt_broadcast , except that the remote procedure's output is decoded there; .Fa addr points to the address of the machine that sent the results. If .Fn eachresult returns zero, .Fn clnt_broadcast waits for more replies; otherwise it returns with appropriate status. .Pp Warning: broadcast sockets are limited in size to the maximum transfer unit of the data link. For ethernet, this value is 1500 bytes. .Pp .It Xo .Ft "enum clnt_stat" .Xc .It Xo .Fo clnt_call .Fa "CLIENT *clnt" .Fa "u_long procnum" .Fa "xdrproc_t inproc" .Fa "char *in" .Fa "xdrproc_t outproc" .Fa "char *out" .Fa "struct timeval tout" .Fc .Xc .Pp A macro that calls the remote procedure .Fa procnum associated with the client handle, .Fa clnt , which is obtained with an .Tn RPC client creation routine such as .Fn clnt_create . The .Fa in argument is the address of the procedure's argument(s), and .Fa out is the address of where to place the result(s); .Fa inproc is used to encode the procedure's arguments, and .Fa outproc is used to decode the procedure's results; .Fa tout is the time allowed for results to come back. .Pp .It Xo .Ft void .Fn clnt_destroy "CLIENT *clnt" .Xc .Pp A macro that destroys the client's .Tn 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 .Tn RPC library opened the associated socket, it will close it also. Otherwise, the socket remains open. .Pp .It Xo .Ft CLIENT * .Xc .It Xo .Fn clnt_create "char *host" "u_long prog" "u_long vers" "char *proto" .Xc .Pp Generic client creation routine. The .Fa host argument identifies the name of the remote host where the server is located. The .Fa proto argument indicates which kind of transport protocol to use. The currently supported values for this field are .Qq Li udp and .Qq Li tcp . Default timeouts are set, but can be modified using .Fn clnt_control . .Pp Warning: Using .Tn UDP has its shortcomings. Since .Tn UDP Ns \-based .Tn RPC messages can only hold up to 8 Kbytes of encoded data, this transport cannot be used for procedures that take large arguments or return huge results. .Pp .It Xo .Ft bool_t .Xc .It Xo .Fn clnt_control "CLIENT *cl" "u_int req" "char *info" .Xc .Pp A macro used to change or retrieve various information about a client object. The .Fa req argument indicates the type of operation, and .Fa info is a pointer to the information. For both .Tn UDP and .Tn TCP , the supported values of .Fa req and their argument types and what they do are: .Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in" .It Dv CLSET_TIMEOUT Ta Xo .Vt "struct timeval" Ta "set total timeout" .Xc .It Dv CLGET_TIMEOUT Ta Xo .Vt "struct timeval" Ta "get total timeout" .Xc .El .Pp Note: if you set the timeout using .Fn clnt_control , the timeout argument passed to .Fn clnt_call will be ignored in all future calls. .Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in" .It Dv CLGET_SERVER_ADDR Ta Xo .Vt "struct sockaddr_in" Ta "get server's address" .Xc .El .Pp The following operations are valid for .Tn UDP only: .Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in" .It Dv CLSET_RETRY_TIMEOUT Ta Xo .Vt "struct timeval" Ta "set the retry timeout" .Xc .It Dv CLGET_RETRY_TIMEOUT Ta Xo .Vt "struct timeval" Ta "get the retry timeout" .Xc .El .Pp The retry timeout is the time that .Tn "UDP RPC" waits for the server to reply before retransmitting the request. .Pp .It Xo .Ft bool_t .Fn clnt_freeres "CLIENT *clnt" "xdrproc_t outproc" "char *out" .Xc .Pp A macro that frees any data allocated by the .Tn RPC/XDR system when it decoded the results of an .Tn RPC call. The .Fa out argument is the address of the results, and .Fa outproc is the .Tn XDR routine describing the results. This routine returns one if the results were successfully freed, and zero otherwise. .Pp .It Xo .Ft void .Xc .It Xo .Fn clnt_geterr "CLIENT *clnt" "struct rpc_err *errp" .Xc .Pp A macro that copies the error structure out of the client handle to the structure at address .Fa errp . .Pp .It Xo .Ft void .Xc .It Xo .Fn clnt_pcreateerror "char *s" .Xc .Pp prints a message to standard error indicating why a client .Tn RPC handle could not be created. The message is prepended with string .Fa s and a colon. A newline is appended at the end of the message. Used when a .Fn clnt_create , .Fn clntraw_create , .Fn clnttcp_create , or .Fn clntudp_create call fails. .Pp .It Xo .Ft void .Xc .It Xo .Fn clnt_perrno "enum clnt_stat stat" .Xc .Pp Print a message to standard error corresponding to the condition indicated by .Fa stat . A newline is appended at the end of the message. Used after .Fn callrpc . .Pp .It Xo .Ft void .Fn clnt_perror "CLIENT *clnt" "char *s" .Xc .Pp Print a message to standard error indicating why an .Tn 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 at the end of the message. Used after .Fn clnt_call . .Pp .It Xo .Ft "char *" .Xc .It Xo .Fn clnt_spcreateerror "char *s" .Xc .Pp Like .Fn clnt_pcreateerror , except that it returns a string instead of printing to the standard error. .Pp Bugs: returns pointer to static data that is overwritten on each call. .Pp .It Xo .Ft "char *" .Xc .It Xo .Fn clnt_sperrno "enum clnt_stat stat" .Xc .Pp Take the same arguments as .Fn clnt_perrno , but instead of sending a message to the standard error indicating why an .Tn RPC call failed, return a pointer to a string which contains the message. .Pp The .Fn clnt_sperrno function is used instead of .Fn clnt_perrno if the program does not have a standard error (as a program running as a server quite likely does not), or if the programmer does not want the message to be output with .Fn printf , or if a message format different from that supported by .Fn clnt_perrno is to be used. .Pp Note: unlike .Fn clnt_sperror and .Fn clnt_spcreateerror , .Fn clnt_sperrno returns pointer to static data, but the result will not get overwritten on each call. .Pp .It Xo .Ft "char *" .Xc .It Xo .Fn clnt_sperror "CLIENT *rpch" "char *s" .Xc .Pp Like .Fn clnt_perror , except that (like .Fn clnt_sperrno ) it returns a string instead of printing to standard error. .Pp Bugs: returns pointer to static data that is overwritten on each call. .Pp .It Xo .Ft "CLIENT *" .Xc .It Xo .Fn clntraw_create "u_long prognum" "u_long versnum" .Xc .Pp This routine creates a toy .Tn RPC client for the remote program .Fa prognum , version .Fa versnum . The transport used to pass messages to the service is actually a buffer within the process's address space, so the corresponding .Tn RPC server should live in the same address space; see .Fn svcraw_create . This allows simulation of .Tn RPC and acquisition of .Tn RPC overheads, such as round trip times, without any kernel interference. This routine returns .Dv NULL if it fails. .Pp .It Xo .Ft "CLIENT *" .Xc .It Xo .Fo clnttcp_create .Fa "struct sockaddr_in *addr" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "int *sockp" .Fa "u_int sendsz" .Fa "u_int recvsz" .Fc .Xc .Pp This routine creates an .Tn RPC client for the remote program .Fa prognum , version .Fa versnum ; the client uses .Tn TCP/IP as a transport. The remote program is located at Internet address .Fa addr . If .Fa addr\->sin_port is zero, then it is set to the actual port that the remote program is listening on (the remote .Xr rpcbind 8 service is consulted for this information). The .Fa sockp argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets .Fa sockp . Since .Tn TCP Ns \-based .Tn RPC uses buffered .Tn I/O , the user may specify the size of the send and receive buffers with the .Fa sendsz and .Fa recvsz arguments; values of zero choose suitable defaults. This routine returns .Dv NULL if it fails. .Pp .It Xo .Ft "CLIENT *" .Xc .It Xo .Fo clntudp_create .Fa "struct sockaddr_in *addr" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "struct timeval wait" .Fa "int *sockp" .Fc .Xc .Pp This routine creates an .Tn RPC client for the remote program .Fa prognum , version .Fa versnum ; the client uses .Tn UDP/IP as a transport. The remote program is located at Internet address .Fa addr . If .Fa addr\->sin_port is zero, then it is set to actual port that the remote program is listening on (the remote .Xr rpcbind 8 service is consulted for this information). The .Fa sockp argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets .Fa sockp . The .Tn UDP transport resends the call message in intervals of .Fa wait time until a response is received or until the call times out. The total time for the call to time out is specified by .Fn clnt_call . .Pp Warning: since .Tn UDP Ns \-based .Tn RPC messages can only hold up to 8 Kbytes of encoded data, this transport cannot be used for procedures that take large arguments or return huge results. .Pp .It Xo .Ft "CLIENT *" .Xc .It Xo .Fo clntudp_bufcreate .Fa "struct sockaddr_in *addr" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "struct timeval wait" .Fa "int *sockp" .Fa "unsigned int sendsize" .Fa "unsigned int recosize" .Fc .Xc .Pp This routine creates an .Tn RPC client for the remote program .Fa prognum , on .Fa versnum ; the client uses .Tn UDP/IP as a transport. The remote program is located at Internet address .Fa addr . If .Fa addr\->sin_port is zero, then it is set to actual port that the remote program is listening on (the remote .Xr rpcbind 8 service is consulted for this information). The .Fa sockp argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets .Fa sockp . The .Tn UDP transport resends the call message in intervals of .Fa wait time until a response is received or until the call times out. The total time for the call to time out is specified by .Fn clnt_call . .Pp This allows the user to specify the maximum packet size for sending and receiving .Tn UDP Ns \-based .Tn RPC messages. .Pp .It Xo .Ft "CLIENT *" .Xc .It Xo .Fo clntunix_create .Fa "struct sockaddr_un *raddr" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "int *sockp" .Fa "u_int sendsz" .Fa "u_int recvsz" .Fc .Xc .Pp This routine creates an .Tn RPC client for the local program .Fa prognum , version .Fa versnum ; the client uses .Ux Ns -domain sockets as a transport. The local program is located at the .Fa *raddr . The .Fa sockp argument is a socket; if it is .Dv RPC_ANYSOCK , then this routine opens a new one and sets .Fa sockp . Since .Ux Ns -based .Tn RPC uses buffered .Tn I/O , the user may specify the size of the send and receive buffers with the .Fa sendsz and .Fa recvsz arguments; values of zero choose suitable defaults. This routine returns .Dv NULL if it fails. .Pp .It Xo .Ft int .Xc .It Xo .Fn get_myaddress "struct sockaddr_in *addr" .Xc .Pp Stuff the machine's .Tn IP address into .Fa addr , without consulting the library routines that deal with .Pa /etc/hosts . The port number is always set to .Fn htons PMAPPORT . Returns zero on success, non-zero on failure. .Pp .It Xo .Ft "struct pmaplist *" .Xc .It Xo .Fn pmap_getmaps "struct sockaddr_in *addr" .Xc .Pp A user interface to the .Xr rpcbind 8 service, which returns a list of the current .Tn RPC program\-to\-port mappings on the host located at .Tn IP address .Fa addr . This routine can return .Dv NULL . The command .Dq Nm rpcinfo Fl p uses this routine. .Pp .It Xo .Ft u_short .Xc .It Xo .Fo pmap_getport .Fa "struct sockaddr_in *addr" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "u_long protocol" .Fc .Xc .Pp A user interface to the .Xr rpcbind 8 service, which returns the port number on which waits a service that supports program number .Fa prognum , version .Fa versnum , and speaks the transport protocol associated with .Fa protocol . The value of .Fa protocol is most likely .Dv IPPROTO_UDP or .Dv IPPROTO_TCP . A return value of zero means that the mapping does not exist or that the .Tn RPC system failed to contact the remote .Xr rpcbind 8 service. In the latter case, the global variable .Va rpc_createerr contains the .Tn RPC status. .Pp .It Xo .Ft "enum clnt_stat" .Xc .It Xo .Fo pmap_rmtcall .Fa "struct sockaddr_in *addr" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "u_long procnum" .Fa "xdrproc_t inproc" .Fa "char *in" .Fa "xdrproc_t outproc" .Fa "char *out" .Fa "struct timeval tout" .Fa "u_long *portp" .Fc .Xc .Pp A user interface to the .Xr rpcbind 8 service, which instructs .Xr rpcbind 8 on the host at .Tn IP address .Fa addr to make an .Tn RPC call on your behalf to a procedure on that host. The .Fa portp argument will be modified to the program's port number if the procedure succeeds. The definitions of other arguments are discussed in .Fn callrpc and .Fn clnt_call . This procedure should be used for a .Dq ping and nothing else. See also .Fn clnt_broadcast . .Pp .It Xo .Ft bool_t .Fn pmap_set "u_long prognum" "u_long versnum" "u_long protocol" "u_short port" .Xc .Pp A user interface to the .Xr rpcbind 8 service, which establishes a mapping between the triple .Pq Fa prognum , versnum , protocol and .Fa port on the machine's .Xr rpcbind 8 service. The value of .Fa protocol is most likely .Dv IPPROTO_UDP or .Dv IPPROTO_TCP . This routine returns one if it succeeds, zero otherwise. Automatically done by .Fn svc_register . .Pp .It Xo .Ft bool_t .Fn pmap_unset "u_long prognum" "u_long versnum" .Xc .Pp A user interface to the .Xr rpcbind 8 service, which destroys all mapping between the triple .Pq Fa prognum , versnum , * and .Fa ports on the machine's .Xr rpcbind 8 service. This routine returns one if it succeeds, zero otherwise. .Pp .It Xo .Ft bool_t .Fo registerrpc .Fa "u_long prognum" .Fa "u_long versnum" .Fa "u_long procnum" .Fa "char *(*procname)(void)" .Fa "xdrproc_t inproc" .Fa "xdrproc_t outproc" .Fc .Xc .Pp Register procedure .Fa procname with the .Tn 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 argument(s); .Fa progname should return a pointer to its static result(s); .Fa inproc is used to decode the arguments while .Fa outproc is used to encode the results. This routine returns zero if the registration succeeded, \-1 otherwise. .Pp Warning: remote procedures registered in this form are accessed using the .Tn UDP/IP transport; see .Fn svcudp_create for restrictions. .Pp .It Xo .Vt "struct rpc_createerr" rpc_createerr ; .Xc .Pp A global variable whose value is set by any .Tn RPC client creation routine that does not succeed. Use the routine .Fn clnt_pcreateerror to print the reason why. .Pp .It Xo .Ft bool_t .Fn svc_destroy "SVCXPRT * xprt" .Xc .Pp A macro that destroys the .Tn RPC service transport 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 Xo .Vt fd_set svc_fdset ; .Xc .Pp A global variable reflecting the .Tn RPC service side's read file descriptor bit mask; it is suitable as a template argument to the .Xr select 2 system call. This is only of interest if a service implementor does not call .Fn svc_run , but rather does his 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. As well, note that if the process has descriptor limits which are extended beyond .Dv FD_SETSIZE , this variable will only be usable for the first .Dv FD_SETSIZE descriptors. .Pp .It Xo .Vt int svc_fds ; .Xc .Pp Similar to .Va svc_fdset , but limited to 32 descriptors. This interface is obsoleted by .Va svc_fdset . .Pp .It Xo .Ft bool_t .Fn svc_freeargs "SVCXPRT *xprt" "xdrproc_t inproc" "char *in" .Xc .Pp A macro that frees any data allocated by the .Tn RPC/XDR system when it decoded the arguments to a service procedure using .Fn svc_getargs . This routine returns 1 if the results were successfully freed, and zero otherwise. .Pp .It Xo .Ft bool_t .Fn svc_getargs "SVCXPRT *xprt" "xdrproc_t inproc" "char *in" .Xc .Pp A macro that decodes the arguments of an .Tn RPC request associated with the .Tn RPC service transport handle, .Fa xprt . The .Fa in argument is the address where the arguments will be placed; .Fa inproc is the .Tn XDR routine used to decode the arguments. This routine returns one if decoding succeeds, and zero otherwise. .Pp .It Xo .Ft "struct sockaddr_in *" .Xc .It Xo .Fn svc_getcaller "SVCXPRT *xprt" .Xc .Pp The approved way of getting the network address of the caller of a procedure associated with the .Tn RPC service transport handle, .Fa xprt . .Pp .It Xo .Ft void .Fn svc_getreqset "fd_set *rdfds" .Xc .Pp 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 the .Xr select 2 system call has determined that an .Tn RPC request has arrived on some .Tn RPC socket(s); .Fa rdfds is the resultant read file descriptor bit mask. The routine returns when all sockets associated with the value of .Fa rdfds have been serviced. .Pp .It Xo .Ft void .Fn svc_getreq "int rdfds" .Xc .Pp Similar to .Fn svc_getreqset , but limited to 32 descriptors. This interface is obsoleted by .Fn svc_getreqset . .Pp .It Xo .Ft bool_t .Fo svc_register .Fa "SVCXPRT *xprt" .Fa "u_long prognum" .Fa "u_long versnum" .Fa "void (*dispatch)(struct svc_req *, SVCXPRT *)" .Fa "int protocol" .Fc .Xc .Pp Associates .Fa prognum and .Fa versnum with the service dispatch procedure, .Fn dispatch . If .Fa protocol is zero, the service is not registered with the .Xr rpcbind 8 service. If .Fa protocol is non-zero, then a mapping of the triple .Pq Fa prognum , versnum , protocol to .Fa xprt\->xp_port is established with the local .Xr rpcbind 8 service (generally .Fa protocol is zero, .Dv IPPROTO_UDP or .Dv IPPROTO_TCP ) . The procedure .Fn dispatch has the following form: .Bd -ragged -offset indent .Ft bool_t .Fn dispatch "struct svc_req *request" "SVCXPRT *xprt" .Ed .Pp The .Fn svc_register routine returns one if it succeeds, and zero otherwise. .Pp .It Xo .Fn svc_run .Xc .Pp This routine never returns. It waits for .Tn RPC requests to arrive, and calls the appropriate service procedure using .Fn svc_getreq when one arrives. This procedure is usually waiting for a .Xr select 2 system call to return. .Pp .It Xo .Ft bool_t .Fn svc_sendreply "SVCXPRT *xprt" "xdrproc_t outproc" "char *out" .Xc .Pp Called by an .Tn RPC service's dispatch routine to send the results of a remote procedure call. The .Fa xprt argument is the request's associated transport handle; .Fa outproc is the .Tn XDR routine which is used to encode the results; and .Fa out is the address of the results. This routine returns one if it succeeds, zero otherwise. .Pp .It Xo .Ft void .Xc .It Xo .Fn svc_unregister "u_long prognum" "u_long versnum" .Xc .Pp Remove all mapping of the double .Pq Fa prognum , versnum to dispatch routines, and of the triple .Pq Fa prognum , versnum , * to port number. .Pp .It Xo .Ft void .Xc .It Xo .Fn svcerr_auth "SVCXPRT *xprt" "enum auth_stat why" .Xc .Pp Called by a service dispatch routine that refuses to perform a remote procedure call due to an authentication error. .Pp .It Xo .Ft void .Xc .It Xo .Fn svcerr_decode "SVCXPRT *xprt" .Xc .Pp Called by a service dispatch routine that cannot successfully decode its arguments. See also .Fn svc_getargs . .Pp .It Xo .Ft void .Xc .It Xo .Fn svcerr_noproc "SVCXPRT *xprt" .Xc .Pp Called by a service dispatch routine that does not implement the procedure number that the caller requests. .Pp .It Xo .Ft void .Xc .It Xo .Fn svcerr_noprog "SVCXPRT *xprt" .Xc .Pp Called when the desired program is not registered with the .Tn RPC package. Service implementors usually do not need this routine. .Pp .It Xo .Ft void .Xc .It Xo .Fn svcerr_progvers "SVCXPRT *xprt" "u_long low_vers" "u_long high_vers" .Xc .Pp Called when the desired version of a program is not registered with the .Tn RPC package. Service implementors usually do not need this routine. .Pp .It Xo .Ft void .Xc .It Xo .Fn svcerr_systemerr "SVCXPRT *xprt" .Xc .Pp 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 Xo .Ft void .Xc .It Xo .Fn svcerr_weakauth "SVCXPRT *xprt" .Xc .Pp Called by a service dispatch routine that refuses to perform a remote procedure call due to insufficient authentication arguments. The routine calls .Fn svcerr_auth xprt AUTH_TOOWEAK . .Pp .It Xo .Ft "SVCXPRT *" .Xc .It Xo .Fn svcraw_create void .Xc .Pp This routine creates a toy .Tn RPC service transport, to which it returns a pointer. The transport is really a buffer within the process's address space, so the corresponding .Tn RPC client should live in the same address space; see .Fn clntraw_create . This routine allows simulation of .Tn RPC and acquisition of .Tn RPC overheads (such as round trip times), without any kernel interference. This routine returns .Dv NULL if it fails. .Pp .It Xo .Ft "SVCXPRT *" .Xc .It Xo .Fn svctcp_create "int sock" "u_int send_buf_size" "u_int recv_buf_size" .Xc .Pp This routine creates a .Tn TCP/IP Ns \-based .Tn RPC service transport, to which it returns a pointer. The transport is associated with the socket .Fa sock , which may be .Dv RPC_ANYSOCK , in which case a new socket is created. If the socket is not bound to a local .Tn TCP port, then this routine binds it to an arbitrary port. Upon completion, .Fa xprt\->xp_fd is the transport's socket descriptor, and .Fa xprt\->xp_port is the transport's port number. This routine returns .Dv NULL if it fails. Since .Tn TCP Ns \-based .Tn RPC uses buffered .Tn I/O , users may specify the size of buffers; values of zero choose suitable defaults. .Pp .It Xo .Ft "SVCXPRT *" .Xc .It Xo .Fn svcunix_create "int sock" "u_int send_buf_size" "u_int recv_buf_size" "char *path" .Xc .Pp This routine creates a .Ux Ns -based .Tn RPC service transport, to which it returns a pointer. The transport is associated with the socket .Fa sock , which may be .Dv RPC_ANYSOCK , in which case a new socket is created. The .Fa *path argument is a variable-length file system pathname of at most 104 characters. This file is .Em not removed when the socket is closed. The .Xr unlink 2 system call must be used to remove the file. Upon completion, .Fa xprt\->xp_fd is the transport's socket descriptor. This routine returns .Dv NULL if it fails. Since .Ux Ns -based .Tn RPC uses buffered .Tn I/O , users may specify the size of buffers; values of zero choose suitable defaults. .Pp .It Xo .Ft "SVCXPRT *" .Xc .It Xo .Fn svcunixfd_create "int fd" "u_int sendsize" "u_int recvsize" .Xc .Pp Create a service on top of any open descriptor. The .Fa sendsize and .Fa recvsize arguments indicate sizes for the send and receive buffers. If they are zero, a reasonable default is chosen. .Pp .It Xo .Ft "SVCXPRT *" .Xc .It Xo .Fn svcfd_create "int fd" "u_int sendsize" "u_int recvsize" .Xc .Pp Create a service on top of any open descriptor. Typically, this descriptor is a connected socket for a stream protocol such as .Tn TCP . The .Fa sendsize and .Fa recvsize arguments indicate sizes for the send and receive buffers. If they are zero, a reasonable default is chosen. .Pp .It Xo .Ft "SVCXPRT *" .Xc .It Xo .Fn svcudp_bufcreate "int sock" "u_int sendsize" "u_int recvsize" .Xc .Pp This routine creates a .Tn UDP/IP Ns \-based .Tn RPC service transport, to which it returns a pointer. The transport is associated with the socket .Fa sock , which may be .Dv RPC_ANYSOCK , in which case a new socket is created. If the socket is not bound to a local .Tn UDP port, then this routine binds it to an arbitrary port. Upon completion, .Fa xprt\->xp_fd is the transport's socket descriptor, and .Fa xprt\->xp_port is the transport's port number. This routine returns .Dv NULL if it fails. .Pp This allows the user to specify the maximum packet size for sending and receiving .Tn UDP Ns \-based .Tn RPC messages. .Pp .It Xo .Ft bool_t .Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar" .Xc .Pp Used for encoding .Tn RPC reply messages. This routine is useful for users who wish to generate .Tn RPC Ns \-style messages without using the .Tn RPC package. .Pp .It Xo .Ft bool_t .Fn xdr_authunix_parms "XDR *xdrs" "struct authunix_parms *aupp" .Xc .Pp Used for describing .Ux credentials. This routine is useful for users who wish to generate these credentials without using the .Tn RPC authentication package. .Pp .It Xo .Ft void .Xc .It Xo .Ft bool_t .Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr" .Xc .Pp Used for describing .Tn RPC call header messages. This routine is useful for users who wish to generate .Tn RPC Ns \-style messages without using the .Tn RPC package. .Pp .It Xo .Ft bool_t .Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg" .Xc .Pp Used for describing .Tn RPC call messages. This routine is useful for users who wish to generate .Tn RPC Ns \-style messages without using the .Tn RPC package. .Pp .It Xo .Ft bool_t .Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap" .Xc .Pp Used for describing .Tn RPC authentication information messages. This routine is useful for users who wish to generate .Tn RPC Ns \-style messages without using the .Tn RPC package. .Pp .It Xo .Vt struct pmap ; .Xc .It Xo .Ft bool_t .Fn xdr_pmap "XDR *xdrs" "struct pmap *regs" .Xc .Pp Used for describing arguments to various .Xr rpcbind 8 procedures, externally. This routine is useful for users who wish to generate these arguments without using the .Fn pmap_* interface. .Pp .It Xo .Ft bool_t .Fn xdr_pmaplist "XDR *xdrs" "struct pmaplist **rp" .Xc .Pp Used for describing a list of port mappings, externally. This routine is useful for users who wish to generate these arguments without using the .Fn pmap_* interface. .Pp .It Xo .Ft bool_t .Fn xdr_rejected_reply "XDR *xdrs" "struct rejected_reply *rr" .Xc .Pp Used for describing .Tn RPC reply messages. This routine is useful for users who wish to generate .Tn RPC Ns \-style messages without using the .Tn RPC package. .Pp .It Xo .Ft bool_t .Fn xdr_replymsg "XDR *xdrs" "struct rpc_msg *rmsg" .Xc .Pp Used for describing .Tn RPC reply messages. This routine is useful for users who wish to generate .Tn RPC style messages without using the .Tn RPC package. .Pp .It Xo .Ft void .Xc .It Xo .Fn xprt_register "SVCXPRT *xprt" .Xc .Pp After .Tn RPC service transport handles are created, they should register themselves with the .Tn RPC service package. This routine modifies the global variable .Va svc_fds . Service implementors usually do not need this routine. .Pp .It Xo .Ft void .Xc .It Xo .Fn xprt_unregister "SVCXPRT *xprt" .Xc .Pp Before an .Tn RPC service transport handle is destroyed, it should unregister itself with the .Tn RPC service package. This routine modifies the global variable .Va svc_fds . Service implementors usually do not need this routine. .El .Sh SEE ALSO .Xr rpc_secure 3 , .Xr xdr 3 .Rs .%T "Remote Procedure Calls: Protocol Specification" .Re .Rs .%T "Remote Procedure Call Programming Guide" .Re .Rs .%T "rpcgen Programming Guide" .Re .Rs .%T "RPC: Remote Procedure Call Protocol Specification" .%O RFC1050 .%Q "Sun Microsystems, Inc., USC-ISI" .Re ntirpc-1.3.1/man/rpc_svc_calls.3t000066400000000000000000000152321261345040100166520ustar00rootroot00000000000000.\" @(#)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.1 2000/06/02 23:11:13 fvdl Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpc_svc_calls.3,v 1.8 2003/09/08 19:57:15 ru 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 cmsgcred *" .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 "SVCXPRT *xprt" "xdrproc_t outproc" "char *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 .Vt SVCXPRT data structure. .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 .Va 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 .Xr rpc_svc_create 3 functions, or using .Fn xprt_register . The .Fn svc_exit function has global scope and ends all RPC server activity. .It Xo .Vt fd_set Va svc_fdset .Xc A global variable reflecting the RPC server's read file descriptor bit mask; it is suitable as an argument 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. .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. .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 .Fa in argument 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. .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; .Fa pollretval is the return value from .Xr poll 2 and .Fa pfdp is the array of .Vt 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. .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. .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 . .It Fn __svc_getcallercreds .Em Warning : this macro is specific to .Fx and thus not portable. This macro returns a pointer to a .Vt cmsgcred 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 Xo .Vt struct pollfd Va svc_pollset[FD_SETSIZE] ; .Xc .Va svc_pollset is an array of .Vt pollfd structures derived from .Va svc_fdset[] . It is suitable as an argument 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. .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. .It Fn svc_sendreply Called by an RPC service's dispatch routine to send the results of a remote procedure call. The .Fa xprt argument 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 select 2 , .Xr rpc 3 , .Xr rpc_svc_create 3 , .Xr rpc_svc_err 3 , .Xr rpc_svc_reg 3 ntirpc-1.3.1/man/rpc_svc_create.3t000066400000000000000000000201531261345040100170150ustar00rootroot00000000000000.\" @(#)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. .\" $FreeBSD: src/lib/libc/rpc/rpc_svc_create.3,v 1.7 2003/09/08 19:57:15 ru 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 "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 "void (*dispatch)(struct svc_req *, 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 .Vt SVCXPRT data structure. .Bl -tag -width XXXXX .It Fn svc_control A function to change or retrieve various information about a service object. The .Fa req argument 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. The .Fa info argument 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. .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. The .Fa info argument 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 .It Fn svc_create The .Fn svc_create function creates server handles for all the transports belonging to the class .Fa nettype . The .Fa nettype argument 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 .Qq netpath . .Pp The .Fn svc_create function registers itself with the rpcbind service (see .Xr rpcbind 8 ) . The .Fa dispatch function 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. .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. .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. The .Fa sendsz and .Fa recvsz arguments are arguments 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 . .Pp 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. .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. The .Fa sendsz and .Fa recvsz arguments 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. .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. .Pp Note: .Fn svc_run should not be called when the raw interface is being used. .It Fn svc_tli_create This routine creates an RPC server handle, and returns a pointer to it. The .Fa fildes argument 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 not .Dv 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 arguments .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. .It Fn svc_tp_create The .Fn svc_tp_create function creates a server handle for the network specified by .Fa netconf , and registers itself with the rpcbind service. The .Fa dispatch function is called when there is a remote procedure call for the given .Fa prognum and .Fa versnum ; this requires calling .Fn svc_run . The .Fn svc_tp_create function returns the service handle if it succeeds, otherwise a .Dv NULL is returned and an error message is logged. .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 arguments .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 ntirpc-1.3.1/man/rpc_svc_err.3t000066400000000000000000000053301261345040100163420ustar00rootroot00000000000000.\" @(#)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.1 2000/06/02 23:11:14 fvdl Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpc_svc_err.3,v 1.4 2002/12/19 09:40:23 ru 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 "SVCXPRT *xprt" "enum auth_stat why" .Ft void .Fn svcerr_decode "SVCXPRT *xprt" .Ft void .Fn svcerr_noproc "SVCXPRT *xprt" .Ft void .Fn svcerr_noprog "SVCXPRT *xprt" .Ft void .Fn svcerr_progvers "SVCXPRT *xprt" "rpcvers_t low_vers" "rpcvers_t high_vers" .Ft void .Fn svcerr_systemerr "SVCXPRT *xprt" .Ft void .Fn svcerr_weakauth "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. .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. .It Fn svcerr_decode Called by a service dispatch routine that cannot successfully decode the remote arguments (see .Fn svc_getargs in .Xr rpc_svc_reg 3 ) . .It Fn svcerr_noproc Called by a service dispatch routine that does not implement the procedure number that the caller requests. .It Fn svcerr_noprog Called when the desired program is not registered with the RPC package. Service implementors usually do not need this routine. .It Fn svcerr_progvers Called when the desired version of a program is not registered with the RPC package. The .Fa low_vers argument is the lowest version number, and .Fa high_vers is the highest version number. Service implementors usually do not need this routine. .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. .It Fn svcerr_weakauth Called by a service dispatch routine that refuses to perform a remote procedure call due to insufficient (but correct) authentication arguments. 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 ntirpc-1.3.1/man/rpc_svc_reg.3t000066400000000000000000000111021261345040100163210ustar00rootroot00000000000000.\" @(#)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.1 2000/06/02 23:11:14 fvdl Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpc_svc_reg.3,v 1.5 2002/12/19 09:40:23 ru 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 int .Fn rpc_reg "rpcprog_t prognum" "rpcvers_t versnum" "rpcproc_t procnum" "char *(*procname)()" "xdrproc_t inproc" "xdrproc_t outproc" "char *nettype" .Ft bool_t .Fn svc_reg "SVCXPRT *xprt" "const rpcprog_t prognum" "const rpcvers_t versnum" "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 "int cred_flavor" "enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)" .Ft void .Fn xprt_register "SVCXPRT *xprt" .Ft void .Fn xprt_unregister "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. .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 argument(s); .Fa procname should return a pointer to its static result(s); .Fa inproc is the XDR function used to decode the arguments 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. .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 .Bq Fa prognum , versnum , netconf->nc_netid to .Fa xprt->xp_ltaddr is established with the local rpcbind service. .Pp The .Fn svc_reg routine returns 1 if it succeeds, and 0 otherwise. .It Fn svc_unreg Remove from the rpcbind service, all mappings of the triple .Bq Fa prognum , versnum , No all-transports to network address and all mappings within the RPC service package of the double .Bq Fa prognum , versnum to dispatch routines. .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 arguments, .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. .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. .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 rpcbind 3 , .Xr rpc_svc_calls 3 , .Xr rpc_svc_create 3 , .Xr rpc_svc_err 3 , .Xr rpcbind 8 ntirpc-1.3.1/man/rpc_xdr.3t000066400000000000000000000054251261345040100155010ustar00rootroot00000000000000.\" @(#)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. .\" $FreeBSD: src/lib/libc/rpc/rpc_xdr.3,v 1.3 2001/10/03 16:47:56 bde 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" "struct accepted_reply *ar" .Ft bool_t .Fn xdr_authsys_parms "XDR *xdrs" "struct authsys_parms *aupp" .Ft bool_t .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" "struct rejected_reply *rr" .Ft bool_t .Fn xdr_replymsg "XDR *xdrs" "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 .Dv TRUE if they succeed, .Dv FALSE otherwise. .Sh Routines See .Xr rpc 3 for the definition of the .Vt XDR data structure. .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. .It Fn xdr_authsys_parms Used for describing .Ux operating system credentials. It includes machine-name, uid, gid list, etc. .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. .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. .It Fn xdr_opaque_auth Used for describing RPC opaque authentication information messages. .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. .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 ntirpc-1.3.1/man/rpcbind.3t000066400000000000000000000114221261345040100154530ustar00rootroot00000000000000.\" @(#)rpcbind.3n 1.25 93/05/07 SMI; from SVr4 .\" Copyright 1989 AT&T .\" Copyright (c) 1988 Sun Microsystem's, Inc. - All Right's Reserved. .\" $NetBSD: rpcbind.3,v 1.2 2000/06/03 18:47:28 fvdl Exp $ .\" $FreeBSD: src/lib/libc/rpc/rpcbind.3,v 1.5 2002/12/19 09:40:23 ru Exp $ .Dd May 7, 1993 .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 "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 caddr_t in" "const xdrproc_t outproc" "const caddr_t out" "const struct timeval tout, const 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. .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 . The .Fa svcaddr argument 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. .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. The .Fn rpcb_gettime function can be used to synchronize the time between the client and the remote server. .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 .Fa svcaddr argument 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 arguments). .Pp This procedure should normally be used for a .Dq 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. .It Fn rpcb_set An interface to the rpcbind service, which establishes a mapping between the triple .Bq Fa prognum , versnum , netconf->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. .It Fn rpcb_unset An interface to the rpcbind service, which destroys the mapping between the triple .Bq Fa prognum , versnum , netconf->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 .Bq Fa prognum , versnum , No 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 ntirpc-1.3.1/ntirpc/000077500000000000000000000000001261345040100143065ustar00rootroot00000000000000ntirpc-1.3.1/ntirpc/fpmath.h000066400000000000000000000041271261345040100157420ustar00rootroot00000000000000/*- * Copyright (c) 2003 Mike Barcroft * Copyright (c) 2002 David Schultz * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD: src/lib/libc/include/fpmath.h,v 1.1 2003/02/08 20:37:53 mike Exp $ */ #include #include "_fpmath.h" union IEEEf2bits { float f; struct { #if _BYTE_ORDER == _LITTLE_ENDIAN unsigned int man:23; unsigned int exp:8; unsigned int sign:1; #else /* _BIG_ENDIAN */ unsigned int sign:1; unsigned int exp:8; unsigned int man:23; #endif } bits; }; union IEEEd2bits { double d; struct { #if _BYTE_ORDER == _LITTLE_ENDIAN unsigned int manl:32; unsigned int manh:20; unsigned int exp:11; unsigned int sign:1; #else /* _BIG_ENDIAN */ unsigned int sign:1; unsigned int exp:11; unsigned int manh:20; unsigned int manl:32; #endif } bits; }; ntirpc-1.3.1/ntirpc/getpeereid.h000066400000000000000000000007341261345040100166000ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * getpeereid.c * get peer userid for UNIX-domain socket connection * * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group * * * IDENTIFICATION * src/port/getpeereid.c * *------------------------------------------------------------------------- */ #ifndef GETPEERID_H #define GETPEERID_H int getpeereid(int s, uid_t *euid, gid_t *egid); #endif /* GETPEERID_H */ ntirpc-1.3.1/ntirpc/intrinsic.h000066400000000000000000000031101261345040100164540ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RPC_INTRINSIC_H #define _RPC_INTRINSIC_H #if (__GNUC__ >= 3) #ifndef likely #define likely(x) __builtin_expect(!!(x), 1) #define unlikely(x) __builtin_expect(!!(x), 0) #endif #else #define likely(x) (x) #define unlikely(x) (x) #endif #endif /* _RPC_INTRINSIC_H */ ntirpc-1.3.1/ntirpc/libc_private.h000066400000000000000000000135071261345040100171300ustar00rootroot00000000000000/* * Copyright (c) 1998 John Birrell . * 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 author nor the names of any co-contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL 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 REGENTS 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. * * $FreeBSD: src/lib/libc/include/libc_private.h,v 1.17.2.2.2.1 2009/04/15 03:14:26 kensmith Exp $ * * Private definitions for libc, libc_r and libpthread. * */ #ifndef _LIBC_PRIVATE_H_ #define _LIBC_PRIVATE_H_ /* * This global flag is non-zero when a process has created one * or more threads. It is used to avoid calling locking functions * when they are not required. */ extern int __isthreaded; /* * File lock contention is difficult to diagnose without knowing * where locks were set. Allow a debug library to be built which * records the source file and line number of each lock call. */ #ifdef _FLOCK_DEBUG #define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__) #else #define _FLOCKFILE(x) _flockfile(x) #endif /* * Macros for locking and unlocking FILEs. These test if the * process is threaded to avoid locking when not required. */ #define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp) #define FUNLOCKFILE(fp) if (__isthreaded) _funlockfile(fp) /* * Indexes into the pthread jump table. * * Warning! If you change this type, you must also change the threads * libraries that reference it (libc_r, libpthread). */ typedef enum { PJT_ATFORK, PJT_ATTR_DESTROY, PJT_ATTR_GETDETACHSTATE, PJT_ATTR_GETGUARDSIZE, PJT_ATTR_GETINHERITSCHED, PJT_ATTR_GETSCHEDPARAM, PJT_ATTR_GETSCHEDPOLICY, PJT_ATTR_GETSCOPE, PJT_ATTR_GETSTACKADDR, PJT_ATTR_GETSTACKSIZE, PJT_ATTR_INIT, PJT_ATTR_SETDETACHSTATE, PJT_ATTR_SETGUARDSIZE, PJT_ATTR_SETINHERITSCHED, PJT_ATTR_SETSCHEDPARAM, PJT_ATTR_SETSCHEDPOLICY, PJT_ATTR_SETSCOPE, PJT_ATTR_SETSTACKADDR, PJT_ATTR_SETSTACKSIZE, PJT_CANCEL, PJT_CLEANUP_POP, PJT_CLEANUP_PUSH, PJT_COND_BROADCAST, PJT_COND_DESTROY, PJT_COND_INIT, PJT_COND_SIGNAL, PJT_COND_TIMEDWAIT, PJT_COND_WAIT, PJT_DETACH, PJT_EQUAL, PJT_EXIT, PJT_GETSPECIFIC, PJT_JOIN, PJT_KEY_CREATE, PJT_KEY_DELETE, PJT_KILL, PJT_MAIN_NP, PJT_MUTEXATTR_DESTROY, PJT_MUTEXATTR_INIT, PJT_MUTEXATTR_SETTYPE, PJT_MUTEX_DESTROY, PJT_MUTEX_INIT, PJT_MUTEX_LOCK, PJT_MUTEX_TRYLOCK, PJT_MUTEX_UNLOCK, PJT_ONCE, PJT_RWLOCK_DESTROY, PJT_RWLOCK_INIT, PJT_RWLOCK_RDLOCK, PJT_RWLOCK_TRYRDLOCK, PJT_RWLOCK_TRYWRLOCK, PJT_RWLOCK_UNLOCK, PJT_RWLOCK_WRLOCK, PJT_SELF, PJT_SETCANCELSTATE, PJT_SETCANCELTYPE, PJT_SETSPECIFIC, PJT_SIGMASK, PJT_TESTCANCEL, PJT_MAX } pjt_index_t; typedef int (*pthread_func_t)(void); typedef pthread_func_t pthread_func_entry_t[2]; extern pthread_func_entry_t __thr_jtable[]; /* * yplib internal interfaces */ #ifdef YP int _yp_check(char **); #endif /* * Initialise TLS for static programs */ void _init_tls(void); /* * Set the TLS thread pointer */ void _set_tp(void *tp); /* * This is a pointer in the C run-time startup code. It is used * by getprogname() and setprogname(). */ extern const char *__progname; /* * This function is used by the threading libraries to notify malloc that a * thread is exiting. */ void _malloc_thread_cleanup(void); /* * These functions are used by the threading libraries in order to protect * malloc across fork(). */ void _malloc_prefork(void); void _malloc_postfork(void); /* * Function to clean up streams, called from abort() and exit(). */ extern void (*__cleanup)(void); /* * Get kern.osreldate to detect ABI revisions. Explicitly * ignores value of $OSVERSION and caches result. Prototypes * for the wrapped "new" pad-less syscalls are here for now. */ extern int __getosreldate(void); #include /* Without pad */ extern __off_t __sys_lseek(int, __off_t, int); extern int __sys_ftruncate(int, __off_t); extern int __sys_truncate(const char *, __off_t); extern __ssize_t __sys_pread(int, void *, __size_t, __off_t); extern __ssize_t __sys_pwrite(int, const void *, __size_t, __off_t); extern void * __sys_mmap(void *, __size_t, int, int, int, __off_t); /* With pad */ extern __off_t __sys_freebsd6_lseek(int, int, __off_t, int); extern int __sys_freebsd6_ftruncate(int, int, __off_t); extern int __sys_freebsd6_truncate(const char *, int, __off_t); extern __ssize_t __sys_freebsd6_pread(int, void *, __size_t, int, __off_t); extern __ssize_t __sys_freebsd6_pwrite(int, const void *, __size_t, int, __off_t); extern void * __sys_freebsd6_mmap(void *, __size_t, int, int, int, int, __off_t); /* Without back-compat translation */ extern int __sys_fcntl(int, int, ...); #endif /* _LIBC_PRIVATE_H_ */ ntirpc-1.3.1/ntirpc/misc/000077500000000000000000000000001261345040100152415ustar00rootroot00000000000000ntirpc-1.3.1/ntirpc/misc/abstract_atomic.h000066400000000000000000001662271261345040100205670ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /* Permission to relicense his contributions under the above license terms * was given by Frank S. Filz, in #ganesha (freenode), on 08/08/2012. */ /** * @file abstract_atomic.h * @author Adam C. Emerson * @author Frank S. Filz * @brief Shim for compiler or library supplied atomic operations * * This file provides inline functions that provide atomic operations * appropriate to the compiler being used. (Someone can add support * for an appropriate library later on.) * * The types functions are provided for: * * ptrdiff_t (fetch and store only) * time_t (fetch and store only) * void* (fetch and store only) * uintptr_t (fetch and store only) * int64_t * uint64_t * int32_t * uint21_t * int16_t * uint16_t * int8_t * uint8_t * size_t * * The functions provided are (using int64_t for example): * * int64_t atomic_add_int64_t(int64_t *augend, int64_t addend) * int64_t atomic_inc_int64_t(int64_t *var) * int64_t atomic_sub_int64_t(int64_t *minuend, int64_t subtrahend) * int64_t atomic_dec_int64_t(int64_t *var) * int64_t atomic_postadd_int64_t(int64_t *augend, int64_t addend) * int64_t atomic_postinc_int64_t(int64_t *var) * int64_t atomic_postsub_int64_t(int64_t *minuend, int64_t subtrahend) * int64_t atomic_postdec_int64_t(int64_t *var) * int64_t atomic_fetch_int64_t(int64_t *var) * void atomic_store_int64_t(int64_t *var, int64_t val) * * The following bit mask operations are provided for * uint64_t, uint32_t, uint_16t, and uint8_t: * * uint64_t atomic_clear_uint64_t_bits(uint64_t *var, uint64_t bits) * uint64_t atomic_set_uint64_t_bits(uint64_t *var, uint64_t bits) * uint64_t atomic_postclear_uint64_t_bits(uint64_t *var, * uint64_t atomic_postset_uint64_t_bits(uint64_t *var, * */ #ifndef _ABSTRACT_ATOMIC_H #define _ABSTRACT_ATOMIC_H #include #include #include #undef GCC_SYNC_FUNCTIONS #undef GCC_ATOMIC_FUNCTIONS #ifndef __GNUC__ #error Please edit abstract_atomic.h and implement support for \ non-GNU compilers. #else /* __GNUC__ */ #define ATOMIC_GCC_VERSION (__GNUC__ * 10000 \ + __GNUC_MINOR__ * 100 \ + __GNUC_PATCHLEVEL__) #if ((ATOMIC_GCC_VERSION) >= 40700) #define GCC_ATOMIC_FUNCTIONS 1 #elif defined(__APPLE__) && defined(__x86_64__) #include "atomic_x86_64.h" #elif ((ATOMIC_GCC_VERSION) >= 40100) #define GCC_SYNC_FUNCTIONS 1 #else #error This verison of GCC does not support atomics. #endif /* Version check */ #endif /* __GNUC__ */ /* * Preaddition, presubtraction, preincrement, predecrement (return the * value after the operation, by analogy with the ++n preincrement * operator.) */ /** * @brief Atomically add to an int64_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int64_t atomic_add_int64_t(int64_t *augend, int64_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int64_t atomic_add_int64_t(int64_t *augend, int64_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment an int64_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline int64_t atomic_inc_int64_t(int64_t *var) { return atomic_add_int64_t(var, 1); } /** * @brief Atomically subtract from an int64_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int64_t atomic_sub_int64_t(int64_t *minuend, int64_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int64_t atomic_sub_int64_t(int64_t *minuend, int64_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int64_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify */ static inline int64_t atomic_dec_int64_t(int64_t *var) { return atomic_sub_int64_t(var, 1); } /** * @brief Atomically add to an int64_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_add_uint64_t(uint64_t *augend, uint64_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_add_uint64_t(uint64_t *augend, uint64_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment a uint64_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline uint64_t atomic_inc_uint64_t(uint64_t *var) { return atomic_add_uint64_t(var, 1); } /** * @brief Atomically subtract from a uint64_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_sub_uint64_t(uint64_t *minuend, uint64_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_sub_uint64_t(uint64_t *minuend, uint64_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement a uint64_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline uint64_t atomic_dec_uint64_t(uint64_t *var) { return atomic_sub_uint64_t(var, 1); } /** * @brief Atomically add to an int32_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int32_t atomic_add_int32_t(int32_t *augend, int32_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int32_t atomic_add_int32_t(int32_t *augend, int32_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment an int32_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline int32_t atomic_inc_int32_t(int32_t *var) { return atomic_add_int32_t(var, 1); } /** * @brief Atomically subtract from an int32_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int32_t atomic_sub_int32_t(int32_t *minuend, int32_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int32_t atomic_sub_int32_t(int32_t *minuend, int32_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int32_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline int32_t atomic_dec_int32_t(int32_t *var) { return atomic_sub_int32_t(var, 1); } /** * @brief Atomically add to a uint32_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_add_uint32_t(uint32_t *augend, uint32_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_add_uint32_t(uint32_t *augend, uint32_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment a uint32_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline uint32_t atomic_inc_uint32_t(uint32_t *var) { return atomic_add_uint32_t(var, 1); } /** * @brief Atomically subtract from a uint32_t * * This function atomically subtracts from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_sub_uint32_t(uint32_t *var, uint32_t sub) { return __atomic_sub_fetch(var, sub, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_sub_uint32_t(uint32_t *var, uint32_t sub) { return __sync_sub_and_fetch(var, sub); } #endif /** * @brief Atomically decrement a uint32_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline uint32_t atomic_dec_uint32_t(uint32_t *var) { return atomic_sub_uint32_t(var, 1); } /** * @brief Atomically add to an int16_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int16_t atomic_add_int16_t(int16_t *augend, int16_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int16_t atomic_add_int16_t(int16_t *augend, int16_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment an int16_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline int16_t atomic_inc_int16_t(int16_t *var) { return atomic_add_int16_t(var, 1); } /** * @brief Atomically subtract from an int16_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int16_t atomic_sub_int16_t(int16_t *minuend, int16_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int16_t atomic_sub_int16_t(int16_t *minuend, int16_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int16_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline int16_t atomic_dec_int16_t(int16_t *var) { return atomic_sub_int16_t(var, 1); } /** * @brief Atomically add to a uint16_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_add_uint16_t(uint16_t *augend, uint16_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_add_uint16_t(uint16_t *augend, uint16_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment a uint16_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline uint16_t atomic_inc_uint16_t(uint16_t *var) { return atomic_add_uint16_t(var, 1); } /** * @brief Atomically subtract from a uint16_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_sub_uint16_t(uint16_t *minuend, uint16_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_sub_uint16_t(uint16_t *minuend, uint16_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement a uint16_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline uint16_t atomic_dec_uint16_t(uint16_t *var) { return atomic_sub_uint16_t(var, 1); } /** * @brief Atomically add to an int8_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int8_t atomic_add_int8_t(int8_t *augend, int8_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int8_t atomic_add_int8_t(int8_t *augend, int8_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment an int8_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline int8_t atomic_inc_int8_t(int8_t *var) { return atomic_add_int8_t(var, 1); } /** * @brief Atomically subtract from an int8_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int8_t atomic_sub_int8_t(int8_t *minuend, int8_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int8_t atomic_sub_int8_t(int8_t *minuend, int8_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int8_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline int8_t atomic_dec_int8_t(int8_t *var) { return atomic_sub_int8_t(var, 1); } /** * @brief Atomically add to a uint8_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_add_uint8_t(uint8_t *augend, int8_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_add_uint8_t(uint8_t *augend, int8_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment a uint8_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline uint8_t atomic_inc_uint8_t(uint8_t *var) { return atomic_add_uint8_t(var, 1); } /** * @brief Atomically subtract from a uint8_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_sub_uint8_t(uint8_t *minuend, uint8_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_sub_uint8_t(uint8_t *minuend, uint8_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement a uint8_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline uint8_t atomic_dec_uint8_t(uint8_t *var) { return atomic_sub_uint8_t(var, 1); } /** * @brief Atomically add to a size_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value after addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline size_t atomic_add_size_t(size_t *augend, size_t addend) { return __atomic_add_fetch(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline size_t atomic_add_size_t(size_t *augend, size_t addend) { return __sync_add_and_fetch(augend, addend); } #endif /** * @brief Atomically increment a size_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after increment. */ static inline size_t atomic_inc_size_t(size_t *var) { return atomic_add_size_t(var, 1); } /** * @brief Atomically subtract from a size_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value after subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline size_t atomic_sub_size_t(size_t *minuend, size_t subtrahend) { return __atomic_sub_fetch(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline size_t atomic_sub_size_t(size_t *minuend, size_t subtrahend) { return __sync_sub_and_fetch(minuend, subtrahend); } #endif /** * @brief Atomically decrement a size_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value after decrement. */ static inline size_t atomic_dec_size_t(size_t *var) { return atomic_sub_size_t(var, 1); } /* * Postaddition, postsubtraction, postincrement, postdecrement (return the * value before the operation, by analogy with the n++ postincrement * operator.) */ /** * @brief Atomically add to an int64_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int64_t atomic_postadd_int64_t(int64_t *augend, int64_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int64_t atomic_postadd_int64_t(int64_t *augend, int64_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment an int64_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline int64_t atomic_postinc_int64_t(int64_t *var) { return atomic_postadd_int64_t(var, 1); } /** * @brief Atomically subtract from an int64_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int64_t atomic_postsub_int64_t(int64_t *minuend, int64_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int64_t atomic_postsub_int64_t(int64_t *minuend, int64_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int64_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify */ static inline int64_t atomic_postdec_int64_t(int64_t *var) { return atomic_postsub_int64_t(var, 1); } /** * @brief Atomically add to an int64_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_postadd_uint64_t(uint64_t *augend, uint64_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_postadd_uint64_t(uint64_t *augend, uint64_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment a uint64_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline uint64_t atomic_postinc_uint64_t(uint64_t *var) { return atomic_postadd_uint64_t(var, 1); } /** * @brief Atomically subtract from a uint64_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_postsub_uint64_t(uint64_t *minuend, uint64_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_postsub_uint64_t(uint64_t *minuend, uint64_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement a uint64_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline uint64_t atomic_postdec_uint64_t(uint64_t *var) { return atomic_postsub_uint64_t(var, 1); } /** * @brief Atomically add to an int32_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int32_t atomic_postadd_int32_t(int32_t *augend, int32_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int32_t atomic_postadd_int32_t(int32_t *augend, int32_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment an int32_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline int32_t atomic_postinc_int32_t(int32_t *var) { return atomic_postadd_int32_t(var, 1); } /** * @brief Atomically subtract from an int32_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int32_t atomic_postsub_int32_t(int32_t *minuend, int32_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int32_t atomic_postsub_int32_t(int32_t *minuend, int32_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int32_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline int32_t atomic_postdec_int32_t(int32_t *var) { return atomic_postsub_int32_t(var, 1); } /** * @brief Atomically add to a uint32_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_postadd_uint32_t(uint32_t *augend, uint32_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_postadd_uint32_t(uint32_t *augend, uint32_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment a uint32_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline uint32_t atomic_postinc_uint32_t(uint32_t *var) { return atomic_postadd_uint32_t(var, 1); } /** * @brief Atomically subtract from a uint32_t * * This function atomically subtracts from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_postsub_uint32_t(uint32_t *var, uint32_t sub) { return __atomic_fetch_sub(var, sub, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_postsub_uint32_t(uint32_t *var, uint32_t sub) { return __sync_fetch_and_sub(var, sub); } #endif /** * @brief Atomically decrement a uint32_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline uint32_t atomic_postdec_uint32_t(uint32_t *var) { return atomic_postsub_uint32_t(var, 1); } /** * @brief Atomically add to an int16_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int16_t atomic_postadd_int16_t(int16_t *augend, int16_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int16_t atomic_postadd_int16_t(int16_t *augend, int16_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment an int16_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline int16_t atomic_postinc_int16_t(int16_t *var) { return atomic_postadd_int16_t(var, 1); } /** * @brief Atomically subtract from an int16_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int16_t atomic_postsub_int16_t(int16_t *minuend, int16_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int16_t atomic_postsub_int16_t(int16_t *minuend, int16_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int16_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline int16_t atomic_postdec_int16_t(int16_t *var) { return atomic_postsub_int16_t(var, 1); } /** * @brief Atomically add to a uint16_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_postadd_uint16_t(uint16_t *augend, uint16_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_postadd_uint16_t(uint16_t *augend, uint16_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment a uint16_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline uint16_t atomic_postinc_uint16_t(uint16_t *var) { return atomic_postadd_uint16_t(var, 1); } /** * @brief Atomically subtract from a uint16_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_postsub_uint16_t(uint16_t *minuend, uint16_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_postsub_uint16_t(uint16_t *minuend, uint16_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement a uint16_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline uint16_t atomic_postdec_uint16_t(uint16_t *var) { return atomic_postsub_uint16_t(var, 1); } /** * @brief Atomically add to an int8_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int8_t atomic_postadd_int8_t(int8_t *augend, int8_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int8_t atomic_postadd_int8_t(int8_t *augend, int8_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment an int8_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline int8_t atomic_postinc_int8_t(int8_t *var) { return atomic_postadd_int8_t(var, 1); } /** * @brief Atomically subtract from an int8_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int8_t atomic_postsub_int8_t(int8_t *minuend, int8_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int8_t atomic_postsub_int8_t(int8_t *minuend, int8_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement an int8_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline int8_t atomic_postdec_int8_t(int8_t *var) { return atomic_postsub_int8_t(var, 1); } /** * @brief Atomically add to a uint8_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_postadd_uint8_t(uint8_t *augend, uint8_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_postadd_uint8_t(uint8_t *augend, uint8_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment a uint8_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline uint8_t atomic_postinc_uint8_t(uint8_t *var) { return atomic_postadd_uint8_t(var, 1); } /** * @brief Atomically subtract from a uint8_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_postsub_uint8_t(uint8_t *minuend, uint8_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_postsub_uint8_t(uint8_t *minuend, uint8_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement a uint8_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline uint8_t atomic_postdec_uint8_t(uint8_t *var) { return atomic_postsub_uint8_t(var, 1); } /** * @brief Atomically add to a size_t * * This function atomically adds to the supplied value. * * @param[in,out] augend Number to be added to * @param[in] addend Number to add * * @return The value before addition. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline size_t atomic_postadd_size_t(size_t *augend, size_t addend) { return __atomic_fetch_add(augend, addend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline size_t atomic_postadd_size_t(size_t *augend, size_t addend) { return __sync_fetch_and_add(augend, addend); } #endif /** * @brief Atomically increment a size_t * * This function atomically adds 1 to the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before increment. */ static inline size_t atomic_postinc_size_t(size_t *var) { return atomic_postadd_size_t(var, 1); } /** * @brief Atomically subtract from a size_t * * This function atomically subtracts from the supplied value. * * @param[in,out] minuend Number to be subtracted from * @param[in] subtrahend Number to subtract * * @return The value before subtraction. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline size_t atomic_postsub_size_t(size_t *minuend, size_t subtrahend) { return __atomic_fetch_sub(minuend, subtrahend, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline size_t atomic_postsub_size_t(size_t *minuend, size_t subtrahend) { return __sync_fetch_and_sub(minuend, subtrahend); } #endif /** * @brief Atomically decrement a size_t * * This function atomically subtracts 1 from the supplied value. * * @param[in,out] var Pointer to the variable to modify * * @return The value before decrement. */ static inline size_t atomic_postdec_size_t(size_t *var) { return atomic_postsub_size_t(var, 1); } /* * Preclear and preset bits (return the value after the operation, by * analogy with the ++n preincrement operator.) */ /** * @brief Atomically clear bits in a uint64_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value after clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_clear_uint64_t_bits(uint64_t *var, uint64_t bits) { return __atomic_and_fetch(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_clear_uint64_t_bits(uint64_t *var, uint64_t bits) { return __sync_and_and_fetch(var, ~bits); } #endif /** * @brief Atomically set bits in a uint64_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value after setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_set_uint64_t_bits(uint64_t *var, uint64_t bits) { return __atomic_or_fetch(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_set_uint64_t_bits(uint64_t *var, uint64_t bits) { return __sync_or_and_fetch(var, bits); } #endif /** * @brief Atomically clear bits in a uint32_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value after clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_clear_uint32_t_bits(uint32_t *var, uint32_t bits) { return __atomic_and_fetch(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_clear_uint32_t_bits(uint32_t *var, uint32_t bits) { return __sync_and_and_fetch(var, ~bits); } #endif /** * @brief Atomically set bits in a uint32_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value after setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_set_uint32_t_bits(uint32_t *var, uint32_t bits) { return __atomic_or_fetch(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_set_uint32_t_bits(uint32_t *var, uint32_t bits) { return __sync_or_and_fetch(var, bits); } #endif /** * @brief Atomically clear bits in a uint16_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value after clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_clear_uint16_t_bits(uint16_t *var, uint16_t bits) { return __atomic_and_fetch(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_clear_uint16_t_bits(uint16_t *var, uint16_t bits) { return __sync_and_and_fetch(var, ~bits); } #endif /** * @brief Atomically set bits in a uint16_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value after setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_set_uint16_t_bits(uint16_t *var, uint16_t bits) { return __atomic_or_fetch(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_set_uint16_t_bits(uint16_t *var, uint16_t bits) { return __sync_or_and_fetch(var, bits); } #endif /** * @brief Atomically clear bits in a uint8_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value after clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_clear_uint8_t_bits(uint8_t *var, uint8_t bits) { return __atomic_and_fetch(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_clear_uint8_t_bits(uint8_t *var, uint8_t bits) { return __sync_and_and_fetch(var, ~bits); } #endif /** * @brief Atomically set bits in a uint8_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value after setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_set_uint8_t_bits(uint8_t *var, uint8_t bits) { return __atomic_or_fetch(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_set_uint8_t_bits(uint8_t *var, uint8_t bits) { return __sync_or_and_fetch(var, bits); } #endif /* * Postclear and postset bits (return the value before the operation, * by analogy with the n++ postincrement operator.) */ /** * @brief Atomically clear bits in a uint64_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value before clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_postclear_uint64_t_bits(uint64_t *var, uint64_t bits) { return __atomic_fetch_and(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_postclear_uint64_t_bits(uint64_t *var, uint64_t bits) { return __sync_fetch_and_and(var, ~bits); } #endif /** * @brief Atomically set bits in a uint64_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value before setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_postset_uint64_t_bits(uint64_t *var, uint64_t bits) { return __atomic_fetch_or(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_postset_uint64_t_bits(uint64_t *var, uint64_t bits) { return __sync_fetch_and_or(var, bits); } #endif /** * @brief Atomically clear bits in a uint32_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value before clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_postclear_uint32_t_bits(uint32_t *var, uint32_t bits) { return __atomic_fetch_and(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_postclear_uint32_t_bits(uint32_t *var, uint32_t bits) { return __sync_fetch_and_and(var, ~bits); } #endif /** * @brief Atomically set bits in a uint32_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value before setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_postset_uint32_t_bits(uint32_t *var, uint32_t bits) { return __atomic_fetch_or(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_postset_uint32_t_bits(uint32_t *var, uint32_t bits) { return __sync_fetch_and_or(var, bits); } #endif /** * @brief Atomically clear bits in a uint16_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value before clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_postclear_uint16_t_bits(uint16_t *var, uint16_t bits) { return __atomic_fetch_and(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_postclear_uint16_t_bits(uint16_t *var, uint16_t bits) { return __sync_fetch_and_and(var, ~bits); } #endif /** * @brief Atomically set bits in a uint16_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value before setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_postset_uint16_t_bits(uint16_t *var, uint16_t bits) { return __atomic_fetch_or(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_postset_uint16_t_bits(uint16_t *var, uint16_t bits) { return __sync_fetch_and_or(var, bits); } #endif /** * @brief Atomically clear bits in a uint8_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to clear * * @return The value before clearing. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_postclear_uint8_t_bits(uint8_t *var, uint8_t bits) { return __atomic_fetch_and(var, ~bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_postclear_uint8_t_bits(uint8_t *var, uint8_t bits) { return __sync_fetch_and_and(var, ~bits); } #endif /** * @brief Atomically set bits in a uint8_t * * This function atomic clears the bits indicated. * * @param[in,out] var Pointer to the value to modify * @param[in] bits Bits to set * * @return The value before setting. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_postset_uint8_t_bits(uint8_t *var, uint8_t bits) { return __atomic_fetch_or(var, bits, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_postset_uint8_t_bits(uint8_t *var, uint8_t bits) { return __sync_fetch_and_or(var, bits); } #endif /* * Fetch and store */ /** * @brief Atomically fetch a size_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline size_t atomic_fetch_size_t(size_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline size_t atomic_fetch_size_t(size_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a size_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_size_t(size_t *var, size_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_size_t(size_t *var, size_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a ptrdiff_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline ptrdiff_t atomic_fetch_ptrdiff_t(ptrdiff_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline ptrdiff_t atomic_fetch_ptrdiff_t(ptrdiff_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a ptrdiff_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_ptrdiff_t(ptrdiff_t *var, ptrdiff_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_ptrdiff_t(ptrdiff_t *var, ptrdiff_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a time_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline time_t atomic_fetch_time_t(time_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline time_t atomic_fetch_time_t(time_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a time_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_time_t(time_t *var, time_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_time_t(time_t *var, time_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a uintptr_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uintptr_t atomic_fetch_uintptr_t(uintptr_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uintptr_t atomic_fetch_uintptr_t(uintptr_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a uintptr_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_uintptr_t(uintptr_t *var, uintptr_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_uintptr_t(uintptr_t *var, uintptr_t val) { (void)__sync_lock_test_and_set(var, 0); } #endif /** * @brief Atomically fetch a void * * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void *atomic_fetch_voidptr(void **var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void *atomic_fetch_voidptr(void **var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a void * * * This function atomically stores the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_voidptr(void **var, void *val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_voidptr(void **var, void *val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch an int64_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int64_t atomic_fetch_int64_t(int64_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int64_t atomic_fetch_int64_t(int64_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store an int64_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_int64_t(int64_t *var, int64_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_int64_t(int64_t *var, int64_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a uint64_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint64_t atomic_fetch_uint64_t(uint64_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint64_t atomic_fetch_uint64_t(uint64_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a uint64_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_uint64_t(uint64_t *var, uint64_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_uint64_t(uint64_t *var, uint64_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch an int32_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int32_t atomic_fetch_int32_t(int32_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int32_t atomic_fetch_int32_t(int32_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store an int32_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_int32_t(int32_t *var, int32_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_int32_t(int32_t *var, int32_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a uint32_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint32_t atomic_fetch_uint32_t(uint32_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint32_t atomic_fetch_uint32_t(uint32_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a uint32_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_uint32_t(uint32_t *var, uint32_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_uint32_t(uint32_t *var, uint32_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch an int16_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int16_t atomic_fetch_int16_t(int16_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int16_t atomic_fetch_int16_t(int16_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store an int16_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_int16_t(int16_t *var, int16_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_int16_t(int16_t *var, int16_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a uint16_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint16_t atomic_fetch_uint16_t(uint16_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint16_t atomic_fetch_uint16_t(uint16_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a uint16_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_uint16_t(uint16_t *var, uint16_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_uint16_t(uint16_t *var, uint16_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a int8_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline int8_t atomic_fetch_int8_t(int8_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline int8_t atomic_fetch_int8_t(int8_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a int8_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_int8_t(int8_t *var, int8_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_int8_t(int8_t *var, int8_t val) { (void)__sync_lock_test_and_set(var, val); } #endif /** * @brief Atomically fetch a uint8_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to fetch * * @return the value pointed to by var. */ #ifdef GCC_ATOMIC_FUNCTIONS static inline uint8_t atomic_fetch_uint8_t(uint8_t *var) { return __atomic_load_n(var, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline uint8_t atomic_fetch_uint8_t(uint8_t *var) { return __sync_fetch_and_add(var, 0); } #endif /** * @brief Atomically store a uint8_t * * This function atomically fetches the value indicated by the * supplied pointer. * * @param[in,out] var Pointer to the variable to modify * @param[in] val The value to store */ #ifdef GCC_ATOMIC_FUNCTIONS static inline void atomic_store_uint8_t(uint8_t *var, uint8_t val) { __atomic_store_n(var, val, __ATOMIC_SEQ_CST); } #elif defined(GCC_SYNC_FUNCTIONS) static inline void atomic_store_uint8_t(uint8_t *var, uint8_t val) { (void)__sync_lock_test_and_set(var, val); } #endif #endif /* !_ABSTRACT_ATOMIC_H */ ntirpc-1.3.1/ntirpc/misc/bsd_epoll.h000066400000000000000000000072331261345040100173620ustar00rootroot00000000000000/* * bsd_epoll.h - Linux epoll.h compatible header * * Signed-off-by: Boaz Harrosh 2009 * * description: * This file makes any code that was compiled with header * on Linux compile-able under FreeBSD and derivatives. It is meant to be * used Together with bsd_epoll.c source file, to also be run-able. * * Example useage: * Any code that was using epoll.h before can now do: * #if defined(__linux__) * # include * #else * # include "bsd_epoll.h" * #endif * Under FreeBSD the Makefile should add the bsd_epoll.c source file * * License: * This header file is not under any license it has been long claimed * and legally proven that Interfaces cannot be copyrighted. * Now since this file only defines interfaces originally put forth * by the Linux Kernel, they are not governed by any License. * In anyway, Linus Trovalds, the originator of the Linux Kernel as * Stated that the Linux Kernel's user-mode APIs are not copyrighted. * * This file was hand crafted by me based on Linux Kernel sources * and GlibC's header epoll.h to be made code compatible with epoll.h * Header on Linux. * * However, the implementation file bsd_epoll.c is copyrighted under * the "New BSD License" so it can be included in the tirpc library * project. * But I fully expect that if you make any fixes/enhancements to * bsd_epoll.c you shall send these changes to me for inclusion * in the next version. (Or I'll hunt your dreams, and you will * not have peace) * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef __BSD_EPOLL_H__ #define __BSD_EPOLL_H__ union epoll_data { int fd; uint32_t u32; uint64_t u64; void *ptr; }; struct epoll_event { uint32_t events; union epoll_data data; }; enum EPOLL_EVENTS { EPOLLIN = 0x001, #define EPOLLIN EPOLLIN EPOLLPRI = 0x002, #define EPOLLPRI EPOLLPRI EPOLLOUT = 0x004, #define EPOLLOUT EPOLLOUT /* EPOLLRDNORM = 0x040, #define EPOLLRDNORM EPOLLRDNORM EPOLLRDBAND = 0x080, #define EPOLLRDBAND EPOLLRDBAND EPOLLWRNORM = 0x100, #define EPOLLWRNORM EPOLLWRNORM EPOLLWRBAND = 0x200, #define EPOLLWRBAND EPOLLWRBAND EPOLLMSG = 0x400, #define EPOLLMSG EPOLLMSG EPOLLERR = 0x008, #define EPOLLERR EPOLLERR EPOLLHUP = 0x010, #define EPOLLHUP EPOLLHUP */ EPOLLRDHUP = 0x2000, #define EPOLLRDHUP EPOLLRDHUP EPOLLONESHOT = (1 << 30), #define EPOLLONESHOT EPOLLONESHOT EPOLLET = (1 << 31) #define EPOLLET EPOLLET }; #define EPOLL_CTL_ADD 1 #define EPOLL_CTL_DEL 2 #define EPOLL_CTL_MOD 3 #define EPOLL_MAX_EVENTS (INT_MAX / sizeof(struct epoll_event)) extern int epoll_create(int size /*unused */); extern int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event); extern int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout); #endif /* __BSD_EPOLL_H__ */ ntirpc-1.3.1/ntirpc/misc/city.h000066400000000000000000000064221261345040100163660ustar00rootroot00000000000000/* city.h - cityhash-c * CityHash on C * Copyright (c) 2011-2012, Alexander Nusov * * - original copyright notice - * Copyright (c) 2011 Google, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * CityHash, by Geoff Pike and Jyrki Alakuijala * * This file provides a few functions for hashing strings. On x86-64 * hardware in 2011, CityHash64() is faster than other high-quality * hash functions, such as Murmur. This is largely due to higher * instruction-level parallelism. CityHash64() and CityHash128() also perform * well on hash-quality tests. * * CityHash128() is optimized for relatively long strings and returns * a 128-bit hash. For strings more than about 2000 bytes it can be * faster than CityHash64(). * * Functions in the CityHash family are not suitable for cryptography. * * WARNING: This code has not been tested on big-endian platforms! * It is known to work well on little-endian platforms that have a small penalty * for unaligned reads, such as current Intel and AMD moderate-to-high-end CPUs. * * By the way, for some hash functions, given strings a and b, the hash * of a+b is easily derived from the hashes of a and b. This property * doesn't hold for any hash functions in this file. */ #ifndef CITY_HASH_H_ #define CITY_HASH_H_ #include #include typedef uint8_t uint8; typedef uint32_t uint32; typedef uint64_t uint64; typedef struct _uint128 uint128; struct _uint128 { uint64 first; uint64 second; }; #define Uint128Low64(x) ((x).first) #define Uint128High64(x) ((x).second) /* Hash function for a byte array. */ uint64 CityHash64(const char *buf, size_t len); /* Hash function for a byte array. For convenience, a 64-bit seed is also * hashed into the result. */ uint64 CityHash64WithSeed(const char *buf, size_t len, uint64 seed); /* Hash function for a byte array. For convenience, two seeds are also * hashed into the result. */ uint64 CityHash64WithSeeds(const char *buf, size_t len, uint64 seed0, uint64 seed1); /* Hash function for a byte array. */ uint128 CityHash128(const char *s, size_t len); /* Hash function for a byte array. For convenience, a 128-bit seed is also * hashed into the result. */ uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed); #endif /* CITY_HASH_H_ */ ntirpc-1.3.1/ntirpc/misc/citycrc.h000066400000000000000000000037211261345040100170550ustar00rootroot00000000000000 /* citycrc.h - cityhash-c * CityHash on C * Copyright (c) 2011-2012, Alexander Nusov * * - original copyright notice - * Copyright (c) 2011 Google, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * CityHash, by Geoff Pike and Jyrki Alakuijala * * This file declares the subset of the CityHash functions that require * _mm_crc32_u64(). See the CityHash README for details. * * Functions in the CityHash family are not suitable for cryptography. */ #ifndef CITY_HASH_CRC_H_ #define CITY_HASH_CRC_H_ #include "city.h" /* Hash function for a byte array. */ uint128 CityHashCrc128(const char *s, size_t len); /* Hash function for a byte array. For convenience, a 128-bit seed is also * hashed into the result. */ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed); /* Hash function for a byte array. Sets result[0] ... result[3]. */ void CityHashCrc256(const char *s, size_t len, uint64 *result); #endif /* CITY_HASH_CRC_H_ */ ntirpc-1.3.1/ntirpc/misc/event.h000066400000000000000000000146331261345040100165420ustar00rootroot00000000000000/*- * Copyright (c) 1999,2000,2001 Jonathan Lemon * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. * * $FreeBSD: src/sys/sys/event.h,v 1.22 2003/02/02 19:39:51 nectar Exp $ */ #ifndef _TIRPC_EVENT_H_ #define _TIRPC_EVENT_H_ #define EVFILT_READ (-1) #define EVFILT_WRITE (-2) #define EVFILT_AIO (-3) /* attached to aio requests */ #define EVFILT_VNODE (-4) /* attached to vnodes */ #define EVFILT_PROC (-5) /* attached to struct proc */ #define EVFILT_SIGNAL (-6) /* attached to struct proc */ #define EVFILT_TIMER (-7) /* timers */ #define EVFILT_NETDEV (-8) /* network devices */ #define EVFILT_SYSCOUNT 8 #define EV_SET(kevp_, a, b, c, d, e, f) do { \ struct kevent *kevp = (kevp_); \ (kevp)->ident = (a); \ (kevp)->filter = (b); \ (kevp)->flags = (c); \ (kevp)->fflags = (d); \ (kevp)->data = (e); \ (kevp)->udata = (f); \ } while (0) #include struct kevent { uintptr_t ident; /* identifier for this event */ short filter; /* filter for event */ u_short flags; u_int fflags; intptr_t data; void *udata; /* opaque user data identifier */ }; /* actions */ #define EV_ADD 0x0001 /* add event to kq (implies enable) */ #define EV_DELETE 0x0002 /* delete event from kq */ #define EV_ENABLE 0x0004 /* enable event */ #define EV_DISABLE 0x0008 /* disable event (not reported) */ /* flags */ #define EV_ONESHOT 0x0010 /* only report one occurrence */ #define EV_CLEAR 0x0020 /* clear event state after reporting */ #define EV_SYSFLAGS 0xF000 /* reserved by system */ #define EV_FLAG1 0x2000 /* filter-specific flag */ /* returned values */ #define EV_EOF 0x8000 /* EOF detected */ #define EV_ERROR 0x4000 /* error, data contains errno */ /* * data/hint flags for EVFILT_{READ|WRITE}, shared with userspace */ #define NOTE_LOWAT 0x0001 /* low water mark */ /* * data/hint flags for EVFILT_VNODE, shared with userspace */ #define NOTE_DELETE 0x0001 /* vnode was removed */ #define NOTE_WRITE 0x0002 /* data contents changed */ #define NOTE_EXTEND 0x0004 /* size increased */ #define NOTE_ATTRIB 0x0008 /* attributes changed */ #define NOTE_LINK 0x0010 /* link count changed */ #define NOTE_RENAME 0x0020 /* vnode was renamed */ #define NOTE_REVOKE 0x0040 /* vnode access was revoked */ /* * data/hint flags for EVFILT_PROC, shared with userspace */ #define NOTE_EXIT 0x80000000 /* process exited */ #define NOTE_FORK 0x40000000 /* process forked */ #define NOTE_EXEC 0x20000000 /* process exec'd */ #define NOTE_PCTRLMASK 0xf0000000 /* mask for hint bits */ #define NOTE_PDATAMASK 0x000fffff /* mask for pid */ /* additional flags for EVFILT_PROC */ #define NOTE_TRACK 0x00000001 /* follow across forks */ #define NOTE_TRACKERR 0x00000002 /* could not track child */ #define NOTE_CHILD 0x00000004 /* am a child process */ /* * data/hint flags for EVFILT_NETDEV, shared with userspace */ #define NOTE_LINKUP 0x0001 /* link is up */ #define NOTE_LINKDOWN 0x0002 /* link is down */ #define NOTE_LINKINV 0x0004 /* link state is invalid */ /* * This is currently visible to userland to work around broken * programs which pull in . */ #include struct knote; SLIST_HEAD(klist, knote); #ifdef _KERNEL #ifdef MALLOC_DECLARE MALLOC_DECLARE(M_KQUEUE); #endif #define KNOTE(list, hint) if ((list) != NULL) knote(list, hint) /* * Flag indicating hint is a signal. Used by EVFILT_SIGNAL, and also * shared by EVFILT_PROC (all knotes attached to p->p_klist) */ #define NOTE_SIGNAL 0x08000000 struct filterops { int f_isfd; /* true if ident == filedescriptor */ int (*f_attach) (struct knote *kn); void (*f_detach) (struct knote *kn); int (*f_event) (struct knote *kn, long hint); }; struct knote { SLIST_ENTRY(knote) kn_link; /* for fd */ SLIST_ENTRY(knote) kn_selnext; /* for struct selinfo */ TAILQ_ENTRY(knote) kn_tqe; struct kqueue *kn_kq; /* which queue we are on */ struct kevent kn_kevent; int kn_status; int kn_sfflags; /* saved filter flags */ intptr_t kn_sdata; /* saved data field */ union { struct file *p_fp; /* file data pointer */ struct proc *p_proc; /* proc pointer */ } kn_ptr; struct filterops *kn_fop; void *kn_hook; #define KN_ACTIVE 0x01 /* event has been triggered */ #define KN_QUEUED 0x02 /* event is on queue */ #define KN_DISABLED 0x04 /* event is disabled */ #define KN_DETACHED 0x08 /* knote is detached */ #define kn_id kn_kevent.ident #define kn_filter kn_kevent.filter #define kn_flags kn_kevent.flags #define kn_fflags kn_kevent.fflags #define kn_data kn_kevent.data #define kn_fp kn_ptr.p_fp }; struct thread; struct proc; extern void knote(struct klist *list, long hint); extern void knote_remove(struct thread *p, struct klist *list); extern void knote_fdclose(struct thread *p, int fd); extern int kqueue_register(struct kqueue *kq, struct kevent *kev, struct thread *p); extern int kqueue_add_filteropts(int filt, struct filterops *filtops); extern int kqueue_del_filteropts(int filt); #else /* !_KERNEL */ #include struct timespec; __BEGIN_DECLS int kqueue(void); int kevent(int kq, const struct kevent *changelist, int nchanges, struct kevent *eventlist, int nevents, const struct timespec *timeout); __END_DECLS #endif /* !_KERNEL */ #endif /* !_TIRPC_EVENT_H_ */ ntirpc-1.3.1/ntirpc/misc/opr.h000066400000000000000000000002571261345040100162160ustar00rootroot00000000000000#ifndef OPR_H #define OPR_H 1 #define opr_containerof(ptr, structure, member) \ ((structure *)((char *)(ptr)-(char *)(&((structure *)NULL)->member))) #endif /* OPR_H */ ntirpc-1.3.1/ntirpc/misc/opr_queue.h000066400000000000000000000166101261345040100174220ustar00rootroot00000000000000/* * Copyright (c) 2010 Your File System Inc. 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /* A better queue implementation. * * This differs from the original queue implementation in that that would * only allow a structure to be threaded onto a single queue. This permits * a given object to be on multiple queues, providing that each queue has * a place in the structure definition. */ #ifndef OPR_QUEUE_H #define OPR_QUEUE_H 1 #include struct opr_queue { struct opr_queue *next; struct opr_queue *prev; }; #define opr_queue_Scan(head, cursor) \ cursor = (head)->next; cursor != (head); cursor = cursor->next #define opr_queue_ScanSafe(head, cursor, store) \ cursor = (head)->next, store = cursor->next; \ cursor != (head); \ cursor = store, store = store->next #define opr_queue_ScanFrom(head, cursor) \ /* nothing */; cursor != (head); cursor = cursor->next #define opr_queue_ScanSafeFrom(head, cursor, store) \ /* nothing */, store = cursor->next; \ cursor != (head); \ cursor = store, store = store->next #define opr_queue_ScanBackwards(head, cursor) \ cursor = (head)->prev; cursor != (head); cursor = cursor->prev #define opr_queue_ScanBackwards(head, cursor) \ cursor = (head)->prev; cursor != (head); cursor = cursor->prev #define opr_queue_ScanBackwardsFrom(head, cursor) \ /* nothing */; cursor != (head); cursor = cursor->prev #define opr_queue_ScanBackwardsSafe(head, cursor, store) \ cursor = (head)->prev, store = cursor->prev; \ cursor != (head); \ cursor = store, store = store->prev #define opr_queue_ScanBackwardsSafeFrom(head, cursor, store) \ /* nothing */, store = cursor->prev; \ cursor != (head); \ cursor = store, store = store->prev static inline void opr_queue_Zero(struct opr_queue *q) { q->prev = q->next = NULL; } static inline void opr_queue_Init(struct opr_queue *q) { q->prev = q->next = q; } static inline void opr_queue_add(struct opr_queue *element, struct opr_queue *before, struct opr_queue *after) { after->prev = element; element->next = after; element->prev = before; before->next = element; } static inline void opr_queue_Append(struct opr_queue *queue, struct opr_queue *element) { opr_queue_add(element, queue->prev, queue); } static inline void opr_queue_Prepend(struct opr_queue *queue, struct opr_queue *element) { opr_queue_add(element, queue, queue->next); } static inline void opr_queue_InsertBefore(struct opr_queue *exist, struct opr_queue *adding) { /* This may seem back to front, but take a list A, B, C where we want * to add 1 before B. So, we're adding 1 with A the element before, * and B the element after, hence the following: */ opr_queue_add(adding, exist->prev, exist); } static inline void opr_queue_InsertAfter(struct opr_queue *exist, struct opr_queue *adding) { opr_queue_add(adding, exist, exist->next); } static inline void opr_queue_Remove(struct opr_queue *element) { element->next->prev = element->prev; element->prev->next = element->next; element->prev = NULL; element->next = NULL; } static inline int opr_queue_IsEmpty(struct opr_queue *q) { return (q->prev == q); } static inline int opr_queue_IsOnQueue(struct opr_queue *q) { return (q->prev != NULL); } static inline int opr_queue_IsEnd(struct opr_queue *q, struct opr_queue *cursor) { return (cursor->next == q); } static inline int opr_queue_Count(struct opr_queue *q) { struct opr_queue *cursor; int n = 0; for (opr_queue_Scan(q, cursor)) { n++; } return n; } static inline void opr_queue_Swap(struct opr_queue *a, struct opr_queue *b) { struct opr_queue tq = *b; if (a->prev == a) { b->prev = b->next = b; } else { *b = *a; b->prev->next = b; b->next->prev = b; } if (tq.prev == b) { a->prev = a->next = a; } else { *a = tq; a->prev->next = a; a->next->prev = a; } } /* Remove the members before pivot from Q1, and append them to Q2 */ static inline void opr_queue_SplitBeforeAppend(struct opr_queue *q1, struct opr_queue *q2, struct opr_queue *pivot) { if (q1 == pivot->prev) return; /* Add ourselves to the end of list 2 */ q2->prev->next = q1->next; /* end of q 2, is now the start of q 1 */ q1->next->prev = q2->prev; pivot->prev->next = q2; /* entry before the pivot is it at end of q2 */ q2->prev = pivot->prev; /* Pull ourselves out of list q1. */ q1->next = pivot; pivot->prev = q1; } /* Remove the members after the pivot from Q1, and prepend them onto Q2 */ static inline void opr_queue_SplitAfterPrepend(struct opr_queue *q1, struct opr_queue *q2, struct opr_queue *pivot) { if (q1 == pivot->next) return; /* start of q2 has last element of q1 before it */ q2->next->prev = q1->prev; q1->prev->next = q2->next; /* item that we're breaking at (pivot->next) is at start of q2 */ q2->next = pivot->next; pivot->next->prev = q2; /* Q1 now ends after pivot */ pivot->next = q1; q1->prev = pivot; } static inline void opr_queue_SpliceAppend(struct opr_queue *target, struct opr_queue *source) { if (source->next == source) return; /* Stick the contents of source onto the end of target */ target->prev->next = source->next; source->next->prev = target->prev; source->prev->next = target; target->prev = source->prev; /* Reinitialise source */ source->next = source->prev = source; } static inline void opr_queue_SplicePrepend(struct opr_queue *target, struct opr_queue *source) { if (source->next == source) return; /* Contents of source go onto the beginning of target */ target->next->prev = source->prev; source->prev->next = target->next; source->next->prev = target; target->next = source->next; /* Reinitialise source */ source->next = source->prev = source; } #define opr_queue_Entry(queue, structure, member) \ ((structure *)((char *)(queue)-(char *)(&((structure *)NULL)->member))) #define opr_queue_First(queue, structure, member) \ opr_queue_Entry((queue)->next, structure, member) #define opr_queue_Last(queue, structure, member) \ opr_queue_Entry((queue)->prev, structure, member) #define opr_queue_Next(entry, structure, member) \ opr_queue_Entry((entry)->next, structure, member) #define opr_queue_Prev(entry, structure, member) \ opr_queue_Entry((entry)->prev, structure, member) #endif ntirpc-1.3.1/ntirpc/misc/os_epoll.h000066400000000000000000000003411261345040100172240ustar00rootroot00000000000000 #ifndef NTIRPC_OS_EPOLL_H #define NTIRPC_OS_EPOLL_H #if defined(__linux__) #include #else /* epoll <-> kevent shim by Boaz Harrosh */ #include #endif #endif /* else NTIRPC_OS_EPOLL_H */ ntirpc-1.3.1/ntirpc/misc/portable.h000066400000000000000000000031231261345040100172210ustar00rootroot00000000000000 #ifndef NTIRPC_PORTABLE_H #define NTIRPC_PORTABLE_H #include #include /* before rpc.h */ #if defined(__FreeBSD__) #include #define SOL_IP 0 #define SOL_IPV6 41 #define IP_PKTINFO IP_RECVIF struct in_pktinfo { struct in_addr ipi_addr; /* destination IPv4 address */ int ipi_ifindex; /* received interface index */ }; /* YES. Move. */ #define HAVE_PEEREID 1 #endif #if defined(__linux__) /* POSIX clocks */ #define CLOCK_REALTIME_FAST CLOCK_REALTIME_COARSE #define CLOCK_MONOTONIC_FAST CLOCK_MONOTONIC_COARSE /* poll */ #define POLLRDNORM 0x040 /* Normal data may be read. */ #define POLLRDBAND 0x080 /* Priority data may be read. */ #define HAVE_GETPEEREID 0 #endif #if defined(_WIN32) #ifdef _MSC_VER #include #else #include #endif #include #include #define CLOCK_MONOTONIC_FAST 6 typedef uint32_t clockid_t; extern int clock_gettime(clockid_t clock, struct timespec *ts); void warnx(const char *fmt, ...); #else #define PtrToUlong(addr) ((unsigned long)(addr)) #endif /* !_WIN32 */ #ifdef __APPLE__ #include typedef unsigned int clockid_t; #define CLOCK_MONOTONIC_FAST 6 extern int clock_gettime(clockid_t clock, struct timespec *ts); #endif #ifndef max #define max(a, b) (a > b ? a : b) #endif #if !defined(CACHE_LINE_SIZE) #if defined(__PPC64__) #define CACHE_LINE_SIZE 128 #else /* __x86_64__, __i386__ and others */ #define CACHE_LINE_SIZE 64 #endif #endif #define CACHE_PAD(_n) char __pad ## _n [CACHE_LINE_SIZE] #endif /* NTIRPC_PORTABLE_H */ ntirpc-1.3.1/ntirpc/misc/queue.h000066400000000000000000000531101261345040100165360ustar00rootroot00000000000000/*- * Copyright (c) 1991, 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)queue.h 8.5 (Berkeley) 8/20/94 $FreeBSD: * src/sys/sys/queue.h,v 1.75.2.1.2.1 2011/11/11 04:20:22 kensmith Exp * $ */ #ifndef _TIRPC_MISC_QUEUE_H_ #define _TIRPC_MISC_QUEUE_H_ #if defined(__FreeBSD__) && defined(_SYS_QUEUE_H_) #error misc/queue.h must be included before sys/queue.h #else #define _SYS_QUEUE_H_ #endif #include /* * This file defines four types of data structures: singly-linked lists, * singly-linked tail queues, lists and tail queues. * * A singly-linked list is headed by a single forward pointer. The elements * are singly linked for minimum space and pointer manipulation overhead at * the expense of O(n) removal for arbitrary elements. New elements can be * added to the list after an existing element or at the head of the list. * Elements being removed from the head of the list should use the explicit * macro for this purpose for optimum efficiency. A singly-linked list may * only be traversed in the forward direction. Singly-linked lists are ideal * for applications with large datasets and few or no removals or for * implementing a LIFO queue. * * A singly-linked tail queue is headed by a pair of pointers, one to the * head of the list and the other to the tail of the list. The elements are * singly linked for minimum space and pointer manipulation overhead at the * expense of O(n) removal for arbitrary elements. New elements can be added * to the list after an existing element, at the head of the list, or at the * end of the list. Elements being removed from the head of the tail queue * should use the explicit macro for this purpose for optimum efficiency. * A singly-linked tail queue may only be traversed in the forward direction. * Singly-linked tail queues are ideal for applications with large datasets * and few or no removals or for implementing a FIFO queue. * * A list is headed by a single forward pointer (or an array of forward * pointers for a hash table header). The elements are doubly linked * so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before * or after an existing element or at the head of the list. A list * may only be traversed in the forward direction. * * A tail queue is headed by a pair of pointers, one to the head of the * list and the other to the tail of the list. The elements are doubly * linked so that an arbitrary element can be removed without a need to * traverse the list. New elements can be added to the list before or * after an existing element, at the head of the list, or at the end of * the list. A tail queue may be traversed in either direction. * * For details on the use of these macros, see the queue(3) manual page. * * * SLIST LIST STAILQ TAILQ * _HEAD + + + + * _HEAD_INITIALIZER + + + + * _ENTRY + + + + * _INIT + + + + * _EMPTY + + + + * _FIRST + + + + * _NEXT + + + + * _PREV - - - + * _LAST - - + + * _FOREACH + + + + * _FOREACH_SAFE + + + + * _FOREACH_REVERSE - - - + * _FOREACH_REVERSE_SAFE - - - + * _INSERT_HEAD + + + + * _INSERT_BEFORE - + - + * _INSERT_AFTER + + + + * _INSERT_TAIL - - + + * _CONCAT - - + + * _REMOVE_AFTER + - + - * _REMOVE_HEAD + - + - * _REMOVE + + + + * _SWAP + + + + * */ #ifdef QUEUE_MACRO_DEBUG /* Store the last 2 places the queue element or head was altered */ struct qm_trace { char *lastfile; int lastline; char *prevfile; int prevline; }; #define TRACEBUF struct qm_trace trace; #define TRASHIT(x) do {(x) = (void *)-1; } while (0) #define QMD_SAVELINK(name, link) void **name = (void *)&(link) #define QMD_TRACE_HEAD(head) do { \ (head)->trace.prevline = (head)->trace.lastline; \ (head)->trace.prevfile = (head)->trace.lastfile; \ (head)->trace.lastline = __LINE__; \ (head)->trace.lastfile = __FILE__; \ } while (0) #define QMD_TRACE_ELEM(elem) do { \ (elem)->trace.prevline = (elem)->trace.lastline; \ (elem)->trace.prevfile = (elem)->trace.lastfile; \ (elem)->trace.lastline = __LINE__; \ (elem)->trace.lastfile = __FILE__; \ } while (0) #else #define QMD_TRACE_ELEM(elem) #define QMD_TRACE_HEAD(head) #define QMD_SAVELINK(name, link) #define TRACEBUF #define TRASHIT(x) #endif /* QUEUE_MACRO_DEBUG */ /* * Singly-linked List declarations. */ #define SLIST_HEAD(name, type) \ struct name { \ struct type *slh_first; /* first element */ \ } #define SLIST_HEAD_INITIALIZER(head) \ { NULL } #define SLIST_ENTRY(type) \ struct { \ struct type *sle_next; /* next element */ \ } /* * Singly-linked List functions. */ #define SLIST_EMPTY(head) ((head)->slh_first == NULL) #define SLIST_FIRST(head) ((head)->slh_first) #define SLIST_FOREACH(var, head, field) \ for ((var) = SLIST_FIRST((head)); \ (var); \ (var) = SLIST_NEXT((var), field)) #define SLIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = SLIST_FIRST((head)); \ (var) && ((tvar) = SLIST_NEXT((var), field), 1); \ (var) = (tvar)) #define SLIST_FOREACH_PREVPTR(var, varp, head, field) \ for ((varp) = &SLIST_FIRST((head)); \ ((var) = *(varp)) != NULL; \ (varp) = &SLIST_NEXT((var), field)) #define SLIST_INIT(head) do { \ SLIST_FIRST((head)) = NULL; \ } while (0) #define SLIST_INSERT_AFTER(slistelm, elm, field) do { \ SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field); \ SLIST_NEXT((slistelm), field) = (elm); \ } while (0) #define SLIST_INSERT_HEAD(head, elm, field) do { \ SLIST_NEXT((elm), field) = SLIST_FIRST((head)); \ SLIST_FIRST((head)) = (elm); \ } while (0) #define SLIST_NEXT(elm, field) ((elm)->field.sle_next) #define SLIST_REMOVE(head, elm, type, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.sle_next); \ if (SLIST_FIRST((head)) == (elm)) { \ SLIST_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = SLIST_FIRST((head)); \ while (SLIST_NEXT(curelm, field) != (elm)) \ curelm = SLIST_NEXT(curelm, field); \ SLIST_REMOVE_AFTER(curelm, field); \ } \ TRASHIT(*oldnext); \ } while (0) #define SLIST_REMOVE_AFTER(elm, field) do { \ SLIST_NEXT(elm, field) = \ SLIST_NEXT(SLIST_NEXT(elm, field), field); \ } while (0) #define SLIST_REMOVE_HEAD(head, field) do { \ SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field); \ } while (0) #define SLIST_SWAP(head1, head2, type) do { \ struct type *swap_first = SLIST_FIRST(head1); \ SLIST_FIRST(head1) = SLIST_FIRST(head2); \ SLIST_FIRST(head2) = swap_first; \ } while (0) /* * Singly-linked Tail queue declarations. */ #define STAILQ_HEAD(name, type) \ struct name { \ struct type *stqh_first;/* first element */ \ struct type **stqh_last;/* addr of last next element */ \ } #define STAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).stqh_first } #define STAILQ_ENTRY(type) \ struct { \ struct type *stqe_next; /* next element */ \ } /* * Singly-linked Tail queue functions. */ #define STAILQ_CONCAT(head1, head2) do { \ if (!STAILQ_EMPTY((head2))) { \ *(head1)->stqh_last = (head2)->stqh_first; \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_INIT((head2)); \ } \ } while (0) #define STAILQ_EMPTY(head) ((head)->stqh_first == NULL) #define STAILQ_FIRST(head) ((head)->stqh_first) #define STAILQ_FOREACH(var, head, field) \ for ((var) = STAILQ_FIRST((head)); \ (var); \ (var) = STAILQ_NEXT((var), field)) #define STAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = STAILQ_FIRST((head)); \ (var) && ((tvar) = STAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #define STAILQ_INIT(head) do { \ STAILQ_FIRST((head)) = NULL; \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) #define STAILQ_INSERT_AFTER(head, tqelm, elm, field) do { \ if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ STAILQ_NEXT((tqelm), field) = (elm); \ } while (0) #define STAILQ_INSERT_HEAD(head, elm, field) do { \ if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL) \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ STAILQ_FIRST((head)) = (elm); \ } while (0) #define STAILQ_INSERT_TAIL(head, elm, field) do { \ STAILQ_NEXT((elm), field) = NULL; \ *(head)->stqh_last = (elm); \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) #define STAILQ_LAST(head, type, field) \ (STAILQ_EMPTY((head)) ? \ NULL : \ ((struct type *)(void *) \ ((char *)((head)->stqh_last) - __offsetof(struct type, field)))) #define STAILQ_NEXT(elm, field) ((elm)->field.stqe_next) #define STAILQ_REMOVE(head, elm, type, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.stqe_next); \ if (STAILQ_FIRST((head)) == (elm)) { \ STAILQ_REMOVE_HEAD((head), field); \ } \ else { \ struct type *curelm = STAILQ_FIRST((head)); \ while (STAILQ_NEXT(curelm, field) != (elm)) \ curelm = STAILQ_NEXT(curelm, field); \ STAILQ_REMOVE_AFTER(head, curelm, field); \ } \ TRASHIT(*oldnext); \ } while (0) #define STAILQ_REMOVE_AFTER(head, elm, field) do { \ if ((STAILQ_NEXT(elm, field) = \ STAILQ_NEXT(STAILQ_NEXT(elm, field), field)) == NULL) \ (head)->stqh_last = &STAILQ_NEXT((elm), field); \ } while (0) #define STAILQ_REMOVE_HEAD(head, field) do { \ if ((STAILQ_FIRST((head)) = \ STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL) \ (head)->stqh_last = &STAILQ_FIRST((head)); \ } while (0) #define STAILQ_SWAP(head1, head2, type) do { \ struct type *swap_first = STAILQ_FIRST(head1); \ struct type **swap_last = (head1)->stqh_last; \ STAILQ_FIRST(head1) = STAILQ_FIRST(head2); \ (head1)->stqh_last = (head2)->stqh_last; \ STAILQ_FIRST(head2) = swap_first; \ (head2)->stqh_last = swap_last; \ if (STAILQ_EMPTY(head1)) \ (head1)->stqh_last = &STAILQ_FIRST(head1); \ if (STAILQ_EMPTY(head2)) \ (head2)->stqh_last = &STAILQ_FIRST(head2); \ } while (0) /* * List declarations. */ #define LIST_HEAD(name, type) \ struct name { \ struct type *lh_first; /* first element */ \ } #define LIST_HEAD_INITIALIZER(head) \ { NULL } #define LIST_ENTRY(type) \ struct { \ struct type *le_next; /* next element */ \ struct type **le_prev; /* address of previous next element */ \ } /* * List functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) #define QMD_LIST_CHECK_HEAD(head, field) do { \ if (LIST_FIRST((head)) != NULL && \ LIST_FIRST((head))->field.le_prev != \ &LIST_FIRST((head))) \ panic("Bad list head %p first->prev != head", (head)); \ } while (0) #define QMD_LIST_CHECK_NEXT(elm, field) do { \ if (LIST_NEXT((elm), field) != NULL && \ LIST_NEXT((elm), field)->field.le_prev != \ &((elm)->field.le_next)) \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) #define QMD_LIST_CHECK_PREV(elm, field) do { \ if (*(elm)->field.le_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ } while (0) #else #define QMD_LIST_CHECK_HEAD(head, field) #define QMD_LIST_CHECK_NEXT(elm, field) #define QMD_LIST_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) */ #define LIST_EMPTY(head) ((head)->lh_first == NULL) #define LIST_FIRST(head) ((head)->lh_first) #define LIST_FOREACH(var, head, field) \ for ((var) = LIST_FIRST((head)); \ (var); \ (var) = LIST_NEXT((var), field)) #define LIST_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = LIST_FIRST((head)); \ (var) && ((tvar) = LIST_NEXT((var), field), 1); \ (var) = (tvar)) #define LIST_INIT(head) do { \ LIST_FIRST((head)) = NULL; \ } while (0) #define LIST_INSERT_AFTER(listelm, elm, field) do { \ QMD_LIST_CHECK_NEXT(listelm, field); \ if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ LIST_NEXT((listelm), field)->field.le_prev = \ &LIST_NEXT((elm), field); \ LIST_NEXT((listelm), field) = (elm); \ (elm)->field.le_prev = &LIST_NEXT((listelm), field); \ } while (0) #define LIST_INSERT_BEFORE(listelm, elm, field) do { \ QMD_LIST_CHECK_PREV(listelm, field); \ (elm)->field.le_prev = (listelm)->field.le_prev; \ LIST_NEXT((elm), field) = (listelm); \ *(listelm)->field.le_prev = (elm); \ (listelm)->field.le_prev = &LIST_NEXT((elm), field); \ } while (0) #define LIST_INSERT_HEAD(head, elm, field) do { \ QMD_LIST_CHECK_HEAD((head), field); \ if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL) \ LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ LIST_FIRST((head)) = (elm); \ (elm)->field.le_prev = &LIST_FIRST((head)); \ } while (0) #define LIST_NEXT(elm, field) ((elm)->field.le_next) #define LIST_REMOVE(elm, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.le_next); \ QMD_SAVELINK(oldprev, (elm)->field.le_prev); \ QMD_LIST_CHECK_NEXT(elm, field); \ QMD_LIST_CHECK_PREV(elm, field); \ if (LIST_NEXT((elm), field) != NULL) \ LIST_NEXT((elm), field)->field.le_prev = \ (elm)->field.le_prev; \ *(elm)->field.le_prev = LIST_NEXT((elm), field); \ TRASHIT(*oldnext); \ TRASHIT(*oldprev); \ } while (0) #define LIST_SWAP(head1, head2, type, field) do { \ struct type *swap_tmp = LIST_FIRST((head1)); \ LIST_FIRST((head1)) = LIST_FIRST((head2)); \ LIST_FIRST((head2)) = swap_tmp; \ if ((swap_tmp = LIST_FIRST((head1))) != NULL) \ swap_tmp->field.le_prev = &LIST_FIRST((head1)); \ if ((swap_tmp = LIST_FIRST((head2))) != NULL) \ swap_tmp->field.le_prev = &LIST_FIRST((head2)); \ } while (0) /* * Tail queue declarations. */ #define TAILQ_HEAD(name, type) \ struct name { \ struct type *tqh_first; /* first element */ \ struct type **tqh_last; /* addr of last next element */ \ TRACEBUF \ } #define TAILQ_HEAD_INITIALIZER(head) \ { NULL, &(head).tqh_first } #define TAILQ_ENTRY(type) \ struct { \ struct type *tqe_next; /* next element */ \ struct type **tqe_prev; /* address of previous next element */ \ TRACEBUF \ } /* * Tail queue functions. */ #if (defined(_KERNEL) && defined(INVARIANTS)) #define QMD_TAILQ_CHECK_HEAD(head, field) do { \ if (!TAILQ_EMPTY(head) && \ TAILQ_FIRST((head))->field.tqe_prev != \ &TAILQ_FIRST((head))) \ panic("Bad tailq head %p first->prev != head", (head)); \ } while (0) #define QMD_TAILQ_CHECK_TAIL(head, field) do { \ if (*(head)->tqh_last != NULL) \ panic("Bad tailq NEXT(%p->tqh_last) != NULL", (head)); \ } while (0) #define QMD_TAILQ_CHECK_NEXT(elm, field) do { \ if (TAILQ_NEXT((elm), field) != NULL && \ TAILQ_NEXT((elm), field)->field.tqe_prev != \ &((elm)->field.tqe_next)) \ panic("Bad link elm %p next->prev != elm", (elm)); \ } while (0) #define QMD_TAILQ_CHECK_PREV(elm, field) do { \ if (*(elm)->field.tqe_prev != (elm)) \ panic("Bad link elm %p prev->next != elm", (elm)); \ } while (0) #else #define QMD_TAILQ_CHECK_HEAD(head, field) #define QMD_TAILQ_CHECK_TAIL(head, headname) #define QMD_TAILQ_CHECK_NEXT(elm, field) #define QMD_TAILQ_CHECK_PREV(elm, field) #endif /* (_KERNEL && INVARIANTS) */ #define TAILQ_CONCAT(head1, head2, field) do { \ if (!TAILQ_EMPTY(head2)) { \ *(head1)->tqh_last = (head2)->tqh_first; \ (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \ (head1)->tqh_last = (head2)->tqh_last; \ TAILQ_INIT((head2)); \ QMD_TRACE_HEAD(head1); \ QMD_TRACE_HEAD(head2); \ } \ } while (0) #define TAILQ_EMPTY(head) ((head)->tqh_first == NULL) #define TAILQ_FIRST(head) ((head)->tqh_first) #define TAILQ_FOREACH(var, head, field) \ for ((var) = TAILQ_FIRST((head)); \ (var); \ (var) = TAILQ_NEXT((var), field)) #define TAILQ_FOREACH_SAFE(var, head, field, tvar) \ for ((var) = TAILQ_FIRST((head)); \ (var) && ((tvar) = TAILQ_NEXT((var), field), 1); \ (var) = (tvar)) #define TAILQ_FOREACH_REVERSE(var, head, headname, field) \ for ((var) = TAILQ_LAST((head), headname); \ (var); \ (var) = TAILQ_PREV((var), headname, field)) #define TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar) \ for ((var) = TAILQ_LAST((head), headname); \ (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1); \ (var) = (tvar)) #define TAILQ_INIT(head) do { \ TAILQ_FIRST((head)) = NULL; \ (head)->tqh_last = &TAILQ_FIRST((head)); \ QMD_TRACE_HEAD(head); \ } while (0) /* XXX optional IS_ENQUEUED support--entries must be initialized if * IS_ENQUEUED will be used */ #define TAILQ_INIT_ENTRY(elm, field) do { \ (elm)->field.tqe_prev = NULL; \ (elm)->field.tqe_next = NULL; \ } while (0) #define TAILQ_IS_ENQUEUED(elm, field) (((elm)->field.tqe_prev != NULL) || \ ((elm)->field.tqe_next != NULL)) #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \ QMD_TAILQ_CHECK_NEXT(listelm, field); \ if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ TAILQ_NEXT((elm), field)->field.tqe_prev = \ &TAILQ_NEXT((elm), field); \ else { \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \ QMD_TRACE_HEAD(head); \ } \ TAILQ_NEXT((listelm), field) = (elm); \ (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field); \ QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&listelm->field); \ } while (0) #define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \ QMD_TAILQ_CHECK_PREV(listelm, field); \ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \ TAILQ_NEXT((elm), field) = (listelm); \ *(listelm)->field.tqe_prev = (elm); \ (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field); \ QMD_TRACE_ELEM(&(elm)->field); \ QMD_TRACE_ELEM(&listelm->field); \ } while (0) #define TAILQ_INSERT_HEAD(head, elm, field) do { \ QMD_TAILQ_CHECK_HEAD(head, field); \ if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL) \ TAILQ_FIRST((head))->field.tqe_prev = \ &TAILQ_NEXT((elm), field); \ else \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \ TAILQ_FIRST((head)) = (elm); \ (elm)->field.tqe_prev = &TAILQ_FIRST((head)); \ QMD_TRACE_HEAD(head); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #define TAILQ_INSERT_TAIL(head, elm, field) do { \ QMD_TAILQ_CHECK_TAIL(head, field); \ TAILQ_NEXT((elm), field) = NULL; \ (elm)->field.tqe_prev = (head)->tqh_last; \ *(head)->tqh_last = (elm); \ (head)->tqh_last = &TAILQ_NEXT((elm), field); \ QMD_TRACE_HEAD(head); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #define TAILQ_LAST(head, headname) \ (*(((struct headname *)((head)->tqh_last))->tqh_last)) #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_PREV(elm, headname, field) \ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) #define TAILQ_REMOVE(head, elm, field) do { \ QMD_SAVELINK(oldnext, (elm)->field.tqe_next); \ QMD_SAVELINK(oldprev, (elm)->field.tqe_prev); \ QMD_TAILQ_CHECK_NEXT(elm, field); \ QMD_TAILQ_CHECK_PREV(elm, field); \ if ((TAILQ_NEXT((elm), field)) != NULL) \ TAILQ_NEXT((elm), field)->field.tqe_prev = \ (elm)->field.tqe_prev; \ else { \ (head)->tqh_last = (elm)->field.tqe_prev; \ QMD_TRACE_HEAD(head); \ } \ *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field); \ TRASHIT(*oldnext); \ TRASHIT(*oldprev); \ QMD_TRACE_ELEM(&(elm)->field); \ } while (0) #define TAILQ_SWAP(head1, head2, type, field) do { \ struct type *swap_first = (head1)->tqh_first; \ struct type **swap_last = (head1)->tqh_last; \ (head1)->tqh_first = (head2)->tqh_first; \ (head1)->tqh_last = (head2)->tqh_last; \ (head2)->tqh_first = swap_first; \ (head2)->tqh_last = swap_last; \ if ((swap_first = (head1)->tqh_first) != NULL) \ swap_first->field.tqe_prev = &(head1)->tqh_first; \ else \ (head1)->tqh_last = &(head1)->tqh_first; \ if ((swap_first = (head2)->tqh_first) != NULL) \ swap_first->field.tqe_prev = &(head2)->tqh_first; \ else \ (head2)->tqh_last = &(head2)->tqh_first; \ } while (0) #endif /* !TIRPC__MISC_QUEUE_H_ */ ntirpc-1.3.1/ntirpc/misc/rbtree.h000066400000000000000000000036451261345040100167050ustar00rootroot00000000000000/* Left-leaning red/black trees */ #ifndef _OPR_RBTREE_H #define _OPR_RBTREE_H 1 #include #include #include /* from opr.h */ #define opr_containerof(ptr, structure, member) \ ((structure *)((char *)(ptr)-(char *)(&((structure *)NULL)->member))) struct opr_rbtree_node { struct opr_rbtree_node *left; struct opr_rbtree_node *right; struct opr_rbtree_node *parent; uint32_t red; uint32_t gen; /* generation number */ }; typedef int (*opr_rbtree_cmpf_t) (const struct opr_rbtree_node *lhs, const struct opr_rbtree_node *rhs); struct opr_rbtree { struct opr_rbtree_node *root; opr_rbtree_cmpf_t cmpf; uint64_t size; uint64_t gen; /* generation number */ }; extern void opr_rbtree_init(struct opr_rbtree *head, opr_rbtree_cmpf_t cmpf); extern struct opr_rbtree_node *opr_rbtree_first(struct opr_rbtree *head); extern struct opr_rbtree_node *opr_rbtree_last(struct opr_rbtree *head); extern struct opr_rbtree_node *opr_rbtree_next(struct opr_rbtree_node *node); extern struct opr_rbtree_node *opr_rbtree_prev(struct opr_rbtree_node *node); extern struct opr_rbtree_node *opr_rbtree_lookup(struct opr_rbtree *head, struct opr_rbtree_node *node); extern struct opr_rbtree_node *opr_rbtree_insert(struct opr_rbtree *head, struct opr_rbtree_node *node); extern void opr_rbtree_insert_at(struct opr_rbtree *head, struct opr_rbtree_node *parent, struct opr_rbtree_node **childptr, struct opr_rbtree_node *node); extern void opr_rbtree_remove(struct opr_rbtree *head, struct opr_rbtree_node *node); extern void opr_rbtree_replace(struct opr_rbtree *head, struct opr_rbtree_node *old, struct opr_rbtree_node *replacement); static inline bool opr_rbtree_node_valid(struct opr_rbtree_node *node) { return (node->gen != 0); } static inline unsigned long opr_rbtree_size(struct opr_rbtree *head) { return (head->size); } #endif /* _OPR_RBTREE_H */ ntirpc-1.3.1/ntirpc/misc/rbtree_x.h000066400000000000000000000073031261345040100172270ustar00rootroot00000000000000 #ifndef _RBTREE_X_H #define _RBTREE_X_H #include #include #include #include struct rbtree_x_part { CACHE_PAD(0); pthread_rwlock_t lock; pthread_mutex_t mtx; void *u1; void *u2; struct opr_rbtree t; struct opr_rbtree_node **cache; CACHE_PAD(1); }; struct rbtree_x { uint32_t npart; uint32_t flags; int32_t cachesz; struct rbtree_x_part *tree; }; #define RBT_X_FLAG_NONE 0x0000 #define RBT_X_FLAG_ALLOC 0x0001 /* Cache strategies. * * In read-through strategy, entries are always inserted in the * tree, but lookups may be O(1) when an entry is shadowed in cache. * * In the write through strategy, t->cache and t->tree partition * t, and t->cache is always consulted first. */ #define RBT_X_FLAG_CACHE_RT 0x0002 #define RBT_X_FLAG_CACHE_WT 0x0004 #define rbtx_idx_of_scalar(xt, k) ((k)%((xt)->npart)) #define rbtx_partition_of_ix(xt, ix) ((xt)->tree+(ix)) #define rbtx_partition_of_scalar(xt, k) \ (rbtx_partition_of_ix((xt), rbtx_idx_of_scalar((xt), (k)))) extern int rbtx_init(struct rbtree_x *xt, opr_rbtree_cmpf_t cmpf, uint32_t npart, uint32_t flags); static inline struct opr_rbtree_node *rbtree_x_cached_lookup( struct rbtree_x *xt, struct rbtree_x_part *t, struct opr_rbtree_node *nk, uint64_t hk) { struct opr_rbtree_node *nv_cached, *nv = NULL; uint32_t offset; if (!t) t = rbtx_partition_of_scalar(xt, hk); offset = hk % xt->cachesz; nv_cached = t->cache[offset]; if (nv_cached) { if (t->t.cmpf(nv_cached, nk) == 0) { nv = nv_cached; goto out; } } nv = opr_rbtree_lookup(&t->t, nk); if (nv && (xt->flags & RBT_X_FLAG_CACHE_RT)) t->cache[offset] = nv; __warnx(TIRPC_DEBUG_FLAG_RBTREE, "rbtree_x_cached_lookup: t %p nk %p nv %p" "(%s hk %" PRIx64 " slot/offset %d)", t, nk, nv, (nv_cached) ? "CACHED" : "", hk, offset); out: return (nv); } static inline struct opr_rbtree_node *rbtree_x_cached_insert( struct rbtree_x *xt, struct rbtree_x_part *t, struct opr_rbtree_node *nk, uint64_t hk) { struct opr_rbtree_node *v_cached, *nv = NULL; uint32_t offset; int cix = rbtx_idx_of_scalar(xt, hk); struct rbtree_x_part *ct = rbtx_partition_of_ix(xt, cix); if (!t) t = ct; offset = hk % xt->cachesz; v_cached = t->cache[offset]; __warnx(TIRPC_DEBUG_FLAG_RBTREE, "rbtree_x_cached_insert: cix %d ct %p t %p inserting %p " "(%s hk %" PRIx64 " slot/offset %d) flags %d", cix, ct, t, nk, (v_cached) ? "rbt" : "cache", hk, offset, xt->flags); if (xt->flags & RBT_X_FLAG_CACHE_WT) { if (!v_cached) { nv = t->cache[offset] = nk; } else { nv = opr_rbtree_insert(&t->t, nk); if (!nv) nv = nk; } } else { /* RBT_X_FLAG_CACHE_RT */ nv = v_cached = t->cache[offset] = nk; (void)opr_rbtree_insert(&t->t, nk); } return (nv); } static inline void rbtree_x_cached_remove(struct rbtree_x *xt, struct rbtree_x_part *t, struct opr_rbtree_node *nk, uint64_t hk) { struct opr_rbtree_node *v_cached; uint32_t offset; int cix = rbtx_idx_of_scalar(xt, hk); struct rbtree_x_part *ct = rbtx_partition_of_ix(xt, cix); if (!t) t = ct; offset = hk % xt->cachesz; v_cached = t->cache[offset]; __warnx(TIRPC_DEBUG_FLAG_RBTREE, "rbtree_x_cached_remove: cix %d ct %p t %p removing %p " "(%s hk %" PRIx64 " slot/offset %d) flags %d", cix, ct, t, nk, (v_cached) ? "cache" : "rbt", hk, offset, xt->flags); if (xt->flags & RBT_X_FLAG_CACHE_WT) { if (v_cached && (t->t.cmpf(nk, v_cached) == 0)) t->cache[offset] = NULL; else return (opr_rbtree_remove(&t->t, nk)); } else { /* RBT_X_FLAG_CACHE_RT */ if (v_cached && (t->t.cmpf(nk, v_cached) == 0)) t->cache[offset] = NULL; return (opr_rbtree_remove(&t->t, nk)); } } #endif /* _RBTREE_X_H */ ntirpc-1.3.1/ntirpc/misc/socket.h000066400000000000000000000054371261345040100167130ustar00rootroot00000000000000/*- * Copyright (c) 1982, 1985, 1986, 1988, 1993, 1994 * The Regents of the University of California. 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. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)socket.h 8.4 (Berkeley) 2/21/94 * $FreeBSD: stable/10/sys/sys/socket.h 254925 2013-08-26 18:16:05Z jhb $ */ #ifndef MISC_SYS_SOCKET_H #define MISC_SYS_SOCKET_H #include #if defined(__linux__) /* * While we may have more groups than this, the cmsgcred struct must * be able to fit in an mbuf and we have historically supported a * maximum of 16 groups. */ #define CMGROUP_MAX 16 /* * Credentials structure, used to verify the identity of a peer * process that has sent us a message. This is allocated by the * peer process but filled in by the kernel. This prevents the * peer from lying about its identity. (Note that cmcred_groups[0] * is the effective GID.) */ struct cmsgcred { pid_t cmcred_pid; /* PID of sending process */ uid_t cmcred_uid; /* real UID of sending process */ uid_t cmcred_euid; /* effective UID of sending process */ gid_t cmcred_gid; /* real GID of sending process */ short cmcred_ngroups; /* number or groups */ gid_t cmcred_groups[CMGROUP_MAX]; /* groups */ }; #endif /* __linux__ */ #endif /* MISC_SYS_SOCKET_H */ ntirpc-1.3.1/ntirpc/misc/stdint.h000066400000000000000000000164411261345040100167250ustar00rootroot00000000000000/* ISO C9x compliant stdint.h for Microsoft Visual Studio * Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 * * Copyright (c) 2006-2008 Alexander Chemeris * * 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. The name of the author may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. */ #ifdef _MSC_VER #ifndef _MSC_STDINT_H_ #define _MSC_STDINT_H_ #if _MSC_VER > 1000 #pragma once #endif #include /* For Visual Studio 6 in C++ mode and for many Visual Studio versions when * compiling for ARM we should wrap include with 'extern "C++" {}' * or compiler give many errors like this: * error C2733: second C linkage of overloaded function 'wmemchr' not allowed */ #ifdef __cplusplus extern "C" { #endif #include #ifdef __cplusplus } #endif /* Define _W64 macros to mark types changing their size, like intptr_t. */ #ifndef _W64 #if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 #define _W64 __w64 #else #define _W64 #endif #endif /* 7.18.1 Integer types */ /* 7.18.1.1 Exact-width integer types */ /* Visual Studio 6 and Embedded Visual C++ 4 doesn't * realize that, e.g. char has the same size as __int8 * so we give up on __intX for them. */ #if (_MSC_VER < 1300) typedef signed char int8_t; typedef signed short int16_t; typedef signed int int32_t; typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #else typedef signed __int8 int8_t; typedef signed __int16 int16_t; typedef signed __int32 int32_t; typedef unsigned __int8 uint8_t; typedef unsigned __int16 uint16_t; typedef unsigned __int32 uint32_t; #endif typedef signed __int64 int64_t; typedef unsigned __int64 uint64_t; /* 7.18.1.2 Minimum-width integer types */ typedef int8_t int_least8_t; typedef int16_t int_least16_t; typedef int32_t int_least32_t; typedef int64_t int_least64_t; typedef uint8_t uint_least8_t; typedef uint16_t uint_least16_t; typedef uint32_t uint_least32_t; typedef uint64_t uint_least64_t; /* 7.18.1.3 Fastest minimum-width integer types */ typedef int8_t int_fast8_t; typedef int16_t int_fast16_t; typedef int32_t int_fast32_t; typedef int64_t int_fast64_t; typedef uint8_t uint_fast8_t; typedef uint16_t uint_fast16_t; typedef uint32_t uint_fast32_t; typedef uint64_t uint_fast64_t; /* 7.18.1.4 Integer types capable of holding object pointers */ #ifdef _WIN64 typedef signed __int64 intptr_t; typedef unsigned __int64 uintptr_t; #else /*_WIN64 */ typedef _W64 signed int intptr_t; typedef _W64 unsigned int uintptr_t; #endif /* _WIN64 */ /* 7.18.1.5 Greatest-width integer types */ typedef int64_t intmax_t; typedef uint64_t uintmax_t; /* 7.18.2 Limits of specified-width integer types */ #if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) /* See footnote 220 at page 257 and footnote 221 at page 259 */ /* 7.18.2.1 Limits of exact-width integer types */ #define INT8_MIN ((int8_t)_I8_MIN) #define INT8_MAX _I8_MAX #define INT16_MIN ((int16_t)_I16_MIN) #define INT16_MAX _I16_MAX #define INT32_MIN ((int32_t)_I32_MIN) #define INT32_MAX _I32_MAX #define INT64_MIN ((int64_t)_I64_MIN) #define INT64_MAX _I64_MAX #define UINT8_MAX _UI8_MAX #define UINT16_MAX _UI16_MAX #define UINT32_MAX _UI32_MAX #define UINT64_MAX _UI64_MAX /* 7.18.2.2 Limits of minimum-width integer types */ #define INT_LEAST8_MIN INT8_MIN #define INT_LEAST8_MAX INT8_MAX #define INT_LEAST16_MIN INT16_MIN #define INT_LEAST16_MAX INT16_MAX #define INT_LEAST32_MIN INT32_MIN #define INT_LEAST32_MAX INT32_MAX #define INT_LEAST64_MIN INT64_MIN #define INT_LEAST64_MAX INT64_MAX #define UINT_LEAST8_MAX UINT8_MAX #define UINT_LEAST16_MAX UINT16_MAX #define UINT_LEAST32_MAX UINT32_MAX #define UINT_LEAST64_MAX UINT64_MAX /* 7.18.2.3 Limits of fastest minimum-width integer types */ #define INT_FAST8_MIN INT8_MIN #define INT_FAST8_MAX INT8_MAX #define INT_FAST16_MIN INT16_MIN #define INT_FAST16_MAX INT16_MAX #define INT_FAST32_MIN INT32_MIN #define INT_FAST32_MAX INT32_MAX #define INT_FAST64_MIN INT64_MIN #define INT_FAST64_MAX INT64_MAX #define UINT_FAST8_MAX UINT8_MAX #define UINT_FAST16_MAX UINT16_MAX #define UINT_FAST32_MAX UINT32_MAX #define UINT_FAST64_MAX UINT64_MAX /* 7.18.2.4 Limits of integer types capable of holding object pointers */ #ifdef _WIN64 #define INTPTR_MIN INT64_MIN #define INTPTR_MAX INT64_MAX #define UINTPTR_MAX UINT64_MAX #else /* _WIN64 */ #define INTPTR_MIN INT32_MIN #define INTPTR_MAX INT32_MAX #define UINTPTR_MAX UINT32_MAX #endif /* _WIN64 */ /* 7.18.2.5 Limits of greatest-width integer types */ #define INTMAX_MIN INT64_MIN #define INTMAX_MAX INT64_MAX #define UINTMAX_MAX UINT64_MAX /* 7.18.3 Limits of other integer types */ #ifdef _WIN64 #define PTRDIFF_MIN _I64_MIN #define PTRDIFF_MAX _I64_MAX #else /* _WIN64 */ #define PTRDIFF_MIN _I32_MIN #define PTRDIFF_MAX _I32_MAX #endif /* _WIN64 */ #define SIG_ATOMIC_MIN INT_MIN #define SIG_ATOMIC_MAX INT_MAX #ifndef SIZE_MAX #ifdef _WIN64 #define SIZE_MAX _UI64_MAX #else /* _WIN64 */ #define SIZE_MAX _UI32_MAX #endif /* _WIN64 */ #endif /* SIZE_MAX */ /* WCHAR_MIN and WCHAR_MAX are also defined in */ #ifndef WCHAR_MIN #define WCHAR_MIN 0 #endif /* WCHAR_MIN */ #ifndef WCHAR_MAX #define WCHAR_MAX _UI16_MAX #endif /* WCHAR_MAX */ #define WINT_MIN 0 #define WINT_MAX _UI16_MAX #endif /* __STDC_LIMIT_MACROS */ /* 7.18.4 Limits of other integer types */ #if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) /* See footnote 224 at page 260 */ /* 7.18.4.1 Macros for minimum-width integer constants */ #define INT8_C(val) val##i8 #define INT16_C(val) val##i16 #define INT32_C(val) val##i32 #define INT64_C(val) val##i64 #define UINT8_C(val) val##ui8 #define UINT16_C(val) val##ui16 #define UINT32_C(val) val##ui32 #define UINT64_C(val) val##ui64 /* 7.18.4.2 Macros for greatest-width integer constants */ #define INTMAX_C INT64_C #define UINTMAX_C UINT64_C #endif /* __STDC_CONSTANT_MACROS */ #endif /* _MSC_STDINT_H_ */ #endif /* _MSC_VER */ ntirpc-1.3.1/ntirpc/misc/stdio.h000066400000000000000000000016441261345040100165410ustar00rootroot00000000000000 #ifndef NTIRPC_STDIO_H #define NTIRPC_STDIO_H #if defined(__MINGW32__) /* XXX fix -- another attraction MSVC */ #undef fprintf #undef printf #undef sprintf #undef vfprintf #undef vprintf #undef fscanf #undef scanf #undef sscanf #undef fclose #undef fflush #undef fgetc #undef fgetpos #undef fgets #undef fopen #undef fputc #undef fputs #undef fread #undef freopen #undef fsetpos #undef fseek #undef fseeko #undef ftell #undef ftello #undef fwrite #undef getc #undef getchar #undef gets #undef popen #undef pclose #undef putc #undef putchar #undef puts #undef remove #undef rename #undef unlink #undef rewind #undef tmpfile #undef tmpnam #undef ungetc #undef fwscanf #undef wscanf #undef fwprintf #undef wprintf #undef vfwprintf #undef vwprintf #undef fgetwc #undef fputwc #undef getwc #undef getwchar #undef putwc #undef putwchar #undef ungetwc #undef fgetws #undef fputws #endif #include #endif /* NTIRPC_STDIO_H */ ntirpc-1.3.1/ntirpc/misc/thrdpool.h000066400000000000000000000044741261345040100172560ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef THRDPOOL_H #define THRDPOOL_H #include #include #define THRD_FLAG_NONE 0x0000 #define THRD_FLAG_SHUTDOWN 0x0001 #define THRD_FLAG_ACTIVE 0x0002 struct work { TAILQ_ENTRY(work) tailq; void (*func) (void*); void *arg; }; struct thrdpool; struct thrd { TAILQ_ENTRY(thrd) tailq; struct thrd_context { pthread_t id; struct wait_entry we; struct work *work; } ctx; struct thrdpool *pool; bool idle; }; struct thrdpool_params { int32_t thrd_max; int32_t thrd_min; }; struct thrdpool { char *name; uint32_t flags; struct thrdpool_params params; pthread_attr_t attr; struct wait_entry we; TAILQ_HEAD(idle_tailq, thrd) idle_q; TAILQ_HEAD(work_tailq, work) work_q; int32_t n_idle; int32_t n_threads; }; typedef void (*thrd_func_t) (void *); int thrdpool_init(struct thrdpool *, const char *, struct thrdpool_params *); int thrdpool_submit_work(struct thrdpool *, thrd_func_t, void *); int thrdpool_shutdown(struct thrdpool *); #endif /* THRDPOOL_H */ ntirpc-1.3.1/ntirpc/misc/timespec.h000066400000000000000000000055501261345040100172300ustar00rootroot00000000000000/*- * Copyright (c) 1982, 1986, 1993 * The Regents of the University of California. 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. * 4. Neither the name of the University 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 REGENTS 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 REGENTS 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. * * @(#)time.h 8.5 (Berkeley) 5/4/95 * $FreeBSD: head/sys/sys/time.h 224732 2011-08-09 14:06:50Z jonathan $ */ #ifndef TIMESPEC_H /* Operations on timespecs */ #define timespecclear(tvp) ((tvp)->tv_sec = (tvp)->tv_nsec = 0) #define timespecisset(tvp) ((tvp)->tv_sec || (tvp)->tv_nsec) #define timespeccmp(tvp, uvp, cmp) \ (((tvp)->tv_sec == (uvp)->tv_sec) ? \ ((tvp)->tv_nsec cmp(uvp)->tv_nsec) : \ ((tvp)->tv_sec cmp(uvp)->tv_sec)) #define timespecadd(vvp, uvp) \ do { \ (vvp)->tv_sec += (uvp)->tv_sec; \ (vvp)->tv_nsec += (uvp)->tv_nsec; \ if ((vvp)->tv_nsec >= 1000000000) { \ (vvp)->tv_sec++; \ (vvp)->tv_nsec -= 1000000000; \ } \ } while (0) #define timespec_adds(vvp, s) \ do { \ (vvp)->tv_sec += s; \ } while (0) #define timespec_addms(vvp, ms) \ do { \ (vvp)->tv_sec += (ms) / 1000; \ (vvp)->tv_nsec += (((ms) % 1000) * 1000000); \ if ((vvp)->tv_nsec >= 1000000000) { \ (vvp)->tv_sec++; \ (vvp)->tv_nsec -= 1000000000; \ } \ } while (0) #define timespecsub(vvp, uvp) \ do { \ (vvp)->tv_sec -= (uvp)->tv_sec; \ (vvp)->tv_nsec -= (uvp)->tv_nsec; \ if ((vvp)->tv_nsec < 0) { \ (vvp)->tv_sec--; \ (vvp)->tv_nsec += 1000000000; \ } \ } while (0) #endif /* TIMESPEC_H */ ntirpc-1.3.1/ntirpc/misc/wait_queue.h000066400000000000000000000046361261345040100175730ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef WAIT_QUEUE_H #define WAIT_QUEUE_H #include #include #include #include #include #include typedef struct wait_entry { mutex_t mtx; cond_t cv; } wait_entry_t; #define Wqe_LFlag_None 0x0000 #define Wqe_LFlag_WaitSync 0x0001 #define Wqe_LFlag_SyncDone 0x0002 /* thread wait queue */ typedef struct wait_q_entry { uint32_t flags; uint32_t waiters; wait_entry_t lwe; /* left */ wait_entry_t rwe; /* right */ TAILQ_HEAD(we_tailq, waiter) waitq; } wait_q_entry_t; static inline void init_wait_entry(wait_entry_t *we) { mutex_init(&we->mtx, NULL); pthread_cond_init(&we->cv, NULL); } static inline void destroy_wait_entry(wait_entry_t *we) { mutex_destroy(&we->mtx); cond_destroy(&we->cv); } static inline void init_wait_q_entry(wait_q_entry_t *wqe) { TAILQ_INIT(&wqe->waitq); init_wait_entry(&wqe->lwe); init_wait_entry(&wqe->rwe); } static inline void thread_delay_ms(unsigned long ms) { struct timespec then = { .tv_sec = ms / 1000, .tv_nsec = ms % 1000000UL }; nanosleep(&then, NULL); } #endif /* WAIT_QUEUE_H */ ntirpc-1.3.1/ntirpc/misc/winpthreads.h000066400000000000000000001253071261345040100177520ustar00rootroot00000000000000/* * Posix Threads library for Microsoft Windows * * Use at own risk, there is no implied warranty to this code. * It uses undocumented features of Microsoft Windows that can change * at any time in the future. * * (C) 2010 Lockless Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of Lockless Inc. nor the names of its contributors may be * used to endorse or promote products derived from this software without * specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AN ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ /* * You may want to use the MingW64 winpthreads library instead. * It is based on this, but adds error checking. */ /* * Version 1.0.1 Released 2 Feb 2012 * Fixes pthread_barrier_destroy() to wait for threads to exit the barrier. */ #ifndef WIN_PTHREADS #define WIN_PTHREADS #include #include #include #include #include #if !defined(__MINGW32__) /* XXX 64? */ #define ETIMEDOUT 110 #define ENOTSUP 134 #endif #define PTHREAD_CANCEL_DISABLE 0 #define PTHREAD_CANCEL_ENABLE 0x01 #define PTHREAD_CANCEL_DEFERRED 0 #define PTHREAD_CANCEL_ASYNCHRONOUS 0x02 #define PTHREAD_CREATE_JOINABLE 0 #define PTHREAD_CREATE_DETACHED 0x04 #define PTHREAD_EXPLICT_SCHED 0 #define PTHREAD_INHERIT_SCHED 0x08 #define PTHREAD_SCOPE_PROCESS 0 #define PTHREAD_SCOPE_SYSTEM 0x10 #define PTHREAD_DEFAULT_ATTR (PTHREAD_CANCEL_ENABLE) #define PTHREAD_CANCELED ((void *) 0xDEADBEEF) #define PTHREAD_ONCE_INIT 0 #define PTHREAD_MUTEX_INITIALIZER {(void *) -1, -1, 0, 0, 0, 0} #define PTHREAD_RWLOCK_INITIALIZER {0} #define PTHREAD_COND_INITIALIZER {0} #define PTHREAD_BARRIER_INITIALIZER \ {0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER} #define PTHREAD_SPINLOCK_INITIALIZER 0 #define PTHREAD_DESTRUCTOR_ITERATIONS 256 #define PTHREAD_KEYS_MAX (1<<20) #define PTHREAD_MUTEX_NORMAL 0 #define PTHREAD_MUTEX_ERRORCHECK 1 #define PTHREAD_MUTEX_RECURSIVE 2 #define PTHREAD_MUTEX_DEFAULT 3 #define PTHREAD_MUTEX_SHARED 4 #define PTHREAD_MUTEX_PRIVATE 0 #define PTHREAD_PRIO_NONE 0 #define PTHREAD_PRIO_INHERIT 8 #define PTHREAD_PRIO_PROTECT 16 #define PTHREAD_PRIO_MULT 32 #define PTHREAD_PROCESS_SHARED 0 #define PTHREAD_PROCESS_PRIVATE 1 #define PTHREAD_BARRIER_SERIAL_THREAD 1 #if !defined(__MINGW32__) /* Windows doesn't have this, so declare it ourselves. */ struct timespec { /* long long in windows is the same as long in unix for 64bit */ long long tv_sec; long long tv_nsec; }; #endif typedef struct _pthread_cleanup _pthread_cleanup; struct _pthread_cleanup { void (*func) (void *); void *arg; _pthread_cleanup *next; }; struct _pthread_v { void *ret_arg; void *(*func) (void *); _pthread_cleanup *clean; uintptr_t h; int cancelled; unsigned p_state; int keymax; void **keyval; jmp_buf jb; }; typedef struct _pthread_v *pthread_t; #if defined(__MINGW32__) #include typedef struct _RTL_CONDITION_VARIABLE { PVOID Ptr; } CONDITION_VARIABLE, *PCONDITION_VARIABLE; typedef struct _RTL_SRWLOCK { PVOID Ptr; } SRWLOCK, *PSRWLOCK; #endif typedef struct pthread_barrier_t pthread_barrier_t; struct pthread_barrier_t { int count; int total; CRITICAL_SECTION m; CONDITION_VARIABLE cv; }; typedef struct pthread_attr_t pthread_attr_t; struct pthread_attr_t { unsigned p_state; void *stack; size_t s_size; }; typedef long pthread_once_t; typedef unsigned pthread_mutexattr_t; typedef SRWLOCK pthread_rwlock_t; typedef CRITICAL_SECTION pthread_mutex_t; typedef unsigned pthread_key_t; typedef void *pthread_barrierattr_t; typedef long pthread_spinlock_t; typedef int pthread_condattr_t; typedef CONDITION_VARIABLE pthread_cond_t; typedef int pthread_rwlockattr_t; volatile long _pthread_cancelling; int _pthread_concur; /* Will default to zero as needed */ pthread_once_t _pthread_tls_once; DWORD _pthread_tls; /* Note initializer is zero, so this works */ pthread_rwlock_t _pthread_key_lock; long _pthread_key_max; long _pthread_key_sch; void (**_pthread_key_dest) (void *); #define pthread_cleanup_push(F, A) \ do { \ const _pthread_cleanup _pthread_cup = {(F), (A), \ pthread_self()->clean}; \ _ReadWriteBarrier(); \ pthread_self()->clean = (_pthread_cleanup *) &_pthread_cup; \ _ReadWriteBarrier(); \ } while (0) #define pthread_cleanup_pop(E) \ do { \ _pthread_cleanup *_pthread_cup = pthread_self()->clean; \ if (_pthread_cup) { \ _pthread_cup->func(_pthread_cup->arg); \ pthread_self()->clean = _pthread_cup->next; \ } \ } while (0) static void _pthread_once_cleanup(void *arg) { pthread_once_t *o = (pthread_once_t *) arg; *o = 0; } static pthread_t pthread_self(void); static int pthread_once(pthread_once_t *o, void (*func) (void)) { long state = *o; _ReadWriteBarrier(); while (state != 1) { if (!state) { if (!_InterlockedCompareExchange(o, 2, 0)) { /* Success */ pthread_cleanup_push(_pthread_once_cleanup, o); func(); pthread_cleanup_pop(0); /* Mark as done */ *o = 1; return 0; } } YieldProcessor(); _ReadWriteBarrier(); state = *o; } /* Done */ return 0; } static int _pthread_once_raw(pthread_once_t *o, void (*func) (void)) { long state = *o; _ReadWriteBarrier(); while (state != 1) { if (!state) { if (!_InterlockedCompareExchange(o, 2, 0)) { /* Success */ func(); /* Mark as done */ *o = 1; return 0; } } YieldProcessor(); _ReadWriteBarrier(); state = *o; } /* Done */ return 0; } static int pthread_mutex_lock(pthread_mutex_t *m) { EnterCriticalSection(m); return 0; } static int pthread_mutex_unlock(pthread_mutex_t *m) { LeaveCriticalSection(m); return 0; } static int pthread_mutex_trylock(pthread_mutex_t *m) { return TryEnterCriticalSection(m) ? 0 : EBUSY; } static int pthread_mutex_init(pthread_mutex_t *m, pthread_mutexattr_t *a) { (void)a; InitializeCriticalSection(m); return 0; } static int pthread_mutex_destroy(pthread_mutex_t *m) { DeleteCriticalSection(m); return 0; } #define pthread_mutex_getprioceiling(M, P) ENOTSUP #define pthread_mutex_setprioceiling(M, P) ENOTSUP static int pthread_equal(pthread_t t1, pthread_t t2) { return t1 == t2; } static void pthread_testcancel(void); static int pthread_rwlock_init(pthread_rwlock_t *l, pthread_rwlockattr_t *a) { (void)a; InitializeSRWLock(l); return 0; } static int pthread_rwlock_destroy(pthread_rwlock_t *l) { (void)*l; return 0; } static int pthread_rwlock_rdlock(pthread_rwlock_t *l) { pthread_testcancel(); AcquireSRWLockShared(l); return 0; } static int pthread_rwlock_wrlock(pthread_rwlock_t *l) { pthread_testcancel(); AcquireSRWLockExclusive(l); return 0; } static int pthread_rwlock_unlock(pthread_rwlock_t *l) { void *state = *(void **)l; if (state == (void *)1) { /* Known to be an exclusive lock */ ReleaseSRWLockExclusive(l); } else { /* A shared unlock will work */ ReleaseSRWLockShared(l); } return 0; } static void pthread_tls_init(void) { _pthread_tls = TlsAlloc(); /* Cannot continue if out of indexes */ if (_pthread_tls == TLS_OUT_OF_INDEXES) abort(); } static void _pthread_cleanup_dest(pthread_t t) { int i, j; for (j = 0; j < PTHREAD_DESTRUCTOR_ITERATIONS; j++) { int flag = 0; for (i = 0; i < t->keymax; i++) { void *val = t->keyval[i]; if (val) { pthread_rwlock_rdlock(&_pthread_key_lock); if ((uintptr_t) _pthread_key_dest[i] > 1) { /* Call destructor */ t->keyval[i] = NULL; _pthread_key_dest[i] (val); flag = 1; } pthread_rwlock_unlock(&_pthread_key_lock); } } /* Nothing to do? */ if (!flag) return; } } static pthread_t pthread_self(void) { pthread_t t; _pthread_once_raw(&_pthread_tls_once, pthread_tls_init); t = TlsGetValue(_pthread_tls); /* Main thread? */ if (!t) { t = malloc(sizeof(struct _pthread_v)); /* If cannot initialize main thread, then the only thing we * can do is abort */ if (!t) abort(); t->ret_arg = NULL; t->func = NULL; t->clean = NULL; t->cancelled = 0; t->p_state = PTHREAD_DEFAULT_ATTR; t->keymax = 0; t->keyval = NULL; t->h = (uintptr_t) GetCurrentThread(); /* Save for later */ TlsSetValue(_pthread_tls, t); if (setjmp(t->jb)) { /* Make sure we free ourselves if we are detached */ if (!t->h) free(t); /* Time to die */ _endthreadex(0); } } return t; } static int pthread_rwlock_tryrdlock(pthread_rwlock_t *l) { /* Get the current state of the lock */ void *state = *(void **)l; if (!state) { /* Unlocked to locked */ if (!_InterlockedCompareExchangePointer ((void *)l, (void *)0x11, NULL)) return 0; return EBUSY; } /* A single writer exists */ if (state == (void *)1) return EBUSY; /* Multiple writers exist? */ if ((uintptr_t) state & 14) return EBUSY; if (_InterlockedCompareExchangePointer ((void *)l, (void *)((uintptr_t) state + 16), state) == state) return 0; return EBUSY; } static int pthread_rwlock_trywrlock(pthread_rwlock_t *l) { /* Try to grab lock if it has no users */ if (!_InterlockedCompareExchangePointer((void *)l, (void *)1, NULL)) return 0; return EBUSY; } static unsigned long long _pthread_time_in_ms(void) { struct __timeb64 tb; _ftime64(&tb); return tb.time * 1000 + tb.millitm; } static unsigned long long _pthread_time_in_ms_from_timespec(const struct timespec *ts) { unsigned long long t = ts->tv_sec * 1000; t += ts->tv_nsec / 1000000; return t; } static unsigned long long _pthread_rel_time_in_ms(const struct timespec *ts) { unsigned long long t1 = _pthread_time_in_ms_from_timespec(ts); unsigned long long t2 = _pthread_time_in_ms(); /* Prevent underflow */ if (t1 < t2) return 0; return t1 - t2; } static int pthread_rwlock_timedrdlock(pthread_rwlock_t *l, const struct timespec *ts) { unsigned long long ct = _pthread_time_in_ms(); unsigned long long t = _pthread_time_in_ms_from_timespec(ts); pthread_testcancel(); /* Use a busy-loop */ while (1) { /* Try to grab lock */ if (!pthread_rwlock_tryrdlock(l)) return 0; /* Get current time */ ct = _pthread_time_in_ms(); /* Have we waited long enough? */ if (ct > t) return ETIMEDOUT; } } static int pthread_rwlock_timedwrlock(pthread_rwlock_t *l, const struct timespec *ts) { unsigned long long ct = _pthread_time_in_ms(); unsigned long long t = _pthread_time_in_ms_from_timespec(ts); pthread_testcancel(); /* Use a busy-loop */ while (1) { /* Try to grab lock */ if (!pthread_rwlock_trywrlock(l)) return 0; /* Get current time */ ct = _pthread_time_in_ms(); /* Have we waited long enough? */ if (ct > t) return ETIMEDOUT; } } static int pthread_get_concurrency(int *val) { *val = _pthread_concur; return 0; } static int pthread_set_concurrency(int val) { _pthread_concur = val; return 0; } #define pthread_getschedparam(T, P, S) ENOTSUP #define pthread_setschedparam(T, P, S) ENOTSUP #define pthread_getcpuclockid(T, C) ENOTSUP static int pthread_exit(void *res) { pthread_t t = pthread_self(); t->ret_arg = res; _pthread_cleanup_dest(t); longjmp(t->jb, 1); } static void _pthread_invoke_cancel(void) { _pthread_cleanup *pcup; _InterlockedDecrement(&_pthread_cancelling); /* Call cancel queue */ for (pcup = pthread_self()->clean; pcup; pcup = pcup->next) { /* suppress block warning */ pcup->func(pcup->arg); } pthread_exit(PTHREAD_CANCELED); } static void pthread_testcancel(void) { if (_pthread_cancelling) { pthread_t t = pthread_self(); if (t->cancelled && (t->p_state & PTHREAD_CANCEL_ENABLE)) _pthread_invoke_cancel(); } } static int pthread_cancel(pthread_t t) { if (t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS) { /* Dangerous asynchronous cancelling */ CONTEXT ctxt; /* Already done? */ if (t->cancelled) return ESRCH; ctxt.ContextFlags = CONTEXT_CONTROL; SuspendThread((HANDLE) t->h); GetThreadContext((HANDLE) t->h, &ctxt); #ifdef _M_X64 ctxt.Rip = (uintptr_t) _pthread_invoke_cancel; #else ctxt.Eip = (uintptr_t) _pthread_invoke_cancel; #endif SetThreadContext((HANDLE) t->h, &ctxt); /* Also try deferred Cancelling */ t->cancelled = 1; /* Notify everyone to look */ _InterlockedIncrement(&_pthread_cancelling); ResumeThread((HANDLE) t->h); } else { /* Safe deferred Cancelling */ t->cancelled = 1; /* Notify everyone to look */ _InterlockedIncrement(&_pthread_cancelling); } return 0; } static unsigned _pthread_get_state(pthread_attr_t *attr, unsigned flag) { return attr->p_state & flag; } static int _pthread_set_state(pthread_attr_t *attr, unsigned flag, unsigned val) { if (~flag & val) return EINVAL; attr->p_state &= ~flag; attr->p_state |= val; return 0; } static int pthread_attr_init(pthread_attr_t *attr) { attr->p_state = PTHREAD_DEFAULT_ATTR; attr->stack = NULL; attr->s_size = 0; return 0; } static int pthread_attr_destroy(pthread_attr_t *attr) { /* No need to do anything */ return 0; } static int pthread_attr_setdetachstate(pthread_attr_t *a, int flag) { return _pthread_set_state(a, PTHREAD_CREATE_DETACHED, flag); } static int pthread_attr_getdetachstate(pthread_attr_t *a, int *flag) { *flag = _pthread_get_state(a, PTHREAD_CREATE_DETACHED); return 0; } static int pthread_attr_setinheritsched(pthread_attr_t *a, int flag) { return _pthread_set_state(a, PTHREAD_INHERIT_SCHED, flag); } static int pthread_attr_getinheritsched(pthread_attr_t *a, int *flag) { *flag = _pthread_get_state(a, PTHREAD_INHERIT_SCHED); return 0; } static int pthread_attr_setscope(pthread_attr_t *a, int flag) { return _pthread_set_state(a, PTHREAD_SCOPE_SYSTEM, flag); } static int pthread_attr_getscope(pthread_attr_t *a, int *flag) { *flag = _pthread_get_state(a, PTHREAD_SCOPE_SYSTEM); return 0; } static int pthread_attr_getstackaddr(pthread_attr_t *attr, void **stack) { *stack = attr->stack; return 0; } static int pthread_attr_setstackaddr(pthread_attr_t *attr, void *stack) { attr->stack = stack; return 0; } static int pthread_attr_getstacksize(pthread_attr_t *attr, size_t *size) { *size = attr->s_size; return 0; } static int pthread_attr_setstacksize(pthread_attr_t *attr, size_t size) { attr->s_size = size; return 0; } #define pthread_attr_getguardsize(A, S) ENOTSUP #define pthread_attr_setgaurdsize(A, S) ENOTSUP #define pthread_attr_getschedparam(A, S) ENOTSUP #define pthread_attr_setschedparam(A, S) ENOTSUP #define pthread_attr_getschedpolicy(A, S) ENOTSUP #define pthread_attr_setschedpolicy(A, S) ENOTSUP static int pthread_setcancelstate(int state, int *oldstate) { pthread_t t = pthread_self(); if ((state & PTHREAD_CANCEL_ENABLE) != state) return EINVAL; if (oldstate) *oldstate = t->p_state & PTHREAD_CANCEL_ENABLE; t->p_state &= ~PTHREAD_CANCEL_ENABLE; t->p_state |= state; return 0; } static int pthread_setcanceltype(int type, int *oldtype) { pthread_t t = pthread_self(); if ((type & PTHREAD_CANCEL_ASYNCHRONOUS) != type) return EINVAL; if (oldtype) *oldtype = t->p_state & PTHREAD_CANCEL_ASYNCHRONOUS; t->p_state &= ~PTHREAD_CANCEL_ASYNCHRONOUS; t->p_state |= type; return 0; } static unsigned int pthread_create_wrapper(void *args) { struct _pthread_v *tv = args; int i, j; _pthread_once_raw(&_pthread_tls_once, pthread_tls_init); TlsSetValue(_pthread_tls, tv); if (!setjmp(tv->jb)) { /* Call function and save return value */ tv->ret_arg = tv->func(tv->ret_arg); /* Clean up destructors */ _pthread_cleanup_dest(tv); } /* If we exit too early, then we can race with create */ while ((HANDLE) tv->h == (HANDLE) - 1) { YieldProcessor(); _ReadWriteBarrier(); } /* Make sure we free ourselves if we are detached */ if (!tv->h) free(tv); return 0; } static int pthread_create(pthread_t *th, pthread_attr_t *attr, void *(*func) (void *), void *arg) { struct _pthread_v *tv = malloc(sizeof(struct _pthread_v)); unsigned ssize = 0; if (!tv) return 1; *th = tv; /* Save data in pthread_t */ tv->ret_arg = arg; tv->func = func; tv->clean = NULL; tv->cancelled = 0; tv->p_state = PTHREAD_DEFAULT_ATTR; tv->keymax = 0; tv->keyval = NULL; tv->h = (uintptr_t) -1; if (attr) { tv->p_state = attr->p_state; ssize = attr->s_size; } /* Make sure tv->h has value of -1 */ _ReadWriteBarrier(); tv->h = _beginthreadex(NULL, ssize, pthread_create_wrapper, tv, 0, NULL); /* Failed */ if (!tv->h) return 1; if (tv->p_state & PTHREAD_CREATE_DETACHED) { CloseHandle((HANDLE) tv->h); _ReadWriteBarrier(); tv->h = 0; } return 0; } static int pthread_join(pthread_t t, void **res) { struct _pthread_v *tv = t; pthread_testcancel(); WaitForSingleObject((HANDLE) tv->h, INFINITE); CloseHandle((HANDLE) tv->h); /* Obtain return value */ if (res) *res = tv->ret_arg; free(tv); return 0; } static int pthread_detach(pthread_t t) { struct _pthread_v *tv = t; /* * This can't race with thread exit because * our call would be undefined if called on a dead thread. */ CloseHandle((HANDLE) tv->h); _ReadWriteBarrier(); tv->h = 0; return 0; } static int pthread_mutexattr_init(pthread_mutexattr_t *a) { *a = 0; return 0; } static int pthread_mutexattr_destroy(pthread_mutexattr_t *a) { (void)a; return 0; } static int pthread_mutexattr_gettype(pthread_mutexattr_t *a, int *type) { *type = *a & 3; return 0; } static int pthread_mutexattr_settype(pthread_mutexattr_t *a, int type) { if ((unsigned)type > 3) return EINVAL; *a &= ~3; *a |= type; return 0; } static int pthread_mutexattr_getpshared(pthread_mutexattr_t *a, int *type) { *type = *a & 4; return 0; } static int pthread_mutexattr_setpshared(pthread_mutexattr_t *a, int type) { if ((type & 4) != type) return EINVAL; *a &= ~4; *a |= type; return 0; } static int pthread_mutexattr_getprotocol(pthread_mutexattr_t *a, int *type) { *type = *a & (8 + 16); return 0; } static int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int type) { if ((type & (8 + 16)) != 8 + 16) return EINVAL; *a &= ~(8 + 16); *a |= type; return 0; } static int pthread_mutexattr_getprioceiling(pthread_mutexattr_t *a, int *prio) { *prio = *a / PTHREAD_PRIO_MULT; return 0; } static int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *a, int prio) { *a &= (PTHREAD_PRIO_MULT - 1); *a += prio * PTHREAD_PRIO_MULT; return 0; } static int pthread_mutex_timedlock(pthread_mutex_t *m, struct timespec *ts) { unsigned long long t, ct; struct _pthread_crit_t { void *debug; LONG count; LONG r_count; HANDLE owner; HANDLE sem; ULONG_PTR spin; }; /* Try to lock it without waiting */ if (!pthread_mutex_trylock(m)) return 0; ct = _pthread_time_in_ms(); t = _pthread_time_in_ms_from_timespec(ts); while (1) { /* Have we waited long enough? */ if (ct > t) return ETIMEDOUT; /* Wait on semaphore within critical section */ WaitForSingleObject(((struct _pthread_crit_t *)m)->sem, t - ct); /* Try to grab lock */ if (!pthread_mutex_trylock(m)) return 0; /* Get current time */ ct = _pthread_time_in_ms(); } } #define _PTHREAD_BARRIER_FLAG (1<<30) static int pthread_barrier_destroy(pthread_barrier_t *b) { EnterCriticalSection(&b->m); while (b->total > _PTHREAD_BARRIER_FLAG) { /* Wait until everyone exits the barrier */ SleepConditionVariableCS(&b->cv, &b->m, INFINITE); } LeaveCriticalSection(&b->m); DeleteCriticalSection(&b->m); return 0; } static int pthread_barrier_init(pthread_barrier_t *b, void *attr, int count) { /* Ignore attr */ (void)attr; b->count = count; b->total = 0; InitializeCriticalSection(&b->m); InitializeConditionVariable(&b->cv); return 0; } static int pthread_barrier_wait(pthread_barrier_t *b) { EnterCriticalSection(&b->m); while (b->total > _PTHREAD_BARRIER_FLAG) { /* Wait until everyone exits the barrier */ SleepConditionVariableCS(&b->cv, &b->m, INFINITE); } /* Are we the first to enter? */ if (b->total == _PTHREAD_BARRIER_FLAG) b->total = 0; b->total++; if (b->total == b->count) { b->total += _PTHREAD_BARRIER_FLAG - 1; WakeAllConditionVariable(&b->cv); LeaveCriticalSection(&b->m); return 1; } else { while (b->total < _PTHREAD_BARRIER_FLAG) { /* Wait until enough threads enter the barrier */ SleepConditionVariableCS(&b->cv, &b->m, INFINITE); } b->total--; /* Get entering threads to wake up */ if (b->total == _PTHREAD_BARRIER_FLAG) WakeAllConditionVariable(&b->cv); LeaveCriticalSection(&b->m); return 0; } } static int pthread_barrierattr_init(void **attr) { *attr = NULL; return 0; } static int pthread_barrierattr_destroy(void **attr) { /* Ignore attr */ (void)attr; return 0; } static int pthread_barrierattr_setpshared(void **attr, int s) { *attr = (void *)(uintptr_t) s; return 0; } static int pthread_barrierattr_getpshared(void **attr, int *s) { *s = (int)(size_t) *attr; return 0; } static int pthread_key_create(pthread_key_t *key, void (*dest) (void *)) { int i; long nmax; void (**d) (void *); if (!key) return EINVAL; pthread_rwlock_wrlock(&_pthread_key_lock); for (i = _pthread_key_sch; i < _pthread_key_max; i++) { if (!_pthread_key_dest[i]) { *key = i; if (dest) _pthread_key_dest[i] = dest; else _pthread_key_dest[i] = (void (*)(void *))1; pthread_rwlock_unlock(&_pthread_key_lock); return 0; } } for (i = 0; i < _pthread_key_sch; i++) { if (!_pthread_key_dest[i]) { *key = i; if (dest) _pthread_key_dest[i] = dest; else _pthread_key_dest[i] = (void (*)(void *))1; pthread_rwlock_unlock(&_pthread_key_lock); return 0; } } if (!_pthread_key_max) _pthread_key_max = 1; if (_pthread_key_max == PTHREAD_KEYS_MAX) { pthread_rwlock_unlock(&_pthread_key_lock); return ENOMEM; } nmax = _pthread_key_max * 2; if (nmax > PTHREAD_KEYS_MAX) nmax = PTHREAD_KEYS_MAX; /* No spare room anywhere */ d = realloc(_pthread_key_dest, nmax * sizeof(*d)); if (!d) { pthread_rwlock_unlock(&_pthread_key_lock); return ENOMEM; } /* Clear new region */ memset((void *)&d[_pthread_key_max], 0, (nmax - _pthread_key_max) * sizeof(void *)); /* Use new region */ _pthread_key_dest = d; _pthread_key_sch = _pthread_key_max + 1; *key = _pthread_key_max; _pthread_key_max = nmax; if (dest) _pthread_key_dest[*key] = dest; else _pthread_key_dest[*key] = (void (*)(void *))1; pthread_rwlock_unlock(&_pthread_key_lock); return 0; } static int pthread_key_delete(pthread_key_t key) { if (key > _pthread_key_max) return EINVAL; if (!_pthread_key_dest) return EINVAL; pthread_rwlock_wrlock(&_pthread_key_lock); _pthread_key_dest[key] = NULL; /* Start next search from our location */ if (_pthread_key_sch > key) _pthread_key_sch = key; pthread_rwlock_unlock(&_pthread_key_lock); return 0; } static void * pthread_getspecific(pthread_key_t key) { pthread_t t = pthread_self(); if (key >= t->keymax) return NULL; return t->keyval[key]; } static int pthread_setspecific(pthread_key_t key, const void *value) { pthread_t t = pthread_self(); if (key > t->keymax) { int keymax = (key + 1) * 2; void **kv = realloc(t->keyval, keymax * sizeof(void *)); if (!kv) return ENOMEM; /* Clear new region */ memset(&kv[t->keymax], 0, (keymax - t->keymax) * sizeof(void *)); t->keyval = kv; t->keymax = keymax; } t->keyval[key] = (void *)value; return 0; } static int pthread_spin_init(pthread_spinlock_t *l, int pshared) { (void)pshared; *l = 0; return 0; } static int pthread_spin_destroy(pthread_spinlock_t *l) { (void)l; return 0; } /* No-fair spinlock due to lack of knowledge of thread number */ static int pthread_spin_lock(pthread_spinlock_t *l) { while (_InterlockedExchange(l, EBUSY)) { /* Don't lock the bus whilst waiting */ while (*l) { YieldProcessor(); /* Compiler barrier. Prevent caching of *l */ _ReadWriteBarrier(); } } return 0; } static int pthread_spin_trylock(pthread_spinlock_t *l) { return _InterlockedExchange(l, EBUSY); } static int pthread_spin_unlock(pthread_spinlock_t *l) { /* Compiler barrier. The store below acts with release symmantics */ _ReadWriteBarrier(); *l = 0; return 0; } static int pthread_cond_init(pthread_cond_t *c, pthread_condattr_t *a) { (void)a; InitializeConditionVariable(c); return 0; } static int pthread_cond_signal(pthread_cond_t *c) { WakeConditionVariable(c); return 0; } static int pthread_cond_broadcast(pthread_cond_t *c) { WakeAllConditionVariable(c); return 0; } static int pthread_cond_wait(pthread_cond_t *c, pthread_mutex_t *m) { pthread_testcancel(); SleepConditionVariableCS(c, m, INFINITE); return 0; } static int pthread_cond_destroy(pthread_cond_t *c) { (void)c; return 0; } static int pthread_cond_timedwait(pthread_cond_t *c, pthread_mutex_t *m, struct timespec *t) { unsigned long long tm = _pthread_rel_time_in_ms(t); pthread_testcancel(); if (!SleepConditionVariableCS(c, m, tm)) return ETIMEDOUT; /* We can have a spurious wakeup after the timeout */ if (!_pthread_rel_time_in_ms(t)) return ETIMEDOUT; return 0; } static int pthread_condattr_destroy(pthread_condattr_t *a) { (void)a; return 0; } #define pthread_condattr_getclock(A, C) ENOTSUP #define pthread_condattr_setclock(A, C) ENOTSUP static int pthread_condattr_init(pthread_condattr_t *a) { *a = 0; return 0; } static int pthread_condattr_getpshared(pthread_condattr_t *a, int *s) { *s = *a; return 0; } static int pthread_condattr_setpshared(pthread_condattr_t *a, int s) { *a = s; return 0; } static int pthread_rwlockattr_destroy(pthread_rwlockattr_t *a) { (void)a; return 0; } static int pthread_rwlockattr_init(pthread_rwlockattr_t *a) { *a = 0; } static int pthread_rwlockattr_getpshared(pthread_rwlockattr_t *a, int *s) { *s = *a; return 0; } static int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *a, int s) { *a = s; return 0; } /* No fork() in windows - so ignore this */ #define pthread_atfork(F1, F2, F3) 0 /* Windows has rudimentary signals support */ #define pthread_kill(T, S) 0 #define pthread_sigmask(H, S1, S2) 0 /* Wrap cancellation points -- seems incompatible with decls in stdio.h */ #define accept(...) (pthread_testcancel(), accept(__VA_ARGS__)) #define aio_suspend(...) (pthread_testcancel(), aio_suspend(__VA_ARGS__)) #define clock_nanosleep(...) \ (pthread_testcancel(), clock_nanosleep(__VA_ARGS__)) #define close(...) (pthread_testcancel(), close(__VA_ARGS__)) #define connect(...) (pthread_testcancel(), connect(__VA_ARGS__)) #define creat(...) (pthread_testcancel(), creat(__VA_ARGS__)) #define fcntl(...) (pthread_testcancel(), fcntl(__VA_ARGS__)) #define fdatasync(...) (pthread_testcancel(), fdatasync(__VA_ARGS__)) #define fsync(...) (pthread_testcancel(), fsync(__VA_ARGS__)) #define getmsg(...) (pthread_testcancel(), getmsg(__VA_ARGS__)) #define getpmsg(...) (pthread_testcancel(), getpmsg(__VA_ARGS__)) #define lockf(...) (pthread_testcancel(), lockf(__VA_ARGS__)) #define mg_receive(...) (pthread_testcancel(), mg_receive(__VA_ARGS__)) #define mg_send(...) (pthread_testcancel(), mg_send(__VA_ARGS__)) #define mg_timedreceive(...) \ (pthread_testcancel(), mg_timedreceive(__VA_ARGS__)) #define mg_timessend(...) (pthread_testcancel(), mg_timedsend(__VA_ARGS__)) #define msgrcv(...) (pthread_testcancel(), msgrecv(__VA_ARGS__)) #define msgsnd(...) (pthread_testcancel(), msgsnd(__VA_ARGS__)) #define msync(...) (pthread_testcancel(), msync(__VA_ARGS__)) #define nanosleep(...) (pthread_testcancel(), nanosleep(__VA_ARGS__)) #define open(...) (pthread_testcancel(), open(__VA_ARGS__)) #define pause(...) (pthread_testcancel(), pause(__VA_ARGS__)) #define poll(...) (pthread_testcancel(), poll(__VA_ARGS__)) #define pread(...) (pthread_testcancel(), pread(__VA_ARGS__)) #define pselect(...) (pthread_testcancel(), pselect(__VA_ARGS__)) #define putmsg(...) (pthread_testcancel(), putmsg(__VA_ARGS__)) #define putpmsg(...) (pthread_testcancel(), putpmsg(__VA_ARGS__)) #define pwrite(...) (pthread_testcancel(), pwrite(__VA_ARGS__)) #define read(...) (pthread_testcancel(), read(__VA_ARGS__)) #define readv(...) (pthread_testcancel(), readv(__VA_ARGS__)) #define recv(...) (pthread_testcancel(), recv(__VA_ARGS__)) #define recvfrom(...) (pthread_testcancel(), recvfrom(__VA_ARGS__)) #define recvmsg(...) (pthread_testcancel(), recvmsg(__VA_ARGS__)) #define select(...) (pthread_testcancel(), select(__VA_ARGS__)) #define sem_timedwait(...) (pthread_testcancel(), sem_timedwait(__VA_ARGS__)) #define sem_wait(...) (pthread_testcancel(), sem_wait(__VA_ARGS__)) #define send(...) (pthread_testcancel(), send(__VA_ARGS__)) #define sendmsg(...) (pthread_testcancel(), sendmsg(__VA_ARGS__)) #define sendto(...) (pthread_testcancel(), sendto(__VA_ARGS__)) #define sigpause(...) (pthread_testcancel(), sigpause(__VA_ARGS__)) #define sigsuspend(...) (pthread_testcancel(), sigsuspend(__VA_ARGS__)) #define sigwait(...) (pthread_testcancel(), sigwait(__VA_ARGS__)) #define sigwaitinfo(...) (pthread_testcancel(), sigwaitinfo(__VA_ARGS__)) #define sleep(...) (pthread_testcancel(), sleep(__VA_ARGS__)) /* #define Sleep(...) (pthread_testcancel(), Sleep(__VA_ARGS__)) */ #define system(...) (pthread_testcancel(), system(__VA_ARGS__)) #define access(...) (pthread_testcancel(), access(__VA_ARGS__)) #define asctime(...) (pthread_testcancel(), asctime(__VA_ARGS__)) #define asctime_r(...) (pthread_testcancel(), asctime_r(__VA_ARGS__)) #define catclose(...) (pthread_testcancel(), catclose(__VA_ARGS__)) #define catgets(...) (pthread_testcancel(), catgets(__VA_ARGS__)) #define catopen(...) (pthread_testcancel(), catopen(__VA_ARGS__)) #define closedir(...) (pthread_testcancel(), closedir(__VA_ARGS__)) #define closelog(...) (pthread_testcancel(), closelog(__VA_ARGS__)) #define ctermid(...) (pthread_testcancel(), ctermid(__VA_ARGS__)) #define ctime(...) (pthread_testcancel(), ctime(__VA_ARGS__)) #define ctime_r(...) (pthread_testcancel(), ctime_r(__VA_ARGS__)) #define dbm_close(...) (pthread_testcancel(), dbm_close(__VA_ARGS__)) #define dbm_delete(...) (pthread_testcancel(), dbm_delete(__VA_ARGS__)) #define dbm_fetch(...) (pthread_testcancel(), dbm_fetch(__VA_ARGS__)) #define dbm_nextkey(...) (pthread_testcancel(), dbm_nextkey(__VA_ARGS__)) #define dbm_open(...) (pthread_testcancel(), dbm_open(__VA_ARGS__)) #define dbm_store(...) (pthread_testcancel(), dbm_store(__VA_ARGS__)) #define dlclose(...) (pthread_testcancel(), dlclose(__VA_ARGS__)) #define dlopen(...) (pthread_testcancel(), dlopen(__VA_ARGS__)) #define endgrent(...) (pthread_testcancel(), endgrent(__VA_ARGS__)) #define endhostent(...) (pthread_testcancel(), endhostent(__VA_ARGS__)) #define endnetent(...) (pthread_testcancel(), endnetent(__VA_ARGS__)) #define endprotoent(...) (pthread_testcancel(), endprotoend(__VA_ARGS__)) #define endpwent(...) (pthread_testcancel(), endpwent(__VA_ARGS__)) #define endservent(...) (pthread_testcancel(), endservent(__VA_ARGS__)) #define endutxent(...) (pthread_testcancel(), endutxent(__VA_ARGS__)) #define fclose(...) (pthread_testcancel(), fclose(__VA_ARGS__)) #define fflush(...) (pthread_testcancel(), fflush(__VA_ARGS__)) #define fgetc(...) (pthread_testcancel(), fgetc(__VA_ARGS__)) #define fgetpos(...) (pthread_testcancel(), fgetpos(__VA_ARGS__)) #define fgets(...) (pthread_testcancel(), fgets(__VA_ARGS__)) #define fgetwc(...) (pthread_testcancel(), fgetwc(__VA_ARGS__)) #define fgetws(...) (pthread_testcancel(), fgetws(__VA_ARGS__)) #define fmtmsg(...) (pthread_testcancel(), fmtmsg(__VA_ARGS__)) #define fopen(...) (pthread_testcancel(), fopen(__VA_ARGS__)) #define fpathconf(...) (pthread_testcancel(), fpathconf(__VA_ARGS__)) #define fprintf(...) (pthread_testcancel(), fprintf(__VA_ARGS__)) #define fputc(...) (pthread_testcancel(), fputc(__VA_ARGS__)) #define fputs(...) (pthread_testcancel(), fputs(__VA_ARGS__)) #define fputwc(...) (pthread_testcancel(), fputwc(__VA_ARGS__)) #define fputws(...) (pthread_testcancel(), fputws(__VA_ARGS__)) #define fread(...) (pthread_testcancel(), fread(__VA_ARGS__)) #define freopen(...) (pthread_testcancel(), freopen(__VA_ARGS__)) #define fscanf(...) (pthread_testcancel(), fscanf(__VA_ARGS__)) #define fseek(...) (pthread_testcancel(), fseek(__VA_ARGS__)) #define fseeko(...) (pthread_testcancel(), fseeko(__VA_ARGS__)) #define fsetpos(...) (pthread_testcancel(), fsetpos(__VA_ARGS__)) #define fstat(...) (pthread_testcancel(), fstat(__VA_ARGS__)) #define ftell(...) (pthread_testcancel(), ftell(__VA_ARGS__)) #define ftello(...) (pthread_testcancel(), ftello(__VA_ARGS__)) #define ftw(...) (pthread_testcancel(), ftw(__VA_ARGS__)) #define fwprintf(...) (pthread_testcancel(), fwprintf(__VA_ARGS__)) #define fwrite(...) (pthread_testcancel(), fwrite(__VA_ARGS__)) #define fwscanf(...) (pthread_testcancel(), fwscanf(__VA_ARGS__)) #define getaddrinfo(...) (pthread_testcancel(), getaddrinfo(__VA_ARGS__)) #define getc(...) (pthread_testcancel(), getc(__VA_ARGS__)) #define getc_unlocked(...) (pthread_testcancel(), getc_unlocked(__VA_ARGS__)) #define getchar(...) (pthread_testcancel(), getchar(__VA_ARGS__)) #define getchar_unlocked(...) \ (pthread_testcancel(), getchar_unlocked(__VA_ARGS__)) #define getcwd(...) (pthread_testcancel(), getcwd(__VA_ARGS__)) #define getdate(...) (pthread_testcancel(), getdate(__VA_ARGS__)) #define getgrent(...) (pthread_testcancel(), getgrent(__VA_ARGS__)) #define getgrgid(...) (pthread_testcancel(), getgrgid(__VA_ARGS__)) #define getgrgid_r(...) (pthread_testcancel(), getgrgid_r(__VA_ARGS__)) #define gergrnam(...) (pthread_testcancel(), getgrnam(__VA_ARGS__)) #define getgrnam_r(...) (pthread_testcancel(), getgrnam_r(__VA_ARGS__)) #define gethostbyaddr(...) (pthread_testcancel(), gethostbyaddr(__VA_ARGS__)) #define gethostbyname(...) (pthread_testcancel(), gethostbyname(__VA_ARGS__)) #define gethostent(...) (pthread_testcancel(), gethostent(__VA_ARGS__)) #define gethostid(...) (pthread_testcancel(), gethostid(__VA_ARGS__)) #define gethostname(...) (pthread_testcancel(), gethostname(__VA_ARGS__)) #define getlogin(...) (pthread_testcancel(), getlogin(__VA_ARGS__)) #define getlogin_r(...) (pthread_testcancel(), getlogin_r(__VA_ARGS__)) #define getnameinfo(...) (pthread_testcancel(), getnameinfo(__VA_ARGS__)) #define getnetbyaddr(...) (pthread_testcancel(), getnetbyaddr(__VA_ARGS__)) #define getnetbyname(...) (pthread_testcancel(), getnetbyname(__VA_ARGS__)) #define getnetent(...) (pthread_testcancel(), getnetent(__VA_ARGS__)) #define getopt(...) (pthread_testcancel(), getopt(__VA_ARGS__)) #define getprotobyname(...) (pthread_testcancel(), getprotobyname(__VA_ARGS__)) #define getprotobynumber(...) \ (pthread_testcancel(), getprotobynumber(__VA_ARGS__)) #define getprotoent(...) (pthread_testcancel(), getprotoent(__VA_ARGS__)) #define getpwent(...) (pthread_testcancel(), getpwent(__VA_ARGS__)) #define getpwnam(...) (pthread_testcancel(), getpwnam(__VA_ARGS__)) #define getpwnam_r(...) (pthread_testcancel(), getpwnam_r(__VA_ARGS__)) #define getpwuid(...) (pthread_testcancel(), getpwuid(__VA_ARGS__)) #define getpwuid_r(...) (pthread_testcancel(), getpwuid_r(__VA_ARGS__)) #define gets(...) (pthread_testcancel(), gets(__VA_ARGS__)) #define getservbyname(...) (pthread_testcancel(), getservbyname(__VA_ARGS__)) #define getservbyport(...) (pthread_testcancel(), getservbyport(__VA_ARGS__)) #define getservent(...) (pthread_testcancel(), getservent(__VA_ARGS__)) #define getutxent(...) (pthread_testcancel(), getutxent(__VA_ARGS__)) #define getutxid(...) (pthread_testcancel(), getutxid(__VA_ARGS__)) #define getutxline(...) (pthread_testcancel(), getutxline(__VA_ARGS__)) #undef getwc #define getwc(...) (pthread_testcancel(), getwc(__VA_ARGS__)) #undef getwchar #define getwchar(...) (pthread_testcancel(), getwchar(__VA_ARGS__)) #define getwd(...) (pthread_testcancel(), getwd(__VA_ARGS__)) #define glob(...) (pthread_testcancel(), glob(__VA_ARGS__)) #define iconv_close(...) (pthread_testcancel(), iconv_close(__VA_ARGS__)) #define iconv_open(...) (pthread_testcancel(), iconv_open(__VA_ARGS__)) #define ioctl(...) (pthread_testcancel(), ioctl(__VA_ARGS__)) #define link(...) (pthread_testcancel(), link(__VA_ARGS__)) #define localtime(...) (pthread_testcancel(), localtime(__VA_ARGS__)) #define localtime_r(...) (pthread_testcancel(), localtime_r(__VA_ARGS__)) #define lseek(...) (pthread_testcancel(), lseek(__VA_ARGS__)) #define lstat(...) (pthread_testcancel(), lstat(__VA_ARGS__)) #define mkstemp(...) (pthread_testcancel(), mkstemp(__VA_ARGS__)) #define nftw(...) (pthread_testcancel(), nftw(__VA_ARGS__)) #define opendir(...) (pthread_testcancel(), opendir(__VA_ARGS__)) #define openlog(...) (pthread_testcancel(), openlog(__VA_ARGS__)) #define pathconf(...) (pthread_testcancel(), pathconf(__VA_ARGS__)) #define pclose(...) (pthread_testcancel(), pclose(__VA_ARGS__)) #define perror(...) (pthread_testcancel(), perror(__VA_ARGS__)) #define popen(...) (pthread_testcancel(), popen(__VA_ARGS__)) #define posix_fadvise(...) (pthread_testcancel(), posix_fadvise(__VA_ARGS__)) #define posix_fallocate(...) \ (pthread_testcancel(), posix_fallocate(__VA_ARGS__)) #define posix_madvise(...) (pthread_testcancel(), posix_madvise(__VA_ARGS__)) #define posix_openpt(...) (pthread_testcancel(), posix_openpt(__VA_ARGS__)) #define posix_spawn(...) (pthread_testcancel(), posix_spawn(__VA_ARGS__)) #define posix_spawnp(...) (pthread_testcancel(), posix_spawnp(__VA_ARGS__)) #define posix_trace_clear(...) \ (pthread_testcancel(), posix_trace_clear(__VA_ARGS__)) #define posix_trace_close(...) \ (pthread_testcancel(), posix_trace_close(__VA_ARGS__)) #define posix_trace_create(...) \ (pthread_testcancel(), posix_trace_create(__VA_ARGS__)) #define posix_trace_create_withlog(...) \ (pthread_testcancel(), posix_trace_create_withlog(__VA_ARGS__)) #define posix_trace_eventtypelist_getne(...) \ (pthread_testcancel(), posix_trace_eventtypelist_getne(__VA_ARGS__)) #define posix_trace_eventtypelist_rewin(...) \ (pthread_testcancel(), posix_trace_eventtypelist_rewin(__VA_ARGS__)) #define posix_trace_flush(...) \ (pthread_testcancel(), posix_trace_flush(__VA_ARGS__)) #define posix_trace_get_attr(...) \ (pthread_testcancel(), posix_trace_get_attr(__VA_ARGS__)) #define posix_trace_get_filter(...) \ (pthread_testcancel(), posix_trace_get_filter(__VA_ARGS__)) #define posix_trace_get_status(...) \ (pthread_testcancel(), posix_trace_get_status(__VA_ARGS__)) #define posix_trace_getnext_event(...) \ (pthread_testcancel(), posix_trace_getnext_event(__VA_ARGS__)) #define posix_trace_open(...) \ (pthread_testcancel(), posix_trace_open(__VA_ARGS__)) #define posix_trace_rewind(...) \ (pthread_testcancel(), posix_trace_rewind(__VA_ARGS__)) #define posix_trace_setfilter(...) \ (pthread_testcancel(), posix_trace_setfilter(__VA_ARGS__)) #define posix_trace_shutdown(...) \ (pthread_testcancel(), posix_trace_shutdown(__VA_ARGS__)) #define posix_trace_timedgetnext_event(...) \ (pthread_testcancel(), posix_trace_timedgetnext_event(__VA_ARGS__)) #define posix_typed_mem_open(...) \ (pthread_testcancel(), posix_typed_mem_open(__VA_ARGS__)) #define printf(...) (pthread_testcancel(), printf(__VA_ARGS__)) #define putc(...) (pthread_testcancel(), putc(__VA_ARGS__)) #define putc_unlocked(...) (pthread_testcancel(), putc_unlocked(__VA_ARGS__)) #define putchar(...) (pthread_testcancel(), putchar(__VA_ARGS__)) #define putchar_unlocked(...) \ (pthread_testcancel(), putchar_unlocked(__VA_ARGS__)) #define puts(...) (pthread_testcancel(), puts(__VA_ARGS__)) #define pututxline(...) (pthread_testcancel(), pututxline(__VA_ARGS__)) #undef putwc #define putwc(...) (pthread_testcancel(), putwc(__VA_ARGS__)) #undef putwchar #define putwchar(...) (pthread_testcancel(), putwchar(__VA_ARGS__)) #define readdir(...) (pthread_testcancel(), readdir(__VA_ARSG__)) #define readdir_r(...) (pthread_testcancel(), readdir_r(__VA_ARGS__)) #define remove(...) (pthread_testcancel(), remove(__VA_ARGS__)) #define rename(...) (pthread_testcancel(), rename(__VA_ARGS__)) #define rewind(...) (pthread_testcancel(), rewind(__VA_ARGS__)) #define rewinddir(...) (pthread_testcancel(), rewinddir(__VA_ARGS__)) #define scanf(...) (pthread_testcancel(), scanf(__VA_ARGS__)) #define seekdir(...) (pthread_testcancel(), seekdir(__VA_ARGS__)) #define semop(...) (pthread_testcancel(), semop(__VA_ARGS__)) #define setgrent(...) (pthread_testcancel(), setgrent(__VA_ARGS__)) #define sethostent(...) (pthread_testcancel(), sethostemt(__VA_ARGS__)) #define setnetent(...) (pthread_testcancel(), setnetent(__VA_ARGS__)) #define setprotoent(...) (pthread_testcancel(), setprotoent(__VA_ARGS__)) #define setpwent(...) (pthread_testcancel(), setpwent(__VA_ARGS__)) #define setservent(...) (pthread_testcancel(), setservent(__VA_ARGS__)) #define setutxent(...) (pthread_testcancel(), setutxent(__VA_ARGS__)) #define stat(...) (pthread_testcancel(), stat(__VA_ARGS__)) #define strerror(...) (pthread_testcancel(), strerror(__VA_ARGS__)) #define strerror_r(...) (pthread_testcancel(), strerror_r(__VA_ARGS__)) #define strftime(...) (pthread_testcancel(), strftime(__VA_ARGS__)) #define symlink(...) (pthread_testcancel(), symlink(__VA_ARGS__)) #define sync(...) (pthread_testcancel(), sync(__VA_ARGS__)) #define syslog(...) (pthread_testcancel(), syslog(__VA_ARGS__)) #define tmpfile(...) (pthread_testcancel(), tmpfile(__VA_ARGS__)) #define tmpnam(...) (pthread_testcancel(), tmpnam(__VA_ARGS__)) #define ttyname(...) (pthread_testcancel(), ttyname(__VA_ARGS__)) #define ttyname_r(...) (pthread_testcancel(), ttyname_r(__VA_ARGS__)) #define tzset(...) (pthread_testcancel(), tzset(__VA_ARGS__)) #define ungetc(...) (pthread_testcancel(), ungetc(__VA_ARGS__)) #define ungetwc(...) (pthread_testcancel(), ungetwc(__VA_ARGS__)) #define unlink(...) (pthread_testcancel(), unlink(__VA_ARGS__)) #define vfprintf(...) (pthread_testcancel(), vfprintf(__VA_ARGS__)) #define vfwprintf(...) (pthread_testcancel(), vfwprintf(__VA_ARGS__)) #define vprintf(...) (pthread_testcancel(), vprintf(__VA_ARGS__)) #define vwprintf(...) (pthread_testcancel(), vwprintf(__VA_ARGS__)) #define wcsftime(...) (pthread_testcancel(), wcsftime(__VA_ARGS__)) #define wordexp(...) (pthread_testcancel(), wordexp(__VA_ARGS__)) #define wprintf(...) (pthread_testcancel(), wprintf(__VA_ARGS__)) #define wscanf(...) (pthread_testcancel(), wscanf(__VA_ARGS__)) #endif /* WIN_PTHREADS */ ntirpc-1.3.1/ntirpc/namespace.h000066400000000000000000000030141261345040100164110ustar00rootroot00000000000000/* * Copyright (c) 2001 Daniel Eischen . * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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. * * $FreeBSD: src/lib/libc/include/namespace.h,v 1.16 2003/05/01 * 19:03:13 nectar Exp $ */ #ifndef _NAMESPACE_H_ #define _NAMESPACE_H_ #endif /* _NAMESPACE_H_ */ ntirpc-1.3.1/ntirpc/netconfig.h000066400000000000000000000042331261345040100164350ustar00rootroot00000000000000#ifndef _NETCONFIG_H_ #define _NETCONFIG_H_ #if defined(__linux__) #include #endif #if defined(_WIN32) #define NETCONFIG "c:\\etc\\netconfig" #else #define NETCONFIG "/etc/netconfig" #endif #define NETPATH "NETPATH" struct netconfig { char *nc_netid; /* Network ID */ unsigned long nc_semantics; /* Semantics (see below) */ unsigned long nc_flag; /* Flags (see below) */ 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 */ unsigned long nc_unused[9]; /* reserved */ }; typedef struct { struct netconfig **nc_head; struct netconfig **nc_curr; } NCONF_HANDLE; /* * nc_semantics values */ #define NC_TPI_CLTS 1 #define NC_TPI_COTS 2 #define NC_TPI_COTS_ORD 3 #define NC_TPI_RAW 4 /* * nc_flag values */ #define NC_NOFLAG 0x00 #define NC_VISIBLE 0x01 #define NC_BROADCAST 0x02 /* * nc_protofmly values */ #define NC_NOPROTOFMLY "-" #define NC_LOOPBACK "loopback" #define NC_INET "inet" #define NC_INET6 "inet6" #define NC_IMPLINK "implink" #define NC_PUP "pup" #define NC_CHAOS "chaos" #define NC_NS "ns" #define NC_NBS "nbs" #define NC_ECMA "ecma" #define NC_DATAKIT "datakit" #define NC_CCITT "ccitt" #define NC_SNA "sna" #define NC_DECNET "decnet" #define NC_DLI "dli" #define NC_LAT "lat" #define NC_HYLINK "hylink" #define NC_APPLETALK "appletalk" #define NC_NIT "nit" #define NC_IEEE802 "ieee802" #define NC_OSI "osi" #define NC_X25 "x25" #define NC_OSINET "osinet" #define NC_GOSIP "gosip" /* * nc_proto values */ #define NC_NOPROTO "-" #define NC_TCP "tcp" #define NC_UDP "udp" #define NC_ICMP "icmp" __BEGIN_DECLS extern void *setnetconfig(void); extern struct netconfig *getnetconfig(void *); extern struct netconfig *getnetconfigent(const char *); extern void freenetconfigent(struct netconfig *); extern int endnetconfig(void *); extern void *setnetpath(void); extern struct netconfig *getnetpath(void *); extern int endnetpath(void *); extern void nc_perror(const char *); extern char *nc_sperror(void); __END_DECLS #endif /* _NETCONFIG_H_ */ ntirpc-1.3.1/ntirpc/reentrant.h000066400000000000000000000101271261345040100164620ustar00rootroot00000000000000/*- * Copyright (c) 1997,98 The NetBSD Foundation, Inc. * All rights reserved. * * This code is derived from software contributed to The NetBSD Foundation * by J.T. Conklin. * * 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. * */ /* * This file was derived from a copy in FreeBSD CVS on August 26, 2010. * FreeBSD/NetBSD have slightly different definitions for some/most of * these functions and types, so they should just use the ones found * in their system copy of reentrant.h. */ #ifndef REENTRANT_H #define REENTRANT_H #if defined(_WIN32) #include #else #include #endif #define mutex_t pthread_mutex_t #define cond_t pthread_cond_t #define rwlock_t pthread_rwlock_t #define spinlock_t pthread_spinlock_t #define once_t pthread_once_t #define thread_key_t pthread_key_t #if defined(__linux__) #define MUTEX_INITIALIZER PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP #else #define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER #endif #define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER #define ONCE_INITIALIZER PTHREAD_ONCE_INIT static inline int mutex_init(pthread_mutex_t *m, const pthread_mutexattr_t *a __attribute__ ((unused))) { pthread_mutexattr_t attr; int rslt; pthread_mutexattr_init(&attr); #if defined(__linux__) pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ADAPTIVE_NP); #endif rslt = pthread_mutex_init(m, &attr); pthread_mutexattr_destroy(&attr); return (rslt); } #define mutex_lock(m) pthread_mutex_lock(m) #define mutex_trylock(m) pthread_mutex_trylock(m) #define mutex_unlock(m) pthread_mutex_unlock(m) #define mutex_destroy(m) pthread_mutex_destroy(m) #define cond_init(c, a, p) pthread_cond_init(c, a) #define cond_signal(m) pthread_cond_signal(m) #define cond_broadcast(m) pthread_cond_broadcast(m) #define cond_wait(c, m) pthread_cond_wait(c, m) #define cond_timedwait(c, m, a) pthread_cond_timedwait(c, m, a) #define cond_destroy(c) pthread_cond_destroy(c) #define rwlock_init(l, a) pthread_rwlock_init(l, a) #define rwlock_rdlock(l) pthread_rwlock_rdlock(l) #define rwlock_wrlock(l) pthread_rwlock_wrlock(l) #define rwlock_unlock(l) pthread_rwlock_unlock(l) #define rwlockattr_init(a) pthread_rwlockattr_init(a) #define rwlock_destroy(l) pthread_rwlock_destroy(l) #define spin_init(l, a) pthread_spin_init(l, a) #define spin_lock(l) pthread_spin_lock(l) #define spin_trylock(l) pthread_spin_trylock(l) #define spin_unlock(l) pthread_spin_unlock(l) #define spin_destroy(l) pthread_spin_destroy(l) #define thr_keycreate(k, d) pthread_key_create(k, d) #define thr_setspecific(k, p) pthread_setspecific(k, p) #define thr_getspecific(k) pthread_getspecific(k) #define thr_sigsetmask(f, n, o) pthread_sigmask(f, n, o) #define thr_once(o, i) pthread_once(o, i) #define thr_self() pthread_self() #define thr_exit(x) pthread_exit(x) #endif /* REENTRANT_H */ ntirpc-1.3.1/ntirpc/rpc/000077500000000000000000000000001261345040100150725ustar00rootroot00000000000000ntirpc-1.3.1/ntirpc/rpc/auth.h000066400000000000000000000305161261345040100162110ustar00rootroot00000000000000/* $NetBSD: auth.h,v 1.15 2000/06/02 22:57:55 fvdl Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)auth.h 1.17 88/02/08 SMI * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC * from: @(#)auth.h 1.43 98/02/02 SMI * $FreeBSD: src/include/rpc/auth.h,v 1.20 2003/01/01 18:48:42 schweikh Exp $ */ /* * auth.h, Authentication interface. * * Copyright (C) 1984, Sun Microsystems, Inc. * * The data structures are completely opaque to the client. The client * is required to pass an AUTH * to routines that create rpc * "sessions". */ #ifndef _TIRPC_AUTH_H #define _TIRPC_AUTH_H #include #include #include #include #if !defined(_WIN32) #include #endif #include #define MAX_AUTH_BYTES 400 /* maximum length of opaque auth */ #define MAXNETNAMELEN 255 /* maximum length of network user's name */ /* * Client side authentication/security data */ typedef struct sec_data { u_int secmod; /* security mode number e.g. in nfssec.conf */ u_int rpcflavor; /* rpc flavors:AUTH_UNIX,AUTH_DES,RPCSEC_GSS */ int flags; /* AUTH_F_xxx flags */ caddr_t data; /* opaque data per flavor */ } sec_data_t; #ifdef _SYSCALL32_IMPL struct sec_data32 { uint32_t secmod; /* security mode number e.g. in nfssec.conf */ uint32_t rpcflavor; /* rpc flavors:AUTH_UNIX,AUTH_DES,RPCSEC_GSS */ int32_t flags; /* AUTH_F_xxx flags */ caddr32_t data; /* opaque data per flavor */ }; #endif /* _SYSCALL32_IMPL */ /* * AUTH_DES flavor specific data from sec_data opaque data field. * AUTH_KERB has the same structure. */ typedef struct des_clnt_data { struct netbuf syncaddr; /* time sync addr */ struct knetconfig *knconf; /* knetconfig info that associated */ /* with the syncaddr. */ char *netname; /* server's netname */ int netnamelen; /* server's netname len */ } dh_k4_clntdata_t; #ifdef _SYSCALL32_IMPL struct des_clnt_data32 { struct netbuf32 syncaddr; /* time sync addr */ caddr32_t knconf; /* knetconfig info that associated */ /* with the syncaddr. */ caddr32_t netname; /* server's netname */ int32_t netnamelen; /* server's netname len */ }; #endif /* _SYSCALL32_IMPL */ #ifdef KERBEROS /* * flavor specific data to hold the data for AUTH_DES/AUTH_KERB(v4) * in sec_data->data opaque field. */ typedef struct krb4_svc_data { int window; /* window option value */ } krb4_svcdata_t; typedef struct krb4_svc_data des_svcdata_t; #endif /* KERBEROS */ /* * authentication/security specific flags */ #define AUTH_F_RPCTIMESYNC 0x001 /* use RPC to do time sync */ #define AUTH_F_TRYNONE 0x002 /* allow fall back to AUTH_NONE */ /* * Status returned from authentication check */ enum auth_stat { AUTH_OK = 0, /* * failed at remote end */ AUTH_BADCRED = 1, /* bogus credentials (seal broken) */ AUTH_REJECTEDCRED = 2, /* client should begin new session */ AUTH_BADVERF = 3, /* bogus verifier (seal broken) */ AUTH_REJECTEDVERF = 4, /* verifier expired or was replayed */ AUTH_TOOWEAK = 5, /* rejected due to security reasons */ /* * failed locally */ AUTH_INVALIDRESP = 6, /* bogus response verifier */ AUTH_FAILED = 7, /* some unknown reason */ #ifdef KERBEROS /* * kerberos errors */ AUTH_KERB_GENERIC = 8, /* kerberos generic error */ AUTH_TIMEEXPIRE = 9, /* time of credential expired */ AUTH_TKT_FILE = 10, /* something wrong with ticket file */ AUTH_DECODE = 11, /* can't decode authenticator */ AUTH_NET_ADDR = 12, /* wrong net address in ticket */ #endif /* KERBEROS */ /* * RPCSEC_GSS errors */ RPCSEC_GSS_CREDPROBLEM = 13, RPCSEC_GSS_CTXPROBLEM = 14 }; typedef u_int32_t u_int32; /* 32-bit unsigned integers */ union des_block { struct { u_int32_t high; u_int32_t low; } key; char c[8]; }; typedef union des_block des_block; __BEGIN_DECLS extern bool xdr_des_block(XDR *, des_block *); __END_DECLS /* * Authentication info. Opaque to client. */ struct opaque_auth { enum_t oa_flavor; /* flavor of auth */ caddr_t oa_base; /* address of more auth stuff */ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */ }; /* * Auth handle, interface to client side authenticators. */ typedef struct __auth { struct opaque_auth ah_cred; struct opaque_auth ah_verf; union des_block ah_key; struct auth_ops { void (*ah_nextverf) (struct __auth *); /* nextverf & serialize */ bool(*ah_marshal) (struct __auth *, XDR *); /* validate verifier */ bool(*ah_validate) (struct __auth *, struct opaque_auth *); /* refresh credentials */ bool(*ah_refresh) (struct __auth *, void *); /* destroy this structure */ void (*ah_destroy) (struct __auth *); /* encode data for wire */ bool(*ah_wrap) (struct __auth *, XDR *, xdrproc_t, caddr_t); /* decode data for wire */ bool(*ah_unwrap) (struct __auth *, XDR *, xdrproc_t, caddr_t); } *ah_ops; void *ah_private; int ah_refcnt; } AUTH; static inline int auth_get(AUTH *auth) { return atomic_add_int32_t(&auth->ah_refcnt, 1); } static inline int auth_put(AUTH *auth) { return atomic_sub_int32_t(&auth->ah_refcnt, 1); } /* * Authentication ops. * The ops and the auth handle provide the interface to the authenticators. * * AUTH *auth; * XDR *xdrs; * struct opaque_auth verf; */ #define AUTH_NEXTVERF(auth) \ ((*((auth)->ah_ops->ah_nextverf))(auth)) #define auth_nextverf(auth) \ ((*((auth)->ah_ops->ah_nextverf))(auth)) #define AUTH_MARSHALL(auth, xdrs) \ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) #define auth_marshall(auth, xdrs) \ ((*((auth)->ah_ops->ah_marshal))(auth, xdrs)) #define AUTH_VALIDATE(auth, verfp) \ ((*((auth)->ah_ops->ah_validate))((auth), verfp)) #define auth_validate(auth, verfp) \ ((*((auth)->ah_ops->ah_validate))((auth), verfp)) #define AUTH_REFRESH(auth, msg) \ ((*((auth)->ah_ops->ah_refresh))(auth, msg)) #define auth_refresh(auth, msg) \ ((*((auth)->ah_ops->ah_refresh))(auth, msg)) #define AUTH_DESTROY(auth) \ do { \ int refs = auth_put((auth)); \ if (refs == 0) \ ((*((auth)->ah_ops->ah_destroy))(auth)); \ __warnx(TIRPC_DEBUG_FLAG_AUTH, \ "%s: auth_put(), refs %d\n", \ __func__, refs); \ } while (0) #define auth_destroy(auth) \ do { \ int refs = auth_put((auth)); \ if (refs == 0) \ ((*((auth)->ah_ops->ah_destroy))(auth)); \ __warnx(TIRPC_DEBUG_FLAG_AUTH, \ "%s: auth_put(), refs %d\n", \ __func__, refs); \ } while (0) #define AUTH_WRAP(auth, xdrs, xfunc, xwhere) \ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \ xfunc, xwhere)) #define auth_wrap(auth, xdrs, xfunc, xwhere) \ ((*((auth)->ah_ops->ah_wrap))(auth, xdrs, \ xfunc, xwhere)) #define AUTH_UNWRAP(auth, xdrs, xfunc, xwhere) \ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \ xfunc, xwhere)) #define auth_unwrap(auth, xdrs, xfunc, xwhere) \ ((*((auth)->ah_ops->ah_unwrap))(auth, xdrs, \ xfunc, xwhere)) __BEGIN_DECLS extern struct opaque_auth _null_auth; __END_DECLS /* * Any style authentication. These routines can be used by any * authentication style that does not use the wrap/unwrap functions. */ int authany_wrap(void), authany_unwrap(void); /* * These are the various implementations of client side authenticators. */ /* * System style authentication * AUTH *authunix_create(machname, uid, gid, len, aup_gids) * char *machname; * int uid; * int gid; * int len; * int *aup_gids; */ __BEGIN_DECLS extern AUTH *authunix_ncreate(char *, uid_t, uid_t, int, uid_t *); extern AUTH *authunix_ncreate_default(void); /* takes no parameters */ extern AUTH *authnone_ncreate(void); /* takes no parameters */ __END_DECLS /* * DES style authentication * AUTH *authsecdes_create(servername, window, timehost, ckey) * char *servername; - network name of server * u_int window; - time to live * const char *timehost; - optional hostname to sync with * des_block *ckey; - optional conversation key to use */ __BEGIN_DECLS extern AUTH *authdes_ncreate(char *, u_int, struct sockaddr *, des_block *); extern AUTH *authdes_nseccreate(const char *, const u_int, const char *, const des_block *); __END_DECLS __BEGIN_DECLS extern bool xdr_opaque_auth(XDR *, struct opaque_auth *); __END_DECLS /* * Netname manipulation routines. */ __BEGIN_DECLS extern int getnetname(char *); extern int host2netname(char *, const char *, const char *); extern int user2netname(char *, const uid_t, const char *); extern int netname2user(char *, uid_t *, gid_t *, int *, gid_t *); extern int netname2host(char *, char *, const int); extern void passwd2des(char *, char *); __END_DECLS /* * * These routines interface to the keyserv daemon * */ __BEGIN_DECLS extern int key_decryptsession(const char *, des_block *); extern int key_encryptsession(const char *, des_block *); extern int key_gendes(des_block *); extern int key_setsecret(const char *); extern int key_secretkey_is_set(void); extern int key_encryptsession_pk(char *, netobj *, des_block *); __END_DECLS /* * Publickey routines. */ __BEGIN_DECLS extern int getpublickey(const char *, char *); extern int getpublicandprivatekey(char *, char *); extern int getsecretkey(char *, char *, char *); __END_DECLS #ifdef KERBEROS /* * Kerberos style authentication * AUTH *authkerb_seccreate(service, srv_inst, realm, window, timehost, status) * const char *service; - service name * const char *srv_inst; - server instance * const char *realm; - server realm * const u_int window; - time to live * const char *timehost; - optional hostname to sync with * int *status; - kerberos status returned */ __BEGIN_DECLS extern AUTH *authkerb_nseccreate(const char *, const char *, const char *, const u_int, const char *, int *); __END_DECLS /* * Map a kerberos credential into a unix cred. * * authkerb_getucred(rqst, uid, gid, grouplen, groups) * const struct svc_req *rqst; - request pointer * uid_t *uid; * gid_t *gid; * short *grouplen; * int *groups; * */ __BEGIN_DECLS extern int authkerb_getucred(/* struct svc_req *, uid_t *, gid_t *, short *, int * */); __END_DECLS #endif /* KERBEROS */ __BEGIN_DECLS struct svc_req; struct rpc_msg; enum auth_stat _svcauth_none(struct svc_req *, struct rpc_msg *); enum auth_stat _svcauth_short(struct svc_req *, struct rpc_msg *); enum auth_stat _svcauth_unix(struct svc_req *, struct rpc_msg *); enum auth_stat _svcauth_gss(struct svc_req *, struct rpc_msg *, bool *); __END_DECLS #define AUTH_NONE 0 /* no authentication */ #define AUTH_NULL 0 /* backward compatibility */ #define AUTH_SYS 1 /* unix style (uid, gids) */ #define AUTH_UNIX AUTH_SYS #define AUTH_SHORT 2 /* short hand unix style */ #define AUTH_DH 3 /* for Diffie-Hellman mechanism */ #define AUTH_DES AUTH_DH /* for backward compatibility */ #define AUTH_KERB 4 /* kerberos style */ #define RPCSEC_GSS 6 /* RPCSEC_GSS */ /* for backward compatibility */ #include #endif /* !_TIRPC_AUTH_H */ ntirpc-1.3.1/ntirpc/rpc/auth_des.h000066400000000000000000000077201261345040100170450ustar00rootroot00000000000000/* @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC; from 1.3 88/02/08 SMI */ /* $FreeBSD: src/include/rpc/auth_des.h,v 1.3 2002/03/23 17:24:55 imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)auth_des.h 2.2 88/07/29 4.0 RPCSRC * from: @(#)auth_des.h 1.14 94/04/25 SMI */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * auth_des.h, Protocol for DES style authentication for RPC */ #ifndef _TI_AUTH_DES_ #define _TI_AUTH_DES_ #include /* * There are two kinds of "names": fullnames and nicknames */ enum authdes_namekind { ADN_FULLNAME, ADN_NICKNAME }; /* * A fullname contains the network name of the client, * a conversation key and the window */ struct authdes_fullname { char *name; /* network name of client, up to MAXNETNAMELEN */ union des_block key; /* conversation key */ /* u_long window; */ u_int32_t window; /* associated window */ }; /* * A credential */ struct authdes_cred { enum authdes_namekind adc_namekind; struct authdes_fullname adc_fullname; /*u_long adc_nickname; */ u_int32_t adc_nickname; }; /* * A des authentication verifier */ struct authdes_verf { union { struct timeval adv_ctime; /* clear time */ des_block adv_xtime; /* crypt time */ } adv_time_u; /*u_long adv_int_u; */ u_int32_t adv_int_u; }; /* * des authentication verifier: client variety * * adv_timestamp is the current time. * adv_winverf is the credential window + 1. * Both are encrypted using the conversation key. */ #define adv_timestamp adv_time_u.adv_ctime #define adv_xtimestamp adv_time_u.adv_xtime #define adv_winverf adv_int_u /* * des authentication verifier: server variety * * adv_timeverf is the client's timestamp + client's window * adv_nickname is the server's nickname for the client. * adv_timeverf is encrypted using the conversation key. */ #define adv_timeverf adv_time_u.adv_ctime #define adv_xtimeverf adv_time_u.adv_xtime #define adv_nickname adv_int_u /* * Map a des credential into a unix cred. * */ __BEGIN_DECLS extern int authdes_getucred(struct authdes_cred *, uid_t *, gid_t *, int *, gid_t *); __END_DECLS __BEGIN_DECLS extern bool xdr_authdes_cred(XDR *, struct authdes_cred *); extern bool xdr_authdes_verf(XDR *, struct authdes_verf *); extern int rtime(dev_t, struct netbuf *, int, struct timeval *, struct timeval *); extern void kgetnetname(char *); extern enum auth_stat _svcauth_des(struct svc_req *, struct rpc_msg *); __END_DECLS #endif /* ndef _TI_AUTH_DES_ */ ntirpc-1.3.1/ntirpc/rpc/auth_gss.h000066400000000000000000000104341261345040100170620ustar00rootroot00000000000000/* auth_gss.h Copyright (c) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (c) 2000 Dug Song . All rights reserved, all wrongs reversed. 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 University 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 ``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 REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _TIRPC_AUTH_GSS_H #define _TIRPC_AUTH_GSS_H #include #include /* RPCSEC_GSS control procedures. */ typedef enum { RPCSEC_GSS_DATA = 0, RPCSEC_GSS_INIT = 1, RPCSEC_GSS_CONTINUE_INIT = 2, RPCSEC_GSS_DESTROY = 3 } rpc_gss_proc_t; /* RPCSEC_GSS services. */ typedef enum { RPCSEC_GSS_SVC_NONE = 1, RPCSEC_GSS_SVC_INTEGRITY = 2, RPCSEC_GSS_SVC_PRIVACY = 3 } rpc_gss_svc_t; #define RPCSEC_GSS_MAXPROC 3 #define RPCSEC_GSS_VERSION 1 /* RPCSEC_GSS security triple. */ struct rpc_gss_sec { gss_OID mech; /* mechanism */ gss_qop_t qop; /* quality of protection */ rpc_gss_svc_t svc; /* service */ gss_cred_id_t cred; /* cred handle */ u_int req_flags; /* req flags for init_sec_context */ }; /* Private data required for kernel implementation */ struct authgss_private_data { gss_ctx_id_t pd_ctx; /* Session context handle */ gss_buffer_desc pd_ctx_hndl; /* Credentials context handle */ u_int pd_seq_win; /* Sequence window */ }; #define g_OID_equal(o1, o2) \ (((o1)->length == (o2)->length) && \ ((o1)->elements != 0) && ((o2)->elements != 0) && \ (memcmp((o1)->elements, (o2)->elements, (int) (o1)->length) == 0)) /* from kerberos source, gssapi_krb5.c */ extern gss_OID_desc krb5oid; extern gss_OID_desc spkm3oid; /* Credentials. */ struct rpc_gss_cred { u_int gc_v; /* version */ rpc_gss_proc_t gc_proc; /* control procedure */ u_int gc_seq; /* sequence number */ rpc_gss_svc_t gc_svc; /* service */ gss_buffer_desc gc_ctx; /* context handle */ }; /* Context creation response. */ struct rpc_gss_init_res { gss_buffer_desc gr_ctx; /* context handle */ u_int gr_major; /* major status */ u_int gr_minor; /* minor status */ u_int gr_win; /* sequence window */ gss_buffer_desc gr_token; /* token */ }; /* Maximum sequence number value. */ #define RPCSEC_GSS_MAXSEQ 0x80000000 /* Prototypes. */ __BEGIN_DECLS bool xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p); bool xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p); bool xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p); bool xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_svc_t svc, u_int seq); AUTH *authgss_ncreate(CLIENT *, gss_name_t, struct rpc_gss_sec *); AUTH *authgss_ncreate_default(CLIENT *, char *, struct rpc_gss_sec *); bool authgss_service(AUTH *auth, int svc); bool authgss_get_private_data(AUTH *auth, struct authgss_private_data *); void log_debug(const char *fmt, ...); void log_status(char *m, OM_uint32 major, OM_uint32 minor); void gss_log_hexdump(const u_char *buf, int len, int offset); __END_DECLS /* for backward compatibility */ #include #endif /* !_TIRPC_AUTH_GSS_H */ ntirpc-1.3.1/ntirpc/rpc/auth_inline.h000066400000000000000000000125021261345040100175420ustar00rootroot00000000000000/* $NetBSD: auth.h,v 1.15 2000/06/02 22:57:55 fvdl Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)auth.h 1.17 88/02/08 SMI * from: @(#)auth.h 2.3 88/08/07 4.0 RPCSRC * from: @(#)auth.h 1.43 98/02/02 SMI * $FreeBSD: src/include/rpc/auth.h,v 1.20 2003/01/01 18:48:42 schweikh Exp $ */ /* * auth.h, Authentication interface. * * Copyright (C) 1984, Sun Microsystems, Inc. * * The data structures are completely opaque to the client. The client * is required to pass an AUTH * to routines that create rpc * "sessions". */ #ifndef _TIRPC_AUTH_INLINE_H #define _TIRPC_AUTH_INLINE_H #include #include /* * encode auth opaque */ static inline bool inline_auth_encode_opaque(XDR *xdrs, struct opaque_auth *oa) { if (oa->oa_length > MAX_AUTH_BYTES) { /* duplicate test, usually done earlier by caller */ __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR oa_length (%u) > %u", __func__, __LINE__, oa->oa_length, MAX_AUTH_BYTES); return (false); } return (inline_xdr_putopaque(xdrs, oa->oa_base, oa->oa_length)); } /* * encode an auth message */ static inline bool inline_auth_encode(XDR *xdrs, struct opaque_auth *oa) { /* * XDR_INLINE is just as likely to do a function call, * so don't bother with it here. */ if (!xdr_putenum(xdrs, oa->oa_flavor)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR oa_flavor", __func__, __LINE__); return (false); } if (!xdr_putuint32(xdrs, &oa->oa_length)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR oa_length", __func__, __LINE__); return (false); } if (oa->oa_length) { /* only call and alloc for > 0 length */ return (inline_auth_encode_opaque(xdrs, oa)); } return (true); /* 0 length succeeds */ } /* * decode auth opaque */ static inline bool inline_auth_decode_opaque(XDR *xdrs, struct opaque_auth *oa) { if (oa->oa_length > MAX_AUTH_BYTES) { /* duplicate test, usually done earlier by caller */ __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR oa_length (%u) > %u", __func__, __LINE__, oa->oa_length, MAX_AUTH_BYTES); return (false); } if (oa->oa_base == NULL) { oa->oa_base = (caddr_t)mem_alloc(oa->oa_length); if (oa->oa_base == NULL) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR mem_alloc(oa->oa_length)", __func__, __LINE__); return (false); } } return (inline_xdr_getopaque(xdrs, oa->oa_base, oa->oa_length)); } /* * decode an auth message * * param[IN] buf 2 more inline */ static inline bool inline_auth_decode(XDR *xdrs, struct opaque_auth *oa, int32_t *buf) { if (buf != NULL) { oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t); oa->oa_length = (u_int) IXDR_GET_U_INT32(buf); } else if (!xdr_getenum(xdrs, (enum_t *)&oa->oa_flavor)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR oa_flavor", __func__, __LINE__); return (false); } else if (!xdr_getuint32(xdrs, &oa->oa_length)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR oa_length", __func__, __LINE__); return (false); } if (oa->oa_length) { /* only call and alloc for > 0 length */ return inline_auth_decode_opaque(xdrs, oa); } return (true); /* 0 length succeeds */ } /* * free an auth message */ static inline bool inline_auth_free(XDR *xdrs, struct opaque_auth *oa) { if (oa->oa_base != NULL) { mem_free(oa->oa_base, oa->oa_length); oa->oa_base = NULL; } return (true); } /* * XDR an auth message */ static inline bool inline_xdr_opaque_auth(XDR *xdrs, struct opaque_auth *oa) { switch (xdrs->x_op) { case XDR_ENCODE: return (inline_auth_encode(xdrs, oa)); case XDR_DECODE: return (inline_auth_decode(xdrs, oa, NULL)); case XDR_FREE: return (inline_auth_free(xdrs, oa)); default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR xdrs->x_op (%u)", __func__, __LINE__, xdrs->x_op); break; } /* x_op */ return (false); } #endif /* !_TIRPC_AUTH_INLINE_H */ ntirpc-1.3.1/ntirpc/rpc/auth_kerb.h000066400000000000000000000110051261345040100172040ustar00rootroot00000000000000/* $FreeBSD: src/include/rpc/auth_kerb.h,v 1.2 2002/09/04 23:58:23 * alfred Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * auth_kerb.h, Protocol for Kerberos style authentication for RPC * * Copyright (C) 1986, Sun Microsystems, Inc. */ #ifndef _RPC_AUTH_KERB_H #define _RPC_AUTH_KERB_H #ifdef KERBEROS #include #include #include #include #include /* * There are two kinds of "names": fullnames and nicknames */ enum authkerb_namekind { AKN_FULLNAME, AKN_NICKNAME }; /* * A fullname contains the ticket and the window */ struct authkerb_fullname { KTEXT_ST ticket; u_long window; /* associated window */ }; /* * cooked credential stored in rq_clntcred */ struct authkerb_clnt_cred { /* start of AUTH_DAT */ unsigned char k_flags; /* Flags from ticket */ char pname[ANAME_SZ]; /* Principal's name */ char pinst[INST_SZ]; /* His Instance */ char prealm[REALM_SZ]; /* His Realm */ unsigned long checksum; /* Data checksum (opt) */ C_Block session; /* Session Key */ int life; /* Life of ticket */ unsigned long time_sec; /* Time ticket issued */ unsigned long address; /* Address in ticket */ /* KTEXT_ST reply; Auth reply (opt) */ /* end of AUTH_DAT */ unsigned long expiry; /* time the ticket is expiring */ u_long nickname; /* Nickname into cache */ u_long window; /* associated window */ }; typedef struct authkerb_clnt_cred authkerb_clnt_cred; /* * A credential */ struct authkerb_cred { enum authkerb_namekind akc_namekind; struct authkerb_fullname akc_fullname; u_long akc_nickname; }; /* * A kerb authentication verifier */ struct authkerb_verf { union { struct timeval akv_ctime; /* clear time */ des_block akv_xtime; /* crypt time */ } akv_time_u; u_long akv_int_u; }; /* * des authentication verifier: client variety * * akv_timestamp is the current time. * akv_winverf is the credential window + 1. * Both are encrypted using the conversation key. */ #ifndef akv_timestamp #define akv_timestamp akv_time_u.akv_ctime #define akv_xtimestamp akv_time_u.akv_xtime #define akv_winverf akv_int_u #endif /* * des authentication verifier: server variety * * akv_timeverf is the client's timestamp + client's window * akv_nickname is the server's nickname for the client. * akv_timeverf is encrypted using the conversation key. */ #ifndef akv_timeverf #define akv_timeverf akv_time_u.akv_ctime #define akv_xtimeverf akv_time_u.akv_xtime #define akv_nickname akv_int_u #endif /* * Register the service name, instance and realm. */ extern int authkerb_ncreate(char *, char *, char *, u_int, struct netbuf *, int *, dev_t, int, AUTH **); extern bool xdr_authkerb_cred(XDR *, struct authkerb_cred *); extern bool xdr_authkerb_verf(XDR *, struct authkerb_verf *); extern int svc_kerb_reg(SVCXPRT *, char *, char *, char *); extern enum auth_stat _svcauth_kerb(struct svc_req *, struct rpc_msg *); /* for backward compatibility */ #include #endif /* KERBEROS */ #endif /* !_RPC_AUTH_KERB_H */ ntirpc-1.3.1/ntirpc/rpc/auth_unix.h000066400000000000000000000056471261345040100172630ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)auth_unix.h 1.8 88/02/08 SMI * from: @(#)auth_unix.h 2.2 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/auth_unix.h,v 1.11 2002/03/23 17:24:55 imp Exp $ */ /* * auth_unix.h, Protocol for UNIX style authentication parameters for RPC * * Copyright (C) 1984, Sun Microsystems, Inc. */ /* * The system is very weak. The client uses no encryption for it * credentials and only sends null verifiers. The server sends backs * null verifiers or optionally a verifier that suggests a new short hand * for the credentials. */ #ifndef _TIRPC_AUTH_UNIX_H #define _TIRPC_AUTH_UNIX_H #include /* The machine name is part of a credential; it may not exceed 255 bytes */ #define MAX_MACHINE_NAME 255 /* gids compose part of a credential; there may not be more than 16 of them */ #define NGRPS 16 /* * Unix style credentials. */ struct authunix_parms { u_long aup_time; char *aup_machname; uid_t aup_uid; gid_t aup_gid; u_int aup_len; gid_t *aup_gids; }; #define authsys_parms authunix_parms __BEGIN_DECLS extern bool xdr_authunix_parms(XDR *, struct authunix_parms *); __END_DECLS /* * If a response verifier has flavor AUTH_SHORT, * then the body of the response verifier encapsulates the following structure; * again it is serialized in the obvious fashion. */ struct short_hand_verf { struct opaque_auth new_cred; }; #endif /* !_TIRPC_AUTH_UNIX_H */ ntirpc-1.3.1/ntirpc/rpc/clnt.h000066400000000000000000000440401261345040100162050ustar00rootroot00000000000000/* $NetBSD: clnt.h,v 1.14 2000/06/02 22:57:55 fvdl Exp $ */ /* * Copyright (c) 2010, Oracle America, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the "Oracle America, Inc." nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)clnt.h 1.31 94/04/29 SMI * from: @(#)clnt.h 2.1 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/clnt.h,v 1.21 2003/01/24 01:47:55 fjoe Exp $ */ /* * clnt.h - Client side remote procedure call interface. */ #ifndef _TIRPC_CLNT_H_ #define _TIRPC_CLNT_H_ #include #include #include "reentrant.h" #include #include #if !defined(_WIN32) #include #endif /* * Well-known IPV6 RPC broadcast address. */ #define RPCB_MULTICAST_ADDR "ff02::202" /* * the following errors are in general unrecoverable. The caller * should give up rather than retry. */ #define IS_UNRECOVERABLE_RPC(s) (((s) == RPC_AUTHERROR) || \ ((s) == RPC_CANTENCODEARGS) || \ ((s) == RPC_CANTDECODERES) || \ ((s) == RPC_VERSMISMATCH) || \ ((s) == RPC_PROCUNAVAIL) || \ ((s) == RPC_PROGUNAVAIL) || \ ((s) == RPC_PROGVERSMISMATCH) || \ ((s) == RPC_CANTDECODEARGS)) /* * Error info. */ struct rpc_err { enum clnt_stat re_status; union { int RE_errno; /* related system error */ uint32_t RE_flags; enum auth_stat RE_why; /* why the auth error occurred */ struct { rpcvers_t low; /* lowest version supported */ rpcvers_t high; /* highest version supported */ } RE_vers; struct { /* maybe meaningful if RPC_FAILED */ int32_t s1; int32_t s2; } RE_lb; /* life boot & debugging only */ } ru; #define re_errno ru.RE_errno #define re_why ru.RE_why #define re_vers ru.RE_vers #define re_lb ru.RE_lb #define re_flags ru.RE_flags }; #define RPC_ERR_FLAGS_NONE 0x0000 #define RPC_ERR_FLAGS_ASYNC_REPLYFAIL 0x0001 /* * Client rpc handle. * Created by individual implementations * Client is responsible for initializing auth, see e.g. auth_none.c. */ typedef struct rpc_client { struct clnt_ops { /* call remote procedure */ enum clnt_stat (*cl_call) (struct rpc_client *, AUTH *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval); /* abort a call */ void (*cl_abort) (struct rpc_client *); /* get specific error code */ void (*cl_geterr) (struct rpc_client *, struct rpc_err *); /* frees results */ bool(*cl_freeres) (struct rpc_client *, xdrproc_t, void *); /* take lifecycle ref */ bool(*cl_ref) (struct rpc_client *, u_int flags); /* release */ void (*cl_release) (struct rpc_client *, u_int flags); /* release and mark destroyed */ void (*cl_destroy) (struct rpc_client *); /* the ioctl() of rpc */ bool(*cl_control) (struct rpc_client *, u_int, void *); } *cl_ops; mutex_t cl_lock; /* serialize private data */ uint32_t cl_refcnt; /* handle refcnt */ uint32_t cl_flags; /* state flags */ void *cl_p1; /* private data */ void *cl_p2; void *cl_p3; char *cl_netid; /* network token */ char *cl_tp; /* device name */ } CLIENT; /* * Timers used for the pseudo-transport protocol when using datagrams */ struct rpc_timers { u_short rt_srtt; /* smoothed round-trip time */ u_short rt_deviate; /* estimated deviation */ u_long rt_rtxcur; /* current (backed-off) rto */ }; /* * Feedback values used for possible congestion and rate control */ #define FEEDBACK_REXMIT1 1 /* first retransmit */ #define FEEDBACK_OK 2 /* no retransmits */ /* Used to set version of portmapper used in broadcast */ #define CLCR_SET_LOWVERS 3 #define CLCR_GET_LOWVERS 4 #define RPCSMALLMSGSIZE 400 /* a more reasonable packet size */ /* * CLNT flags */ #define CLNT_FLAG_NONE 0x0000 #define CLNT_FLAG_DESTROYED 0x0001 /* * CLNT_REF flags */ #define CLNT_REF_FLAG_NONE 0x0000 #define CLNT_REF_FLAG_LOCKED 0x0001 /* * CLNT_RELEASE flags */ #define CLNT_RELEASE_FLAG_NONE 0x0000 #define CLNT_RELEASE_FLAG_LOCKED 0x0001 /* * client side rpc interface ops * * Parameter types are: * */ /* * enum clnt_stat * CLNT_CALL(rh, proc, xargs, argsp, xres, resp, timeout) * CLIENT *rh; * AUTH * auth; * rpcproc_t proc; * xdrproc_t xargs; * void *argsp; * xdrproc_t xres; * void *resp; * struct timeval timeout; */ #define CLNT_CALL(rh, ah, proc, xargs, argsp, xres, resp, secs) \ ((*(rh)->cl_ops->cl_call)(rh, ah, proc, xargs, argsp, xres, resp, secs)) #define clnt_call(rh, ah, proc, xargs, argsp, xres, resp, secs) \ ((*(rh)->cl_ops->cl_call)(rh, ah, proc, xargs, argsp, xres, resp, secs)) /* * void * CLNT_ABORT(rh); * CLIENT *rh; */ #define CLNT_ABORT(rh) ((*(rh)->cl_ops->cl_abort)(rh)) #define clnt_abort(rh) ((*(rh)->cl_ops->cl_abort)(rh)) /* * struct rpc_err * CLNT_GETERR(rh); * CLIENT *rh; */ #define CLNT_GETERR(rh, errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) #define clnt_geterr(rh, errp) ((*(rh)->cl_ops->cl_geterr)(rh, errp)) /* * uint32_t flags * CLNT_REF(rh); * CLIENT *rh; */ #define CLNT_REF(rh, flags) ((*(rh)->cl_ops->cl_ref)(rh, flags)) #define clnt_ref(rh, flags) ((*(rh)->cl_ops->cl_ref)(rh, flags)) /* * uint32_t flags * CLNT_RELEASE(rh); * CLIENT *rh; */ #define CLNT_RELEASE(rh, flags) ((*(rh)->cl_ops->cl_release)(rh, flags)) #define clnt_release(rh, flags) ((*(rh)->cl_ops->cl_release)(rh, flags)) /* * bool * CLNT_FREERES(rh, xres, resp); * CLIENT *rh; * xdrproc_t xres; * void *resp; */ #define CLNT_FREERES(rh, xres, resp) \ ((*(rh)->cl_ops->cl_freeres)(rh, xres, resp)) #define clnt_freeres(rh, xres, resp) \ ((*(rh)->cl_ops->cl_freeres)(rh, xres, resp)) /* * bool * CLNT_CONTROL(cl, request, info) * CLIENT *cl; * u_int request; * char *info; */ #define CLNT_CONTROL(cl, rq, in) \ ((*(cl)->cl_ops->cl_control)(cl, rq, in)) #define clnt_control(cl, rq, in) \ ((*(cl)->cl_ops->cl_control)(cl, rq, in)) /* * control operations that apply to both udp and tcp transports */ #define CLSET_TIMEOUT 1 /* set timeout (timeval) */ #define CLGET_TIMEOUT 2 /* get timeout (timeval) */ #define CLGET_SERVER_ADDR 3 /* get server's address (sockaddr) */ #define CLGET_FD 6 /* get connections file descriptor */ #define CLGET_SVC_ADDR 7 /* get server's address (netbuf) */ #define CLSET_FD_CLOSE 8 /* close fd while clnt_destroy */ #define CLSET_FD_NCLOSE 9 /* Do not close fd while clnt_destroy */ #define CLGET_XID 10 /* Get xid */ #define CLSET_XID 11 /* Set xid */ #define CLGET_VERS 12 /* Get version number */ #define CLSET_VERS 13 /* Set version number */ #define CLGET_PROG 14 /* Get program number */ #define CLSET_PROG 15 /* Set program number */ #define CLSET_SVC_ADDR 16 /* get server's address (netbuf) */ #define CLSET_PUSH_TIMOD 17 /* push timod if not already present */ #define CLSET_POP_TIMOD 18 /* pop timod */ /* * Connectionless only control operations */ #define CLSET_RETRY_TIMEOUT 4 /* set retry timeout (timeval) */ #define CLGET_RETRY_TIMEOUT 5 /* get retry timeout (timeval) */ #define CLSET_ASYNC 19 #define CLSET_CONNECT 20 /* Use connect() for UDP. (int) */ /* * void * CLNT_DESTROY(rh); * CLIENT *rh; */ #define CLNT_DESTROY(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) #define clnt_destroy(rh) ((*(rh)->cl_ops->cl_destroy)(rh)) /* * RPCTEST is a test program which is accessible on every rpc * transport/port. It is used for testing, performance evaluation, * and network administration. */ #define RPCTEST_PROGRAM ((rpcprog_t)1) #define RPCTEST_VERSION ((rpcvers_t)1) #define RPCTEST_NULL_PROC ((rpcproc_t)2) #define RPCTEST_NULL_BATCH_PROC ((rpcproc_t)3) /* * By convention, procedure 0 takes null arguments and returns them */ #define NULLPROC ((rpcproc_t)0) /* * Below are the client handle creation routines for the various * implementations of client side rpc. They can return NULL if a * creation failure occurs. */ /* * Generic client creation routine. Supported protocols are those that * belong to the nettype namespace (/etc/netconfig). */ __BEGIN_DECLS extern CLIENT * clnt_ncreate(const char *, const rpcprog_t, const rpcvers_t, const char *); /* * * const char *hostname; -- hostname * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const char *nettype; -- network type */ /* * Generic client creation routine. Just like clnt_create(), except * it takes an additional timeout parameter. */ extern CLIENT *clnt_ncreate_timed(const char *, const rpcprog_t, const rpcvers_t, const char *, const struct timeval *); /* * * const char *hostname; -- hostname * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const char *nettype; -- network type * const struct timeval *tp; -- timeout */ /* * Generic client creation routine. Supported protocols are which belong * to the nettype name space. */ extern CLIENT *clnt_ncreate_vers(const char *, const rpcprog_t, rpcvers_t *, const rpcvers_t, const rpcvers_t, const char *); /* * const char *host; -- hostname * const rpcprog_t prog; -- program number * rpcvers_t *vers_out; -- servers highest available version * const rpcvers_t vers_low; -- low version number * const rpcvers_t vers_high; -- high version number * const char *nettype; -- network type */ /* * Generic client creation routine. Supported protocols are which belong * to the nettype name space. */ extern CLIENT *clnt_ncreate_vers_timed(const char *, const rpcprog_t, rpcvers_t *, const rpcvers_t, const rpcvers_t, const char *, const struct timeval *); /* * const char *host; -- hostname * const rpcprog_t prog; -- program number * rpcvers_t *vers_out; -- servers highest available version * const rpcvers_t vers_low; -- low version number * const rpcvers_t vers_high; -- high version number * const char *nettype; -- network type * const struct timeval *tp -- timeout */ /* * Generic client creation routine. It takes a netconfig structure * instead of nettype */ extern CLIENT *clnt_tp_ncreate(const char *, const rpcprog_t, const rpcvers_t, const struct netconfig *); /* * const char *hostname; -- hostname * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const struct netconfig *netconf; -- network config structure */ /* * Generic client creation routine. Just like clnt_tp_create(), except * it takes an additional timeout parameter. */ extern CLIENT *clnt_tp_ncreate_timed(const char *, const rpcprog_t, const rpcvers_t, const struct netconfig *, const struct timeval *); /* * const char *hostname; -- hostname * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const struct netconfig *netconf; -- network config structure * const struct timeval *tp -- timeout */ /* * Generic TLI create routine. Only provided for compatibility. */ extern CLIENT *clnt_tli_ncreate(const int, const struct netconfig *, struct netbuf *, const rpcprog_t, const rpcvers_t, const u_int, const u_int); /* * const register int fd; -- fd * const struct netconfig *nconf; -- netconfig structure * struct netbuf *svcaddr; -- servers address * const u_long prog; -- program number * const u_long vers; -- version number * const u_int sendsz; -- send size * const u_int recvsz; -- recv size */ /* * Low level clnt create routines for connectionful transports, e.g. tcp. */ #define CLNT_CREATE_FLAG_NONE 0x0000 #define CLNT_CREATE_FLAG_CONNECT 0x0001 #define CLNT_CREATE_FLAG_SVCXPRT 0x0002 extern CLIENT *clnt_vc_ncreate(const int, const struct netbuf *, const rpcprog_t, const rpcvers_t, u_int, u_int); extern CLIENT *clnt_vc_ncreate2(const int, const struct netbuf *, const rpcprog_t, const rpcvers_t, u_int, u_int, u_int); #if !defined(_WIN32) /* * Added for compatibility to old rpc 4.0. Obsoleted by clnt_vc_create(). */ extern CLIENT *clntunix_ncreate(struct sockaddr_un *, u_long, u_long, int *, u_int, u_int); #endif /* * const int fd; -- open file descriptor * const struct netbuf *svcaddr; -- servers address * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const u_int sendsz; -- buffer recv size * const u_int recvsz; -- buffer send size */ /* * Low level clnt create routine for connectionless transports, e.g. udp. */ extern CLIENT *clnt_dg_ncreate(const int, const struct netbuf *, const rpcprog_t, const rpcvers_t, const u_int, const u_int); /* * const int fd; -- open file descriptor * const struct netbuf *svcaddr; -- servers address * const rpcprog_t program; -- program number * const rpcvers_t version; -- version number * const u_int sendsz; -- buffer recv size * const u_int recvsz; -- buffer send size */ /* * Memory based rpc (for speed check and testing) * CLIENT * * clnt_raw_create(prog, vers) * u_long prog; * u_long vers; */ extern CLIENT *clnt_raw_ncreate(rpcprog_t, rpcvers_t); __END_DECLS /* * Print why creation failed */ __BEGIN_DECLS extern void clnt_pcreateerror(const char *); /* stderr */ extern char *clnt_spcreateerror(const char *); /* string */ __END_DECLS /* * Like clnt_perror(), but is more verbose in its output */ __BEGIN_DECLS extern void clnt_perrno(enum clnt_stat); /* stderr */ extern char *clnt_sperrno(enum clnt_stat); /* string */ __END_DECLS /* * Print an English error message, given the client error code */ __BEGIN_DECLS extern void clnt_perror(CLIENT *, const char *); /* stderr */ extern char *clnt_sperror(CLIENT *, const char *); /* string */ __END_DECLS /* * If a creation fails, the following allows the user to figure out why. */ struct rpc_createerr { enum clnt_stat cf_stat; struct rpc_err cf_error; /* useful when cf_stat == RPC_PMAPFAILURE */ }; __BEGIN_DECLS extern struct rpc_createerr *__rpc_createerr(void); __END_DECLS #define get_rpc_createerr() (*(__rpc_createerr())) #define rpc_createerr (*(__rpc_createerr())) /* * The simplified interface: * enum clnt_stat * rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype) * const char *host; * const rpcprog_t prognum; * const rpcvers_t versnum; * const rpcproc_t procnum; * const xdrproc_t inproc, outproc; * const char *in; * char *out; * const char *nettype; */ __BEGIN_DECLS extern enum clnt_stat rpc_call(const char *, const rpcprog_t, const rpcvers_t, const rpcproc_t, const xdrproc_t, const char *, const xdrproc_t, char *, const char *); __END_DECLS /* * RPC broadcast interface * The call is broadcasted to all locally connected nets. * * extern enum clnt_stat * rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, * eachresult, nettype) * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const rpcproc_t proc; -- procedure number * const xdrproc_t xargs; -- xdr routine for args * caddr_t argsp; -- pointer to args * const xdrproc_t xresults; -- xdr routine for results * caddr_t resultsp; -- pointer to results * const resultproc_t eachresult; -- call with each result * const char *nettype; -- Transport type * * For each valid response received, the procedure eachresult is called. * Its form is: * done = eachresult(resp, raddr, nconf) * bool done; * caddr_t resp; * struct netbuf *raddr; * struct netconfig *nconf; * where resp points to the results of the call and raddr is the * address if the responder to the broadcast. nconf is the transport * on which the response was received. * * extern enum clnt_stat * rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp, * eachresult, inittime, waittime, nettype) * const rpcprog_t prog; -- program number * const rpcvers_t vers; -- version number * const rpcproc_t proc; -- procedure number * const xdrproc_t xargs; -- xdr routine for args * caddr_t argsp; -- pointer to args * const xdrproc_t xresults; -- xdr routine for results * caddr_t resultsp; -- pointer to results * const resultproc_t eachresult; -- call with each result * const int inittime; -- how long to wait initially * const int waittime; -- maximum time to wait * const char *nettype; -- Transport type */ typedef bool(*resultproc_t) (caddr_t, ...); __BEGIN_DECLS extern enum clnt_stat rpc_broadcast(const rpcprog_t, const rpcvers_t, const rpcproc_t, const xdrproc_t, caddr_t, const xdrproc_t, caddr_t, const resultproc_t, const char *); extern enum clnt_stat rpc_broadcast_exp(const rpcprog_t, const rpcvers_t, const rpcproc_t, const xdrproc_t, caddr_t, const xdrproc_t, caddr_t, const resultproc_t, const int, const int, const char *); __END_DECLS /* For backward compatibility */ #include #include #endif /* !_TIRPC_CLNT_H_ */ ntirpc-1.3.1/ntirpc/rpc/clnt_soc.h000066400000000000000000000072561261345040100170610ustar00rootroot00000000000000/* $NetBSD: clnt_soc.h,v 1.1 2000/06/02 22:57:55 fvdl Exp $ */ /* $FreeBSD: src/include/rpc/clnt_soc.h,v 1.2 2002/03/23 17:24:55 * imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1984 - 1991 by Sun Microsystems, Inc. */ /* * clnt.h - Client side remote procedure call interface. */ #ifndef _RPC_CLNT_SOC_H #define _RPC_CLNT_SOC_H /* derived from clnt_soc.h 1.3 88/12/17 SMI */ /* * All the following declarations are only for backward compatibility * with TS-RPC. */ #include #define UDPMSGSIZE 8800 /* rpc imposed limit on udp msg size */ /* * TCP based rpc * CLIENT * * clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; * u_long prog; * u_long version; * register int *sockp; * u_int sendsz; * u_int recvsz; */ __BEGIN_DECLS extern CLIENT * clnttcp_ncreate(struct sockaddr_in *, u_long, u_long, int *, u_int, u_int); __END_DECLS /* * Raw (memory) rpc. */ __BEGIN_DECLS extern CLIENT *clntraw_ncreate(u_long, u_long); __END_DECLS /* IPv6 socket version */ #ifdef INET6 __BEGIN_DECLS extern CLIENT *clnttcp6_ncreate(struct sockaddr_in6 *, u_long, u_long, int *, u_int, u_int); __END_DECLS #endif /* * UDP based rpc. * CLIENT * * clntudp_create(raddr, program, version, wait, sockp) * struct sockaddr_in *raddr; * u_long program; * u_long version; * struct timeval wait; * int *sockp; * * Same as above, but you specify max packet sizes. * CLIENT * * clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz) * struct sockaddr_in *raddr; * u_long program; * u_long version; * struct timeval wait; * int *sockp; * u_int sendsz; * u_int recvsz; */ __BEGIN_DECLS extern CLIENT *clntudp_ncreate(struct sockaddr_in *, u_long, u_long, struct timeval, int *); extern CLIENT *clntudp_nbufcreate(struct sockaddr_in *, u_long, u_long, struct timeval, int *, u_int, u_int); #ifdef INET6 extern CLIENT *clntudp6_ncreate(struct sockaddr_in6 *, u_long, u_long, struct timeval, int *); extern CLIENT *clntudp6_nbufcreate(struct sockaddr_in6 *, u_long, u_long, struct timeval, int *, u_int, u_int); #endif __END_DECLS #endif /* _RPC_CLNT_SOC_H */ ntirpc-1.3.1/ntirpc/rpc/clnt_stat.h000066400000000000000000000042701261345040100172410ustar00rootroot00000000000000/* $FreeBSD: src/include/rpc/clnt_stat.h,v 1.2 2001/03/20 * 08:20:50 alfred Exp $ */ /* * Copyright (c) 1986 - 1991, 1994, 1996, 1997 by Sun Microsystems, Inc. * All rights reserved. */ /* * clnt_stat.h - Client side remote procedure call enum * */ #ifndef _RPC_CLNT_STAT_H #define _RPC_CLNT_STAT_H /* #pragma ident "@(#)clnt_stat.h 1.2 97/04/28 SMI" */ #ifdef __cplusplus extern "C" { #endif enum clnt_stat { RPC_SUCCESS = 0, /* call succeeded */ /* * local errors */ RPC_CANTENCODEARGS = 1, /* can't encode arguments */ RPC_CANTDECODERES = 2, /* can't decode results */ RPC_CANTSEND = 3, /* failure in sending call */ RPC_CANTRECV = 4, /* failure in receiving result */ RPC_TIMEDOUT = 5, /* call timed out */ RPC_INTR = 18, /* call interrupted */ RPC_UDERROR = 23, /* recv got uderr indication */ /* * remote errors */ RPC_VERSMISMATCH = 6, /* rpc versions not compatible */ RPC_AUTHERROR = 7, /* authentication error */ RPC_PROGUNAVAIL = 8, /* program not available */ RPC_PROGVERSMISMATCH = 9, /* program version mismatched */ RPC_PROCUNAVAIL = 10, /* procedure unavailable */ RPC_CANTDECODEARGS = 11, /* decode arguments error */ RPC_SYSTEMERROR = 12, /* generic "other problem" */ /* * rpc_call & clnt_create errors */ RPC_UNKNOWNHOST = 13, /* unknown host name */ RPC_UNKNOWNPROTO = 17, /* unknown protocol */ RPC_UNKNOWNADDR = 19, /* Remote address unknown */ RPC_NOBROADCAST = 21, /* Broadcasting not supported */ /* * rpcbind errors */ RPC_RPCBFAILURE = 14, /* the pmapper failed in its call */ #define RPC_PMAPFAILURE RPC_RPCBFAILURE RPC_PROGNOTREGISTERED = 15,/* remote program not registered */ RPC_N2AXLATEFAILURE = 22, /* Name to address translation failed */ /* * Misc error in the TLI library */ RPC_TLIERROR = 20, /* * unspecified error */ RPC_FAILED = 16, /* * asynchronous errors */ RPC_INPROGRESS = 24, RPC_STALERACHANDLE = 25, RPC_CANTCONNECT = 26, /* couldn't make connection (cots) */ RPC_XPRTFAILED = 27, /* received discon from remote (cots) */ RPC_CANTCREATESTREAM = 28 /* can't push rpc module (cots) */ }; #ifdef __cplusplus } #endif #endif /* !_RPC_CLNT_STAT_H */ ntirpc-1.3.1/ntirpc/rpc/des.h000066400000000000000000000057331261345040100160260ustar00rootroot00000000000000/* @(#)des.h 2.2 88/08/10 4.0 RPCSRC; from 2.7 88/02/08 SMI */ /* $FreeBSD: src/include/rpc/des.h,v 1.4 2002/03/23 17:24:55 imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Generic DES driver interface * Keep this file hardware independent! * Copyright (c) 1986 by Sun Microsystems, Inc. */ #ifndef _RPC_DES_H_ #define _RPC_DES_H_ #define DES_MAXLEN 65536 /* maximum # of bytes to encrypt */ #define DES_QUICKLEN 16 /* maximum # of bytes to encrypt quickly */ enum desdir { ENCRYPT, DECRYPT }; enum desmode { CBC, ECB }; /* * parameters to ioctl call */ struct desparams { u_char des_key[8]; /* key (with low bit parity) */ enum desdir des_dir; /* direction */ enum desmode des_mode; /* mode */ u_char des_ivec[8]; /* input vector */ unsigned des_len; /* number of bytes to crypt */ union { u_char UDES_data[DES_QUICKLEN]; u_char *UDES_buf; } UDES; # define des_data UDES.UDES_data /* direct data here if quick */ # define des_buf UDES.UDES_buf /* otherwise, pointer to data */ }; #ifdef notdef /* * These ioctls are only implemented in SunOS. Maybe someday * if somebody writes a driver for DES hardware that works * with FreeBSD, we can being that back. */ /* * Encrypt an arbitrary sized buffer */ #define DESIOCBLOCK _IOWR('d', 6, struct desparams) /* * Encrypt of small amount of data, quickly */ #define DESIOCQUICK _IOWR('d', 7, struct desparams) #endif /* * Software DES. */ extern int _des_crypt(char *, int, struct desparams *); #endif ntirpc-1.3.1/ntirpc/rpc/des_crypt.h000066400000000000000000000070201261345040100172360ustar00rootroot00000000000000/* * @(#)des_crypt.h 2.1 88/08/11 4.0 RPCSRC; from 1.4 88/02/08 (C) 1986 * SMI $FreeBSD: src/include/rpc/des_crypt.h,v 1.4 2002/03/23 17:24:55 * imp Exp $ * * des_crypt.h, des library routine interface * Copyright (C) 1986, Sun Microsystems, Inc. */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * des_crypt.h, des library routine interface */ #ifndef _DES_DES_CRYPT_H #define _DES_DES_CRYPT_H #include #include #define DES_MAXDATA 8192 /* max bytes encrypted in one call */ #define DES_DIRMASK (1 << 0) #define DES_ENCRYPT (0*DES_DIRMASK) /* Encrypt */ #define DES_DECRYPT (1*DES_DIRMASK) /* Decrypt */ #define DES_DEVMASK (1 << 1) #define DES_HW (0*DES_DEVMASK) /* Use hardware device */ #define DES_SW (1*DES_DEVMASK) /* Use software device */ #define DESERR_NONE 0 /* succeeded */ #define DESERR_NOHWDEVICE 1 /* succeeded, but hw device not available */ #define DESERR_HWERROR 2 /* failed, hardware/driver error */ #define DESERR_BADPARAM 3 /* failed, bad parameter to call */ #define DES_FAILED(err) \ ((err) > DESERR_NOHWDEVICE) /* * cbc_crypt() * ecb_crypt() * * Encrypt (or decrypt) len bytes of a buffer buf. * The length must be a multiple of eight. * The key should have odd parity in the low bit of each byte. * ivec is the input vector, and is updated to the new one (cbc only). * The mode is created by oring together the appropriate parameters. * DESERR_NOHWDEVICE is returned if DES_HW was specified but * there was no hardware to do it on (the data will still be * encrypted though, in software). */ /* * Cipher Block Chaining mode */ __BEGIN_DECLS int cbc_crypt(char *, char *, unsigned int, unsigned int, char *); __END_DECLS /* * Electronic Code Book mode */ __BEGIN_DECLS int ecb_crypt(char *, char *, unsigned int, unsigned int); __END_DECLS /* * Set des parity for a key. * DES parity is odd and in the low bit of each byte */ __BEGIN_DECLS void des_setparity(char *); __END_DECLS #endif /* _DES_DES_CRYPT_H */ ntirpc-1.3.1/ntirpc/rpc/gss_internal.h000066400000000000000000000101771261345040100177410ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GSS_INTERNAL_H #define GSS_INTERNAL_H #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_HEIMDAL #include #define gss_nt_service_name GSS_C_NT_HOSTBASED_SERVICE #else #include #include #include #endif #include extern SVCAUTH svc_auth_none; #define SVCAUTH_PRIVATE(auth) \ ((struct svc_rpc_gss_data *)(auth)->svc_ah_private) /* * from mit-krb5-1.2.1 mechglue/mglueP.h: * Array of context IDs typed by mechanism OID */ struct gss_union_ctx_id { gss_OID mech_type; gss_ctx_id_t internal_ctx_id; }; typedef struct gss_union_ctx_id gss_union_ctx_id_desc; typedef gss_union_ctx_id_desc *gss_union_ctx_id_t; #define SVC_RPC_GSS_FLAG_NONE 0x0000 #define SVC_RPC_GSS_FLAG_MSPAC 0x0001 #define SVC_RPC_GSS_FLAG_LOCKED 0x0002 struct svc_rpc_gss_data { struct opr_rbtree_node node_k; TAILQ_ENTRY(svc_rpc_gss_data) lru_q; mutex_t lock; uint32_t flags; uint32_t refcnt; uint32_t gen; struct { uint32_t k; } hk; bool established; gss_ctx_id_t ctx; /* context id */ struct rpc_gss_sec sec; /* security triple */ gss_buffer_desc cname; /* GSS client name */ u_int seq; u_int win; u_int seqlast; uint32_t seqmask; gss_name_t client_name; gss_buffer_desc checksum; struct { /* extended krb5 ticket ("pac") data */ gss_buffer_desc ms_pac; } pac; SVCAUTH *auth; uint32_t endtime; }; bool svcauth_gss_destroy(SVCAUTH *auth); static inline struct svc_rpc_gss_data *alloc_svc_rpc_gss_data(void) { struct svc_rpc_gss_data *gd = (struct svc_rpc_gss_data *) mem_zalloc(sizeof(struct svc_rpc_gss_data)); mutex_init(&gd->lock, NULL); TAILQ_INIT_ENTRY(gd, lru_q); gd->refcnt = 1; return (gd); } static inline void unref_svc_rpc_gss_data(struct svc_rpc_gss_data *gd, uint32_t flags) { u_int refcnt; bool gd_locked = flags & SVC_RPC_GSS_FLAG_LOCKED; refcnt = atomic_dec_uint32_t(&gd->refcnt); /* if refcnt is 0, gd is not reachable */ if (unlikely(refcnt == 0)) { if (!gd_locked) { mutex_lock(&gd->lock); gd_locked = true; if (likely(refcnt == 0)) { mutex_unlock(&gd->lock); /* XXX disposes gd */ svcauth_gss_destroy(gd->auth); return; } } } if (gd_locked) mutex_unlock(&gd->lock); } void authgss_hash_init(); struct svc_rpc_gss_data *authgss_ctx_hash_get(struct rpc_gss_cred *gc); bool authgss_ctx_hash_set(struct svc_rpc_gss_data *gd); bool authgss_ctx_hash_del(struct svc_rpc_gss_data *gd); bool svcauth_gss_acquire_cred(void); bool svcauth_gss_release_cred(void); bool svcauth_gss_import_name(char *service); bool svcauth_gss_set_svc_name(gss_name_t name); #endif /* GSS_INTERNAL_H */ ntirpc-1.3.1/ntirpc/rpc/nettype.h000066400000000000000000000047221261345040100167400ustar00rootroot00000000000000/* $NetBSD: nettype.h,v 1.2 2000/07/06 03:17:19 christos Exp $ */ /* $FreeBSD: src/include/rpc/nettype.h,v 1.2 2002/03/23 17:24:55 * imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * nettype.h, Nettype definitions. * All for the topmost layer of rpc * */ #ifndef _TIRPC_NETTYPE_H #define _TIRPC_NETTYPE_H #include #define _RPC_NONE 0 #define _RPC_NETPATH 1 #define _RPC_VISIBLE 2 #define _RPC_CIRCUIT_V 3 #define _RPC_DATAGRAM_V 4 #define _RPC_CIRCUIT_N 5 #define _RPC_DATAGRAM_N 6 #define _RPC_TCP 7 #define _RPC_UDP 8 __BEGIN_DECLS extern void *__rpc_setconf(const char *); extern void __rpc_endconf(void *); extern struct netconfig *__rpc_getconf(void *); extern struct netconfig *__rpc_getconfip(const char *); extern struct netbuf *rpcb_find_mapped_addr(char *nettype, rpcprog_t prog, rpcvers_t vers, char *local_addr); __END_DECLS #endif /* !_TIRPC_NETTYPE_H */ ntirpc-1.3.1/ntirpc/rpc/pmap_clnt.h000066400000000000000000000065521261345040100172300ustar00rootroot00000000000000/* $NetBSD: pmap_clnt.h,v 1.9 2000/06/02 22:57:55 fvdl Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)pmap_clnt.h 1.11 88/02/08 SMI * from: @(#)pmap_clnt.h 2.1 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/pmap_clnt.h,v 1.14 2002/04/28 15:18:45 des Exp $ */ /* * pmap_clnt.h * Supplies C routines to get to portmap services. * * Copyright (C) 1984, Sun Microsystems, Inc. */ /* * Usage: * success = pmap_set(program, version, protocol, port); * success = pmap_unset(program, version); * port = pmap_getport(address, program, version, protocol); * head = pmap_getmaps(address); * clnt_stat = pmap_rmtcall(address, program, version, procedure, * xdrargs, argsp, xdrres, resp, tout, port_ptr) * (works for udp only.) * clnt_stat = clnt_broadcast(program, version, procedure, * xdrargs, argsp, xdrres, resp, eachresult) * (like pmap_rmtcall, except the call is broadcasted to all * locally connected nets. For each valid response received, * the procedure eachresult is called. Its form is: * done = eachresult(resp, raddr) * bool done; * caddr_t resp; * struct sockaddr_in raddr; * where resp points to the results of the call and raddr is the * address if the responder to the broadcast. */ #ifndef _RPC_PMAP_CLNT_H_ #define _RPC_PMAP_CLNT_H_ #include __BEGIN_DECLS extern bool pmap_set(u_long, u_long, int, int); extern bool pmap_unset(u_long, u_long); extern struct pmaplist *pmap_getmaps(struct sockaddr_in *); extern enum clnt_stat pmap_rmtcall(struct sockaddr_in *, u_long, u_long, u_long, xdrproc_t, caddr_t, xdrproc_t, caddr_t, struct timeval, u_long *); extern enum clnt_stat clnt_broadcast(u_long, u_long, u_long, xdrproc_t, void *, xdrproc_t, void *, resultproc_t); extern u_short pmap_getport(struct sockaddr_in *, u_long, u_long, u_int); __END_DECLS #endif /* !_RPC_PMAP_CLNT_H_ */ ntirpc-1.3.1/ntirpc/rpc/pmap_prot.h000066400000000000000000000073441261345040100172540ustar00rootroot00000000000000/* * pmap_prot.h * Protocol for the local binder service, or pmap. * * Copyright (c) 2010, Oracle America, Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are * met: * * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * Neither the name of the "Oracle America, Inc." nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _RPC_PMAP_PROT_H #define _RPC_PMAP_PROT_H 1 #if defined(__linux__) #include #endif #include __BEGIN_DECLS /* The following procedures are supported by the protocol: * * PMAPPROC_NULL() returns () * takes nothing, returns nothing * * PMAPPROC_SET(struct pmap) returns (bool) * TRUE is success, FALSE is failure. Registers the tuple * [prog, vers, prot, port]. * * PMAPPROC_UNSET(struct pmap) returns (bool) * TRUE is success, FALSE is failure. Un-registers pair * [prog, vers]. prot and port are ignored. * * PMAPPROC_GETPORT(struct pmap) returns (long unsigned). * 0 is failure. Otherwise returns the port number where the pair * [prog, vers] is registered. It may lie! * * PMAPPROC_DUMP() RETURNS (struct pmaplist *) * * PMAPPROC_CALLIT(unsigned, unsigned, unsigned, string<>) RETURNS * (port, string<>); usage: encapsulatedresults = * PMAPPROC_CALLIT(prog, vers, proc, encapsulatedargs); Calls the * procedure on the local machine. If it is not registered, this * procedure is quite; ie it does not return error information!!! * This procedure only is supported on rpc/udp and calls via rpc/udp. * This routine only passes null authentication parameters. This file * has no interface to xdr routines for PMAPPROC_CALLIT. * * The service supports remote procedure calls on udp/ip or tcp/ip socket 111. */ #define PMAPPORT ((u_short)111) #define PMAPPROG ((u_long)100000) #define PMAPVERS ((u_long)2) #define PMAPVERS_PROTO ((u_long)2) #define PMAPVERS_ORIG ((u_long)1) #define PMAPPROC_NULL ((u_long)0) #define PMAPPROC_SET ((u_long)1) #define PMAPPROC_UNSET ((u_long)2) #define PMAPPROC_GETPORT ((u_long)3) #define PMAPPROC_DUMP ((u_long)4) #define PMAPPROC_CALLIT ((u_long)5) struct pmap { long unsigned pm_prog; long unsigned pm_vers; long unsigned pm_prot; long unsigned pm_port; }; extern bool xdr_pmap(XDR *__xdrs, struct pmap *__regs); struct pmaplist { struct pmap pml_map; struct pmaplist *pml_next; }; extern bool xdr_pmaplist(XDR *__xdrs, struct pmaplist **__rp); __END_DECLS #endif /* rpc/pmap_prot.h */ ntirpc-1.3.1/ntirpc/rpc/pmap_rmt.h000066400000000000000000000045761261345040100170760ustar00rootroot00000000000000/* $NetBSD: pmap_rmt.h,v 1.7 1998/02/11 23:01:23 lukem Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)pmap_rmt.h 1.2 88/02/08 SMI * from: @(#)pmap_rmt.h 2.1 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/pmap_rmt.h,v 1.12 2002/03/23 17:24:55 imp Exp $ */ /* * Structures and XDR routines for parameters to and replies from * the portmapper remote-call-service. * * Copyright (C) 1986, Sun Microsystems, Inc. */ #ifndef _RPC_PMAP_RMT_H #define _RPC_PMAP_RMT_H #include struct rmtcallargs { u_long prog, vers, proc, arglen; caddr_t args_ptr; xdrproc_t xdr_args; }; struct rmtcallres { u_long *port_ptr; u_long resultslen; caddr_t results_ptr; xdrproc_t xdr_results; }; __BEGIN_DECLS extern bool xdr_rmtcall_args(XDR *, struct rmtcallargs *); extern bool xdr_rmtcallres(XDR *, struct rmtcallres *); __END_DECLS #endif /* !_RPC_PMAP_RMT_H */ ntirpc-1.3.1/ntirpc/rpc/pool_queue.h000066400000000000000000000045671261345040100174340ustar00rootroot00000000000000/* * Copyright (c) 2013-2015 CohortFS, LLC. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /** * @file pool_queue.h * @author William Allen Simpson * @brief Pthreads-based TAILQ package * * @section DESCRIPTION * * This provides simple queues using pthreads and TAILQ primitives. * * @note Loosely based upon previous wait_queue by * Matt Benjamin */ #ifndef POOL_QUEUE_H #define POOL_QUEUE_H #include #include #include struct poolq_entry { TAILQ_ENTRY(poolq_entry) q; /*** 1st ***/ u_int qsize; /* allocated size of q entry, * 0: default size */ u_int qflags; }; struct poolq_head { TAILQ_HEAD(q_head, poolq_entry) qh; pthread_mutex_t qmutex; u_int qsize; /* default size of q entries, * 0: static size */ int qcount; /* number of entries, * < 0: has waiting workers. */ }; static inline void poolq_head_destroy(struct poolq_head *qh) { pthread_mutex_destroy(&qh->qmutex); } static inline void poolq_head_setup(struct poolq_head *qh) { TAILQ_INIT(&qh->qh); pthread_mutex_init(&qh->qmutex, NULL); qh->qcount = 0; } #endif /* POOL_QUEUE_H */ ntirpc-1.3.1/ntirpc/rpc/raw.h000066400000000000000000000041121261345040100160320ustar00rootroot00000000000000/* $NetBSD: raw.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */ /* $FreeBSD: src/include/rpc/raw.h,v 1.1 2001/03/19 12:49:47 * alfred Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ #ifndef _RPC_RAW_H #define _RPC_RAW_H /* from: @(#)raw.h 1.11 94/04/25 SMI */ /* from: @(#)raw.h 1.2 88/10/25 SMI */ #ifdef __cplusplus extern "C" { #endif /* * raw.h * * Raw interface * The common memory area over which they will communicate */ extern char *__rpc_rawcombuf; #ifdef __cplusplus } #endif #endif /* _RPC_RAW_H */ ntirpc-1.3.1/ntirpc/rpc/rpc.h000066400000000000000000000101771261345040100160350ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * rpc.h, Just includes the billions of rpc header files necessary to * do remote procedure calling. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef _TIRPC_RPC_H #define _TIRPC_RPC_H #include /* some typedefs */ #if defined(_WIN32) #include #else #include #include #endif /* external data representation interfaces */ #include /* generic (de)serializer */ /* Client side only authentication */ #include /* generic authenticator (client side) */ /* Client side (mostly) remote procedure call */ #include /* generic rpc stuff */ /* semi-private protocol headers */ #include /* protocol for rpc messages */ #include /* protocol for unix style cred */ /* * Uncomment-out the next line if you are building the rpc library with * DES Authentication (see the README file in the secure_rpc/ directory). */ #include /* protocol for des style cred */ #ifdef HAVE_RPCSEC_GSS #include /* RPCSEC_GSS */ #endif /* Server side only remote procedure callee */ #include /* service manager and multiplexer */ /* Portmapper client, server, and protocol headers */ #include #include #ifndef _KERNEL #include /* rpcbind interface functions */ #endif #include #ifndef UDPMSGSIZE #define UDPMSGSIZE 8800 #endif __BEGIN_DECLS extern int get_myaddress(struct sockaddr_in *); extern int bindresvport(int, struct sockaddr_in *); extern int registerrpc(int, int, int, char *(*)(char[UDPMSGSIZE]), xdrproc_t, xdrproc_t); extern int callrpc(const char *, int, int, int, xdrproc_t, void *, xdrproc_t, void *); extern int getrpcport(char *, int, int, int); char *taddr2uaddr(const struct netconfig *, const struct netbuf *); struct netbuf *uaddr2taddr(const struct netconfig *, const char *); struct sockaddr; extern int bindresvport_sa(int, struct sockaddr *); extern bool tirpc_control(const u_int, void *); extern void *__mem_alloc(size_t); extern void __mem_free(void *, size_t); __END_DECLS /* * The following are not exported interfaces, they are for internal library * and rpcbind use only. Do not use, they may change without notice. */ __BEGIN_DECLS int __rpc_nconf2fd(const struct netconfig *); int __rpc_nconf2fd_flags(const struct netconfig *, int); int __rpc_nconf2sockinfo(const struct netconfig *, struct __rpc_sockinfo *); int __rpc_fd2sockinfo(int, struct __rpc_sockinfo *); u_int __rpc_get_t_size(int, int, int); __END_DECLS #endif /* !_RPC_RPC_H */ ntirpc-1.3.1/ntirpc/rpc/rpc_cksum.h000066400000000000000000000042361261345040100172360ustar00rootroot00000000000000/*- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. */ /* * First, the polynomial itself and its table of feedback terms. The * polynomial is * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * * Note that we take it "backwards" and put the highest-order term in * the lowest-order bit. The X^32 term is "implied"; the LSB is the * X^31 term, etc. The X^0 term (usually shown as "+1") results in * the MSB being 1 * * Note that the usual hardware shift register implementation, which * is what we're using (we're merely optimizing it by doing eight-bit * chunks at a time) shifts bits into the lowest-order term. In our * implementation, that means shifting towards the right. Why do we * do it this way? Because the calculated CRC must be transmitted in * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way * we hand it to the UART in the order low-byte to high-byte; the UART * sends each low-bit to hight-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly * * The feedback terms table consists of 256, 32-bit entries. Notes * * The table can be generated at runtime if desired; code to do so * is shown later. It might not be obvious, but the feedback * terms simply represent the results of eight shift/xor opera * tions for all combinations of data and CRC register values * * The values must be right-shifted by eight bits by the "updcrc * logic; the shift must be unsigned (bring in zeroes). On some * hardware you could probably optimize the shift in assembler by * using byte-swap instructions * polynomial $edb88320 * * * CRC32 code derived from work by Gary S. Brown. */ #ifndef RPC_CKSUM_H #define RPC_CKSUM_H /* table-driven, software crc32c */ uint32_t calculate_crc32c(uint32_t crc32c, const unsigned char *buffer, unsigned int length); #endif /* RPC_CKSUM_H */ ntirpc-1.3.1/ntirpc/rpc/rpc_com.h000066400000000000000000000061201261345040100166640ustar00rootroot00000000000000/* $NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $ */ /* $FreeBSD: src/include/rpc/rpc_com.h,v 1.6 2003/01/16 07:13:51 mbr Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * rpc_com.h, Common definitions for both the server and client side. * All for the topmost layer of rpc * */ #ifndef _RPC_RPCCOM_H #define _RPC_RPCCOM_H #include /* #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */ /* * The max size of the transport, if the size cannot be determined * by other means. */ #define RPC_MAXDATASIZE 9000 #define RPC_MAXADDRSIZE 1024 #define __RPC_GETXID(now) \ ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \ (u_int32_t)(now)->tv_usec) __BEGIN_DECLS extern u_int __rpc_get_a_size(int); extern int __rpc_dtbsize(void); extern int _rpc_dtablesize(void); extern struct netconfig *__rpcgettp(int); extern 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 *__rpc_set_netbuf(struct netbuf *, const void *, size_t); struct netbuf *__rpcb_findaddr(rpcprog_t, rpcvers_t, const struct netconfig *, const char *, CLIENT **); bool rpc_control(int, void *); char *_get_next_token(char *, int); __END_DECLS #endif /* _RPC_RPCCOM_H */ ntirpc-1.3.1/ntirpc/rpc/rpc_dplx.h000066400000000000000000000057251261345040100170670ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RPC_DPLX_H #define RPC_DPLX_H /* SVCXPRT variants */ /* slx: send lock xprt */ #define rpc_dplx_slx(xprt) \ rpc_dplx_slxi(xprt, __func__, __LINE__) /* slxi: send lock xprt impl */ void rpc_dplx_slxi(SVCXPRT *xprt, const char *file, int line); /* sux: send unlock xprt */ void rpc_dplx_sux(SVCXPRT *xprt); /* rlx: recv lock xprt */ #define rpc_dplx_rlx(xprt) \ rpc_dplx_rlxi(xprt, __func__, __LINE__) /* rlxi: recv lock xprt impl */ void rpc_dplx_rlxi(SVCXPRT *xprt, const char *file, int line); /* rux: recv unlock xprt */ void rpc_dplx_rux(SVCXPRT *xprt); /* CLIENT variants */ /* slc: send lock clnt */ #define rpc_dplx_slc(clnt) \ rpc_dplx_slci(clnt, __func__, __LINE__) /* slci: send lock clnt impl */ void rpc_dplx_slci(CLIENT *clnt, const char *file, int line); /* suc: send unlock clnt */ void rpc_dplx_suc(CLIENT *clnt); /* rlc: recv lock clnt */ #define rpc_dplx_rlc(clnt) \ rpc_dplx_rlci(clnt, __func__, __LINE__) /* rlci: recv lock clnt impl */ void rpc_dplx_rlci(CLIENT *clnt, const char *file, int line); /* ruc: recv unlock clnt */ void rpc_dplx_ruc(CLIENT *client); /* fd variants--these interfaces should be used only when NO OTHER * APPROACH COULD WORK. Please. */ /* slf: send lock fd */ #define rpc_dplx_slf(fd) \ rpc_dplx_slfi(fd, __func__, __LINE__) /* slfi: send lock fd impl */ void rpc_dplx_slfi(int fd, const char *file, int line); /* suf: send unlock fd */ void rpc_dplx_suf(int fd); /* rlf: recv lock fd */ #define rpc_dplx_rlf(fd) \ rpc_dplx_rlfi(fd, __func__, __LINE__) /* rlfi: recv lock fd impl */ void rpc_dplx_rlfi(int fd, const char *file, int line); /* ruf: recv unlock fd */ void rpc_dplx_ruf(int fd); #endif /* RPC_DPLX_H */ ntirpc-1.3.1/ntirpc/rpc/rpc_msg.h000066400000000000000000000140641261345040100167020ustar00rootroot00000000000000/* $NetBSD: rpc_msg.h,v 1.11 2000/06/02 22:57:56 fvdl Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)rpc_msg.h 1.7 86/07/16 SMI * from: @(#)rpc_msg.h 2.1 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/rpc_msg.h,v 1.15 2003/01/01 18:48:42 schweikh Exp $ */ /* * rpc_msg.h * rpc message definition * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef _TIRPC_RPC_MSG_H #define _TIRPC_RPC_MSG_H #define RPC_MSG_VERSION ((u_int32_t) 2) #define RPC_SERVICE_PORT ((u_short) 2048) #include #include /* * Bottom up definition of an rpc message. * NOTE: call and reply use the same overall stuct but * different parts of unions within it. */ enum msg_type { CALL = 0, REPLY = 1 }; enum reply_stat { MSG_ACCEPTED = 0, MSG_DENIED = 1 }; enum accept_stat { SUCCESS = 0, PROG_UNAVAIL = 1, PROG_MISMATCH = 2, PROC_UNAVAIL = 3, GARBAGE_ARGS = 4, SYSTEM_ERR = 5 }; enum reject_stat { RPC_MISMATCH = 0, AUTH_ERROR = 1 }; /* * Reply part of an rpc exchange */ /* * Reply to an rpc request that was accepted by the server. * Note: there could be an error even though the request was * accepted. */ struct accepted_reply { struct opaque_auth ar_verf; enum accept_stat ar_stat; union { struct { rpcvers_t low; rpcvers_t high; } AR_versions; struct { caddr_t where; xdrproc_t proc; } AR_results; /* and many other null cases */ } ru; #define ar_results ru.AR_results #define ar_vers ru.AR_versions }; /* * Reply to an rpc request that was rejected by the server. */ struct rejected_reply { enum reject_stat rj_stat; union { struct { rpcvers_t low; rpcvers_t high; } RJ_versions; enum auth_stat RJ_why; /* why authentication did not work */ } ru; #define rj_vers ru.RJ_versions #define rj_why ru.RJ_why }; /* * Body of a reply to an rpc request. */ struct reply_body { enum reply_stat rp_stat; union { struct accepted_reply RP_ar; struct rejected_reply RP_dr; } ru; #define rp_acpt ru.RP_ar #define rp_rjct ru.RP_dr }; /* * Body of an rpc request call. */ struct call_body { rpcvers_t cb_rpcvers; /* must be equal to two */ rpcprog_t cb_prog; rpcvers_t cb_vers; rpcproc_t cb_proc; struct opaque_auth cb_cred; struct opaque_auth cb_verf; /* protocol specific - provided by client */ }; /* * The rpc message */ #define RPC_MSG_FLAG_NONE 0x0000 struct rpc_msg { u_int32_t rm_xid; enum msg_type rm_direction; struct { struct call_body RM_cmb; struct reply_body RM_rmb; } ru; #define rm_call ru.RM_cmb #define rm_reply ru.RM_rmb int32_t *rm_ibuf; uint32_t rm_flags; /* queue of msgs for control xfer */ TAILQ_ENTRY(rpc_msg) msg_q; /* avoid separate alloc/free */ char cb_cred_body[MAX_AUTH_BYTES]; char cb_verf_body[MAX_AUTH_BYTES]; char rq_cred_body[MAX_AUTH_BYTES]; /* size is excessive */ }; #define acpted_rply ru.RM_rmb.ru.RP_ar #define rjcted_rply ru.RM_rmb.ru.RP_dr __BEGIN_DECLS /* * XDR routine to handle a rpc message. * xdr_ncallmsg(xdrs, cmsg) * XDR *xdrs; * struct rpc_msg *cmsg; */ extern bool xdr_ncallmsg(XDR *, struct rpc_msg *); extern bool xdr_call_decode(XDR *, struct rpc_msg *, int32_t *buf); extern bool xdr_call_encode(XDR *, struct rpc_msg *); /* * XDR routine to handle a duplex rpc message. * xdr_dplx_msg(xdrs, cmsg) * XDR *xdrs; * struct rpc_msg *cmsg; */ extern bool xdr_dplx_msg(XDR *, struct rpc_msg *); extern bool xdr_dplx_decode(XDR *, struct rpc_msg *); extern bool xdr_reply_decode(XDR *, struct rpc_msg *, int32_t *buf); extern bool xdr_reply_encode(XDR *, struct rpc_msg *); /* * XDR routine to pre-serialize the static part of a rpc message. * xdr_ncallhdr(xdrs, cmsg) * XDR *xdrs; * struct rpc_msg *cmsg; */ extern bool xdr_ncallhdr(XDR *, struct rpc_msg *); /* * XDR routine to handle a rpc reply. * xdr_nreplymsg(xdrs, rmsg) * XDR *xdrs; * struct rpc_msg *rmsg; */ extern bool xdr_nreplymsg(XDR *, struct rpc_msg *); /* * XDR routine to handle an accepted rpc reply. * xdr_accepted_reply(xdrs, rej) * XDR *xdrs; * struct accepted_reply *rej; */ extern bool xdr_naccepted_reply(XDR *, struct accepted_reply *); /* * XDR routine to handle a rejected rpc reply. * xdr_rejected_reply(xdrs, rej) * XDR *xdrs; * struct rejected_reply *rej; */ extern bool xdr_nrejected_reply(XDR *, struct rejected_reply *); /* * Fills in the error part of a reply message. * _seterr_reply(msg, error) * struct rpc_msg *msg; * struct rpc_err *error; */ extern void _seterr_reply(struct rpc_msg *, struct rpc_err *); __END_DECLS /* For backward compatibility */ #include #endif /* !_TIRPC_RPC_MSG_H */ ntirpc-1.3.1/ntirpc/rpc/rpcb_clnt.h000066400000000000000000000065671261345040100172270ustar00rootroot00000000000000/* $NetBSD: rpcb_clnt.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */ /* $FreeBSD: src/include/rpc/rpcb_clnt.h,v 1.2 2002/03/23 17:24:55 imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * rpcb_clnt.h * Supplies C routines to get to rpcbid services. * */ /* * Usage: * success = rpcb_set(program, version, nconf, address); * success = rpcb_unset(program, version, nconf); * success = rpcb_getaddr(program, version, nconf, host); * head = rpcb_getmaps(nconf, host); * clnt_stat = rpcb_rmtcall(nconf, host, program, version, procedure, * xdrargs, argsp, xdrres, resp, tout, addr_ptr) * success = rpcb_gettime(host, timep) * uaddr = rpcb_taddr2uaddr(nconf, taddr); * taddr = rpcb_uaddr2uaddr(nconf, uaddr); */ #ifndef _RPC_RPCB_CLNT_H #define _RPC_RPCB_CLNT_H /* #pragma ident "@(#)rpcb_clnt.h 1.13 94/04/25 SMI" */ /* rpcb_clnt.h 1.3 88/12/05 SMI */ #include #include __BEGIN_DECLS extern bool rpcb_set(const rpcprog_t, const rpcvers_t, const struct netconfig *, const struct netbuf *); extern bool rpcb_unset(const rpcprog_t, const rpcvers_t, const struct netconfig *); extern rpcblist *rpcb_getmaps(const struct netconfig *, const char *); extern enum clnt_stat rpcb_rmtcall(const struct netconfig *, const char *, const rpcprog_t, const rpcvers_t, const rpcproc_t, const xdrproc_t, const caddr_t, const xdrproc_t, const caddr_t, const struct timeval, const struct netbuf *); extern bool rpcb_getaddr(const rpcprog_t, const rpcvers_t, const struct netconfig *, struct netbuf *, const char *); extern bool rpcb_gettime(const char *, time_t *); extern char *rpcb_taddr2uaddr(struct netconfig *, struct netbuf *); extern struct netbuf *rpcb_uaddr2taddr(struct netconfig *, char *); __END_DECLS #endif /* !_RPC_RPCB_CLNT_H */ ntirpc-1.3.1/ntirpc/rpc/rpcb_prot.h000066400000000000000000000616371261345040100172520ustar00rootroot00000000000000/* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _RPCB_PROT_H_RPCGEN #define _RPCB_PROT_H_RPCGEN #include #ifndef IXDR_GET_INT32 #define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf)) #endif #ifndef IXDR_PUT_INT32 #define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v)) #endif #ifndef IXDR_GET_U_INT32 #define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf)) #endif #ifndef IXDR_PUT_U_INT32 #define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v)) #endif /* * $FreeBSD: src/include/rpc/rpcb_prot.x,v 1.3 2002/03/13 10:29:06 obrien Exp $ * * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1988 by Sun Microsystems, Inc. */ /* from rpcb_prot.x */ /* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */ #ifndef _KERNEL /* * The following procedures are supported by the protocol in version 3: * * RPCBPROC_NULL() returns () * takes nothing, returns nothing * * RPCBPROC_SET(rpcb) returns (bool) * TRUE is success, FALSE is failure. Registers the tuple * [prog, vers, address, owner, netid]. * Finds out owner and netid information on its own. * * RPCBPROC_UNSET(rpcb) returns (bool) * TRUE is success, FALSE is failure. Un-registers tuple * [prog, vers, netid]. addresses is ignored. * If netid is NULL, unregister all. * * RPCBPROC_GETADDR(rpcb) returns (string). * 0 is failure. Otherwise returns the universal address where the * triple [prog, vers, netid] is registered. Ignore address and owner. * * RPCBPROC_DUMP() RETURNS (rpcblist_ptr) * used to dump the entire rpcbind maps * * RPCBPROC_CALLIT(rpcb_rmtcallargs) * RETURNS (rpcb_rmtcallres); * Calls the procedure on the remote machine. If it is not registered, * this procedure is quiet; i.e. it does not return error information!!! * This routine only passes null authentication parameters. * It has no interface to xdr routines for RPCBPROC_CALLIT. * * RPCBPROC_GETTIME() returns (int). * Gets the remote machines time * * RPCBPROC_UADDR2TADDR(strint) RETURNS (struct netbuf) * Returns the netbuf address from universal address. * * RPCBPROC_TADDR2UADDR(struct netbuf) RETURNS (string) * Returns the universal address from netbuf address. * * END OF RPCBIND VERSION 3 PROCEDURES */ /* * Except for RPCBPROC_CALLIT, the procedures above are carried over to * rpcbind version 4. Those below are added or modified for version 4. * NOTE: RPCBPROC_BCAST HAS THE SAME FUNCTIONALITY AND PROCEDURE NUMBER * AS RPCBPROC_CALLIT. * * RPCBPROC_BCAST(rpcb_rmtcallargs) * RETURNS (rpcb_rmtcallres); * Calls the procedure on the remote machine. If it is not registered, * this procedure IS quiet; i.e. it DOES NOT return error information!!! * This routine should be used for broadcasting and nothing else. * * RPCBPROC_GETVERSADDR(rpcb) returns (string). * 0 is failure. Otherwise returns the universal address where the * triple [prog, vers, netid] is registered. Ignore address and owner. * Same as RPCBPROC_GETADDR except that if the given version number * is not available, the address is not returned. * * RPCBPROC_INDIRECT(rpcb_rmtcallargs) * RETURNS (rpcb_rmtcallres); * Calls the procedure on the remote machine. If it is not registered, * this procedure is NOT quiet; i.e. it DOES return error information!!! * as any normal application would expect. * * RPCBPROC_GETADDRLIST(rpcb) returns (rpcb_entry_list_ptr). * Same as RPCBPROC_GETADDR except that it returns a list of all the * addresses registered for the combination (prog, vers) (for all * transports). * * RPCBPROC_GETSTAT(void) returns (rpcb_stat_byvers) * Returns the statistics about the kind of requests received by rpcbind. */ /* * A mapping of (program, version, network ID) to address */ struct rpcb { rpcprog_t r_prog; rpcvers_t r_vers; char *r_netid; char *r_addr; char *r_owner; }; typedef struct rpcb rpcb; #ifdef __cplusplus extern "C" { bool xdr_rpcb(XDR *, rpcb *); } #elif __STDC__ extern bool xdr_rpcb(XDR *, rpcb *); #else /* Old Style C */ bool xdr_rpcb(); #endif /* Old Style C */ typedef rpcb RPCB; /* * A list of mappings * * Below are two definitions for the rpcblist structure. This is done because * xdr_rpcblist() is specified to take a struct rpcblist **, rather than a * struct rpcblist * that rpcgen would produce. One version of the rpcblist * structure (actually called rp__list) is used with rpcgen, and the other is * defined only in the header file for compatibility with the specified * interface. */ struct rp__list { rpcb rpcb_map; struct rp__list *rpcb_next; }; typedef struct rp__list rp__list; #ifdef __cplusplus extern "C" { bool xdr_rp__list(XDR *, rp__list *); } #elif __STDC__ extern bool xdr_rp__list(XDR *, rp__list *); #else /* Old Style C */ bool xdr_rp__list(); #endif /* Old Style C */ typedef rp__list *rpcblist_ptr; #ifdef __cplusplus extern "C" { bool xdr_rpcblist_ptr(XDR *, rpcblist_ptr *); } #elif __STDC__ extern bool xdr_rpcblist_ptr(XDR *, rpcblist_ptr *); #else /* Old Style C */ bool xdr_rpcblist_ptr(); #endif /* Old Style C */ typedef struct rp__list rpcblist; typedef struct rp__list RPCBLIST; #ifndef __cplusplus struct rpcblist { RPCB rpcb_map; struct rpcblist *rpcb_next; }; #endif #ifdef __cplusplus extern "C" { #endif extern bool xdr_rpcblist(XDR *, rpcblist **); #ifdef __cplusplus } #endif /* * Arguments of remote calls */ struct rpcb_rmtcallargs { rpcprog_t prog; rpcvers_t vers; rpcproc_t proc; struct { u_int args_len; char *args_val; } args; }; typedef struct rpcb_rmtcallargs rpcb_rmtcallargs; #ifdef __cplusplus extern "C" { bool xdr_rpcb_rmtcallargs(XDR *, rpcb_rmtcallargs *); } #elif __STDC__ extern bool xdr_rpcb_rmtcallargs(XDR *, rpcb_rmtcallargs *); #else /* Old Style C */ bool xdr_rpcb_rmtcallargs(); #endif /* Old Style C */ /* * Client-side only representation of rpcb_rmtcallargs structure. * * The routine that XDRs the rpcb_rmtcallargs structure must deal with the * opaque arguments in the "args" structure. xdr_rpcb_rmtcallargs() needs to * be passed the XDR routine that knows the args' structure. This routine * doesn't need to go over-the-wire (and it wouldn't make sense anyway) since * the application being called already knows the args structure. So we use a * different "XDR" structure on the client side, r_rpcb_rmtcallargs, which * includes the args' XDR routine. */ struct r_rpcb_rmtcallargs { rpcprog_t prog; rpcvers_t vers; rpcproc_t proc; struct { u_int args_len; char *args_val; } args; xdrproc_t xdr_args; /* encodes args */ }; /* * Results of the remote call */ struct rpcb_rmtcallres { char *addr; struct { u_int results_len; char *results_val; } results; }; typedef struct rpcb_rmtcallres rpcb_rmtcallres; #ifdef __cplusplus extern "C" { bool xdr_rpcb_rmtcallres(XDR *, rpcb_rmtcallres *); } #elif __STDC__ extern bool xdr_rpcb_rmtcallres(XDR *, rpcb_rmtcallres *); #else /* Old Style C */ bool xdr_rpcb_rmtcallres(); #endif /* Old Style C */ /* * Client-side only representation of rpcb_rmtcallres structure. */ struct r_rpcb_rmtcallres { char *addr; struct { u_int32_t results_len; char *results_val; } results; xdrproc_t xdr_res; /* decodes results */ }; /* * rpcb_entry contains a merged address of a service on a particular * transport, plus associated netconfig information. A list of rpcb_entrys * is returned by RPCBPROC_GETADDRLIST. See netconfig.h for values used * in r_nc_* fields. */ struct rpcb_entry { char *r_maddr; char *r_nc_netid; u_int r_nc_semantics; char *r_nc_protofmly; char *r_nc_proto; }; typedef struct rpcb_entry rpcb_entry; #ifdef __cplusplus extern "C" { bool xdr_rpcb_entry(XDR *, rpcb_entry *); } #elif __STDC__ extern bool xdr_rpcb_entry(XDR *, rpcb_entry *); #else /* Old Style C */ bool xdr_rpcb_entry(); #endif /* Old Style C */ /* * A list of addresses supported by a service. */ struct rpcb_entry_list { rpcb_entry rpcb_entry_map; struct rpcb_entry_list *rpcb_entry_next; }; typedef struct rpcb_entry_list rpcb_entry_list; #ifdef __cplusplus extern "C" { bool xdr_rpcb_entry_list(XDR *, rpcb_entry_list *); } #elif __STDC__ extern bool xdr_rpcb_entry_list(XDR *, rpcb_entry_list *); #else /* Old Style C */ bool xdr_rpcb_entry_list(); #endif /* Old Style C */ typedef rpcb_entry_list *rpcb_entry_list_ptr; #ifdef __cplusplus extern "C" { bool xdr_rpcb_entry_list_ptr(XDR *, rpcb_entry_list_ptr *); } #elif __STDC__ extern bool xdr_rpcb_entry_list_ptr(XDR *, rpcb_entry_list_ptr *); #else /* Old Style C */ bool xdr_rpcb_entry_list_ptr(); #endif /* Old Style C */ /* * rpcbind statistics */ #define rpcb_highproc_2 RPCBPROC_CALLIT #define rpcb_highproc_3 RPCBPROC_TADDR2UADDR #define rpcb_highproc_4 RPCBPROC_GETSTAT #define RPCBSTAT_HIGHPROC 13 #define RPCBVERS_STAT 3 #define RPCBVERS_4_STAT 2 #define RPCBVERS_3_STAT 1 #define RPCBVERS_2_STAT 0 /* Link list of all the stats about getport and getaddr */ struct rpcbs_addrlist { rpcprog_t prog; rpcvers_t vers; int success; int failure; char *netid; struct rpcbs_addrlist *next; }; typedef struct rpcbs_addrlist rpcbs_addrlist; #ifdef __cplusplus extern "C" { bool xdr_rpcbs_addrlist(XDR *, rpcbs_addrlist *); } #elif __STDC__ extern bool xdr_rpcbs_addrlist(XDR *, rpcbs_addrlist *); #else /* Old Style C */ bool xdr_rpcbs_addrlist(); #endif /* Old Style C */ /* Link list of all the stats about rmtcall */ struct rpcbs_rmtcalllist { rpcprog_t prog; rpcvers_t vers; rpcproc_t proc; int success; int failure; int indirect; char *netid; struct rpcbs_rmtcalllist *next; }; typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist; #ifdef __cplusplus extern "C" { bool xdr_rpcbs_rmtcalllist(XDR *, rpcbs_rmtcalllist *); } #elif __STDC__ extern bool xdr_rpcbs_rmtcalllist(XDR *, rpcbs_rmtcalllist *); #else /* Old Style C */ bool xdr_rpcbs_rmtcalllist(); #endif /* Old Style C */ typedef int rpcbs_proc[RPCBSTAT_HIGHPROC]; #ifdef __cplusplus extern "C" { bool xdr_rpcbs_proc(XDR *, rpcbs_proc); } #elif __STDC__ extern bool xdr_rpcbs_proc(XDR *, rpcbs_proc); #else /* Old Style C */ bool xdr_rpcbs_proc(); #endif /* Old Style C */ typedef rpcbs_addrlist *rpcbs_addrlist_ptr; #ifdef __cplusplus extern "C" { bool xdr_rpcbs_addrlist_ptr(XDR *, rpcbs_addrlist_ptr *); } #elif __STDC__ extern bool xdr_rpcbs_addrlist_ptr(XDR *, rpcbs_addrlist_ptr *); #else /* Old Style C */ bool xdr_rpcbs_addrlist_ptr(); #endif /* Old Style C */ typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr; #ifdef __cplusplus extern "C" { bool xdr_rpcbs_rmtcalllist_ptr(XDR *, rpcbs_rmtcalllist_ptr *); } #elif __STDC__ extern bool xdr_rpcbs_rmtcalllist_ptr(XDR *, rpcbs_rmtcalllist_ptr *); #else /* Old Style C */ bool xdr_rpcbs_rmtcalllist_ptr(); #endif /* Old Style C */ struct rpcb_stat { rpcbs_proc info; int setinfo; int unsetinfo; rpcbs_addrlist_ptr addrinfo; rpcbs_rmtcalllist_ptr rmtinfo; }; typedef struct rpcb_stat rpcb_stat; #ifdef __cplusplus extern "C" { bool xdr_rpcb_stat(XDR *, rpcb_stat *); } #elif __STDC__ extern bool xdr_rpcb_stat(XDR *, rpcb_stat *); #else /* Old Style C */ bool xdr_rpcb_stat(); #endif /* Old Style C */ /* * One rpcb_stat structure is returned for each version of rpcbind * being monitored. */ typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT]; #ifdef __cplusplus extern "C" { bool xdr_rpcb_stat_byvers(XDR *, rpcb_stat_byvers); } #elif __STDC__ extern bool xdr_rpcb_stat_byvers(XDR *, rpcb_stat_byvers); #else /* Old Style C */ bool xdr_rpcb_stat_byvers(); #endif /* Old Style C */ /* * We don't define netbuf in RPCL, since it would contain structure member * names that would conflict with the definition of struct netbuf in * . Instead we merely declare the XDR routine xdr_netbuf() here, * and implement it ourselves in rpc/rpcb_prot.c. */ #ifdef __cplusplus extern "C" { bool xdr_netbuf(XDR *, struct netbuf *); } #else /* __STDC__ */ extern bool xdr_netbuf(XDR *, struct netbuf *); #endif #define RPCBVERS_3 RPCBVERS #define RPCBVERS_4 RPCBVERS4 #define _PATH_RPCBINDSOCK "/var/run/rpcbind.sock" #else /* ndef _KERNEL */ #ifdef __cplusplus extern "C" { #endif /* * A mapping of (program, version, network ID) to address */ struct rpcb { rpcprog_t r_prog; /* program number */ rpcvers_t r_vers; /* version number */ char *r_netid; /* network id */ char *r_addr; /* universal address */ char *r_owner; /* owner of the mapping */ }; typedef struct rpcb RPCB; /* * A list of mappings */ struct rpcblist { RPCB rpcb_map; struct rpcblist *rpcb_next; }; typedef struct rpcblist RPCBLIST; typedef struct rpcblist *rpcblist_ptr; /* * Remote calls arguments */ struct rpcb_rmtcallargs { rpcprog_t prog; /* program number */ rpcvers_t vers; /* version number */ rpcproc_t proc; /* procedure number */ u_int32_t arglen; /* arg len */ caddr_t args_ptr; /* argument */ xdrproc_t xdr_args; /* XDR routine for argument */ }; typedef struct rpcb_rmtcallargs rpcb_rmtcallargs; /* * Remote calls results */ struct rpcb_rmtcallres { char *addr_ptr; /* remote universal address */ u_int32_t resultslen; /* results length */ caddr_t results_ptr; /* results */ xdrproc_t xdr_results; /* XDR routine for result */ }; typedef struct rpcb_rmtcallres rpcb_rmtcallres; struct rpcb_entry { char *r_maddr; char *r_nc_netid; unsigned int r_nc_semantics; char *r_nc_protofmly; char *r_nc_proto; }; typedef struct rpcb_entry rpcb_entry; /* * A list of addresses supported by a service. */ struct rpcb_entry_list { rpcb_entry rpcb_entry_map; struct rpcb_entry_list *rpcb_entry_next; }; typedef struct rpcb_entry_list rpcb_entry_list; typedef rpcb_entry_list *rpcb_entry_list_ptr; /* * rpcbind statistics */ #define rpcb_highproc_2 RPCBPROC_CALLIT #define rpcb_highproc_3 RPCBPROC_TADDR2UADDR #define rpcb_highproc_4 RPCBPROC_GETSTAT #define RPCBSTAT_HIGHPROC 13 #define RPCBVERS_STAT 3 #define RPCBVERS_4_STAT 2 #define RPCBVERS_3_STAT 1 #define RPCBVERS_2_STAT 0 /* Link list of all the stats about getport and getaddr */ struct rpcbs_addrlist { rpcprog_t prog; rpcvers_t vers; int success; int failure; char *netid; struct rpcbs_addrlist *next; }; typedef struct rpcbs_addrlist rpcbs_addrlist; /* Link list of all the stats about rmtcall */ struct rpcbs_rmtcalllist { rpcprog_t prog; rpcvers_t vers; rpcproc_t proc; int success; int failure; int indirect; char *netid; struct rpcbs_rmtcalllist *next; }; typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist; typedef int rpcbs_proc[RPCBSTAT_HIGHPROC]; typedef rpcbs_addrlist *rpcbs_addrlist_ptr; typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr; struct rpcb_stat { rpcbs_proc info; int setinfo; int unsetinfo; rpcbs_addrlist_ptr addrinfo; rpcbs_rmtcalllist_ptr rmtinfo; }; typedef struct rpcb_stat rpcb_stat; /* * One rpcb_stat structure is returned for each version of rpcbind * being monitored. */ typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT]; #ifdef __cplusplus } #endif #endif /* ndef _KERNEL */ #define RPCBPROG ((u_int32_t)100000) #define RPCBVERS ((u_int32_t)3) #ifdef __cplusplus #define RPCBPROC_SET ((u_int32_t)1) extern "C" { bool *rpcbproc_set_3(rpcb *, CLIENT *); bool *rpcbproc_set_3_svc(rpcb *, struct svc_req *); } #define RPCBPROC_UNSET ((u_int32_t)2) extern "C" { bool *rpcbproc_unset_3(rpcb *, CLIENT *); bool *rpcbproc_unset_3_svc(rpcb *, struct svc_req *); } #define RPCBPROC_GETADDR ((u_int32_t)3) extern "C" { char **rpcbproc_getaddr_3(rpcb *, CLIENT *); char **rpcbproc_getaddr_3_svc(rpcb *, struct svc_req *); } #define RPCBPROC_DUMP ((u_int32_t)4) extern "C" { rpcblist_ptr *rpcbproc_dump_3(void *, CLIENT *); rpcblist_ptr *rpcbproc_dump_3_svc(void *, struct svc_req *); } #define RPCBPROC_CALLIT ((u_int32_t)5) extern "C" { rpcb_rmtcallres *rpcbproc_callit_3(rpcb_rmtcallargs *, CLIENT *); rpcb_rmtcallres *rpcbproc_callit_3_svc(rpcb_rmtcallargs *, struct svc_req *); } #define RPCBPROC_GETTIME ((u_int32_t)6) extern "C" { u_int *rpcbproc_gettime_3(void *, CLIENT *); u_int *rpcbproc_gettime_3_svc(void *, struct svc_req *); } #define RPCBPROC_UADDR2TADDR ((u_int32_t)7) extern "C" { struct netbuf *rpcbproc_uaddr2taddr_3(char **, CLIENT *); struct netbuf *rpcbproc_uaddr2taddr_3_svc(char **, struct svc_req *); } #define RPCBPROC_TADDR2UADDR ((u_int32_t)8) extern "C" { char **rpcbproc_taddr2uaddr_3(struct netbuf *, CLIENT *); char **rpcbproc_taddr2uaddr_3_svc(struct netbuf *, struct svc_req *); } #elif __STDC__ #define RPCBPROC_SET ((u_int32_t)1) extern bool *rpcbproc_set_3(rpcb *, CLIENT *); extern bool *rpcbproc_set_3_svc(rpcb *, struct svc_req *); #define RPCBPROC_UNSET ((u_int32_t)2) extern bool *rpcbproc_unset_3(rpcb *, CLIENT *); extern bool *rpcbproc_unset_3_svc(rpcb *, struct svc_req *); #define RPCBPROC_GETADDR ((u_int32_t)3) extern char **rpcbproc_getaddr_3(rpcb *, CLIENT *); extern char **rpcbproc_getaddr_3_svc(rpcb *, struct svc_req *); #define RPCBPROC_DUMP ((u_int32_t)4) extern rpcblist_ptr *rpcbproc_dump_3(void *, CLIENT *); extern rpcblist_ptr *rpcbproc_dump_3_svc(void *, struct svc_req *); #define RPCBPROC_CALLIT ((u_int32_t)5) extern rpcb_rmtcallres *rpcbproc_callit_3(rpcb_rmtcallargs *, CLIENT *); extern rpcb_rmtcallres *rpcbproc_callit_3_svc(rpcb_rmtcallargs *, struct svc_req *); #define RPCBPROC_GETTIME ((u_int32_t)6) extern u_int *rpcbproc_gettime_3(void *, CLIENT *); extern u_int *rpcbproc_gettime_3_svc(void *, struct svc_req *); #define RPCBPROC_UADDR2TADDR ((u_int32_t)7) extern struct netbuf *rpcbproc_uaddr2taddr_3(char **, CLIENT *); extern struct netbuf *rpcbproc_uaddr2taddr_3_svc(char **, struct svc_req *); #define RPCBPROC_TADDR2UADDR ((u_int32_t)8) extern char **rpcbproc_taddr2uaddr_3(struct netbuf *, CLIENT *); extern char **rpcbproc_taddr2uaddr_3_svc(struct netbuf *, struct svc_req *); #else /* Old Style C */ #define RPCBPROC_SET ((u_int32_t)1) extern bool *rpcbproc_set_3(); extern bool *rpcbproc_set_3_svc(); #define RPCBPROC_UNSET ((u_int32_t)2) extern bool *rpcbproc_unset_3(); extern bool *rpcbproc_unset_3_svc(); #define RPCBPROC_GETADDR ((u_int32_t)3) extern char **rpcbproc_getaddr_3(); extern char **rpcbproc_getaddr_3_svc(); #define RPCBPROC_DUMP ((u_int32_t)4) extern rpcblist_ptr *rpcbproc_dump_3(); extern rpcblist_ptr *rpcbproc_dump_3_svc(); #define RPCBPROC_CALLIT ((u_int32_t)5) extern rpcb_rmtcallres *rpcbproc_callit_3(); extern rpcb_rmtcallres *rpcbproc_callit_3_svc(); #define RPCBPROC_GETTIME ((u_int32_t)6) extern u_int *rpcbproc_gettime_3(); extern u_int *rpcbproc_gettime_3_svc(); #define RPCBPROC_UADDR2TADDR ((u_int32_t)7) extern struct netbuf *rpcbproc_uaddr2taddr_3(); extern struct netbuf *rpcbproc_uaddr2taddr_3_svc(); #define RPCBPROC_TADDR2UADDR ((u_int32_t)8) extern char **rpcbproc_taddr2uaddr_3(); extern char **rpcbproc_taddr2uaddr_3_svc(); #endif /* Old Style C */ #define RPCBVERS4 ((u_int32_t)4) #ifdef __cplusplus extern "C" { bool *rpcbproc_set_4(rpcb *, CLIENT *); bool *rpcbproc_set_4_svc(rpcb *, struct svc_req *); bool *rpcbproc_unset_4(rpcb *, CLIENT *); bool *rpcbproc_unset_4_svc(rpcb *, struct svc_req *); char **rpcbproc_getaddr_4(rpcb *, CLIENT *); char **rpcbproc_getaddr_4_svc(rpcb *, struct svc_req *); rpcblist_ptr *rpcbproc_dump_4(void *, CLIENT *); rpcblist_ptr *rpcbproc_dump_4_svc(void *, struct svc_req *); } #define RPCBPROC_BCAST ((u_int32_t)RPCBPROC_CALLIT) extern "C" { rpcb_rmtcallres *rpcbproc_bcast_4(rpcb_rmtcallargs *, CLIENT *); rpcb_rmtcallres *rpcbproc_bcast_4_svc(rpcb_rmtcallargs *, struct svc_req *); u_int *rpcbproc_gettime_4(void *, CLIENT *); u_int *rpcbproc_gettime_4_svc(void *, struct svc_req *); struct netbuf *rpcbproc_uaddr2taddr_4(char **, CLIENT *); struct netbuf *rpcbproc_uaddr2taddr_4_svc(char **, struct svc_req *); char **rpcbproc_taddr2uaddr_4(struct netbuf *, CLIENT *); char **rpcbproc_taddr2uaddr_4_svc(struct netbuf *, struct svc_req *); } #define RPCBPROC_GETVERSADDR ((u_int32_t)9) extern "C" { char **rpcbproc_getversaddr_4(rpcb *, CLIENT *); char **rpcbproc_getversaddr_4_svc(rpcb *, struct svc_req *); } #define RPCBPROC_INDIRECT ((u_int32_t)10) extern "C" { rpcb_rmtcallres *rpcbproc_indirect_4(rpcb_rmtcallargs *, CLIENT *); rpcb_rmtcallres *rpcbproc_indirect_4_svc(rpcb_rmtcallargs *, struct svc_req *); } #define RPCBPROC_GETADDRLIST ((u_int32_t)11) extern "C" { rpcb_entry_list_ptr *rpcbproc_getaddrlist_4(rpcb *, CLIENT *); rpcb_entry_list_ptr *rpcbproc_getaddrlist_4_svc(rpcb *, struct svc_req *); } #define RPCBPROC_GETSTAT ((u_int32_t)12) extern "C" { rpcb_stat *rpcbproc_getstat_4(void *, CLIENT *); rpcb_stat *rpcbproc_getstat_4_svc(void *, struct svc_req *); } #elif __STDC__ extern bool *rpcbproc_set_4(rpcb *, CLIENT *); extern bool *rpcbproc_set_4_svc(rpcb *, struct svc_req *); extern bool *rpcbproc_unset_4(rpcb *, CLIENT *); extern bool *rpcbproc_unset_4_svc(rpcb *, struct svc_req *); extern char **rpcbproc_getaddr_4(rpcb *, CLIENT *); extern char **rpcbproc_getaddr_4_svc(rpcb *, struct svc_req *); extern rpcblist_ptr *rpcbproc_dump_4(void *, CLIENT *); extern rpcblist_ptr *rpcbproc_dump_4_svc(void *, struct svc_req *); #define RPCBPROC_BCAST ((u_int32_t)RPCBPROC_CALLIT) extern rpcb_rmtcallres *rpcbproc_bcast_4(rpcb_rmtcallargs *, CLIENT *); extern rpcb_rmtcallres *rpcbproc_bcast_4_svc(rpcb_rmtcallargs *, struct svc_req *); extern u_int *rpcbproc_gettime_4(void *, CLIENT *); extern u_int *rpcbproc_gettime_4_svc(void *, struct svc_req *); extern struct netbuf *rpcbproc_uaddr2taddr_4(char **, CLIENT *); extern struct netbuf *rpcbproc_uaddr2taddr_4_svc(char **, struct svc_req *); extern char **rpcbproc_taddr2uaddr_4(struct netbuf *, CLIENT *); extern char **rpcbproc_taddr2uaddr_4_svc(struct netbuf *, struct svc_req *); #define RPCBPROC_GETVERSADDR ((u_int32_t)9) extern char **rpcbproc_getversaddr_4(rpcb *, CLIENT *); extern char **rpcbproc_getversaddr_4_svc(rpcb *, struct svc_req *); #define RPCBPROC_INDIRECT ((u_int32_t)10) extern rpcb_rmtcallres *rpcbproc_indirect_4(rpcb_rmtcallargs *, CLIENT *); extern rpcb_rmtcallres *rpcbproc_indirect_4_svc(rpcb_rmtcallargs *, struct svc_req *); #define RPCBPROC_GETADDRLIST ((u_int32_t)11) extern rpcb_entry_list_ptr *rpcbproc_getaddrlist_4(rpcb *, CLIENT *); extern rpcb_entry_list_ptr *rpcbproc_getaddrlist_4_svc(rpcb *, struct svc_req *); #define RPCBPROC_GETSTAT ((u_int32_t)12) extern rpcb_stat *rpcbproc_getstat_4(void *, CLIENT *); extern rpcb_stat *rpcbproc_getstat_4_svc(void *, struct svc_req *); #else /* Old Style C */ extern bool *rpcbproc_set_4(); extern bool *rpcbproc_set_4_svc(); extern bool *rpcbproc_unset_4(); extern bool *rpcbproc_unset_4_svc(); extern char **rpcbproc_getaddr_4(); extern char **rpcbproc_getaddr_4_svc(); extern rpcblist_ptr *rpcbproc_dump_4(); extern rpcblist_ptr *rpcbproc_dump_4_svc(); #define RPCBPROC_BCAST ((u_int32_t)RPCBPROC_CALLIT) extern rpcb_rmtcallres *rpcbproc_bcast_4(); extern rpcb_rmtcallres *rpcbproc_bcast_4_svc(); extern u_int *rpcbproc_gettime_4(); extern u_int *rpcbproc_gettime_4_svc(); extern struct netbuf *rpcbproc_uaddr2taddr_4(); extern struct netbuf *rpcbproc_uaddr2taddr_4_svc(); extern char **rpcbproc_taddr2uaddr_4(); extern char **rpcbproc_taddr2uaddr_4_svc(); #define RPCBPROC_GETVERSADDR ((u_int32_t)9) extern char **rpcbproc_getversaddr_4(); extern char **rpcbproc_getversaddr_4_svc(); #define RPCBPROC_INDIRECT ((u_int32_t)10) extern rpcb_rmtcallres *rpcbproc_indirect_4(); extern rpcb_rmtcallres *rpcbproc_indirect_4_svc(); #define RPCBPROC_GETADDRLIST ((u_int32_t)11) extern rpcb_entry_list_ptr *rpcbproc_getaddrlist_4(); extern rpcb_entry_list_ptr *rpcbproc_getaddrlist_4_svc(); #define RPCBPROC_GETSTAT ((u_int32_t)12) extern rpcb_stat *rpcbproc_getstat_4(); extern rpcb_stat *rpcbproc_getstat_4_svc(); #endif /* Old Style C */ #endif /* !_RPCB_PROT_H_RPCGEN */ ntirpc-1.3.1/ntirpc/rpc/rpcb_prot.x000066400000000000000000000345131261345040100172630ustar00rootroot00000000000000%/* % * $FreeBSD: src/include/rpc/rpcb_prot.x,v 1.3 2002/03/13 10:29:06 obrien Exp $ % * % * Copyright (c) 2009, Sun Microsystems, Inc. % * All rights reserved. % * % * Redistribution and use in source and binary forms, with or without % * modification, are permitted provided that the following conditions are met: % * - Redistributions of source code must retain the above copyright notice, % * this list of conditions and the following disclaimer. % * - Redistributions in binary form must reproduce the above copyright notice, % * this list of conditions and the following disclaimer in the documentation % * and/or other materials provided with the distribution. % * - Neither the name of Sun Microsystems, Inc. nor the names of its % * contributors may be used to endorse or promote products derived % * from this software without specific prior written permission. % * % * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" % * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE % * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE % * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE % * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR % * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF % * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS % * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN % * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) % * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE % * POSSIBILITY OF SUCH DAMAGE. % */ %/* % * Copyright (c) 1988 by Sun Microsystems, Inc. % */ %/* from rpcb_prot.x */ #ifdef RPC_HDR % %/* #pragma ident "@(#)rpcb_prot.x 1.5 94/04/29 SMI" */ % %#ifndef _KERNEL % #endif /* * rpcb_prot.x * rpcbind protocol, versions 3 and 4, in RPC Language */ % %/* % * The following procedures are supported by the protocol in version 3: % * % * RPCBPROC_NULL() returns () % * takes nothing, returns nothing % * % * RPCBPROC_SET(rpcb) returns (bool_t) % * TRUE is success, FALSE is failure. Registers the tuple % * [prog, vers, address, owner, netid]. % * Finds out owner and netid information on its own. % * % * RPCBPROC_UNSET(rpcb) returns (bool_t) % * TRUE is success, FALSE is failure. Un-registers tuple % * [prog, vers, netid]. addresses is ignored. % * If netid is NULL, unregister all. % * % * RPCBPROC_GETADDR(rpcb) returns (string). % * 0 is failure. Otherwise returns the universal address where the % * triple [prog, vers, netid] is registered. Ignore address and owner. % * % * RPCBPROC_DUMP() RETURNS (rpcblist_ptr) % * used to dump the entire rpcbind maps % * % * RPCBPROC_CALLIT(rpcb_rmtcallargs) % * RETURNS (rpcb_rmtcallres); % * Calls the procedure on the remote machine. If it is not registered, % * this procedure is quiet; i.e. it does not return error information!!! % * This routine only passes null authentication parameters. % * It has no interface to xdr routines for RPCBPROC_CALLIT. % * % * RPCBPROC_GETTIME() returns (int). % * Gets the remote machines time % * % * RPCBPROC_UADDR2TADDR(strint) RETURNS (struct netbuf) % * Returns the netbuf address from universal address. % * % * RPCBPROC_TADDR2UADDR(struct netbuf) RETURNS (string) % * Returns the universal address from netbuf address. % * % * END OF RPCBIND VERSION 3 PROCEDURES % */ %/* % * Except for RPCBPROC_CALLIT, the procedures above are carried over to % * rpcbind version 4. Those below are added or modified for version 4. % * NOTE: RPCBPROC_BCAST HAS THE SAME FUNCTIONALITY AND PROCEDURE NUMBER % * AS RPCBPROC_CALLIT. % * % * RPCBPROC_BCAST(rpcb_rmtcallargs) % * RETURNS (rpcb_rmtcallres); % * Calls the procedure on the remote machine. If it is not registered, % * this procedure IS quiet; i.e. it DOES NOT return error information!!! % * This routine should be used for broadcasting and nothing else. % * % * RPCBPROC_GETVERSADDR(rpcb) returns (string). % * 0 is failure. Otherwise returns the universal address where the % * triple [prog, vers, netid] is registered. Ignore address and owner. % * Same as RPCBPROC_GETADDR except that if the given version number % * is not available, the address is not returned. % * % * RPCBPROC_INDIRECT(rpcb_rmtcallargs) % * RETURNS (rpcb_rmtcallres); % * Calls the procedure on the remote machine. If it is not registered, % * this procedure is NOT quiet; i.e. it DOES return error information!!! % * as any normal application would expect. % * % * RPCBPROC_GETADDRLIST(rpcb) returns (rpcb_entry_list_ptr). % * Same as RPCBPROC_GETADDR except that it returns a list of all the % * addresses registered for the combination (prog, vers) (for all % * transports). % * % * RPCBPROC_GETSTAT(void) returns (rpcb_stat_byvers) % * Returns the statistics about the kind of requests received by rpcbind. % */ % %/* % * A mapping of (program, version, network ID) to address % */ struct rpcb { rpcprog_t r_prog; /* program number */ rpcvers_t r_vers; /* version number */ string r_netid<>; /* network id */ string r_addr<>; /* universal address */ string r_owner<>; /* owner of this service */ }; #ifdef RPC_HDR % %typedef rpcb RPCB; % #endif % %/* % * A list of mappings % * % * Below are two definitions for the rpcblist structure. This is done because % * xdr_rpcblist() is specified to take a struct rpcblist **, rather than a % * struct rpcblist * that rpcgen would produce. One version of the rpcblist % * structure (actually called rp__list) is used with rpcgen, and the other is % * defined only in the header file for compatibility with the specified % * interface. % */ struct rp__list { rpcb rpcb_map; struct rp__list *rpcb_next; }; typedef rp__list *rpcblist_ptr; /* results of RPCBPROC_DUMP */ #ifdef RPC_HDR % %typedef struct rp__list rpcblist; %typedef struct rp__list RPCBLIST; % %#ifndef __cplusplus %struct rpcblist { % RPCB rpcb_map; % struct rpcblist *rpcb_next; %}; %#endif % %#ifdef __cplusplus %extern "C" { %#endif %extern bool xdr_rpcblist(XDR *, rpcblist**); %#ifdef __cplusplus %} %#endif % #endif % %/* % * Arguments of remote calls % */ struct rpcb_rmtcallargs { rpcprog_t prog; /* program number */ rpcvers_t vers; /* version number */ rpcproc_t proc; /* procedure number */ opaque args<>; /* argument */ }; #ifdef RPC_HDR % %/* % * Client-side only representation of rpcb_rmtcallargs structure. % * % * The routine that XDRs the rpcb_rmtcallargs structure must deal with the % * opaque arguments in the "args" structure. xdr_rpcb_rmtcallargs() needs to % * be passed the XDR routine that knows the args' structure. This routine % * doesn't need to go over-the-wire (and it wouldn't make sense anyway) since % * the application being called already knows the args structure. So we use a % * different "XDR" structure on the client side, r_rpcb_rmtcallargs, which % * includes the args' XDR routine. % */ %struct r_rpcb_rmtcallargs { % rpcprog_t prog; % rpcvers_t vers; % rpcproc_t proc; % struct { % u_int args_len; % char *args_val; % } args; % xdrproc_t xdr_args; /* encodes args */ %}; % #endif /* def RPC_HDR */ % %/* % * Results of the remote call % */ struct rpcb_rmtcallres { string addr<>; /* remote universal address */ opaque results<>; /* result */ }; #ifdef RPC_HDR % %/* % * Client-side only representation of rpcb_rmtcallres structure. % */ %struct r_rpcb_rmtcallres { % char *addr; % struct { % u_int32_t results_len; % char *results_val; % } results; % xdrproc_t xdr_res; /* decodes results */ %}; #endif /* RPC_HDR */ % %/* % * rpcb_entry contains a merged address of a service on a particular % * transport, plus associated netconfig information. A list of rpcb_entrys % * is returned by RPCBPROC_GETADDRLIST. See netconfig.h for values used % * in r_nc_* fields. % */ struct rpcb_entry { string r_maddr<>; /* merged address of service */ string r_nc_netid<>; /* netid field */ unsigned int r_nc_semantics; /* semantics of transport */ string r_nc_protofmly<>; /* protocol family */ string r_nc_proto<>; /* protocol name */ }; % %/* % * A list of addresses supported by a service. % */ struct rpcb_entry_list { rpcb_entry rpcb_entry_map; struct rpcb_entry_list *rpcb_entry_next; }; typedef rpcb_entry_list *rpcb_entry_list_ptr; % %/* % * rpcbind statistics % */ % const rpcb_highproc_2 = RPCBPROC_CALLIT; const rpcb_highproc_3 = RPCBPROC_TADDR2UADDR; const rpcb_highproc_4 = RPCBPROC_GETSTAT; const RPCBSTAT_HIGHPROC = 13; /* # of procs in rpcbind V4 plus one */ const RPCBVERS_STAT = 3; /* provide only for rpcbind V2, V3 and V4 */ const RPCBVERS_4_STAT = 2; const RPCBVERS_3_STAT = 1; const RPCBVERS_2_STAT = 0; % %/* Link list of all the stats about getport and getaddr */ struct rpcbs_addrlist { rpcprog_t prog; rpcvers_t vers; int success; int failure; string netid<>; struct rpcbs_addrlist *next; }; % %/* Link list of all the stats about rmtcall */ struct rpcbs_rmtcalllist { rpcprog_t prog; rpcvers_t vers; rpcproc_t proc; int success; int failure; int indirect; /* whether callit or indirect */ string netid<>; struct rpcbs_rmtcalllist *next; }; typedef int rpcbs_proc[RPCBSTAT_HIGHPROC]; typedef rpcbs_addrlist *rpcbs_addrlist_ptr; typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr; struct rpcb_stat { rpcbs_proc info; int setinfo; int unsetinfo; rpcbs_addrlist_ptr addrinfo; rpcbs_rmtcalllist_ptr rmtinfo; }; % %/* % * One rpcb_stat structure is returned for each version of rpcbind % * being monitored. % */ typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT]; #ifdef RPC_HDR % %/* % * We don't define netbuf in RPCL, since it would contain structure member % * names that would conflict with the definition of struct netbuf in % * . Instead we merely declare the XDR routine xdr_netbuf() here, % * and implement it ourselves in rpc/rpcb_prot.c. % */ %#ifdef __cplusplus %extern "C" bool xdr_netbuf(XDR *, struct netbuf *); % %#else /* __STDC__ */ %extern bool xdr_netbuf(XDR *, struct netbuf *); % %#endif #endif /* def RPC_HDR */ /* * rpcbind procedures */ program RPCBPROG { version RPCBVERS { bool RPCBPROC_SET(rpcb) = 1; bool RPCBPROC_UNSET(rpcb) = 2; string RPCBPROC_GETADDR(rpcb) = 3; rpcblist_ptr RPCBPROC_DUMP(void) = 4; rpcb_rmtcallres RPCBPROC_CALLIT(rpcb_rmtcallargs) = 5; unsigned int RPCBPROC_GETTIME(void) = 6; struct netbuf RPCBPROC_UADDR2TADDR(string) = 7; string RPCBPROC_TADDR2UADDR(struct netbuf) = 8; } = 3; version RPCBVERS4 { bool RPCBPROC_SET(rpcb) = 1; bool RPCBPROC_UNSET(rpcb) = 2; string RPCBPROC_GETADDR(rpcb) = 3; rpcblist_ptr RPCBPROC_DUMP(void) = 4; /* * NOTE: RPCBPROC_BCAST has the same functionality as CALLIT; * the new name is intended to indicate that this * procedure should be used for broadcast RPC, and * RPCBPROC_INDIRECT should be used for indirect calls. */ rpcb_rmtcallres RPCBPROC_BCAST(rpcb_rmtcallargs) = RPCBPROC_CALLIT; unsigned int RPCBPROC_GETTIME(void) = 6; struct netbuf RPCBPROC_UADDR2TADDR(string) = 7; string RPCBPROC_TADDR2UADDR(struct netbuf) = 8; string RPCBPROC_GETVERSADDR(rpcb) = 9; rpcb_rmtcallres RPCBPROC_INDIRECT(rpcb_rmtcallargs) = 10; rpcb_entry_list_ptr RPCBPROC_GETADDRLIST(rpcb) = 11; rpcb_stat_byvers RPCBPROC_GETSTAT(void) = 12; } = 4; } = 100000; #ifdef RPC_HDR % %#define RPCBVERS_3 RPCBVERS %#define RPCBVERS_4 RPCBVERS4 % %#define _PATH_RPCBINDSOCK "/var/run/rpcbind.sock" % %#else /* ndef _KERNEL */ %#ifdef __cplusplus %extern "C" { %#endif % %/* % * A mapping of (program, version, network ID) to address % */ %struct rpcb { % rpcprog_t r_prog; /* program number */ % rpcvers_t r_vers; /* version number */ % char *r_netid; /* network id */ % char *r_addr; /* universal address */ % char *r_owner; /* owner of the mapping */ %}; %typedef struct rpcb RPCB; % %/* % * A list of mappings % */ %struct rpcblist { % RPCB rpcb_map; % struct rpcblist *rpcb_next; %}; %typedef struct rpcblist RPCBLIST; %typedef struct rpcblist *rpcblist_ptr; % %/* % * Remote calls arguments % */ %struct rpcb_rmtcallargs { % rpcprog_t prog; /* program number */ % rpcvers_t vers; /* version number */ % rpcproc_t proc; /* procedure number */ % u_int32_t arglen; /* arg len */ % caddr_t args_ptr; /* argument */ % xdrproc_t xdr_args; /* XDR routine for argument */ %}; %typedef struct rpcb_rmtcallargs rpcb_rmtcallargs; % %/* % * Remote calls results % */ %struct rpcb_rmtcallres { % char *addr_ptr; /* remote universal address */ % u_int32_t resultslen; /* results length */ % caddr_t results_ptr; /* results */ % xdrproc_t xdr_results; /* XDR routine for result */ %}; %typedef struct rpcb_rmtcallres rpcb_rmtcallres; % %struct rpcb_entry { % char *r_maddr; % char *r_nc_netid; % unsigned int r_nc_semantics; % char *r_nc_protofmly; % char *r_nc_proto; %}; %typedef struct rpcb_entry rpcb_entry; % %/* % * A list of addresses supported by a service. % */ % %struct rpcb_entry_list { % rpcb_entry rpcb_entry_map; % struct rpcb_entry_list *rpcb_entry_next; %}; %typedef struct rpcb_entry_list rpcb_entry_list; % %typedef rpcb_entry_list *rpcb_entry_list_ptr; % %/* % * rpcbind statistics % */ % %#define rpcb_highproc_2 RPCBPROC_CALLIT %#define rpcb_highproc_3 RPCBPROC_TADDR2UADDR %#define rpcb_highproc_4 RPCBPROC_GETSTAT %#define RPCBSTAT_HIGHPROC 13 %#define RPCBVERS_STAT 3 %#define RPCBVERS_4_STAT 2 %#define RPCBVERS_3_STAT 1 %#define RPCBVERS_2_STAT 0 % %/* Link list of all the stats about getport and getaddr */ % %struct rpcbs_addrlist { % rpcprog_t prog; % rpcvers_t vers; % int success; % int failure; % char *netid; % struct rpcbs_addrlist *next; %}; %typedef struct rpcbs_addrlist rpcbs_addrlist; % %/* Link list of all the stats about rmtcall */ % %struct rpcbs_rmtcalllist { % rpcprog_t prog; % rpcvers_t vers; % rpcproc_t proc; % int success; % int failure; % int indirect; % char *netid; % struct rpcbs_rmtcalllist *next; %}; %typedef struct rpcbs_rmtcalllist rpcbs_rmtcalllist; % %typedef int rpcbs_proc[RPCBSTAT_HIGHPROC]; % %typedef rpcbs_addrlist *rpcbs_addrlist_ptr; % %typedef rpcbs_rmtcalllist *rpcbs_rmtcalllist_ptr; % %struct rpcb_stat { % rpcbs_proc info; % int setinfo; % int unsetinfo; % rpcbs_addrlist_ptr addrinfo; % rpcbs_rmtcalllist_ptr rmtinfo; %}; %typedef struct rpcb_stat rpcb_stat; % %/* % * One rpcb_stat structure is returned for each version of rpcbind % * being monitored. % */ % %typedef rpcb_stat rpcb_stat_byvers[RPCBVERS_STAT]; % %#ifdef __cplusplus %} %#endif % %#endif /* ndef _KERNEL */ #endif /* RPC_HDR */ ntirpc-1.3.1/ntirpc/rpc/rpcent.h000066400000000000000000000053621261345040100165440ustar00rootroot00000000000000/* $NetBSD: rpcent.h,v 1.1 2000/06/02 22:57:56 fvdl Exp $ */ /* $FreeBSD: src/include/rpc/rpcent.h,v 1.2 2002/03/23 17:24:55 * imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * rpcent.h, * For converting rpc program numbers to names etc. * */ #ifndef _RPC_RPCENT_H #define _RPC_RPCENT_H /* #pragma ident "@(#)rpcent.h 1.13 94/04/25 SMI" */ /* @(#)rpcent.h 1.1 88/12/06 SMI */ __BEGIN_DECLS /* These are defined in /usr/include/rpc/netdb.h */ #if defined(__FreeBSD__) struct rpcent { char *r_name; /* name of server for this rpc program */ char **r_aliases; /* alias list */ int r_number; /* rpc program number */ }; #endif #if 0 extern struct rpcent *getrpcbyname_r(const char *, struct rpcent *, char *, int); extern struct rpcent *getrpcbynumber_r(int, struct rpcent *, char *, int); extern struct rpcent *getrpcent_r(struct rpcent *, char *, int); /* Old interfaces that return a pointer to a static area; MT-unsafe */ extern struct rpcent *getrpcbyname(char *); extern struct rpcent *getrpcbynumber(int); extern struct rpcent *getrpcent(void); #endif extern void setrpcent(int); extern void endrpcent(void); __END_DECLS #endif /* !_RPC_CENT_H */ ntirpc-1.3.1/ntirpc/rpc/svc.h000066400000000000000000000636761261345040100160600ustar00rootroot00000000000000/* $netbsd: svc.h,v 1.17 2000/06/02 22:57:56 fvdl Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)svc.h 1.35 88/12/17 SMI * from: @(#)svc.h 1.27 94/04/25 SMI * $FreeBSD: src/include/rpc/svc.h,v 1.24 2003/06/15 10:32:01 mbr Exp $ */ /* * svc.h, Server-side remote procedure call interface. * * Copyright (C) 1986-1993 by Sun Microsystems, Inc. */ #ifndef _TIRPC_SVC_H #define _TIRPC_SVC_H #include #include #include #include #include #include #include "reentrant.h" #if defined(HAVE_BLKIN) #include #endif /* * This interface must manage two items concerning remote procedure calling: * * 1) An arbitrary number of transport connections upon which rpc requests * are received. The two most notable transports are TCP and UDP; they are * created and registered by routines in svc_tcp.c and svc_udp.c, respectively; * they in turn call xprt_register and xprt_unregister. * * 2) An arbitrary number of locally registered services. Services are * described by the following four data: program number, version number, * "service dispatch" function, a transport handle, and a boolean that * indicates whether or not the exported program should be registered with a * local binder service; if true the program's number and version and the * port number from the transport handle are registered with the binder. * These data are registered with the rpc svc system via svc_register. * * A service's dispatch function is called whenever an rpc request comes in * on a transport. The request's program and version numbers must match * those of the registered service. The dispatch function is passed two * parameters, struct svc_req * and SVCXPRT *, defined below. */ /* Package init flags */ #define SVC_INIT_DEFAULT 0x0000 #define SVC_INIT_XPRTS 0x0001 #define SVC_INIT_EPOLL 0x0002 #define SVC_INIT_WARNX 0x0004 #define SVC_INIT_NOREG_XPRTS 0x0008 #define SVC_INIT_BLKIN 0x0010 #define SVC_SHUTDOWN_FLAG_NONE 0x0000 /* * Service control requests */ #define SVCGET_VERSQUIET 1 #define SVCSET_VERSQUIET 2 #define SVCGET_CONNMAXREC 3 #define SVCSET_CONNMAXREC 4 #define SVCGET_XP_RECV 5 #define SVCSET_XP_RECV 6 #define SVCGET_XP_FLAGS 7 #define SVCSET_XP_FLAGS 8 #define SVCGET_XP_GETREQ 9 #define SVCSET_XP_GETREQ 10 #define SVCGET_XP_DISPATCH 11 #define SVCSET_XP_DISPATCH 12 #define SVCGET_XP_RECV_USER_DATA 13 #define SVCSET_XP_RECV_USER_DATA 14 #define SVCGET_XP_FREE_USER_DATA 15 #define SVCSET_XP_FREE_USER_DATA 16 /* * Operations for rpc_control(). */ #define RPC_SVC_CONNMAXREC_SET 0 /* set max rec size, enable nonblock */ #define RPC_SVC_CONNMAXREC_GET 1 #define RPC_SVC_XPRTS_GET 2 #define RPC_SVC_XPRTS_SET 3 #define RPC_SVC_FDSET_GET 4 #define RPC_SVC_FDSET_SET 5 /* * Flags for svc_fd_ncreate2 */ #define SVC_VCCR_NONE 0x0000 /* Svc event strategy */ enum svc_event_type { SVC_EVENT_FDSET /* trad. using select and poll (currently unhooked) */ , SVC_EVENT_EPOLL /* Linux epoll interface */ }; typedef struct svc_init_params { u_long flags; warnx_t warnx; u_int max_connections; /* xprts */ u_int max_events; /* evchan events */ u_int svc_ioq_maxbuf; int32_t idle_timeout; u_int gss_ctx_hash_partitions; u_int gss_max_ctx; u_int gss_max_idle_gen; u_int gss_max_gc; u_int ioq_thrd_max; } svc_init_params; /* Svc param flags */ #define SVC_FLAG_NONE 0x0000 #define SVC_FLAG_NOREG_XPRTS 0x0001 /* * SVCXPRT xp_flags */ #define SVC_XPRT_FLAG_NONE 0x0000 /* uint16_t actually used */ #define SVC_XPRT_FLAG_ADDED 0x0001 #define SVC_XPRT_FLAG_BLOCKED 0x0002 #define SVC_XPRT_FLAG_DESTROYED 0x0020 /* SVC_DESTROY() was called */ #define SVC_XPRT_FLAG_DESTROYING 0x0040 /* (*xp_destroy) was called */ /* uint32_t instructions */ #define SVC_XPRT_FLAG_LOCK SVC_XPRT_FLAG_NONE #define SVC_XPRT_FLAG_LOCKED 0x00010000 #define SVC_XPRT_FLAG_UNLOCK 0x00020000 /* * SVC_REF flags */ #define SVC_REF_FLAG_NONE SVC_XPRT_FLAG_NONE #define SVC_REF_FLAG_LOCKED SVC_XPRT_FLAG_LOCKED /* * SVC_RELEASE flags */ #define SVC_RELEASE_FLAG_NONE SVC_XPRT_FLAG_NONE #define SVC_RELEASE_FLAG_LOCKED SVC_XPRT_FLAG_LOCKED /* XXX Ganesha * Don't confuse with (currently incomplete) transport type, nee * socktype. */ typedef enum xprt_type { XPRT_UNKNOWN = 0, XPRT_UDP, XPRT_TCP, XPRT_TCP_RENDEZVOUS, XPRT_SCTP, XPRT_RDMA } xprt_type_t; enum xprt_stat { XPRT_DIED, XPRT_MOREREQS, XPRT_IDLE, XPRT_DESTROYED }; struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */ u_int sendsize; u_int recvsize; int maxrec; }; struct SVCAUTH; /* forward decl. */ /* * Server side transport handle */ typedef struct rpc_svcxprt { struct xp_ops { /* receive incoming requests */ bool (*xp_recv) (struct rpc_svcxprt *, struct svc_req *); /* get transport status */ enum xprt_stat (*xp_stat) (struct rpc_svcxprt *); /* get arguments, thread u_data in arg4 */ bool (*xp_getargs) (struct rpc_svcxprt *, struct svc_req *, xdrproc_t, void *, void *); /* send reply */ bool (*xp_reply) (struct rpc_svcxprt *, struct svc_req *, struct rpc_msg *); /* free mem allocated for args */ bool (*xp_freeargs) (struct rpc_svcxprt *, struct svc_req *, xdrproc_t, void *); /* actually destroy after xp_destroy_it and xp_release_it */ void (*xp_destroy) (struct rpc_svcxprt *, u_int, const char *, const int); /* catch-all function */ bool (*xp_control) (struct rpc_svcxprt *, const u_int, void *); /* transport locking (may be duplex-aware, etc) */ void (*xp_lock) (struct rpc_svcxprt *, uint32_t, const char *, int); void (*xp_unlock) (struct rpc_svcxprt *, uint32_t, const char *, int); /* handle incoming requests (calls xp_recv) */ bool (*xp_getreq) (struct rpc_svcxprt *); /* call dispatch strategy function */ void (*xp_dispatch) (struct rpc_svcxprt *, struct rpc_msg **); /* rendezvous (epilogue) */ u_int (*xp_recv_user_data) (struct rpc_svcxprt *, struct rpc_svcxprt *, const u_int, void *); /* free client user data */ bool (*xp_free_user_data) (struct rpc_svcxprt *); } *xp_ops; char *xp_tp; /* transport provider device name */ char *xp_netid; /* network token */ void *xp_ev; /* event handle */ void *xp_p1; /* private: for use by svc ops */ void *xp_p2; /* private: for use by svc ops */ void *xp_p3; /* private: for use by svc lib */ void *xp_p4; /* private: for use by svc lib */ void *xp_p5; /* private: for use by svc lib */ void *xp_u1; /* client user data */ void *xp_u2; /* client user data */ struct rpc_address xp_local; /* local address, length, port */ struct rpc_address xp_remote; /* remote address, length, port */ #if defined(HAVE_BLKIN) /* blkin tracing */ struct { char *svc_name; struct blkin_endpoint endp; } blkin; #endif /* auth */ mutex_t xp_auth_lock; /* lock owned by installed authenticator */ /* serialize private data */ mutex_t xp_lock; /* event vector list */ TAILQ_ENTRY(rpc_svcxprt) xp_evq; /* indexed by fd */ struct opr_rbtree_node xp_fd_node; uint32_t xp_refs; /* handle reference count */ uint32_t xp_requests; /* related requests count */ int xp_fd; int xp_si_type; /* si type */ int xp_type; /* xprt type */ uint16_t xp_flags; /* flags */ u_short xp_port; /* associated port number */ /* * union of event processor types */ enum svc_event_type ev_type; union { #if defined(TIRPC_EPOLL) struct { struct epoll_event event; } epoll; #endif } ev_u; } SVCXPRT; /* Service record used by exported search routines */ typedef struct svc_record { rpcprog_t sc_prog; rpcvers_t sc_vers; char *sc_netid; void (*sc_dispatch) (struct svc_req *, SVCXPRT *); } svc_rec_t; typedef struct svc_vers_range { rpcvers_t lowvers; rpcvers_t highvers; } svc_vers_range_t; typedef enum svc_lookup_result { SVC_LKP_SUCCESS = 0, SVC_LKP_PROG_NOTFOUND = 1, SVC_LKP_VERS_NOTFOUND = 2, SVC_LKP_NETID_NOTFOUND = 3, SVC_LKP_ERR = 667, } svc_lookup_result_t; /* functions which can be installed using a control function, e.g., * xp_ops->xp_control */ typedef bool(*xp_recv_t) (struct rpc_svcxprt *, struct svc_req *); typedef bool(*xp_getreq_t) (struct rpc_svcxprt *); typedef void (*xp_dispatch_t) (struct rpc_svcxprt *, struct rpc_msg **); typedef u_int(*xp_recv_user_data_t) (struct rpc_svcxprt *, struct rpc_svcxprt *, const u_int, void *); typedef bool(*xp_free_user_data_t) (struct rpc_svcxprt *); /* * Service request */ struct svc_req { u_int32_t rq_prog; /* service program number */ u_int32_t rq_vers; /* service protocol version */ u_int32_t rq_proc; /* the desired procedure */ struct opaque_auth rq_cred; /* raw creds from the wire */ void *rq_clntcred; /* read only cooked cred */ SVCXPRT *rq_xprt; /* associated transport */ /* New with TI-RPC */ caddr_t rq_clntname; /* read only client name */ caddr_t rq_svcname; /* read only cooked service cred */ /* New with N TI-RPC */ struct rpc_msg *rq_msg; /* decoded rpc_msg */ void *rq_context; /* private context */ void *rq_u1; /* user data */ void *rq_u2; /* user data */ uint64_t rq_cksum; u_int32_t rq_xid; /* xid */ /* Moved in N TI-RPC */ struct opaque_auth rq_verf; /* raw response verifier */ struct SVCAUTH *rq_auth; /* auth handle */ void *rq_ap1; /* auth private */ void *rq_ap2; /* auth private */ /* copy of remote transport address */ struct sockaddr_storage rq_raddr; /* Store dest addr for UDP to send replys from */ struct sockaddr_storage rq_daddr; size_t rq_raddr_len; size_t rq_daddr_len; #if defined(HAVE_BLKIN) /* blkin tracing */ struct blkin_trace bl_trace; #endif }; /* * Approved way of getting addresses */ #define svc_getrpccaller(x) (&(x)->xp_remote.ss) #define svc_getrpclocal(x) (&(x)->xp_local.ss) /* * Ganesha. Get connected transport type. */ #define svc_get_xprt_type(x) ((x)->xp_type) /* * Ganesha. Original TI-RPC si type. */ #define svc_get_xprt_si_type(x) ((x)->xp_si_type) /* * Trace transport (de-)references, with remote address */ __BEGIN_DECLS extern void svc_xprt_trace(SVCXPRT *, const char *, const char *, const int); __END_DECLS #define XPRT_TRACE(xprt, func, tag, line) \ if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_REFCNT) { \ svc_xprt_trace((xprt), (func), (tag), (line)); \ } /* * Operations defined on an SVCXPRT handle * * SVCXPRT *xprt; * struct svc_req *req; * xdrproc_t xargs; * void * argsp; */ #define SVC_RECV(xprt, req) \ (*(xprt)->xp_ops->xp_recv)((xprt), (req)) #define svc_recv(xprt, req) \ (*(xprt)->xp_ops->xp_recv)((xprt), (req)) #define SVC_STAT(xprt) \ (*(xprt)->xp_ops->xp_stat)(xprt) #define svc_stat(xprt) \ (*(xprt)->xp_ops->xp_stat)(xprt) #define SVC_GETARGS(xprt, req, xargs, argsp, u_data) \ (*(xprt)->xp_ops->xp_getargs)((xprt), (req), (xargs), (argsp), \ (u_data)) #define svc_getargs(xprt, req, xargs, argsp, u_data) \ (*(xprt)->xp_ops->xp_getargs)((xprt), (req), (xargs), (argsp), \ (u_data)) #define SVC_REPLY(xprt, req, msg) \ (*(xprt)->xp_ops->xp_reply) ((xprt), (req), (msg)) #define svc_reply(xprt, req, msg) \ (*(xprt)->xp_ops->xp_reply) ((xprt), (req), (msg)) #define SVC_FREEARGS(xprt, req, xargs, argsp) \ (*(xprt)->xp_ops->xp_freeargs)((xprt), (req), (xargs), (argsp)) #define svc_freeargs(xprt, req, xargs, argsp) \ (*(xprt)->xp_ops->xp_freeargs)((xprt), (req), (xargs), (argsp)) /* Protect a SVCXPRT with a SVC_REF for each call or request. */ static inline void svc_ref_it(struct rpc_svcxprt *xprt, u_int flags, const char *tag, const int line) { atomic_inc_uint32_t(&xprt->xp_refs); if (flags & SVC_REF_FLAG_LOCKED) { /* unlock before warning trace */ mutex_unlock(&xprt->xp_lock); } XPRT_TRACE(xprt, __func__, tag, line); } #define SVC_REF2(xprt, flags, tag, line) \ svc_ref_it(xprt, flags, tag, line) #define svc_ref2(xprt, flags, tag, line) \ svc_ref_it(xprt, flags, tag, line) #define SVC_REF(xprt, flags) \ svc_ref_it(xprt, flags, __func__, __LINE__) #define svc_ref(xprt, flags) \ svc_ref_it(xprt, flags, __func__, __LINE__) static inline void svc_release_it(struct rpc_svcxprt *xprt, u_int flags, const char *tag, const int line) { uint32_t refs = atomic_dec_uint32_t(&xprt->xp_refs); uint16_t xp_flags; if (flags & SVC_RELEASE_FLAG_LOCKED) { /* unlock before warning trace */ mutex_unlock(&xprt->xp_lock); } XPRT_TRACE(xprt, __func__, tag, line); if (likely(refs > 0)) { /* normal case */ return; } /* enforce once-only semantic, trace others */ xp_flags = atomic_postset_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_DESTROYING); if (xp_flags & SVC_XPRT_FLAG_DESTROYING) { XPRT_TRACE(xprt, "ERROR! already destroying!", tag, line); return; } /* Releasing last reference */ (*(xprt)->xp_ops->xp_destroy)(xprt, flags, tag, line); } #define SVC_RELEASE2(xprt, flags, tag, line) \ svc_release_it(xprt, flags, __func__, __LINE__) #define svc_release2(xprt, flags, tag, line) \ svc_release_it(xprt, flags, __func__, __LINE__) #define SVC_RELEASE(xprt, flags) \ svc_release_it(xprt, flags, __func__, __LINE__) #define svc_release(xprt, flags) \ svc_release_it(xprt, flags, __func__, __LINE__) /* SVC_DESTROY is SVC_RELEASE with once-only semantics. Also, idempotent * SVC_XPRT_FLAG_DESTROYED indicates that more references should not be taken. */ static inline void svc_destroy_it(struct rpc_svcxprt *xprt, const char *tag, const int line) { uint16_t flags = atomic_postset_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_DESTROYED); XPRT_TRACE(xprt, __func__, tag, line); if (flags & SVC_XPRT_FLAG_DESTROYED) { /* previously set, do nothing */ return; } svc_release_it(xprt, SVC_RELEASE_FLAG_NONE, tag, line); } #define SVC_DESTROY(xprt) \ svc_destroy_it(xprt, __func__, __LINE__) #define svc_destroy(xprt) \ svc_destroy_it(xprt, __func__, __LINE__) #define SVC_CONTROL(xprt, rq, in) \ (*(xprt)->xp_ops->xp_control)((xprt), (rq), (in)) #define XP_LOCK_NONE 0x0000 #define XP_LOCK_SEND 0x0001 #define XP_LOCK_RECV 0x0002 #define SVC_LOCK(xprt, flags, func, line) \ (*(xprt)->xp_ops->xp_lock)((xprt), (flags), (func), (line)) #define svc_lock(xprt, flags, func, line) \ (*(xprt)->xp_ops->xp_lock)((xprt), (flags), (func), (line)) #define SVC_UNLOCK(xprt, flags, func, line) \ (*(xprt)->xp_ops->xp_unlock)((xprt), (flags), (func), (line)) #define svc_unlock(xprt, flags, func, line) \ (*(xprt)->xp_ops->xp_unlock)((xprt), (flags), (func), (line)) /* * Service init (optional). */ __BEGIN_DECLS extern struct work_pool svc_work_pool; bool svc_init(struct svc_init_params *); __END_DECLS /* * Service shutdown (optional). */ __BEGIN_DECLS int svc_shutdown(u_long flags); __END_DECLS /* * Service registration * * svc_reg(xprt, prog, vers, dispatch, nconf) * const SVCXPRT *xprt; * const rpcprog_t prog; * const rpcvers_t vers; * const void (*dispatch)(); * const struct netconfig *nconf; */ __BEGIN_DECLS extern bool svc_reg(SVCXPRT *, const rpcprog_t, const rpcvers_t, void (*)(struct svc_req *, SVCXPRT *), const struct netconfig *); __END_DECLS /* * Service un-registration * * svc_unreg(prog, vers) * const rpcprog_t prog; * const rpcvers_t vers; */ __BEGIN_DECLS extern void svc_unreg(const rpcprog_t, const rpcvers_t); __END_DECLS /* * Transport registration. * * xprt_register(xprt) * SVCXPRT *xprt; */ __BEGIN_DECLS extern void xprt_register(SVCXPRT *); __END_DECLS /* * Transport un-register * * xprt_unregister(xprt) * SVCXPRT *xprt; */ __BEGIN_DECLS extern void xprt_unregister(SVCXPRT *); __END_DECLS /* * This is used to set local and remote addresses in a way legacy * apps can deal with, at the same time setting up a corresponding * netbuf -- with no alloc/free needed. */ __BEGIN_DECLS extern void __rpc_set_address(struct rpc_address *, const struct sockaddr_storage *, socklen_t); __END_DECLS /* * When the service routine is called, it must first check to see if it * knows about the procedure; if not, it should call svcerr_noproc * and return. If so, it should deserialize its arguments via * SVC_GETARGS (defined above). If the deserialization does not work, * svcerr_decode should be called followed by a return. Successful * decoding of the arguments should be followed the execution of the * procedure's code and a call to svc_sendreply. * * Also, if the service refuses to execute the procedure due to too- * weak authentication parameters, svcerr_weakauth should be called. * Note: do not confuse access-control failure with weak authentication! * * NB: In pure implementations of rpc, the caller always waits for a reply * msg. This message is sent when svc_sendreply is called. * Therefore pure service implementations should always call * svc_sendreply even if the function logically returns void; use * xdr.h - xdr_void for the xdr routine. HOWEVER, tcp based rpc allows * for the abuse of pure rpc via batched calling or pipelining. In the * case of a batched call, svc_sendreply should NOT be called since * this would send a return message, which is what batching tries to avoid. * It is the service/protocol writer's responsibility to know which calls are * batched and which are not. Warning: responding to batch calls may * deadlock the caller and server processes! */ __BEGIN_DECLS extern bool svc_sendreply(SVCXPRT *, struct svc_req *, xdrproc_t, void *); extern void svcerr_decode(SVCXPRT *, struct svc_req *); extern void svcerr_weakauth(SVCXPRT *, struct svc_req *); extern void svcerr_noproc(SVCXPRT *, struct svc_req *); extern void svcerr_progvers(SVCXPRT *, struct svc_req *, rpcvers_t, rpcvers_t); extern void svcerr_auth(SVCXPRT *, struct svc_req *, enum auth_stat); extern void svcerr_noprog(SVCXPRT *, struct svc_req *); extern void svcerr_systemerr(SVCXPRT *, struct svc_req *); extern int rpc_reg(rpcprog_t, rpcvers_t, rpcproc_t, char *(*)(char *), xdrproc_t, xdrproc_t, char *); __END_DECLS /* * a small program implemented by the svc_rpc implementation itself; * also see clnt.h for protocol numbers. */ __BEGIN_DECLS extern void rpctest_service(void); __END_DECLS __BEGIN_DECLS extern void svc_getreq(int); extern void svc_getreqset(fd_set *); extern void svc_getreq_common(int); struct pollfd; extern void svc_getreq_poll(struct pollfd *, int); extern void svc_run(void); extern void svc_exit(void); __END_DECLS /* * Socket to use on svcxxx_ncreate call to get default socket */ #define RPC_ANYSOCK -1 #define RPC_ANYFD RPC_ANYSOCK /* * These are the existing service side transport implementations */ __BEGIN_DECLS /* * Transport independent svc_create routine. */ extern int svc_ncreate(void (*)(struct svc_req *, SVCXPRT *), const rpcprog_t, const rpcvers_t, const char *); /* * void (*dispatch)(); -- dispatch routine * const rpcprog_t prognum; -- program number * const rpcvers_t versnum; -- version number * const char *nettype; -- network type */ /* * Generic server creation routine. It takes a netconfig structure * instead of a nettype. */ extern SVCXPRT *svc_tp_ncreate(void (*)(struct svc_req *, SVCXPRT *), const rpcprog_t, const rpcvers_t, const struct netconfig *); /* * void (*dispatch)(); -- dispatch routine * const rpcprog_t prognum; -- program number * const rpcvers_t versnum; -- version number * const struct netconfig *nconf; -- netconfig structure */ /* * Generic TLI create routine */ extern SVCXPRT *svc_tli_ncreate(const int, const struct netconfig *, const struct t_bind *, const u_int, const u_int); /* * const int fd; -- connection end point * const struct netconfig *nconf; -- netconfig structure for network * const struct t_bind *bindaddr; -- local bind address * const u_int sendsz; -- max sendsize * const u_int recvsz; -- max recvsize */ /* * Connectionless and connectionful create routines */ extern SVCXPRT *svc_vc_ncreate(const int, const u_int, const u_int); /* * const int fd; -- open connection end point * const u_int sendsize; -- max send size * const u_int recvsize; -- max recv size */ extern SVCXPRT *svc_vc_ncreate2(const int, const u_int, const u_int, const u_int); /* * const int fd; -- open connection end point * const u_int sendsize; -- max send size * const u_int recvsize; -- max recv size * const u_int flags; -- flags */ __END_DECLS #define SVC_VC_CREATE_NONE 0x0000 #define SVC_VC_CREATE_BOTHWAYS 0x0001 #define SVC_VC_CREATE_ONEWAY 0x0002 /* !bothways */ #define SVC_VC_CREATE_DISPOSE 0x0004 /* !bothways */ #define SVC_VC_CREATE_XPRT_NOREG 0x0008 #define SVC_VC_CREATE_LISTEN 0x0010 __BEGIN_DECLS /* * Create a client handle from an active service transport handle. */ extern CLIENT *clnt_vc_ncreate_svc(SVCXPRT *, const rpcprog_t, const rpcvers_t, const uint32_t); /* * SVCXPRT *xprt; -- active service xprt * const rpcprog_t prog; -- RPC program number * const rpcvers_t vers; -- RPC program version */ __END_DECLS __BEGIN_DECLS /* * Create an RPC SVCXPRT handle from an active client transport * handle, i.e., to service RPC requests */ extern SVCXPRT *svc_vc_ncreate_clnt(CLIENT *, u_int, u_int, const uint32_t); /* * * CLIENT *cl; -- connected client * const u_int sendsize; -- max send size * const u_int recvsize; -- max recv size * const uint32_t flags; -- flags */ /* * Added for compatibility to old rpc 4.0. Obsoleted by svc_vc_create(). */ extern SVCXPRT *svcunix_ncreate(int, u_int, u_int, char *); extern SVCXPRT *svc_dg_ncreate(const int, const u_int, const u_int); /* * const int fd; -- open connection * const u_int sendsize; -- max send size * const u_int recvsize; -- max recv size */ /* * the routine takes any *open* connection * descriptor as its first input and is used for open connections. */ extern SVCXPRT *svc_fd_ncreate(const int, const u_int, const u_int); /* * const int fd; -- open connection end point * const u_int sendsize; -- max send size * const u_int recvsize; -- max recv size */ /* * Added for compatibility to old rpc 4.0. Obsoleted by svc_fd_create(). */ extern SVCXPRT *svcunixfd_ncreate(int, u_int, u_int); /* * Memory based rpc (for speed check and testing) */ extern SVCXPRT *svc_raw_ncreate(void); /* * RDMA based rpc */ extern SVCXPRT *svc_rdma_ncreate(void *arg, const u_int sendsize, const u_int recvsize, const u_int flags); struct rpc_rdma_attr { char *statistics_prefix; /* silly char * to pass to rdma_getaddrinfo() */ char *node; /**< remote peer's hostname */ char *port; /**< service port (or name) */ void (*disconnect_cb)(SVCXPRT *); enum xprt_stat (*request_cb)(void *, SVCXPRT *); u_long timeout; /**< ms wait for events */ u_int sq_depth; /**< depth of Send Queue */ u_int max_send_sge; /**< s/g elements per send */ u_int rq_depth; /**< depth of Receive Queue. */ u_int max_recv_sge; /**< s/g elements per recv */ u_int backlog; /**< connection backlog */ u_int credits; /**< parallel messages */ u_int worker_count; /**< worker threads */ u_int worker_queue_size; /**< worker data queue */ bool destroy_on_disconnect; /**< should perform cleanup */ bool use_srq; /**< server use srq? */ }; extern SVCXPRT *rpc_rdma_create(struct rpc_rdma_attr *arg); /* * Getreq plug-out prototype */ extern bool svc_getreq_default(SVCXPRT *); /* * Dispatch plug-out prototype */ extern void svc_dispatch_default(SVCXPRT *, struct rpc_msg **); /* * Convenience functions for implementing these */ extern bool svc_validate_xprt_list(SVCXPRT *); extern struct rpc_msg *alloc_rpc_msg(void); extern void free_rpc_msg(struct rpc_msg *); /* * svc_dg_enable_cache() enables the cache on dg transports. */ int svc_dg_enablecache(SVCXPRT *, const u_int); int __rpc_get_local_uid(SVCXPRT *, uid_t *); __END_DECLS /* for backward compatibility */ #include #include #endif /* !_TIRPC_SVC_H */ ntirpc-1.3.1/ntirpc/rpc/svc_auth.h000066400000000000000000000061411261345040100170610ustar00rootroot00000000000000/* $NetBSD: svc_auth.h,v 1.8 2000/06/02 22:57:57 fvdl Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)svc_auth.h 1.6 86/07/16 SMI * @(#)svc_auth.h 2.1 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/svc_auth.h,v 1.14 2002/03/23 17:24:55 imp Exp $ */ /* * svc_auth.h, Service side of rpc authentication. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef _RPC_SVC_AUTH_H #define _RPC_SVC_AUTH_H #include /* * Interface to server-side authentication flavors. */ typedef struct SVCAUTH { struct svc_auth_ops { bool(*svc_ah_wrap) (struct SVCAUTH *, struct svc_req *, XDR *, xdrproc_t, caddr_t); bool(*svc_ah_unwrap) (struct SVCAUTH *, struct svc_req *, XDR *, xdrproc_t, caddr_t); bool(*svc_ah_release) (struct SVCAUTH *, struct svc_req *); bool(*svc_ah_destroy) (struct SVCAUTH *); } *svc_ah_ops; caddr_t svc_ah_private; } SVCAUTH; #define SVCAUTH_WRAP(auth, req, xdrs, xfunc, xwhere) \ ((*((auth)->svc_ah_ops->svc_ah_wrap))(auth, req, xdrs, xfunc, xwhere)) #define SVCAUTH_UNWRAP(auth, req, xdrs, xfunc, xwhere) \ ((*((auth)->svc_ah_ops->svc_ah_unwrap))(auth, req, xdrs, xfunc, xwhere)) #define SVCAUTH_RELEASE(auth, req) \ ((*((auth)->svc_ah_ops->svc_ah_release))(auth, req)) #define SVCAUTH_DESTROY(auth) \ ((*((auth)->svc_ah_ops->svc_ah_destroy))(auth)) /* * Server side authenticator */ __BEGIN_DECLS extern enum auth_stat svc_auth_authenticate(struct svc_req *, struct rpc_msg *, bool *); extern int svc_auth_reg(int, enum auth_stat (*)(struct svc_req *, struct rpc_msg *)); __END_DECLS #endif /* !_RPC_SVC_AUTH_H */ ntirpc-1.3.1/ntirpc/rpc/svc_dg.h000066400000000000000000000054571261345040100165230ustar00rootroot00000000000000/* $NetBSD: svc_dg.h,v 1.1 2000/06/02 23:11:16 fvdl Exp $ */ /* $FreeBSD: src/include/rpc/svc_dg.h,v 1.1 2001/03/19 12:49:47 * alfred Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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. */ #ifndef _TIRPC_SVC_DG_H_ #define _TIRPC_SVC_DG_H_ #include #include /* * The following union is defined just to use SVC_CMSG_LEN macro for an * array length. _GNU_SOURCE must be defined to get in6_pktinfo * declaration! */ union in_pktinfo_u { struct in_pktinfo x; struct in6_pktinfo y; }; #define SVC_CMSG_LEN CMSG_SPACE(sizeof(union in_pktinfo_u)) /* * 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 */ struct msghdr su_msghdr; /* msghdr received from clnt */ unsigned char su_cmsg[SVC_CMSG_LEN]; /* cmsghdr received from clnt */ }; #define __rpcb_get_dg_xidp(x) (&((struct svc_dg_data *)(x)->xp_p2)->su_xid) #endif ntirpc-1.3.1/ntirpc/rpc/svc_rqst.h000066400000000000000000000077401261345040100171170ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TIRPC_SVC_RQST_H #define TIRPC_SVC_RQST_H #include /** ** Maintains a tree of all extant transports by event **/ #define SVC_RQST_FLAG_NONE SVC_XPRT_FLAG_NONE /* uint16_t actually used */ #define SVC_RQST_FLAG_CHAN_AFFINITY 0x1000 /* bind conn to parent chan */ #define SVC_RQST_FLAG_MASK (SVC_RQST_FLAG_CHAN_AFFINITY) /* uint32_t instructions */ #define SVC_RQST_FLAG_LOCKED SVC_XPRT_FLAG_LOCKED #define SVC_RQST_FLAG_UNLOCK SVC_XPRT_FLAG_UNLOCK #define SVC_RQST_FLAG_EPOLL 0x00080000 #define SVC_RQST_FLAG_PART_LOCKED 0x00100000 #define SVC_RQST_FLAG_PART_UNLOCK 0x00200000 #define SVC_RQST_FLAG_SREC_LOCKED 0x01000000 #define SVC_RQST_FLAG_SREC_UNLOCK 0x02000000 #define SVC_RQST_FLAG_XPRT_UREG 0x04000000 #define SR_REQ_RELEASE_KEEP_LOCKED 0x08000000 /* * exported interface: * * svc_rqst_init -- init module (optional) * svc_rqst_init_xprt -- init svc_rqst part of xprt handle * svc_rqst_new_evchan -- create event channel * svc_rqst_evchan_reg -- set {xprt, dispatcher} mapping * svc_rqst_foreach_xprt -- scan registered xprts at id (or 0 for all) * svc_rqst_thrd_run -- enter dispatch loop at id * svc_rqst_thrd_signal --request thread to run a callout function which * can cause the thread to return * svc_rqst_shutdown -- cause all threads to return * * callback function interface: * * svc_xprt_rendezvous -- called when a new transport connection is accepted, * can be used by the application to chose a correct request handler, or do * other adaptation */ void svc_rqst_init(); void svc_rqst_init_xprt(SVCXPRT *xprt); int svc_rqst_new_evchan(uint32_t *chan_id /* OUT */ , void *u_data, uint32_t flags); int svc_rqst_evchan_reg(uint32_t chan_id, SVCXPRT *xprt, uint32_t flags); int svc_rqst_rearm_events(SVCXPRT *xprt, uint32_t flags); int svc_rqst_xprt_register(SVCXPRT *xprt, SVCXPRT *newxprt); int svc_rqst_thrd_run(uint32_t chan_id, uint32_t flags); int svc_rqst_thrd_signal(uint32_t chan_id, uint32_t flags); /* xprt/connection rendezvous callout */ typedef int (*svc_rqst_rendezvous_t) (SVCXPRT *oxprt, SVCXPRT *nxprt, uint32_t flags); /* iterator callback prototype */ typedef void (*svc_rqst_xprt_each_func_t) (uint32_t chan_id, SVCXPRT *xprt, void *arg); int svc_rqst_foreach_xprt(uint32_t chan_id, svc_rqst_xprt_each_func_t each_f, void *arg); #define SVC_RQST_STATE_NONE 0x00000 #define SVC_RQST_STATE_ACTIVE 0x00001 /* thrd in event loop */ #define SVC_RQST_STATE_BLOCKED 0x00002 /* channel blocked */ #define SVC_RQST_STATE_DESTROYED 0x00004 #define SVC_RQST_SIGNAL_SHUTDOWN 0x00008 /* chan shutdown */ #define SVC_RQST_SIGNAL_MASK (SVC_RQST_SIGNAL_SHUTDOWN) #endif /* TIRPC_SVC_RQST_H */ ntirpc-1.3.1/ntirpc/rpc/svc_soc.h000066400000000000000000000066221261345040100167100ustar00rootroot00000000000000/* $NetBSD: svc_soc.h,v 1.1 2000/06/02 22:57:57 fvdl Exp $ */ /* $FreeBSD: src/include/rpc/svc_soc.h,v 1.2 2002/03/23 17:24:55 imp Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * svc.h, Server-side remote procedure call interface. */ #ifndef _RPC_SVC_SOC_H #define _RPC_SVC_SOC_H #include /* #pragma ident "@(#)svc_soc.h 1.11 94/04/25 SMI" */ /* svc_soc.h 1.8 89/05/01 SMI */ /* * All the following declarations are only for backward compatibility * with TS-RPC */ /* * Approved way of getting addresses */ #define svc_getcaller_netbuf(x) (&(x)->xp_remote.nb) #define svc_getlocal_netbuf(x) (&(x)->xp_local.nb) /* * Service registration * * svc_register(xprt, prog, vers, dispatch, protocol) * SVCXPRT *xprt; * u_long prog; * u_long vers; * void (*dispatch)(); * int protocol; like TCP or UDP, zero means do not register */ __BEGIN_DECLS extern bool svc_register(SVCXPRT *, u_long, u_long, void (*)(struct svc_req *, SVCXPRT *), int); __END_DECLS /* * Service un-registration * * svc_unregister(prog, vers) * u_long prog; * u_long vers; */ __BEGIN_DECLS extern void svc_unregister(u_long, u_long); __END_DECLS /* * Memory based rpc for testing and timing. */ __BEGIN_DECLS extern SVCXPRT *svcraw_ncreate(void); __END_DECLS /* * Udp based rpc. */ __BEGIN_DECLS extern SVCXPRT *svcudp_ncreate(int); extern SVCXPRT *svcudp_nbufcreate(int, u_int, u_int); extern int svcudp_enablecache(SVCXPRT *, u_long); extern SVCXPRT *svcudp6_ncreate(int); extern SVCXPRT *svcudp6_nbufcreate(int, u_int, u_int); __END_DECLS /* * Tcp based rpc. */ __BEGIN_DECLS extern SVCXPRT *svctcp_ncreate(int, u_int, u_int); extern SVCXPRT *svctcp6_ncreate(int, u_int, u_int); __END_DECLS /* * Fd based rpc. */ __BEGIN_DECLS extern SVCXPRT *svcfd_ncreate(int, u_int, u_int); __END_DECLS #endif /* !_RPC_SVC_SOC_H */ ntirpc-1.3.1/ntirpc/rpc/tirpc_compat.h000066400000000000000000000120611261345040100177270ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TIRPC_COMPAT_H #define TIRPC_COMPAT_H /* clnt_soc.h */ #define clnttcp_create(a, b, c, d, e, f) clnttcp_ncreate(a, b, c, d, e, f) #define clntraw_create(a, b) clntraw_ncreate(a, b) #define clnttcp6_create(a, b, c, d, e, f) clnttcp6_ncreate(a, b, c, d, e, f) #define clntudp_create(a, b, c, d, e) clntudp_ncreate(a, b, c, d, e) #define clntudp_bufcreate(a, b, c, d, e, f, g) \ clntudp_nbufcreate(a, b, c, d, e, f, g) #define clntudp6_create(a, b, c, d, e) clntudp6_ncreate(a, b, c, d, e) #define clntudp6_bufcreate(a, b, c, d, e, f, g) \ clntudp6_nbufcreate(a, b, c, d, e, f, g) /* clnt.h */ #define clnt_create(a, b, c, d) clnt_ncreate(a, b, c, d) #define clnt_create_time(a, b, c, d, e) clnt_ncreate_time(a, b, c, d, e) #define clnt_create_vers(a, b, c, d, e, f) clnt_ncreate_vers(a, b, c, d, e, f) #define clnt_create_vers_timed(a, b, c, d, e, f, g) \ clnt_ncreate_vers_timed(a, b, c, d, e, f, g) #define clnt_tp_create(a, b, c, d) clnt_tp_ncreate(a, b, c, d) #define clnt_tp_create_timed(a, b, c, d, e) clnt_tp_ncreate_timed(a, b, c, d, e) #define clnt_tli_create(a, b, c, d, e, f, g) \ clnt_tli_ncreate(a, b, c, d, e, f, g) #define clnt_vc_create(a, b, c, d, e, f) clnt_vc_ncreate(a, b, c, d, e, f) #define clnt_vc_create2(a, b, c, d, e, f, g) \ clnt_vc_ncreate2(a, b, c, d, e, f, g) #define clntunix_create(a, b, c, d, e) clntunix_ncreate(a, b, c, d, e) #define clnt_dg_create(a, b, c, d, e, f) clnt_dg_ncreate(a, b, c, d, e, f) #define clnt_raw_create(a, b) clnt_raw_ncreate(a, b) /* svc_soc.h */ #define svcraw_create() svcraw_ncreate() #define svcudp_create(a) svcudp_ncreate(a) #define svcudp_bufcreate(a, b, c) svcudp_nbufcreate(a, b, c) #define svcudp6_create(a) svcudp6_ncreate(a) #define svcudp6_bufcreate(a, b, c) svcudp6_nbufcreate(a, b, c) #define svctcp_create(a, b, c) svctcp_ncreate(a, b, c) #define svctcp6_create(a, b, c) svctcp6_ncreate(a, b, c) /* svc.h */ #define svc_create(a, b, c, d) svc_ncreate(a, b, c, d) #define svc_tp_create(a, b, c, d) svc_tp_ncreate(a, b, c, d) #define svc_tli_create(a, b, c, d, e) svc_tli_ncreate(a, b, c, d, e) #define svc_vc_create(a, b, c) svc_vc_ncreate(a, b, c) #define svc_vc_create2(a, b, c, d) svc_vc_ncreate2(a, b, c, d) #define clnt_vc_create_svc(a, b, c, d) clnt_vc_ncreate_svc(a, b, c, d) #define svc_vc_create_clnt(a, b, c, d) svc_vc_ncreate_clnt(a, b, c, d) #define svcunix_create(a, b, c, d) svcunix_ncreate(a, b, c, d) #define svc_dg_create(a, b, c) svc_dg_ncreate(a, b, c) #define svc_fd_create(a, b, c) svc_fd_ncreate(a, b, c) #define svcunixfd_create(a, b, c) svcunixfd_ncreate(a, b, c) #define svc_raw_create() svc_raw_ncreate() #define svc_rdma_create(a, b, c, d) svc_rdma_ncreate(a, b, c, d) /* auth */ #define authunix_create(a, b, c, d, e) authunix_ncreate(a, b, c, d, e) #define authunix_create_default() authunix_ncreate_default() #define authnone_create() authnone_ncreate() #define authdes_create(a, b, c, d) authdes_ncreate(a, b, c, d) #define authdes_seccreate(a, b, c, d) authdes_nseccreate(a, b, c, d) #define authsys_create(c, i1, i2, i3, ip) \ authunix_ncreate((c), (i1), (i2), (i3), (ip)) #define authsys_create_default() authunix_ncreate_default() #define authkerb_seccreate(a, b, c, d, e, f) \ authkerb_nseccreate(a, b, c, d, e, f) #define authkerb_create(a, b, c, d, e, f, g, h, i) \ authkerb_ncreate(a, b, c, d, e, f, g, h, i) #define authgss_create(a, b, c) authgss_ncreate(a, b, c) #define authgss_create_default(a, b, c) authgss_ncreate_default(a, b, c) /* rpc_msg */ #define xdr_callmsg xdr_ncallmsg #define xdr_callhdr xdr_ncallhdr #define xdr_replymsg xdr_nreplymsg #define xdr_accepted_reply xdr_naccepted_reply #define xdr_rejected_reply xdr_nrejected_reply /* xdr */ #define xdr_netobj xdr_nnetobj #define xdrmem_create(a, b, c, d) xdrmem_ncreate(a, b, c, d) #define xdr_free xdr_nfree #endif /* !TIRPC_COMPAT_H */ ntirpc-1.3.1/ntirpc/rpc/types.h000066400000000000000000000155511261345040100164160ustar00rootroot00000000000000/* $NetBSD: types.h,v 1.13 2000/06/13 01:02:44 thorpej Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)types.h 1.18 87/07/24 SMI * from: @(#)types.h 2.3 88/08/15 4.0 RPCSRC * $FreeBSD: src/include/rpc/types.h,v 1.10.6.1 2003/12/18 00:59:50 peter Exp $ */ /* * Rpc additions to */ #ifndef _TIRPC_TYPES_H #define _TIRPC_TYPES_H #ifdef _MSC_VER #include #else #include #endif #include #include #include #if defined(_WIN32) #define __BEGIN_DECLS #define __END_DECLS /* integral types */ #ifndef _MSC_VER #include <_bsd_types.h> /* XXX mingw (defines u_long) */ #endif typedef uint8_t u_char; typedef uint16_t u_int16_t; typedef uint16_t u_short_t; typedef uint16_t u_short; typedef uint32_t u_int; typedef uint32_t u_int32_t; typedef int64_t quad_t; typedef uint64_t u_int64_t; typedef uint64_t u_quad_t; /* misc */ typedef char *caddr_t; typedef uint32_t uid_t; typedef uint32_t gid_t; struct iovec { void *iov_base; size_t iov_len; }; #include #include /* XXX mingw */ #endif typedef int32_t bool_t; typedef int32_t enum_t; typedef u_int32_t rpcprog_t; typedef u_int32_t rpcvers_t; typedef u_int32_t rpcproc_t; typedef u_int32_t rpcprot_t; typedef u_int32_t rpcport_t; typedef int32_t rpc_inline_t; #ifndef NULL #define NULL 0 #endif #define __dontcare__ -1 #define honey_badger __dontcare__ #ifndef FALSE #define FALSE (0) #endif #ifndef TRUE #define TRUE (1) #endif /* * Package params support */ #define TIRPC_GET_MALLOC 1 #define TIRPC_SET_MALLOC 2 #define TIRPC_GET_MEM_FREE 3 #define TIRPC_SET_MEM_FREE 4 #define TIRPC_GET_FREE 5 #define TIRPC_SET_FREE 6 #define TIRPC_GET_FLAGS 7 #define TIRPC_SET_FLAGS 8 #define TIRPC_GET_DEBUG_FLAGS 9 #define TIRPC_SET_DEBUG_FLAGS 10 #define TIRPC_GET_WARNX 11 #define TIRPC_SET_WARNX 12 /* * Debug flags support */ #define TIRPC_FLAG_NONE 0x0000000 #define TIRPC_DEBUG_FLAG_NONE 0x0000000 #define TIRPC_DEBUG_FLAG_ERROR 0x0000001 #define TIRPC_DEBUG_FLAG_EVENT 0x0000002 #define TIRPC_DEBUG_FLAG_REFCNT 0x0000004 #define TIRPC_DEBUG_FLAG_LOCK 0x0000008 #define TIRPC_DEBUG_FLAG_MEM 0x0000010 #define TIRPC_DEBUG_FLAG_RBTREE 0x0000020 #define TIRPC_DEBUG_FLAG_RPCSEC_GSS 0x0000040 #define TIRPC_DEBUG_FLAG_AUTH 0x0000080 #define TIRPC_DEBUG_FLAG_CLNT_BCAST 0x0000100 #define TIRPC_DEBUG_FLAG_CLNT_DG 0x0000200 #define TIRPC_DEBUG_FLAG_CLNT_GEN 0x0000400 #define TIRPC_DEBUG_FLAG_CLNT_RAW 0x0000800 #define TIRPC_DEBUG_FLAG_CLNT_RDMA 0x0001000 #define TIRPC_DEBUG_FLAG_CLNT_SCTP 0x0002000 #define TIRPC_DEBUG_FLAG_CLNT_VC 0x0004000 #define TIRPC_DEBUG_FLAG_SVC 0x0008000 #define TIRPC_DEBUG_FLAG_SVC_DG 0x0010000 #define TIRPC_DEBUG_FLAG_SVC_RQST 0x0020000 #define TIRPC_DEBUG_FLAG_SVC_XPRT 0x0040000 #define TIRPC_DEBUG_FLAG_SVC_RDMA 0x0080000 #define TIRPC_DEBUG_FLAG_SVC_SCTP 0x0100000 #define TIRPC_DEBUG_FLAG_SVC_VC 0x0200000 #define TIRPC_DEBUG_FLAG_XDRREC 0x0400000 #define TIRPC_DEBUG_FLAG_XDR 0x0800000 #define TIRPC_DEBUG_FLAG_RPC_CTX 0x1000000 #define TIRPC_DEBUG_FLAG_RPC_CACHE 0x2000000 #define TIRPC_DEBUG_FLAG_RPC_MSG 0x4000000 #define TIRPC_DEBUG_FLAG_RPC_RDMA 0x8000000 /* or symbolic names for default */ #define TIRPC_DEBUG_FLAG_DEFAULT \ (TIRPC_DEBUG_FLAG_ERROR | TIRPC_DEBUG_FLAG_EVENT) typedef void *(*mem_alloc_t) (size_t); typedef void (*mem_free_t) (void *, size_t); typedef void (*std_free_t) (void *); typedef void (*warnx_t) (const char *fmt, ...); /* * Package params support */ typedef struct tirpc_pkg_params { u_int flags; u_int debug_flags; warnx_t warnx; } tirpc_pkg_params; extern tirpc_pkg_params __ntirpc_pkg_params; #include #define __warnx(flags, ...) \ do { \ if (__ntirpc_pkg_params.debug_flags & (flags)) { \ __ntirpc_pkg_params.warnx(__VA_ARGS__); \ } \ } while (0) #define __debug_flag(flags) (__ntirpc_pkg_params.debug_flags & (flags)) #define mem_alloc(size) malloc((size)) #define mem_zalloc(size) calloc(1, (size)) #define mem_alloc_aligned(size, align) aligned_alloc((align), (size)) #define mem_free(ptr, size) free(ptr) #ifndef _MSC_VER #include #include #endif #include #include /* * The netbuf structure is defined here, because FreeBSD / NetBSD only use * it inside the RPC code. It's in on SVR4, but it would be confusing * to have an xti.h, since FreeBSD / NetBSD do not support XTI/TLI. */ /* * The netbuf structure is used for transport-independent address storage. */ struct netbuf { unsigned int maxlen; unsigned int len; void *buf; }; struct rpc_address { struct netbuf nb; struct sockaddr_storage ss; /* address buffer */ }; /* * The format of the addres and options arguments of the XTI t_bind call. * Only provided for compatibility, it should not be used. */ struct t_bind { struct netbuf addr; unsigned int qlen; }; /* * Internal library and rpcbind use. This is not an exported interface, do * not use. */ struct __rpc_sockinfo { int si_af; int si_proto; int si_socktype; int si_alen; }; #endif /* _TIRPC_TYPES_H */ ntirpc-1.3.1/ntirpc/rpc/work_pool.h000066400000000000000000000047401261345040100172630ustar00rootroot00000000000000/* * Copyright (c) 2013-2015 CohortFS, LLC. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /** * @file work_pool.h * @author William Allen Simpson * @brief Pthreads-based work queue package * * @section DESCRIPTION * * This provides simple work queues using pthreads and TAILQ primitives. * * @note Loosely based upon previous thrdpool by * Matt Benjamin */ #ifndef WORK_POOL_H #define WORK_POOL_H #include struct work_pool_entry; typedef void (*work_pool_fun_t) (struct work_pool_entry *); struct work_pool_entry { struct poolq_entry pqe; /*** 1st ***/ work_pool_fun_t fun; void *arg; }; struct work_pool_params { int32_t thrd_max; int32_t thrd_min; }; struct work_pool { struct poolq_head pqh; char *name; pthread_attr_t attr; struct work_pool_params params; uint32_t n_threads; }; struct work_pool_thread { struct poolq_entry pqe; /*** 1st ***/ pthread_cond_t pqcond; struct work_pool *pool; struct work_pool_entry *work; pthread_t id; uint32_t worker_index; }; int work_pool_init(struct work_pool *, const char *, struct work_pool_params *); int work_pool_submit(struct work_pool *, struct work_pool_entry *); int work_pool_shutdown(struct work_pool *); #endif /* WORK_POOL_H */ ntirpc-1.3.1/ntirpc/rpc/xdr.h000066400000000000000000000512771261345040100160540ustar00rootroot00000000000000/* $NetBSD: xdr.h,v 1.19 2000/07/17 05:00:45 matt Exp $ */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * from: @(#)xdr.h 1.19 87/04/22 SMI * from: @(#)xdr.h 2.2 88/07/29 4.0 RPCSRC * $FreeBSD: src/include/rpc/xdr.h,v 1.23 2003/03/07 13:19:40 nectar Exp $ */ /* * xdr.h, External Data Representation Serialization Routines. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #ifndef _TIRPC_XDR_H #define _TIRPC_XDR_H #include #include #include #if !defined(_WIN32) #include #endif #include #include /* * XDR provides a conventional way for converting between C data * types and an external bit-string representation. Library supplied * routines provide for the conversion on built-in C data types. These * routines and utility routines defined here are used to help implement * a type encode/decode routine for each user-defined type. * * Each data type provides a single procedure which takes two arguments: * * bool * xdrproc(xdrs, argresp) * XDR *xdrs; * *argresp; * * xdrs is an instance of a XDR handle, to which or from which the data * type is to be converted. argresp is a pointer to the structure to be * converted. The XDR handle contains an operation field which indicates * which of the operations (ENCODE, DECODE * or FREE) is to be performed. * * XDR_DECODE may allocate space if the pointer argresp is null. This * data can be freed with the XDR_FREE operation. * * We write only one procedure per data type to make it easy * to keep the encode and decode procedures for a data type consistent. * In many cases the same code performs all operations on a user defined type, * because all the hard work is done in the component type routines. * decode as a series of calls on the nested data types. */ /* * Xdr operations. XDR_ENCODE causes the type to be encoded into the * stream. XDR_DECODE causes the type to be extracted from the stream. * XDR_FREE can be used to release the space allocated by an XDR_DECODE * request. */ enum xdr_op { XDR_ENCODE = 0, XDR_DECODE = 1, XDR_FREE = 2 }; /* * This is the number of bytes per unit of external data. */ #define BYTES_PER_XDR_UNIT (4) /* Taken verbatim from a system xdr.h, which carries a BSD-style * license (Matt) */ /* * This only works if the above is a power of 2. But it's defined to be * 4 by the appropriate RFCs. So it will work. And it's normally quicker * than the old routine. */ #if 1 #define RNDUP(x) (((x) + BYTES_PER_XDR_UNIT - 1) & ~(BYTES_PER_XDR_UNIT - 1)) #else /* this is the old routine */ #define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) / BYTES_PER_XDR_UNIT) \ * BYTES_PER_XDR_UNIT) #endif /* XDR buffer vector descriptors */ typedef struct xdr_vio { void *vio_base; void *vio_head; /* minimum vio_tail (header offset) */ void *vio_tail; void *vio_wrap; /* maximum vio_tail */ } xdr_vio; /* vio_wrap >= vio_tail >= vio_head >= vio_base */ #define UIO_FLAG_NONE 0x0000 #define UIO_FLAG_GIFT 0x0001 #define UIO_FLAG_FREE 0x0002 #define UIO_FLAG_BUFQ 0x0004 #define UIO_FLAG_REALLOC 0x0008 struct xdr_uio; typedef void (*xdr_uio_release)(struct xdr_uio *, u_int); typedef struct xdr_uio { struct xdr_uio *uio_refer; xdr_uio_release uio_release; void *uio_p1; void *uio_p2; void *uio_u1; void *uio_u2; size_t uio_count; /* count of entries in vio array, * 0: not allocated */ u_int uio_flags; int32_t uio_references; xdr_vio uio_vio[0]; /* appended vectors */ } xdr_uio; /* Op flags */ #define XDR_PUTBUFS_FLAG_NONE 0x0000 #define XDR_PUTBUFS_FLAG_RDNLY 0x0001 #define XDR_FLAG_NONE 0x0000 #define XDR_FLAG_CKSUM 0x0001 #define XDR_FLAG_VIO 0x0002 /* * The XDR handle. * Contains operation which is being applied to the stream, * an operations vector for the particular implementation (e.g. see xdr_mem.c), * and two private fields for the use of the particular implementation. * XXX: w/64-bit pointers, u_int not enough! */ typedef struct rpc_xdr { enum xdr_op x_op; /* operation; fast additional param */ const struct xdr_ops { /* get a long from underlying stream */ bool (*x_getlong)(struct rpc_xdr *, long *); /* put a long to " */ bool (*x_putlong)(struct rpc_xdr *, const long *); /* get some bytes from " */ bool (*x_getbytes)(struct rpc_xdr *, char *, u_int); /* put some bytes to " */ bool (*x_putbytes)(struct rpc_xdr *, const char *, u_int); /* returns bytes off from beginning */ u_int (*x_getpostn)(struct rpc_xdr *); /* lets you reposition the stream */ bool (*x_setpostn)(struct rpc_xdr *, u_int); /* buf quick ptr to buffered data */ int32_t *(*x_inline)(struct rpc_xdr *, u_int); /* free private resources of this xdr_stream */ void (*x_destroy)(struct rpc_xdr *); bool (*x_control)(struct rpc_xdr *, int, void *); /* new vector and refcounted interfaces */ bool (*x_getbufs)(struct rpc_xdr *, xdr_uio *, u_int); bool (*x_putbufs)(struct rpc_xdr *, xdr_uio *, u_int); } *x_ops; void *x_public; /* users' data */ void *x_private; /* pointer to private data */ void *x_lib[2]; /* RPC library private */ void *x_base; /* private used for position info */ struct xdr_vio x_v; /* private buffer vector */ u_int x_handy; /* extra private word */ u_int x_flags; /* shared flags */ } XDR; #define XDR_VIO(x) ((xdr_vio *)((x)->x_base)) static inline size_t xdr_size_inline(XDR *xdrs) { return ((uintptr_t)xdrs->x_v.vio_wrap - (uintptr_t)xdrs->x_private); } static inline size_t xdr_tail_inline(XDR *xdrs) { return ((uintptr_t)xdrs->x_v.vio_tail - (uintptr_t)xdrs->x_private); } static inline void xdr_tail_update(XDR *xdrs) { if ((uintptr_t)xdrs->x_v.vio_tail < (uintptr_t)xdrs->x_private) { xdrs->x_v.vio_tail = xdrs->x_private; XDR_VIO(xdrs)->vio_tail = xdrs->x_private; } } /* * A xdrproc_t exists for each data type which is to be encoded or decoded. * * The second argument to the xdrproc_t is a pointer to an opaque pointer. * The opaque pointer generally points to a structure of the data type * to be decoded. If this pointer is 0, then the type routines should * allocate dynamic storage of the appropriate size and return it. */ #ifdef _KERNEL typedef bool(*xdrproc_t) (XDR *, void *, u_int); #else /* * XXX can't actually prototype it, because some take three args!!! */ typedef bool(*xdrproc_t) (XDR *, ...); #endif /* * Operations defined on a XDR handle * * XDR *xdrs; * long *longp; * char * addr; * u_int len; * u_int pos; */ static inline bool xdr_getlong(XDR *xdrs, long *lp) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_tail)) { return (*xdrs->x_ops->x_getlong)(xdrs, lp); } *lp = (long)ntohl(*((uint32_t *) (xdrs->x_private))); xdrs->x_private = future; return (true); } static inline bool xdr_putlong(XDR *xdrs, const long *lp) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_wrap)) { return (*xdrs->x_ops->x_putlong)(xdrs, lp); } *((int32_t *) (xdrs->x_private)) = (int32_t) htonl((int32_t) (*lp)); xdrs->x_private = future; return (true); } #define XDR_GETLONG(xdrs, lp) xdr_getlong(xdrs, lp) #define XDR_PUTLONG(xdrs, lp) xdr_putlong(xdrs, lp) #define XDR_GETBYTES(xdrs, addr, len) \ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) #define xdr_getbytes(xdrs, addr, len) \ (*(xdrs)->x_ops->x_getbytes)(xdrs, addr, len) #define XDR_PUTBYTES(xdrs, addr, len) \ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) #define xdr_putbytes(xdrs, addr, len) \ (*(xdrs)->x_ops->x_putbytes)(xdrs, addr, len) #define XDR_GETBUFS(xdrs, uio, len, flags) \ (*(xdrs)->x_ops->x_getbufs)(xdrs, uio, len, flags) #define xdr_getbufs(xdrs, uio, len, flags) \ (*(xdrs)->x_ops->x_getbufs)(xdrs, uio, len, flags) #define XDR_PUTBUFS(xdrs, uio, flags) \ (*(xdrs)->x_ops->x_putbufs)(xdrs, uio, flags) #define xdr_putbufs(xdrs, uio, flags) \ (*(xdrs)->x_ops->x_putbufs)(xdrs, uio, flags) #define XDR_GETPOS(xdrs) \ (*(xdrs)->x_ops->x_getpostn)(xdrs) #define xdr_getpos(xdrs) \ (*(xdrs)->x_ops->x_getpostn)(xdrs) #define XDR_SETPOS(xdrs, pos) \ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) #define xdr_setpos(xdrs, pos) \ (*(xdrs)->x_ops->x_setpostn)(xdrs, pos) #define XDR_INLINE(xdrs, len) \ (*(xdrs)->x_ops->x_inline)(xdrs, len) #define xdr_inline(xdrs, len) \ (*(xdrs)->x_ops->x_inline)(xdrs, len) #define XDR_DESTROY(xdrs) \ if ((xdrs)->x_ops->x_destroy) \ (*(xdrs)->x_ops->x_destroy)(xdrs) #define xdr_destroy(xdrs) \ if ((xdrs)->x_ops->x_destroy) \ (*(xdrs)->x_ops->x_destroy)(xdrs) #define XDR_CONTROL(xdrs, req, op) \ if ((xdrs)->x_ops->x_control) \ (*(xdrs)->x_ops->x_control)(xdrs, req, op) #define xdr_control(xdrs, req, op) XDR_CONTROL(xdrs, req, op) /* * Solaris strips the '_t' from these types -- not sure why. * But, let's be compatible. */ #define xdr_rpcvers(xdrs, versp) xdr_u_int32(xdrs, versp) #define xdr_rpcprog(xdrs, progp) xdr_u_int32(xdrs, progp) #define xdr_rpcproc(xdrs, procp) xdr_u_int32(xdrs, procp) #define xdr_rpcprot(xdrs, protp) xdr_u_int32(xdrs, protp) #define xdr_rpcport(xdrs, portp) xdr_u_int32(xdrs, portp) /* * Support struct for discriminated unions. * You create an array of xdrdiscrim structures, terminated with * an entry with a null procedure pointer. The xdr_union routine gets * the discriminant value and then searches the array of structures * for a matching value. If a match is found the associated xdr routine * is called to handle that part of the union. If there is * no match, then a default routine may be called. * If there is no match and no default routine it is an error. */ #define NULL_xdrproc_t ((xdrproc_t)0) struct xdr_discrim { int value; xdrproc_t proc; }; /* * In-line routines for fast encode/decode of primitive data types. * Caveat emptor: these use single memory cycles to get the * data from the underlying buffer, and will fail to operate * properly where the data is not aligned. The standard way to use these * is to say: * if ((buf = XDR_INLINE(xdrs, count)) == NULL) * return (false); * <<< macro calls >>> * where ``count'' is the number of bytes of data occupied * by the primitive data types. * * N.B. and frozen for all time: each data type here uses 4 bytes * of external representation. */ #define IXDR_GET_INT32(buf) ((int32_t)ntohl((u_int32_t)*(buf)++)) #define IXDR_PUT_INT32(buf, v) (*(buf)++ = (int32_t)htonl((u_int32_t)v)) #define IXDR_GET_U_INT32(buf) ((u_int32_t)IXDR_GET_INT32(buf)) #define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_INT32((buf), ((int32_t)(v))) #define IXDR_GET_LONG(buf) ((long)ntohl((u_int32_t)*(buf)++)) #define IXDR_PUT_LONG(buf, v) (*(buf)++ = (int32_t)htonl((u_int32_t)v)) #define IXDR_GET_BOOL(buf) ((bool)IXDR_GET_LONG(buf)) #define IXDR_GET_ENUM(buf, t) ((t)IXDR_GET_LONG(buf)) #define IXDR_GET_U_LONG(buf) ((u_long)IXDR_GET_LONG(buf)) #define IXDR_GET_SHORT(buf) ((short)IXDR_GET_LONG(buf)) #define IXDR_GET_U_SHORT(buf) ((u_short)IXDR_GET_LONG(buf)) #define IXDR_PUT_BOOL(buf, v) IXDR_PUT_LONG((buf), (v)) #define IXDR_PUT_ENUM(buf, v) IXDR_PUT_LONG((buf), (v)) #define IXDR_PUT_U_LONG(buf, v) IXDR_PUT_LONG((buf), (v)) #define IXDR_PUT_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) #define IXDR_PUT_U_SHORT(buf, v) IXDR_PUT_LONG((buf), (v)) /* * In-line routines for vector encode/decode of primitive data types. * Intermediate speed, avoids function calls in most cases, at the expense of * checking the remaining space available for each item. * * Caveat emptor: these use single memory cycles to get the * data from the underlying buffer, and will fail to operate * properly where the data is not aligned. * * if (!FUNCTION(xdrs, &variable)) { * print(warning); * return (false); * } * * N.B. and frozen for all time: each data type here uses 4 bytes * of external representation. */ static inline bool xdr_getuint32(XDR *xdrs, uint32_t *ip) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_tail)) { long l; if (!(*xdrs->x_ops->x_getlong)(xdrs, &l)) return (false); *ip = (uint32_t) l; return (true); } *ip = ntohl(*((uint32_t *) (xdrs->x_private))); xdrs->x_private = future; return (true); } static inline bool xdr_putuint32(XDR *xdrs, uint32_t *ip) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_wrap)) { long l = (long)*ip; return (*xdrs->x_ops->x_putlong)(xdrs, &l); } *((int32_t *) (xdrs->x_private)) = htonl(*ip); xdrs->x_private = future; return (true); } #define XDR_GETUINT32(xdrs, uint32p) xdr_getuint32(xdrs, uint32p) #define XDR_PUTUINT32(xdrs, uint32p) xdr_putuint32(xdrs, uint32p) static inline bool xdr_getint32(XDR *xdrs, int32_t *ip) { return xdr_getuint32(xdrs, (uint32_t *)ip); } static inline bool xdr_putint32(XDR *xdrs, int32_t *ip) { return xdr_putuint32(xdrs, (uint32_t *)ip); } #define XDR_GETINT32(xdrs, int32p) xdr_getint32(xdrs, int32p) #define XDR_PUTINT32(xdrs, int32p) xdr_putint32(xdrs, int32p) static inline bool xdr_getuint16(XDR *xdrs, uint16_t *ip) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_tail)) { long l; if (!(*xdrs->x_ops->x_getlong)(xdrs, &l)) return (false); *ip = (uint16_t) l; return (true); } *ip = (uint16_t)ntohl(*((uint32_t *) (xdrs->x_private))); xdrs->x_private = future; return (true); } static inline bool xdr_putuint16(XDR *xdrs, uint32_t uint16v) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_wrap)) { long l = (long)uint16v; return (*xdrs->x_ops->x_putlong)(xdrs, &l); } *((int32_t *) (xdrs->x_private)) = htonl(uint16v); xdrs->x_private = future; return (true); } #define XDR_GETUINT16(xdrs, uint16p) xdr_getuint16(xdrs, uint16p) #define XDR_PUTUINT16(xdrs, uint16v) xdr_putuint16(xdrs, uint16v) static inline bool xdr_getint16(XDR *xdrs, int16_t *ip) { return xdr_getuint16(xdrs, (uint16_t *)ip); } /* extend sign before storage */ static inline bool xdr_putint16(XDR *xdrs, int32_t int16v) { return xdr_putuint16(xdrs, int16v); } #define XDR_GETINT16(xdrs, int16p) xdr_getint16(xdrs, int16p) #define XDR_PUTINT16(xdrs, int16v) xdr_putint16(xdrs, int16v) static inline bool xdr_getuint8(XDR *xdrs, uint8_t *ip) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_tail)) { long l; if (!(*xdrs->x_ops->x_getlong)(xdrs, &l)) return (false); *ip = (uint8_t) l; return (true); } *ip = (uint8_t)ntohl(*((uint32_t *) (xdrs->x_private))); xdrs->x_private = future; return (true); } static inline bool xdr_putuint8(XDR *xdrs, uint32_t uint8v) { void *future; if (!(xdrs->x_flags & XDR_FLAG_VIO) || unlikely((future = xdrs->x_private + sizeof(uint32_t)) > xdrs->x_v.vio_wrap)) { long l = (long)uint8v; return (*xdrs->x_ops->x_putlong)(xdrs, &l); } *((int32_t *) (xdrs->x_private)) = htonl(uint8v); xdrs->x_private = future; return (true); } #define XDR_GETUINT8(xdrs, uint8p) xdr_getuint8(xdrs, uint8p) #define XDR_PUTUINT8(xdrs, uint8v) xdr_putuint8(xdrs, uint8v) static inline bool xdr_getint8(XDR *xdrs, int8_t *ip) { return xdr_getuint8(xdrs, (uint8_t *)ip); } /* extend sign before storage */ static inline bool xdr_putint8(XDR *xdrs, int32_t int8v) { return xdr_putuint8(xdrs, int8v); } #define XDR_GETINT8(xdrs, int8p) xdr_getint8(xdrs, int8p) #define XDR_PUTINT8(xdrs, int8v) xdr_putint8(xdrs, int8v) static inline bool xdr_getenum(XDR *xdrs, enum_t *ip) { return xdr_getuint32(xdrs, (uint32_t *)ip); } static inline bool xdr_putenum(XDR *xdrs, enum_t enumv) { return xdr_putuint16(xdrs, (uint32_t)enumv); } #define XDR_GETENUM(xdrs, enump) xdr_getenum(xdrs, enump) #define XDR_PUTENUM(xdrs, enumv) xdr_putenum(xdrs, enumv) static inline bool xdr_getbool(XDR *xdrs, bool_t *ip) { return xdr_getuint32(xdrs, (uint32_t *)ip); } static inline bool xdr_putbool(XDR *xdrs, bool_t boolv) { return xdr_putuint16(xdrs, (uint32_t)boolv); } #define XDR_GETBOOL(xdrs, boolp) xdr_getbool(xdrs, boolp) #define XDR_PUTBOOL(xdrs, boolv) xdr_putbool(xdrs, boolv) /* * These are the "generic" xdr routines. */ __BEGIN_DECLS extern XDR xdr_free_null_stream; extern bool xdr_void(void); extern bool xdr_int(XDR *, int *); extern bool xdr_u_int(XDR *, u_int *); extern bool xdr_long(XDR *, long *); extern bool xdr_u_long(XDR *, u_long *); extern bool xdr_short(XDR *, short *); extern bool xdr_u_short(XDR *, u_short *); extern bool xdr_int16_t(XDR *, int16_t *); extern bool xdr_u_int16_t(XDR *, u_int16_t *); extern bool xdr_int32_t(XDR *, int32_t *); extern bool xdr_u_int32_t(XDR *, u_int32_t *); extern bool xdr_uint32_t(XDR *, u_int32_t *); extern bool xdr_int64_t(XDR *, int64_t *); extern bool xdr_u_int64_t(XDR *, u_int64_t *); extern bool xdr_uint64_t(XDR *, u_int64_t *); extern bool xdr_bool(XDR *, bool_t *); extern bool xdr_enum(XDR *, enum_t *); extern bool xdr_array(XDR *, char **, u_int *, u_int, u_int, xdrproc_t); extern bool xdr_bytes(XDR *, char **, u_int *, u_int); extern bool xdr_opaque(XDR *, char *, u_int); extern bool xdr_string(XDR *, char **, u_int); extern bool xdr_union(XDR *, enum_t *, char *, const struct xdr_discrim *, xdrproc_t); extern bool xdr_char(XDR *, char *); extern bool xdr_u_char(XDR *, u_char *); extern bool xdr_vector(XDR *, char *, u_int, u_int, xdrproc_t); extern bool xdr_float(XDR *, float *); extern bool xdr_double(XDR *, double *); extern bool xdr_quadruple(XDR *, long double *); extern bool xdr_reference(XDR *, char **, u_int, xdrproc_t); extern bool xdr_pointer(XDR *, char **, u_int, xdrproc_t); extern bool xdr_wrapstring(XDR *, char **); extern bool xdr_hyper(XDR *, quad_t *); extern bool xdr_u_hyper(XDR *, u_quad_t *); extern bool xdr_longlong_t(XDR *, quad_t *); extern bool xdr_u_longlong_t(XDR *, u_quad_t *); #define xdr_quad_t xdr_int64_t #define xdr_uquad_t xdr_uint64_t __END_DECLS /* * Free a data structure using XDR * Not a filter, but a convenient utility nonetheless */ static inline bool xdr_nfree(xdrproc_t proc, void *objp) { return (*proc) (&xdr_free_null_stream, objp); } /* * Common opaque bytes objects used by many rpc protocols; * declared here due to commonality. */ #define MAX_NETOBJ_SZ 1024 struct netobj { u_int n_len; char *n_bytes; }; typedef struct netobj netobj; extern bool xdr_nnetobj(XDR *, struct netobj *); /* * These are the public routines for the various implementations of * xdr streams. */ __BEGIN_DECLS /* XDR using memory buffers */ extern void xdrmem_ncreate(XDR *, char *, u_int, enum xdr_op); /* intrinsic checksum (be careful) */ extern uint64_t xdrmem_cksum(XDR *, u_int); /* XDR using stdio library */ extern void xdrstdio_create(XDR *, FILE *, enum xdr_op); /* XDR pseudo records for tcp */ extern void xdrrec_create(XDR *, u_int, u_int, void *, int (*)(XDR *, void *, void *, int), int (*)(XDR *, void *, void *, int)); /* make end of xdr record */ extern bool xdrrec_endofrecord(XDR *, bool); /* move to beginning of next record */ extern bool xdrrec_skiprecord(XDR *); /* true if no more input */ extern bool xdrrec_eof(XDR *); __END_DECLS /* For backward compatibility */ #include #endif /* !_TIRPC_XDR_H */ ntirpc-1.3.1/ntirpc/rpc/xdr_inline.h000066400000000000000000000422171261345040100174040ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include /* * xdr.c, Generic XDR routines implementation. * * Copyright (C) 1986, Sun Microsystems, Inc. * * These are the "generic" xdr routines used to serialize and de-serialize * most common data items. See xdr.h for more info on the interface to * xdr. */ #ifndef _TIRPC_INLINE_XDR_H #define _TIRPC_INLINE_XDR_H #if !defined(_WIN32) #include #endif #include #include #include #include #include /* * constants specific to the xdr "protocol" */ #define XDR_FALSE ((long) 0) #define XDR_TRUE ((long) 1) #define LASTUNSIGNED ((u_int) 0-1) /* * Free a data structure using XDR * Not a filter, but a convenient utility nonetheless */ static inline void inline_xdr_free(xdrproc_t proc, void *objp) { XDR x; x.x_op = XDR_FREE; (*proc) (&x, objp); } /* * XDR nothing */ static inline bool inline_xdr_void(void) { return (true); } /* * XDR integers */ static inline bool inline_xdr_int(XDR *xdrs, int *ip) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*ip; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *ip = (int)l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned integers */ static inline bool inline_xdr_u_int(XDR *xdrs, u_int *up) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *up; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *up = (u_int) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR long integers * same as xdr_u_long - open coded to save a proc call! */ static inline bool inline_xdr_long(XDR *xdrs, long *lp) { switch (xdrs->x_op) { case XDR_ENCODE: return (XDR_PUTLONG(xdrs, lp)); case XDR_DECODE: return (XDR_GETLONG(xdrs, lp)); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned long integers * same as xdr_long - open coded to save a proc call! */ static inline bool inline_xdr_u_long(XDR *xdrs, u_long *ulp) { switch (xdrs->x_op) { case XDR_ENCODE: return (XDR_PUTLONG(xdrs, (long *)ulp)); case XDR_DECODE: return (XDR_GETLONG(xdrs, (long *)ulp)); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR 32-bit integers * same as xdr_u_int32_t - open coded to save a proc call! */ static inline bool inline_xdr_int32_t(XDR *xdrs, int32_t *int32_p) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*int32_p; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *int32_p = (int32_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 32-bit integers * same as xdr_int32_t - open coded to save a proc call! */ static inline bool inline_xdr_u_int32_t(XDR *xdrs, u_int32_t *u_int32_p) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *u_int32_p; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *u_int32_p = (u_int32_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR short integers */ static inline bool inline_xdr_short(XDR *xdrs, short *sp) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*sp; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *sp = (short)l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned short integers */ static inline bool inline_xdr_u_short(XDR *xdrs, u_short *usp) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *usp; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *usp = (u_short) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR 16-bit integers */ static inline bool inline_xdr_int16_t(XDR *xdrs, int16_t *int16_p) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*int16_p; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *int16_p = (int16_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 16-bit integers */ static inline bool inline_xdr_u_int16_t(XDR *xdrs, u_int16_t *u_int16_p) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *u_int16_p; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *u_int16_p = (u_int16_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR a char */ static inline bool inline_xdr_char(XDR *xdrs, char *cp) { int i; i = (*cp); if (!inline_xdr_int(xdrs, &i)) return (false); *cp = i; return (true); } /* * XDR an unsigned char */ static inline bool inline_xdr_u_char(XDR *xdrs, u_char *cp) { u_int u; u = (*cp); if (!inline_xdr_u_int(xdrs, &u)) return (false); *cp = u; return (true); } /* * XDR booleans */ static inline bool inline_xdr_bool(XDR *xdrs, bool_t *bp) { long lb; switch (xdrs->x_op) { case XDR_ENCODE: lb = *bp ? XDR_TRUE : XDR_FALSE; return (XDR_PUTLONG(xdrs, &lb)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &lb)) return (false); *bp = (lb == XDR_FALSE) ? false : true; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR enumerations */ static inline bool inline_xdr_enum(XDR *xdrs, enum_t *ep) { enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ /* * enums are treated as ints */ /* LINTED */ if (sizeof(enum sizecheck) == sizeof(long)) { return (inline_xdr_long(xdrs, (long *)(void *)ep)); } else /* LINTED */ if (sizeof(enum sizecheck) == sizeof(int)) { return (inline_xdr_int(xdrs, (int *)(void *)ep)); } else /* LINTED */ if (sizeof(enum sizecheck) == sizeof(short)) { return (inline_xdr_short(xdrs, (short *)(void *)ep)); } else { return (false); } } /* * decode opaque data * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ static inline bool inline_xdr_getopaque(XDR *xdrs, caddr_t cp, u_int cnt) { u_int rndup; /* * if no data we are done */ if (cnt == 0) return (true); /* * XDR_INLINE is just as likely to do a function call, * so don't bother with it here. */ if (!XDR_GETBYTES(xdrs, cp, cnt)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR opaque", __func__, __LINE__); return (false); } /* * round byte count to full xdr units */ rndup = cnt & (BYTES_PER_XDR_UNIT - 1); if (rndup > 0) { uint32_t crud; if (!XDR_GETBYTES(xdrs, (caddr_t) &crud, BYTES_PER_XDR_UNIT - rndup)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR crud", __func__, __LINE__); return (false); } } return (true); } /* * encode opaque data * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ static inline bool inline_xdr_putopaque(XDR *xdrs, caddr_t cp, u_int cnt) { u_int rndup; /* * if no data we are done */ if (cnt == 0) return (true); /* * XDR_INLINE is just as likely to do a function call, * so don't bother with it here. */ if (!XDR_PUTBYTES(xdrs, cp, cnt)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR opaque", __func__, __LINE__); return (false); } /* * round byte count to full xdr units */ rndup = cnt & (BYTES_PER_XDR_UNIT - 1); if (rndup > 0) { uint32_t zero = 0; if (!XDR_PUTBYTES(xdrs, (caddr_t) &zero, BYTES_PER_XDR_UNIT - rndup)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR zero", __func__, __LINE__); return (false); } } return (true); } /* * XDR opaque data * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ static inline bool inline_xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt) { if (xdrs->x_op == XDR_DECODE) return (inline_xdr_getopaque(xdrs, cp, cnt)); if (xdrs->x_op == XDR_ENCODE) return (inline_xdr_putopaque(xdrs, cp, cnt)); if (xdrs->x_op == XDR_FREE) return (true); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR xdrs->x_op (%u)", __func__, __LINE__, xdrs->x_op); return (false); } /* * XDR counted bytes * *cpp is a pointer to the bytes, *sizep is the count. * If *cpp is NULL maxsize bytes are allocated */ static inline bool inline_xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) { char *sp = *cpp; /* sp is the actual string pointer */ u_int nodesize; /* * first deal with the length since xdr bytes are counted */ if (!inline_xdr_u_int(xdrs, sizep)) return (false); nodesize = *sizep; if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) return (false); /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (nodesize == 0) return (true); if (sp == NULL) *cpp = sp = (char *)mem_alloc(nodesize); if (sp == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDR, "xdr_bytes: out of memory"); return (false); } return (inline_xdr_getopaque(xdrs, sp, nodesize)); case XDR_ENCODE: return (inline_xdr_putopaque(xdrs, sp, nodesize)); case XDR_FREE: if (sp != NULL) { mem_free(sp, nodesize); *cpp = NULL; } return (true); } /* NOTREACHED */ return (false); } /* * Implemented here due to commonality of the object. */ static inline bool inline_xdr_netobj(XDR *xdrs, struct netobj *np) { return (inline_xdr_bytes (xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); } /* * XDR a descriminated union * Support routine for discriminated unions. * You create an array of xdrdiscrim structures, terminated with * an entry with a null procedure pointer. The routine gets * the discriminant value and then searches the array of xdrdiscrims * looking for that value. It calls the procedure given in the xdrdiscrim * to handle the discriminant. If there is no specific routine a default * routine may be called. * If there is no specific or default routine an error is returned. */ static inline bool inline_xdr_union(XDR *xdrs, enum_t *dscmp, /* enum to decide which arm to work on */ char *unp, /* the union itself */ const struct xdr_discrim *choices, /* [value, xdr proc] for each arm */ xdrproc_t dfault) { /* default xdr routine */ enum_t dscm; /* * we deal with the discriminator; it's an enum */ if (!inline_xdr_enum(xdrs, dscmp)) return (false); dscm = *dscmp; /* * search choices for a value that matches the discriminator. * if we find one, execute the xdr routine for that value. */ for (; choices->proc != NULL_xdrproc_t; choices++) { if (choices->value == dscm) return ((*(choices->proc)) (xdrs, unp)); } /* * no match - execute the default xdr routine if there is one */ return ((dfault == NULL_xdrproc_t) ? false : (*dfault) (xdrs, unp)); } /* * Non-portable xdr primitives. * Care should be taken when moving these routines to new architectures. */ /* * XDR null terminated ASCII strings * xdr_string deals with "C strings" - arrays of bytes that are * terminated by a NULL character. The parameter cpp references a * pointer to storage; If the pointer is null, then the necessary * storage is allocated. The last parameter is the max allowed length * of the string as specified by a protocol. */ static inline bool inline_xdr_string(XDR *xdrs, char **cpp, u_int maxsize) { char *sp = *cpp; /* sp is the actual string pointer */ u_int size = 0; /* XXX remove warning */ u_int nodesize; /* * first deal with the length since xdr strings are counted-strings */ switch (xdrs->x_op) { case XDR_FREE: if (sp == NULL) return (true); /* already free */ /* FALLTHROUGH */ case XDR_ENCODE: if (sp == NULL) return false; size = strlen(sp); break; case XDR_DECODE: break; } if (!inline_xdr_u_int(xdrs, &size)) return (false); if (size > maxsize) return (false); nodesize = size + 1; if (nodesize == 0) { /* This means an overflow. It a bug in the caller which * provided a too large maxsize but nevertheless catch it * here. */ return false; } /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (sp == NULL) *cpp = sp = (char *)mem_alloc(nodesize); if (sp == NULL) { warnx("xdr_string: out of memory"); return (false); } sp[size] = 0; return (inline_xdr_getopaque(xdrs, sp, size)); case XDR_ENCODE: return (inline_xdr_putopaque(xdrs, sp, size)); case XDR_FREE: mem_free(sp, nodesize); *cpp = NULL; return (true); } /* NOTREACHED */ return (false); } /* * Wrapper for xdr_string that can be called directly from * routines like clnt_call */ static inline bool inline_xdr_wrapstring(XDR *xdrs, char **cpp) { return inline_xdr_string(xdrs, cpp, LASTUNSIGNED); } /* * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t() * are in the "non-portable" section because they require that a `long long' * be a 64-bit type. * * --thorpej@netbsd.org, November 30, 1999 */ /* * XDR 64-bit integers */ static inline bool inline_xdr_int64_t(XDR *xdrs, int64_t *llp) { u_long ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: ul[0] = (u_long) ((u_int64_t) *llp >> 32) & 0xffffffff; ul[1] = (u_long) ((u_int64_t) *llp) & 0xffffffff; if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == false) return (false); return (XDR_PUTLONG(xdrs, (long *)&ul[1])); case XDR_DECODE: if (XDR_GETLONG(xdrs, (long *)&ul[0]) == false) return (false); if (XDR_GETLONG(xdrs, (long *)&ul[1]) == false) return (false); *llp = (int64_t) (((u_int64_t) ul[0] << 32) | ((u_int64_t) ul[1])); return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 64-bit integers */ static inline bool inline_xdr_u_int64_t(XDR *xdrs, u_int64_t *ullp) { u_long ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: ul[0] = (u_long) (*ullp >> 32) & 0xffffffff; ul[1] = (u_long) (*ullp) & 0xffffffff; if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == false) return (false); return (XDR_PUTLONG(xdrs, (long *)&ul[1])); case XDR_DECODE: if (XDR_GETLONG(xdrs, (long *)&ul[0]) == false) return (false); if (XDR_GETLONG(xdrs, (long *)&ul[1]) == false) return (false); *ullp = (u_int64_t) (((u_int64_t) ul[0] << 32) | ((u_int64_t) ul[1])); return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR hypers */ static inline bool inline_xdr_hyper(XDR *xdrs, quad_t *llp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_int64_t(). */ return (inline_xdr_int64_t(xdrs, (int64_t *) llp)); } /* * XDR unsigned hypers */ static inline bool inline_xdr_u_hyper(XDR *xdrs, u_quad_t *ullp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_u_int64_t(). */ return (inline_xdr_u_int64_t(xdrs, (u_int64_t *) ullp)); } /* * XDR longlong_t's */ static inline bool inline_xdr_longlong_t(XDR *xdrs, quad_t *llp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_int64_t(). */ return (inline_xdr_int64_t(xdrs, (int64_t *) llp)); } /* * XDR u_longlong_t's */ static inline bool inline_xdr_u_longlong_t(XDR *xdrs, u_quad_t *ullp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_u_int64_t(). */ return (inline_xdr_u_int64_t(xdrs, (u_int64_t *) ullp)); } #endif /* _TIRPC_INLINE_XDR_H */ ntirpc-1.3.1/ntirpc/rpc/xdr_inrec.h000066400000000000000000000036211261345040100172220ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef XDR_INREC_H #define XDR_INREC_H #include #include /* XDR pseudo records for tcp */ extern void xdr_inrec_create(XDR *, u_int, void *, int (*)(XDR * xdrs, void *, void *, int)); extern bool xdr_inrec_readahead(XDR *xdrs, u_int maxfraglen); /* make end of xdr record */ extern bool xdr_inrec_endofrecord(XDR *, bool); /* move to beginning of next record */ extern bool xdr_inrec_skiprecord(XDR *); /* true if no more input */ extern bool xdr_inrec_eof(XDR *); /* intrinsic checksum (be careful) */ extern uint64_t xdr_inrec_cksum(XDR *); #endif /* XDR_INREC_H */ ntirpc-1.3.1/ntirpc/rpc/xdr_ioq.h000066400000000000000000000103211261345040100167050ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef XDR_IOQ_H #define XDR_IOQ_H #include #include #include #include #include #include struct xdr_ioq_uv { struct poolq_entry uvq; /* spliced buffers, if any */ struct xdr_uio u; /* Each xdr_ioq_uv can have a different kind of buffer or data source, * as indicated by the uio_flags, needing different release techniques. * Note: overloads uio_release with uio_p1 for pool. */ struct xdr_vio v; /* immediately follows u (uio_vio[0]) */ }; #define IOQ_(p) (opr_containerof((p), struct xdr_ioq_uv, uvq)) #define IOQU(p) (opr_containerof((p), struct xdr_ioq_uv, u)) #define IOQV(p) (opr_containerof((p), struct xdr_ioq_uv, v)) #define ioquv_length(uv) \ ((uintptr_t)((uv)->v.vio_tail) - (uintptr_t)((uv)->v.vio_head)) #define ioquv_size(uv) \ ((uintptr_t)((uv)->v.vio_wrap) - (uintptr_t)((uv)->v.vio_base)) struct xdr_ioq; struct xdr_ioq_uv_head { struct poolq_head uvqh; /* Each xdr_ioq_uv can have a different kind of buffer or data source, * as indicated by the uio_flags, needing different create techniques. */ struct poolq_entry *(*uvq_fetch)(struct xdr_ioq *xioq, struct poolq_head *ioqh, char *comment, u_int count, u_int ioq_flags); u_int plength; /* sub-total of previous lengths, not including * any length in this xdr_ioq_uv */ u_int pcount; /* fill index (0..m) in the current stream */ u_int min_bsize; /* multiple of pagesize */ u_int max_bsize; /* multiple of min_bsize */ }; struct xdr_ioq { XDR xdrs[1]; struct poolq_entry ioq_s; /* segment of stream */ pthread_cond_t ioq_cond; struct poolq_head *ioq_pool; void *ioq_p2; void *ioq_u1; void *ioq_u2; struct xdr_ioq_uv_head ioq_uv; /* header/vectors */ uint64_t id; }; #define _IOQ(p) (opr_containerof((p), struct xdr_ioq, ioq_s)) #define XIOQ(p) (opr_containerof((p), struct xdr_ioq, xdrs)) /* avoid conflicts with UIO_FLAG */ #define IOQ_FLAG_NONE 0x0000 #define IOQ_FLAG_BALLOC 0x4000 #define IOQ_FLAG_XTENDQ 0x8000 extern struct xdr_ioq_uv *xdr_ioq_uv_create(u_int size, u_int uio_flags); extern struct poolq_entry *xdr_ioq_uv_fetch(struct xdr_ioq *xioq, struct poolq_head *ioqh, char *comment, u_int count, u_int ioq_flags); extern struct poolq_entry *xdr_ioq_uv_fetch_nothing(struct xdr_ioq *xioq, struct poolq_head *ioqh, char *comment, u_int count, u_int ioq_flags); extern void xdr_ioq_uv_release(struct xdr_ioq_uv *uv); extern XDR *xdr_ioq_create(u_int min_bsize, u_int max_bsize, u_int uio_flags); extern void xdr_ioq_release(struct poolq_head *ioqh); extern void xdr_ioq_reset(struct xdr_ioq *xioq, u_int wh_pos); extern void xdr_ioq_setup(struct xdr_ioq *xioq); extern void xdr_ioq_destroy(struct xdr_ioq *xioq, size_t qsize); extern void xdr_ioq_destroy_pool(struct poolq_head *ioqh); extern const struct xdr_ops xdr_ioq_ops; #endif /* XDR_IOQ_H */ ntirpc-1.3.1/ntirpc/rpcsvc/000077500000000000000000000000001261345040100156065ustar00rootroot00000000000000ntirpc-1.3.1/ntirpc/rpcsvc/crypt.h000066400000000000000000000045261261345040100171270ustar00rootroot00000000000000/* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _CRYPT_H_RPCGEN #define _CRYPT_H_RPCGEN #include #ifndef IXDR_GET_INT32 #define IXDR_GET_INT32(buf) IXDR_GET_LONG((buf)) #endif #ifndef IXDR_PUT_INT32 #define IXDR_PUT_INT32(buf, v) IXDR_PUT_LONG((buf), (v)) #endif #ifndef IXDR_GET_U_INT32 #define IXDR_GET_U_INT32(buf) IXDR_GET_U_LONG((buf)) #endif #ifndef IXDR_PUT_U_INT32 #define IXDR_PUT_U_INT32(buf, v) IXDR_PUT_U_LONG((buf), (v)) #endif enum des_dir { ENCRYPT_DES = 0, DECRYPT_DES = 1, }; typedef enum des_dir des_dir; #ifdef __cplusplus extern "C" bool xdr_des_dir(XDR *, des_dir *); #elif __STDC__ extern bool xdr_des_dir(XDR *, des_dir *); #else /* Old Style C */ bool xdr_des_dir(); #endif /* Old Style C */ enum des_mode { CBC_DES = 0, ECB_DES = 1, }; typedef enum des_mode des_mode; #ifdef __cplusplus extern "C" bool xdr_des_mode(XDR *, des_mode *); #elif __STDC__ extern bool xdr_des_mode(XDR *, des_mode *); #else /* Old Style C */ bool xdr_des_mode(); #endif /* Old Style C */ struct desargs { u_char des_key[8]; des_dir des_dir; des_mode des_mode; u_char des_ivec[8]; struct { u_int desbuf_len; char *desbuf_val; } desbuf; }; typedef struct desargs desargs; #ifdef __cplusplus extern "C" bool xdr_desargs(XDR *, desargs *); #elif __STDC__ extern bool xdr_desargs(XDR *, desargs *); #else /* Old Style C */ bool xdr_desargs(); #endif /* Old Style C */ struct desresp { struct { u_int desbuf_len; char *desbuf_val; } desbuf; u_char des_ivec[8]; int stat; }; typedef struct desresp desresp; #ifdef __cplusplus extern "C" bool xdr_desresp(XDR *, desresp *); #elif __STDC__ extern bool xdr_desresp(XDR *, desresp *); #else /* Old Style C */ bool xdr_desresp(); #endif /* Old Style C */ #define CRYPT_PROG ((u_int32_t)600100029) #define CRYPT_VERS ((u_int32_t)1) #ifdef __cplusplus #define DES_CRYPT ((u_int32_t)1) extern "C" { desresp *des_crypt_1(desargs *, CLIENT *); desresp *des_crypt_1_svc(desargs *, struct svc_req *); } #elif __STDC__ #define DES_CRYPT ((u_int32_t)1) extern desresp *des_crypt_1(desargs *, CLIENT *); extern desresp *des_crypt_1_svc(desargs *, struct svc_req *); #else /* Old Style C */ #define DES_CRYPT ((u_int32_t)1) extern desresp *des_crypt_1(); extern desresp *des_crypt_1_svc(); #endif /* Old Style C */ #endif /* !_CRYPT_H_RPCGEN */ ntirpc-1.3.1/ntirpc/un-namespace.h000066400000000000000000000075651261345040100170500ustar00rootroot00000000000000/* * Copyright (c) 2001 Daniel Eischen . * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 REGENTS 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. * * $FreeBSD: src/lib/libc/include/un-namespace.h,v 1.13 2003/05/01 * 19:03:13 nectar Exp $ */ #ifndef _UN_NAMESPACE_H_ #define _UN_NAMESPACE_H_ #undef accept #undef __acl_aclcheck_fd #undef __acl_delete_fd #undef __acl_get_fd #undef __acl_set_fd #undef bind #undef __cap_get_fd #undef __cap_set_fd #undef close #undef connect #undef dup #undef dup2 #undef execve #undef fcntl #undef flock #undef flockfile #undef fpathconf #undef fstat #undef fstatfs #undef fsync #undef funlockfile #undef getdirentries #undef getlogin #undef getpeername #undef getprogname #undef getsockname #undef getsockopt #undef ioctl #undef kevent #undef listen #undef nanosleep #undef open #undef poll #undef pthread_cond_broadcast #undef pthread_cond_destroy #undef pthread_cond_init #undef pthread_cond_signal #undef pthread_cond_timedwait #undef pthread_cond_wait #undef pthread_exit #undef pthread_getspecific #undef pthread_key_create #undef pthread_key_delete #undef pthread_main_np #undef pthread_mutex_destroy #undef pthread_mutex_init #undef pthread_mutex_lock #undef pthread_mutex_trylock #undef pthread_mutex_unlock #undef pthread_mutexattr_init #undef pthread_mutexattr_destroy #undef pthread_mutexattr_settype #undef pthread_once #undef pthread_rwlock_destroy #undef pthread_rwlock_init #undef pthread_rwlock_rdlock #undef pthread_rwlock_wrlock #undef pthread_rwlock_tryrdlock #undef pthread_rwlock_trywrlock #undef pthread_rwlock_unlock #undef pthread_self #undef pthread_setspecific #undef pthread_sigmask #undef read #undef readv #undef recvfrom #undef recvmsg #undef select #undef sendmsg #undef sendto #undef setsockopt #undef sigaction #undef sigprocmask #undef sigsuspend #undef socket #undef socketpair #undef wait4 #undef waitpid #undef write #undef writev #if 0 #undef creat #undef fchflags #undef fchmod #undef ftrylockfile #undef msync #undef nfssvc #undef pause #undef pthread_rwlockattr_init #undef pthread_rwlockattr_destroy #undef sched_yield #undef sendfile #undef shutdown #undef sigaltstack #undef sigpending #undef sigreturn #undef sigsetmask #undef sleep #undef system #undef tcdrain #undef wait #endif /* 0 */ #ifdef _SIGNAL_H_ int _sigaction(int, const struct sigaction *, struct sigaction *); #endif #ifdef _SYS_EVENT_H_ int _kevent(int, const struct kevent *, int, struct kevent *, int, const struct timespec *); #endif #ifdef _SYS_FCNTL_H_ int _flock(int, int); #endif #undef err #undef warn #undef nsdispatch #endif /* _UN_NAMESPACE_H_ */ ntirpc-1.3.1/src/000077500000000000000000000000001261345040100135765ustar00rootroot00000000000000ntirpc-1.3.1/src/CMakeLists.txt000066400000000000000000000044231261345040100163410ustar00rootroot00000000000000 add_definitions( -DPORTMAP -DINET6 -D_GNU_SOURCE ) # ok on Linux and FreeBSD w/GCC and clang compilers set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC") ########### next target ############### SET(ntirpc_common_SRCS auth_none.c auth_unix.c authunix_prot.c bindresvport.c bsd_epoll.c city.c clnt_bcast.c clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_vc.c getnetconfig.c getnetpath.c getpeereid.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 rbtree.c rbtree_x.c rpc_dplx.c rpc_prot.c rpc_callmsg.c rpc_commondata.c rpc_crc32.c rpc_ctx.c rpc_dplx_msg.c rpc_dtablesize.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c rpcb_st_xdr.c strlcpy.c svc.c svc_auth.c svc_auth_unix.c svc_auth_none.c svc_dg.c svc_generic.c svc_raw.c svc_rqst.c svc_run.c svc_simple.c svc_vc.c svc_xprt.c vc_generic.c xdr.c xdr_array.c xdr_float.c xdr_mem.c xdr_rec.c xdr_reference.c xdr_stdio.c xdr_inrec.c xdr_ioq.c svc_ioq.c work_pool.c ) if(USE_DES) SET(ntirpc_des_SRCS auth_des.c authdes_prot.c ) endif(USE_DES) if(USE_GSS) SET(ntirpc_gss_SRCS auth_gss.c authgss_hash.c authgss_prot.c svc_auth_gss.c ) # fixme # libntirpc_la_LDFLAGS += $(GSSGLUE_LIBS) # libntirpc_la_CFLAGS = -DHAVE_RPCSEC_GSS $(GSSGLUE_CFLAGS) endif(USE_GSS) if(USE_RPC_RDMA) SET(ntirpc_rdma_SRCS clnt_rdma.c rpc_rdma.c svc_rdma.c xdr_rdma.c ) endif(USE_RPC_RDMA) # declares the library add_library(ntirpc SHARED ${ntirpc_common_SRCS} ${ntirpc_des_SRCS} ${ntirpc_gss_SRCS} ${ntirpc_rdma_SRCS} ) # add required libraries--for Ganesha build, it's ok for them to # propagate (i.e., omit PRIVATE) target_link_libraries(ntirpc ${SYSTEM_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) # set library version and symbol namespace(s) from gen'd map file set_target_properties(ntirpc PROPERTIES LINK_FLAGS "-Wl,--version-script=${PROJECT_BINARY_DIR}/libntirpc.map" VERSION ${NTIRPC_VERSION} SOVERSION "${NTIRPC_MAJOR_VERSION}.${NTIRPC_MINOR_VERSION}" ) install(TARGETS ntirpc DESTINATION ${LIB_INSTALL_DIR}) ########### install files ############### # We are still missing the install of docs and stuff ntirpc-1.3.1/src/auth_des.c000066400000000000000000000342361261345040100155460ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1988 by Sun Microsystems, Inc. */ /* * auth_des.c, client-side implementation of DES authentication */ #ifndef __APPLE__ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #undef NIS #include #if defined(LIBC_SCCS) && !defined(lint) #endif #include #define USEC_PER_SEC 1000000 #define RTIME_TIMEOUT 5 /* seconds to wait for sync */ #define AUTH_PRIVATE(auth) ((struct ad_private *) (auth)->ah_private) #define ALLOC(object_type) ((object_type *) mem_alloc(sizeof(object_type))) #define FREE(ptr, size) mem_free((char *)(ptr), (int) size) #define ATTEMPT(xdr_op) if (!(xdr_op)) return (false) bool xdr_authdes_cred(XDR *, struct authdes_cred *); bool xdr_authdes_verf(XDR *, struct authdes_verf *); bool __rpc_get_time_offset(struct timeval *, nis_server *, char *, char **, char **); /* * DES authenticator operations vector */ static void authdes_nextverf(AUTH *); static bool authdes_marshal(AUTH *, XDR *); static bool authdes_validate(AUTH *, struct opaque_auth *); static bool authdes_refresh(AUTH *, void *); static void authdes_destroy(AUTH *); static struct auth_ops *authdes_ops(void); /* * This struct is pointed to by the ah_private field of an "AUTH *" */ struct ad_private { char *ad_fullname; /* client's full name */ u_int ad_fullnamelen; /* length of name, rounded up */ char *ad_servername; /* server's full name */ u_int ad_servernamelen; /* length of name, rounded up */ u_int ad_window; /* client specified window */ bool ad_dosync; /* synchronize? */ struct netbuf ad_syncaddr; /* remote host to synch with */ char *ad_timehost; /* remote host to synch with */ struct timeval ad_timediff; /* server's time - client's time */ u_int ad_nickname; /* server's nickname for client */ struct authdes_cred ad_cred; /* storage for credential */ struct authdes_verf ad_verf; /* storage for verifier */ struct timeval ad_timestamp; /* timestamp sent */ des_block ad_xkey; /* encrypted conversation key */ u_char ad_pkey[1024]; /* Server's actual public key */ char *ad_netid; /* Timehost netid */ char *ad_uaddr; /* Timehost uaddr */ nis_server *ad_nis_srvr; /* NIS+ server struct */ }; AUTH * authdes_pk_nseccreate(const char *, netobj *, u_int, const char *, const des_block *, nis_server *); /* * documented version of authdes_nseccreate */ /* servername: network name of server win: time to live timehost: optional hostname to sync with ckey: optional conversation key to use */ AUTH * authdes_nseccreate(const char *servername, const u_int win, const char *timehost, const des_block *ckey) { u_char pkey_data[1024]; netobj pkey; AUTH *dummy; if (!getpublickey(servername, (char *)pkey_data)) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_nseccreate: no public key found for %s", servername); return (NULL); } pkey.n_bytes = (char *)pkey_data; pkey.n_len = (u_int) strlen((char *)pkey_data) + 1; dummy = authdes_pk_nseccreate(servername, &pkey, win, timehost, ckey, NULL); return (dummy); } /* * Slightly modified version of authdessec_create which takes the public key * of the server principal as an argument. This spares us a call to * getpublickey() which in the nameserver context can cause a deadlock. */ AUTH * authdes_pk_nseccreate(const char *servername, netobj *pkey, u_int window, const char *timehost, const des_block *ckey, nis_server *srvr) { AUTH *auth; struct ad_private *ad; char namebuf[MAXNETNAMELEN + 1]; /* * Allocate everything now */ auth = ALLOC(AUTH); if (auth == NULL) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_pk_nseccreate: out of memory"); return (NULL); } ad = ALLOC(struct ad_private); if (ad == NULL) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_pk_nseccreate: out of memory"); goto failed; } ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */ ad->ad_timehost = NULL; ad->ad_netid = NULL; ad->ad_uaddr = NULL; ad->ad_nis_srvr = NULL; ad->ad_timediff.tv_sec = 0; ad->ad_timediff.tv_usec = 0; memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len); if (!getnetname(namebuf)) goto failed; ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf)); ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); ad->ad_servernamelen = strlen(servername); ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_nseccreate: out of memory"); goto failed; } if (timehost != NULL) { ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1); if (ad->ad_timehost == NULL) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_nseccreate: out of memory"); goto failed; } memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1); ad->ad_dosync = true; } else if (srvr != NULL) { ad->ad_nis_srvr = srvr; /* transient */ ad->ad_dosync = true; } else { ad->ad_dosync = false; } memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1); ad->ad_window = window; if (ckey == NULL) { if (key_gendes(&auth->ah_key) < 0) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_nseccreate: keyserv(1m) is unable to generate " "session key"); goto failed; } } else { auth->ah_key = *ckey; } /* * Set up auth handle */ auth->ah_cred.oa_flavor = AUTH_DES; auth->ah_verf.oa_flavor = AUTH_DES; auth->ah_ops = authdes_ops(); auth->ah_private = (caddr_t) ad; if (!authdes_refresh(auth, NULL)) goto failed; ad->ad_nis_srvr = NULL; /* not needed any longer */ auth_get(auth); /* Reference for caller */ return (auth); failed: if (auth) FREE(auth, sizeof(AUTH)); if (ad) { if (ad->ad_fullname) FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); if (ad->ad_servername) FREE(ad->ad_servername, ad->ad_servernamelen + 1); if (ad->ad_timehost) FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); if (ad->ad_netid) FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); if (ad->ad_uaddr) FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); FREE(ad, sizeof(struct ad_private)); } return (NULL); } /* * Implement the five authentication operations */ /* * 1. Next Verifier */ static void authdes_nextverf(AUTH *auth) { /* what the heck am I supposed to do??? */ } /* * 2. Marshal */ static bool authdes_marshal(AUTH *auth, XDR *xdrs) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_cred *cred = &ad->ad_cred; struct authdes_verf *verf = &ad->ad_verf; des_block cryptbuf[2]; des_block ivec; int status; int len; rpc_inline_t *ixdr; /* * Figure out the "time", accounting for any time difference * with the server if necessary. */ (void)gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL); ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) { ad->ad_timestamp.tv_usec -= USEC_PER_SEC; ad->ad_timestamp.tv_sec++; } /* * XDR the timestamp and possibly some other things, then * encrypt them. */ ixdr = (rpc_inline_t *) cryptbuf; IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec); IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec); if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { IXDR_PUT_U_INT32(ixdr, ad->ad_window); IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1); ivec.key.high = ivec.key.low = 0; status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf, (u_int) 2 * sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec); } else { status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf, (u_int) sizeof(des_block), DES_ENCRYPT | DES_HW); } if (DES_FAILED(status)) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_marshal: DES encryption failure"); return (false); } ad->ad_verf.adv_xtimestamp = cryptbuf[0]; if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; ad->ad_verf.adv_winverf = cryptbuf[1].key.low; } else { ad->ad_cred.adc_nickname = ad->ad_nickname; ad->ad_verf.adv_winverf = 0; } /* * Serialize the credential and verifier into opaque * authentication data. */ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { len = ((1 + 1 + 2 + 1) * BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); } else { len = (1 + 1) * BYTES_PER_XDR_UNIT; } ixdr = xdr_inline(xdrs, 2 * BYTES_PER_XDR_UNIT); if (ixdr) { IXDR_PUT_INT32(ixdr, AUTH_DES); IXDR_PUT_INT32(ixdr, len); } else { ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor)); ATTEMPT(xdr_putint32(xdrs, &len)); } ATTEMPT(xdr_authdes_cred(xdrs, cred)); len = (2 + 1) * BYTES_PER_XDR_UNIT; ixdr = xdr_inline(xdrs, 2 * BYTES_PER_XDR_UNIT); if (ixdr) { IXDR_PUT_INT32(ixdr, AUTH_DES); IXDR_PUT_INT32(ixdr, len); } else { ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor)); ATTEMPT(xdr_putint32(xdrs, &len)); } ATTEMPT(xdr_authdes_verf(xdrs, verf)); return (true); } /* * 3. Validate */ static bool authdes_validate(AUTH *auth, struct opaque_auth *rverf) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_verf verf; int status; uint32_t *ixdr; des_block buf; if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) return (false); /* LINTED pointer alignment */ ixdr = (uint32_t *) rverf->oa_base; buf.key.high = (uint32_t) *ixdr++; buf.key.low = (uint32_t) *ixdr++; verf.adv_int_u = (uint32_t) *ixdr++; /* * Decrypt the timestamp */ status = ecb_crypt((char *)&auth->ah_key, (char *)&buf, (u_int) sizeof(des_block), DES_DECRYPT | DES_HW); if (DES_FAILED(status)) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_validate: DES decryption failure"); return (false); } /* * xdr the decrypted timestamp */ /* LINTED pointer alignment */ ixdr = (uint32_t *) buf.c; verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1; verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr); /* * validate */ if (bcmp ((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, sizeof(struct timeval)) != 0) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_validate: verifier mismatch"); return (false); } /* * We have a nickname now, let's use it */ ad->ad_nickname = verf.adv_nickname; ad->ad_cred.adc_namekind = ADN_NICKNAME; return (true); } /* * 4. Refresh */ /*ARGSUSED*/ static bool authdes_refresh(AUTH *auth, void *dummy) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); struct authdes_cred *cred = &ad->ad_cred; int ok; netobj pkey; if (ad->ad_dosync) { ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr, ad->ad_timehost, &(ad->ad_uaddr), &(ad->ad_netid)); if (!ok) { /* * Hope the clocks are synced! */ ad->ad_dosync = 0; __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_refresh: unable to synchronize clock"); } } ad->ad_xkey = auth->ah_key; pkey.n_bytes = (char *)(ad->ad_pkey); pkey.n_len = (u_int) strlen((char *)ad->ad_pkey) + 1; if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "authdes_refresh: keyserv(1m) is unable to encrypt " "session key"); return (false); } cred->adc_fullname.key = ad->ad_xkey; cred->adc_namekind = ADN_FULLNAME; cred->adc_fullname.name = ad->ad_fullname; return (true); } /* * 5. Destroy */ static void authdes_destroy(AUTH *auth) { /* LINTED pointer alignment */ struct ad_private *ad = AUTH_PRIVATE(auth); FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); FREE(ad->ad_servername, ad->ad_servernamelen + 1); if (ad->ad_timehost) FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); if (ad->ad_netid) FREE(ad->ad_netid, strlen(ad->ad_netid) + 1); if (ad->ad_uaddr) FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1); FREE(ad, sizeof(struct ad_private)); FREE(auth, sizeof(AUTH)); } static bool authdes_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere) { return ((*xfunc) (xdrs, xwhere)); } static struct auth_ops * authdes_ops(void) { static struct auth_ops ops; extern mutex_t authdes_ops_lock; /* VARIABLES PROTECTED BY ops_lock: ops */ mutex_lock(&authdes_ops_lock); if (ops.ah_nextverf == NULL) { ops.ah_nextverf = authdes_nextverf; ops.ah_marshal = authdes_marshal; ops.ah_validate = authdes_validate; ops.ah_refresh = authdes_refresh; ops.ah_destroy = authdes_destroy; ops.ah_wrap = authdes_wrap; ops.ah_unwrap = authdes_wrap; } mutex_unlock(&authdes_ops_lock); return (&ops); } #endif ntirpc-1.3.1/src/auth_gss.c000066400000000000000000000402351261345040100155630ustar00rootroot00000000000000/* auth_gss.c RPCSEC_GSS client routines. Copyright (c) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (c) 2000 Dug Song . All rights reserved, all wrongs reversed. 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 University 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 ``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 REGENTS 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include static void authgss_nextverf(AUTH *auth); static bool authgss_marshal(AUTH *auth, XDR *xdrs); static bool authgss_refresh(AUTH *auth, void *arg); static bool authgss_validate(AUTH *auth, struct opaque_auth *verf); static void authgss_destroy(AUTH *auth); static void authgss_destroy_context(AUTH *auth); static bool authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr); static bool authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr); /* * from mit-krb5-1.2.1 mechglue/mglueP.h: * Array of context IDs typed by mechanism OID */ typedef struct gss_union_ctx_id_t { gss_OID mech_type; gss_ctx_id_t internal_ctx_id; } gss_union_ctx_id_desc, *gss_union_ctx_id_t; static struct auth_ops authgss_ops = { authgss_nextverf, authgss_marshal, authgss_validate, authgss_refresh, authgss_destroy, authgss_wrap, authgss_unwrap }; #ifdef DEBUG /* useful as i add more mechanisms */ void print_rpc_gss_sec(struct rpc_gss_sec *ptr) { int i; char *p; log_debug("rpc_gss_sec:"); if (ptr->mech == NULL) log_debug("NULL gss_OID mech"); else { __warnx(TIRPC_DEBUG_FLAG_AUTH, " mechanism_OID: {"); p = (char *)ptr->mech->elements; for (i = 0; i < ptr->mech->length; i++) /* First byte of OIDs encoded to save a byte */ if (i == 0) { int first, second; if (*p < 40) { first = 0; second = *p; } else if (40 <= *p && *p < 80) { first = 1; second = *p - 40; } else if (80 <= *p && *p < 127) { first = 2; second = *p - 80; } else { /* Invalid value! */ first = -1; second = -1; } __warnx(TIRPC_DEBUG_FLAG_AUTH, " %u %u", first, second); p++; } else { __warnx(TIRPC_DEBUG_FLAG_AUTH, " %u", (unsigned char)*p++); } __warnx(" }\n"); } __warnx(TIRPC_DEBUG_FLAG_AUTH, " qop: %d\n", ptr->qop); __warnx(TIRPC_DEBUG_FLAG_AUTH, " service: %d\n", ptr->svc); __warnx(TIRPC_DEBUG_FLAG_AUTH, " cred: %p\n", ptr->cred); } #endif /*DEBUG*/ struct rpc_gss_data { mutex_t lock; bool established; /* context established */ gss_buffer_desc gc_wire_verf; /* save GSS_S_COMPLETE NULL RPC verfier * to process at end of context * negotiation*/ CLIENT *clnt; /* client handle */ gss_name_t name; /* service name */ struct rpc_gss_sec sec; /* security tuple */ gss_ctx_id_t ctx; /* context id */ struct rpc_gss_cred gc; /* client credentials */ u_int win; /* sequence window */ }; #define AUTH_PRIVATE(auth) ((struct rpc_gss_data *)auth->ah_private) static struct timeval AUTH_TIMEOUT = { 25, 0 }; AUTH * authgss_ncreate(CLIENT *clnt, gss_name_t name, struct rpc_gss_sec *sec) { AUTH *auth; struct rpc_gss_data *gd; OM_uint32 min_stat = 0; log_debug("in authgss_ncreate()"); memset(&rpc_createerr, 0, sizeof(rpc_createerr)); auth = mem_alloc(sizeof(*auth)); if (auth == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = ENOMEM; return (NULL); } /* XXX move to ctor */ gd = mem_alloc(sizeof(*gd)); if (gd == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = ENOMEM; mem_free(auth, 0); return (NULL); } mutex_init(&gd->lock, NULL); #ifdef DEBUG __warnx(TIRPC_DEBUG_FLAG_AUTH, "authgss_ncreate: name is %p\n", name); #endif if (name != GSS_C_NO_NAME) { if (gss_duplicate_name(&min_stat, name, &gd->name) != GSS_S_COMPLETE) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = ENOMEM; mem_free(gd, 0); mem_free(auth, 0); return (NULL); } } else gd->name = name; #ifdef DEBUG __warnx(TIRPC_DEBUG_FLAG_AUTH, "authgss_ncreate: gd->name is %p\n", gd->name); #endif gd->clnt = clnt; gd->ctx = GSS_C_NO_CONTEXT; gd->sec = *sec; gd->gc.gc_v = RPCSEC_GSS_VERSION; gd->gc.gc_proc = RPCSEC_GSS_INIT; gd->gc.gc_svc = gd->sec.svc; auth->ah_ops = &authgss_ops; auth->ah_private = (caddr_t) gd; if (!authgss_refresh(auth, NULL)) auth = NULL; else auth_get(auth); /* Reference for caller */ return (auth); } AUTH * authgss_ncreate_default(CLIENT *clnt, char *service, struct rpc_gss_sec *sec) { AUTH *auth; OM_uint32 maj_stat = 0, min_stat = 0; gss_buffer_desc sname; gss_name_t name = GSS_C_NO_NAME; log_debug("in authgss_ncreate_default()"); sname.value = service; sname.length = strlen(service); maj_stat = gss_import_name(&min_stat, &sname, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &name); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_import_name", maj_stat, min_stat); rpc_createerr.cf_stat = RPC_AUTHERROR; return (NULL); } auth = authgss_ncreate(clnt, name, sec); if (name != GSS_C_NO_NAME) { #ifdef DEBUG __warnx(TIRPC_DEBUG_FLAG_AUTH, "authgss_ncreate_default: freeing name %p\n", name); #endif gss_release_name(&min_stat, &name); } return (auth); } bool authgss_get_private_data(AUTH *auth, struct authgss_private_data *pd) { struct rpc_gss_data *gd; log_debug("in authgss_get_private_data()"); if (!auth || !pd) return (false); gd = AUTH_PRIVATE(auth); if (!gd || !gd->established) return (false); pd->pd_ctx = gd->ctx; pd->pd_ctx_hndl = gd->gc.gc_ctx; pd->pd_seq_win = gd->win; return (true); } static void authgss_nextverf(AUTH *auth) { log_debug("in authgss_nextverf()"); /* no action necessary */ } static bool authgss_marshal(AUTH *auth, XDR *xdrs) { XDR tmpxdrs; char tmp[MAX_AUTH_BYTES]; struct rpc_gss_data *gd; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat; bool xdr_stat; log_debug("in authgss_marshal()"); gd = AUTH_PRIVATE(auth); if (gd->established) { /* XXX */ mutex_lock(&gd->lock); gd->gc.gc_seq++; mutex_unlock(&gd->lock); } xdrmem_create(&tmpxdrs, tmp, sizeof(tmp), XDR_ENCODE); if (!xdr_rpc_gss_cred(&tmpxdrs, &gd->gc)) { XDR_DESTROY(&tmpxdrs); return (false); } auth->ah_cred.oa_flavor = RPCSEC_GSS; auth->ah_cred.oa_base = tmp; auth->ah_cred.oa_length = XDR_GETPOS(&tmpxdrs); XDR_DESTROY(&tmpxdrs); if (!inline_xdr_opaque_auth(xdrs, &auth->ah_cred)) return (false); if (gd->gc.gc_proc == RPCSEC_GSS_INIT || gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) { return (inline_xdr_opaque_auth(xdrs, &_null_auth)); } /* Checksum serialized RPC header, up to and including credential. */ rpcbuf.length = XDR_GETPOS(xdrs); XDR_SETPOS(xdrs, 0); rpcbuf.value = XDR_INLINE(xdrs, rpcbuf.length); maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop, &rpcbuf, &checksum); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_get_mic", maj_stat, min_stat); if (maj_stat == GSS_S_CONTEXT_EXPIRED) { gd->established = false; authgss_destroy_context(auth); } return (false); } auth->ah_verf.oa_flavor = RPCSEC_GSS; auth->ah_verf.oa_base = checksum.value; auth->ah_verf.oa_length = checksum.length; xdr_stat = xdr_opaque_auth(xdrs, &auth->ah_verf); gss_release_buffer(&min_stat, &checksum); return (xdr_stat); } static bool authgss_validate(AUTH *auth, struct opaque_auth *verf) { struct rpc_gss_data *gd; u_int num, qop_state; gss_buffer_desc signbuf, checksum; OM_uint32 maj_stat, min_stat; log_debug("in authgss_validate()"); gd = AUTH_PRIVATE(auth); if (gd->established == false) { /* would like to do this only on NULL rpc -- * gc->established is good enough. * save the on the wire verifier to validate last * INIT phase packet after decode if the major * status is GSS_S_COMPLETE */ gd->gc_wire_verf.value = mem_alloc(verf->oa_length); if (gd->gc_wire_verf.value == NULL) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "gss_validate: out of memory\n"); return (false); } memcpy(gd->gc_wire_verf.value, verf->oa_base, verf->oa_length); gd->gc_wire_verf.length = verf->oa_length; return (true); } if (gd->gc.gc_proc == RPCSEC_GSS_INIT || gd->gc.gc_proc == RPCSEC_GSS_CONTINUE_INIT) { num = htonl(gd->win); } else num = htonl(gd->gc.gc_seq); signbuf.value = # signbuf.length = sizeof(num); checksum.value = verf->oa_base; checksum.length = verf->oa_length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &signbuf, &checksum, &qop_state); if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) { log_status("gss_verify_mic", maj_stat, min_stat); if (maj_stat == GSS_S_CONTEXT_EXPIRED) { gd->established = false; authgss_destroy_context(auth); } return (false); } return (true); } #define authgss_refresh_return(code) \ do { \ if (gd_locked) \ mutex_unlock(&gd->lock); \ return (code); \ } while (0) static bool authgss_refresh(AUTH *auth, void *arg) { struct rpc_gss_data *gd; struct rpc_gss_init_res gr; gss_buffer_desc *recv_tokenp, send_token; OM_uint32 maj_stat, min_stat, call_stat, ret_flags; bool gd_locked = false; log_debug("in authgss_refresh()"); gd = AUTH_PRIVATE(auth); /* Serialize context. */ mutex_lock(&gd->lock); gd_locked = true; if (gd->established) authgss_refresh_return(true); /* GSS context establishment loop. */ memset(&gr, 0, sizeof(gr)); recv_tokenp = GSS_C_NO_BUFFER; #ifdef DEBUG print_rpc_gss_sec(&gd->sec); #endif /*DEBUG*/ for (;;) { #ifdef DEBUG /* print the token we just received */ if (recv_tokenp != GSS_C_NO_BUFFER) { log_debug("The token we just received (length %d):", recv_tokenp->length); gss_log_hexdump(recv_tokenp->value, recv_tokenp->length, 0); } #endif maj_stat = gss_init_sec_context(&min_stat, gd->sec.cred, &gd->ctx, gd->name, gd->sec.mech, gd->sec.req_flags, 0, /* time req */ NULL, /* channel */ recv_tokenp, NULL, /* used mech */ &send_token, &ret_flags, NULL); /* time rec */ if (recv_tokenp != GSS_C_NO_BUFFER) { gss_release_buffer(&min_stat, &gr.gr_token); recv_tokenp = GSS_C_NO_BUFFER; } if (maj_stat != GSS_S_COMPLETE && maj_stat != GSS_S_CONTINUE_NEEDED) { log_status("gss_init_sec_context", maj_stat, min_stat); break; } if (send_token.length != 0) { memset(&gr, 0, sizeof(gr)); #ifdef DEBUG /* print the token we are about to send */ log_debug("The token being sent (length %d):", send_token.length); gss_log_hexdump(send_token.value, send_token.length, 0); #endif call_stat = clnt_call(gd->clnt, auth, NULLPROC, (xdrproc_t) xdr_rpc_gss_init_args, &send_token, (xdrproc_t) xdr_rpc_gss_init_res, (caddr_t) &gr, AUTH_TIMEOUT); gss_release_buffer(&min_stat, &send_token); if (call_stat != RPC_SUCCESS || (gr.gr_major != GSS_S_COMPLETE && gr.gr_major != GSS_S_CONTINUE_NEEDED)) authgss_refresh_return(false); if (gr.gr_ctx.length != 0) { if (gd->gc.gc_ctx.value) gss_release_buffer(&min_stat, &gd->gc.gc_ctx); gd->gc.gc_ctx = gr.gr_ctx; } if (gr.gr_token.length != 0) { if (maj_stat != GSS_S_CONTINUE_NEEDED) break; recv_tokenp = &gr.gr_token; } gd->gc.gc_proc = RPCSEC_GSS_CONTINUE_INIT; } /* GSS_S_COMPLETE => check gss header verifier, * usually checked in gss_validate */ if (maj_stat == GSS_S_COMPLETE) { gss_buffer_desc bufin; gss_buffer_desc bufout; u_int seq, qop_state = 0; seq = htonl(gr.gr_win); bufin.value = (unsigned char *)&seq; bufin.length = sizeof(seq); bufout.value = (unsigned char *)gd->gc_wire_verf.value; bufout.length = gd->gc_wire_verf.length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &bufin, &bufout, &qop_state); if (maj_stat != GSS_S_COMPLETE || qop_state != gd->sec.qop) { log_status("gss_verify_mic", maj_stat, min_stat); if (maj_stat == GSS_S_CONTEXT_EXPIRED) { gd->established = false; authgss_destroy_context(auth); } authgss_refresh_return (false); } gd->established = true; gd->gc.gc_proc = RPCSEC_GSS_DATA; gd->gc.gc_seq = 0; gd->win = gr.gr_win; break; } } /* End context negotiation loop. */ if (gd->gc.gc_proc != RPCSEC_GSS_DATA) { if (gr.gr_token.length != 0) gss_release_buffer(&min_stat, &gr.gr_token); authgss_destroy(auth); auth = NULL; rpc_createerr.cf_stat = RPC_AUTHERROR; authgss_refresh_return(false); } authgss_refresh_return(true); } bool authgss_service(AUTH *auth, int svc) { struct rpc_gss_data *gd; log_debug("in authgss_service()"); if (!auth) return (false); gd = AUTH_PRIVATE(auth); if (!gd || !gd->established) return (false); gd->sec.svc = svc; gd->gc.gc_svc = svc; return (true); } static void authgss_destroy_context(AUTH *auth) { struct rpc_gss_data *gd; OM_uint32 min_stat; log_debug("in authgss_destroy_context()"); gd = AUTH_PRIVATE(auth); if (gd->gc.gc_ctx.length != 0) { if (gd->established) { gd->gc.gc_proc = RPCSEC_GSS_DESTROY; clnt_call(gd->clnt, auth, NULLPROC, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_void, NULL, AUTH_TIMEOUT); } gss_release_buffer(&min_stat, &gd->gc.gc_ctx); /* XXX ANDROS check size of context - should be 8 */ memset(&gd->gc.gc_ctx, 0, sizeof(gd->gc.gc_ctx)); } if (gd->ctx != GSS_C_NO_CONTEXT) { gss_delete_sec_context(&min_stat, &gd->ctx, NULL); gd->ctx = GSS_C_NO_CONTEXT; } /* free saved wire verifier (if any) */ mem_free(gd->gc_wire_verf.value, gd->gc_wire_verf.length); gd->gc_wire_verf.value = NULL; gd->gc_wire_verf.length = 0; gd->established = false; } static void authgss_destroy(AUTH *auth) { struct rpc_gss_data *gd; OM_uint32 min_stat; log_debug("in authgss_destroy()"); gd = AUTH_PRIVATE(auth); authgss_destroy_context(auth); #ifdef DEBUG __warnx(TIRPC_DEBUG_FLAG_AUTH, "authgss_destroy: freeing name %p\n", gd->name); #endif if (gd->name != GSS_C_NO_NAME) gss_release_name(&min_stat, &gd->name); mem_free(gd, 0); mem_free(auth, 0); } bool authgss_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) { struct rpc_gss_data *gd; log_debug("in authgss_wrap()"); gd = AUTH_PRIVATE(auth); if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) return ((*xdr_func) (xdrs, xdr_ptr)); return (xdr_rpc_gss_data (xdrs, xdr_func, xdr_ptr, gd->ctx, gd->sec.qop, gd->sec.svc, gd->gc.gc_seq)); } bool authgss_unwrap(AUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) { struct rpc_gss_data *gd; log_debug("in authgss_unwrap()"); gd = AUTH_PRIVATE(auth); if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) return ((*xdr_func) (xdrs, xdr_ptr)); return (xdr_rpc_gss_data (xdrs, xdr_func, xdr_ptr, gd->ctx, gd->sec.qop, gd->sec.svc, gd->gc.gc_seq)); } ntirpc-1.3.1/src/auth_none.c000066400000000000000000000117331261345040100157270ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* #if defined(LIBC_SCCS) && !defined(lint) 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"; #endif #include __FBSDID("$FreeBSD: src/lib/libc/rpc/auth_none.c,v 1.12 2002/03/22 23:18:35 obrien Exp $"); */ /* * auth_none.c * Creates a client authentication handle for passing "null" * credentials and verifiers to remote systems. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #define MAX_MARSHAL_SIZE 20 /* * Authenticator operations routines */ static bool authnone_marshal(AUTH *, XDR *); static void authnone_verf(AUTH *); static bool authnone_validate(AUTH *, struct opaque_auth *); static bool authnone_refresh(AUTH *, void *); static void authnone_destroy(AUTH *); static struct auth_ops *authnone_ops(void); struct authnone_private { AUTH no_client; char marshalled_client[MAX_MARSHAL_SIZE]; u_int mcnt; }; static struct authnone_private auth_none_priv; static struct authnone_private *ap; static pthread_mutex_t init_lock = MUTEX_INITIALIZER; AUTH * authnone_ncreate(void) { XDR xdr_stream; XDR *xdrs; if (!ap) { mutex_lock(&init_lock); if (!ap) { ap = &auth_none_priv; /* shared */ ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth; ap->no_client.ah_ops = authnone_ops(); xdrs = &xdr_stream; xdrmem_create(xdrs, ap->marshalled_client, (u_int) MAX_MARSHAL_SIZE, XDR_ENCODE); (void)inline_xdr_opaque_auth(xdrs, &ap->no_client.ah_cred); (void)inline_xdr_opaque_auth(xdrs, &ap->no_client.ah_verf); ap->mcnt = XDR_GETPOS(xdrs); XDR_DESTROY(xdrs); } mutex_unlock(&init_lock); } return (&ap->no_client); } /*ARGSUSED*/ static bool authnone_marshal(AUTH *client, XDR *xdrs) { struct authnone_private *ap = opr_containerof(client, struct authnone_private, no_client); return ((*xdrs->x_ops->x_putbytes) (xdrs, ap->marshalled_client, ap->mcnt)); } /* All these unused parameters are required to keep ANSI-C from grumbling */ /*ARGSUSED*/ static void authnone_verf(__attribute__ ((unused)) AUTH *client) { /* do nothing */ } /*ARGSUSED*/ static bool authnone_validate( __attribute__ ((unused)) AUTH *client, __attribute__ ((unused)) struct opaque_auth *opaque) { return (true); } /*ARGSUSED*/ static bool authnone_refresh(__attribute__ ((unused)) AUTH *client, __attribute__ ((unused)) void *dummy) { return (false); } /*ARGSUSED*/ static void authnone_destroy(__attribute__ ((unused)) AUTH *client) { /* do nothing */ } static bool authnone_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere) { return ((*xfunc) (xdrs, xwhere)); } static struct auth_ops * authnone_ops(void) { static struct auth_ops ops; extern mutex_t ops_lock; /* XXXX does this need to be extern? */ /* VARIABLES PROTECTED BY ops_lock: ops */ mutex_lock(&ops_lock); if (ops.ah_nextverf == NULL) { ops.ah_nextverf = authnone_verf; ops.ah_marshal = authnone_marshal; ops.ah_validate = authnone_validate; ops.ah_refresh = authnone_refresh; ops.ah_destroy = authnone_destroy; ops.ah_wrap = authnone_wrap; ops.ah_unwrap = authnone_wrap; } mutex_unlock(&ops_lock); return (&ops); } ntirpc-1.3.1/src/auth_unix.c000066400000000000000000000252671261345040100157620ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* auth_unix.c */ static void authunix_nextverf(AUTH *); static bool authunix_marshal(AUTH *, XDR *); static bool authunix_validate(AUTH *, struct opaque_auth *); static bool authunix_refresh(AUTH *, void *); static void authunix_destroy(AUTH *); static void marshal_new_auth(AUTH *); static struct auth_ops *authunix_ops(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_ncreate(char *machname, uid_t uid, gid_t gid, int len, gid_t *aup_gids) { struct authunix_parms aup; char mymem[MAX_AUTH_BYTES]; struct timespec now; XDR xdrs; AUTH *auth; struct audata *au; memset(&rpc_createerr, 0, sizeof(rpc_createerr)); /* * Allocate and set up auth handle */ au = NULL; auth = mem_alloc(sizeof(*auth)); #ifndef _KERNEL if (auth == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = ENOMEM; goto cleanup_authunix_create; } #endif au = mem_alloc(sizeof(*au)); #ifndef _KERNEL if (au == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = ENOMEM; goto cleanup_authunix_create; } #endif auth->ah_ops = authunix_ops(); auth->ah_private = (caddr_t) au; auth->ah_verf = au->au_shcred = _null_auth; auth->ah_refcnt = 1; au->au_shfaults = 0; au->au_origcred.oa_base = NULL; /* * fill in param struct from the given params */ (void)clock_gettime(CLOCK_MONOTONIC_FAST, &now); aup.aup_time = now.tv_sec; aup.aup_machname = machname; aup.aup_uid = uid; aup.aup_gid = gid; aup.aup_len = (u_int) len; aup.aup_gids = aup_gids; /* * Serialize the parameters into origcred */ xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); if (!xdr_authunix_parms(&xdrs, &aup)) { rpc_createerr.cf_stat = RPC_CANTENCODEARGS; goto cleanup_authunix_create; } au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); au->au_origcred.oa_flavor = AUTH_UNIX; #ifdef _KERNEL au->au_origcred.oa_base = mem_alloc((u_int) len); #else au->au_origcred.oa_base = mem_alloc((u_int) len); if (au->au_origcred.oa_base == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = ENOMEM; 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; /* auth_get not needed: ah_refcnt == 1, as desired */ 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_ncreate_default(void) { int len; char machname[MAXHOSTNAMELEN + 1]; uid_t uid; gid_t gid, *gids; AUTH *result; memset(&rpc_createerr, 0, sizeof(rpc_createerr)); if (gethostname(machname, sizeof(machname)) == -1) { rpc_createerr.cf_error.re_errno = errno; goto out_err; } machname[sizeof(machname) - 1] = 0; uid = geteuid(); gid = getegid(); /* According to glibc comments, an intervening setgroups(2) * call can increase the number of supplemental groups between * these two getgroups(2) calls. */ retry: len = getgroups(0, NULL); if (len == -1) { rpc_createerr.cf_error.re_errno = errno; goto out_err; } /* Bump allocation size. A zero allocation size may result in a * NULL calloc(3) result, which is not reliably distinguishable * from a memory allocation error. */ gids = mem_alloc((len + 1) * sizeof(gid_t)); if (gids == NULL) { rpc_createerr.cf_error.re_errno = ENOMEM; goto out_err; } len = getgroups(len, gids); if (len == -1) { rpc_createerr.cf_error.re_errno = errno; mem_free(gids, 0); /* XXX */ if (rpc_createerr.cf_error.re_errno == EINVAL) { rpc_createerr.cf_error.re_errno = 0; goto retry; } goto out_err; } /* * AUTH_UNIX sends on the wire only the first NGRPS groups in the * supplemental groups list. */ if (len > NGRPS) len = NGRPS; /* XXX: interface problem; those should all have been unsigned */ result = authunix_ncreate(machname, uid, gid, len, gids); mem_free(gids, 0); /* XXX */ return result; out_err: rpc_createerr.cf_stat = RPC_SYSTEMERROR; return NULL; } /* * authunix operations */ /* ARGSUSED */ static void authunix_nextverf(AUTH *auth) { /* no action necessary */ } static bool authunix_marshal(AUTH *auth, XDR *xdrs) { struct audata *au; assert(auth != NULL); assert(xdrs != NULL); au = AUTH_PRIVATE(auth); return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); } static bool authunix_validate(AUTH *auth, struct opaque_auth *verf) { struct audata *au; XDR xdrs; assert(auth != NULL); assert(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 authunix_refresh(AUTH *auth, void *dummy) { struct audata *au = AUTH_PRIVATE(auth); struct authunix_parms aup; struct timespec now; XDR xdrs; int stat; assert(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)clock_gettime(CLOCK_MONOTONIC_FAST, &now); aup.aup_time = now.tv_sec; xdrs.x_op = XDR_ENCODE; XDR_SETPOS(&xdrs, 0); stat = xdr_authunix_parms(&xdrs, &aup); if (!stat) goto done; auth->ah_cred = au->au_origcred; marshal_new_auth(auth); done: /* free the struct authunix_parms created by deserializing */ xdrs.x_op = XDR_FREE; (void)xdr_authunix_parms(&xdrs, &aup); XDR_DESTROY(&xdrs); return (stat); } static void authunix_destroy(AUTH *auth) { struct audata *au; assert(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) { XDR xdr_stream; XDR *xdrs = &xdr_stream; struct audata *au; assert(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(TIRPC_DEBUG_FLAG_AUTH, "auth_none.c - Fatal marshalling " "problem"); else au->au_mpos = XDR_GETPOS(xdrs); XDR_DESTROY(xdrs); } static bool authunix_wrap(AUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere) { return ((*xfunc) (xdrs, xwhere)); } static struct auth_ops * authunix_ops(void) { static struct auth_ops ops; extern mutex_t ops_lock; /* XXXX does it need to be extern? */ /* 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; ops.ah_wrap = authunix_wrap; ops.ah_unwrap = authunix_wrap; } mutex_unlock(&ops_lock); return (&ops); } ntirpc-1.3.1/src/authdes_prot.c000066400000000000000000000055001261345040100164430ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ /* * authdes_prot.c, XDR routines for DES authentication */ #include #include #include #include #include #include #define ATTEMPT(xdr_op) if (!(xdr_op)) return (false) bool xdr_authdes_cred(XDR *xdrs, struct authdes_cred *cred) { /* * Unrolled xdr */ ATTEMPT(inline_xdr_enum(xdrs, (enum_t *) &cred->adc_namekind)); switch (cred->adc_namekind) { case ADN_FULLNAME: ATTEMPT(inline_xdr_string (xdrs, &cred->adc_fullname.name, MAXNETNAMELEN)); ATTEMPT(inline_xdr_opaque (xdrs, (caddr_t) &cred->adc_fullname.key, sizeof(des_block))); ATTEMPT(inline_xdr_opaque (xdrs, (caddr_t) &cred->adc_fullname.window, sizeof(cred->adc_fullname.window))); return (true); case ADN_NICKNAME: ATTEMPT(inline_xdr_opaque (xdrs, (caddr_t) &cred->adc_nickname, sizeof(cred->adc_nickname))); return (true); default: return (false); } } bool xdr_authdes_verf(XDR *xdrs, struct authdes_verf *verf) { /* * Unrolled xdr */ ATTEMPT(inline_xdr_opaque (xdrs, (caddr_t) &verf->adv_xtimestamp, sizeof(des_block))); ATTEMPT(inline_xdr_opaque (xdrs, (caddr_t) &verf->adv_int_u, sizeof(verf->adv_int_u))); return (true); } ntirpc-1.3.1/src/authgss_hash.c000066400000000000000000000167141261345040100164340ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /* Portions Copyright (c) 2010-2011, ** others, update */ #include #include #include #include #include #include #include "rpc_com.h" #include #include #include #include #include #include #include "svc_internal.h" /* GSS context cache */ struct authgss_x_part { uint32_t gen; TAILQ_HEAD(ctx_tailq, svc_rpc_gss_data) lru_q; }; struct authgss_hash_st { mutex_t lock; struct rbtree_x xt; uint32_t max_part; uint32_t size; bool initialized; }; static struct authgss_hash_st authgss_hash_st = { MUTEX_INITIALIZER, /* lock */ { 0, /* npart */ RBT_X_FLAG_NONE, /* flags */ 255, /* cachesz */ NULL /* tree */ }, /* xt */ false /* initialized */ }; static inline uint64_t gss_ctx_hash(gss_union_ctx_id_desc *gss_ctx) { return ((uint64_t) gss_ctx->mech_type + (uint64_t) gss_ctx->internal_ctx_id); } static int svc_rpc_gss_cmpf(const struct opr_rbtree_node *lhs, const struct opr_rbtree_node *rhs) { struct svc_rpc_gss_data *lk, *rk; lk = opr_containerof(lhs, struct svc_rpc_gss_data, node_k); rk = opr_containerof(rhs, struct svc_rpc_gss_data, node_k); if (lk->hk.k < rk->hk.k) return (-1); if (lk->hk.k == rk->hk.k) return (0); return (1); } void authgss_hash_init() { int ix, code = 0; mutex_lock(&authgss_hash_st.lock); /* once */ if (authgss_hash_st.initialized) goto unlock; code = rbtx_init(&authgss_hash_st.xt, svc_rpc_gss_cmpf, __svc_params->gss.ctx_hash_partitions, RBT_X_FLAG_ALLOC | RBT_X_FLAG_CACHE_RT); if (code) __warnx(TIRPC_DEBUG_FLAG_RPCSEC_GSS, "%s: rbtx_init failed", __func__); /* init read-through cache */ for (ix = 0; ix < __svc_params->gss.ctx_hash_partitions; ++ix) { struct rbtree_x_part *xp = &(authgss_hash_st.xt.tree[ix]); struct authgss_x_part *axp; xp->cache = mem_zalloc(authgss_hash_st.xt.cachesz * sizeof(struct opr_rbtree_node *)); if (unlikely(!xp->cache)) { __warnx(TIRPC_DEBUG_FLAG_RPCSEC_GSS, "%s: rbtx cache partition alloc failed", __func__); authgss_hash_st.xt.cachesz = 0; break; } /* partition ctx LRU */ axp = (struct authgss_x_part *) mem_alloc(sizeof(struct authgss_x_part)); TAILQ_INIT(&axp->lru_q); xp->u1 = axp; } authgss_hash_st.size = 0; authgss_hash_st.max_part = __svc_params->gss.max_gc / authgss_hash_st.xt.npart; authgss_hash_st.initialized = true; unlock: mutex_unlock(&authgss_hash_st.lock); } #define cond_init_authgss_hash() { \ do { \ if (!authgss_hash_st.initialized) \ authgss_hash_init(); \ } while (0); \ } struct svc_rpc_gss_data * authgss_ctx_hash_get(struct rpc_gss_cred *gc) { struct svc_rpc_gss_data gk, *gd = NULL; gss_union_ctx_id_desc *gss_ctx; struct opr_rbtree_node *ngd; struct authgss_x_part *axp; struct rbtree_x_part *t; cond_init_authgss_hash(); gss_ctx = (gss_union_ctx_id_desc *) (gc->gc_ctx.value); gk.hk.k = gss_ctx_hash(gss_ctx); t = rbtx_partition_of_scalar(&authgss_hash_st.xt, gk.hk.k); mutex_lock(&t->mtx); ngd = rbtree_x_cached_lookup(&authgss_hash_st.xt, t, &gk.node_k, gk.hk.k); if (ngd) { gd = opr_containerof(ngd, struct svc_rpc_gss_data, node_k); /* lru adjust */ axp = (struct authgss_x_part *)t->u1; TAILQ_REMOVE(&axp->lru_q, gd, lru_q); TAILQ_INSERT_TAIL(&axp->lru_q, gd, lru_q); ++(axp->gen); (void)atomic_inc_uint32_t(&gd->refcnt); (void)atomic_inc_uint32_t(&gd->gen); } mutex_unlock(&t->mtx); return (gd); } bool authgss_ctx_hash_set(struct svc_rpc_gss_data *gd) { struct rbtree_x_part *t; struct authgss_x_part *axp; gss_union_ctx_id_desc *gss_ctx; bool rslt; cond_init_authgss_hash(); gss_ctx = (gss_union_ctx_id_desc *) (gd->ctx); gd->hk.k = gss_ctx_hash(gss_ctx); ++(gd->refcnt); /* locked */ t = rbtx_partition_of_scalar(&authgss_hash_st.xt, gd->hk.k); mutex_lock(&t->mtx); rslt = rbtree_x_cached_insert(&authgss_hash_st.xt, t, &gd->node_k, gd->hk.k); /* lru */ axp = (struct authgss_x_part *)t->u1; TAILQ_INSERT_TAIL(&axp->lru_q, gd, lru_q); mutex_unlock(&t->mtx); /* global size */ (void)atomic_inc_uint32_t(&authgss_hash_st.size); return (rslt); } bool authgss_ctx_hash_del(struct svc_rpc_gss_data *gd) { struct rbtree_x_part *t; struct authgss_x_part *axp; cond_init_authgss_hash(); t = rbtx_partition_of_scalar(&authgss_hash_st.xt, gd->hk.k); mutex_lock(&t->mtx); rbtree_x_cached_remove(&authgss_hash_st.xt, t, &gd->node_k, gd->hk.k); axp = (struct authgss_x_part *)t->u1; TAILQ_REMOVE(&axp->lru_q, gd, lru_q); mutex_unlock(&t->mtx); /* global size */ (void)atomic_dec_uint32_t(&authgss_hash_st.size); /* release gd */ unref_svc_rpc_gss_data(gd, SVC_RPC_GSS_FLAG_NONE); return (true); } static inline bool authgss_ctx_expired(struct svc_rpc_gss_data *gd) { OM_uint32 maj_stat, min_stat; maj_stat = gss_inquire_context(&min_stat, gd->ctx, NULL, NULL, NULL, NULL, NULL, NULL, NULL); return (maj_stat == GSS_S_CONTEXT_EXPIRED); } static uint32_t idle_next; #define IDLE_NEXT() \ (atomic_inc_uint32_t(&(idle_next)) % authgss_hash_st.xt.npart) void authgss_ctx_gc_idle(void) { struct rbtree_x_part *xp; struct authgss_x_part *axp; struct svc_rpc_gss_data *gd; int ix, cnt, part; cond_init_authgss_hash(); for (ix = 0, part = IDLE_NEXT(); ix < authgss_hash_st.xt.npart; ++ix, part = IDLE_NEXT()) { xp = &(authgss_hash_st.xt.tree[part]); axp = (struct authgss_x_part *)xp->u1; cnt = 0; mutex_lock(&xp->mtx); again: gd = TAILQ_FIRST(&axp->lru_q); if (!gd) goto next_t; if (unlikely((authgss_hash_st.size > __svc_params->gss.max_gc) || ((abs(axp->gen - gd->gen) > __svc_params->gss.max_idle_gen)) || (authgss_ctx_expired(gd)))) { /* remove entry */ rbtree_x_cached_remove(&authgss_hash_st.xt, xp, &gd->node_k, gd->hk.k); TAILQ_REMOVE(&axp->lru_q, gd, lru_q); (void)atomic_dec_uint32_t(&authgss_hash_st.size); /* drop sentinel ref (may free gd) */ unref_svc_rpc_gss_data(gd, SVC_RPC_GSS_FLAG_NONE); if (++cnt < authgss_hash_st.max_part) goto again; } next_t: mutex_unlock(&xp->mtx); } /* perturb by 1 */ (void)IDLE_NEXT(); } ntirpc-1.3.1/src/authgss_prot.c000066400000000000000000000256231261345040100164740ustar00rootroot00000000000000/* authgss_prot.c Copyright (c) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (c) 2000 Dug Song . All rights reserved, all wrongs reversed. 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 University 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 ``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 REGENTS 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 #include #include #include #include #include #include #include #include #include #include /* additional space needed for encoding */ #define RPC_SLACK_SPACE 1024 #define AUTHGSS_MAX_TOKEN_SIZE 24576 /* default MS PAC is 12000 bytes */ bool xdr_rpc_gss_buf(XDR *xdrs, gss_buffer_t buf, u_int maxsize) { bool xdr_stat; u_int tmplen = 0; if (xdrs->x_op != XDR_DECODE) { if (buf->length > UINT_MAX) return FALSE; else tmplen = buf->length; } xdr_stat = inline_xdr_bytes(xdrs, (char **)&buf->value, &tmplen, maxsize); if (xdr_stat && xdrs->x_op == XDR_DECODE) buf->length = tmplen; log_debug("xdr_rpc_gss_buf: %s %s (%p:%d)", (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", (xdr_stat == TRUE) ? "success" : "failure", buf->value, buf->length); return xdr_stat; } bool xdr_rpc_gss_cred(XDR *xdrs, struct rpc_gss_cred *p) { bool xdr_stat; xdr_stat = (inline_xdr_u_int(xdrs, &p->gc_v) && inline_xdr_enum(xdrs, (enum_t *) &p->gc_proc) && inline_xdr_u_int(xdrs, &p->gc_seq) && inline_xdr_enum(xdrs, (enum_t *) &p->gc_svc) && xdr_rpc_gss_buf(xdrs, &p->gc_ctx, MAX_AUTH_BYTES)); log_debug("xdr_rpc_gss_cred: %s %s " "(v %d, proc %d, seq %d, svc %d, ctx %p:%d)", (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", (xdr_stat == TRUE) ? "success" : "failure", p->gc_v, p->gc_proc, p->gc_seq, p->gc_svc, p->gc_ctx.value, p->gc_ctx.length); return (xdr_stat); } bool xdr_rpc_gss_init_args(XDR *xdrs, gss_buffer_desc *p) { bool xdr_stat; u_int maxlen = AUTHGSS_MAX_TOKEN_SIZE; xdr_stat = xdr_rpc_gss_buf(xdrs, p, maxlen); log_debug("xdr_rpc_gss_init_args: %s %s (token %p:%d)", (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", (xdr_stat == TRUE) ? "success" : "failure", p->value, p->length); return (xdr_stat); } bool xdr_rpc_gss_init_res(XDR *xdrs, struct rpc_gss_init_res *p) { bool xdr_stat; u_int ctx_maxlen = (u_int) (p->gr_ctx.length + RPC_SLACK_SPACE); u_int tok_maxlen = (u_int) (p->gr_token.length + RPC_SLACK_SPACE); xdr_stat = (xdr_rpc_gss_buf(xdrs, &p->gr_ctx, ctx_maxlen) && inline_xdr_u_int(xdrs, &p->gr_major) && inline_xdr_u_int(xdrs, &p->gr_minor) && inline_xdr_u_int(xdrs, &p->gr_win) && xdr_rpc_gss_buf(xdrs, &p->gr_token, tok_maxlen)); log_debug("xdr_rpc_gss_init_res %s %s " "(ctx %p:%d, maj %d, min %d, win %d, token %p:%d)", (xdrs->x_op == XDR_ENCODE) ? "encode" : "decode", (xdr_stat == TRUE) ? "success" : "failure", p->gr_ctx.value, p->gr_ctx.length, p->gr_major, p->gr_minor, p->gr_win, p->gr_token.value, p->gr_token.length); return (xdr_stat); } bool xdr_rpc_gss_wrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_svc_t svc, u_int seq) { gss_buffer_desc databuf, wrapbuf; OM_uint32 maj_stat, min_stat; int start, end, conf_state; bool xdr_stat; u_int databuflen, maxwrapsz; /* Write dummy for databody length. */ start = XDR_GETPOS(xdrs); databuflen = 0xaaaaaaaa; /* should always overwrite */ if (!inline_xdr_u_int(xdrs, &databuflen)) return (FALSE); memset(&databuf, 0, sizeof(databuf)); memset(&wrapbuf, 0, sizeof(wrapbuf)); /* Marshal rpc_gss_data_t (sequence number + arguments). */ if (!inline_xdr_u_int(xdrs, &seq) || !(*xdr_func) (xdrs, xdr_ptr)) return (FALSE); end = XDR_GETPOS(xdrs); /* Set databuf to marshalled rpc_gss_data_t. */ databuflen = end - start - 4; if (!XDR_SETPOS(xdrs, start+4)) { log_debug("xdr_setpos#1 failed"); return (FALSE); } databuf.value = XDR_INLINE(xdrs, databuflen); databuf.length = databuflen; if (!databuf.value) { log_debug("XDR_INLINE failed"); return (FALSE); } xdr_stat = FALSE; if (svc == RPCSEC_GSS_SVC_INTEGRITY) { /* Marshal databody_integ length. */ if (!XDR_SETPOS(xdrs, start)) { log_debug("xdr_setpos#2 failed"); return (FALSE); } if (!inline_xdr_u_int(xdrs, &databuflen)) return (FALSE); /* Checksum rpc_gss_data_t. */ maj_stat = gss_get_mic(&min_stat, ctx, qop, &databuf, &wrapbuf); if (maj_stat != GSS_S_COMPLETE) { log_debug("gss_get_mic failed"); return (FALSE); } /* Marshal checksum. */ if (!XDR_SETPOS(xdrs, end)) { log_debug("xdr_setpos#3 failed"); gss_release_buffer(&min_stat, &wrapbuf); return (FALSE); } maxwrapsz = (u_int) (wrapbuf.length + RPC_SLACK_SPACE); xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz); gss_release_buffer(&min_stat, &wrapbuf); } else if (svc == RPCSEC_GSS_SVC_PRIVACY) { /* Encrypt rpc_gss_data_t. */ maj_stat = gss_wrap(&min_stat, ctx, TRUE, qop, &databuf, &conf_state, &wrapbuf); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_wrap", maj_stat, min_stat); return (FALSE); } /* Marshal databody_priv. */ if (!XDR_SETPOS(xdrs, start)) { log_debug("xdr_setpos#4 failed"); gss_release_buffer(&min_stat, &wrapbuf); return (FALSE); } maxwrapsz = (u_int) (wrapbuf.length + RPC_SLACK_SPACE); xdr_stat = xdr_rpc_gss_buf(xdrs, &wrapbuf, maxwrapsz); gss_release_buffer(&min_stat, &wrapbuf); } if (!xdr_stat) { log_debug("xdr_rpc_gss_wrap_data failed"); } return (xdr_stat); } bool xdr_rpc_gss_unwrap_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_svc_t svc, u_int seq) { XDR tmpxdrs; gss_buffer_desc databuf, wrapbuf; OM_uint32 maj_stat, min_stat; u_int seq_num, qop_state; int conf_state; bool xdr_stat; if (xdr_func == (xdrproc_t) xdr_void || xdr_ptr == NULL) return (TRUE); memset(&databuf, 0, sizeof(databuf)); memset(&wrapbuf, 0, sizeof(wrapbuf)); if (svc == RPCSEC_GSS_SVC_INTEGRITY) { /* Decode databody_integ. */ if (!xdr_rpc_gss_buf(xdrs, &databuf, (u_int) -1)) { log_debug("xdr decode databody_integ failed"); return (FALSE); } /* Decode checksum. */ if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int) -1)) { gss_release_buffer(&min_stat, &databuf); log_debug("xdr decode checksum failed"); return (FALSE); } /* Verify checksum and QOP. */ maj_stat = gss_verify_mic(&min_stat, ctx, &databuf, &wrapbuf, &qop_state); gss_release_buffer(&min_stat, &wrapbuf); if (maj_stat != GSS_S_COMPLETE || qop_state != qop) { gss_release_buffer(&min_stat, &databuf); log_status("gss_verify_mic", maj_stat, min_stat); return (FALSE); } } else if (svc == RPCSEC_GSS_SVC_PRIVACY) { /* Decode databody_priv. */ if (!xdr_rpc_gss_buf(xdrs, &wrapbuf, (u_int) -1)) { log_debug("xdr decode databody_priv failed"); return (FALSE); } /* Decrypt databody. */ maj_stat = gss_unwrap(&min_stat, ctx, &wrapbuf, &databuf, &conf_state, &qop_state); gss_release_buffer(&min_stat, &wrapbuf); /* Verify encryption and QOP. */ if (maj_stat != GSS_S_COMPLETE || qop_state != qop || conf_state != TRUE) { gss_release_buffer(&min_stat, &databuf); log_status("gss_unwrap", maj_stat, min_stat); return (FALSE); } } /* Decode rpc_gss_data_t (sequence number + arguments). */ xdrmem_create(&tmpxdrs, databuf.value, databuf.length, XDR_DECODE); xdr_stat = (xdr_u_int(&tmpxdrs, &seq_num) && (*xdr_func) (&tmpxdrs, xdr_ptr)); XDR_DESTROY(&tmpxdrs); gss_release_buffer(&min_stat, &databuf); /* Verify sequence number. */ if (xdr_stat == TRUE && seq_num != seq) { log_debug("wrong sequence number in databody"); return (FALSE); } return (xdr_stat); } bool xdr_rpc_gss_data(XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr, gss_ctx_id_t ctx, gss_qop_t qop, rpc_gss_svc_t svc, u_int seq) { switch (xdrs->x_op) { case XDR_ENCODE: return (xdr_rpc_gss_wrap_data (xdrs, xdr_func, xdr_ptr, ctx, qop, svc, seq)); case XDR_DECODE: return (xdr_rpc_gss_unwrap_data (xdrs, xdr_func, xdr_ptr, ctx, qop, svc, seq)); case XDR_FREE: return (TRUE); } return (FALSE); } #ifdef DEBUG #include #define log_debug __warnx #if 0 void log_debug(const char *fmt, ...) { va_list ap; va_start(ap, fmt); fprintf(stderr, "rpcsec_gss: "); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); } #endif void log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) { OM_uint32 min; gss_buffer_desc msg; int msg_ctx = 0; __warnx("rpcsec_gss: %s: ", m); gss_display_status(&min, maj_stat, GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &msg); __warnx("%s - ", (char *)msg.value); gss_release_buffer(&min, &msg); gss_display_status(&min, min_stat, GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &msg); __warnx("%s\n", (char *)msg.value); gss_release_buffer(&min, &msg); } void gss_log_hexdump(const u_char *buf, int len, int offset) { u_int i, j, jm; int c; __warnx("\n"); for (i = 0; i < len; i += 0x10) { __warnx(" %04x: ", (u_int) (i + offset)); jm = len - i; jm = jm > 16 ? 16 : jm; for (j = 0; j < jm; j++) { if ((j % 2) == 1) __warnx("%02x ", (u_int) buf[i + j]); else __warnx("%02x", (u_int) buf[i + j]); } for (; j < 16; j++) { if ((j % 2) == 1) printf(" "); else __warnx(" "); } __warnx(" "); for (j = 0; j < jm; j++) { c = buf[i + j]; c = isprint(c) ? c : '.'; __warnx("%c", c); } __warnx("\n"); } } #else void log_debug(const char *fmt, ...) { } void log_status(char *m, OM_uint32 maj_stat, OM_uint32 min_stat) { } void loggss__hexdump(const u_char *buf, int len, int offset) { } #endif ntirpc-1.3.1/src/authunix_prot.c000066400000000000000000000045351261345040100166620ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * authunix_prot.c * XDR for UNIX style authentication parameters for RPC * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include /* * XDR for unix authentication parameters. */ bool xdr_authunix_parms(XDR *xdrs, struct authunix_parms *p) { assert(xdrs != NULL); assert(p != NULL); if (inline_xdr_u_long(xdrs, &(p->aup_time)) && inline_xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME) && inline_xdr_u_int(xdrs, &(p->aup_uid)) && inline_xdr_u_int(xdrs, &(p->aup_gid)) && xdr_array(xdrs, (caddr_t *) &(p->aup_gids), &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t) xdr_int)) { return (true); } return (false); } ntirpc-1.3.1/src/bindresvport.c000066400000000000000000000126361261345040100164730ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * Copyright (c) 1987 by Sun Microsystems, Inc. * * Portions Copyright(C) 1996, Jason Downs. All rights reserved. */ #include #include #include #include #include #include #include #include /* * Bind a socket to a privileged IP port */ int bindresvport(int sd, struct sockaddr_in *sin) { return bindresvport_sa(sd, (struct sockaddr *)sin); } #ifdef __linux__ #define STARTPORT 600 #define LOWPORT 512 #define ENDPORT (IPPORT_RESERVED - 1) #define NPORTS (ENDPORT - STARTPORT + 1) int bindresvport_sa(int sd, struct sockaddr *sa) { int res, af; struct sockaddr_storage myaddr; struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif u_int16_t *portp; static u_int16_t port; static short startport = STARTPORT; socklen_t salen; int nports = ENDPORT - startport + 1; int endport = ENDPORT; int i; if (sa == NULL) { salen = sizeof(myaddr); sa = (struct sockaddr *)&myaddr; if (getsockname(sd, (struct sockaddr *)&myaddr, &salen) == -1) return -1; /* errno is correctly set */ af = myaddr.ss_family; } else af = sa->sa_family; switch (af) { case AF_INET: sin = (struct sockaddr_in *)sa; salen = sizeof(struct sockaddr_in); port = ntohs(sin->sin_port); portp = &sin->sin_port; break; #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)sa; salen = sizeof(struct sockaddr_in6); port = ntohs(sin6->sin6_port); portp = &sin6->sin6_port; break; #endif default: errno = EPFNOSUPPORT; return (-1); } sa->sa_family = af; if (port == 0) port = (getpid() % NPORTS) + STARTPORT; res = -1; errno = EADDRINUSE; again: for (i = 0; i < nports; ++i) { *portp = htons(port++); if (port > endport) port = startport; res = bind(sd, sa, salen); if (res >= 0 || errno != EADDRINUSE) break; } if (i == nports && startport != LOWPORT) { startport = LOWPORT; endport = STARTPORT - 1; nports = STARTPORT - LOWPORT; port = LOWPORT + port % (STARTPORT - LOWPORT); goto again; } return (res); } #else #define IP_PORTRANGE 19 #define IP_PORTRANGE_LOW 2 /* * Bind a socket to a privileged IP port */ int bindresvport_sa(int sd, struct sockaddr *sa) { int old, error, af; struct sockaddr_storage myaddr; struct sockaddr_in *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif int proto, portrange, portlow; u_int16_t *portp; socklen_t salen; if (sa == NULL) { salen = sizeof(myaddr); sa = (struct sockaddr *)&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; sin = (struct sockaddr_in *)sa; salen = sizeof(struct sockaddr_in); portp = &sin->sin_port; break; #ifdef INET6 case AF_INET6: proto = IPPROTO_IPV6; portrange = IPV6_PORTRANGE; portlow = IPV6_PORTRANGE_LOW; sin6 = (struct sockaddr_in6 *)sa; salen = sizeof(struct sockaddr_in6); portp = &sin6->sin6_port; break; #endif default: errno = EPFNOSUPPORT; return (-1); } sa->sa_family = af; 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 *)&myaddr) { /* Hmm, what did the kernel assign? */ if (getsockname(sd, sa, &salen) < 0) errno = saved_errno; return (error); } } return (error); } #endif ntirpc-1.3.1/src/bsd_epoll.c000066400000000000000000000143261261345040100157130ustar00rootroot00000000000000/* * bsd_epoll.c - Linux epoll.h emulation via kevent API * * Copyright (c) 2009 Boaz Harrosh * All rights reserved. * * Inspired by code written by Roman Divacky * from the freebsd's linux emulation project at linux_epoll.c file * However none of that code ended up here. * * description: * This file implements a workable set of the header file * on a linux distribution. The implementation translates back and forth from * epoll calls and constants to Kevent calls and constants. * * This file is copyrighted under the "New BSD License" (see below) so it can * be included in the tirpc library project. * But I fully expect that if you make any fixes/enhancements to bsd_epoll.c * you shall send these changes to me for inclusion in the next version. * (Or I'll hunt your dreams, and you will not have peace) * * License: "New BSD License" * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * Neither the name of the nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #if defined(__FreeBSD__) #include #include #include #include #include #include #include #include /* Create a new epoll file descriptor. */ int epoll_create(int size) { if (size <= 0) return -EINVAL; /* * args->size is unused. Linux just tests it * and then forgets it as well. */ return kqueue(); } static void kevent_to_epoll(struct kevent *kevent, struct epoll_event *event) { /* if (kevent->flags & EV_ERROR) { ... Any special event flags on Errors? } */ memset(event, 0, sizeof(*event)); switch (kevent->filter) { case EVFILT_READ: /* in Linux EPOLLIN with Zero Data will signal a close * condition. So do that if EV_EOF. */ if ((kevent->data > 0) || (kevent->flags & EV_EOF)) event->events = EPOLLIN; break; case EVFILT_WRITE: if (kevent->data > 0) event->events = EPOLLOUT; break; default: fprintf(stderr, "Unsupported kevent_to_epoll event=%d" " data=%lx flags=0x%x ident=%ld fflags=0x%x\n", kevent->filter, (long)kevent->data, kevent->flags, (long)kevent->ident, kevent->fflags); } event->data.ptr = kevent->udata; } static void kevent_to_epoll_arr(struct kevent *kevp, int count, struct epoll_event *eep) { int i; for (i = 0; i < count; i++) { kevent_to_epoll(&kevp[i], &eep[i]); /*printf("eep[%d]=%p\n", i, eep[i].data.ptr); */ } } /* * Always create two filters An EVFILT_READ and an EVFILT_WRITE. * EV_ENABLE/EV_DISABLE according to epoll flags. On EPOLL_CTL_MOD * first delete then add a new. On EPOLL_CTL_DEL remove both. */ int epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) { struct kevent kev[2] = { {.flags = 0}, }; int read_flags, write_flags; switch (op) { case EPOLL_CTL_MOD: epoll_ctl(epfd, EPOLL_CTL_DEL, fd, event); /* fall through */ case EPOLL_CTL_ADD: { int flags; if ((event->events & EPOLLIN) || event->events & EPOLLPRI) read_flags = EV_ENABLE; else read_flags = EV_DISABLE; if (event->events & EPOLLOUT) write_flags = EV_ENABLE; else write_flags = EV_DISABLE; flags = EV_ADD; if (event->events & EPOLLET) flags |= EV_CLEAR; if (event->events & EPOLLONESHOT) flags |= EV_ONESHOT; read_flags |= flags; write_flags |= flags; /* printf("%s(fd=%d data.ptr=%p\n", op == EPOLL_CTL_MOD ? "EPOLL_CTL_MOD" : "EPOLL_CTL_ADD", fd ,event->data.ptr); printf(" EVFILT_READ(on=%d read_flags=0x%x\n", read_flags & EV_ENABLE, read_flags); printf(" EVFILT_WRITE(on=%d write_flags=0x%x);\n", write_flags & EV_ENABLE, write_flags);*/ } break; case EPOLL_CTL_DEL: read_flags = write_flags = EV_DELETE | EV_DISABLE; /*printf("EPOLL_CTL_DEL(fd=%d\n",fd); */ break; default: fprintf(stderr, "Unsupported epoll operation=%d" " epfd=%d, fd=%d events=%x\n", op, epfd, fd, event->events); errno = EINVAL; return -1; } EV_SET(&kev[0], fd, EVFILT_READ, read_flags, 0, 0, event ? event->data.ptr : 0); EV_SET(&kev[1], fd, EVFILT_WRITE, write_flags, 0, 0, event ? event->data.ptr : 0); return kevent(epfd, kev, 2, NULL, 0, NULL); } /* * Wait for a filter to be triggered on the epoll file descriptor. */ int epoll_wait(int epfd, struct epoll_event *events, int maxevents, int timeout) { struct kevent *kevp; struct timespec ts; int rc; /* Convert from miliseconds to timespec. */ ts.tv_sec = timeout / 1000000; ts.tv_nsec = (timeout % 1000000) * 1000; kevp = calloc(maxevents, sizeof(*kevp)); /* * ENOMEM is not expected from epoll_wait. * Maybe we should translate that but I don't think it matters at all. */ if (!kevp) return -ENOMEM; rc = kevent(epfd, NULL, 0, kevp, maxevents, &ts); if (rc > 0) { /*printf("epoll_wait LEAVE %d\n", rc); */ kevent_to_epoll_arr(kevp, rc, events); } free(kevp); return rc; } #endif /* __FreeBSD__ */ ntirpc-1.3.1/src/city-test.c000066400000000000000000003154701261345040100157010ustar00rootroot00000000000000/* city-test.c - cityhash-c * CityHash on C * Copyright (c) 2011-2012, Alexander Nusov * * - original copyright notice - * Copyright (c) 2011 Google, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ #include #include #include "city.h" #ifdef __SSE4_2__ #include "citycrc.h" #endif static const uint64 k0 = 0xc3a5c85c97cb3127ULL; static const uint64 kSeed0 = 1234567; static const uint64 kSeed1 = 0xc3a5c85c97cb3127ULL; static const uint128 kSeed128 = { 1234567, 0xc3a5c85c97cb3127ULL }; static const int kDataSize = 1 << 20; static const int kTestSize = 300; static char data[1 << 20]; static int errors; /* global error count */ /* Initialize data to pseudorandom values. */ void setup() { uint64 a = 9; uint64 b = 777; int i; for (i = 0; i < kDataSize; i++) { a = (a ^ (a >> 41)) * k0 + b; b = (b ^ (b >> 41)) * k0 + i; uint8 u = b >> 37; memcpy(data + i, &u, 1); /* uint8 -> char */ } } #define C(x) (0x ## x ## ULL) static const uint64 testdata[300][15] = { {C(9 ae16a3b2f90404f), C(75106 db890237a4a), C(3f eac5f636039766), C(3 df09dfc64c09a2b), C(3 cb540c392e51e29), C(6 b56343feac0663), C(5 b7bc50fd8e8ad92), C(3 df09dfc64c09a2b), C(3 cb540c392e51e29), C(6 b56343feac0663), C(5 b7bc50fd8e8ad92), C(889f 555 a0f5b2dc0), C(7767800902 c8a8ce), C(bcd2a808f4cb4a44), C(e9024dba8f94f2f3)}, {C(75e9 dee28ded761d), C(931992 c1b14334c5), C(245ee b25ba2c172e), C(1290f 0e8 a5caa74d), C(ca4c6bf7583f5cda), C(e1d60d51632c536d), C(cbc54a1db641910a), C(1290f 0e8 a5caa74d), C(ca4c6bf7583f5cda), C(e1d60d51632c536d), C(cbc54a1db641910a), C(9866 d68d17c2c08e), C(8 d84ba63eb4d020a), C(df0ad99c78cbce44), C(7 c98593ef62573ed)}, {C(75 de892fdc5ba914), C(f89832e71f764c86), C(39 a82df1f278a297), C(b4af8ae673acb930), C(992 b7acb203d8885), C(57 b533f3f8b94d50), C(bbb69298a5dcf1a1), C(b4af8ae673acb930), C(992 b7acb203d8885), C(57 b533f3f8b94d50), C(bbb69298a5dcf1a1), C(433495196 af9ac4f), C(53445 c0896ae1fe6), C(f7b939315f6fb56f), C(ac1b05e5a2e0335e)}, {C(69 cfe9fca1cc683a), C(e65f2a81e19b8067), C(20575ea6370 a9d14), C(8f 52532f c6f005b7), C(4eb e60df371ec129), C(c6ef8a7f8deb8116), C(83 df17e3c9bb9a67), C(8f 52532f c6f005b7), C(4eb e60df371ec129), C(c6ef8a7f8deb8116), C(83 df17e3c9bb9a67), C(6 a0aaf51016e19cd), C(fb0d1e89f39dbf6a), C(c73095102872943a), C(405ea97456 c28a75)}, {C(675 b04c582a34966), C(53624 b5ef8cd4f45), C(c412e0931ac8c9b1), C(798637e677 c65a3), C(83e3 b06adc4cd3ff), C(f3e76e8a7135852f), C(111e66 cfbb05366d), C(798637e677 c65a3), C(83e3 b06adc4cd3ff), C(f3e76e8a7135852f), C(111e66 cfbb05366d), C(29 c4f84aa48e8682), C(b77a8685750c94d0), C(7 cab65571969123f), C(fb1dbd79f68a8519)}, {C(46f a817397ea8b68), C(cc960c1c15ce2d20), C(e5f9f947bafb9e79), C(b342cdf0d7ac4b2a), C(66914 d44b373b232), C(261194e76 cb43966), C(45 a0010190365048), C(b342cdf0d7ac4b2a), C(66914 d44b373b232), C(261194e76 cb43966), C(45 a0010190365048), C(e2586947ca8eac83), C(6650 daf2d9677cdc), C(2f 9533 d8f4951a9), C(a5bdc0f3edc4bd7b)}, {C(406e959 cdffadec7), C(e80dc125dca28ed1), C(e5beb146d4b79a21), C(e66d5c1bb441541a), C(d14961bc1fd265a2), C(e4cc669d4fc0577f), C(abf4a51e36da2702), C(e66d5c1bb441541a), C(d14961bc1fd265a2), C(e4cc669d4fc0577f), C(abf4a51e36da2702), C(21236 d12df338f75), C(54 b8c4a5ad2ae4a4), C(202 d50ef9c2d4465), C(5ec c6a128e51a797)}, {C(46663908 b4169b95), C(4e7 e90b5c426bf1d), C(dc660b58daaf8b2c), C(b298265ebd1bd55f), C(4 a5f6838b55c0b08), C(fc003c97aa05d397), C(2f b5adad3380c3bc), C(b298265ebd1bd55f), C(4 a5f6838b55c0b08), C(fc003c97aa05d397), C(2f b5adad3380c3bc), C(c46fd01d253b4a0b), C(4 c799235c2a33188), C(7e21 bc57487a11bf), C(e1392bb1994bd4f2)}, {C(f214b86cffeab596), C(5f ccb0b132da564f), C(86e7 aa8b4154b883), C(763529 c8d4189ea8), C(860 d77e7fef74ca3), C(3 b1ba41191219b6b), C(722 b25dfa6d0a04b), C(763529 c8d4189ea8), C(860 d77e7fef74ca3), C(3 b1ba41191219b6b), C(722 b25dfa6d0a04b), C(5f 7 b463094e22a91), C(75 d6f57376b31bd7), C(d253c7f89efec8e6), C(efe56ac880a2b8a3)}, {C(eba670441d1a4f7d), C(eb6b272502d975fa), C(69f 8 d424d50c083e), C(313 d49cb51b8cd2c), C(6e982 d8b4658654a), C(dd59629a17e5492d), C(81 cb23bdab95e30e), C(313 d49cb51b8cd2c), C(6e982 d8b4658654a), C(dd59629a17e5492d), C(81 cb23bdab95e30e), C(1e6 c3e6c454c774f), C(177655172666 d5ea), C(9 cc67e0d38d80886), C(36 a2d64d7bc58d22)}, {C(172 c17ff21dbf88d), C(1f 5104e320f 0 c815), C(1e34 e9f1fa63bcef), C(3506 ae8fae368d2a), C(59f a2b2de5306203), C(67 d1119dcfa6007e), C(1f 7190 c648ad9aef), C(3506 ae8fae368d2a), C(59f a2b2de5306203), C(67 d1119dcfa6007e), C(1f 7190 c648ad9aef), C(7e8 b1e689137b637), C(cbe373368a31db3c), C(dbc79d82cd49c671), C(641399520 c452c99)}, {C(5 a0838df8a019b8c), C(73f c859b4952923), C(45e39 daf153491bd), C(a9b91459a5fada46), C(de0fbf8800a2da3), C(21800e4 b5af9dedb), C(517 c3726ae0dbae7), C(a9b91459a5fada46), C(de0fbf8800a2da3), C(21800e4 b5af9dedb), C(517 c3726ae0dbae7), C(1 ccffbd74acf9d66), C(cbb08cf95e7eda99), C(61444f 09e2 a29587), C(35 c0d15745f96455)}, {C(8f 42 b1fbb2fc0302), C(5 ae31626076ab6ca), C(b87f0cb67cb75d28), C(2498586 ac2e1fab2), C(e683f9cbea22809a), C(a9728d0b2bbe377c), C(46 baf5cae53dc39a), C(2498586 ac2e1fab2), C(e683f9cbea22809a), C(a9728d0b2bbe377c), C(46 baf5cae53dc39a), C(806f 4352 c99229e), C(d4643728fc71754a), C(998 c1647976bc893), C(d8094fdc2d6bb032)}, {C(72085e82 d70dcea9), C(32f 502 c43349ba16), C(5eb c98c3645a018f), C(c7fa762238fd90ac), C(8 d03b5652d615677), C(a3f5226e51d42217), C(46 d5010a7cae8c1e), C(c7fa762238fd90ac), C(8 d03b5652d615677), C(a3f5226e51d42217), C(46 d5010a7cae8c1e), C(4293122580 db7f5f), C(3 df6042f39c6d487), C(439124809 cf5c90e), C(90 b704e4f71d0ccf)}, {C(32 b75fc2223b5032), C(246f ff80eb230868), C(a6fdbc82c9aeecc0), C(c089498074167021), C(ab094a9f9ab81c23), C(4f acf3d9466bcb03), C(57 aa9c67938cf3eb), C(c089498074167021), C(ab094a9f9ab81c23), C(4f acf3d9466bcb03), C(57 aa9c67938cf3eb), C(79 a769ca1c762117), C(9 c8dee60337f87a8), C(dabf1b96535a3abb), C(f87e9fbb590ba446)}, {C(e1dd010487d2d647), C(12352858295 d2167), C(acc5e9b6f6b02dbb), C(1 c66ceea473413df), C(dc3f70a124b25a40), C(66 a6dfe54c441cd8), C(b436dabdaaa37121), C(1 c66ceea473413df), C(dc3f70a124b25a40), C(66 a6dfe54c441cd8), C(b436dabdaaa37121), C(6 d95aa6890f51674), C(42 c6c0fc7ab3c107), C(83 b9dfe082e76140), C(939 cdbd3614d6416)}, {C(2994f 9245194 a7e2), C(b7cd7249d6db6c0c), C(2170 a7d119c5c6c3), C(8505 c996b70ee9fc), C(b92bba6b5d778eb7), C(4 db4c57f3a7a4aee), C(3 cfd441cb222d06f), C(8505 c996b70ee9fc), C(b92bba6b5d778eb7), C(4 db4c57f3a7a4aee), C(3 cfd441cb222d06f), C(4 d940313c96ac6bd), C(43762837 c9ffac4b), C(480f cf58920722e3), C(4 bbd1e1a1d06752f)}, {C(32e2 ed6fa03e5b22), C(58 baf09d7c71c62b), C(a9c599f3f8f50b5b), C(1660 a2c4972d0fa1), C(1 a1538d6b50a57c), C(8 a5362485bbc9363), C(e8eec3c84fd9f2f8), C(1660 a2c4972d0fa1), C(1 a1538d6b50a57c), C(8 a5362485bbc9363), C(e8eec3c84fd9f2f8), C(2562514461 d373da), C(33857675f ed52b4), C(e58d2a17057f1943), C(fe7d3f30820e4925)}, {C(37 a72b6e89410c9f), C(139f ec53b78cee23), C(4f ccd8f0da7575c3), C(3 a5f04166518ac75), C(f49afe05a44fc090), C(cb01b4713cfda4bd), C(9027 bd37ffc0a5de), C(3 a5f04166518ac75), C(f49afe05a44fc090), C(cb01b4713cfda4bd), C(9027 bd37ffc0a5de), C(e15144d3ad46ec1b), C(736f d99679a5ae78), C(b3d7ed9ed0ddfe57), C(cef60639457867d7)}, {C(10836563 cb8ff3a1), C(d36f67e2dfc085f7), C(edc1bb6a3dcba8df), C(bd4f3a0566df3bed), C(81f c8230c163dcbe), C(4168 bc8417a8281b), C(7100 c9459827c6a6), C(bd4f3a0566df3bed), C(81f c8230c163dcbe), C(4168 bc8417a8281b), C(7100 c9459827c6a6), C(21 cad59eaf79e72f), C(61 c8af6fb71469f3), C(b0dfc42ce4f578b), C(33ea34 ccea305d4e)}, {C(4 dabcb5c1d382e5c), C(9 a868c608088b7a4), C(7 b2b6c389b943be5), C(c914b925ab69fda0), C(6 bafe864647c94d7), C(7 a48682dd4afa22), C(40f e01210176ba10), C(c914b925ab69fda0), C(6 bafe864647c94d7), C(7 a48682dd4afa22), C(40f e01210176ba10), C(88 dd28f33ec31388), C(c6db60abf1d45381), C(7 b94c447298824d5), C(6 b2a5e05ad0b9fc0)}, {C(296 afb509046d945), C(c38fe9eb796bd4be), C(d7b17535df110279), C(dd2482b87d1ade07), C(662785 d2e3e78ddf), C(eae39994375181bb), C(9994500 c077ee1db), C(dd2482b87d1ade07), C(662785 d2e3e78ddf), C(eae39994375181bb), C(9994500 c077ee1db), C(a275489f8c6bb289), C(30695ea31 df1a369), C(1 aeeb31802d701b5), C(7799 d5a6d5632838)}, {C(f7c0257efde772ea), C(af6af9977ecf7bff), C(1 cdff4bd07e8d973), C(fab1f4acd2cd4ab4), C(b4e19ba52b566bd), C(7f 1 db45725fe2881), C(70276f f8763f8396), C(fab1f4acd2cd4ab4), C(b4e19ba52b566bd), C(7f 1 db45725fe2881), C(70276f f8763f8396), C(1 b0f2b546dddd16b), C(aa066984b5fd5144), C(7 c3f9386c596a5a8), C(e5befdb24b665d5f)}, {C(61e021 c8da344ba1), C(cf9c720676244755), C(354f fa8e9d3601f6), C(44e40 a03093fbd92), C(bda9481cc5b93cae), C(986 b589cbc0cf617), C(210f 59f 074044831), C(44e40 a03093fbd92), C(bda9481cc5b93cae), C(986 b589cbc0cf617), C(210f 59f 074044831), C(ac32cbbb6f50245a), C(afa6f712efb22075), C(47289f 7 af581719f), C(31 b6e75d3aa0e54b)}, {C(c0a86ed83908560b), C(440 c8b6f97bd1749), C(a99bf2891726ea93), C(ac0c0b84df66df9d), C(3ee2337 b437eb264), C(8 a341daed9a25f98), C(cc665499aa38c78c), C(ac0c0b84df66df9d), C(3ee2337 b437eb264), C(8 a341daed9a25f98), C(cc665499aa38c78c), C(af7275299d79a727), C(874f a8434b45d0e), C(ca7b67388950dd33), C(2 db5cd3675ec58f7)}, {C(35 c9cf87e4accbf3), C(2267eb4 d2191b2a3), C(80217695666 b2c9), C(cd43a24abbaae6d), C(a88abf0ea1b2a8ff), C(e297ff01427e2a9d), C(935 d545695b2b41d), C(cd43a24abbaae6d), C(a88abf0ea1b2a8ff), C(e297ff01427e2a9d), C(935 d545695b2b41d), C(6 accd4dbcb52e849), C(261295 acb662fd49), C(f9d91f1ac269a8a2), C(5e45f 39 df355e395)}, {C(e74c366b3091e275), C(522e657 c5da94b06), C(ca9afa806f1a54ac), C(b545042f67929471), C(90 d10e75ed0e75d8), C(3ea60f 8f 158 df77e), C(8863eff 3 c2d670b7), C(b545042f67929471), C(90 d10e75ed0e75d8), C(3ea60f 8f 158 df77e), C(8863eff 3 c2d670b7), C(5799296e97f 144 a7), C(1 d6e517c12a88271), C(da579e9e1add90ef), C(942f b4cdbc3a4da)}, {C(a3f2ca45089ad1a6), C(13f 6270f e56fbce4), C(1f 93 a534bf03e705), C(aaea14288ae2d90c), C(1 be3cd51ef0f15e8), C(e8b47c84d5a4aac1), C(297 d27d55b766782), C(aaea14288ae2d90c), C(1 be3cd51ef0f15e8), C(e8b47c84d5a4aac1), C(297 d27d55b766782), C(e922d1d8bb2afd0), C(b4481c4fa2e7d8d5), C(691e21538 af794d5), C(9 bd4fb0a53962a72)}, {C(e5181466d8e60e26), C(cf31f3a2d582c4f3), C(d9cee87cb71f75b2), C(4750 ca6050a2d726), C(d6e6dd8940256849), C(f3b3749fdab75b0), C(c55d8a0f85ba0ccf), C(4750 ca6050a2d726), C(d6e6dd8940256849), C(f3b3749fdab75b0), C(c55d8a0f85ba0ccf), C(47f 134f 9544 c6da6), C(e1cdd9cb74ad764), C(3 ce2d096d844941e), C(321f e62f608d2d4e)}, {C(fb528a8dd1e48ad7), C(98 c4fd149c8a63dd), C(4 abd8fc3377ae1f), C(d7a9304abbb47cc5), C(7f 2 b9a27aa57f99), C(353 ab332d4ef9f18), C(47 d56b8d6c8cf578), C(d7a9304abbb47cc5), C(7f 2 b9a27aa57f99), C(353 ab332d4ef9f18), C(47 d56b8d6c8cf578), C(df55f58ae09f311f), C(dba9511784fa86e3), C(c43ce0288858a47e), C(62971e94270 b78e1)}, {C(da6d2b7ea9d5f9b6), C(57 b11153ee3b4cc8), C(7 d3bd1256037142f), C(90 b16ff331b719b5), C(fc294e7ad39e01e6), C(d2145386bab41623), C(7045 a63d44d76011), C(90 b16ff331b719b5), C(fc294e7ad39e01e6), C(d2145386bab41623), C(7045 a63d44d76011), C(a232222ed0fe2fa4), C(e6c17dff6c323a8a), C(bbcb079be123ac6c), C(4121f e2c5de7d850)}, {C(61 d95225bc2293e), C(f6c52cb6be9889a8), C(91 a0667a7ed6a113), C(441133 d221486a3d), C(fb9c5a40e19515b), C(6 c967b6c69367c2d), C(145 bd9ef258c4099), C(441133 d221486a3d), C(fb9c5a40e19515b), C(6 c967b6c69367c2d), C(145 bd9ef258c4099), C(a0197657160c686e), C(91 ada0871c23f379), C(2f d74fceccb5c80c), C(bf04f24e2dc17913)}, {C(81247 c01ab6a9cc1), C(fbccea953e810636), C(ae18965000c31be0), C(15 bb46383daec2a5), C(716294063 b4ba089), C(f3bd691ce02c3014), C(14 ccaad685a20764), C(15 bb46383daec2a5), C(716294063 b4ba089), C(f3bd691ce02c3014), C(14 ccaad685a20764), C(5 db25914279d6f24), C(25 c451fce3b2ed06), C(e6bacb43ba1ddb9a), C(6 d77493a2e6fd76)}, {C(c17f3ebd3257cb8b), C(e9e68c939c118c8d), C(72 a5572be35bfc1b), C(f6916c341cb31f2a), C(591 da1353ee5f31c), C(f1313c98a836b407), C(e0b8473eada48cd1), C(f6916c341cb31f2a), C(591 da1353ee5f31c), C(f1313c98a836b407), C(e0b8473eada48cd1), C(ac5c2fb40b09ba46), C(3 a3e8a9344eb6548), C(3 bf9349a9d8483a6), C(c30dd0d9b15e92d0)}, {C(9802438969 c3043b), C(6 cd07575c948dd82), C(83e26 b6830ea8640), C(d52f1fa190576961), C(11 d182e4f0d419cc), C(5 d9ccf1b56617424), C(c8a16debb585e452), C(d52f1fa190576961), C(11 d182e4f0d419cc), C(5 d9ccf1b56617424), C(c8a16debb585e452), C(2158 a752d2686d40), C(b93c1fdf54789e8c), C(3 a9a435627b2a30b), C(de6e5e551e7e5ad5)}, {C(3 dd8ed248a03d754), C(d8c1fcf001cb62e0), C(87 a822141ed64927), C(4 bfaf6fd26271f47), C(aefeae8222ad3c77), C(cfb7b24351a60585), C(8678904e9 e890b8f), C(4 bfaf6fd26271f47), C(aefeae8222ad3c77), C(cfb7b24351a60585), C(8678904e9 e890b8f), C(968 dd1aa4d7dcf31), C(7 ac643b015007a39), C(d1e1bac3d94406ec), C(babfa52474a404fa)}, {C(c5bf48d7d3e9a5a3), C(8f 0249 b5c5996341), C(c6d2c8a606f45125), C(fd1779db740e2c48), C(1950ef50f efab3f8), C(e4536426a6196809), C(699556 c502a01a6a), C(fd1779db740e2c48), C(1950ef50f efab3f8), C(e4536426a6196809), C(699556 c502a01a6a), C(2f 49 d268bb57b946), C(b205baa6c66ebfa5), C(ab91ebe4f48b0da1), C(c7e0718ccc360328)}, {C(bc4a21d00cf52288), C(28 df3eb5a533fa87), C(6081 bbc2a18dd0d), C(8ee d355d219e58b9), C(2 d7b9f1a3d645165), C(5758 d1aa8d85f7b2), C(9 c90c65920041dff), C(8ee d355d219e58b9), C(2 d7b9f1a3d645165), C(5758 d1aa8d85f7b2), C(9 c90c65920041dff), C(3 c5c4ea46645c7f1), C(346879ec c0e2eb90), C(8434f ec461bb5a0f), C(783 ccede50ef5ce9)}, {C(172 c8674913ff413), C(1815 a22400e832bf), C(7e011f 9467 a06650), C(161 be43353a31dd0), C(79 a8afddb0642ac3), C(df43af54e3e16709), C(6e12553 a75b43f07), C(161 be43353a31dd0), C(79 a8afddb0642ac3), C(df43af54e3e16709), C(6e12553 a75b43f07), C(3 ac1b1121e87d023), C(2 d47d33df7b9b027), C(e2d3f71f4e817ff5), C(70 b3a11ca85f8a39)}, {C(17 a361dbdaaa7294), C(c67d368223a3b83c), C(f49cf8d51ab583d2), C(666eb21 e2eaa596), C(778f 3e1 b6650d56), C(3f 6 be451a668fe2d), C(5452892 b0b101388), C(666eb21 e2eaa596), C(778f 3e1 b6650d56), C(3f 6 be451a668fe2d), C(5452892 b0b101388), C(cc867fceaeabdb95), C(f238913c18aaa101), C(f5236b44f324cea1), C(c507cc892ff83dd1)}, {C(5 cc268bac4bd55f), C(232717 a35d5b2f1), C(38 da1393365c961d), C(2 d187f89c16f7b62), C(4eb504204f a1be8), C(222 bd53d2efe5fa), C(a4dcd6d721ddb187), C(2 d187f89c16f7b62), C(4eb504204f a1be8), C(222 bd53d2efe5fa), C(a4dcd6d721ddb187), C(d86bbe67666eca70), C(c8bbae99d8e6429f), C(41 dac4ceb2cb6b10), C(2f 90 c331755f6c48)}, {C(db04969cc06547f1), C(fcacc8a75332f120), C(967 ccec4ed0c977e), C(ac5d1087e454b6cd), C(c1f8b2e284d28f6c), C(cc3994f4a9312cfa), C(8 d61606dbc4e060d), C(ac5d1087e454b6cd), C(c1f8b2e284d28f6c), C(cc3994f4a9312cfa), C(8 d61606dbc4e060d), C(17315 af3202a1307), C(850775145e01163 a), C(96f 10e7357f 930 d2), C(abf27049cf07129)}, {C(25 bd8d3ca1b375b2), C(4 ad34c2c865816f9), C(9 be30ad32f8f28aa), C(7755ea02 dbccad6a), C(cb8aaf8886247a4a), C(8f 6966 ce7ea1b6e6), C(3f 2863090f a45a70), C(7755ea02 dbccad6a), C(cb8aaf8886247a4a), C(8f 6966 ce7ea1b6e6), C(3f 2863090f a45a70), C(1e46 d73019c9fb06), C(af37f39351616f2c), C(657ef dfff20ea2ed), C(93 bdf4c58ada3ecb)}, {C(166 c11fbcbc89fd8), C(cce1af56c48a48aa), C(78908959 b8ede084), C(19032925 ba2c951a), C(a53ed6e81b67943a), C(edc871a9e8ef4bdf), C(ae66cf46a8371aba), C(19032925 ba2c951a), C(a53ed6e81b67943a), C(edc871a9e8ef4bdf), C(ae66cf46a8371aba), C(a37b97790fe75861), C(eda28c8622708b98), C(3f 0 a23509d3d5c9d), C(5787 b0e7976c97cf)}, {C(3565 bcc4ca4ce807), C(ec35bfbe575819d5), C(6 a1f690d886e0270), C(1 ab8c584625f6a04), C(ccfcdafb81b572c4), C(53 b04ba39fef5af9), C(64 ce81828eefeed4), C(1 ab8c584625f6a04), C(ccfcdafb81b572c4), C(53 b04ba39fef5af9), C(64 ce81828eefeed4), C(131 af99997fc662c), C(8 d9081192fae833c), C(2828064791 cb2eb), C(80554 d2e8294065c)}, {C(b7897fd2f274307d), C(6 d43a9e5dd95616d), C(31 a2218e64d8fce0), C(664e581f c1cf769b), C(415110942f c97022), C(7 a5d38fee0bfa763), C(dc87ddb4d7495b6c), C(664e581f c1cf769b), C(415110942f c97022), C(7 a5d38fee0bfa763), C(dc87ddb4d7495b6c), C(7 c3b66372e82e64b), C(1 c89c0ceeeb2dd1), C(dad76d2266214dbd), C(744783486e43 cc61)}, {C(aba98113ab0e4a16), C(287f 883 aede0274d), C(3ec d2a607193ba3b), C(e131f6cc9e885c28), C(b399f98d827e4958), C(6eb90 c8ed6c9090c), C(ec89b378612a2b86), C(e131f6cc9e885c28), C(b399f98d827e4958), C(6eb90 c8ed6c9090c), C(ec89b378612a2b86), C(cfc0e126e2f860c0), C(a9a8ab5dec95b1c), C(d06747f372f7c733), C(fbd643f943a026d3)}, {C(17f 7796e0 d4b636c), C(ddba5551d716137b), C(65f 9735375 df1ada), C(a39e946d02e14ec2), C(1 c88cc1d3822a193), C(663f 8074 a5172bb4), C(8 ad2934942e4cb9c), C(a39e946d02e14ec2), C(1 c88cc1d3822a193), C(663f 8074 a5172bb4), C(8 ad2934942e4cb9c), C(3 da03b033a95f16c), C(54 a52f1932a1749d), C(779ee b734199bc25), C(359 ce8c8faccc57b)}, {C(33 c0128e62122440), C(b23a588c8c37ec2b), C(f2608199ca14c26a), C(acab0139dc4f36df), C(9502 b1605ca1345a), C(32174ef1 e06a5e9c), C(d824b7869258192b), C(acab0139dc4f36df), C(9502 b1605ca1345a), C(32174ef1 e06a5e9c), C(d824b7869258192b), C(681 d021b52064762), C(30 b6c735f80ac371), C(6 a12d8d7f78896b3), C(157111657 a972144)}, {C(988 bc5d290b97aef), C(6754 bb647eb47666), C(44 b5cf8b5b8106a8), C(a1c5ba961937f723), C(32 d6bc7214dfcb9b), C(6863397e0f 4 c6758), C(e644bcb87e3eef70), C(a1c5ba961937f723), C(32 d6bc7214dfcb9b), C(6863397e0f 4 c6758), C(e644bcb87e3eef70), C(bf25ae22e7aa7c97), C(f5f3177da5756312), C(56 a469cb0dbb58cd), C(5233184 bb6130470)}, {C(23 c8c25c2ab72381), C(d6bc672da4175fba), C(6 aef5e6eb4a4eb10), C(3 df880c945e68aed), C(5e08 a75e956d456f), C(f984f088d1a322d7), C(7 d44a1b597b7a05e), C(3 df880c945e68aed), C(5e08 a75e956d456f), C(f984f088d1a322d7), C(7 d44a1b597b7a05e), C(cbd7d157b7fcb020), C(2e2945 e90749c2aa), C(a86a13c934d8b1bb), C(fbe3284bb4eab95f)}, {C(450f e4acc4ad3749), C(3111 b29565e4f852), C(db570fc2abaf13a9), C(35107 d593ba38b22), C(fd8212a125073d88), C(72805 d6e015bfacf), C(6 b22ae1a29c4b853), C(35107 d593ba38b22), C(fd8212a125073d88), C(72805 d6e015bfacf), C(6 b22ae1a29c4b853), C(df2401f5c3c1b633), C(c72307e054c81c8f), C(3ef bfe65bd2922c0), C(b4f632e240b3190c)}, {C(48e1 eff032d90c50), C(dee0fe333d962b62), C(c845776990c96775), C(8ea71758346 b71c9), C(d84258cab79431fd), C(af566b4975cce10a), C(5 c5c7e70a91221d2), C(8ea71758346 b71c9), C(d84258cab79431fd), C(af566b4975cce10a), C(5 c5c7e70a91221d2), C(c33202c7be49ea6f), C(e8ade53b6cbf4caf), C(102ea04f c82ce320), C(c1f7226614715e5e)}, {C(c048604ba8b6c753), C(21ea6 d24b417fdb6), C(4e40 a127ad2d6834), C(5234231 bf173c51), C(62319525583eaf 29), C(87632ef a9144cc04), C(1749 de70c8189067), C(5234231 bf173c51), C(62319525583eaf 29), C(87632ef a9144cc04), C(1749 de70c8189067), C(29672240923e8207), C(11 dd247a815f6d0d), C(8 d64e16922487ed0), C(9f a6f45d50d83627)}, {C(67f f1cbe469ebf84), C(3 a828ac9e5040eb0), C(85 bf1ad6b363a14b), C(2f c6c0783390d035), C(ef78307f5be5524e), C(a46925b7a1a77905), C(fea37470f9a51514), C(2f c6c0783390d035), C(ef78307f5be5524e), C(a46925b7a1a77905), C(fea37470f9a51514), C(9 d6504cf6d3947ce), C(174 cc006b8e96e7), C(d653a06d8a009836), C(7 d22b5399326a76c)}, {C(b45c7536bd7a5416), C(e2d17c16c4300d3c), C(b70b641138765ff5), C(a5a859ab7d0ddcfc), C(8730164 a0b671151), C(af93810c10348dd0), C(7256010 c74f5d573), C(a5a859ab7d0ddcfc), C(8730164 a0b671151), C(af93810c10348dd0), C(7256010 c74f5d573), C(e22a335be6cd49f3), C(3 bc9c8b40c9c397a), C(18 da5c08e28d3fb5), C(f58ea5a00404a5c9)}, {C(215 c2eaacdb48f6f), C(33 b09acf1bfa2880), C(78 c4e94ba9f28bf), C(981 b7219224443d1), C(1f 476f c4344d7bba), C(abad36e07283d3a5), C(831 bf61190eaaead), C(981 b7219224443d1), C(1f 476f c4344d7bba), C(abad36e07283d3a5), C(831 bf61190eaaead), C(4 c90729f62432254), C(2f fadc94c89f47b3), C(677e790 b43d20e9a), C(bb0a1686e7c3ae5f)}, {C(241 baf16d80e0fe8), C(b6b3c5b53a3ce1d), C(6 ae6b36209eecd70), C(a560b6a4aa3743a4), C(b3e04f202b7a99b), C(3 b3b1573f4c97d9f), C(ccad8715a65af186), C(a560b6a4aa3743a4), C(b3e04f202b7a99b), C(3 b3b1573f4c97d9f), C(ccad8715a65af186), C(d0c93a838b0c37e7), C(7150 aa1be7eb1aad), C(755 b1e60b84d8d), C(51916e77 b1b05ba9)}, {C(d10a9743b5b1c4d1), C(f16e0e147ff9ccd6), C(fbd20a91b6085ed3), C(43 d309eb00b771d5), C(a6d1f26105c0f61b), C(d37ad62406e5c37e), C(75 d9b28c717c8cf7), C(43 d309eb00b771d5), C(a6d1f26105c0f61b), C(d37ad62406e5c37e), C(75 d9b28c717c8cf7), C(8f 5f 118 b425b57cd), C(5 d806318613275f3), C(8150848 bcf89d009), C(d5531710d53e1462)}, {C(919ef9 e209f2edd1), C(684 c33fb726a720a), C(540353f 94e8033), C(26 da1a143e7d4ec4), C(55095ea e445aacf4), C(31ef ad866d075938), C(f9b580cff4445f94), C(26 da1a143e7d4ec4), C(55095ea e445aacf4), C(31ef ad866d075938), C(f9b580cff4445f94), C(b1bea6b8716d9c48), C(9ed2 a3df4a15dc53), C(11f 1 be58843eb8e9), C(d9899ecaaef3c77c)}, {C(b5f9519b6c9280b), C(7823 a2fe2e103803), C(d379a205a3bd4660), C(466ec55 ee4b4302a), C(714f 1 b9985deeaf0), C(728595f 26e633 cf7), C(25ec d0738e1bee2b), C(466ec55 ee4b4302a), C(714f 1 b9985deeaf0), C(728595f 26e633 cf7), C(25ec d0738e1bee2b), C(db51771ad4778278), C(763e5742 ac55639e), C(df040e92d38aa785), C(5 df997d298499bf1)}, {C(77 a75e89679e6757), C(25 d31fee616b5dd0), C(d81f2dfd08890060), C(7598 df8911dd40a4), C(3 b6dda517509b41b), C(7 dae29d248dfffae), C(6697 c427733135f), C(7598 df8911dd40a4), C(3 b6dda517509b41b), C(7 dae29d248dfffae), C(6697 c427733135f), C(834 d6c0444c90899), C(c790675b3cd53818), C(28 bb4c996ecadf18), C(92 c648513e6e6064)}, {C(9 d709e1b086aabe2), C(4 d6d6a6c543e3fec), C(df73b01acd416e84), C(d54f613658e35418), C(fcc88fd0567afe77), C(d18f2380980db355), C(ec3896137dfbfa8b), C(d54f613658e35418), C(fcc88fd0567afe77), C(d18f2380980db355), C(ec3896137dfbfa8b), C(eb48dbd9a1881600), C(ca7bd7415ab43ca9), C(e6c5a362919e2351), C(2f 4e4 bd2d5267c21)}, {C(91 c89971b3c20a8a), C(87 b82b1d55780b5), C(bc47bb80dfdaefcd), C(87e11 c0f44454863), C(2 df1aedb5871cc4b), C(ba72fd91536382c8), C(52 cebef9e6ea865d), C(87e11 c0f44454863), C(2 df1aedb5871cc4b), C(ba72fd91536382c8), C(52 cebef9e6ea865d), C(5 befc3fc66bc7fc5), C(b128bbd735a89061), C(f8f500816fa012b3), C(f828626c9612f04)}, {C(16468 c55a1b3f2b4), C(40 b1e8d6c63c9ff4), C(143 adc6fee592576), C(4 caf4deeda66a6ee), C(264720f 6f 35f 7840), C(71 c3aef9e59e4452), C(97886 ca1cb073c55), C(4 caf4deeda66a6ee), C(264720f 6f 35f 7840), C(71 c3aef9e59e4452), C(97886 ca1cb073c55), C(16155f ef16fc08e8), C(9 d0c1d1d5254139a), C(246513 bf2ac95ee2), C(22 c8440f59925034)}, {C(1 a2bd6641870b0e4), C(e4126e928f4a7314), C(1e9227 d52aab00b2), C(d82489179f16d4e8), C(a3c59f65e2913cc5), C(36 cbaecdc3532b3b), C(f1b454616cfeca41), C(d82489179f16d4e8), C(a3c59f65e2913cc5), C(36 cbaecdc3532b3b), C(f1b454616cfeca41), C(99393e31 e3eefc16), C(3 ca886eac5754cdf), C(c11776fc3e4756dd), C(ca118f7059198ba)}, {C(1 d2f92f23d3e811a), C(e0812edbcd475412), C(92 d2d6ad29c05767), C(fd7feb3d2956875e), C(d7192a886b8b01b6), C(16e71 dba55f5b85a), C(93 dabd3ff22ff144), C(fd7feb3d2956875e), C(d7192a886b8b01b6), C(16e71 dba55f5b85a), C(93 dabd3ff22ff144), C(14f f0a5444c272c9), C(fb024d3bb8d915c2), C(1 bc3229a94cab5fe), C(6f 6f 1f b3c0dccf09)}, {C(a47c08255da30ca8), C(cf6962b7353f4e68), C(2808051ea18946 b1), C(b5b472960ece11ec), C(13935 c99b9abbf53), C(3e80 d95687f0432c), C(3516 ab536053be5), C(b5b472960ece11ec), C(13935 c99b9abbf53), C(3e80 d95687f0432c), C(3516 ab536053be5), C(748 ce6a935755e20), C(2961 b51d61b0448c), C(864624113 aae88d2), C(a143805366f91338)}, {C(efb3b0262c9cd0c), C(1273901e9 e7699b3), C(58633f 4 ad0dcd5bb), C(62e33 ba258712d51), C(fa085c15d779c0e), C(2 c15d9142308c5ad), C(feb517011f27be9e), C(62e33 ba258712d51), C(fa085c15d779c0e), C(2 c15d9142308c5ad), C(feb517011f27be9e), C(1 b2b049793b9eedb), C(d26be505fabc5a8f), C(adc483e42a5c36c5), C(c81ff37d56d3b00b)}, {C(5029700 a7773c3a4), C(d01231e97e300d0f), C(397 cdc80f1f0ec58), C(e4041579de57c879), C(bbf513cb7bab5553), C(66 ad0373099d5fa0), C(44 bb6b21b87f3407), C(e4041579de57c879), C(bbf513cb7bab5553), C(66 ad0373099d5fa0), C(44 bb6b21b87f3407), C(a8108c43b4daba33), C(c0b5308c311e865e), C(cdd265ada48f6fcf), C(efbc1dae0a95ac0a)}, {C(71 c8287225d96c9a), C(eb836740524735c4), C(4777522 d0e09846b), C(16f de90d02a1343b), C(ad14e0ed6e165185), C(8 df6e0b2f24085dd), C(caa8a47292d50263), C(16f de90d02a1343b), C(ad14e0ed6e165185), C(8 df6e0b2f24085dd), C(caa8a47292d50263), C(a020413ba660359d), C(9 de401413f7c8a0c), C(20 bfb965927a7c85), C(b52573e5f817ae27)}, {C(4e8 b9ad9347d7277), C(c0f195eeee7641cf), C(dbd810bee1ad5e50), C(8459801016414808), C(6f bf75735353c2d1), C(6e69 aaf2d93ed647), C(85 bb5b90167cce5e), C(8459801016414808), C(6f bf75735353c2d1), C(6e69 aaf2d93ed647), C(85 bb5b90167cce5e), C(39 d79ee490d890cc), C(ac9f31f7ec97deb0), C(3 bdc1cae4ed46504), C(eb5c63cfaee05622)}, {C(1 d5218d6ee2e52ab), C(cb25025c4daeff3b), C(aaf107566f31bf8c), C(aad20d70e231582b), C(eab92d70d9a22e54), C(cc5ab266375580c0), C(85091463e3630 dce), C(aad20d70e231582b), C(eab92d70d9a22e54), C(cc5ab266375580c0), C(85091463e3630 dce), C(b830b617a4690089), C(9 dacf13cd76f13cf), C(d47cc5224265c68f), C(f04690880202b002)}, {C(162360 be6c293c8b), C(ff672b4a831953c8), C(dda57487ab6f78b5), C(38 a42e0db55a4275), C(585971 da56bb56d6), C(cd957009adc1482e), C(d6a96021e427567d), C(38 a42e0db55a4275), C(585971 da56bb56d6), C(cd957009adc1482e), C(d6a96021e427567d), C(8e2 b1a5a63cd96fe), C(426ef8 ce033d722d), C(c4d1c3d8acdda5f), C(4e694 c9be38769b2)}, {C(31459914f 13 c8867), C(ef96f4342d3bef53), C(a4e944ee7a1762fc), C(3526 d9b950a1d910), C(a58ba01135bca7c0), C(cbad32e86d60a87c), C(adde1962aad3d730), C(3526 d9b950a1d910), C(a58ba01135bca7c0), C(cbad32e86d60a87c), C(adde1962aad3d730), C(55f aade148929704), C(bfc06376c72a2968), C(97762698 b87f84be), C(117483 d4828cbaf7)}, {C(6 b4e8fca9b3aecff), C(3ea0 a33def0a296c), C(901f cb5fe05516f5), C(7 c909e8cd5261727), C(c5acb3d5fbdc832e), C(54eff 5 c782ad3cdd), C(9 d54397f3caf5bfa), C(7 c909e8cd5261727), C(c5acb3d5fbdc832e), C(54eff 5 c782ad3cdd), C(9 d54397f3caf5bfa), C(6 b53ce24c4fc3092), C(2789 abfdd4c9a14d), C(94 d6a2261637276c), C(648 aa4a2a1781f25)}, {C(dd3271a46c7aec5d), C(fb1dcb0683d711c3), C(240332e9 ebe5da44), C(479f 936 b6d496dca), C(dc2dc93d63739d4a), C(27e4151 c3870498c), C(3 a3a22ba512d13ba), C(479f 936 b6d496dca), C(dc2dc93d63739d4a), C(27e4151 c3870498c), C(3 a3a22ba512d13ba), C(5 da92832f96d3cde), C(439 b9ad48c4e7644), C(d2939279030accd9), C(6829f 920e2950 dbe)}, {C(109 b226238347d6e), C(e27214c32c43b7e7), C(eb71b0afaf0163ef), C(464f 1 adf4c68577), C(acf3961e1c9d897f), C(985 b01ab89b41fe1), C(6972 d6237390aac0), C(464f 1 adf4c68577), C(acf3961e1c9d897f), C(985 b01ab89b41fe1), C(6972 d6237390aac0), C(122 d89898e256a0e), C(ac830561bd8be599), C(5744312574f bf0ad), C(7 bff7f480a924ce9)}, {C(cc920608aa94cce4), C(d67efe9e097bce4f), C(5687727 c2c9036a9), C(8 af42343888843c), C(191433f fcbab7800), C(7eb45f c94f88a71), C(31 bc5418ffb88fa8), C(8 af42343888843c), C(191433f fcbab7800), C(7eb45f c94f88a71), C(31 bc5418ffb88fa8), C(4 b53a37d8f446cb7), C(a6a7dfc757a60d28), C(a074be7bacbc013a), C(cc6db5f270de7adc)}, {C(901f f46f22283dbe), C(9 dd59794d049a066), C(3 c7d9c3b0e77d2c6), C(dc46069eec17bfdf), C(cacb63fe65d9e3e), C(362f b57287d530c6), C(5854 a4fbe1762d9), C(dc46069eec17bfdf), C(cacb63fe65d9e3e), C(362f b57287d530c6), C(5854 a4fbe1762d9), C(3197427495021ef c), C(5f abf34386aa4205), C(ca662891de36212), C(21f 603e4 d39bca84)}, {C(11 b3bdda68b0725d), C(2366 bf0aa97a00bd), C(55 dc4a4f6bf47e2b), C(69437142 dae5a255), C(f2980cc4816965ac), C(dbbe76ba1d9adfcf), C(49 c18025c0a8b0b5), C(69437142 dae5a255), C(f2980cc4816965ac), C(dbbe76ba1d9adfcf), C(49 c18025c0a8b0b5), C(fe25c147c9001731), C(38 b99cad0ca30c81), C(c7ff06ac47eb950), C(a10f92885a6b3c02)}, {C(9f 5f 03e84 a40d232), C(1151 a9ff99da844), C(d6f2e7c559ac4657), C(5e351 e20f30377bf), C(91 b3805daf12972c), C(94417f a6452a265e), C(bfa301a26765a7c), C(5e351 e20f30377bf), C(91 b3805daf12972c), C(94417f a6452a265e), C(bfa301a26765a7c), C(6924e2 a053297d13), C(ed4a7904ed30d77e), C(d734abaad66d6eab), C(ce373e6c09e6e8a1)}, {C(39eef f4f60f439be), C(1f 7559 c118517c70), C(6139 d2492237a36b), C(fd39b7642cecf78f), C(104f 1 af4e9201df5), C(ab1a3cc7eaeab609), C(cee3363f210a3d8b), C(fd39b7642cecf78f), C(104f 1 af4e9201df5), C(ab1a3cc7eaeab609), C(cee3363f210a3d8b), C(51490f 65f e56c884), C(6 a8c8322cda993c), C(1f 90609 a017de1f0), C(9f 3 acea480a41edf)}, {C(9 b9e0126fe4b8b04), C(6 a6190d520886c41), C(69640 b27c16b3ed8), C(18865f f87619fd8f), C(dec5293e665663d8), C(ea07c345872d3201), C(6f ce64da038a17ab), C(18865f f87619fd8f), C(dec5293e665663d8), C(ea07c345872d3201), C(6f ce64da038a17ab), C(ad48f3c826c6a83e), C(70 a1ff080a4da737), C(ecdac686c7d7719), C(700338424 b657470)}, {C(3ec4 b8462b36df47), C(ff8de4a1cbdb7e37), C(4ed e0449884716ac), C(b5f630ac75a8ce03), C(7 cf71ae74fa8566a), C(e068f2b4618df5d), C(369 df952ad3fd0b8), C(b5f630ac75a8ce03), C(7 cf71ae74fa8566a), C(e068f2b4618df5d), C(369 df952ad3fd0b8), C(5e1 ba38fea018eb6), C(5ea5 edce48e3da30), C(9 b3490c941069dcb), C(e17854a44cc2fff)}, {C(5e3f d9298fe7009f), C(d2058a44222d5a1d), C(cc25df39bfeb005c), C(1 b0118c5c60a99c7), C(6 ae919ef932301b8), C(cde25defa089c2fc), C(c2a3776e3a7716c4), C(1 b0118c5c60a99c7), C(6 ae919ef932301b8), C(cde25defa089c2fc), C(c2a3776e3a7716c4), C(2557 bf65fb26269e), C(b2edabba58f2ae4f), C(264144e9f 0e632 cb), C(ad6481273c979566)}, {C(7504ec b4727b274e), C(f698cfed6bc11829), C(71 b62c425ecd348e), C(2 a5e555fd35627db), C(55 d5da439c42f3b8), C(a758e451732a1c6f), C(18 caa6b46664b484), C(2 a5e555fd35627db), C(55 d5da439c42f3b8), C(a758e451732a1c6f), C(18 caa6b46664b484), C(6ec1 c7d1524bbad7), C(1 cc3531dc422529d), C(61 a6eeb29c0e5110), C(9 cc8652016784a6a)}, {C(4 bdedc104d5eaed5), C(531 c4bb4fd721e5d), C(1 d860834e94a219f), C(1944ec723253392 b), C(7ea6 aa6a2f278ea5), C(5f f786af8113b3d5), C(194832eb9 b0b8d0f), C(1944ec723253392 b), C(7ea6 aa6a2f278ea5), C(5f f786af8113b3d5), C(194832eb9 b0b8d0f), C(56 ab0396ed73fd38), C(2 c88725b3dfbf89d), C(7f f57adf6275c816), C(b32f7630bcdb218)}, {C(da0b4a6fb26a4748), C(8 a3165320ae1af74), C(4803664ee3 d61d09), C(81 d90ddff0d00fdb), C(2 c8c7ce1173b5c77), C(18 c6b6c8d3f91dfb), C(415 d5cbbf7d9f717), C(81 d90ddff0d00fdb), C(2 c8c7ce1173b5c77), C(18 c6b6c8d3f91dfb), C(415 d5cbbf7d9f717), C(b683e956f1eb3235), C(43166 dde2b64d11f), C(f9689c90f5aad771), C(ca0ebc253c2eec38)}, {C(bad6dd64d1b18672), C(6 d4c4b91c68bd23f), C(d8f1507176822db7), C(381068e0f 65f 708 b), C(b4f3762e451b12a6), C(6 d61ed2f6d4e741), C(8 b3b9df537b91a2c), C(381068e0f 65f 708 b), C(b4f3762e451b12a6), C(6 d61ed2f6d4e741), C(8 b3b9df537b91a2c), C(b0759e599a91575c), C(9e7 adbcc77212239), C(cf0eba98436555fe), C(b1fcc9c42c4cd1e6)}, {C(98 da3fe388d5860e), C(14 a9fda8b3adb103), C(d85f5f798637994b), C(6e8 e8ff107799274), C(24 a2ef180891b531), C(c0eaf33a074bcb9d), C(1f a399a82974e17e), C(6e8 e8ff107799274), C(24 a2ef180891b531), C(c0eaf33a074bcb9d), C(1f a399a82974e17e), C(e7c116bef933725d), C(859908 c7d17b93de), C(f6cfa27113af4a72), C(edf41c5d83c721a8)}, {C(ef243a576431d7ac), C(92 a32619ecfae0a5), C(fb34d2c062dc803a), C(f5f8b21ec30bd3a0), C(80 a442fd5c6482a8), C(4f de11e5ccde5169), C(55671451f 661 a885), C(f5f8b21ec30bd3a0), C(80 a442fd5c6482a8), C(4f de11e5ccde5169), C(55671451f 661 a885), C(94f 27 bc2d5d8d63e), C(2156968 b87f084dc), C(b591bcae146f6fea), C(f57f4c01e41ac7fe)}, {C(97854 de6f22c97b6), C(1292 ac07b0f426bb), C(9 a099a28b22d3a38), C(caac64f5865d87f3), C(771 b9fdbd3aa4bd2), C(88446393 c3606c2d), C(bc3d3dcd5b7d6d7f), C(caac64f5865d87f3), C(771 b9fdbd3aa4bd2), C(88446393 c3606c2d), C(bc3d3dcd5b7d6d7f), C(56e22512 b832d3ee), C(bbc677fe5ce0b665), C(f1914b0f070e5c32), C(c10d40362472dcd1)}, {C(d26ce17bfc1851d), C(db30fb632c7da294), C(26 cb7b1a465400a5), C(401 a0581221957e2), C(fc04e99ae3a283ce), C(fe895303ab2d1e3e), C(35 ab7c498403975b), C(401 a0581221957e2), C(fc04e99ae3a283ce), C(fe895303ab2d1e3e), C(35 ab7c498403975b), C(c6e4c8dc6f52fb11), C(63f 0 b484c2c7502f), C(93693 da3439bdbe9), C(1264 dbaaaaf6b7f1)}, {C(97477 bac0ba4c7f1), C(788ef8729 dca29ac), C(63 d88e226d36132c), C(330 b7e93663affbd), C(3 c59913fcf0d603f), C(e207e6572672fd0a), C(8 a5dc17019c8a667), C(330 b7e93663affbd), C(3 c59913fcf0d603f), C(e207e6572672fd0a), C(8 a5dc17019c8a667), C(5 c8f47ade659d40), C(6e0838 e5a808e9a2), C(8 a2d9a0afcd48b19), C(d1c9d5af7b48418d)}, {C(f6bbcba92b11f5c8), C(72 cf221cad20f191), C(a04726593764122d), C(77f bb70409d316e2), C(c864432c5208e583), C(d3f593922668c184), C(23307562648 bdb54), C(77f bb70409d316e2), C(c864432c5208e583), C(d3f593922668c184), C(23307562648 bdb54), C(b03e0b274f848a74), C(c6121e3af71f4281), C(2e48 dd2a16ca63ec), C(f4cd44c69ae024df)}, {C(1 ac8b67c1c82132), C(7536 db9591be9471), C(42f 18f be7141e565), C(20085827 a39ff749), C(42e6 c504df174606), C(839 da16331fea7ac), C(7f d768552b10ffc6), C(20085827 a39ff749), C(42e6 c504df174606), C(839 da16331fea7ac), C(7f d768552b10ffc6), C(d1c53c90fde72640), C(c61ae7cf4e266556), C(127561e440 e4c156), C(f329cae8c26af3e1)}, {C(9 cd716ca0eee52fa), C(67 c1076e1ef11f93), C(927342024f 36f 5 d7), C(d0884af223fd056b), C(bb33aafc7b80b3e4), C(36 b722fea81a4c88), C(6e72 e3022c0ed97), C(d0884af223fd056b), C(bb33aafc7b80b3e4), C(36 b722fea81a4c88), C(6e72 e3022c0ed97), C(5 db446a3ba66e0ba), C(2e138f b81b28ad9), C(16e8 e82995237c85), C(9730 dbfb072fbf03)}, {C(1909f 39123 d9ad44), C(c0bdd71c5641fdb7), C(112e5 d19abda9b14), C(984 cf3f611546e28), C(d7d9c9c4e7efb5d7), C(b3152c389532b329), C(1 c168b512ec5f659), C(984 cf3f611546e28), C(d7d9c9c4e7efb5d7), C(b3152c389532b329), C(1 c168b512ec5f659), C(eca67cc49e26069a), C(73 cb0b224d36d541), C(df8379190ae6c5fe), C(e0f6bde7c4726211)}, {C(1 d206f99f535efeb), C(882e15548 afc3422), C(c94f203775c8c634), C(24940 a3adac420b8), C(5 adf73051c52bce0), C(1 aa5030247ed3d32), C(e1ae74ab6804c08b), C(24940 a3adac420b8), C(5 adf73051c52bce0), C(1 aa5030247ed3d32), C(e1ae74ab6804c08b), C(95217 bf71b0da84c), C(ca9bb91c0126a36e), C(741 b9a99ea470974), C(2 adc4e34b8670f41)}, {C(b38c3a83042eb802), C(ea134be7c6e0c326), C(81 d396c683df4f35), C(2 a55645640911e27), C(4f ac2eefbd36e26f), C(79 ad798fb4c5835c), C(359 aa2faec050131), C(2 a55645640911e27), C(4f ac2eefbd36e26f), C(79 ad798fb4c5835c), C(359 aa2faec050131), C(5 b802dcec21a7157), C(6ec de915b75ede0a), C(f2e653587e89058b), C(a661be80528d3385)}, {C(488 d6b45d927161b), C(f5cac66d869a8aaf), C(c326d56c643a214e), C(10 a7228693eb083e), C(1054f b19cbacf01c), C(a8f389d24587ebd8), C(afcb783a39926dba), C(10 a7228693eb083e), C(1054f b19cbacf01c), C(a8f389d24587ebd8), C(afcb783a39926dba), C(fe83e658532edf8f), C(6f dcf97f147dc4db), C(dc5e487845abef4b), C(137693f 4ea b77e27)}, {C(3 d6aaa43af5d4f86), C(44 c7d370910418d8), C(d099515f7c5c4eca), C(39756960441f be2f), C(fb68e5fedbe3d874), C(3f f380fbdd27b8e), C(f48832fdda648998), C(39756960441f be2f), C(fb68e5fedbe3d874), C(3f f380fbdd27b8e), C(f48832fdda648998), C(270 ddbf2327058c9), C(9ee ad83a8319d0c4), C(b4c3356e162b086d), C(88f 013588f 411 b7)}, {C(e5c40a6381e43845), C(312 a18e66bbceaa3), C(31365186 c2059563), C(cba4c10e65410ba0), C(3 c250c8b2d72c1b6), C(177e82f 415595117), C(8 c8dcfb9e73d3f6), C(cba4c10e65410ba0), C(3 c250c8b2d72c1b6), C(177e82f 415595117), C(8 c8dcfb9e73d3f6), C(c017a797e49c0f7), C(ea2b233b2e7d5aea), C(878 d204c55a56cb1), C(7 b1b62cc0dfdc523)}, {C(86f b323e5a4b710b), C(710 c1092c23a79e0), C(bd2c6d3fc949402e), C(951f 2078 aa4b8099), C(e68b7fefa1cfd190), C(41525 a4990ba6d4a), C(c373552ef4b51712), C(951f 2078 aa4b8099), C(e68b7fefa1cfd190), C(41525 a4990ba6d4a), C(c373552ef4b51712), C(73eb44 c6122bdf5a), C(58047289 a314b013), C(e31d30432521705b), C(6 cf856774873faa4)}, {C(7930 c09adaf6e62e), C(f230d3311593662c), C(a795b9bf6c37d211), C(b57ec44bc7101b96), C(6 cb710e77767a25a), C(2f 446152 d5e3a6d0), C(cd69172f94543ce3), C(b57ec44bc7101b96), C(6 cb710e77767a25a), C(2f 446152 d5e3a6d0), C(cd69172f94543ce3), C(e6c2483cf425f072), C(2060 d5d4379d6d5a), C(86 a3c04c2110d893), C(561 d3b8a509313c6)}, {C(e505e86f0eff4ecd), C(cf31e1ccb273b9e6), C(d8efb8e9d0fe575), C(ed094f47671e359d), C(d9ebdb047d57611a), C(1 c620e4d301037a3), C(df6f401c172f68e8), C(ed094f47671e359d), C(d9ebdb047d57611a), C(1 c620e4d301037a3), C(df6f401c172f68e8), C(af0a2c7f72388ec7), C(6 d4c4a087fa4564a), C(411 b30def69700a), C(67e5 c84557a47e01)}, {C(dedccb12011e857), C(d831f899174feda8), C(ee4bcdb5804c582a), C(5 d765af4e88f3277), C(d2abe1c63ad4d103), C(342 a8ce0bc7af6e4), C(31 bfda956f3e5058), C(5 d765af4e88f3277), C(d2abe1c63ad4d103), C(342 a8ce0bc7af6e4), C(31 bfda956f3e5058), C(4 c7a1fec9af54bbb), C(84 a88f0655899bf4), C(66f b60d0582ac601), C(be0dd1ffe967bd4a)}, {C(4 d679bda26f5555f), C(7 deb387eb7823c1c), C(a65ef3b4fecd6888), C(a6814d3dc578b9df), C(3372111 a3292b691), C(e97589c81d92b513), C(74ed d943d1b9b5bf), C(a6814d3dc578b9df), C(3372111 a3292b691), C(e97589c81d92b513), C(74ed d943d1b9b5bf), C(889e38 b0af80bb7a), C(a416349af3c5818b), C(f5f5bb25576221c1), C(3 be023fa6912c32e)}, {C(e47cd22995a75a51), C(3686350 c2569a162), C(861 afcb185b8efd9), C(63672 de7951e1853), C(3 ca0c763273b99db), C(29e04f a994cccb98), C(b02587d792be5ee8), C(63672 de7951e1853), C(3 ca0c763273b99db), C(29e04f a994cccb98), C(b02587d792be5ee8), C(c85ada4858f7e4fc), C(3f 280 ab7d5864460), C(4109822f 92f 68326), C(2 d73f61314a2f630)}, {C(92 ba8e12e0204f05), C(4e29321580273802), C(aa83b675ed74a851), C(a16cd2e8b445a3fd), C(f0d4f9fb613c38ef), C(eee7755d444d8f2f), C(b530591eb67ae30d), C(a16cd2e8b445a3fd), C(f0d4f9fb613c38ef), C(eee7755d444d8f2f), C(b530591eb67ae30d), C(6f b3031a6edf8fec), C(65118 d08aecf56d8), C(9 a2117bbef1faa8), C(97055 c5fd310aa93)}, {C(bb3a8427c64f8939), C(b5902af2ec095a04), C(89f 1 b440667b2a28), C(5386ef0 b438d0330), C(d39e03c686f8a2da), C(9555249 bb9073d78), C(8 c0b3623fdf0b156), C(5386ef0 b438d0330), C(d39e03c686f8a2da), C(9555249 bb9073d78), C(8 c0b3623fdf0b156), C(354f c5d3a5504e5e), C(b2fd7391719aa614), C(13 cd4ce3dfe27b3d), C(a2d63a85dc3cae4b)}, {C(998988f 7 d6dacc43), C(5f 2 b853d841152db), C(d76321badc5cb978), C(e381f24ee1d9a97d), C(7 c5d95b2a3af2e08), C(ca714acc461cdc93), C(1 a8ee94bc847aa3e), C(e381f24ee1d9a97d), C(7 c5d95b2a3af2e08), C(ca714acc461cdc93), C(1 a8ee94bc847aa3e), C(ee59ee4c21a36f47), C(d476e8bba5bf5143), C(22 a03cb5900f6ec8), C(19 d954e14f35d7a8)}, {C(3f 1049221 dd72b98), C(8 d9200d7a0664c37), C(3925704 c83a5f406), C(4 cbef49086e62678), C(d77dfecc2819ef19), C(c327e4deaf4c7e72), C(b4d58c73a262a32d), C(4 cbef49086e62678), C(d77dfecc2819ef19), C(c327e4deaf4c7e72), C(b4d58c73a262a32d), C(78 cd002324861653), C(7 c3f3977576efb88), C(d1c9975fd4a4cc26), C(3e3 cbc90a9baa442)}, {C(419e4f f78c3e06f3), C(aa8ff514c8a141d7), C(5 bb176e21f89f10d), C(becb065dc12d8b4e), C(ebee135492a2018), C(d3f07e65bcd9e13a), C(85 c933e85382e9f9), C(becb065dc12d8b4e), C(ebee135492a2018), C(d3f07e65bcd9e13a), C(85 c933e85382e9f9), C(2 c19ab7c419ebaca), C(982375 b2999bdb46), C(652 ca1c6325d9296), C(e9c790fa8561940a)}, {C(9 ba090af14171317), C(b0445c5232d7be53), C(72 cc929d1577ddb8), C(bc944c1b5ba2184d), C(ab3d57e5e60e9714), C(5 d8d27e7dd0a365a), C(4 dd809e11740af1a), C(bc944c1b5ba2184d), C(ab3d57e5e60e9714), C(5 d8d27e7dd0a365a), C(4 dd809e11740af1a), C(6f 42 d856faad44df), C(5118 dc58d7eaf56e), C(829 bbc076a43004), C(1747f bbfaca6da98)}, {C(6 ad739e4ada9a340), C(2 c6c4fb3a2e9b614), C(ab58620e94ca8a77), C(aaa144fbe3e6fda2), C(52 a9291d1e212bc5), C(2 b4c68291f26b570), C(45351 ab332855267), C(aaa144fbe3e6fda2), C(52 a9291d1e212bc5), C(2 b4c68291f26b570), C(45351 ab332855267), C(1149f 55400 bc9799), C(8 c6ec1a0c617771f), C(e9966cc03f3bec05), C(3e6889140 ccd2646)}, {C(8ecf f07fd67e4abd), C(f1b8029b17006ece), C(21 d96d5859229a61), C(b8c18d66154ac51), C(5807350371 ad7388), C(81f 783f 4f 5 ab2b8), C(fa4e659f90744de7), C(b8c18d66154ac51), C(5807350371 ad7388), C(81f 783f 4f 5 ab2b8), C(fa4e659f90744de7), C(809 da4baa51cad2c), C(88 d5c11ff5598342), C(7 c7125b0681d67d0), C(1 b5ba6124bfed8e8)}, {C(497 ca8dbfee8b3a7), C(58 c708155d70e20e), C(90428 a7e349d6949), C(b744f5056e74ca86), C(88 aa27b96f3d84a5), C(b4b1ee0470ac3826), C(aeb46264f4e15d4f), C(b744f5056e74ca86), C(88 aa27b96f3d84a5), C(b4b1ee0470ac3826), C(aeb46264f4e15d4f), C(14921 b1ee856bc55), C(a341d74aaba00a02), C(4f 50 aa8e3d08a919), C(75 a148668ff3869e)}, {C(a929cd66daa65b0a), C(7 c0150a2d9ca564d), C(46 ddec37e2ec0a6d), C(4323852 cc57e4af3), C(1f 5f 638 bbf9d2e5b), C(578f b6ac89a31d9), C(7792536 d9ac4bf12), C(4323852 cc57e4af3), C(1f 5f 638 bbf9d2e5b), C(578f b6ac89a31d9), C(7792536 d9ac4bf12), C(60 be62e795ef5798), C(c276cc5b44febefe), C(519 ba0b9f6d1be95), C(1f dce3561ed35bb8)}, {C(4107 c4156bc8d4bc), C(1 cda0c6f3f0f48af), C(cf11a23299cf7181), C(766 b71bff7d6f461), C(b004f2c910a6659e), C(4 c0eb3848e1a7c8), C(3f 90439 d05c3563b), C(766 b71bff7d6f461), C(b004f2c910a6659e), C(4 c0eb3848e1a7c8), C(3f 90439 d05c3563b), C(4 a2a013f4bc2c1d7), C(888779 ab0c272548), C(ae0f8462d89a4241), C(c5c85b7c44679abd)}, {C(15 b38dc0e40459d1), C(344f edcfc00fff43), C(b9215c5a0fcf17df), C(d178444a236c1f2d), C(5576 deee27f3f103), C(943611 bb5b1b0736), C(a0fde17cb5c2316d), C(d178444a236c1f2d), C(5576 deee27f3f103), C(943611 bb5b1b0736), C(a0fde17cb5c2316d), C(feaa1a047f4375f3), C(5435f 313e84767 e), C(522e4333 cd0330c1), C(7e6 b609b0ea9e91f)}, {C(e5e5370ed3186f6c), C(4592e75 db47ea35d), C(355 d452b82250e83), C(7 a265e37da616168), C(6 a1f06c34bafa27), C(fbae175e7ed22a9c), C(b144e84f6f33c098), C(7 a265e37da616168), C(6 a1f06c34bafa27), C(fbae175e7ed22a9c), C(b144e84f6f33c098), C(bd444561b0db41fc), C(2072 c85731e7b0b0), C(ce1b1fac436b51f3), C(4f 5 d44f31a3dcdb9)}, {C(ea2785c8f873e28f), C(3e257272f 4464f 5f), C(9267e7 e0cc9c7fb5), C(9f d4d9362494cbbc), C(e562bc615befb1b9), C(8096808 d8646cfde), C(c4084a587b9776ec), C(9f d4d9362494cbbc), C(e562bc615befb1b9), C(8096808 d8646cfde), C(c4084a587b9776ec), C(a9135db8a850d8e4), C(fffc4f8b1a11f5af), C(c50e9173c2c6fe64), C(a32630581df4ceda)}, {C(e7bf98235fc8a4a8), C(4042ef2 aae400e64), C(6538 ba9ffe72dd70), C(c84bb7b3881ab070), C(36f e6c51023fbda0), C(d62838514bb87ea4), C(9ee b5e7934373d86), C(c84bb7b3881ab070), C(36f e6c51023fbda0), C(d62838514bb87ea4), C(9ee b5e7934373d86), C(5f 8480 d0a2750a96), C(40 afa38506456ad9), C(e4012b7ef2e0ddea), C(659 da200a011836b)}, {C(b94e261a90888396), C(1f 468 d07e853294c), C(cb2c9b863a5317b9), C(4473 c8e2a3458ee0), C(258053945 ab4a39a), C(f8d745ca41962817), C(7 afb6d40df9b8f71), C(4473 c8e2a3458ee0), C(258053945 ab4a39a), C(f8d745ca41962817), C(7 afb6d40df9b8f71), C(9030 c2349604f677), C(f544dcd593087faf), C(77 a3b0efe6345d12), C(fff4e398c05817cc)}, {C(4 b0226e5f5cdc9c), C(a836ae7303dc4301), C(8505e1 b628bac101), C(b5f52041a698da7), C(29864874 b5f1936d), C(49 b3a0c6d78f98da), C(93 a1a8c7d90de296), C(b5f52041a698da7), C(29864874 b5f1936d), C(49 b3a0c6d78f98da), C(93 a1a8c7d90de296), C(ed62288423c17b7f), C(685 afa2cfba09660), C(6 d9b6f59585452c6), C(e505535c4010efb9)}, {C(e07edbe7325c718c), C(9 db1eda964f06827), C(2f 245 ad774e4cb1b), C(664ec3f ad8521859), C(406f 082 beb9ca29a), C(b6b0fb3a7981c7c8), C(3eb d280b598a9721), C(664ec3f ad8521859), C(406f 082 beb9ca29a), C(b6b0fb3a7981c7c8), C(3eb d280b598a9721), C(d9a6ceb072eab22a), C(d5bc5df5eb2ff6f1), C(488 db3cab48daa0b), C(9916f 14f a5672f37)}, {C(f4b56421eae4c4e7), C(5 da0070cf40937a0), C(aca4a5e01295984a), C(5414e385f 5677 a6d), C(41ef105f 8 a682a28), C(4 cd2e95ea7f5e7b0), C(775 bb1e0d57053b2), C(5414e385f 5677 a6d), C(41ef105f 8 a682a28), C(4 cd2e95ea7f5e7b0), C(775 bb1e0d57053b2), C(8919017805e84 b3f), C(15402f 44e0 e2b259), C(483 b1309e1403c87), C(85 c7b4232d45b0d9)}, {C(c07fcb8ae7b4e480), C(4eb cad82e0b53976), C(8643 c63d6c78a6ce), C(d4bd358fed3e6aa5), C(8 a1ba396356197d9), C(7 afc2a54733922cc), C(b813bdac4c7c02ef), C(d4bd358fed3e6aa5), C(8 a1ba396356197d9), C(7 afc2a54733922cc), C(b813bdac4c7c02ef), C(f6c610cf7e7c955), C(dab6a53e1c0780f8), C(837 c9ffec33e5d48), C(8 cb8c20032af152d)}, {C(3ed ad9568a9aaab), C(23891 bbaeb3a17bc), C(4eb7238738 b0c51a), C(db0c32f76f5b7fc1), C(5e41 b711f0abd1a0), C(bcb758f01ded0a11), C(7 d15f7d87955e28b), C(db0c32f76f5b7fc1), C(5e41 b711f0abd1a0), C(bcb758f01ded0a11), C(7 d15f7d87955e28b), C(cd2dc1f0b05939b), C(9f d6d680462e4c47), C(95 d5846e993bc8ff), C(f0b3cafc2697b8a8)}, {C(fcabde8700de91e8), C(63784 d19c60bf366), C(8f 3 af9a056b1a1c8), C(32 d3a29cf49e2dc9), C(3079 c0b0c2269bd0), C(ed76ba44f04e7b82), C(6ee e76a90b83035f), C(32 d3a29cf49e2dc9), C(3079 c0b0c2269bd0), C(ed76ba44f04e7b82), C(6ee e76a90b83035f), C(4 a9286f545bbc09), C(bd36525be4dd1b51), C(5f 7 a9117228fdee5), C(543 c96a08f03151c)}, {C(362f c5ba93e8eb31), C(7549 ae99fa609d61), C(47e4 cf524e37178f), C(a54eaa5d7f3a7227), C(9 d26922965d54727), C(27 d22acb31a194d4), C(e9b8e68771db0da6), C(a54eaa5d7f3a7227), C(9 d26922965d54727), C(27 d22acb31a194d4), C(e9b8e68771db0da6), C(16f d0e006209abe8), C(81 d3f72987a6a81a), C(74e96 e4044817bc7), C(924 ca5f08572fef9)}, {C(e323b1c5b55a4dfb), C(719993 d7d1ad77fb), C(555 ca6c6166e989c), C(ea37f61c0c2f6d53), C(9 b0c2174f14a01f5), C(7 bbe6921e26293f3), C(2 ab6c72235b6c98a), C(ea37f61c0c2f6d53), C(9 b0c2174f14a01f5), C(7 bbe6921e26293f3), C(2 ab6c72235b6c98a), C(2 c6e7668f37f6d23), C(3e8 edb057a57c2dd), C(2595f c79768c8b34), C(ffc541f5efed9c43)}, {C(9461913 a153530ef), C(83f c6d9ed7d1285a), C(73 df90bdc50807cf), C(a32c192f6e3c3f66), C(8f 10077 b8a902d00), C(61 a227f2faac29b4), C(1 a71466fc005a61d), C(a32c192f6e3c3f66), C(8f 10077 b8a902d00), C(61 a227f2faac29b4), C(1 a71466fc005a61d), C(12545812f 3 d01a92), C(aece72f823ade07d), C(52634 cdd5f9e5260), C(cb48f56805c08e98)}, {C(ec2332acc6df0c41), C(59f 5ee17 e20a8263), C(1087 d756afcd8e7b), C(a82a7bb790678fc9), C(d197682c421e4373), C(dd78d25c7f0f935a), C(9850 cb6fbfee520f), C(a82a7bb790678fc9), C(d197682c421e4373), C(dd78d25c7f0f935a), C(9850 cb6fbfee520f), C(2590847398688 a46), C(ad266f08713ca5fe), C(25 b978be91e830b5), C(2996 c8f2b4c8f231)}, {C(aae00b3a289bc82), C(4f 6 d69f5a5a5b659), C(3f f5abc145614e3), C(33322363 b5f45216), C(7e83f 1f e4189e843), C(df384b2adfc35b03), C(396 ce7790a5ada53), C(33322363 b5f45216), C(7e83f 1f e4189e843), C(df384b2adfc35b03), C(396 ce7790a5ada53), C(c3286e44108b8d36), C(6 db8716c498d703f), C(d1db09466f37f4e7), C(56 c98e7f68a41388)}, {C(4 c842e732fcd25f), C(e7dd7b953cf9c2b2), C(911ee248 a76ae3), C(33 c6690937582317), C(fe6d61a77985d7bb), C(97 b153d04a115535), C(d3fde02e42cfe6df), C(33 c6690937582317), C(fe6d61a77985d7bb), C(97 b153d04a115535), C(d3fde02e42cfe6df), C(d1c7d1efa52a016), C(1 d6ed137f4634c), C(1 a260ec505097081), C(8 d1e70861a1c7db6)}, {C(40e23 ca5817a91f3), C(353e2935809 b7ad1), C(f7820021b86391bb), C(f3d41b3d4717eb83), C(2670 d457dde68842), C(19707 a6732c49278), C(5 d0f05a83569ba26), C(f3d41b3d4717eb83), C(2670 d457dde68842), C(19707 a6732c49278), C(5 d0f05a83569ba26), C(6f e5bc84e528816a), C(94 df3dca91a29ace), C(420196ed097 e8b6f), C(7 c52da0e1f043ad6)}, {C(2564527f ad710b8d), C(2 bdcca8d57f890f), C(81f 7 bfcd9ea5a532), C(dd70e407984cfa80), C(66996 d6066db6e1a), C(36 a812bc418b97c9), C(18ea2 c63da57f36e), C(dd70e407984cfa80), C(66996 d6066db6e1a), C(36 a812bc418b97c9), C(18ea2 c63da57f36e), C(937f d7ad09be1a8f), C(163 b12cab35d5d15), C(3606 c3e441335cce), C(949f 6ea5 bb241ae8)}, {C(6 bf70df9d15a2bf6), C(81 cad17764b8e0dd), C(58 b349a9ba22a7ef), C(9432536 dd9f65229), C(192 dc54522da3e3d), C(274 c6019e0227ca9), C(160 abc932a4e4f35), C(9432536 dd9f65229), C(192 dc54522da3e3d), C(274 c6019e0227ca9), C(160 abc932a4e4f35), C(1204f 2f b5aa79dc6), C(2536ed af890f0760), C(6f 2 b561f44ff46b4), C(8 c7b3e95baa8d984)}, {C(45e6f 446eb6 bbcf5), C(98 ab0ef06f1a7d84), C(85 ae96bacca50de6), C(b9aa5bead3352801), C(8 a6d9e02a19a4229), C(c352f5b6d5ee1d9d), C(ce562bdb0cfa84fb), C(b9aa5bead3352801), C(8 a6d9e02a19a4229), C(c352f5b6d5ee1d9d), C(ce562bdb0cfa84fb), C(d47b768a85283981), C(1f e72557be57a11b), C(95 d8afe4af087d51), C(2f 59 c4e383f30045)}, {C(620 d3fe4b8849c9e), C(975 a15812a429ec2), C(437 c453593dcaf13), C(8 d8e7c63385df78e), C(16 d55add72a5e25e), C(aa6321421dd87eb5), C(6f 27f 62e785f 0203), C(8 d8e7c63385df78e), C(16 d55add72a5e25e), C(aa6321421dd87eb5), C(6f 27f 62e785f 0203), C(829030 a61078206e), C(ae1f30fcfa445cc8), C(f61f21c9df4ef68d), C(1e5 b1945f858dc4c)}, {C(535 aa7340b3c168f), C(bed5d3c3cd87d48a), C(266 d40ae10f0cbc1), C(ce218d5b44f7825a), C(2 ae0c64765800d3a), C(f22dc1ae0728fc01), C(48 a171bc666d227f), C(ce218d5b44f7825a), C(2 ae0c64765800d3a), C(f22dc1ae0728fc01), C(48 a171bc666d227f), C(e7367aff24203c97), C(da39d2be1db3a58d), C(85 ce86523003933a), C(dfd4ef2ae83f138a)}, {C(dd3e761d4eada300), C(893 d7e4c3bea5bb6), C(cc6d6783bf43eea), C(eb8eed7c391f0044), C(b58961c3abf80753), C(3 d75ea687191521), C(389 be7bbd8e478f3), C(eb8eed7c391f0044), C(b58961c3abf80753), C(3 d75ea687191521), C(389 be7bbd8e478f3), C(917070 a07441ee47), C(d78efa8cd65b313), C(a8a16f4c1c08c8a1), C(b69cb8ee549eb113)}, {C(4 ac1902ccde06545), C(2 c44aeb0983a7a07), C(b566035215b309f9), C(64 c136fe9404a7b3), C(99f 3 d8c98a399d5e), C(6319 c7cb14180185), C(fbacdbd277d33f4c), C(64 c136fe9404a7b3), C(99f 3 d8c98a399d5e), C(6319 c7cb14180185), C(fbacdbd277d33f4c), C(a96a5626c2adda86), C(39ea72f d2ad133ed), C(b5583f2f736df73e), C(ef2c63619782b7ba)}, {C(aee339a23bb00a5e), C(cbb402255318f919), C(9922948e99 aa0781), C(df367034233fedc4), C(dcbe14db816586e5), C(f4b1cb814adf21d3), C(f4690695102fa00a), C(df367034233fedc4), C(dcbe14db816586e5), C(f4b1cb814adf21d3), C(f4690695102fa00a), C(6 b4f01dd6b76dafc), C(b79388676b50da5d), C(cb64f8bde5ed3393), C(9 b422781f13219d3)}, {C(627599e91148 df4f), C(3e2 d01e8baab062b), C(2 daab20edb245251), C(9 a958bc3a895a223), C(331058 dd6c5d2064), C(46 c4d962072094fa), C(e6207c19160e58eb), C(9 a958bc3a895a223), C(331058 dd6c5d2064), C(46 c4d962072094fa), C(e6207c19160e58eb), C(5655e4 dbf7272728), C(67 b217b1f56c747d), C(3 ac0be79691b9a0d), C(9 d0954dd0b57073)}, {C(cfb04cf00cfed6b3), C(5f e75fc559af22fa), C(c440a935d72cdc40), C(3 ab0d0691b251b8b), C(47181 a443504a819), C(9 bcaf1253f99f499), C(8ee002 b89c1b6b3f), C(3 ab0d0691b251b8b), C(47181 a443504a819), C(9 bcaf1253f99f499), C(8ee002 b89c1b6b3f), C(55 dfe8eedcd1ec5e), C(1 bf50f0bbad796a5), C(9044369 a042d7fd6), C(d423df3e3738ba8f)}, {C(942631 c47a26889), C(427962 c82d8a6e00), C(224071 a6592537ff), C(d3e96f4fb479401), C(68 b3f2ec11de9368), C(cb51b01083acad4f), C(500 cec4564d62aeb), C(d3e96f4fb479401), C(68 b3f2ec11de9368), C(cb51b01083acad4f), C(500 cec4564d62aeb), C(4 ce547491e732887), C(9423883 a9a11df4c), C(1 a0fc7a14214360), C(9e837914505 da6ed)}, {C(4 c9eb4e09726b47e), C(fd927483a2b38cf3), C(6 d7e56407d1ba870), C(9f 5 dc7db69fa1e29), C(f42fff56934533d5), C(92 d768c230a53918), C(f3360ff11642136c), C(9f 5 dc7db69fa1e29), C(f42fff56934533d5), C(92 d768c230a53918), C(f3360ff11642136c), C(9e989932 eb86d1b5), C(449 a77f69a8a9d65), C(efabaf8a7789ed9a), C(2798eb4 c50c826fd)}, {C(cf7f208ef20e887a), C(f4ce4edeadcaf1a1), C(7ee15226 eaf4a74d), C(17 ab41ab2ae0705d), C(9 dd56694aa2dcd4e), C(dd4fa2add9baced2), C(7 ad99099c9e199a3), C(17 ab41ab2ae0705d), C(9 dd56694aa2dcd4e), C(dd4fa2add9baced2), C(7 ad99099c9e199a3), C(a59112144accef0e), C(5838 df47e38d251d), C(8750f e45760331e5), C(4 b2ce14732e0312a)}, {C(a8dc4687bcf27f4), C(c4aadd7802553f15), C(5401eb9912 be5269), C(5 c2a2b5b0657a928), C(1e1968 ebb38fcb99), C(a082d0e067c4a59c), C(18 b616495ad9bf5d), C(5 c2a2b5b0657a928), C(1e1968 ebb38fcb99), C(a082d0e067c4a59c), C(18 b616495ad9bf5d), C(18 c5dc6c78a7f9ed), C(b3cc94fe34b68aa1), C(3 b77e91292be38cc), C(61 d1786ec5097971)}, {C(daed638536ed19df), C(1 a762ea5d7ac6f7e), C(48 a1cc07a798b84f), C(7f 15 bdaf50d550f9), C(4 c1d48aa621a037e), C(2 b1d7a389d497ee0), C(81 c6775d46f4b517), C(7f 15 bdaf50d550f9), C(4 c1d48aa621a037e), C(2 b1d7a389d497ee0), C(81 c6775d46f4b517), C(35296005 cbba3ebe), C(db1642f825b53532), C(3e07588 a9fd829a4), C(60f 13 b5446bc7638)}, {C(90 a04b11ee1e4af3), C(ab09a35f8f2dff95), C(d7cbe82231ae1e83), C(3262e9017 bb788c4), C(1612017731 c997bc), C(e789d66134aff5e1), C(275642f d17048af1), C(3262e9017 bb788c4), C(1612017731 c997bc), C(e789d66134aff5e1), C(275642f d17048af1), C(99255 b68d0b46b51), C(74 a6f1ad4b2bb296), C(4164222761 af840e), C(54 d59bf6211a8fe6)}, {C(511f 29e1 b732617d), C(551 cb47a9a83d769), C(df6f56fbda20e7a), C(f27583a930221d44), C(d7d2c46de69b2ed8), C(add24ddd2be4a850), C(5 cf2f688dbb93585), C(f27583a930221d44), C(d7d2c46de69b2ed8), C(add24ddd2be4a850), C(5 cf2f688dbb93585), C(a7f8e42d5dd4aa00), C(72 dc11fd76b4dea9), C(8886f 194e6f 8e3f f), C(7e8 ead04a0e0b1ef)}, {C(95567f 03939e651f), C(62 a426f09d81d884), C(15 cb96e36a8e712c), C(1 a2f43bdeaea9c28), C(bca2fd840831291f), C(83446 d4a1f7dcc1a), C(449 a211df83b6187), C(1 a2f43bdeaea9c28), C(bca2fd840831291f), C(83446 d4a1f7dcc1a), C(449 a211df83b6187), C(553 ce97832b2f695), C(3110 a2ba303db75), C(b91d6d399a02f453), C(3 cb148561e0ef2bb)}, {C(248 a32ad10e76bc3), C(dac39c8b036985e9), C(79 d38c4af2958b56), C(cc954b4e56275f54), C(700 cd864e04e8aaa), C(d6ba03cbff7cc34b), C(da297d7891c9c046), C(cc954b4e56275f54), C(700 cd864e04e8aaa), C(d6ba03cbff7cc34b), C(da297d7891c9c046), C(c05d2be8f8ee8114), C(7f 4541 cbe2ec0025), C(8f 0 a7a70af6ea926), C(3837 ddce693781b5)}, {C(f9f05a2a892242eb), C(de00b6b2e0998460), C(f1f4bd817041497a), C(3 deac49eb42a1e26), C(642f 77f 7 c57e84b7), C(2f 2 c231222651e8b), C(380202ec06 bdc29e), C(3 deac49eb42a1e26), C(642f 77f 7 c57e84b7), C(2f 2 c231222651e8b), C(380202ec06 bdc29e), C(59 abc4ff54765e66), C(8561ea1 dddd1f742), C(9 ca1f94b0d3f3875), C(b7fa93c3a9fa4ec4)}, {C(3 a015cea8c3f5bdf), C(5583521 b852fc3ac), C(53 d5cd66029a1014), C(ac2eeca7bb04412a), C(daba45cb16ccff2b), C(ddd90b51209e414), C(d90e74ee28cb6271), C(ac2eeca7bb04412a), C(daba45cb16ccff2b), C(ddd90b51209e414), C(d90e74ee28cb6271), C(117027648 ca9db68), C(29 c1dba39bbcf072), C(787f 6 bb010a34cd9), C(e099f487e09b847)}, {C(670e43506 aa1f71b), C(1 cd7929573e54c05), C(cbb00a0aaba5f20a), C(f779909e3d5688d1), C(88211 b9117678271), C(59f 44f 73759 a8bc6), C(ef14f73c405123b4), C(f779909e3d5688d1), C(88211 b9117678271), C(59f 44f 73759 a8bc6), C(ef14f73c405123b4), C(78775601f 11186f), C(fc4641d676fbeed9), C(669 ca96b5a2ae5b), C(67 b5f0d072025f8d)}, {C(977 bb79b58bbd984), C(26 d45cfcfb0e9756), C(df8885db518d5f6a), C(6 a1d2876488bed06), C(ae35d83c3afb5769), C(33667427 d99f9f4e), C(d84c31c17495e3ba), C(6 a1d2876488bed06), C(ae35d83c3afb5769), C(33667427 d99f9f4e), C(d84c31c17495e3ba), C(31357 cded7495ffc), C(295e2 eefcd383a2e), C(25063ef4 a24c29ae), C(88 c694170fcbf0b7)}, {C(e6264fbccd93a530), C(c92f420494e99a7d), C(c14001a298cf976), C(5 c8685fee2e4ce55), C(228 c49268d6a4345), C(3 b04ee2861baec6d), C(7334878 a00e96e72), C(5 c8685fee2e4ce55), C(228 c49268d6a4345), C(3 b04ee2861baec6d), C(7334878 a00e96e72), C(7317164 b2ce711bb), C(e645447e363e8ca1), C(d326d129ad7b4e7f), C(58 b9b76d5c2eb272)}, {C(54e4 d0cab7ec5c27), C(31 ca61d2262a9acc), C(30 bd3a50d8082ff6), C(46 b3b963bf7e2847), C(b319d04e16ad10b0), C(76 c8dd82e6f5a0eb), C(2070363 cefb488bc), C(46 b3b963bf7e2847), C(b319d04e16ad10b0), C(76 c8dd82e6f5a0eb), C(2070363 cefb488bc), C(6f 9 dbacb2bdc556d), C(88 a5fb0b293c1e22), C(cb131d9b9abd84b7), C(21 db6f0e147a0040)}, {C(882 a598e98cf5416), C(36 c8dca4a80d9788), C(c386480f07591cfe), C(5 b517bcf2005fd9c), C(b9b8f8e5f90e7025), C(2 a833e6199e21708), C(bcb7549de5fda812), C(5 b517bcf2005fd9c), C(b9b8f8e5f90e7025), C(2 a833e6199e21708), C(bcb7549de5fda812), C(44f c96a3cafa1c34), C(fb7724d4899ec7c7), C(4662e3 b87df93e13), C(bcf22545acbcfd4e)}, {C(7 c37a5376c056d55), C(e0cce8936a06b6f6), C(d32f933fdbec4c7d), C(7 ac50423e2be4703), C(546 d4b42340d6dc7), C(624f 56ee027f 12 bf), C(5f 7f 65 d1e90c30f9), C(7 ac50423e2be4703), C(546 d4b42340d6dc7), C(624f 56ee027f 12 bf), C(5f 7f 65 d1e90c30f9), C(d6f15c19625d2621), C(c7afd12394f24b50), C(2 c6adde5d249bcd0), C(6 c857e6aa07b9fd2)}, {C(21 c5e9616f24be97), C(ba3536c86e4b6fe9), C(6 d3a65cfe3a9ae06), C(2113903eb d760a31), C(e561f76a5eac8beb), C(86 b5b3e76392e166), C(68 c8004ccc53e049), C(2113903eb d760a31), C(e561f76a5eac8beb), C(86 b5b3e76392e166), C(68 c8004ccc53e049), C(b51a28fe4251dd79), C(fd9c2d4d2a84c3c7), C(5 bf2ec8a470d2553), C(135 a52cdc76241c9)}, {C(a6eaefe74fa7d62b), C(cb34669c751b10eb), C(80 da952ad8abd5f3), C(3368262 b0e172d82), C(1 d51f6c982476285), C(4497675 ac57228a9), C(2 a71766a71d0b83f), C(3368262 b0e172d82), C(1 d51f6c982476285), C(4497675 ac57228a9), C(2 a71766a71d0b83f), C(79 ad94d1e9c1dedd), C(cbf1a1c9f23bfa40), C(3ebf 24e068 cd638b), C(be8e63472edfb462)}, {C(764 af88ed4b0b828), C(36946775f 20457 ce), C(d4bc88ac8281c22e), C(3 b2104d68dd9ac02), C(2ec a14fcdc0892d0), C(7913 b0c09329cd47), C(9373f 458938688 c8), C(3 b2104d68dd9ac02), C(2ec a14fcdc0892d0), C(7913 b0c09329cd47), C(9373f 458938688 c8), C(b4448f52a5bf9425), C(9f 8 c8b90b61ed532), C(78f 6774f 48e72961), C(e47c00bf9c1206f4)}, {C(5f 55 a694fb173ea3), C(7 db02b80ef5a918b), C(d87ff079f476ca3a), C(1 d11117374e0da3), C(744 bfbde42106439), C(93 a99fab10bb1789), C(246 ba292a85d8d7c), C(1 d11117374e0da3), C(744 bfbde42106439), C(93 a99fab10bb1789), C(246 ba292a85d8d7c), C(e5bd7838e9edd53a), C(d9c0b104c79d9019), C(ee3dcc7a8e565de5), C(619 c9e0a9cf3596d)}, {C(86 d086738b0a7701), C(d2402313a4280dda), C(b327aa1a25278366), C(49ef dde5d1f98163), C(cbcffcee90f22824), C(951 aec1daeb79bab), C(7055e2 c70d2eeb4c), C(49ef dde5d1f98163), C(cbcffcee90f22824), C(951 aec1daeb79bab), C(7055e2 c70d2eeb4c), C(1f c0de9399bacb96), C(dab7bbe67901959e), C(375805ec cf683ef0), C(bbb6f465c4bae04e)}, {C(acfc8be97115847b), C(c8f0d887bf8d9d1), C(e698fbc6d39bf837), C(61f d1d6b13c1ea77), C(527ed97f f4ae24f0), C(af51a9ebb322c0), C(14f 7 c25058864825), C(61f d1d6b13c1ea77), C(527ed97f f4ae24f0), C(af51a9ebb322c0), C(14f 7 c25058864825), C(f40b2bbeaf9f021d), C(80 d827160dfdc2d2), C(77 baea2e3650486e), C(5 de2d256740a1a97)}, {C(dc5ad3c016024d4), C(a0235e954da1a152), C(6 daa8a4ed194cc43), C(185e650 afc8d39f8), C(adba03a4d40de998), C(9975 c776b499b26f), C(9770 c59368a43a2), C(185e650 afc8d39f8), C(adba03a4d40de998), C(9975 c776b499b26f), C(9770 c59368a43a2), C(d2776f0cf0e4f66c), C(38ea aabfb743f7f6), C(c066f03d959b3f07), C(9 d91c2d52240d546)}, {C(a0e91182f03277f7), C(15 c6ebef7376556), C(516f 887657 ab5a), C(f95050524c7f4b84), C(460 dcebbaaa09ae3), C(a9f7a9f0b1b2a961), C(5f 8 dc5e198e34539), C(f95050524c7f4b84), C(460 dcebbaaa09ae3), C(a9f7a9f0b1b2a961), C(5f 8 dc5e198e34539), C(9 c49227ffcff07cb), C(a29388e9fcb794c8), C(475867910 d110cba), C(8 c9a5cee480b5bac)}, {C(767f 1 dbd1dba673b), C(1e466 a3848a5b01e), C(483ea def1347cd6e), C(a67645c72f54fe24), C(c7a5562c69bd796b), C(e14201a35b55e4a6), C(b3a6d89f19d8f774), C(a67645c72f54fe24), C(c7a5562c69bd796b), C(e14201a35b55e4a6), C(b3a6d89f19d8f774), C(bb4d607ac22bebe5), C(792030ed eaa924e0), C(138730 dcb60f7e32), C(699 d9dcc326c72dc)}, {C(a5e30221500dcd53), C(3 a1058d71c9fad93), C(510520710 c6444e8), C(a6a5e60c2c1d0108), C(45 c8ea4e14bf8c6b), C(213 a7235416b86df), C(c186072f80d56ad3), C(a6a5e60c2c1d0108), C(45 c8ea4e14bf8c6b), C(213 a7235416b86df), C(c186072f80d56ad3), C(2e7 be098db59d832), C(d5fa382f3717a0ee), C(b168b26921d243d), C(61601 a60c2addfbb)}, {C(ebaed82e48e18ce4), C(cfe6836b65ebe7c7), C(504 d9d388684d449), C(bd9c744ee9e3308e), C(faefbb8d296b65d4), C(eba051fe2404c25f), C(250 c8510b8931f87), C(bd9c744ee9e3308e), C(faefbb8d296b65d4), C(eba051fe2404c25f), C(250 c8510b8931f87), C(3 c4a49150dc5676f), C(6 c28793c565345c4), C(9 df6dd8829a6d8fb), C(760 d3a023fab72e7)}, {C(ffa50913362b118d), C(626 d52251a8ec3e0), C(76 ce4b9dde2e8c5e), C(fc57418d92e52355), C(6 b46c559e67a063), C(3f 5 c269e10690c5c), C(6870 de8d49e65349), C(fc57418d92e52355), C(6 b46c559e67a063), C(3f 5 c269e10690c5c), C(6870 de8d49e65349), C(88737e5 c672de296), C(ca71fca5f4c4f1ce), C(42f ca3fa7f60e031), C(4 a70246d0d4c2bd8)}, {C(256186 bcda057f54), C(fb059b012049fd8e), C(304e07418 b5f739b), C(3e166f 9f ac2eec0b), C(82 bc11707ec4a7a4), C(e29acd3851ce36b6), C(9765 ca9323d30046), C(3e166f 9f ac2eec0b), C(82 bc11707ec4a7a4), C(e29acd3851ce36b6), C(9765 ca9323d30046), C(dab63e7790017f7c), C(b9559988bff0f170), C(48 d9ef8aea13eee8), C(e31e47857c511ec2)}, {C(382 b15315e84f28b), C(f9a2578b79590b72), C(708936 af6d4450e8), C(76 a9d4843df75c1c), C(2 c33447da3f2c70a), C(5e4 dcf2eaeace0d6), C(2 ae1727aa7220634), C(76 a9d4843df75c1c), C(2 c33447da3f2c70a), C(5e4 dcf2eaeace0d6), C(2 ae1727aa7220634), C(a122f6b52e1130ba), C(a17ae9a21f345e91), C(ff67313f1d0906a9), C(bb16dc0acd6ebecc)}, {C(9983 a9cc5576d967), C(29e37689 a173109f), C(c526073a91f2808c), C(fe9a9d4a799cf817), C(7 ca841999012c0d1), C(8 b3abfa4bd2aa28e), C(4ed49274526602 eb), C(fe9a9d4a799cf817), C(7 ca841999012c0d1), C(8 b3abfa4bd2aa28e), C(4ed49274526602 eb), C(40995 df99063fe23), C(7f 51 b7ceded05144), C(743 c89732b265bf2), C(10 c8e1fd835713fd)}, {C(c2c58a843f733bdb), C(516 c47c97b4ba886), C(abc3cae0339517db), C(be29af0dad5c9d27), C(70f 802599 d97fe08), C(23 af3f67d941e52b), C(a031edd8b3a008fb), C(be29af0dad5c9d27), C(70f 802599 d97fe08), C(23 af3f67d941e52b), C(a031edd8b3a008fb), C(43431336 b198f8fd), C(7 c4b60284e1c2245), C(51ee580 ddabae1b3), C(ca99bd13845d8f7f)}, {C(648f f27fabf93521), C(d7fba33cbc153035), C(3 dbcdcf87ad06c9e), C(52 ddbdc9dfd26990), C(d46784cd2aeabb28), C(bd3a15e5e4eb7177), C(b5d7632e19a2cd), C(52 ddbdc9dfd26990), C(d46784cd2aeabb28), C(bd3a15e5e4eb7177), C(b5d7632e19a2cd), C(8007450f a355dc04), C(41 ca59f64588bb5c), C(66f 2 ca6b7487499d), C(8098716530 db9bea)}, {C(99 be55475dcb3461), C(d94ffa462f6ba8dc), C(dbab2b456bdf13bb), C(f28f496e15914b2d), C(1171 ce20f49cc87d), C(1 b5f514bc1b377a9), C(8 a02cb12ec4d6397), C(f28f496e15914b2d), C(1171 ce20f49cc87d), C(1 b5f514bc1b377a9), C(8 a02cb12ec4d6397), C(1 c6540740c128d79), C(d085b67114969f41), C(af8c1988085306f3), C(4681f 415 d9ce8038)}, {C(e16fbb9303dd6d92), C(4 d92b99dd164db74), C(3f 98f 2 c9da4f5ce3), C(c65b38c5a47eeed0), C(5 c5301c8ee3923a6), C(51 bf9f9eddec630e), C(b1cbf1a68be455c2), C(c65b38c5a47eeed0), C(5 c5301c8ee3923a6), C(51 bf9f9eddec630e), C(b1cbf1a68be455c2), C(c356f5f98499bdb8), C(d897df1ad63fc1d4), C(9 bf2a3a69982e93a), C(a2380d43e271bcc8)}, {C(4 a57a4899834e4c0), C(836 c4df2aac32257), C(cdb66b29e3e12147), C(c734232cbda1eb4c), C(30 a3cffff6b9dda0), C(d199313e17cca1ed), C(594 d99e4c1360d82), C(c734232cbda1eb4c), C(30 a3cffff6b9dda0), C(d199313e17cca1ed), C(594 d99e4c1360d82), C(ccc37662829a65b7), C(cae30ff4d2343ce9), C(54 da907f7aade4fa), C(5 d6e4a0272958922)}, {C(f658958cdf49f149), C(de8e4a622b7a16b), C(a227ebf448c80415), C(3 de9e38b3a369785), C(84 d160d688c573a9), C(8f 562593 add0ad54), C(4446 b762cc34e6bf), C(3 de9e38b3a369785), C(84 d160d688c573a9), C(8f 562593 add0ad54), C(4446 b762cc34e6bf), C(2f 795f 1594 c7d598), C(29e05 bd1e0dceaff), C(a9a88f2962b49589), C(4 b9c86c141ac120b)}, {C(ae1befc65d3ea04d), C(cfd9bc0388c8fd00), C(522f 2e1f 6 cdb31af), C(585447eb e078801a), C(14 a31676ec4a2cbd), C(b274e7e6af86a5e1), C(2 d487019570bedce), C(585447eb e078801a), C(14 a31676ec4a2cbd), C(b274e7e6af86a5e1), C(2 d487019570bedce), C(ea1dc9ef3c7b2fcc), C(bde99d4af2f4ee8c), C(64e4 c43cd7c43442), C(9 b5262ee2eed2f99)}, {C(2f c8f9fc5946296d), C(6 a2b94c6765ebfa2), C(f4108b8c79662fd8), C(3 a48de4a1e994623), C(6318e6 e1ff7bc092), C(84 aee2ea26a048fb), C(cf3c393fdad7b184), C(3 a48de4a1e994623), C(6318e6 e1ff7bc092), C(84 aee2ea26a048fb), C(cf3c393fdad7b184), C(28 b265bd8985a71e), C(bd3d97dbd76d89a5), C(b04ba1623c0937d), C(b6de821229693515)}, {C(efdb4dc26e84dce4), C(9 ce45b6172dffee8), C(c15ad8c8bcaced19), C(f10cc2bcf0475411), C(1126f 457 c160d8f5), C(34 c67f6ea249d5cc), C(3 ab7633f4557083), C(f10cc2bcf0475411), C(1126f 457 c160d8f5), C(34 c67f6ea249d5cc), C(3 ab7633f4557083), C(3 b2e4d8611a03bd7), C(3103 d6e63d71c3c9), C(43 a56a0b93bb9d53), C(50 aa3ae25803c403)}, {C(e84a123b3e1b0c91), C(735 cc1d493c5e524), C(287030 af8f4ac951), C(fb46abaf4713dda0), C(e8835b9a08cf8cb2), C(3 b85a40e6bee4cce), C(eea02a3930757200), C(fb46abaf4713dda0), C(e8835b9a08cf8cb2), C(3 b85a40e6bee4cce), C(eea02a3930757200), C(fe7057d5fb18ee87), C(723 d258b36eada2a), C(67641393692 a716c), C(c8539a48dae2e539)}, {C(686 c22d2863c48a6), C(1ee6804 e3ddde627), C(8 d66184dd34ddac8), C(35 ac1bc76c11976), C(fed58f898503280d), C(ab6fcb01c630071e), C(edabf3ec7663c3c9), C(35 ac1bc76c11976), C(fed58f898503280d), C(ab6fcb01c630071e), C(edabf3ec7663c3c9), C(591ec5025592 b76e), C(918 a77179b072163), C(25421 d9db4c81e1a), C(96f 1 b3be51f0b548)}, {C(2 c5c1c9fa0ecfde0), C(266 a71b430afaec3), C(53 ab2d731bd8184a), C(5722f 16 b15e7f206), C(35 bb5922c0946610), C(b8d72c08f927f2aa), C(65f 2 c378cb9e8c51), C(5722f 16 b15e7f206), C(35 bb5922c0946610), C(b8d72c08f927f2aa), C(65f 2 c378cb9e8c51), C(cd42fec772c2d221), C(10 ccd5d7bacffdd9), C(a75ecb52192f60e2), C(a648f5fe45e5c164)}, {C(7 a0ac8dd441c9a9d), C(4 a4315964b7377f0), C(24092991 c8f27459), C(9 c6868d561691eb6), C(78 b7016996f98828), C(651e072f 06 c9e7b7), C(fed953d1251ae90), C(9 c6868d561691eb6), C(78 b7016996f98828), C(651e072f 06 c9e7b7), C(fed953d1251ae90), C(7 a4d19fdd89e368c), C(d8224d83b6b9a753), C(3 a93520a455ee9c9), C(159942 bea42b999c)}, {C(c6f9a31dfc91537c), C(b3a250ae029272f8), C(d065fc76d79ec222), C(d2baa99749c71d52), C(5f 90 a2cfc2a3f637), C(79e4 aca7c8bb0998), C(981633149 c85c0ba), C(d2baa99749c71d52), C(5f 90 a2cfc2a3f637), C(79e4 aca7c8bb0998), C(981633149 c85c0ba), C(5 ded415df904b2ee), C(d37d1fc032ebca94), C(ed5b024594967bf7), C(ed7ae636d467e961)}, {C(2 d12010eaf7d8d3d), C(eaec74ccd9b76590), C(541338571 d45608b), C(e97454e4191065f3), C(afb357655f2a5d1c), C(521 ac1614653c130), C(c8a8cac96aa7f32c), C(e97454e4191065f3), C(afb357655f2a5d1c), C(521 ac1614653c130), C(c8a8cac96aa7f32c), C(196 d7f3f386dfd29), C(1 dcd2da5227325cc), C(10e3 b9fa712d3405), C(fdf7864ede0856c0)}, {C(f46de22b2d79a5bd), C(e3e198ba766c0a29), C(828 d8c137216b797), C(bafdb732c8a29420), C(2ed0 b9f4548a9ac3), C(f1ed2d5417d8d1f7), C(451462f 90354 d097), C(bafdb732c8a29420), C(2ed0 b9f4548a9ac3), C(f1ed2d5417d8d1f7), C(451462f 90354 d097), C(bdd091094408851a), C(c4c1731c1ea46c2c), C(615 a2348d60409a8), C(fbc2f058d5539bcc)}, {C(2 ce2f3e89fa141fe), C(ac588fe6ab2b719), C(59 b848c80739487d), C(423722957 b566d10), C(ae4be02664998dc6), C(64017 aacfa69ef80), C(28076 dddbf65a40a), C(423722957 b566d10), C(ae4be02664998dc6), C(64017 aacfa69ef80), C(28076 dddbf65a40a), C(873 bc41acb810f94), C(ac0edafb574b7c0d), C(937 d5d5fd95330bf), C(4ea91171 e208bd7e)}, {C(8 aa75419d95555dd), C(bdb046419d0bf1b0), C(aadf49f217b153da), C(c3cbbe7eb0f5e126), C(fd1809c329311bf6), C(9 c26cc255714d79d), C(67093 aeb89f5d8c8), C(c3cbbe7eb0f5e126), C(fd1809c329311bf6), C(9 c26cc255714d79d), C(67093 aeb89f5d8c8), C(265954 c61009eaf7), C(a5703e8073eaf83f), C(855382 b1aed9c128), C(a6652d5a53d4a008)}, {C(1f bf19dd9207e6aa), C(722834f 3 c5e43cb7), C(e3c13578c5a69744), C(db9120bc83472135), C(f3d9f715e669cfd5), C(63f acc852f487dda), C(9f 08f d85a3a78111), C(db9120bc83472135), C(f3d9f715e669cfd5), C(63f acc852f487dda), C(9f 08f d85a3a78111), C(6 c1e5c694b51b7ca), C(bbceb2e47d44f6a1), C(2eb472 efe06f8330), C(1844408e2 bb87ee)}, {C(6f 11f 9 c1131f1182), C(6f 90740 debc7bad2), C(8 d6e4e2d46ee614b), C(403e3793f 0805 ac3), C(6278 da3d8667a055), C(98ec eadb4f237978), C(4 daa96284c847b0), C(403e3793f 0805 ac3), C(6278 da3d8667a055), C(98ec eadb4f237978), C(4 daa96284c847b0), C(ab119ac9f803d770), C(ab893fe847208376), C(f9d9968ae4472ac3), C(b149ff3b35874201)}, {C(92e896 d8bfdebdb5), C(2 d5c691a0acaeba7), C(377 d7f86b7cb2f8b), C(b8a0738135dde772), C(57f b6c9033fc5f35), C(20e628f 266e63 e1), C(1 ad6647eaaa153a3), C(b8a0738135dde772), C(57f b6c9033fc5f35), C(20e628f 266e63 e1), C(1 ad6647eaaa153a3), C(10005 c85a89e601a), C(cc9088ed03a78e4a), C(c8d3049b8c0d26a1), C(26e8 c0e936cf8cce)}, {C(369 ba54df3c534d1), C(972 c7d2be5f62834), C(112 c8d0cfcc8b1e), C(bcddd22a14192678), C(446 cf170a4f05e72), C(c9e992c7a79ce219), C(fa4762e60a93cf84), C(bcddd22a14192678), C(446 cf170a4f05e72), C(c9e992c7a79ce219), C(fa4762e60a93cf84), C(b2e11a375a352f), C(a70467d0fd624cf1), C(776 b638246febf88), C(e7d1033f7faa39b5)}, {C(bcc4229e083e940e), C(7 a42ebe9e8f526b5), C(bb8d1f389b0769ee), C(ae6790e9fe24c57a), C(659 a16feab53eb5), C(6f d4cfade750bf16), C(31 b1acd328815c81), C(ae6790e9fe24c57a), C(659 a16feab53eb5), C(6f d4cfade750bf16), C(31 b1acd328815c81), C(8 a711090a6ccfd44), C(363240 c31681b80e), C(ad791f19de0b07e9), C(d512217d21c7c370)}, {C(17 c648f416fb15ca), C(fe4d070d14d71a1d), C(ff22eac66f7eb0d3), C(fa4c10f92facc6c7), C(94 cad9e4daecfd58), C(6f fcf829a275d7ef), C(2 a35d2436894d549), C(fa4c10f92facc6c7), C(94 cad9e4daecfd58), C(6f fcf829a275d7ef), C(2 a35d2436894d549), C(c9ea25549513f5a), C(93f 7 cf06df2d0206), C(ef0da319d38fe57c), C(f715dc84df4f4a75)}, {C(8 b752dfa2f9fa592), C(ca95e87b662fe94d), C(34 da3aadfa49936d), C(bf1696df6e61f235), C(9724f ac2c03e3859), C(d9fd1463b07a8b61), C(f8e397251053d8ca), C(bf1696df6e61f235), C(9724f ac2c03e3859), C(d9fd1463b07a8b61), C(f8e397251053d8ca), C(c6d26d868c9e858e), C(2f 4 a1cb842ed6105), C(6 cc48927bd59d1c9), C(469e836 d0b7901e1)}, {C(3ed da5262a7869bf), C(a15eab8c522050c9), C(ba0853c48707207b), C(4 d751c1a836dcda3), C(9747 a6e96f1dd82c), C(3 c986fc5c9dc9755), C(a9d04f3a92844ecd), C(4 d751c1a836dcda3), C(9747 a6e96f1dd82c), C(3 c986fc5c9dc9755), C(a9d04f3a92844ecd), C(2 da9c6cede185e36), C(fae575ef03f987d6), C(b4a6a620b2bee11a), C(8 acba91c5813c424)}, {C(b5776f9ceaf0dba2), C(546ee e4cee927b0a), C(ce70d774c7b1cf77), C(7f 707785 c2d807d7), C(1ea8247 d40cdfae9), C(4945806ea c060028), C(1 a14948790321c37), C(7f 707785 c2d807d7), C(1ea8247 d40cdfae9), C(4945806ea c060028), C(1 a14948790321c37), C(ba3327bf0a6ab79e), C(54e2939592862 de8), C(b7d4651234fa11c7), C(d122970552454def)}, {C(313161f 3 ce61ec83), C(c6c5acb78303987d), C(f00761c6c6e44cee), C(ea660b39d2528951), C(e84537f81a44826a), C(b850bbb69593c26d), C(22499793145e1209), C(ea660b39d2528951), C(e84537f81a44826a), C(b850bbb69593c26d), C(22499793145e1209), C(4 c61b993560bbd58), C(636 d296abe771743), C(f1861b17b8bc3146), C(cd5fca4649d30f8a)}, {C(6e23080 c57f4bcb), C(5f 4 dad6078644535), C(f1591bc445804407), C(46 ca76959d0d4824), C(200 b16bb4031e6a5), C(3 d0e4718ed5363d2), C(4 c8cfcc96382106f), C(46 ca76959d0d4824), C(200 b16bb4031e6a5), C(3 d0e4718ed5363d2), C(4 c8cfcc96382106f), C(8 d6258d795b8097b), C(23 ae7cd1cab4b141), C(cbe74e8fd420afa), C(d553da4575629c63)}, {C(a194c120f440fd48), C(ac0d985eef446947), C(5 df9fa7d97244438), C(fce2269035535eba), C(2 d9b4b2010a90960), C(2 b0952b893dd72f0), C(9 a51e8462c1111de), C(fce2269035535eba), C(2 d9b4b2010a90960), C(2 b0952b893dd72f0), C(9 a51e8462c1111de), C(8682 b5e0624432a4), C(de8500edda7c67a9), C(4821 b171f562c5a2), C(ecb17dea1002e2df)}, {C(3 c78f67ee87b62fe), C(274 c83c73f20f662), C(25 a94c36d3763332), C(7e053f 1 b873bed61), C(d1c343547cd9c816), C(4 deee69b90a52394), C(14038f 0f 3128 ca46), C(7e053f 1 b873bed61), C(d1c343547cd9c816), C(4 deee69b90a52394), C(14038f 0f 3128 ca46), C(ebbf836e38c70747), C(c3c1077b9a7598d0), C(e73c720a27b07ba7), C(ec57f8a9a75af4d9)}, {C(b7d2aee81871e3ac), C(872 ac6546cc94ff2), C(a1b0d2f507ad2d8f), C(bdd983653b339252), C(c02783d47ab815f8), C(36 c5dc27d64d776c), C(5193988ee a7df808), C(bdd983653b339252), C(c02783d47ab815f8), C(36 c5dc27d64d776c), C(5193988ee a7df808), C(8 d8cca9c605cdb4a), C(334904f d32a1f934), C(dbfc15742057a47f), C(f3f92db42ec0cba1)}, {C(41ec0382933 e8f72), C(bd5e52d651bf3a41), C(cbf51a6873d4b29e), C(1 c8c650bfed2c546), C(9 c9085c070350c27), C(e82305be3bded854), C(cf56326bab3d685d), C(1 c8c650bfed2c546), C(9 c9085c070350c27), C(e82305be3bded854), C(cf56326bab3d685d), C(f94db129adc6cecc), C(1f 80871ec4 b35deb), C(c0dc1a4c74d63d0), C(d3cac509f998c174)}, {C(7f e4e777602797f0), C(626e62f 39f 7 c575d), C(d15d6185215fee2f), C(f82ef80641514b70), C(e2702de53389d34e), C(9950592 b7f2da8d8), C(d6b960bf3503f893), C(f82ef80641514b70), C(e2702de53389d34e), C(9950592 b7f2da8d8), C(d6b960bf3503f893), C(95 de69e4f131a9b), C(ee6f56eeff9cdefa), C(28f 4f 86 c2b856b72), C(b73d2decaac56b5b)}, {C(aa71127fd91bd68a), C(960f 6304500f 8069), C(5 cfa9758933beba8), C(dcbbdeb1f56b0ac5), C(45164 c603d084ce4), C(85693f 4ef7 e34314), C(e3a3e3a5ec1f6252), C(dcbbdeb1f56b0ac5), C(45164 c603d084ce4), C(85693f 4ef7 e34314), C(e3a3e3a5ec1f6252), C(91f 4711 c59532bab), C(5e5 a61d26f97200b), C(ffa65a1a41da5883), C(5f 0e712235371 eef)}, {C(677 b53782a8af152), C(90 d76ef694361f72), C(fa2cb9714617a9e0), C(72 c8667cc1e45aa9), C(3 a0aa035bbcd1ef6), C(588e89 b034fde91b), C(f62e4e1d81c1687), C(72 c8667cc1e45aa9), C(3 a0aa035bbcd1ef6), C(588e89 b034fde91b), C(f62e4e1d81c1687), C(1ea81508 efa11e09), C(1 cf493a4dcd49aad), C(8217 d0fbe8226130), C(607 b979c0eb297dd)}, {C(8f 97 bb03473c860f), C(e23e420f9a32e4a2), C(3432 c97895fea7cf), C(69 cc85dac0991c6c), C(4 a6c529f94e9c36a), C(e5865f8da8c887df), C(27e8 c77da38582e0), C(69 cc85dac0991c6c), C(4 a6c529f94e9c36a), C(e5865f8da8c887df), C(27e8 c77da38582e0), C(8e60596 b4e327dbc), C(955 cf21baa1ddb18), C(c24a8eb9360370aa), C(70 d75fd116c2cab1)}, {C(fe50ea9f58e4de6f), C(f0a085b814230ce7), C(89407f 0548f 90e9 d), C(6 c595ea139648eba), C(efe867c726ab2974), C(26f 48ec c1c3821cf), C(55 c63c1b3d0f1549), C(6 c595ea139648eba), C(efe867c726ab2974), C(26f 48ec c1c3821cf), C(55 c63c1b3d0f1549), C(552e5f 78e1 d87a69), C(c9bfe2747a4eedf0), C(d5230acb6ef95a1), C(1e812f 3 c0d9962bd)}, {C(56eb0f cb9852bd27), C(c817b9a578c7b12), C(45427842795 bfa84), C(8 dccc5f52a65030c), C(f89ffa1f4fab979), C(7 d94da4a61305982), C(1 ba6839d59f1a07a), C(8 dccc5f52a65030c), C(f89ffa1f4fab979), C(7 d94da4a61305982), C(1 ba6839d59f1a07a), C(e0162ec1f40d583e), C(6 abf0b85552c7c33), C(f14bb021a875867d), C(c12a569c8bfe3ba7)}, {C(6 be2903d8f07af90), C(26 aaf7b795987ae8), C(44 a19337cb53fdeb), C(f0e14afc59e29a3a), C(a4d0084172a98c0d), C(275998 a345d04f0f), C(db73704d81680e8d), C(f0e14afc59e29a3a), C(a4d0084172a98c0d), C(275998 a345d04f0f), C(db73704d81680e8d), C(351388 cf7529b1b1), C(a3155d0237571da5), C(355231 b516da2890), C(263 c5a3d498c1cc)}, {C(58668066 da6bfc4), C(a4ea2eb7212df3dd), C(481f 64f 7 ca220524), C(11 b3b649b1cea339), C(57f 4 ad5b54d71118), C(feeb30bec803ab49), C(6ed9 bcc1973d9bf9), C(11 b3b649b1cea339), C(57f 4 ad5b54d71118), C(feeb30bec803ab49), C(6ed9 bcc1973d9bf9), C(bf2859d9964a70c8), C(d31ab162ca25f24e), C(70349336f f55d5d5), C(9 a2fa97115ef4409)}, {C(2 d04d1fbab341106), C(efe0c5b2878b444c), C(882 a2a889b5e8e71), C(18 cc96be09e5455), C(1 ad58fd26919e409), C(76593521 c4a0006b), C(f1361f348fa7cbfb), C(18 cc96be09e5455), C(1 ad58fd26919e409), C(76593521 c4a0006b), C(f1361f348fa7cbfb), C(205 bc68e660b0560), C(74360e11f 9f c367e), C(a88b7b0fa86caf), C(a982d749b30d4e4c)}, {C(d366b37bcd83805b), C(a6d16fea50466886), C(cb76dfa8eaf74d70), C(389 c44e423749aa), C(a30d802bec4e5430), C(9 ac1279f92bea800), C(686ef471 c2624025), C(389 c44e423749aa), C(a30d802bec4e5430), C(9 ac1279f92bea800), C(686ef471 c2624025), C(2 c21a72f8e3a3423), C(df5ab83f0918646a), C(cd876e0cb4df80fa), C(5 abbb92679b3ea36)}, {C(bbb9bc819ab65946), C(25e0 c756c95803e2), C(82 a73a1e1cc9bf6a), C(671 b931b702519a3), C(61609e7 dc0dd9488), C(9 cb329b8cab5420), C(3 c64f8ea340096ca), C(671 b931b702519a3), C(61609e7 dc0dd9488), C(9 cb329b8cab5420), C(3 c64f8ea340096ca), C(1690 afe3befd3afb), C(4 d3c18a846602740), C(a6783133a31dd64d), C(ecf4665e6bc76729)}, {C(8e994 eac99bbc61), C(84 de870b6f3c114e), C(150ef c95ce7b0cd2), C(4 c5d48abf41185e3), C(86049 a83c7cdcc70), C(ad828ff609277b93), C(f60fe028d582ccc7), C(4 c5d48abf41185e3), C(86049 a83c7cdcc70), C(ad828ff609277b93), C(f60fe028d582ccc7), C(464e0 b174da0cbd4), C(eadf1df69041b06e), C(48 cb9c96a9df1cdc), C(b7e5ee62809223a1)}, {C(364 cabf6585e2f7d), C(3 be1cc452509807e), C(1236 ce85788680d4), C(4 cea77c54fc3583a), C(9 a2a64766fd77614), C(63e6 c9254b5dc4db), C(26 af12ba3bf5988e), C(4 cea77c54fc3583a), C(9 a2a64766fd77614), C(63e6 c9254b5dc4db), C(26 af12ba3bf5988e), C(4 a821aca3ffa26a1), C(99 aa9aacbb3d08e3), C(619 ac77b52e8a823), C(68 c745a1ce4b7adb)}, {C(e878e2200893d775), C(76 b1e0a25867a803), C(9 c14d6d91f5ae2c5), C(ac0ffd8d64e242ed), C(e1673ee2dd997587), C(8 cdf3e9369d61003), C(c37c9a5258b98eba), C(ac0ffd8d64e242ed), C(e1673ee2dd997587), C(8 cdf3e9369d61003), C(c37c9a5258b98eba), C(f252b2e7b67dd012), C(47f c1eb088858f28), C(59 c42e4af1353223), C(e05b6c61c19eb26e)}, {C(6f 6 a014b9a861926), C(269e13 a120277867), C(37f c8a181e78711b), C(33 dd054c41f3aef2), C(4f c8ab1a2ef3da7b), C(597178 c3756a06dc), C(748f 8 aadc540116f), C(33 dd054c41f3aef2), C(4f c8ab1a2ef3da7b), C(597178 c3756a06dc), C(748f 8 aadc540116f), C(78e3 be34de99461e), C(28 b7b60d90dddab4), C(e47475fa9327a619), C(88 b17629e6265924)}, {C(da52b64212e8149b), C(121e713 c1692086f), C(f3d63cfa03850a02), C(f0d82bafec3c564c), C(37 dece35b549a1ce), C(5f b28f6078c4a2bd), C(b69990b7d9405710), C(f0d82bafec3c564c), C(37 dece35b549a1ce), C(5f b28f6078c4a2bd), C(b69990b7d9405710), C(3 af5223132071100), C(56 d5bb35f3bb5d2a), C(fcad4a4d5d3a1bc7), C(f17bf3d8853724d0)}, {C(1100f 797 ce53a629), C(f528c6614a1a30c2), C(30e49f b56bec67fa), C(f991664844003cf5), C(d54f5f6c8c7cf835), C(ca9cc4437c591ef3), C(d5871c77cf8fb424), C(f991664844003cf5), C(d54f5f6c8c7cf835), C(ca9cc4437c591ef3), C(d5871c77cf8fb424), C(5 cf90f1e617b750c), C(1648f 825 ab986232), C(936 cf225126a60), C(90f a5311d6f2445c)}, {C(4f 00655 b76e9cfda), C(9 dc5c707772ed283), C(b0f885f1e01927ec), C(6e4 d6843289dfb47), C(357 b41c6e5fd561f), C(491e386 bacb6df3c), C(86 be1b64ecd9945c), C(6e4 d6843289dfb47), C(357 b41c6e5fd561f), C(491e386 bacb6df3c), C(86 be1b64ecd9945c), C(be9547e3cfd85fae), C(f9e26ac346b430a8), C(38508 b84b0e68cff), C(a28d49dbd5562703)}, {C(d970198b6ca854db), C(92e3 d1786ae556a0), C(99 a165d7f0d85cf1), C(6548910 c5f668397), C(a5c8d20873e7de65), C(5 b7c4ecfb8e38e81), C(6 aa50a5531dad63e), C(6548910 c5f668397), C(a5c8d20873e7de65), C(5 b7c4ecfb8e38e81), C(6 aa50a5531dad63e), C(ab903d724449e003), C(ea3cc836c28fef88), C(4 b250d6c7200949d), C(13 a110654fa916c0)}, {C(76 c850754f28803), C(a4bffed2982cb821), C(6710e352247 caf63), C(d9cbf5b9c31d964e), C(25 c8f890178b97ae), C(e7c46064676cde9f), C(d8bb5eeb49c06336), C(d9cbf5b9c31d964e), C(25 c8f890178b97ae), C(e7c46064676cde9f), C(d8bb5eeb49c06336), C(962 b35ae89d5f4c1), C(c49083801ac2c21), C(2 db46ddec36ff33b), C(da48992ab8da284)}, {C(9 c98da9763f0d691), C(f5437139a3d40401), C(6f 493 c26c42f91e2), C(e857e4ab2d124d5), C(6417 bb2f363f36da), C(adc36c9c92193bb1), C(d35bd456172df3df), C(e857e4ab2d124d5), C(6417 bb2f363f36da), C(adc36c9c92193bb1), C(d35bd456172df3df), C(577 da94064d3a3d6), C(23f 13 d7532ea496a), C(6e09392 d80b8e85b), C(2e05f f6f23663892)}, {C(22f 8f 6869 a5f325), C(a0e7a96180772c26), C(cb71ea6825fa3b77), C(39 d3dec4e718e903), C(900 c9fbdf1ae2428), C(305301 da2584818), C(c6831f674e1fdb1f), C(39 d3dec4e718e903), C(900 c9fbdf1ae2428), C(305301 da2584818), C(c6831f674e1fdb1f), C(8 ad0e38ffe71babf), C(554 ac85a8a837e64), C(9900 c582cf401356), C(169f 646 b01ed7762)}, {C(9 ae7575fc14256bb), C(ab9c5a397fabc1b3), C(1 d3f582aaa724b2e), C(94412f 598ef156), C(15 bf1a588f25b327), C(5756646 bd68ce022), C(f062a7d29be259a5), C(94412f 598ef156), C(15 bf1a588f25b327), C(5756646 bd68ce022), C(f062a7d29be259a5), C(aa99c683cfb60b26), C(9e3 b7d4b17f91273), C(301 d3f5422dd34cf), C(53 d3769127253551)}, {C(540040e79752 b619), C(670327e237 c88cb3), C(50962f 261 bcc31d9), C(9 a8ea2b68b2847ec), C(bc24ab7d4cbbda31), C(df5aff1cd42a9b57), C(db47d368295f4628), C(9 a8ea2b68b2847ec), C(bc24ab7d4cbbda31), C(df5aff1cd42a9b57), C(db47d368295f4628), C(9 a66c221d1bf3f3), C(7 ae74ee1281de8ee), C(a4e173e2c787621f), C(5 b51062d10ae472)}, {C(34 cbf85722d897b1), C(6208 cb2a0fff4eba), C(e926cbc7e86f544e), C(883706 c4321efee0), C(8f d5d3d84c7827e4), C(a5c80e455a7ccaaa), C(3515f 41164654591), C(883706 c4321efee0), C(8f d5d3d84c7827e4), C(a5c80e455a7ccaaa), C(3515f 41164654591), C(2 c08bfc75dbfd261), C(6e9 eadf14f8c965e), C(18783f 5770 cd19a3), C(a6c7f2f1aa7b59ea)}, {C(46 afa66366bf5989), C(aa0d424ac649008b), C(97 a9108b3cd9c5c9), C(6 ca08e09227a9630), C(8 b11f73a8e5b80eb), C(2391 bb535dc7ce02), C(e43e2529cf36f4b9), C(6 ca08e09227a9630), C(8 b11f73a8e5b80eb), C(2391 bb535dc7ce02), C(e43e2529cf36f4b9), C(c9bd6d82b7a73d9d), C(b2ed9bae888447ac), C(bd22bb13af0cd06d), C(62781441785 b355b)}, {C(e15074b077c6e560), C(7 c8f2173fcc34afa), C(8 aad55bc3bd38370), C(d407ecdbfb7cb138), C(642442eff 44578 af), C(d3e9fdaf71a5b79e), C(c87c53eda46aa860), C(d407ecdbfb7cb138), C(642442eff 44578 af), C(d3e9fdaf71a5b79e), C(c87c53eda46aa860), C(8462310 a2c76ff51), C(1 bc17a2e0976665e), C(6ec446 b13b4d79cf), C(388 c7a904b4264c1)}, {C(9740 b2b2d6d06c6), C(e738265f9de8dafc), C(fdc947c1fca8be9e), C(d6936b41687c1e3d), C(a1a2deb673345994), C(91501e58 b17168bd), C(b8edee2b0b708dfc), C(d6936b41687c1e3d), C(a1a2deb673345994), C(91501e58 b17168bd), C(b8edee2b0b708dfc), C(ddf4b43dafd17445), C(44015 d050a04ce5c), C(1019f d9ab82c4655), C(c803aea0957bcdd1)}, {C(f1431889f2db1bff), C(85257 aa1dc6bd0d0), C(1 abbdea0edda5be4), C(775 aa89d278f26c3), C(a542d20265e3ef09), C(933 bdcac58a33090), C(c43614862666ca42), C(775 aa89d278f26c3), C(a542d20265e3ef09), C(933 bdcac58a33090), C(c43614862666ca42), C(4 c5e54d481a9748d), C(65 ce3cd0db838b26), C(9 ccbb4005c7f09d2), C(e6dda9555dde899a)}, {C(e2dd273a8d28c52d), C(8 cd95915fdcfd96b), C(67 c0f5b1025f0699), C(cbc94668d48df4d9), C(7e3 d656e49d632d1), C(8329e30 cac7a61d4), C(38e6 cd1e2034e668), C(cbc94668d48df4d9), C(7e3 d656e49d632d1), C(8329e30 cac7a61d4), C(38e6 cd1e2034e668), C(41e0 bce03ed9394b), C(7 be48d0158b9834a), C(9ea8 d5d1a976b18b), C(606 c424c33617e7a)}, {C(e0f79029834cc6ac), C(f2b1dcb87cc5e94c), C(4210 bc221fe5e70a), C(fd4a4301d4e2ac67), C(8f 84358 d25b2999b), C(6 c4b7d8a5a22ccbb), C(25 df606bb23c9d40), C(fd4a4301d4e2ac67), C(8f 84358 d25b2999b), C(6 c4b7d8a5a22ccbb), C(25 df606bb23c9d40), C(915298 b0eaadf85b), C(5ec23 cc4c6a74e62), C(d640a4ff99763439), C(1603753f b34ad427)}, {C(9 dc0a29830bcbec1), C(ec4a01dbd52d96a0), C(cd49c657eff87b05), C(ea487fe948c399e1), C(f5de9b2e59192609), C(4604 d9b3248b3a5), C(1929878 a22c86a1d), C(ea487fe948c399e1), C(f5de9b2e59192609), C(4604 d9b3248b3a5), C(1929878 a22c86a1d), C(3 cf6cd7c19dfa1ef), C(46e404 ee4af2d726), C(613 ab0588a5527b5), C(73e39385 ced7e684)}, {C(d10b70dde60270a6), C(be0f3b256e23422a), C(6 c601297a3739826), C(e327ffc477cd2467), C(ebebba63911f32b2), C(2 c2c5c24cf4970a2), C(a3cd2c192c1b8bf), C(e327ffc477cd2467), C(ebebba63911f32b2), C(2 c2c5c24cf4970a2), C(a3cd2c192c1b8bf), C(94 cb02c94aaf250b), C(30 ca38d5e3dac579), C(d68598a91dc597b5), C(162 b050e8de2d92)}, {C(58 d2459f094d075c), C(b4df247528d23251), C(355283f 2128 a9e71), C(d046198e4df506c2), C(c61bb9705786ae53), C(b360200380d10da8), C(59942 bf009ee7bc), C(d046198e4df506c2), C(c61bb9705786ae53), C(b360200380d10da8), C(59942 bf009ee7bc), C(95806 d027f8d245e), C(32 df87487ed9d0f4), C(e2c5bc224ce97a98), C(9 a47c1e33cfb1cc5)}, {C(68 c600cdd42d9f65), C(bdf0c331f039ff25), C(1354 ac1d98944023), C(b5cdfc0b06fd1bd9), C(71f 0 ce33b183efab), C(d8ae4f9d4b949755), C(877 da19d6424f6b3), C(b5cdfc0b06fd1bd9), C(71f 0 ce33b183efab), C(d8ae4f9d4b949755), C(877 da19d6424f6b3), C(f7cc5cbf76bc6006), C(c93078f44b98efdb), C(3 d482142c727e8bc), C(8e23f 92e0616 d711)}, {C(9f c0bd876cb975da), C(80f 41015045 d1ade), C(5 cbf601fc55c809a), C(7 d9c567075001705), C(a2fafeed0df46d5d), C(a70b82990031da8f), C(8611 c76abf697e56), C(7 d9c567075001705), C(a2fafeed0df46d5d), C(a70b82990031da8f), C(8611 c76abf697e56), C(806911617e1 ee53), C(1 ce82ae909fba503), C(52 df85fea9e404bd), C(dbd184e5d9a11a3e)}, {C(7 b3e8c267146c361), C(c6ad095af345b726), C(af702ddc731948bd), C(7 ca4c883bded44b5), C(c90beb31ee9b699a), C(2 cdb4aba3d59b8a3), C(df0d4fa685e938f0), C(7 ca4c883bded44b5), C(c90beb31ee9b699a), C(2 cdb4aba3d59b8a3), C(df0d4fa685e938f0), C(cc0e568e91aaa382), C(70 ca583a464dbea), C(b7a5859b44710e1a), C(ad141467fdf9a83a)}, {C(6 c49c6b3c9dd340f), C(897 c41d89af37bd1), C(52 df69e0e2c68a8d), C(eec4be1f65531a50), C(bf23d928f20f1b50), C(c642009b9c593940), C(c5e59e6ca9e96f85), C(eec4be1f65531a50), C(bf23d928f20f1b50), C(c642009b9c593940), C(c5e59e6ca9e96f85), C(7f bd53343e7da499), C(dd87e7b88afbd251), C(92696e7683 b9f322), C(60f f51ef02c24652)}, {C(47324327 a4cf1732), C(6044753 d211e1dd5), C(1ec ae46d75192d3b), C(b6d6315a902807e3), C(ccc8312c1b488e5d), C(b933a7b48a338ec), C(9 d6753cd83422074), C(b6d6315a902807e3), C(ccc8312c1b488e5d), C(b933a7b48a338ec), C(9 d6753cd83422074), C(5714 bd5c0efdc7a8), C(221585e2 c88068ca), C(303342 b25678904), C(8 c174a03e69a76e)}, {C(1e984 ef53c5f6aae), C(99ea10 dac804298b), C(a3f8c241100fb14d), C(259eb3 c63a9c9be6), C(f8991532947c7037), C(a16d20b3fc29cfee), C(493 c2e91a775af8c), C(259eb3 c63a9c9be6), C(f8991532947c7037), C(a16d20b3fc29cfee), C(493 c2e91a775af8c), C(275f ccf4acb08abc), C(d13fb6ea3eeaf070), C(505283e5 b702b9ea), C(64 c092f9f8df1901)}, {C(b88f5c9b8b854cc6), C(54f c5d39825b446), C(a12fc1546eac665d), C(ab90eb7fa58b280c), C(dda26598356aa599), C(64191 d63f2586e52), C(cada0075c34e8b02), C(ab90eb7fa58b280c), C(dda26598356aa599), C(64191 d63f2586e52), C(cada0075c34e8b02), C(e7de6532b691d87c), C(a28fec86e368624), C(796 c280eebd0241a), C(acfcecb641fdbeee)}, {C(9f cb3fdb09e7a63a), C(7 a115c9ded150112), C(e9ba629108852f37), C(9 b03c7c218c192a), C(93 c1dd563f46308e), C(f9553625917ea800), C(e0a52f8a5024c59), C(9 b03c7c218c192a), C(93 c1dd563f46308e), C(f9553625917ea800), C(e0a52f8a5024c59), C(2 bb3a9e8b053e490), C(8 b97936723cd8ff6), C(bf3f835246d02722), C(c8e033da88ecd724)}, {C(d58438d62089243), C(d8c19375b228e9d3), C(13042546ed96 e790), C(4 a42ef343514138c), C(549e62449 e225cf1), C(dd8260e2808f68e8), C(69580f c81fcf281b), C(4 a42ef343514138c), C(549e62449 e225cf1), C(dd8260e2808f68e8), C(69580f c81fcf281b), C(fc0e30d682e87289), C(f44b784248d6107b), C(df25119527fdf209), C(cc265612588171a8)}, {C(7ea73 b6b74c8cd0b), C(e07188dd9b5bf3ca), C(6ef62f f2dd008ed4), C(acd94b3038342152), C(1 b0ed99c9b7ba297), C(b794a93f4c895939), C(97 a60cd93021206d), C(acd94b3038342152), C(1 b0ed99c9b7ba297), C(b794a93f4c895939), C(97 a60cd93021206d), C(9e0 c0e6da5001b07), C(5f 5 b817de5d2a391), C(35 b8a8702acdd533), C(3 bbcfef344f455)}, {C(e42ffdf6278bb21), C(59 df3e5ca582ff9d), C(f3108785599dbde9), C(f78e8a2d4aba6a1d), C(700473f b0d8380fc), C(d0a0d68061ac74b2), C(11650612f a426e5a), C(f78e8a2d4aba6a1d), C(700473f b0d8380fc), C(d0a0d68061ac74b2), C(11650612f a426e5a), C(e39ceb5b2955710c), C(f559ff201f8cebaa), C(1f bc182809e829a0), C(295 c7fc82fa6fb5b)}, {C(9 ad37fcd49fe4aa0), C(76 d40da71930f708), C(bea08b630f731623), C(797292108901 a81f), C(3 b94127b18fae49c), C(688247179f 144f 1 b), C(48 a507a1625d13d7), C(797292108901 a81f), C(3 b94127b18fae49c), C(688247179f 144f 1 b), C(48 a507a1625d13d7), C(452322 aaad817005), C(51 d730d973e13d44), C(c883eb30176652ea), C(8 d338fd678b2404d)}, {C(27 b7ff391136696e), C(60 db94a18593438c), C(b5e46d79c4dafbad), C(ad56fd25a6f15289), C(68 a0ec7c0179df80), C(a0aacfc36620957), C(87 a0762a09e2e1c1), C(ad56fd25a6f15289), C(68 a0ec7c0179df80), C(a0aacfc36620957), C(87 a0762a09e2e1c1), C(d50ace99460f0be3), C(7f 1f e5653ae0d999), C(3870899 d9d6c22c), C(df5f952dd90d5a09)}, {C(76 bd077e42692ddf), C(c14b60958c2c7a85), C(fd9f3b0b3b1e2738), C(273 d2c51a8e65e71), C(ac531423f670bf34), C(7f 40 c6bfb8c5758a), C(5f de65b433a10b02), C(273 d2c51a8e65e71), C(ac531423f670bf34), C(7f 40 c6bfb8c5758a), C(5f de65b433a10b02), C(dbda6c4252b0a75c), C(5 d4cfd8f937b23d9), C(3895f 478e1 c29c9d), C(e3e7c1fd1199aec6)}, {C(81 c672225442e053), C(927 c3f6c8964050e), C(cb59f8f2bb36fac5), C(298f 3583326f d942), C(b85602a9a2e2f97c), C(65 c849bfa3191459), C(bf21329dfb496c0d), C(298f 3583326f d942), C(b85602a9a2e2f97c), C(65 c849bfa3191459), C(bf21329dfb496c0d), C(ea7b7b44c596aa18), C(c18bfb6e9a36d59c), C(1 b55f03e8a38cc0a), C(b6a94cd47bbf847f)}, {C(37 b9e308747448ca), C(513f 39f 5545 b1bd), C(145 b32114ca00f9c), C(cce24b9910eb0489), C(af4ac64668ac57d9), C(ea0e44c13a9a5d5e), C(b224fb0c680455f4), C(cce24b9910eb0489), C(af4ac64668ac57d9), C(ea0e44c13a9a5d5e), C(b224fb0c680455f4), C(a7714bbba8699be7), C(fecad6e0e0092204), C(c1ce8bd5ac247eb4), C(3993 aef5c07cdca2)}, {C(dab71695950a51d4), C(9e98 e4dfa07566fe), C(fab3587513b84ec0), C(2409f 60f 0854f 305), C(b17f6e6c8ff1894c), C(62f a048551dc7ad6), C(d99f4fe2799bad72), C(2409f 60f 0854f 305), C(b17f6e6c8ff1894c), C(62f a048551dc7ad6), C(d99f4fe2799bad72), C(4 a38e7f2f4a669d3), C(53173510 ca91f0e3), C(cc9096c0df860b0), C(52ed637026 a4a0d5)}, {C(28630288285 c747b), C(a165a5bf51aaec95), C(927 d211f27370016), C(727 c782893d30c22), C(742706852989 c247), C(c546494c3bb5e7e2), C(1f b2a5d1570f5dc0), C(727 c782893d30c22), C(742706852989 c247), C(c546494c3bb5e7e2), C(1f b2a5d1570f5dc0), C(71e498804 df91b76), C(4 a6a5aa6f7e5621), C(871 a63730d13a544), C(63f 77 c8f371cc2f8)}, {C(4 b591ad5160b6c1b), C(e8f85ddd5a1143f7), C(377e18171476 d64), C(829481773 cce2cb1), C(c9d9fb4e25e4d243), C(c1fff894f0cf713b), C(69ed d73ec20984b0), C(829481773 cce2cb1), C(c9d9fb4e25e4d243), C(c1fff894f0cf713b), C(69ed d73ec20984b0), C(7f b1132262925f4a), C(a292e214fe56794f), C(915 bfee68e16f46f), C(98 bcc857bb6d31e7)}, {C(7e02f 7 a5a97dd3df), C(9724 a88ac8c30809), C(d8dee12589eeaf36), C(c61f8fa31ad1885b), C(3e3744 e04485ff9a), C(939335 b37f34c7a2), C(faa5de308dbbbc39), C(c61f8fa31ad1885b), C(3e3744 e04485ff9a), C(939335 b37f34c7a2), C(faa5de308dbbbc39), C(f5996b1be7837a75), C(4f cb12d267f5af4f), C(39 be67b8cd132169), C(5 c39e3819198b8a1)}, {C(ff66660873521fb2), C(d82841f7e714ce03), C(c830d273f005e378), C(66990 c8c54782228), C(4f 28 bea83dda97c), C(6 a24c64698688de0), C(69721141111 da99b), C(66990 c8c54782228), C(4f 28 bea83dda97c), C(6 a24c64698688de0), C(69721141111 da99b), C(d5c771fade83931b), C(8094ed75 e6feb396), C(7 a79d4de8efd1a2c), C(5f 9e50167693 e363)}, {C(ef3c4dd60fa37412), C(e8d2898c86d11327), C(8 c883d860aafacfe), C(a4ace72ba19d6de5), C(4 cae26627dfc5511), C(38e496 de9f677b05), C(558770996e1906 d6), C(a4ace72ba19d6de5), C(4 cae26627dfc5511), C(38e496 de9f677b05), C(558770996e1906 d6), C(40 df30e332ceca69), C(8f 106 cbd94166c42), C(332 b6ab4f4c1014e), C(7 c0bc3092ad850e5)}, {C(a7b07bcb1a1333ba), C(9 d007956720914c3), C(4751f 60ef2 b15545), C(77 ac4dcee10c9023), C(e90235108fa20e56), C(1 d3ea38535215800), C(5ed1 ccfff26bc64), C(77 ac4dcee10c9023), C(e90235108fa20e56), C(1 d3ea38535215800), C(5ed1 ccfff26bc64), C(789 a1c352bf5c61e), C(860 a119056da8252), C(a6c268a238699086), C(4 d70f5cccf4ef2eb)}, {C(89858f c94ee25469), C(f72193b78aeaa896), C(7 dba382760727c27), C(846 b72f372f1685a), C(f708db2fead5433c), C(c04e121770ee5dc), C(4619793 b67d0daa4), C(846 b72f372f1685a), C(f708db2fead5433c), C(c04e121770ee5dc), C(4619793 b67d0daa4), C(79f 80506f 152285f), C(5300074926f ccd56), C(7f bbff6cc418fce6), C(b908f77c676b32e4)}, {C(e6344d83aafdca2e), C(6e147816 e6ebf87), C(8508 c38680732caf), C(f4ce36d3a375c981), C(9 d67e5572f8d7bf4), C(900 d63d9ec79e477), C(5251 c85ab52839a3), C(f4ce36d3a375c981), C(9 d67e5572f8d7bf4), C(900 d63d9ec79e477), C(5251 c85ab52839a3), C(92ec4 b3952e38027), C(40 b2dc421a518cbf), C(661ea97 b2331a070), C(8 d428a4a9485179b)}, {C(3 ddbb400198d3d4d), C(fe73de3ada21af5c), C(cd7df833dacd8da3), C(162 be779eea87bf8), C(7 d62d36edf759e6d), C(dc20f528362e37b2), C(1 a902edfe4a5824e), C(162 be779eea87bf8), C(7 d62d36edf759e6d), C(dc20f528362e37b2), C(1 a902edfe4a5824e), C(e6a258d30fa817ba), C(c5d73adf6fb196fd), C(475 b7a6286a207fb), C(d35f96363e8eba95)}, {C(79 d4c20cf83a7732), C(651ea0 a6ab059bcd), C(94631144f 363 cdef), C(894 a0ee0c1f87a22), C(4e682573f 8 b38f25), C(89803f c082816289), C(71613963 a02d90e1), C(894 a0ee0c1f87a22), C(4e682573f 8 b38f25), C(89803f c082816289), C(71613963 a02d90e1), C(4 c6cc0e5a737c910), C(a3765b5da16bccd9), C(8 bf483c4d735ec96), C(7f d7c8ba1934afec)}, {C(5 aaf0d7b669173b5), C(19661 ca108694547), C(5 d03d681639d71fe), C(7 c422f4a12fd1a66), C(aa561203e7413665), C(e99d8d202a04d573), C(6090357ec6f 1f 1), C(7 c422f4a12fd1a66), C(aa561203e7413665), C(e99d8d202a04d573), C(6090357ec6f 1f 1), C(dbfe89f01f0162e), C(49 aa89da4f1e389b), C(7119 a6f4514efb22), C(56593f 6 b4e7318d9)}, {C(35 d6cc883840170c), C(444694 c4f8928732), C(98500f 14 b8741c6), C(5021 ac9480077dd), C(44 c2ebc11cfb9837), C(e5d310c4b5c1d9fd), C(a577102c33ac773c), C(5021 ac9480077dd), C(44 c2ebc11cfb9837), C(e5d310c4b5c1d9fd), C(a577102c33ac773c), C(a00d2efd2effa3cf), C(c2c33ffcda749df6), C(d172099d3b6f2986), C(f308fe33fcd23338)}, {C(b07eead7a57ff2fe), C(c1ffe295ca7dbf47), C(ef137b125cfa8851), C(8f 8ee c5cde7a490a), C(79916 d20a405760b), C(3 c30188c6d38c43c), C(b17e3c3ff7685e8d), C(8f 8ee c5cde7a490a), C(79916 d20a405760b), C(3 c30188c6d38c43c), C(b17e3c3ff7685e8d), C(ac8aa3cd0790c4c9), C(78 ca60d8bf10f670), C(26f 522 be4fbc1184), C(55 bc7688083326d4)}, {C(20f ba36c76380b18), C(95 c39353c2a3477d), C(4f 362902 cf9117ad), C(89816ec851 e3f405), C(65258396f 932858 d), C(b7dcaf3cc57a0017), C(b368f482afc90506), C(89816ec851 e3f405), C(65258396f 932858 d), C(b7dcaf3cc57a0017), C(b368f482afc90506), C(88f 08 c74465015f1), C(94eb af209d59099d), C(c1b7ff7304b0a87), C(56 bf8235257d4435)}, {C(c7e9e0c45afeab41), C(999 d95f41d9ee841), C(55ef15 ac11ea010), C(cc951b8eab5885d), C(956 c702c88ac056b), C(de355f324a37e3c0), C(ed09057eb60bd463), C(cc951b8eab5885d), C(956 c702c88ac056b), C(de355f324a37e3c0), C(ed09057eb60bd463), C(1f 44 b6d04a43d088), C(53631822 a26ba96d), C(90305f c2d21f8d28), C(60693 a9a6093351a)}, {C(69 a8e59c1577145d), C(cb04a6e309ebc626), C(9 b3326a5b250e9b1), C(d805f665265fd867), C(82 b2b019652c19c6), C(f0df7738353c82a6), C(6 a9acf124383ca5f), C(d805f665265fd867), C(82 b2b019652c19c6), C(f0df7738353c82a6), C(6 a9acf124383ca5f), C(6838374508 a7a99f), C(7 b6719db8d3e40af), C(1 a22666cf0dcb7cf), C(989 a9cf7f46b434d)}, {C(6638191337226509), C(42 b55e08e4894870), C(a7696f5fbd51878e), C(433 bbdd27481d85d), C(ee32136b5a47bbec), C(769 a77f346d82f4e), C(38 b91b1cb7e34be), C(433 bbdd27481d85d), C(ee32136b5a47bbec), C(769 a77f346d82f4e), C(38 b91b1cb7e34be), C(cb10fd95c0e43875), C(ce9744efd6f11427), C(946 b32bddada6a13), C(35 d544690b99e3b6)}, {C(c44e8c33ff6c5e13), C(1f 128 a22aab3007f), C(6 a8b41bf04cd593), C(1 b9b0deaf126522a), C(cc51d382baedc2eb), C(8 df8831bb2e75daa), C(de4e7a4b5de99588), C(1 b9b0deaf126522a), C(cc51d382baedc2eb), C(8 df8831bb2e75daa), C(de4e7a4b5de99588), C(55 a2707103a9f968), C(e0063f4e1649702d), C(7e82f 5 b440e74043), C(649 b44a27f00219d)}, {C(68125009158 bded7), C(563 a9a62753fc088), C(b97a9873a352cf6a), C(237 d1de15ae56127), C(b96445f758ba57d), C(b842628a9f9938eb), C(70313 d232dc2cd0d), C(237 d1de15ae56127), C(b96445f758ba57d), C(b842628a9f9938eb), C(70313 d232dc2cd0d), C(8 bfe1f78cb40ad5b), C(a5bde811d49f56e1), C(1 acd0cf913ded507), C(820 b3049fa5e6786)}, {C(e0dd644db35a62d6), C(292889772752 ab42), C(b80433749dbb8793), C(7032f e67035f95db), C(d8076d1fda17eb8d), C(115 ca1775560f946), C(92 da1e16f396bf61), C(7032f e67035f95db), C(d8076d1fda17eb8d), C(115 ca1775560f946), C(92 da1e16f396bf61), C(17 c8bc7f6d23a639), C(fb28a2afa4d562a9), C(6 c59c95fa2450d5f), C(fe0d41d5ebfbce2a)}, {C(21 ce9eab220aaf87), C(27 d20caec922d708), C(610 c51f976cb1d30), C(6052f 97 a1e02d2ba), C(836ee a7ce63dea17), C(e1f8efb81b443b45), C(ddbdbbe717570246), C(6052f 97 a1e02d2ba), C(836ee a7ce63dea17), C(e1f8efb81b443b45), C(ddbdbbe717570246), C(69551045 b0e56f60), C(625 a435960ba7466), C(9 cdb004e8b11405c), C(d6284db99a3b16af)}, {C(83 b54046fdca7c1e), C(e3709e9153c01626), C(f306b5edc2682490), C(88f 14 b0b554fba02), C(a0ec13fac0a24d0), C(f468ebbc03b05f47), C(a9cc417c8dad17f0), C(88f 14 b0b554fba02), C(a0ec13fac0a24d0), C(f468ebbc03b05f47), C(a9cc417c8dad17f0), C(4 c1ababa96d42275), C(c112895a2b751f17), C(5 dd7d9fa55927aa9), C(ca09db548d91cd46)}, {C(dd3b2ce7dabb22fb), C(64888 c62a5cb46ee), C(f004e8b4b2a97362), C(31831 cf3efc20c84), C(901 ba53808e677ae), C(4 b36895c097d0683), C(7 d93ad993f9179aa), C(31831 cf3efc20c84), C(901 ba53808e677ae), C(4 b36895c097d0683), C(7 d93ad993f9179aa), C(a4c5ea29ae78ba6b), C(9 cf637af6d607193), C(5731 bd261d5b3adc), C(d59a9e4f796984f3)}, {C(9ee08f c7a86b0ea6), C(5 c8d17dff5768e66), C(18859672 bafd1661), C(d3815c5f595e513e), C(44 b3bdbdc0fe061f), C(f5f43b2a73ad2df5), C(7 c0e6434c8d7553c), C(d3815c5f595e513e), C(44 b3bdbdc0fe061f), C(f5f43b2a73ad2df5), C(7 c0e6434c8d7553c), C(8 c05859060821002), C(73629 a0d275008ce), C(860 c012879e6f00f), C(d48735a120d2c37c)}, {C(4e2 a10f1c409dfa5), C(6e684591f 5 da86bd), C(ff8c9305d447cadb), C(c43ae49df25b1c86), C(d4f42115cee1ac8), C(a0e6a714471b975c), C(a40089dec5fe07b0), C(c43ae49df25b1c86), C(d4f42115cee1ac8), C(a0e6a714471b975c), C(a40089dec5fe07b0), C(18 c3d8f967915e10), C(739 c747dbe05adfb), C(4 b0397b596e16230), C(3 c57d7e1de9e58d1)}, {C(bdf3383d7216ee3c), C(eed3a37e4784d324), C(247 cff656d081ba0), C(76059e4 cb25d4700), C(e0af815fe1fa70ed), C(5 a6ccb4f36c5b3df), C(391 a274cd5f5182d), C(76059e4 cb25d4700), C(e0af815fe1fa70ed), C(5 a6ccb4f36c5b3df), C(391 a274cd5f5182d), C(ff1579baa6a2b511), C(c385fc5062e8a728), C(e940749739a37c78), C(a093523a5b5edee5)}, {C(a22e8f6681f0267d), C(61e79 bc120729914), C(86ec13 c84c1600d3), C(1614811 d59dcab44), C(d1ddcca9a2675c33), C(f3c551d5fa617763), C(5 c78d4181402e98c), C(1614811 d59dcab44), C(d1ddcca9a2675c33), C(f3c551d5fa617763), C(5 c78d4181402e98c), C(b43b4a9caa6f5d4c), C(f112829bca2df8f3), C(87e5 c85db80d06c3), C(8eb4 bac85453409)}, {C(6997121 cae0ce362), C(ba3594cbcc299a07), C(7e4 b71c7de25a5e4), C(16 ad89e66db557ba), C(a43c401140ffc77d), C(3780 a8b3fd91e68), C(48190678248 a06b5), C(16 ad89e66db557ba), C(a43c401140ffc77d), C(3780 a8b3fd91e68), C(48190678248 a06b5), C(d10deb97b651ad42), C(3 a69f3f29046a24f), C(f7179735f2c6dab4), C(ac82965ad3b67a02)}, {C(9 bfc2c3e050a3c27), C(dc434110e1059ff3), C(5426055 da178decd), C(cb44d00207e16f99), C(9 d9e99afedc8107f), C(56907 c4fb7b3bc01), C(bcff1472bb01f85a), C(cb44d00207e16f99), C(9 d9e99afedc8107f), C(56907 c4fb7b3bc01), C(bcff1472bb01f85a), C(516f 800f 74 ad0985), C(f93193ade9614da4), C(9f 4 a7845355b75b7), C(423 c17045824dea5)}, {C(a3f37e415aedf14), C(8 d21c92bfa0dc545), C(a2715ebb07deaf80), C(98 ce1ff2b3f99f0f), C(162 acfd3b47c20bf), C(62 b9a25fd39dc6c0), C(c165c3c95c878dfe), C(98 ce1ff2b3f99f0f), C(162 acfd3b47c20bf), C(62 b9a25fd39dc6c0), C(c165c3c95c878dfe), C(2 b9a7e1f055bd27c), C(e91c8099cafaa75d), C(37e38 d64ef0263b), C(a46e89f47a1a70d5)}, {C(cef3c748045e7618), C(41 dd44faef4ca301), C(6 add718a88f383c6), C(1197ec a317e70a93), C(61f 9497e6 cc4a33), C(22e7178 d1e57af73), C(5 df95da0ff1c6435), C(1197ec a317e70a93), C(61f 9497e6 cc4a33), C(22e7178 d1e57af73), C(5 df95da0ff1c6435), C(934327643705e56 c), C(11eb0 eec553137c9), C(1e6 b9b57ac5283ec), C(6934785 db184b2e4)}, {C(fe2b841766a4d212), C(42 cf817e58fe998c), C(29f 7f 493 ba9cbe6c), C(2 a9231d98b441827), C(fca55e769df78f6c), C(da87ea680eb14df4), C(e0b77394b0fd2bcc), C(2 a9231d98b441827), C(fca55e769df78f6c), C(da87ea680eb14df4), C(e0b77394b0fd2bcc), C(f36a2a3c73ab371a), C(d52659d36d93b71), C(3 d3b7d2d2fafbb14), C(b4b7b317d9266711)}, {C(d6131e688593a181), C(5 b658b282688ccd3), C(b9f7c066beed1204), C(e9dd79bad89f6b19), C(b420092bae6aaf41), C(515f 9 bbd06069d77), C(80664957 a02cbc29), C(e9dd79bad89f6b19), C(b420092bae6aaf41), C(515f 9 bbd06069d77), C(80664957 a02cbc29), C(f9dc7a744a56d9b3), C(7eb2 bdcd6667f383), C(c5914296fbdaf9d1), C(af0d5a8fec374fc4)}, {C(91288884ebf cf145), C(3 dffd892d36403af), C(7 c4789db82755080), C(634 acbe037edec27), C(878 a97fab822d804), C(fcb042af908f0577), C(4 cbafc318bb90a2e), C(634 acbe037edec27), C(878 a97fab822d804), C(fcb042af908f0577), C(4 cbafc318bb90a2e), C(68 a96d589d5e5654), C(a752cb250bca1bc0), C(8f 228f 406024 aa7e), C(fc5408cf22a080b5)}, {C(754 c7e98ae3495ea), C(2030124 a22512c19), C(ec241579c626c39d), C(e682b5c87fa8e41b), C(6 cfa4baff26337ac), C(4 d66358112f09b2a), C(58889 d3f50ffa99c), C(33f c6ffd1ffb8676), C(36 db7617b765f6e2), C(8 df41c03c514a9dc), C(6707 cc39a809bb74), C(3f 27 d7bb79e31984), C(a39dc6ac6cb0b0a8), C(33f c6ffd1ffb8676), C(36 db7617b765f6e2)}, }; void Check(uint64 expected, uint64 actual) { if (expected != actual) { fprintf(stderr, "ERROR: expected %llx, but got %llx", expected, actual); ++errors; } } void Test(const uint64 *expected, int offset, int len) { const uint128 u = CityHash128(data + offset, len); const uint128 v = CityHash128WithSeed(data + offset, len, kSeed128); Check(expected[0], CityHash64(data + offset, len)); Check(expected[1], CityHash64WithSeed(data + offset, len, kSeed0)); Check(expected[2], CityHash64WithSeeds(data + offset, len, kSeed0, kSeed1)); Check(expected[3], Uint128Low64(u)); Check(expected[4], Uint128High64(u)); Check(expected[5], Uint128Low64(v)); Check(expected[6], Uint128High64(v)); #ifdef __SSE4_2__ const uint128 y = CityHashCrc128(data + offset, len); const uint128 z = CityHashCrc128WithSeed(data + offset, len, kSeed128); uint64 crc256_results[4]; CityHashCrc256(data + offset, len, crc256_results); Check(expected[7], Uint128Low64(y)); Check(expected[8], Uint128High64(y)); Check(expected[9], Uint128Low64(z)); Check(expected[10], Uint128High64(z)); int i; for (i = 0; i < 4; i++) { /* suppress block warning */ Check(expected[11 + i], crc256_results[i]); } #endif } int main(int argc, char **argv) { setup(); int i; for (i = 0; i < kTestSize - 1; i++) { /* suppress block warning */ Test(testdata[i], i * i, i); } Test(testdata[i], 0, kDataSize); return errors > 0; } ntirpc-1.3.1/src/city.c000066400000000000000000000361731261345040100147240ustar00rootroot00000000000000/* city.c - cityhash-c * CityHash on C * Copyright (c) 2011-2012, Alexander Nusov * * - original copyright notice - * Copyright (c) 2011 Google, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * CityHash, by Geoff Pike and Jyrki Alakuijala * * This file provides CityHash64() and related functions. * * It's probably possible to create even faster hash functions by * writing a program that systematically explores some of the space of * possible hash functions, by using SIMD instructions, or by * compromising on hash quality. */ #include #include static uint64 UNALIGNED_LOAD64(const char *p) { uint64 result; memcpy(&result, p, sizeof(result)); return result; } static uint32 UNALIGNED_LOAD32(const char *p) { uint32 result; memcpy(&result, p, sizeof(result)); return result; } #if !defined(WORDS_BIGENDIAN) #define uint32_in_expected_order(x) (x) #define uint64_in_expected_order(x) (x) #else #ifdef _MSC_VER #include #define bswap_32(x) _byteswap_ulong(x) #define bswap_64(x) _byteswap_uint64(x) #elif defined(__APPLE__) /* Mac OS X / Darwin features */ #include #define bswap_32(x) OSSwapInt32(x) #define bswap_64(x) OSSwapInt64(x) #else #include #endif #define uint32_in_expected_order(x) (bswap_32(x)) #define uint64_in_expected_order(x) (bswap_64(x)) #endif /* WORDS_BIGENDIAN */ #if !defined(LIKELY) #if HAVE_BUILTIN_EXPECT #define LIKELY(x) (__builtin_expect(!!(x), 1)) #else #define LIKELY(x) (x) #endif #endif static uint64 Fetch64(const char *p) { return uint64_in_expected_order(UNALIGNED_LOAD64(p)); } static uint32 Fetch32(const char *p) { return uint32_in_expected_order(UNALIGNED_LOAD32(p)); } /* Some primes between 2^63 and 2^64 for various uses. */ static const uint64 k0 = 0xc3a5c85c97cb3127ULL; static const uint64 k1 = 0xb492b66fbe98f273ULL; static const uint64 k2 = 0x9ae16a3b2f90404fULL; static const uint64 k3 = 0xc949d7c7509e6557ULL; /* Hash 128 input bits down to 64 bits of output. * This is intended to be a reasonably good hash function. */ static inline uint64 Hash128to64(const uint128 x) { /* Murmur-inspired hashing. */ const uint64 kMul = 0x9ddfea08eb382d69ULL; uint64 a = (Uint128Low64(x) ^ Uint128High64(x)) * kMul; a ^= (a >> 47); uint64 b = (Uint128High64(x) ^ a) * kMul; b ^= (b >> 47); b *= kMul; return b; } /* Bitwise right rotate. Normally this will compile to a single * instruction, especially if the shift is a manifest constant. */ static uint64 Rotate(uint64 val, int shift) { /* Avoid shifting by 64: doing so yields an undefined result. */ return shift == 0 ? val : ((val >> shift) | (val << (64 - shift))); } /* Equivalent to Rotate(), but requires the second arg to be non-zero. * On x86-64, and probably others, it's possible for this to compile * to a single instruction if both args are already in registers. */ static uint64 RotateByAtLeast1(uint64 val, int shift) { return (val >> shift) | (val << (64 - shift)); } static uint64 ShiftMix(uint64 val) { return val ^ (val >> 47); } static uint64 HashLen16(uint64 u, uint64 v) { uint128 result; result.first = u; result.second = v; return Hash128to64(result); } static uint64 HashLen0to16(const char *s, size_t len) { if (len > 8) { uint64 a = Fetch64(s); uint64 b = Fetch64(s + len - 8); return HashLen16(a, RotateByAtLeast1(b + len, len)) ^ b; } if (len >= 4) { uint64 a = Fetch32(s); return HashLen16(len + (a << 3), Fetch32(s + len - 4)); } if (len > 0) { uint8 a = s[0]; uint8 b = s[len >> 1]; uint8 c = s[len - 1]; uint32 y = (uint32) (a) + ((uint32) (b) << 8); uint32 z = len + ((uint32) (c) << 2); return ShiftMix(y * k2 ^ z * k3) * k2; } return k2; } /* This probably works well for 16-byte strings as well, but it may be overkill * in that case. */ static uint64 HashLen17to32(const char *s, size_t len) { uint64 a = Fetch64(s) * k1; uint64 b = Fetch64(s + 8); uint64 c = Fetch64(s + len - 8) * k2; uint64 d = Fetch64(s + len - 16) * k0; return HashLen16(Rotate(a - b, 43) + Rotate(c, 30) + d, a + Rotate(b ^ k3, 20) - c + len); } /* Return a 16-byte hash for 48 bytes. Quick and dirty. Callers do best to use "random-looking" values for a and b. static pair WeakHashLen32WithSeeds( */ uint128 WeakHashLen32WithSeeds6(uint64 w, uint64 x, uint64 y, uint64 z, uint64 a, uint64 b) { a += w; b = Rotate(b + a + z, 21); uint64 c = a; a += x; a += y; b += Rotate(a, 44); uint128 result; result.first = (uint64) (a + z); result.second = (uint64) (b + c); return result; } /* Return a 16-byte hash for s[0] ... s[31], a, and b. Quick and dirty. * static pair WeakHashLen32WithSeeds( */ uint128 WeakHashLen32WithSeeds(const char *s, uint64 a, uint64 b) { return WeakHashLen32WithSeeds6(Fetch64(s), Fetch64(s + 8), Fetch64(s + 16), Fetch64(s + 24), a, b); } /* Return an 8-byte hash for 33 to 64 bytes. */ static uint64 HashLen33to64(const char *s, size_t len) { uint64 z = Fetch64(s + 24); uint64 a = Fetch64(s) + (len + Fetch64(s + len - 16)) * k0; uint64 b = Rotate(a + z, 52); uint64 c = Rotate(a, 37); a += Fetch64(s + 8); c += Rotate(a, 7); a += Fetch64(s + 16); uint64 vf = a + z; uint64 vs = b + Rotate(a, 31) + c; a = Fetch64(s + 16) + Fetch64(s + len - 32); z = Fetch64(s + len - 8); b = Rotate(a + z, 52); c = Rotate(a, 37); a += Fetch64(s + len - 24); c += Rotate(a, 7); a += Fetch64(s + len - 16); uint64 wf = a + z; uint64 ws = b + Rotate(a, 31) + c; uint64 r = ShiftMix((vf + ws) * k2 + (wf + vs) * k0); return ShiftMix(r * k0 + vs) * k2; } uint64 CityHash64(const char *s, size_t len) { if (len <= 32) { if (len <= 16) return HashLen0to16(s, len); else return HashLen17to32(s, len); } else if (len <= 64) return HashLen33to64(s, len); /* For strings over 64 bytes we hash the end first, and then as we * loop we keep 56 bytes of state: v, w, x, y, and z. */ uint64 x = Fetch64(s + len - 40); uint64 y = Fetch64(s + len - 16) + Fetch64(s + len - 56); uint64 z = HashLen16(Fetch64(s + len - 48) + len, Fetch64(s + len - 24)); uint64 temp; uint128 v = WeakHashLen32WithSeeds(s + len - 64, len, z); uint128 w = WeakHashLen32WithSeeds(s + len - 32, y + k1, x); x = x * k1 + Fetch64(s); /* Decrease len to the nearest multiple of 64, and operate on 64-byte * chunks. */ len = (len - 1) & ~(size_t) (63); do { x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; x ^= w.second; y += v.first + Fetch64(s + 40); z = Rotate(z + w.first, 33) * k1; v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); temp = z; z = x; x = temp; s += 64; len -= 64; } while (len != 0); return HashLen16(HashLen16(v.first, w.first) + ShiftMix(y) * k1 + z, HashLen16(v.second, w.second) + x); } uint64 CityHash64WithSeed(const char *s, size_t len, uint64 seed) { return CityHash64WithSeeds(s, len, k2, seed); } uint64 CityHash64WithSeeds(const char *s, size_t len, uint64 seed0, uint64 seed1) { return HashLen16(CityHash64(s, len) - seed0, seed1); } /* A subroutine for CityHash128(). Returns a decent 128-bit hash for strings * of any length representable in signed long. Based on City and Murmur. */ static uint128 CityMurmur(const char *s, size_t len, uint128 seed) { uint64 a = Uint128Low64(seed); uint64 b = Uint128High64(seed); uint64 c = 0; uint64 d = 0; signed long l = len - 16; if (l <= 0) { /* len <= 16 */ a = ShiftMix(a * k1) * k1; c = b * k1 + HashLen0to16(s, len); d = ShiftMix(a + (len >= 8 ? Fetch64(s) : c)); } else { /* len > 16 */ c = HashLen16(Fetch64(s + len - 8) + k1, a); d = HashLen16(b + len, c + Fetch64(s + len - 16)); a += d; do { a ^= ShiftMix(Fetch64(s) * k1) * k1; a *= k1; b ^= a; c ^= ShiftMix(Fetch64(s + 8) * k1) * k1; c *= k1; d ^= c; s += 16; l -= 16; } while (l > 0); } a = HashLen16(a, c); b = HashLen16(d, b); uint128 result; result.first = (uint64) (a ^ b); result.second = (uint64) (HashLen16(b, a)); return result; } uint128 CityHash128WithSeed(const char *s, size_t len, uint128 seed) { if (len < 128) return CityMurmur(s, len, seed); /* We expect len >= 128 to be the common case. Keep 56 bytes of state: * v, w, x, y, and z. */ uint128 v, w; uint64 x = Uint128Low64(seed); uint64 y = Uint128High64(seed); uint64 z = len * k1; uint64 temp; v.first = Rotate(y ^ k1, 49) * k1 + Fetch64(s); v.second = Rotate(v.first, 42) * k1 + Fetch64(s + 8); w.first = Rotate(y + z, 35) * k1 + x; w.second = Rotate(x + Fetch64(s + 88), 53) * k1; /* This is the same inner loop as CityHash64(), manually unrolled. */ do { x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; x ^= w.second; y += v.first + Fetch64(s + 40); z = Rotate(z + w.first, 33) * k1; v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); temp = z; z = x; x = temp; s += 64; x = Rotate(x + y + v.first + Fetch64(s + 8), 37) * k1; y = Rotate(y + v.second + Fetch64(s + 48), 42) * k1; x ^= w.second; y += v.first + Fetch64(s + 40); z = Rotate(z + w.first, 33) * k1; v = WeakHashLen32WithSeeds(s, v.second * k1, x + w.first); w = WeakHashLen32WithSeeds(s + 32, z + w.second, y + Fetch64(s + 16)); temp = z; z = x; x = temp; s += 64; len -= 128; } while (LIKELY(len >= 128)); x += Rotate(v.first + z, 49) * k0; z += Rotate(w.first, 37) * k0; /* If 0 < len < 128, hash up to 4 chunks of 32 bytes each from the end * of s. */ size_t tail_done; for (tail_done = 0; tail_done < len;) { tail_done += 32; y = Rotate(x + y, 42) * k0 + v.second; w.first += Fetch64(s + len - tail_done + 16); x = x * k0 + w.first; z += w.second + Fetch64(s + len - tail_done); w.second += v.first; v = WeakHashLen32WithSeeds(s + len - tail_done, v.first + z, v.second); } /* At this point our 56 bytes of state should contain more than * enough information for a strong 128-bit hash. We use two * different 56-byte-to-8-byte hashes to get a 16-byte final result. */ x = HashLen16(x, v.first); y = HashLen16(y + z, w.first); uint128 result; result.first = (uint64) (HashLen16(x + v.second, w.second) + y); result.second = (uint64) HashLen16(x + w.second, y + v.second); return result; } uint128 CityHash128(const char *s, size_t len) { uint128 r; if (len >= 16) { r.first = (uint64) (Fetch64(s) ^ k3); r.second = (uint64) (Fetch64(s + 8)); return CityHash128WithSeed(s + 16, len - 16, r); } else if (len >= 8) { r.first = (uint64) (Fetch64(s) ^ (len * k0)); r.second = (uint64) (Fetch64(s + len - 8) ^ k1); return CityHash128WithSeed(NULL, 0, r); } else { r.first = (uint64) k0; r.second = (uint64) k1; return CityHash128WithSeed(s, len, r); } } #ifdef __SSE4_2__ #include "citycrc.h" #include /* Requires len >= 240. */ static void CityHashCrc256Long(const char *s, size_t len, uint32 seed, uint64 * result) { uint64 a = Fetch64(s + 56) + k0; uint64 b = Fetch64(s + 96) + k0; uint64 c = result[0] = HashLen16(b, len); uint64 d = result[1] = Fetch64(s + 120) * k0 + len; uint64 e = Fetch64(s + 184) + seed; uint64 f = seed; uint64 g = 0; uint64 h = 0; uint64 i = 0; uint64 j = 0; uint64 t = c + d; /* 240 bytes of input per iter. */ size_t iters = len / 240; len -= iters * 240; do { #define CHUNK(multiplier, z) \ { \ uint64 old_a = a; \ a = Rotate(b, 41 ^ z) * multiplier + Fetch64(s); \ b = Rotate(c, 27 ^ z) * multiplier + Fetch64(s + 8); \ c = Rotate(d, 41 ^ z) * multiplier + Fetch64(s + 16); \ d = Rotate(e, 33 ^ z) * multiplier + Fetch64(s + 24); \ e = Rotate(t, 25 ^ z) * multiplier + Fetch64(s + 32); \ t = old_a; \ } \ f = _mm_crc32_u64(f, a); \ g = _mm_crc32_u64(g, b); \ h = _mm_crc32_u64(h, c); \ i = _mm_crc32_u64(i, d); \ j = _mm_crc32_u64(j, e); \ s += 40 CHUNK(1, 1); CHUNK(k0, 0); CHUNK(1, 1); CHUNK(k0, 0); CHUNK(1, 1); CHUNK(k0, 0); } while (--iters > 0); while (len >= 40) { CHUNK(k0, 0); len -= 40; } if (len > 0) { s = s + len - 40; CHUNK(k0, 0); } j += i << 32; a = HashLen16(a, j); h += g << 32; b += h; c = HashLen16(c, f) + i; d = HashLen16(d, e + result[0]); j += e; i += HashLen16(h, t); e = HashLen16(a, d) + j; f = HashLen16(b, c) + a; g = HashLen16(j, i) + c; result[0] = e + f + g + h; a = ShiftMix((a + g) * k0) * k0 + b; result[1] += a + result[0]; a = ShiftMix(a * k0) * k0 + c; result[2] = a + result[1]; a = ShiftMix((a + e) * k0) * k0; result[3] = a + result[2]; } /* Requires len < 240. */ static void CityHashCrc256Short(const char *s, size_t len, uint64 *result) { char buf[240]; memcpy(buf, s, len); memset(buf + len, 0, 240 - len); CityHashCrc256Long(buf, 240, ~(uint32) (len), result); } void CityHashCrc256(const char *s, size_t len, uint64 *result) { if (LIKELY(len >= 240)) CityHashCrc256Long(s, len, 0, result); else CityHashCrc256Short(s, len, result); } uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed) { if (len <= 900) { return CityHash128WithSeed(s, len, seed); } else { uint64 result[4]; CityHashCrc256(s, len, result); uint64 u = Uint128High64(seed) + result[0]; uint64 v = Uint128Low64(seed) + result[1]; uint128 crc; crc.first = (uint64) (HashLen16(u, v + result[2])); crc.second = (uint64) (HashLen16(Rotate(v, 32), u * k0 + result[3])); return crc; } } uint128 CityHashCrc128(const char *s, size_t len) { if (len <= 900) { return CityHash128(s, len); } else { uint64 result[4]; CityHashCrc256(s, len, result); uint128 crc; crc.first = (uint64) result[2]; crc.second = (uint64) result[3]; return crc; } } #endif ntirpc-1.3.1/src/citycrc.h000066400000000000000000000037171261345040100154170ustar00rootroot00000000000000/* citycrc.h - cityhash-c * CityHash on C * Copyright (c) 2011-2012, Alexander Nusov * * - original copyright notice - * Copyright (c) 2011 Google, Inc. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * * CityHash, by Geoff Pike and Jyrki Alakuijala * * This file declares the subset of the CityHash functions that require * _mm_crc32_u64(). See the CityHash README for details. * * Functions in the CityHash family are not suitable for cryptography. */ #ifndef CITY_HASH_CRC_H_ #define CITY_HASH_CRC_H_ #include "city.h" /* Hash function for a byte array. */ uint128 CityHashCrc128(const char *s, size_t len); /* Hash function for a byte array. For convenience, a 128-bit seed is also * hashed into the result. */ uint128 CityHashCrc128WithSeed(const char *s, size_t len, uint128 seed); /* Hash function for a byte array. Sets result[0] ... result[3]. */ void CityHashCrc256(const char *s, size_t len, uint64 *result); #endif /* CITY_HASH_CRC_H_ */ ntirpc-1.3.1/src/clnt_bcast.c000066400000000000000000000447441261345040100160730ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ #include #include /* * 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 #include #include #include #include #include #include #include #include #include #ifdef PORTMAP #include #include #include #endif /* PORTMAP */ #include #include #ifdef RPC_DEBUG #include #endif #include #include #include #include #include #include #include "rpc_com.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. */ #define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) #define TAILQ_FIRST(head) ((head)->tqh_first) struct broadif { int index; struct sockaddr_storage broadaddr; TAILQ_ENTRY(broadif) link; }; typedef TAILQ_HEAD(, broadif) broadlist_t; int __rpc_getbroadifs(int, int, int, broadlist_t *); void __rpc_freebroadifs(broadlist_t *); int __rpc_broadenable(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 *sin; struct addrinfo hints, *res; 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) 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 = (struct broadif *)mem_alloc(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); */ memcpy(&bip->broadaddr, ifap->ifa_broadaddr, sizeof(bip->broadaddr)); sin = (struct sockaddr_in *)(void *)&bip->broadaddr; sin->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_port = ((struct sockaddr_in6 *) (void *)res->ai_addr)->sin6_port; sin6->sin6_scope_id = bip->index; } else #endif { mem_free(bip, 0); continue; } TAILQ_INSERT_TAIL(list, bip, link); count++; } freeifaddrs(ifp); freeaddrinfo(res); return count; } void __rpc_freebroadifs(broadlist_t *list) { struct broadif *bip, *next; bip = TAILQ_FIRST(list); while (bip != NULL) { next = TAILQ_NEXT(bip, link); mem_free(bip, 0); bip = next; } } int /*ARGSUSED*/ __rpc_broadenable(int af, int s, struct broadif *bip) { int o = 1; #if 0 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(rpcprog_t prog, /* program number */ rpcvers_t vers, /* version number */ rpcproc_t 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 */ 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 */ struct timespec ts; char *outbuf = NULL; /* Broadcast msg buffer */ char *inbuf = NULL; /* Reply buf */ int inlen; u_int maxbufsize = 0; AUTH *sys_auth = authunix_ncreate_default(); int 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; #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"; handle = __rpc_setconf(nettype); if (handle == NULL) { stat = RPC_UNKNOWNPROTO; goto cleanup; } 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) { if (udpbufsz < fdlist[fdlistno].dsize) udpbufsz = fdlist[fdlistno].dsize; pmap_flag = 1; } #endif /* PORTMAP */ 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 = mem_alloc(maxbufsize); outbuf = mem_alloc(maxbufsize); if ((inbuf == NULL) || (outbuf == NULL)) { stat = RPC_SYSTEMERROR; goto done_broad; } /* Serialize all the arguments which have to be sent */ (void)clock_gettime(CLOCK_MONOTONIC_FAST, &ts); msg.rm_xid = __RPC_GETXID(&ts); 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) { outbuf_pmap = mem_alloc(udpbufsz); if (outbuf_pmap == NULL) { stat = RPC_SYSTEMERROR; goto done_broad; } 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 (sendto (fdlist[i].fd, outbuf, outlen, 0, (struct sockaddr *)addr, (size_t) fdlist[i].asize) != outlen) { #ifdef RPC_DEBUG perror("sendto"); #endif __warnx (TIRPC_DEBUG_FLAG_CLNT_BCAST, "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 (sendto (fdlist[i].fd, outbuf_pmap, outlen_pmap, 0, addr, (size_t) fdlist[i].asize) != outlen_pmap) { __warnx (TIRPC_DEBUG_FLAG_CLNT_BCAST, "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: switch (pollretval = poll(pfd, fdlistno, msec)) { 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 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 _poll() 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(TIRPC_DEBUG_FLAG_CLNT_BCAST, "clnt_bcast: Cannot receive reply to broadcast"); stat = RPC_CANTRECV; continue; } if (inlen < 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 *np; #ifdef PORTMAP struct netbuf taddr; struct sockaddr_in sin; if (pmap_flag && pmap_reply_flag) { memcpy(&sin, &fdlist[i].raddr, sizeof(sin)); sin.sin_port = htons((u_short) port); memcpy(&fdlist[i].raddr, &sin, sizeof(sin)); taddr.len = taddr.maxlen = sizeof(fdlist[i].raddr); taddr.buf = &fdlist[i].raddr; done = (*eachresult) (resultsp, &taddr, fdlist[i]. nconf); } else { #endif /* PORTMAP */ #ifdef RPC_DEBUG fprintf(stderr, "uaddr %s\n", uaddrp); #endif np = uaddr2taddr(fdlist[i]. nconf, uaddrp); done = (*eachresult) (resultsp, np, fdlist[i]. nconf); mem_free(np, 0); #ifdef PORTMAP } #endif /* PORTMAP */ } /* 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) mem_free(inbuf, 0); if (outbuf) mem_free(outbuf, 0); #ifdef PORTMAP if (outbuf_pmap) mem_free(outbuf_pmap, 0); #endif /* PORTMAP */ for (i = 0; i < fdlistno; i++) { (void)close(fdlist[i].fd); __rpc_freebroadifs(&fdlist[i].nal); } cleanup: AUTH_DESTROY(sys_auth); (void)__rpc_endconf(handle); return (stat); } enum clnt_stat rpc_broadcast(rpcprog_t prog, /* program number */ rpcvers_t vers, /* version number */ rpcproc_t 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 */ 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); } ntirpc-1.3.1/src/clnt_dg.c000066400000000000000000000501641261345040100153620ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ /* * Implements a connectionless client side RPC. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef IP_RECVERR #include #include #include #endif #include #include #include #include #include "rpc_com.h" #include "clnt_internal.h" #include "rpc_dplx_internal.h" #include "rpc_ctx.h" #include #define MAX_DEFAULT_FDS 20000 static struct clnt_ops *clnt_dg_ops(void); static bool time_not_ok(struct timeval *); static enum clnt_stat clnt_dg_call(CLIENT *, AUTH *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval); static void clnt_dg_geterr(CLIENT *, struct rpc_err *); static bool clnt_dg_freeres(CLIENT *, xdrproc_t, void *); static bool clnt_dg_ref(CLIENT *, u_int); static void clnt_dg_release(CLIENT *, u_int flags); static void clnt_dg_abort(CLIENT *); static bool clnt_dg_control(CLIENT *, u_int, void *); static void clnt_dg_destroy(CLIENT *); static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory"; /* * 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. * * 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_ncreate(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 *clnt = NULL; /* client handle */ struct cx_data *cx = NULL; /* private data */ struct cu_data *cu = NULL; struct timespec now; struct rpc_msg call_msg; struct __rpc_sockinfo si; uint32_t oflags; int one = 1; 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); } clnt = mem_alloc(sizeof(CLIENT)); if (clnt == NULL) goto err1; mutex_init(&clnt->cl_lock, NULL); clnt->cl_flags = CLNT_FLAG_NONE; /* * Should be multiple of 4 for XDR. */ sendsz = ((sendsz + 3) / 4) * 4; recvsz = ((recvsz + 3) / 4) * 4; cx = alloc_cx_data(CX_DG_DATA, sendsz, recvsz); if (cx == NULL) goto err1; cu = CU_DATA(cx); (void)memcpy(&cu->cu_raddr, svcaddr->buf, (size_t) svcaddr->len); cu->cu_rlen = svcaddr->len; /* 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; cu->cu_async = false; cu->cu_connect = false; cu->cu_connected = false; (void)clock_gettime(CLOCK_MONOTONIC_FAST, &now); call_msg.rm_xid = __RPC_GETXID(&now); /* XXX? */ 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 #ifdef IP_RECVERR { int on = 1; (void) setsockopt(fd, SOL_IP, IP_RECVERR, &on, sizeof(on)); } #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; clnt->cl_ops = clnt_dg_ops(); clnt->cl_p1 = cx; clnt->cl_p2 = rpc_dplx_lookup_rec(fd, RPC_DPLX_LKP_FLAG_NONE, &oflags); /* ref+1 */ clnt->cl_tp = NULL; clnt->cl_netid = NULL; return (clnt); err1: __warnx(TIRPC_DEBUG_FLAG_CLNT_DG, mem_err_clnt_dg); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; err2: if (clnt) { mem_free(clnt, sizeof(CLIENT)); if (cx) free_cx_data(cx); } return (NULL); } static enum clnt_stat clnt_dg_call(CLIENT *clnt, /* client handle */ AUTH *auth, /* auth handle */ rpcproc_t proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ void *argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ void *resultsp, /* pointer to results */ struct timeval utimeout /* seconds to wait before giving up */) { struct cu_data *cu = CU_DATA((struct cx_data *)clnt->cl_p1); XDR *xdrs; size_t outlen = 0; struct rpc_msg reply_msg; XDR reply_xdrs; bool ok; int nrefreshes = 2; /* number of times to refresh cred */ struct timeval timeout; struct pollfd fd; int total_time, nextsend_time, tv = 0; struct sockaddr *sa; socklen_t __attribute__ ((unused)) inlen, salen; ssize_t recvlen = 0; u_int32_t xid, inval, outval; bool slocked = false; bool rlocked = false; bool once = true; outlen = 0; rpc_dplx_slc(clnt); slocked = true; if (cu->cu_total.tv_usec == -1) timeout = utimeout; /* use supplied timeout */ else timeout = cu->cu_total; /* use default timeout */ total_time = timeout.tv_sec * 1000 + timeout.tv_usec / 1000; nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000; if (cu->cu_connect && !cu->cu_connected) { if (connect (cu->cu_fd, (struct sockaddr *)&cu->cu_raddr, cu->cu_rlen) < 0) { cu->cu_error.re_errno = errno; cu->cu_error.re_status = RPC_CANTSEND; goto out; } cu->cu_connected = 1; } if (cu->cu_connected) { sa = NULL; salen = 0; } else { sa = (struct sockaddr *)&cu->cu_raddr; salen = cu->cu_rlen; } /* Clean up in case the last call ended in a longjmp(3) call. */ call_again: if (!slocked) { rpc_dplx_slc(clnt); slocked = true; } xdrs = &(cu->cu_outxdrs); if (cu->cu_async == true && xargs == NULL) goto get_reply; xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, cu->cu_xdrpos); /* * the transaction is the first thing in the out buffer * XXX Yes, and it's in network byte order, so we should to * be careful when we increment it, shouldn't we. */ xid = ntohl(*(u_int32_t *) (void *)(cu->cu_outbuf)); xid++; *(u_int32_t *) (void *)(cu->cu_outbuf) = htonl(xid); if ((!XDR_PUTINT32(xdrs, (int32_t *) &proc)) || (!AUTH_MARSHALL(auth, xdrs)) || (!AUTH_WRAP(auth, xdrs, xargs, argsp))) { cu->cu_error.re_status = RPC_CANTENCODEARGS; goto out; } outlen = (size_t) XDR_GETPOS(xdrs); send_again: nextsend_time = cu->cu_wait.tv_sec * 1000 + cu->cu_wait.tv_usec / 1000; if (sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) { cu->cu_error.re_errno = errno; cu->cu_error.re_status = RPC_CANTSEND; goto out; } get_reply: /* * 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.) */ rpc_dplx_suc(clnt); slocked = false; rpc_dplx_rlc(clnt); rlocked = true; reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = NULL; reply_msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; fd.fd = cu->cu_fd; fd.events = POLLIN; fd.revents = 0; while ((total_time > 0) || once) { tv = total_time < nextsend_time ? total_time : nextsend_time; once = false; switch (poll(&fd, 1, tv)) { case 0: total_time -= tv; rpc_dplx_ruc(clnt); rlocked = false; if (total_time <= 0) { cu->cu_error.re_status = RPC_TIMEDOUT; goto out; } goto send_again; case -1: if (errno == EINTR) continue; cu->cu_error.re_status = RPC_CANTRECV; cu->cu_error.re_errno = errno; goto out; } break; } #ifdef IP_RECVERR if (fd.revents & POLLERR) { struct msghdr msg; struct cmsghdr *cmsg; struct sock_extended_err *e; struct sockaddr_in err_addr; struct sockaddr_in *sin = (struct sockaddr_in *)&cu->cu_raddr; struct iovec iov; char *cbuf = (char *)alloca(outlen + 256); int ret; iov.iov_base = cbuf + 256; iov.iov_len = outlen; msg.msg_name = (void *)&err_addr; msg.msg_namelen = sizeof(err_addr); msg.msg_iov = &iov; msg.msg_iovlen = 1; msg.msg_flags = 0; msg.msg_control = cbuf; msg.msg_controllen = 256; ret = recvmsg(cu->cu_fd, &msg, MSG_ERRQUEUE); if (ret >= 0 && memcmp(cbuf + 256, cu->cu_outbuf, ret) == 0 && (msg.msg_flags & MSG_ERRQUEUE) && ((msg.msg_namelen == 0 && ret >= 12) || (msg.msg_namelen == sizeof(err_addr) && err_addr.sin_family == AF_INET && memcmp(&err_addr.sin_addr, &sin->sin_addr, sizeof(err_addr.sin_addr)) == 0 && err_addr.sin_port == sin->sin_port))) for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) if ((cmsg->cmsg_level == SOL_IP) && (cmsg->cmsg_type == IP_RECVERR)) { e = (struct sock_extended_err *) CMSG_DATA(cmsg); cu->cu_error.re_errno = e->ee_errno; cu->cu_error.re_status = RPC_CANTRECV; } } #endif /* 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 < sizeof(u_int32_t)) { total_time -= tv; rpc_dplx_ruc(clnt); rlocked = false; goto send_again; } if (cu->cu_async == true) inlen = (socklen_t) recvlen; else { memcpy(&inval, cu->cu_inbuf, sizeof(u_int32_t)); memcpy(&outval, cu->cu_outbuf, sizeof(u_int32_t)); if (inval != outval) { total_time -= tv; rpc_dplx_ruc(clnt); rlocked = false; goto send_again; } inlen = (socklen_t) recvlen; } /* * 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 (auth, &reply_msg.acpted_rply.ar_verf)) { cu->cu_error.re_status = RPC_AUTHERROR; cu->cu_error.re_why = AUTH_INVALIDRESP; } else if (!AUTH_UNWRAP (auth, &reply_xdrs, xresults, resultsp)) { if (cu->cu_error.re_status == RPC_SUCCESS) cu->cu_error.re_status = RPC_CANTDECODERES; } 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(auth, &reply_msg)) { nrefreshes--; rpc_dplx_ruc(clnt); rlocked = false; goto call_again; } /* end of unsuccessful completion */ } /* end of valid reply message */ else cu->cu_error.re_status = RPC_CANTDECODERES; out: if (slocked) rpc_dplx_suc(clnt); if (rlocked) rpc_dplx_ruc(clnt); return (cu->cu_error.re_status); } static void clnt_dg_geterr(CLIENT *clnt, struct rpc_err *errp) { struct cu_data *cu = CU_DATA((struct cx_data *)clnt->cl_p1); *errp = cu->cu_error; } static bool clnt_dg_freeres(CLIENT *clnt, xdrproc_t xdr_res, void *res_ptr) { struct cu_data *cu = CU_DATA((struct cx_data *)clnt->cl_p1); XDR *xdrs; sigset_t mask, newmask; bool dummy = 0; /* XXX guard against illegal invocation from libc (will fix) */ if (!xdr_res) goto out; xdrs = &(cu->cu_outxdrs); /* XXX outxdrs? */ /* Handle our own signal mask here, the signal section is * larger than the wait (not 100% clear why) */ sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); /* barrier recv channel */ rpc_dplx_rwc(clnt, rpc_flag_clear); xdrs->x_op = XDR_FREE; if (xdr_res) dummy = (*xdr_res) (xdrs, res_ptr); thr_sigsetmask(SIG_SETMASK, &mask, NULL); /* signal recv channel */ rpc_dplx_rsc(clnt, RPC_DPLX_FLAG_NONE); out: return (dummy); } static bool clnt_dg_ref(CLIENT *clnt, u_int flags) { return (true); } static void clnt_dg_release(CLIENT *clnt, u_int flags) { } /*ARGSUSED*/ static void clnt_dg_abort(CLIENT *h) { } static bool clnt_dg_control(CLIENT *clnt, u_int request, void *info) { struct cu_data *cu = CU_DATA((struct cx_data *)clnt->cl_p1); struct netbuf *addr; bool rslt = true; /* always take recv lock first, if taking both locks together */ rpc_dplx_rlc(clnt); rpc_dplx_slc(clnt); switch (request) { case CLSET_FD_CLOSE: cu->cu_closeit = true; rslt = true; goto unlock; case CLSET_FD_NCLOSE: cu->cu_closeit = false; rslt = true; goto unlock; } /* for other requests which use info */ if (info == NULL) { rslt = false; goto unlock; } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { rslt = false; goto unlock; } cu->cu_total = *(struct timeval *)info; break; case CLGET_TIMEOUT: *(struct timeval *)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 *)info)) { rslt = false; goto unlock; } cu->cu_wait = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: *(struct timeval *)info = cu->cu_wait; break; case CLGET_FD: *(int *)info = cu->cu_fd; break; case CLGET_SVC_ADDR: addr = (struct netbuf *)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 *)info; if (addr->len < sizeof(cu->cu_raddr)) { rslt = false; goto unlock; } (void)memcpy(&cu->cu_raddr, addr->buf, 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 *) 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 *) 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 *) 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 *) 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 *) 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 *) info); break; case CLSET_ASYNC: cu->cu_async = *(int *)info; break; case CLSET_CONNECT: cu->cu_connect = *(int *)info; break; default: break; } unlock: rpc_dplx_ruc(clnt); rpc_dplx_suc(clnt); return (rslt); } static void clnt_dg_destroy(CLIENT *clnt) { struct cx_data *cx = (struct cx_data *)clnt->cl_p1; struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; int cu_fd = CU_DATA(cx)->cu_fd; sigset_t mask, newmask; /* Handle our own signal mask here, the signal section is * larger than the wait (not 100% clear why) */ sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); /* barrier both channels */ rpc_dplx_swc(clnt, rpc_flag_clear); rpc_dplx_rwc(clnt, rpc_flag_clear); if (CU_DATA(cx)->cu_closeit) (void)close(cu_fd); XDR_DESTROY(&(CU_DATA(cx)->cu_outxdrs)); /* signal both channels */ rpc_dplx_ssc(clnt, RPC_DPLX_FLAG_NONE); rpc_dplx_rsc(clnt, RPC_DPLX_FLAG_NONE); /* release */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_NONE); free_cx_data(cx); if (clnt->cl_netid && clnt->cl_netid[0]) mem_free(clnt->cl_netid, strlen(clnt->cl_netid) + 1); if (clnt->cl_tp && clnt->cl_tp[0]) mem_free(clnt->cl_tp, strlen(clnt->cl_tp) + 1); mem_free(clnt, sizeof(CLIENT)); thr_sigsetmask(SIG_SETMASK, &mask, NULL); } static struct clnt_ops * clnt_dg_ops(void) { static struct clnt_ops ops; extern mutex_t ops_lock; /* XXXX does it need to be extern? */ sigset_t mask; 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_ref = clnt_dg_ref; ops.cl_release = clnt_dg_release; 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 time_not_ok(struct timeval *t) { return (t->tv_sec < -1 || t->tv_sec > 100000000 || t->tv_usec < -1 || t->tv_usec > 1000000); } ntirpc-1.3.1/src/clnt_generic.c000066400000000000000000000312271261345040100164030ustar00rootroot00000000000000/* * Copyright (c) 2010, Oracle America, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the "Oracle America, Inc." nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" int __rpc_raise_fd(int); #ifndef NETIDLEN #define NETIDLEN 32 #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. * * It calls clnt_create_vers_timed() with a NULL value for the timeout * pointer, which indicates that the default timeout should be used. */ CLIENT * clnt_ncreate_vers(const char *hostname, rpcprog_t prog, rpcvers_t *vers_out, rpcvers_t vers_low, rpcvers_t vers_high, const char *nettype) { return (clnt_ncreate_vers_timed (hostname, prog, vers_out, vers_low, vers_high, nettype, NULL)); } /* * This the routine has the same definition as clnt_create_vers(), * except it takes an additional timeout parameter - a pointer to * a timeval structure. A NULL value for the pointer indicates * that the default timeout value should be used. */ CLIENT * clnt_ncreate_vers_timed(const char *hostname, rpcprog_t prog, rpcvers_t *vers_out, rpcvers_t vers_low, rpcvers_t vers_high, const char *nettype, const struct timeval *tp) { CLIENT *clnt; struct timeval to; enum clnt_stat rpc_stat; struct rpc_err rpcerr; AUTH *auth = authnone_ncreate(); /* idempotent */ clnt = clnt_ncreate_timed(hostname, prog, vers_high, nettype, tp); if (clnt == NULL) return (NULL); to.tv_sec = 10; to.tv_usec = 0; rpc_stat = clnt_call(clnt, auth, NULLPROC, (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void, (char *)NULL, to); if (rpc_stat == RPC_SUCCESS) { *vers_out = vers_high; return (clnt); } while (rpc_stat == RPC_PROGVERSMISMATCH && vers_high > vers_low) { unsigned int minvers, maxvers; clnt_geterr(clnt, &rpcerr); minvers = rpcerr.re_vers.low; maxvers = rpcerr.re_vers.high; if (maxvers < vers_high) vers_high = maxvers; else vers_high--; if (minvers > vers_low) vers_low = minvers; if (vers_low > vers_high) goto error; CLNT_CONTROL(clnt, CLSET_VERS, (char *)&vers_high); rpc_stat = clnt_call(clnt, auth, NULLPROC, (xdrproc_t) xdr_void, (char *)NULL, (xdrproc_t) xdr_void, (char *)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_ncreate_timed() with the default timeout. */ CLIENT * clnt_ncreate(const char *hostname, rpcprog_t prog, rpcvers_t vers, const char *nettype) { return (clnt_ncreate_timed(hostname, prog, vers, nettype, NULL)); } /* * This the routine has the same definition as clnt_create(), * except it takes an additional timeout parameter - a pointer to * a timeval structure. A NULL value for the pointer indicates * that the default timeout value should be used. * * This function calls clnt_tp_create_timed(). */ CLIENT * clnt_ncreate_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers, const char *netclass, const struct timeval *tp) { struct netconfig *nconf; CLIENT *clnt = NULL; void *handle; enum clnt_stat save_cf_stat = RPC_SUCCESS; struct rpc_err save_cf_error; char nettype_array[NETIDLEN]; char *nettype = &nettype_array[0]; if (netclass == NULL) nettype = NULL; else { size_t len = strlen(netclass); if (len >= sizeof(nettype_array)) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } strcpy(nettype, netclass); } handle = __rpc_setconf((char *)nettype); if (handle == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } rpc_createerr.cf_stat = RPC_SUCCESS; while (clnt == NULL) { nconf = __rpc_getconf(handle); if (nconf == NULL) { if (rpc_createerr.cf_stat == RPC_SUCCESS) rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; break; } #ifdef CLNT_DEBUG __warnx(TIRPC_DEBUG_FLAG_CLNT_GEN, "%s: trying netid %s", __func__, nconf->nc_netid); #endif clnt = clnt_tp_ncreate_timed(hostname, prog, vers, nconf, tp); 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). We also check for a more * meaningful error than ``unknown host * name'' for the same reasons. */ if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE && rpc_createerr.cf_stat != RPC_UNKNOWNHOST) { 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'' or ``unknown host name'' */ if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE || rpc_createerr.cf_stat == RPC_UNKNOWNHOST) && (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(). * * It calls clnt_tp_create_timed() with the default timeout. */ CLIENT * clnt_tp_ncreate(const char *hostname, rpcprog_t prog, rpcvers_t vers, const struct netconfig *nconf) { return (clnt_tp_ncreate_timed(hostname, prog, vers, nconf, NULL)); } /* * This has the same definition as clnt_tp_ncreate(), except it * takes an additional parameter - a pointer to a timeval structure. * A NULL value for the timeout pointer indicates that the default * value for the timeout should be used. */ CLIENT * clnt_tp_ncreate_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers, const struct netconfig *nconf, const struct timeval *tp) { struct netbuf *svcaddr; /* servers address */ CLIENT *cl = NULL; /* client handle */ if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } /* * Get the address of the server */ svcaddr = __rpcb_findaddr_timed(prog, vers, (struct netconfig *)nconf, (char *)hostname, &cl, (struct timeval *)tp); if (svcaddr == NULL) { /* appropriate error number is set by rpcbind libraries */ return (NULL); } if (cl == NULL) { /* __rpc_findaddr_timed failed? */ cl = clnt_tli_ncreate(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 = rpc_strdup(nconf->nc_netid); if (cl->cl_tp == NULL) cl->cl_tp = rpc_strdup(nconf->nc_device); (void)CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog); (void)CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers); } else { CLNT_DESTROY(cl); cl = clnt_tli_ncreate(RPC_ANYFD, nconf, svcaddr, prog, vers, 0, 0); } } mem_free(svcaddr->buf, 0); /* XXX */ mem_free(svcaddr, 0); return (cl); } /* * 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_ncreate(int fd, const struct netconfig *nconf, struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers, u_int sendsz, u_int recvsz) { CLIENT *cl; /* client handle */ bool madefd = false; /* whether fd opened here */ long servtype; int one = 1; struct __rpc_sockinfo si; extern int __rpc_minfd; if (fd == RPC_ANYFD) { if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } fd = __rpc_nconf2fd(nconf); if (fd == -1) goto err; if (fd < __rpc_minfd) fd = __rpc_raise_fd(fd); 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: cl = clnt_vc_ncreate(fd, svcaddr, prog, vers, sendsz, recvsz); break; case NC_TPI_COTS_ORD: if (nconf && ((strcmp(nconf->nc_protofmly, "inet") == 0) || (strcmp(nconf->nc_protofmly, "inet6") == 0))) { (void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)); } cl = clnt_vc_ncreate(fd, svcaddr, prog, vers, sendsz, recvsz); break; case NC_TPI_CLTS: cl = clnt_dg_ncreate(fd, svcaddr, prog, vers, sendsz, recvsz); break; default: goto err; } if (cl == NULL) goto err1; /* borrow errors from clnt_dg/vc ncreates */ if (nconf) { cl->cl_netid = rpc_strdup(nconf->nc_netid); cl->cl_tp = rpc_strdup(nconf->nc_device); } else { cl->cl_netid = ""; cl->cl_tp = ""; } if (madefd) { (void)CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL); /* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */ }; return (cl); err: rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; err1: if (madefd) (void)close(fd); return (NULL); } /* * To avoid conflicts with the "magic" file descriptors (0, 1, and 2), * we try to not use them. The __rpc_raise_fd() routine will dup * a descriptor to a higher value. If we fail to do it, we continue * to use the old one (and hope for the best). */ int __rpc_minfd = 3; int __rpc_raise_fd(int fd) { int nfd; if (fd >= __rpc_minfd) return (fd); nfd = fcntl(fd, F_DUPFD, __rpc_minfd); if (nfd == -1) return (fd); if (fsync(nfd) == -1) { close(nfd); return (fd); } if (close(fd) == -1) { /* this is okay, we will log an error, then use the new fd */ __warnx(TIRPC_DEBUG_FLAG_CLNT_GEN, "could not close() fd %d; mem & fd leak", fd); } return (nfd); } ntirpc-1.3.1/src/clnt_internal.h000066400000000000000000000164211261345040100166070ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * clnt_internal.h Internal client structures needed by some async * svc routines */ #ifndef _CLNT_INTERNAL_H #define _CLNT_INTERNAL_H struct ct_wait_entry { mutex_t mtx; cond_t cv; }; #include #include #include #include typedef struct rpc_dplx_lock { struct wait_entry we; int32_t lock_flag_value; /* XXX killme */ struct { const char *func; int line; } locktrace; } rpc_dplx_lock_t; #define MCALL_MSG_SIZE 24 #define CT_NONE 0x0000 #define CT_EVENTS_BLOCKED 0x0002 #define CT_EPOLL_ACTIVE 0x0004 #define CT_XPRT_DESTROYED 0x0008 /* * A client call context. Intended to enable efficient multiplexing of * client calls sharing a client channel. */ typedef struct rpc_call_ctx { struct opr_rbtree_node node_k; struct wait_entry we; uint32_t xid; uint32_t flags; struct rpc_msg *msg; struct rpc_err error; union { struct { struct rpc_client *clnt; struct x_vc_data *xd; struct timespec timeout; } clnt; struct { /* nothing */ } svc; } ctx_u; } rpc_ctx_t; static inline int call_xid_cmpf(const struct opr_rbtree_node *lhs, const struct opr_rbtree_node *rhs) { rpc_ctx_t *lk, *rk; lk = opr_containerof(lhs, rpc_ctx_t, node_k); rk = opr_containerof(rhs, rpc_ctx_t, node_k); if (lk->xid < rk->xid) return (-1); if (lk->xid == rk->xid) return (0); return (1); } /* unify client private data */ struct cu_data { XDR cu_outxdrs; int cu_fd; /* connections fd */ bool 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; u_int cu_xdrpos; u_int cu_sendsz; /* send size */ u_int cu_recvsz; /* recv size */ int cu_async; int cu_connect; /* Use connect(). */ int cu_connected; /* Have done connect(). */ /* formerly, buffers were tacked onto the end */ char *cu_inbuf; char *cu_outbuf; }; struct ct_serialized { union { char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */ u_int32_t ct_mcalli; } ct_u; u_int ct_mpos; /* pos after marshal */ }; struct ct_data { int ct_fd; bool ct_closeit; /* close it on destroy */ struct timeval ct_wait; /* wait interval in milliseconds */ bool ct_waitset; /* wait set by clnt_control? */ struct netbuf ct_addr; /* remote addr */ struct wait_entry ct_sync; /* wait for completion */ }; #ifdef USE_RPC_RDMA struct cm_data { XDR cm_xdrs; char *buffers; struct timeval cm_wait; /* wait interval in milliseconds */ struct timeval cm_total; /* total time for the call */ struct rpc_err cm_error; struct rpc_msg call_msg; //add a lastreceive? u_int cm_xdrpos; bool cm_closeit; /* close it on destroy */ }; #endif enum CX_TYPE { CX_DG_DATA, CX_VC_DATA, CX_MSK_DATA }; #define X_VC_DATA_FLAG_NONE 0x0000 #define X_VC_DATA_FLAG_SVC_DESTROYED 0x0001 /* new unified state */ struct rpc_dplx_rec { int fd_k; #if 0 mutex_t mtx; #else struct { mutex_t mtx; const char *func; int line; } locktrace; #endif struct opr_rbtree_node node_k; uint32_t refcnt; struct { rpc_dplx_lock_t lock; } send; struct { rpc_dplx_lock_t lock; } recv; struct { struct x_vc_data *xd; SVCXPRT *xprt; } hdl; }; #define REC_LOCK(rec) \ do { \ mutex_lock(&((rec)->locktrace.mtx)); \ (rec)->locktrace.func = __func__; \ (rec)->locktrace.line = __LINE__; \ } while (0) #define REC_UNLOCK(rec) mutex_unlock(&((rec)->locktrace.mtx)) struct cx_data { enum CX_TYPE type; union { struct cu_data cu; struct ct_data ct; #ifdef USE_RPC_RDMA struct cm_data cm; #endif } c_u; int cx_fd; /* connection's fd */ struct rpc_dplx_rec *cx_rec; /* unified sync */ }; struct x_vc_data { struct work_pool_entry wpe; /*** 1st ***/ struct rpc_dplx_rec *rec; /* unified sync */ uint32_t flags; uint32_t refcnt; struct { struct ct_data data; struct { uint32_t xid; /* current xid */ struct opr_rbtree t; } calls; } cx; struct { enum xprt_stat strm_stat; struct timespec last_recv; /* XXX move to shared? */ int32_t maxrec; } sx; struct { struct poolq_head ioq; bool active; bool nonblock; u_int sendsz; u_int recvsz; XDR xdrs_in; /* send queue */ XDR xdrs_out; /* recv queue */ } shared; }; #define CU_DATA(cx) (&(cx)->c_u.cu) #define CT_DATA(cx) (&(cx)->c_u.ct) #define CM_DATA(cx) (&(cx)->c_u.cm) /* compartmentalize a bit */ static inline struct x_vc_data * alloc_x_vc_data(void) { struct x_vc_data *xd = mem_zalloc(sizeof(struct x_vc_data)); TAILQ_INIT(&xd->shared.ioq.qh); return (xd); } static inline void free_x_vc_data(struct x_vc_data *xd) { mem_free(xd, sizeof(struct x_vc_data)); } static inline struct cx_data * alloc_cx_data(enum CX_TYPE type, uint32_t sendsz, uint32_t recvsz) { struct cx_data *cx = mem_zalloc(sizeof(struct cx_data)); cx->type = type; switch (type) { case CX_DG_DATA: cx->c_u.cu.cu_inbuf = mem_alloc(recvsz); cx->c_u.cu.cu_outbuf = mem_alloc(sendsz); case CX_VC_DATA: case CX_MSK_DATA: break; default: /* err */ __warnx(TIRPC_DEBUG_FLAG_MEM, "%s: asked to allocate cx_data of unknown type (BUG)", __func__); break; }; return (cx); } static inline void free_cx_data(struct cx_data *cx) { switch (cx->type) { case CX_DG_DATA: mem_free(cx->c_u.cu.cu_inbuf, cx->c_u.cu.cu_recvsz); mem_free(cx->c_u.cu.cu_outbuf, cx->c_u.cu.cu_sendsz); case CX_VC_DATA: case CX_MSK_DATA: break; default: /* err */ __warnx(TIRPC_DEBUG_FLAG_MEM, "%s: asked to free cx_data of unknown type (BUG)", __func__); break; }; mem_free(cx, sizeof(struct cx_data)); } void vc_shared_destroy(struct x_vc_data *xd); #endif /* _CLNT_INTERNAL_H */ ntirpc-1.3.1/src/clnt_perror.c000066400000000000000000000175551261345040100163100ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* #include */ /* * clnt_perror.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include #include #include #include #include #include #include #include static char *buf; static char *_buf(void); static char *auth_errmsg(enum auth_stat); #define CLNT_PERROR_BUFLEN 256 static char * _buf(void) { if (buf == 0) buf = (char *)mem_alloc(CLNT_PERROR_BUFLEN); return (buf); } /* * Print reply error info */ char * clnt_sperror(CLIENT *rpch, const char *s) { struct rpc_err e; char *err; char *str; char *strstart; size_t len, i; if (rpch == NULL || s == NULL) return (0); str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */ if (str == 0) return (0); len = CLNT_PERROR_BUFLEN; strstart = str; CLNT_GETERR(rpch, &e); if (snprintf(str, len, "%s: ", s) > 0) { i = strlen(str); 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: snprintf(str, len, "; errno = %s", strerror(e.re_errno)); i = strlen(str); if (i > 0) { str += i; len -= i; } break; case RPC_VERSMISMATCH: snprintf(str, len, "; low version = %u, high version = %u", e.re_vers.low, e.re_vers.high); i = strlen(str); if (i > 0) { str += i; len -= i; } break; case RPC_AUTHERROR: err = auth_errmsg(e.re_why); snprintf(str, len, "; why = "); i = strlen(str); if (i > 0) { str += i; len -= i; } if (err != NULL) { snprintf(str, len, "%s", err); } else { snprintf(str, len, "(unknown authentication error - %d)", (int)e.re_why); } i = strlen(str); if (i > 0) { str += i; len -= i; } break; case RPC_PROGVERSMISMATCH: snprintf(str, len, "; low version = %u, high version = %u", e.re_vers.low, e.re_vers.high); i = strlen(str); if (i > 0) { str += i; len -= i; } break; default: /* unknown */ snprintf(str, len, "; s1 = %u, s2 = %u", e.re_lb.s1, e.re_lb.s2); i = strlen(str); if (i > 0) { str += i; len -= i; } break; } strstart[CLNT_PERROR_BUFLEN - 1] = '\0'; return (strstart); } void clnt_perror(CLIENT *rpch, const char *s) { if (rpch == NULL || s == NULL) return; (void)fprintf(stderr, "%s\n", clnt_sperror(rpch, s)); } static const char *const rpc_errlist[] = { "RPC: Success", /* 0 - RPC_SUCCESS */ "RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */ "RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */ "RPC: Unable to send", /* 3 - RPC_CANTSEND */ "RPC: Unable to receive", /* 4 - RPC_CANTRECV */ "RPC: Timed out", /* 5 - RPC_TIMEDOUT */ "RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */ "RPC: Authentication error", /* 7 - RPC_AUTHERROR */ "RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */ "RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */ "RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */ "RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */ "RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */ "RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */ "RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */ "RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */ "RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */ "RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */ }; /* * This interface for use by clntrpc */ char * clnt_sperrno(enum clnt_stat stat) { unsigned int errnum = stat; if (errnum < (sizeof(rpc_errlist) / sizeof(rpc_errlist[0]))) /* LINTED interface problem */ return (char *)rpc_errlist[errnum]; return ("RPC: (unknown error code)"); } void clnt_perrno(enum clnt_stat num) { (void)fprintf(stderr, "%s\n", clnt_sperrno(num)); } char * clnt_spcreateerror(const char *s) { char *str, *err; size_t len, i; if (s == NULL) return (0); str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */ if (str == 0) return (0); len = CLNT_PERROR_BUFLEN; snprintf(str, len, "%s: ", s); i = strlen(str); if (i > 0) 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); err = clnt_sperrno(rpc_createerr.cf_error.re_status); if (err) (void)strncat(str, err + 5, len - 5); switch (rpc_createerr.cf_error.re_status) { case RPC_CANTSEND: case RPC_CANTRECV: i = strlen(str); len -= i; snprintf(str + i, len, ": errno %d (%s)", rpc_createerr.cf_error.re_errno, strerror(rpc_createerr.cf_error.re_errno)); break; default: break; } 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; } str[CLNT_PERROR_BUFLEN - 1] = '\0'; return (str); } void clnt_pcreateerror(const char *s) { if (s == NULL) return; (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(enum auth_stat stat) { unsigned int errnum = stat; if (errnum < (sizeof(auth_errlist) / sizeof(auth_errlist[0]))) /* LINTED interface problem */ return (char *)auth_errlist[errnum]; return (NULL); } ntirpc-1.3.1/src/clnt_raw.c000066400000000000000000000173361261345040100155650ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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 #include #include #include #include #include #include #include #include extern mutex_t clntraw_lock; /* XXXX does it need to be extern? */ #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(CLIENT *, AUTH *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval); static void clnt_raw_geterr(CLIENT *, struct rpc_err *); static bool clnt_raw_freeres(CLIENT *, xdrproc_t, void *); static void clnt_raw_abort(CLIENT *); static bool clnt_raw_control(CLIENT *, u_int, void *); static void clnt_raw_destroy(CLIENT *); static struct clnt_ops *clnt_raw_ops(void); /* * Create a client handle for memory based rpc. */ CLIENT * clnt_raw_ncreate(rpcprog_t prog, rpcvers_t vers) { struct clntraw_private *clp; struct rpc_msg call_msg; XDR *xdrs; CLIENT *client; mutex_lock(&clntraw_lock); clp = clntraw_private; if (clp == NULL) { clp = (struct clntraw_private *)calloc(1, sizeof(*clp)); if (clp == NULL) { mutex_unlock(&clntraw_lock); return NULL; } if (__rpc_rawcombuf == NULL) __rpc_rawcombuf = (char *)calloc(UDPMSGSIZE, sizeof(char)); clp->_raw_buf = __rpc_rawcombuf; clntraw_private = clp; } xdrs = &clp->xdr_stream; client = &clp->client_object; /* * pre-serialize the static part of the call msg and stash it away */ call_msg.rm_direction = CALL; call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; /* 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(TIRPC_DEBUG_FLAG_CLNT_RAW, "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(); mutex_unlock(&clntraw_lock); return (client); } /* ARGSUSED */ static enum clnt_stat clnt_raw_call(CLIENT *h, AUTH *auth, rpcproc_t proc, xdrproc_t xargs, void *argsp, xdrproc_t xresults, void *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; assert(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(auth, xdrs)) || (!(*xargs) (xdrs, argsp))) { return (RPC_CANTENCODEARGS); } (void)XDR_GETPOS(xdrs); /* called just to cause overhead */ /* * We have to call server input routine here because this is * all going on in one process. Yuk. */ svc_getreq_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; (void) 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(auth, &msg.acpted_rply.ar_verf)) status = RPC_AUTHERROR; } /* end successful completion */ else { if (AUTH_REFRESH(auth, &msg)) goto call_again; } /* end of unsuccessful completion */ if (status == RPC_SUCCESS) { if (!AUTH_VALIDATE(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(CLIENT *cl, struct rpc_err *err) { } /* ARGSUSED */ static bool clnt_raw_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) { struct clntraw_private *clp = clntraw_private; XDR *xdrs = &clp->xdr_stream; bool rval; mutex_lock(&clntraw_lock); if (clp == NULL) { rval = (bool) 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(CLIENT *cl) { } /*ARGSUSED*/ static bool clnt_raw_control(CLIENT *cl, u_int ui, void *str) { return (false); } /*ARGSUSED*/ static void clnt_raw_destroy(CLIENT *cl) { } static struct clnt_ops * clnt_raw_ops(void) { static struct clnt_ops ops; extern mutex_t ops_lock; /* XXXX does it need to be extern? */ /* 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); } ntirpc-1.3.1/src/clnt_rdma.c000066400000000000000000000276261261345040100157220ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * Dominique Martinet * contributeur : William Allen Simpson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Implements an msk connection client side RPC. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #ifdef IP_RECVERR #include #include #include #endif #include "clnt_internal.h" #include "rpc_rdma.h" #include "rpc_dplx_internal.h" #define MAX_DEFAULT_FDS 20000 static struct clnt_ops *clnt_rdma_ops(void); /* * Make sure that the time is not garbage. -1 value is allowed. */ static bool time_not_ok(struct timeval *t) { return (t->tv_sec < -1 || t->tv_sec > 100000000 || t->tv_usec < -1 || t->tv_usec > 1000000); } /* * client mooshika create */ CLIENT * clnt_rdma_create(RDMAXPRT *xprt, /* init but NOT connect()ed descriptor */ rpcprog_t program, /* program number */ rpcvers_t version, const u_int flags) { CLIENT *cl = NULL; /* client handle */ struct cx_data *cx = NULL; /* private data */ struct cm_data *cm = NULL; struct timeval now; if (!xprt || xprt->state != RDMAXS_INITIAL) { rpc_createerr.cf_stat = RPC_UNKNOWNADDR; /* FIXME, add a warnx? */ rpc_createerr.cf_error.re_errno = 0; return (NULL); } /* * Find the receive and the send size */ // u_int sendsz = 8*1024; // u_int recvsz = 4*8*1024; u_int sendsz = 1024; u_int recvsz = 1024; if ((cl = mem_alloc(sizeof (CLIENT))) == NULL) goto err1; /* * Should be multiple of 4 for XDR. */ cx = alloc_cx_data(CX_MSK_DATA, sendsz, recvsz); if (cx == NULL) goto err1; cm = CM_DATA(cx); /* Other values can also be set through clnt_control() */ cm->cm_xdrs.x_lib[1] = (void *)xprt; cm->cm_wait.tv_sec = 15; /* heuristically chosen */ cm->cm_wait.tv_usec = 0; (void) gettimeofday(&now, NULL); // cm->call_msg.rm_xid = __RPC_GETXID(&now); cm->call_msg.rm_xid = 1; cm->call_msg.rm_call.cb_prog = program; cm->call_msg.rm_call.cb_vers = version; rpc_rdma_connect(xprt); xdr_rdma_create(&cm->cm_xdrs, xprt, sendsz, recvsz, flags); rpc_rdma_connect_finalize(xprt); /* * 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. */ cm->cm_closeit = FALSE; cl->cl_ops = clnt_rdma_ops(); // cl->cl_private = (caddr_t)(void *) cx; cl->cl_p1 = (caddr_t)(void *) cx; cl->cl_p2 = NULL; // cl->cl_p2 = rec; // cl->cl_auth = authnone_create(); cl->cl_tp = NULL; cl->cl_netid = NULL; return (cl); err1: __warnx(TIRPC_DEBUG_FLAG_CLNT_RDMA, "%s: err, out of memory", __func__); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; if (cl) { mem_free(cl, sizeof (CLIENT)); if (cx) free_cx_data(cx); } return (NULL); } static enum clnt_stat clnt_rdma_call(CLIENT *cl, /* client handle */ AUTH *auth, rpcproc_t proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ void *argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ void *resultsp, /* pointer to results */ struct timeval utimeout /* seconds to wait before giving up */) { struct cm_data *cm = CM_DATA((struct cx_data *) cl->cl_p1); XDR *xdrs; struct rpc_msg reply_msg; bool ok; #if 0 struct timeval timeout; int total_time; #endif // sigset_t mask; socklen_t __attribute__((unused)) inlen, salen; int nrefreshes = 2; /* number of times to refresh cred */ // thr_sigsetmask(SIG_SETMASK, (sigset_t *) 0, &mask); /* XXX */ // vc_fd_lock_c(cl, &mask); //What does that do? #if 0 if (cm->cm_total.tv_usec == -1) { timeout = utimeout; /* use supplied timeout */ } else { timeout = cm->cm_total; /* use default timeout */ } total_time = timeout.tv_sec * 1000 + timeout.tv_usec / 1000; #endif /* Clean up in case the last call ended in a longjmp(3) call. */ call_again: xdrs = &(cm->cm_xdrs); if (0) //FIXME check for async goto get_reply; if (! xdr_rdma_clnt_call(&cm->cm_xdrs, cm->call_msg.rm_xid) || ! xdr_callhdr(&(cm->cm_xdrs), &cm->call_msg)) { rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */ rpc_createerr.cf_error.re_errno = 0; goto out; } if ((! XDR_PUTINT32(xdrs, (int32_t *)&proc)) || (! AUTH_MARSHALL(auth, xdrs)) || (! AUTH_WRAP(auth, xdrs, xargs, argsp))) { cm->cm_error.re_status = RPC_CANTENCODEARGS; goto out; } if (! xdr_rdma_clnt_flushout(&cm->cm_xdrs)) { cm->cm_error.re_errno = errno; cm->cm_error.re_status = RPC_CANTSEND; goto out; } get_reply: /* * sub-optimal code appears here because we have * some clock time to spare while the packets are in flight. * (We assume that this is actually only executed once.) */ reply_msg.acpted_rply.ar_verf = _null_auth; reply_msg.acpted_rply.ar_results.where = NULL; reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; if (! xdr_rdma_clnt_reply(&cm->cm_xdrs, cm->call_msg.rm_xid)) { //FIXME add timeout cm->cm_error.re_status = RPC_TIMEDOUT; goto out; } /* * now decode and validate the response */ ok = xdr_replymsg(&cm->cm_xdrs, &reply_msg); if (ok) { if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) && (reply_msg.acpted_rply.ar_stat == SUCCESS)) cm->cm_error.re_status = RPC_SUCCESS; else _seterr_reply(&reply_msg, &(cm->cm_error)); if (cm->cm_error.re_status == RPC_SUCCESS) { if (! AUTH_VALIDATE(auth, &reply_msg.acpted_rply.ar_verf)) { cm->cm_error.re_status = RPC_AUTHERROR; cm->cm_error.re_why = AUTH_INVALIDRESP; } else if (! AUTH_UNWRAP(auth, &cm->cm_xdrs, xresults, resultsp)) { if (cm->cm_error.re_status == RPC_SUCCESS) cm->cm_error.re_status = RPC_CANTDECODERES; } 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 (cm->cm_error.re_status == RPC_AUTHERROR) /* maybe our credentials need to be refreshed ... */ if (nrefreshes > 0 && AUTH_REFRESH(auth, &reply_msg)) { nrefreshes--; goto call_again; } /* end of unsuccessful completion */ } /* end of valid reply message */ else { cm->cm_error.re_status = RPC_CANTDECODERES; } out: cm->call_msg.rm_xid++; // vc_fd_unlock_c(cl, &mask); return (cm->cm_error.re_status); } static void clnt_rdma_geterr(CLIENT *cl, struct rpc_err *errp) { struct cm_data *cm = CM_DATA((struct cx_data *) cl->cl_p1); *errp = cm->cm_error; } static bool clnt_rdma_freeres(CLIENT *cl, xdrproc_t xdr_res, void *res_ptr) { struct cm_data *cm = CM_DATA((struct cx_data *)cl->cl_p1); XDR *xdrs; sigset_t mask, newmask; bool dummy = 0; /* XXX guard against illegal invocation from libc (will fix) */ if (! xdr_res) goto out; xdrs = &(cm->cm_xdrs); /* Handle our own signal mask here, the signal section is * larger than the wait (not 100% clear why) */ /* barrier recv channel */ // rpc_dplx_rwc(clnt, rpc_flag_clear); sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); xdrs->x_op = XDR_FREE; if (xdr_res) dummy = (*xdr_res)(xdrs, res_ptr); thr_sigsetmask(SIG_SETMASK, &mask, NULL); rpc_dplx_rsc(cl, RPC_DPLX_FLAG_NONE); out: return (dummy); } /*ARGSUSED*/ static void clnt_rdma_abort(CLIENT *h) { } static bool clnt_rdma_control(CLIENT *cl, u_int request, void *info) { struct cm_data *cm = CM_DATA((struct cx_data *) cl->cl_p1); sigset_t mask; bool result = TRUE; thr_sigsetmask(SIG_SETMASK, (sigset_t *) 0, &mask); /* XXX */ /* always take recv lock first if taking together */ rpc_dplx_rlc(cl); //receive lock clnt rpc_dplx_slc(cl); //send lock clnt switch (request) { case CLSET_FD_CLOSE: cm->cm_closeit = TRUE; result = TRUE; goto unlock; case CLSET_FD_NCLOSE: cm->cm_closeit = FALSE; result = TRUE; goto unlock; } /* for other requests which use info */ if (info == NULL) { result = FALSE; goto unlock; } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { result = FALSE; goto unlock; } cm->cm_total = *(struct timeval *)info; break; case CLGET_TIMEOUT: *(struct timeval *)info = cm->cm_total; break; case CLSET_RETRY_TIMEOUT: if (time_not_ok((struct timeval *)info)) { result = FALSE; goto unlock; } cm->cm_wait = *(struct timeval *)info; break; case CLGET_RETRY_TIMEOUT: *(struct timeval *)info = cm->cm_wait; break; case CLGET_FD: *(RDMAXPRT **)info = cm->cm_xdrs.x_lib[1]; 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 *)info = cm->call_msg.rm_xid - 1; break; case CLSET_XID: /* This will set the xid of the NEXT call */ cm->call_msg.rm_xid = *(u_int32_t *)info; break; case CLGET_VERS: *(u_int32_t *)info = cm->call_msg.rm_call.cb_vers; break; case CLSET_VERS: cm->call_msg.rm_call.cb_vers = *(u_int32_t *)info; break; case CLGET_PROG: *(u_int32_t *)info = cm->call_msg.rm_call.cb_prog; break; case CLSET_PROG: cm->call_msg.rm_call.cb_prog = *(u_int32_t *)info; break; case CLSET_ASYNC: //FIXME cm->cm_async = *(int *)info; break; case CLSET_CONNECT: //FIXMEcm->cm_connect = *(int *)info; break; default: break; } unlock: rpc_dplx_ruc(cl); rpc_dplx_suc(cl); return (result); } static void clnt_rdma_destroy(CLIENT *cl) { // struct cx_data *cx = (struct cx_data *)cl->cl_private; //FIXME } static struct clnt_ops * clnt_rdma_ops(void) { static struct clnt_ops ops; extern mutex_t ops_lock; sigset_t mask; 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_rdma_call; ops.cl_abort = clnt_rdma_abort; ops.cl_geterr = clnt_rdma_geterr; ops.cl_freeres = clnt_rdma_freeres; ops.cl_destroy = clnt_rdma_destroy; ops.cl_control = clnt_rdma_control; } mutex_unlock(&ops_lock); thr_sigsetmask(SIG_SETMASK, &mask, NULL); return (&ops); } ntirpc-1.3.1/src/clnt_simple.c000066400000000000000000000127411261345040100162600ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ #include #include /* * clnt_simple.c * Simplified front end to client rpc. */ #include #include #include #include #include #include #include #include #include #include #include #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 */ AUTH *auth; 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 void rpc_call_destroy(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); mem_free(rcp, 0); } } /* * 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(const char *host, /* host name */ rpcprog_t prognum, /* program number */ rpcvers_t versnum, /* version number */ rpcproc_t procnum, /* procedure number */ xdrproc_t inproc, /* in XDR procedure */ const char *in, xdrproc_t outproc, /* out XDR procedure */ 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; extern thread_key_t rpc_call_key; extern mutex_t tsd_lock; if (rpc_call_key == -1) { mutex_lock(&tsd_lock); if (rpc_call_key == -1) thr_keycreate(&rpc_call_key, rpc_call_destroy); mutex_unlock(&tsd_lock); } rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key); if (rcp == NULL) { rcp = mem_alloc(sizeof(*rcp)); if (rcp == NULL) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; return (rpc_createerr.cf_stat); } 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_ncreate(host, prognum, versnum, nettype); rcp->pid = getpid(); if (rcp->client == NULL) return (rpc_createerr.cf_stat); /* Create null auth handle--idempotent */ rcp->auth = authnone_create(); /* * 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)) fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ 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; /* LINTED const castaway */ clnt_stat = CLNT_CALL(rcp->client, rcp->auth, procnum, inproc, (char *)in, outproc, out, tottimeout); /* * if call failed, empty cache */ if (clnt_stat != RPC_SUCCESS) rcp->valid = 0; return (clnt_stat); } ntirpc-1.3.1/src/clnt_vc.c000066400000000000000000000627201261345040100154010ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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. [Ouch, that was intemperate.] */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include "clnt_internal.h" #include "rpc_dplx_internal.h" #include "rpc_ctx.h" #include #include #include #include "svc_ioq.h" #ifndef __APPLE__ struct cmessage { struct cmsghdr cmsg; struct cmsgcred cmcred; }; #endif static enum clnt_stat clnt_vc_call(CLIENT *, AUTH *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval); static void clnt_vc_geterr(CLIENT *, struct rpc_err *); static bool clnt_vc_freeres(CLIENT *, xdrproc_t, void *); static void clnt_vc_abort(CLIENT *); static bool clnt_vc_control(CLIENT *, u_int, void *); static bool clnt_vc_ref(CLIENT *, u_int); static void clnt_vc_release(CLIENT *, u_int); static void clnt_vc_destroy(CLIENT *); static struct clnt_ops *clnt_vc_ops(void); static bool time_not_ok(struct timeval *); int generic_read_vc(XDR *, void *, void *, int); int generic_write_vc(XDR *, void *, void *, int); #include "clnt_internal.h" #include "svc_internal.h" /* * 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 active on some * CLIENT handle created for that fd. (Historical interest only.) * * 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. (Fixing this.) * * The ONC RPC record marking (RM) standard (RFC 5531, s. 11) does not * provide for mixed call and reply fragment reassembly, so writes to the * bytestream with MUST be record-wise atomic. It appears that an * implementation may interleave call and reply messages on distinct * conversations. This is not incompatible with holding a transport * exclusive locked across a full call and reply, bud does require new * control tranfers and delayed decoding support in the transport. For * duplex channels, full coordination is required between client and * server tranpsorts sharing an underlying bytestream (Matt). */ static const char clnt_vc_errstr[] = "%s : %s"; static const char clnt_vc_str[] = "clnt_vc_ncreate"; static const char __no_mem_str[] = "out of memory"; /* * 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_ncreate(int fd, /* open file descriptor */ const struct netbuf *raddr, /* servers address */ const rpcprog_t prog, /* program number */ const rpcvers_t vers, /* version number */ u_int sendsz, /* buffer recv size */ u_int recvsz /* buffer send size */) { return (clnt_vc_ncreate2 (fd, raddr, prog, vers, sendsz, recvsz, CLNT_CREATE_FLAG_CONNECT)); } CLIENT * clnt_vc_ncreate2(int fd, /* open file descriptor */ const struct netbuf *raddr, /* servers address */ const rpcprog_t prog, /* program number */ const rpcvers_t vers, /* version number */ u_int sendsz, /* buffer send size */ u_int recvsz, /* buffer recv size */ u_int flags) { CLIENT *clnt = NULL; struct rpc_dplx_rec *rec = NULL; struct x_vc_data *xd = NULL; struct ct_data *ct = NULL; struct ct_serialized *cs = NULL; struct rpc_msg call_msg; sigset_t mask, newmask; struct __rpc_sockinfo si; struct sockaddr_storage ss; XDR ct_xdrs[1]; /* temp XDR stream */ uint32_t oflags; socklen_t slen; sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); if (flags & CLNT_CREATE_FLAG_CONNECT) { slen = sizeof(ss); if (getpeername(fd, (struct sockaddr *)&ss, &slen) < 0) { if (errno != ENOTCONN) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } if (connect (fd, (struct sockaddr *)raddr->buf, raddr->len) < 0) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } } } /* connect */ if (!__rpc_fd2sockinfo(fd, &si)) goto err; /* atomically find or create shared fd state */ rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_LKP_IFLAG_LOCKREC, &oflags); if (!rec) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "clnt_vc_ncreate2: rpc_dplx_lookup_rec failed"); goto err; } /* attach shared state */ if ((oflags & RPC_DPLX_LKP_OFLAG_ALLOC) || (!rec->hdl.xd)) { xd = rec->hdl.xd = alloc_x_vc_data(); if (!xd) { (void)syslog(LOG_ERR, clnt_vc_errstr, clnt_vc_str, __no_mem_str); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } xd->rec = rec; /* XXX tracks outstanding calls */ opr_rbtree_init(&xd->cx.calls.t, call_xid_cmpf); xd->cx.calls.xid = 0; /* next call xid is 1 */ xd->refcnt = 1; xd->shared.sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz); xd->shared.recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz); /* duplex streams */ xdr_inrec_create(&(xd->shared.xdrs_in), xd->shared.recvsz, xd, generic_read_vc); xd->shared.xdrs_in.x_op = XDR_DECODE; xdrrec_create(&(xd->shared.xdrs_out), sendsz, xd->shared.recvsz, xd, generic_read_vc, generic_write_vc); xd->shared.xdrs_out.x_op = XDR_ENCODE; } else { xd = rec->hdl.xd; ++(xd->refcnt); } clnt = (CLIENT *) mem_alloc(sizeof(CLIENT)); if (!clnt) { (void)syslog(LOG_ERR, clnt_vc_errstr, clnt_vc_str, __no_mem_str); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; goto err; } mutex_init(&clnt->cl_lock, NULL); clnt->cl_flags = CLNT_FLAG_NONE; clnt->cl_refcnt = 1; /* private data struct */ xd->cx.data.ct_fd = fd; cs = mem_alloc(sizeof(struct ct_serialized)); ct = &xd->cx.data; ct->ct_closeit = false; ct->ct_wait.tv_usec = 0; ct->ct_waitset = false; ct->ct_addr.buf = mem_alloc(raddr->maxlen); if (ct->ct_addr.buf == NULL) goto err; memcpy(ct->ct_addr.buf, raddr->buf, raddr->len); ct->ct_addr.len = raddr->len; ct->ct_addr.maxlen = raddr->maxlen; clnt->cl_netid = NULL; clnt->cl_tp = NULL; /* * initialize call message */ call_msg.rm_xid = 1; 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_xdrs, cs->ct_u.ct_mcallc, MCALL_MSG_SIZE, XDR_ENCODE); if (!xdr_callhdr(ct_xdrs, &call_msg)) { if (ct->ct_closeit) (void)close(fd); goto err; } cs->ct_mpos = XDR_GETPOS(ct_xdrs); XDR_DESTROY(ct_xdrs); /* * Create a client handle which uses xdrrec for serialization * and authnone for authentication. */ clnt->cl_ops = clnt_vc_ops(); clnt->cl_p1 = xd; clnt->cl_p2 = rec; clnt->cl_p3 = cs; /* release rec */ REC_UNLOCK(rec); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); return (clnt); err: if (clnt) { /* XXX fix */ if (xd) { if (ct->ct_addr.len) mem_free(ct->ct_addr.buf, ct->ct_addr.len); free_x_vc_data(xd); } if (cs) { mem_free(cs, sizeof(struct ct_serialized)); } mutex_destroy(&clnt->cl_lock); mem_free(clnt, sizeof(CLIENT)); } if (rec) { if (rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED)) REC_UNLOCK(rec); } thr_sigsetmask(SIG_SETMASK, &(mask), NULL); return (NULL); } #define vc_call_return(r) \ do { \ result = (r); \ goto out; \ } while (0) #define vc_call_return_slocked(r) \ do { \ result = (r); \ if (!bidi) \ rpc_dplx_suc(clnt); \ goto out; \ } while (0) #define vc_call_return_rlocked(r) \ do { \ result = (r); \ rpc_dplx_ruc(clnt); \ goto out; \ } while (0) static enum clnt_stat clnt_vc_call(CLIENT *clnt, AUTH *auth, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr, xdrproc_t xdr_results, void *results_ptr, struct timeval timeout) { struct x_vc_data *xd = (struct x_vc_data *)clnt->cl_p1; struct ct_data *ct = &(xd->cx.data); struct ct_serialized *cs = (struct ct_serialized *)clnt->cl_p3; struct rpc_dplx_rec *rec = xd->rec; enum clnt_stat result = RPC_SUCCESS; rpc_ctx_t *ctx = NULL; XDR *xdrs; int code, refreshes = 2; bool ctx_needack = false; bool bidi = (rec->hdl.xprt != NULL); bool shipnow; bool gss = false; /* Create a call context. A lot of TI-RPC decisions need to be * looked at, including: * * 1. the client has a serialized call. This looks harmless, so long * as the xid is adjusted. * * 2. the last xid used is now saved in handle shared private data, it * will be incremented by rpc_call_create (successive calls). There's * no more reason to use the old time-dependent xid logic. It should be * preferable to count atomically from 1. * * 3. the client has an XDR structure, which contains the initialied * xdrrec stream. Since there is only one physical byte stream, it * would potentially be worse to do anything else? The main issue which * will arise is the need to transition the stream between calls--which * may require adjustment to xdrrec code. But on review it seems to * follow that one xdrrec stream would be parameterized by different * call contexts. We'll keep the call parameters, control transfer * machinery, etc, in an rpc_ctx_t, to permit this. */ ctx = alloc_rpc_call_ctx(clnt, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout); /*add total timeout? */ if (!ct->ct_waitset) { /* If time is not within limits, we ignore it. */ 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: if (bidi) { /* XXX Until gss_get_mic and gss_wrap can be replaced with * iov equivalents, replies with RPCSEC_GSS security must be * encoded in a contiguous buffer. * * Nb, we should probably use getpagesize() on Unix. Need * an equivalent for Windows. */ gss = (auth->ah_cred.oa_flavor == RPCSEC_GSS); xdrs = xdr_ioq_create(8192 /* default segment size */ , __svc_params->svc_ioq_maxbuf + 8192, gss ? UIO_FLAG_REALLOC | UIO_FLAG_FREE : UIO_FLAG_FREE); } else { rpc_dplx_slc(clnt); xdrs = &(xd->shared.xdrs_out); xdrs->x_lib[0] = (void *)RPC_DPLX_CLNT; xdrs->x_lib[1] = (void *)ctx; /* thread call ctx */ } ctx->error.re_status = RPC_SUCCESS; cs->ct_u.ct_mcalli = ntohl(ctx->xid); if ((!XDR_PUTBYTES(xdrs, cs->ct_u.ct_mcallc, cs->ct_mpos)) || (!XDR_PUTINT32(xdrs, (int32_t *) &proc)) || (!AUTH_MARSHALL(auth, xdrs)) || (!AUTH_WRAP(auth, xdrs, xdr_args, args_ptr))) { if (ctx->error.re_status == RPC_SUCCESS) ctx->error.re_status = RPC_CANTENCODEARGS; /* error case */ if (!bidi) { (void)xdrrec_endofrecord(xdrs, true); vc_call_return_slocked(ctx->error.re_status); } else vc_call_return(ctx->error.re_status); } if (bidi) { svc_ioq_append(rec->hdl.xprt, xd, xdrs); } else { if (!xdrrec_endofrecord(xdrs, shipnow)) vc_call_return_slocked(ctx->error.re_status = RPC_CANTSEND); if (!shipnow) vc_call_return_slocked(RPC_SUCCESS); /* * Hack to provide rpc-based message passing */ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) vc_call_return_slocked(ctx->error.re_status = RPC_TIMEDOUT); rpc_dplx_suc(clnt); } /* reply */ rpc_dplx_rlc(clnt); /* if the channel is bi-directional, then the the shared conn is in a * svc event loop, and recv processing decodes reply headers */ xdrs = &(xd->shared.xdrs_in); xdrs->x_lib[0] = (void *)RPC_DPLX_CLNT; xdrs->x_lib[1] = (void *)ctx; /* transiently thread call ctx */ if (bidi) { code = rpc_ctx_wait_reply(ctx, RPC_DPLX_FLAG_LOCKED);/* RECV! */ if (code == ETIMEDOUT) { /* UL can retry, we dont. This CAN indicate xprt * destroyed (error status already set). */ ctx->error.re_status = RPC_TIMEDOUT; goto unlock; } /* switch on direction */ switch (ctx->msg->rm_direction) { case REPLY: if (ctx->msg->rm_xid == ctx->xid) { ctx_needack = true; goto replied; } break; case CALL: /* in this configuration, we do not expect calls */ break; default: break; } } else { /* * Keep receiving until we get a valid transaction id. */ while (true) { /* skiprecord */ if (!xdr_inrec_skiprecord(xdrs)) { __warnx(TIRPC_DEBUG_FLAG_CLNT_VC, "%s: error at skiprecord", __func__); vc_call_return_rlocked(ctx->error.re_status); } /* now decode and validate the response header */ if (!xdr_dplx_decode(xdrs, ctx->msg)) { __warnx(TIRPC_DEBUG_FLAG_CLNT_VC, "%s: error at xdr_dplx_decode", __func__); vc_call_return_rlocked(ctx->error.re_status); } /* switch on direction */ switch (ctx->msg->rm_direction) { case REPLY: if (ctx->msg->rm_xid == ctx->xid) goto replied; break; case CALL: /* in this configuration, we do not expect * calls */ break; default: break; } } /* while (true) */ } /* ! bi-directional */ /* * process header */ replied: /* XXX move into routine which can be called from rpc_ctx_xfer_replymsg, * for (maybe) reduced MP overhead */ _seterr_reply(ctx->msg, &(ctx->error)); if (ctx->error.re_status == RPC_SUCCESS) { if (!AUTH_VALIDATE(auth, &(ctx->msg->acpted_rply.ar_verf))) { ctx->error.re_status = RPC_AUTHERROR; ctx->error.re_why = AUTH_INVALIDRESP; } else if (xdr_results /* XXX caller setup error? */ && !AUTH_UNWRAP(auth, xdrs, xdr_results, results_ptr)) { if (ctx->error.re_status == RPC_SUCCESS) ctx->error.re_status = RPC_CANTDECODERES; } /* free verifier ... */ if (ctx->msg->acpted_rply.ar_verf.oa_base != NULL) { xdrs->x_op = XDR_FREE; (void)xdr_opaque_auth(xdrs, &(ctx->msg->acpted_rply.ar_verf)); } if (ctx_needack) rpc_ctx_ack_xfer(ctx); } /* end successful completion */ else { /* maybe our credentials need to be refreshed ... */ if (refreshes-- && AUTH_REFRESH(auth, &(ctx->msg))) { rpc_ctx_next_xid(ctx, RPC_CTX_FLAG_NONE); rpc_dplx_ruc(clnt); if (ctx_needack) rpc_ctx_ack_xfer(ctx); goto call_again; } } /* end of unsuccessful completion */ unlock: vc_call_return_rlocked(ctx->error.re_status); out: free_rpc_call_ctx(ctx, RPC_CTX_FLAG_NONE); return (result); } static void clnt_vc_geterr(CLIENT *clnt, struct rpc_err *errp) { struct x_vc_data *xd = (struct x_vc_data *)clnt->cl_p1; XDR *xdrs; /* assert: it doesn't matter which we use */ xdrs = &xd->shared.xdrs_out; if (xdrs->x_lib[0]) { rpc_ctx_t *ctx = (rpc_ctx_t *) xdrs->x_lib[1]; *errp = ctx->error; } else { /* XXX we don't want (overhead of) an unsafe last-error value */ struct rpc_err err; memset(&err, 0, sizeof(struct rpc_err)); *errp = err; } } static bool clnt_vc_freeres(CLIENT *clnt, xdrproc_t xdr_res, void *res_ptr) { sigset_t mask, newmask; bool rslt; /* XXX is this (legacy) signalling/barrier logic needed? */ /* Handle our own signal mask here, the signal section is * larger than the wait (not 100% clear why) */ sigfillset(&newmask); thr_sigsetmask(SIG_SETMASK, &newmask, &mask); /* barrier recv channel */ rpc_dplx_rwc(clnt, rpc_flag_clear); rslt = xdr_free(xdr_res, res_ptr); thr_sigsetmask(SIG_SETMASK, &(mask), NULL); /* signal recv channel */ rpc_dplx_rsc(clnt, RPC_DPLX_FLAG_NONE); return (rslt); } /*ARGSUSED*/ static void clnt_vc_abort(CLIENT *clnt) { } static bool clnt_vc_control(CLIENT *clnt, u_int request, void *info) { struct x_vc_data *xd = (struct x_vc_data *)clnt->cl_p1; struct ct_data *ct = &(xd->cx.data); struct ct_serialized *cs = (struct ct_serialized *)clnt->cl_p3; void *infop = info; bool rslt = true; /* always take recv lock first if taking together */ rpc_dplx_rlc(clnt); rpc_dplx_slc(clnt); switch (request) { case CLSET_FD_CLOSE: ct->ct_closeit = true; goto unlock; return (true); case CLSET_FD_NCLOSE: ct->ct_closeit = false; goto unlock; return (true); default: break; } /* for other requests which use info */ if (info == NULL) { rslt = false; goto unlock; } switch (request) { case CLSET_TIMEOUT: if (time_not_ok((struct timeval *)info)) { rslt = false; goto unlock; } 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 *)info = ct->ct_fd; break; case CLGET_SVC_ADDR: /* The caller should not free this memory area */ *(struct netbuf *)info = ct->ct_addr; break; case CLSET_SVC_ADDR: /* set to new address */ rslt = false; goto unlock; 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 *) info = ntohl(*(u_int32_t *) (void *)&cs->ct_u.ct_mcalli); break; case CLSET_XID: /* This will set the xid of the NEXT call */ *(u_int32_t *) (void *)&cs->ct_u.ct_mcalli = htonl(*((u_int32_t *) 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 *tmp = (u_int32_t *) (cs->ct_u.ct_mcallc + 4 * BYTES_PER_XDR_UNIT); *(u_int32_t *) info = ntohl(*tmp); } break; case CLSET_VERS: { u_int32_t tmp = htonl(*(u_int32_t *) info); *(cs->ct_u.ct_mcallc + 4 * BYTES_PER_XDR_UNIT) = tmp; } 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 *tmp = (u_int32_t *) (cs->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT); *(u_int32_t *) info = ntohl(*tmp); } break; case CLSET_PROG: { u_int32_t tmp = htonl(*(u_int32_t *) info); *(cs->ct_u.ct_mcallc + 3 * BYTES_PER_XDR_UNIT) = tmp; } break; default: rslt = false; goto unlock; break; } unlock: rpc_dplx_ruc(clnt); rpc_dplx_suc(clnt); return (rslt); } static bool clnt_vc_ref(CLIENT *clnt, u_int flags) { uint32_t refcnt; if (!(flags & CLNT_REF_FLAG_LOCKED)) mutex_lock(&clnt->cl_lock); if (clnt->cl_flags & CLNT_FLAG_DESTROYED) { mutex_unlock(&clnt->cl_lock); return (false); } refcnt = ++(clnt->cl_refcnt); mutex_unlock(&clnt->cl_lock); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: postref %p %u", __func__, clnt, refcnt); return (true); } static void clnt_vc_release(CLIENT *clnt, u_int flags) { uint32_t cl_refcnt; if (!(flags & CLNT_RELEASE_FLAG_LOCKED)) mutex_lock(&clnt->cl_lock); cl_refcnt = --(clnt->cl_refcnt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: postunref %p cl_refcnt %u", __func__, clnt, cl_refcnt); /* conditional destroy */ if ((clnt->cl_flags & CLNT_FLAG_DESTROYED) && (cl_refcnt == 0)) { struct x_vc_data *xd = (struct x_vc_data *)clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; struct ct_serialized *cs = (struct ct_serialized *)clnt->cl_p3; uint32_t xd_refcnt; mutex_unlock(&clnt->cl_lock); /* client handles are now freed directly */ mem_free(cs, sizeof(struct ct_serialized)); if (clnt->cl_netid && clnt->cl_netid[0]) mem_free(clnt->cl_netid, strlen(clnt->cl_netid) + 1); if (clnt->cl_tp && clnt->cl_tp[0]) mem_free(clnt->cl_tp, strlen(clnt->cl_tp) + 1); mutex_destroy(&clnt->cl_lock); mem_free(clnt, sizeof(CLIENT)); REC_LOCK(rec); xd_refcnt = --(xd->refcnt); if (xd_refcnt == 0) { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: xd_refcnt %u on destroyed %p %u calling " "vc_shared_destroy", __func__, clnt, cl_refcnt); vc_shared_destroy(xd); /* RECLOCKED */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_NONE); } else { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: xd_refcnt %u on destroyed %p omit " "vc_shared_destroy", __func__, clnt, cl_refcnt); rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED); } } else mutex_unlock(&clnt->cl_lock); } static void clnt_vc_destroy(CLIENT *clnt) { struct rpc_dplx_rec *rec; struct x_vc_data *xd; uint32_t cl_refcnt = 0; uint32_t xd_refcnt = 0; mutex_lock(&clnt->cl_lock); if (clnt->cl_flags & CLNT_FLAG_DESTROYED) { mutex_unlock(&clnt->cl_lock); goto out; } xd = (struct x_vc_data *)clnt->cl_p1; rec = xd->rec; clnt->cl_flags |= CLNT_FLAG_DESTROYED; cl_refcnt = --(clnt->cl_refcnt); mutex_unlock(&clnt->cl_lock); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: cl_destroy %p cl_refcnt %u", __func__, clnt, cl_refcnt); /* bidirectional */ REC_LOCK(rec); xd_refcnt = --(xd->refcnt); /* conditional destroy */ if (cl_refcnt == 0) { struct ct_serialized *cs = (struct ct_serialized *)clnt->cl_p3; /* client handles are now freed directly */ mem_free(cs, sizeof(struct ct_serialized)); if (clnt->cl_netid && clnt->cl_netid[0]) mem_free(clnt->cl_netid, strlen(clnt->cl_netid) + 1); if (clnt->cl_tp && clnt->cl_tp[0]) mem_free(clnt->cl_tp, strlen(clnt->cl_tp) + 1); mutex_destroy(&clnt->cl_lock); mem_free(clnt, sizeof(CLIENT)); if (xd_refcnt == 0) { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: %p cl_refcnt %u xd_refcnt %u calling " "vc_shared_destroy", __func__, clnt, cl_refcnt, xd_refcnt); vc_shared_destroy(xd); /* RECLOCKED */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_NONE); goto out; } } REC_UNLOCK(rec); out: return; } static struct clnt_ops * clnt_vc_ops(void) { static struct clnt_ops ops; extern mutex_t ops_lock; sigset_t mask, 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_ref = clnt_vc_ref; ops.cl_release = clnt_vc_release; 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 time_not_ok(struct timeval *t) { return (t->tv_sec <= -1 || t->tv_sec > 100000000 || t->tv_usec <= -1 || t->tv_usec > 1000000); } ntirpc-1.3.1/src/des_crypt.c000066400000000000000000000074701261345040100157460ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * des_crypt.c, DES encryption library routines * Copyright (C) 1986, Sun Microsystems, Inc. */ #include #include #include #include #if 0 #ifndef lint static const char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; " "from 1.13 88/02/08 SMI"; #endif #endif #include static int common_crypt(char *, char *, unsigned, unsigned, struct desparams *); int (*__des_crypt_LOCAL) () = 0; extern int _des_crypt_call(char *, int, struct desparams *); /* * Copy 8 bytes */ #define COPY8(src, dst) { \ char *a = (char *) dst; \ char *b = (char *) src; \ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ } /* * Copy multiple of 8 bytes */ #define DESCOPY(src, dst, len) { \ char *a = (char *) dst; \ char *b = (char *) src; \ int i; \ for (i = (int) len; i > 0; i -= 8) { \ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ } \ } /* * CBC mode encryption */ int cbc_crypt(char *key, char *buf, unsigned len, unsigned mode, char *ivec) { int err; struct desparams dp; #ifdef BROKEN_DES dp.UDES.UDES_buf = buf; dp.des_mode = ECB; #else dp.des_mode = CBC; #endif COPY8(ivec, dp.des_ivec); err = common_crypt(key, buf, len, mode, &dp); COPY8(dp.des_ivec, ivec); return (err); } /* * ECB mode encryption */ int ecb_crypt(char *key, char *buf, unsigned len, unsigned mode) { struct desparams dp; #ifdef BROKEN_DES dp.UDES.UDES_buf = buf; dp.des_mode = CBC; #else dp.des_mode = ECB; #endif return (common_crypt(key, buf, len, mode, &dp)); } /* * Common code to cbc_crypt() & ecb_crypt() */ static int common_crypt(char *key, char *buf, unsigned len, unsigned mode, struct desparams *desp) { int desdev; if ((len % 8) != 0 || len > DES_MAXDATA) return (DESERR_BADPARAM); desp->des_dir = ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT; desdev = mode & DES_DEVMASK; COPY8(key, desp->des_key); /* * software */ if (__des_crypt_LOCAL != NULL) { if (!__des_crypt_LOCAL(buf, len, desp)) return (DESERR_HWERROR); } else { if (!_des_crypt_call(buf, len, desp)) return (DESERR_HWERROR); } return (desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE); } ntirpc-1.3.1/src/des_soft.c000066400000000000000000000050731261345040100155550ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Table giving odd parity in the low bit for ASCII characters */ static char partab[128] = { 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, }; /* * Add odd parity to low bit of 8 byte key */ void des_setparity(char *p) { int i; for (i = 0; i < 8; i++) { *p = partab[*p & 0x7f]; p++; } } ntirpc-1.3.1/src/getnetconfig.c000066400000000000000000000462751261345040100164340ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1989 by Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" /* * 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 */ #define NC_NOTFOUND ENOPROTOOPT /* specified netid was not found */ /* * 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 "-" /* serialize globals */ static mutex_t nc_mtx = MUTEX_INITIALIZER; static const char *const _nc_errors[] = { "Netconfig database not found", "Not enough memory", "Not initialized", "Netconfig database has invalid format", "Netid not found in netconfig database" }; 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 a 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(void); static int parse_ncp(char *, struct netconfig *); static struct netconfig *dup_ncp(struct netconfig *); static FILE *nc_file; /* for netconfig db */ static struct netconfig_info ni = { 0, 0, NULL, NULL }; #define MAXNETCONFIGLINE 1000 static int * __nc_error(void) { static pthread_mutex_t nc_lock = MUTEX_INITIALIZER; extern thread_key_t nc_key; static int nc_error; int error, *nc_addr; /* * Use the static `nc_error' if we are the main thread * (including non-threaded programs), or if an allocation * fails. */ if (nc_key == -1) { error = 0; mutex_lock(&nc_lock); if (nc_key == -1) error = thr_keycreate(&nc_key, free); /* XXX */ mutex_unlock(&nc_lock); if (error) return (&nc_error); } nc_addr = (int *)thr_getspecific(nc_key); if (nc_addr == NULL) { nc_addr = (int *)mem_zalloc(sizeof(int)); if (thr_setspecific(nc_key, (void *)nc_addr) != 0) { if (nc_addr) mem_free(nc_addr, 0); /* XXX */ return (&nc_error); } *nc_addr = 0; } return (nc_addr); } #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(void) { struct netconfig_vars *nc_vars; nc_vars = (struct netconfig_vars *) mem_zalloc(sizeof(struct netconfig_vars)); if (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. */ mutex_lock(&nc_mtx); ni.ref++; if (!nc_file) nc_file = fopen(NETCONFIG, "r"); if (nc_file) { nc_vars->valid = NC_VALID; nc_vars->flag = 0; nc_vars->nc_configs = ni.head; mutex_unlock(&nc_mtx); return ((void *)nc_vars); } ni.ref--; mutex_unlock(&nc_mtx); nc_error = NC_NONETCONFIG; mem_free(nc_vars, 0); /* XXX */ 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(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); } mutex_lock(&nc_mtx); 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 */ mutex_unlock(&nc_mtx); return (ncp->nc_configs->ncp); } } else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) { ncp->nc_configs = ncp->nc_configs->next; mutex_unlock(&nc_mtx); 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) { mutex_unlock(&nc_mtx); return (NULL); } break; default: nc_error = NC_NOTINIT; mutex_unlock(&nc_mtx); return (NULL); } stringp = (char *)mem_zalloc(MAXNETCONFIGLINE); if (stringp == NULL) { mutex_unlock(&nc_mtx); 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) { mem_free(stringp, 0); ni.eof = 1; mutex_unlock(&nc_mtx); return (NULL); } } while (*stringp == '#'); list = (struct netconfig_list *)mem_zalloc(sizeof(struct netconfig_list)); if (list == NULL) { mem_free(stringp, 0); mutex_unlock(&nc_mtx); return (NULL); } np = (struct netconfig *)mem_zalloc(sizeof(struct netconfig)); if (np == NULL) { mem_free(stringp, 0); mem_free(list, 0); mutex_unlock(&nc_mtx); return (NULL); } list->ncp = np; list->next = NULL; list->ncp->nc_lookups = NULL; list->linep = stringp; if (parse_ncp(stringp, list->ncp) == -1) { mem_free(stringp, 0); mem_free(np, 0); mem_free(list, 0); mutex_unlock(&nc_mtx); 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; mutex_unlock(&nc_mtx); return (ni.tail->ncp); } mutex_unlock(&nc_mtx); } /* * 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(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. */ mutex_lock(&nc_mtx); nc_handlep->valid = NC_INVALID; nc_handlep->flag = 0; nc_handlep->nc_configs = NULL; if (--ni.ref > 0) { mutex_unlock(&nc_mtx); mem_free(nc_handlep, 0); 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) mem_free(q->ncp->nc_lookups, 0); mem_free(q->ncp, 0); mem_free(q->linep, 0); mem_free(q, 0); q = p; } fclose(nc_file); nc_file = NULL; mutex_unlock(&nc_mtx); mem_free(nc_handlep, 0); 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(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 */ nc_error = NC_NOTFOUND; /* default error. */ if (netid == NULL || strlen(netid) == 0) return (NULL); if (strcmp(netid, "unix") == 0) { fprintf(stderr, "The local transport is called \"unix\" "); fprintf(stderr, "in /etc/netconfig.\n"); fprintf(stderr, "Please change this to \"local\" manually "); fprintf(stderr, "or run mergemaster(8).\n"); fprintf(stderr, "See UPDATING entry 20021216 for details.\n"); fprintf(stderr, "Continuing in 10 seconds\n\n"); fprintf(stderr, "This warning will be removed 20030301\n"); sleep(10); } /* * 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. */ mutex_lock(&nc_mtx); if (ni.head != NULL) { for (list = ni.head; list; list = list->next) { if (strcmp(list->ncp->nc_netid, netid) == 0) { mutex_unlock(&nc_mtx); return (dup_ncp(list->ncp)); } } if (ni.eof == 1) { /* that's all the entries */ mutex_unlock(&nc_mtx); return (NULL); } } file = fopen(NETCONFIG, "r"); if (!file) { nc_error = NC_NONETCONFIG; mutex_unlock(&nc_mtx); return (NULL); } linep = mem_zalloc(MAXNETCONFIGLINE); if (!linep) { fclose(file); nc_error = NC_NOMEM; mutex_unlock(&nc_mtx); return (NULL); } do { ptrdiff_t len; char *tmpp; /* tmp string pointer */ do { stringp = fgets(linep, MAXNETCONFIGLINE, file); if (!stringp) break; } while (*stringp == '#'); if (!stringp) /* eof */ break; tmpp = strpbrk(stringp, "\t "); if (!tmpp) { /* can't parse file */ nc_error = NC_BADFILE; break; } len = tmpp - stringp; if (strlen(netid) == (size_t) len && /* a match */ strncmp(stringp, netid, (size_t) len) == 0) { ncp = (struct netconfig *) mem_zalloc(sizeof(struct netconfig)); if (ncp == NULL) break; ncp->nc_lookups = NULL; if (parse_ncp(linep, ncp) == -1) { mem_free(ncp, 0); ncp = NULL; } break; } } while (stringp != NULL); if (!ncp) mem_free(linep, 0); fclose(file); mutex_unlock(&nc_mtx); return (ncp); } /* * freenetconfigent(netconfigp) frees the netconfig structure pointed to by * netconfigp (previously returned by getnetconfigent()). */ void freenetconfigent(struct netconfig *netconfigp) { if (netconfigp != NULL) { mem_free(netconfigp->nc_netid, 0); /* holds all netconfigp's strings */ if (netconfigp->nc_lookups != NULL) mem_free(netconfigp->nc_lookups, 0); mem_free(netconfigp, 0); } return; } /* * 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(char *stringp, /* string to parse */ struct netconfig *ncp /* where to put results */) { char *tokenp; /* for processing tokens */ char *lasts; /* nearly anything that breaks is for this reason */ nc_error = NC_BADFILE; stringp[strlen(stringp) - 1] = '\0'; /* get rid of newline */ /* netid */ ncp->nc_netid = strtok_r(stringp, "\t ", &lasts); if (!ncp->nc_netid) return (-1); /* semantics */ tokenp = strtok_r(NULL, "\t ", &lasts); if (!tokenp) 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 */ tokenp = strtok_r(NULL, "\t ", &lasts); if (!tokenp) 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 */ ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts); if (!ncp->nc_protofmly) return (-1); /* protocol name */ ncp->nc_proto = strtok_r(NULL, "\t ", &lasts); if (!ncp->nc_proto) return (-1); /* network device */ ncp->nc_device = strtok_r(NULL, "\t ", &lasts); if (!ncp->nc_device) return (-1); tokenp = strtok_r(NULL, "\t ", &lasts); if (!tokenp) 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 */ mem_free(ncp->nc_lookups, 0); /* XXX */ /* preallocate one string pointer */ ncp->nc_lookups = (char **)mem_zalloc(sizeof(char *)); ncp->nc_nlookups = 0; while ((cp = tokenp) != NULL) { tokenp = _get_next_token(cp, ','); ncp->nc_lookups[(size_t) ncp->nc_nlookups++] = cp; /* XXXX ok, this works, but should be fixed */ 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(void) { 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; case NC_NOTFOUND: message = _nc_errors[4]; break; default: message = "Unknown network selection error"; } /* LINTED const castaway */ return ((char *)message); } /* * Prints a message onto standard error describing the reason for failure. */ void nc_perror(const char *s) { fprintf(stderr, "%s: %s\n", s, nc_sperror()); } /* * Duplicates the matched netconfig buffer. */ static struct netconfig * dup_ncp(struct netconfig *ncp) { struct netconfig *p; char *tmp; u_int i; tmp = mem_zalloc(MAXNETCONFIGLINE); if (!tmp) return (NULL); p = (struct netconfig *)mem_zalloc(sizeof(struct netconfig)); if (!p) { mem_free(tmp, 0); 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 = (char **)mem_zalloc((size_t) (p->nc_nlookups + 1) * sizeof(char *)); if (p->nc_lookups == NULL) { mem_free(p->nc_netid, 0); return (NULL); } for (i = 0; i < p->nc_nlookups; i++) { tmp = strchr(tmp, 0) + 1; p->nc_lookups[i] = (char *)strcpy(tmp, ncp->nc_lookups[i]); } return (p); } ntirpc-1.3.1/src/getnetpath.c000066400000000000000000000210101261345040100160770ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * Copyright (c) 1989 by Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include /* * 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 alloc. this session */ }; #define NP_VALID 0xf00d #define NP_INVALID 0 char *_get_next_token(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(void) { struct netpath_vars *np_sessionp; /* this session's variables */ char *npp; /* NETPATH env variable */ #ifdef MEM_CHK malloc_debug(1); #endif np_sessionp = (struct netpath_vars *) mem_zalloc(sizeof(struct netpath_vars)); if (!np_sessionp) return (NULL); np_sessionp->nc_handlep = setnetconfig(); if (!np_sessionp->nc_handlep) { mem_free(np_sessionp, sizeof(struct netpath_vars)); syslog(LOG_ERR, "rpc: failed to open " NETCONFIG); return (NULL); } np_sessionp->valid = NP_VALID; np_sessionp->ncp_list = NULL; npp = getenv(NETPATH); if (!npp) np_sessionp->netpath = NULL; else { (void)endnetconfig(np_sessionp->nc_handlep); /* won't need nc session */ np_sessionp->nc_handlep = NULL; np_sessionp->netpath = mem_zalloc(strlen(npp) + 1); if (!np_sessionp->netpath) { mem_free(np_sessionp, 0); /* XXX */ 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(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); } ncp = getnetconfig(np_sessionp->nc_handlep); if (!ncp) 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. */ ncp = getnetconfigent(npp); if (ncp) { /* cobble alloc chain entry */ chainp = (struct netpath_chain *) mem_zalloc(sizeof(struct netpath_chain)); chainp->ncp = ncp; chainp->nchain_next = NULL; if (!np_sessionp->ncp_list) 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(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) mem_free(np_sessionp->netpath_start, 0); for (chainp = np_sessionp->ncp_list; chainp != NULL; lastp = chainp, chainp = chainp->nchain_next, mem_free(lastp, 0)) { freenetconfigent(chainp->ncp); } mem_free(np_sessionp, 0); #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 */ cp = strchr(npp, token); if (!cp) 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 */ int n = strlen(cp); memmove(&cp[-1], cp, n); /* XXX: was overlapping * strcpy */ /* * 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 */ } ntirpc-1.3.1/src/getpeereid.c000066400000000000000000000036211261345040100160610ustar00rootroot00000000000000/*------------------------------------------------------------------------- * * getpeereid.c * get peer userid for UNIX-domain socket connection * * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group * * * IDENTIFICATION * src/port/getpeereid.c * *------------------------------------------------------------------------- */ #include #include #include #include #include #include #ifdef HAVE_SYS_UN_H #include #endif #ifdef HAVE_UCRED_H #include #endif #ifdef HAVE_SYS_UCRED_H #include #endif #if !HAVE_GETPEEREID /* * BSD-style getpeereid() for platforms that lack it. */ int getpeereid(int sock, uid_t *uid, gid_t *gid) { #if defined(SO_PEERCRED) /* Linux: use getsockopt(SO_PEERCRED) */ struct ucred peercred; socklen_t so_len = sizeof(peercred); if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 || so_len != sizeof(peercred)) return -1; *uid = peercred.uid; *gid = peercred.gid; return 0; #elif defined(LOCAL_PEERCRED) /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */ struct xucred peercred; ACCEPT_TYPE_ARG3 so_len = sizeof(peercred); if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 || so_len != sizeof(peercred) || peercred.cr_version != XUCRED_VERSION) return -1; *uid = peercred.cr_uid; *gid = peercred.cr_gid; return 0; #elif defined(HAVE_GETPEERUCRED) /* Solaris: use getpeerucred() */ ucred_t *ucred; ucred = NULL; /* must be initialized to NULL */ if (getpeerucred(sock, &ucred) == -1) return -1; *uid = ucred_geteuid(ucred); *gid = ucred_getegid(ucred); ucred_free(ucred); if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1)) return -1; return 0; #else /* No implementation available on this platform */ errno = ENOSYS; return -1; #endif } #endif /* HAVE_PEEREID */ ntirpc-1.3.1/src/getpublickey.c000066400000000000000000000101761261345040100164360ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* #include */ /* * publickey.c * Copyright (C) 1986, Sun Microsystems, Inc. */ /* * Public key lookup routines */ #include #include #include #include #include #include #include #include #define PKFILE "/etc/publickey" /* * Hack to let ypserv/rpc.nisd use AUTH_DES. */ int (*__getpublickey_LOCAL) () = 0; /* * Get somebody's public key */ int __getpublickey_real(char *netname, char *publickey) { char lookup[3 * HEXKEYBYTES]; char *p; if (publickey == NULL) return (0); if (!getpublicandprivatekey(netname, lookup)) return (0); p = strchr(lookup, ':'); if (!p) return (0); *p = '\0'; (void)strncpy(publickey, lookup, HEXKEYBYTES); publickey[HEXKEYBYTES] = '\0'; return (1); } /* * reads the file /etc/publickey looking for a + to optionally go to the * yellow pages */ int getpublicandprivatekey(char *key, char *ret) { char buf[1024]; /* big enough */ char *res; FILE *fd; char *mkey; char *mval; fd = fopen(PKFILE, "r"); if (fd == NULL) return (0); for (;;) { res = fgets(buf, sizeof(buf), fd); if (res == NULL) { fclose(fd); return (0); } if (res[0] == '#') continue; else if (res[0] == '+') { #ifdef YP char *PKMAP = "publickey.byname"; char *lookup; char *domain; int err; int len; err = yp_get_default_domain(&domain); if (err) continue; lookup = NULL; err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len); if (err) { #ifdef DEBUG fprintf(stderr, "match failed error %d\n", err); #endif continue; } lookup[len] = 0; strcpy(ret, lookup); fclose(fd); free(lookup); /* yp allocated with malloc */ return (2); #else /* YP */ #ifdef DEBUG fprintf(stderr, "Bad record in %s '+' -- NIS not supported in " "this library copy\n", PKFILE); #endif /* DEBUG */ continue; #endif /* YP */ } else { mkey = strsep(&res, "\t "); if (mkey == NULL) { fprintf(stderr, "Bad record in %s -- %s", PKFILE, buf); continue; } do { mval = strsep(&res, " \t#\n"); } while (mval != NULL && !*mval); if (mval == NULL) { fprintf(stderr, "Bad record in %s val problem - %s", PKFILE, buf); continue; } if (strcmp(mkey, key) == 0) { strcpy(ret, mval); fclose(fd); return (1); } } } } int getpublickey(const char *netname, char *publickey) { if (__getpublickey_LOCAL != NULL) return (__getpublickey_LOCAL(netname, publickey)); else return (__getpublickey_real(netname, publickey)); } ntirpc-1.3.1/src/getrpcent.c000066400000000000000000000146761261345040100157530ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1984 by Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef YP #include #include #endif #if defined(__FreeBSD__) || defined(__NetBSD__) #include #endif /* * Internet version. */ static struct rpcdata { FILE *rpcf; int stayopen; #define MAXALIASES 35 char *rpc_aliases[MAXALIASES]; struct rpcent rpc; char line[BUFSIZ + 1]; #ifdef YP char *domain; char *current; int currentlen; #endif } *rpcdata; static struct rpcent *interpret(char *val, size_t len); #ifdef YP static int __yp_nomap; #endif /* YP */ #define RPCDB "/etc/rpc" static struct rpcdata *_rpcdata(void); static struct rpcdata * _rpcdata(void) { struct rpcdata *d = rpcdata; if (d == 0) { d = (struct rpcdata *)mem_alloc(sizeof(struct rpcdata)); rpcdata = d; } return (d); } #ifdef GQ struct rpcent * getrpcbynumber(int number) { #ifdef YP int reason; char adrstr[16]; #endif struct rpcent *p; struct rpcdata *d = _rpcdata(); if (d == 0) return (0); #ifdef YP if (!__yp_nomap && _yp_check(&d->domain)) { sprintf(adrstr, "%d", number); reason = yp_match(d->domain, "rpc.bynumber", adrstr, strlen(adrstr), &d->current, &d->currentlen); switch (reason) { case 0: break; case YPERR_MAP: __yp_nomap = 1; goto no_yp; break; default: return (0); break; } d->current[d->currentlen] = '\0'; p = interpret(d->current, d->currentlen); __free(d->current); return p; } no_yp: #endif /* YP */ setrpcent(0); while ((p = getrpcent()) != NULL) { if (p->r_number == number) break; } endrpcent(); return (p); } struct rpcent * getrpcbyname(char *name) { struct rpcent *rpc = NULL; char **rp; assert(name != NULL); setrpcent(0); while ((rpc = getrpcent()) != NULL) { if (strcmp(rpc->r_name, name) == 0) goto done; for (rp = rpc->r_aliases; *rp != NULL; rp++) { if (strcmp(*rp, name) == 0) goto done; } } done: endrpcent(); return (rpc); } #endif /* GQ */ void setrpcent(int f) { struct rpcdata *d = _rpcdata(); if (d == 0) return; #ifdef YP if (!__yp_nomap && _yp_check(NULL)) { if (d->current) __free(d->current); d->current = NULL; d->currentlen = 0; return; } __yp_nomap = 0; #endif /* YP */ if (d->rpcf == NULL) d->rpcf = fopen(RPCDB, "r"); else rewind(d->rpcf); d->stayopen |= f; } void endrpcent(void) { struct rpcdata *d = _rpcdata(); if (d == 0) return; #ifdef YP if (!__yp_nomap && _yp_check(NULL)) { if (d->current && !d->stayopen) __free(d->current); d->current = NULL; d->currentlen = 0; return; } __yp_nomap = 0; #endif /* YP */ if (d->rpcf && !d->stayopen) { fclose(d->rpcf); d->rpcf = NULL; } } struct rpcent * getrpcent(void) { struct rpcdata *d = _rpcdata(); #ifdef YP struct rpcent *hp; int reason; char *val = NULL; int vallen; #endif if (d == 0) return (NULL); #ifdef YP if (!__yp_nomap && _yp_check(&d->domain)) { if (d->current == NULL && d->currentlen == 0) { reason = yp_first(d->domain, "rpc.bynumber", &d->current, &d->currentlen, &val, &vallen); } else { reason = yp_next(d->domain, "rpc.bynumber", d->current, d->currentlen, &d->current, &d->currentlen, &val, &vallen); } switch (reason) { case 0: break; case YPERR_MAP: __yp_nomap = 1; goto no_yp; break; default: return (0); break; } val[vallen] = '\0'; hp = interpret(val, vallen); free(val); /* yp allocated with malloc */ return hp; } no_yp: #endif /* YP */ if (!d->rpcf) { d->rpcf = fopen(RPCDB, "r"); if (!d->rpcf) return (NULL); } /* -1 so there is room to append a \n below */ if (fgets(d->line, BUFSIZ - 1, 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; assert(val != NULL); if (d == 0) return (0); (void)strncpy(d->line, val, BUFSIZ); d->line[BUFSIZ] = '\0'; p = d->line; p[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); } ntirpc-1.3.1/src/getrpcport.c000066400000000000000000000045001261345040100161320ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1985 by Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include int getrpcport(char *host, int prognum, int versnum, int proto) { struct sockaddr_in addr; struct hostent *hp; assert(host != NULL); hp = gethostbyname(host); if (!hp) return (0); memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; addr.sin_port = 0; if (hp->h_length > sizeof(addr)) hp->h_length = sizeof(addr); 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)); } ntirpc-1.3.1/src/key_call.c000066400000000000000000000266621261345040100155410ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ #include /* * key_call.c, Interface to keyserver * * setsecretkey(key) - set your secret key * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent * decryptsessionkey(agent, deskey) - decrypt ditto * gendeskey(deskey) - generate a secure des key */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define KEY_TIMEOUT 5 /* per-try timeout in seconds */ #define KEY_NRETRY 12 /* number of retries */ #ifdef DEBUG #define debug(msg) \ ((void) fprintf(stderr, "%s\n", msg)) #else #define debug(msg) #endif /* DEBUG */ /* * Hack to allow the keyserver to use AUTH_DES (for authenticated * NIS+ calls, for example). The only functions that get called * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. * * The approach is to have the keyserver fill in pointers to local * implementations of these functions, and to call those in key_call(). */ cryptkeyres *(*__key_encryptsession_pk_LOCAL) () = 0; cryptkeyres *(*__key_decryptsession_pk_LOCAL) () = 0; des_block *(*__key_gendes_LOCAL) () = 0; static int key_call(u_long, xdrproc_t, void *, xdrproc_t, void *); int key_setsecret(const char *secretkey) { keystatus status; if (!key_call ((u_long) KEY_SET, (xdrproc_t) xdr_keybuf, (void *)secretkey, (xdrproc_t) xdr_keystatus, &status)) { return (-1); } if (status != KEY_SUCCESS) { debug("set status is nonzero"); return (-1); } return (0); } /* key_secretkey_is_set() returns 1 if the keyserver has a secret key * stored for the caller's effective uid; it returns 0 otherwise * * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't * be using it, because it allows them to get the user's secret key. */ int key_secretkey_is_set(void) { struct key_netstres kres; memset((void *)&kres, 0, sizeof(kres)); if (key_call ((u_long) KEY_NET_GET, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_key_netstres, &kres) && (kres.status == KEY_SUCCESS) && (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { /* avoid leaving secret key in memory */ memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); return (1); } return (0); } int key_encryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) { cryptkeyarg2 arg; cryptkeyres res; arg.remotename = remotename; arg.remotekey = *remotekey; arg.deskey = *deskey; if (!key_call ((u_long) KEY_ENCRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, &arg, (xdrproc_t) xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { debug("encrypt status is nonzero"); return (-1); } *deskey = res.cryptkeyres_u.deskey; return (0); } int key_decryptsession_pk(char *remotename, netobj *remotekey, des_block *deskey) { cryptkeyarg2 arg; cryptkeyres res; arg.remotename = remotename; arg.remotekey = *remotekey; arg.deskey = *deskey; if (!key_call ((u_long) KEY_DECRYPT_PK, (xdrproc_t) xdr_cryptkeyarg2, &arg, (xdrproc_t) xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { debug("decrypt status is nonzero"); return (-1); } *deskey = res.cryptkeyres_u.deskey; return (0); } int key_encryptsession(const char *remotename, des_block *deskey) { cryptkeyarg arg; cryptkeyres res; arg.remotename = (char *)remotename; arg.deskey = *deskey; if (!key_call ((u_long) KEY_ENCRYPT, (xdrproc_t) xdr_cryptkeyarg, &arg, (xdrproc_t) xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { debug("encrypt status is nonzero"); return (-1); } *deskey = res.cryptkeyres_u.deskey; return (0); } int key_decryptsession(const char *remotename, des_block *deskey) { cryptkeyarg arg; cryptkeyres res; arg.remotename = (char *)remotename; arg.deskey = *deskey; if (!key_call ((u_long) KEY_DECRYPT, (xdrproc_t) xdr_cryptkeyarg, &arg, (xdrproc_t) xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { debug("decrypt status is nonzero"); return (-1); } *deskey = res.cryptkeyres_u.deskey; return (0); } int key_gendes(des_block *key) { if (!key_call ((u_long) KEY_GEN, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_des_block, key)) { return (-1); } return (0); } int key_setnet(struct key_netstarg *arg) { keystatus status; if (!key_call ((u_long) KEY_NET_PUT, (xdrproc_t) xdr_key_netstarg, arg, (xdrproc_t) xdr_keystatus, &status)) { return (-1); } if (status != KEY_SUCCESS) { debug("key_setnet status is nonzero"); return (-1); } return (1); } int key_get_conv(char *pkey, des_block *deskey) { cryptkeyres res; if (!key_call ((u_long) KEY_GET_CONV, (xdrproc_t) xdr_keybuf, pkey, (xdrproc_t) xdr_cryptkeyres, &res)) { return (-1); } if (res.status != KEY_SUCCESS) { debug("get_conv status is nonzero"); return (-1); } *deskey = res.cryptkeyres_u.deskey; return (0); } struct key_call_private { CLIENT *client; /* Client handle */ pid_t pid; /* process-id at moment of creation */ uid_t uid; /* user-id at last authorization */ }; static struct key_call_private *key_call_private_mainL; static void key_call_destroy(void *vp) { struct key_call_private *kcp = (struct key_call_private *)vp; if (kcp) { if (kcp->client) clnt_destroy(kcp->client); __free(kcp); } } /* * Keep the handle cached. This call may be made quite often. */ static CLIENT * getkeyserv_handle(int vers) { void *localhandle; struct netconfig *nconf; struct netconfig *tpconf; struct key_call_private *kcp = key_call_private_main; struct timeval wait_time; struct utsname u; int fd; extern thread_key_t key_call_key; extern mutex_t tsd_lock; #define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */ #define TOTAL_TRIES 5 /* Number of tries */ if (key_call_key == -1) { mutex_lock(&tsd_lock); if (key_call_key == -1) thr_keycreate(&key_call_key, key_call_destroy); mutex_unlock(&tsd_lock); } kcp = (struct key_call_private *)thr_getspecific(key_call_key); if (kcp == (struct key_call_private *)NULL) { kcp = (struct key_call_private *)mem_alloc(sizeof(*kcp)); if (kcp == (struct key_call_private *)NULL) return ((CLIENT *) NULL); thr_setspecific(key_call_key, (void *)kcp); kcp->client = NULL; } /* if pid has changed, destroy client and rebuild */ if (kcp->client != NULL && kcp->pid != getpid()) { clnt_destroy(kcp->client); kcp->client = NULL; } if (kcp->client != NULL) { /* if uid has changed, build client handle again */ if (kcp->uid != geteuid()) { kcp->uid = geteuid(); auth_destroy(kcp->client->cl_auth); kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL); if (kcp->client->cl_auth == NULL) { clnt_destroy(kcp->client); kcp->client = NULL; return ((CLIENT *) NULL); } } /* Change the version number to the new one */ clnt_control(kcp->client, CLSET_VERS, (void *)&vers); return (kcp->client); } localhandle = setnetconfig(); if (!localhandle) return ((CLIENT *) NULL); tpconf = NULL; #if defined(__FreeBSD__) if (uname(&u) == -1) #else #if defined(i386) if (uname(&u) == -1) #elif defined(sparc) if (uname(&u) == -1) #else #error Unknown architecture! #endif #endif { endnetconfig(localhandle); return ((CLIENT *) NULL); } while ((nconf = getnetconfig(localhandle)) != NULL) { if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { /* * We use COTS_ORD here so that the caller can * find out immediately if the server is dead. */ if (nconf->nc_semantics == NC_TPI_COTS_ORD) { kcp->client = clnt_tp_create(u.nodename, KEY_PROG, vers, nconf); if (kcp->client) break; } else { tpconf = nconf; } } } if ((kcp->client == (CLIENT *) NULL) && (tpconf)) /* Now, try the CLTS or COTS loopback transport */ kcp->client = clnt_tp_create(u.nodename, KEY_PROG, vers, tpconf); endnetconfig(localhandle); if (kcp->client == (CLIENT *) NULL) return ((CLIENT *) NULL); kcp->uid = geteuid(); kcp->pid = getpid(); kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL); if (kcp->client->cl_auth == NULL) { clnt_destroy(kcp->client); kcp->client = NULL; return ((CLIENT *) NULL); } wait_time.tv_sec = TOTAL_TIMEOUT / TOTAL_TRIES; wait_time.tv_usec = 0; (void)clnt_control(kcp->client, CLSET_RETRY_TIMEOUT, (char *)&wait_time); if (clnt_control(kcp->client, CLGET_FD, (char *)&fd)) fcntl(fd, F_SETFD, 1); /* make it "close on exec" */ return (kcp->client); } /* returns 0 on failure, 1 on success */ static int key_call(u_long proc, xdrproc_t xdr_arg, void *arg, xdrproc_t xdr_rslt, void *rslt) { CLIENT *clnt; struct timeval wait_time; if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { cryptkeyres *res; res = (*__key_encryptsession_pk_LOCAL) (geteuid(), arg); *(cryptkeyres *) rslt = *res; return (1); } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { cryptkeyres *res; res = (*__key_decryptsession_pk_LOCAL) (geteuid(), arg); *(cryptkeyres *) rslt = *res; return (1); } else if (proc == KEY_GEN && __key_gendes_LOCAL) { des_block *res; res = (*__key_gendes_LOCAL) (geteuid(), 0); *(des_block *) rslt = *res; return (1); } if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || (proc == KEY_GET_CONV)) clnt = getkeyserv_handle(2); /* talk to version 2 */ else clnt = getkeyserv_handle(1); /* talk to version 1 */ if (clnt == NULL) return (0); wait_time.tv_sec = TOTAL_TIMEOUT; wait_time.tv_usec = 0; if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, wait_time) == RPC_SUCCESS) return (1); else return (0); } ntirpc-1.3.1/src/key_prot_xdr.c000066400000000000000000000101051261345040100164500ustar00rootroot00000000000000/* * Please do not edit this file. * It was generated using rpcgen. */ #include /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */ #include /* * Compiled from key_prot.x using rpcgen. * DO NOT EDIT THIS FILE! * This is NOT source code! */ bool xdr_keystatus(XDR *xdrs, keystatus *objp) { if (!xdr_enum(xdrs, (enum_t *) objp)) return (false); return (true); } bool xdr_keybuf(XDR *xdrs, keybuf objp) { if (!xdr_opaque(xdrs, objp, HEXKEYBYTES)) return (false); return (true); } bool xdr_netnamestr(XDR *xdrs, netnamestr *objp) { if (!xdr_string(xdrs, objp, MAXNETNAMELEN)) return (false); return (true); } bool xdr_cryptkeyarg(XDR *xdrs, cryptkeyarg *objp) { if (!xdr_netnamestr(xdrs, &objp->remotename)) return (false); if (!xdr_des_block(xdrs, &objp->deskey)) return (false); return (true); } bool xdr_cryptkeyarg2(XDR *xdrs, cryptkeyarg2 *objp) { if (!xdr_netnamestr(xdrs, &objp->remotename)) return (false); if (!xdr_netobj(xdrs, &objp->remotekey)) return (false); if (!xdr_des_block(xdrs, &objp->deskey)) return (false); return (true); } bool xdr_cryptkeyres(XDR *xdrs, cryptkeyres *objp) { if (!xdr_keystatus(xdrs, &objp->status)) return (false); switch (objp->status) { case KEY_SUCCESS: if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey)) return (false); break; default: break; } return (true); } bool xdr_unixcred(XDR *xdrs, unixcred *objp) { if (!xdr_u_int(xdrs, &objp->uid)) return (false); if (!xdr_u_int(xdrs, &objp->gid)) return (false); if (!xdr_array (xdrs, (char **)&objp->gids.gids_val, (u_int *) &objp->gids.gids_len, MAXGIDS, sizeof(u_int), (xdrproc_t) xdr_u_int)) return (false); return (true); } bool xdr_getcredres(register XDR *xdrs, getcredres *objp) { if (!xdr_keystatus(xdrs, &objp->status)) return (false); switch (objp->status) { case KEY_SUCCESS: if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred)) return (false); break; default: break; } return (true); } bool xdr_key_netstarg(XDR *xdrs, key_netstarg *objp) { if (!xdr_keybuf(xdrs, objp->st_priv_key)) return (false); if (!xdr_keybuf(xdrs, objp->st_pub_key)) return (false); if (!xdr_netnamestr(xdrs, &objp->st_netname)) return (false); return (true); } bool xdr_key_netstres(register XDR *xdrs, key_netstres *objp) { if (!xdr_keystatus(xdrs, &objp->status)) return (false); switch (objp->status) { case KEY_SUCCESS: if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet)) return (false); break; default: break; } return (true); } ntirpc-1.3.1/src/libntirpc.map.in.cmake000066400000000000000000000130401261345040100177450ustar00rootroot00000000000000NTIRPC_${NTIRPC_VERSION} { global: # __* __ntirpc_pkg_params; __rpc_createerr; __rpc_dtbsize; __rpc_endconf; __rpc_fd2sockinfo; __rpc_fixup_addr; __rpc_get_a_size; __rpc_get_local_uid; __rpc_get_t_size; __rpc_getconf; __rpc_getconfip; __rpc_nconf2fd; __rpc_nconf2fd_flags; __rpc_nconf2sockinfo; __rpc_rawcombuf; __rpc_seman2socktype; __rpc_setconf; __rpc_sockinfo2netid; __rpc_sockisbound; __rpc_socktype2seman; __rpc_taddr2uaddr_af; __rpc_uaddr2taddr_af; __rpcgettp; # _* _authenticate; _get_next_token; _gss_authenticate; _svcauth_gss; _null_auth; _rpc_dtablesize; _seterr_reply; _svcauth_none; _svcauth_short; _svcauth_unix; # a* authgss_ncreate; authgss_ncreate_default; authgss_get_private_data; authgss_service; authnone_ncreate; authunix_ncreate; authunix_ncreate_default; # b* bindresvport; bindresvport_sa; # c* callrpc; cbc_crypt; clnt_broadcast; clnt_ncreate; clnt_ncreate_timed; clnt_ncreate_vers; clnt_ncreate_vers_timed; clnt_dg_ncreate; clnt_pcreateerror; clnt_perrno; clnt_perror; clnt_raw_ncreate; clnt_spcreateerror; clnt_sperrno; clnt_sperror; clnt_tli_create; clnt_tp_ncreate; clnt_tp_ncreate_timed; clnt_vc_ncreate; clnt_vc_ncreate2; clnt_vc_ncreate_svc; clntraw_ncreate; clnttcp_ncreate; clntudp_nbufcreate; clntudp_ncreate; clntunix_ncreate; # e* endnetconfig; endnetpath; endrpcent; # f* freenetconfigent; free_rpc_msg; # g* get_myaddress; getnetconfig; getnetconfigent; getnetpath; getrpcent; getrpcbynumber; getrpcbyname; getrpcport; # n* nc_perror; nc_sperror; # o* opr_rbtree_first; opr_rbtree_init; opr_rbtree_insert; opr_rbtree_insert_at; opr_rbtree_last; opr_rbtree_lookup; opr_rbtree_next; opr_rbtree_prev; opr_rbtree_remove; opr_rbtree_replace; # p* pmap_getmaps; pmap_getport; pmap_rmtcall; pmap_set; pmap_unset; # r* rbtx_init; registerrpc; rpc_broadcast; rpc_broadcast_exp; rpc_call; rpc_control; rpc_createerr; rpc_nullproc; rpc_rdma_create; rpc_reg; rpcb_find_mapped_addr; rpcb_getaddr; rpcb_getmaps; rpcb_gettime; rpcb_rmtcall; rpcb_set; rpcb_taddr2uaddr; rpcb_uaddr2taddr; rpcb_unset; # s* setnetconfig; setnetpath; setrpcent; svc_auth_authenticate; svc_auth_reg; svc_dg_ncreate; svc_exit; svc_fd_ncreate; svc_fd_ncreate2; svc_init; svc_ncreate; svc_raw_ncreate; svc_rdma_ncreate; svc_reg; svc_register; svc_rqst_new_evchan; svc_rqst_evchan_reg; svc_rqst_evchan_unreg; svc_rqst_rearm_events; svc_rqst_thrd_run; svc_rqst_thrd_signal; svc_run; svc_run_epoll; svc_sendreply; svc_shutdown; svc_tli_ncreate; svc_tp_ncreate; svc_unreg; svc_unregister; svc_validate_xprt_list; svc_vc_ncreate; svc_vc_ncreate2; svc_xprt_trace; svcauth_gss_acquire_cred; svcauth_gss_destroy; svcauth_gss_get_principal; svcauth_gss_import_name; svcauth_gss_nextverf; svcauth_gss_release_cred; svcauth_gss_set_svc_name; svcerr_auth; svcerr_decode; svcerr_noproc; svcerr_noprog; svcerr_progvers; svcerr_systemerr; svcerr_weakauth; svcfd_ncreate; svcraw_ncreate; svctcp_ncreate; svcudp_nbufcreate; svcudp_ncreate; svcunix_ncreate; svcunixfd_ncreate; # t* taddr2uaddr; tirpc_control; # u* uaddr2taddr; # x* xdr_array; xdr_authunix_parms; xdr_bool; xdr_bytes; xdr_call_decode; xdr_call_encode; xdr_char; xdr_double; xdr_dplx_decode; xdr_dplx_msg; xdr_enum; xdr_float; xdr_hyper; xdr_inrec_cksum; xdr_inrec_create; xdr_inrec_eof; xdr_inrec_readahead; xdr_inrec_skiprecord; xdr_int; xdr_int8_t; xdr_int16_t; xdr_int32_t; xdr_int64_t; xdr_long; xdr_longlong_t; xdr_naccepted_reply; xdr_ncallhdr; xdr_ncallmsg; xdr_netbuf; xdr_nnetobj; xdr_nrejected_reply; xdr_nreplymsg; xdr_opaque; xdr_opaque_auth; xdr_pmap; xdr_pmaplist; xdr_pmaplist_ptr; xdr_pointer; xdr_quad_t; xdr_reference; xdr_rmtcall_args; xdr_rmtcallres; xdr_rpc_gss_buf; xdr_rpc_gss_cred; xdr_rpc_gss_data; xdr_rpc_gss_init_args; xdr_rpc_gss_init_res; xdr_rpc_gss_unwrap_data; xdr_rpc_gss_wrap_data; xdr_rpcb; xdr_rpcb_entry; xdr_rpcb_entry_list_ptr; xdr_rpcb_rmtcallargs; xdr_rpcb_rmtcallres; xdr_rpcb_stat; xdr_rpcb_stat_byvers; xdr_rpcblist; xdr_rpcblist_ptr; xdr_rpcbs_addrlist; xdr_rpcbs_addrlist_ptr; xdr_rpcbs_proc; xdr_rpcbs_rmtcalllist; xdr_rpcbs_rmtcalllist_ptr; xdr_short; xdr_string; xdr_u_char; xdr_u_hyper; xdr_u_int8_t; xdr_u_int16_t; xdr_u_int32_t; xdr_u_int64_t; xdr_u_int; xdr_u_long; xdr_u_longlong_t; xdr_u_quad_t; xdr_u_short; xdr_uint8_t; xdr_uint16_t; xdr_uint32_t; xdr_uint64_t; xdr_union; xdr_vector; xdr_void; xdr_wrapstring; xdrmem_ncreate; xdrrec_create; xdrrec_endofrecord; xdrrec_eof; xdrrec_skiprecord; xdrstdio_create; xprt_register; xprt_unregister; local: *; }; NTIRPC_PRIVATE { global: global_foo_bar; }; ntirpc-1.3.1/src/mt_misc.c000066400000000000000000000067701261345040100154070ustar00rootroot00000000000000 #include #include #include #include #include #include #include #include #include "rpc_com.h" /* protects the services list (svc.c) */ pthread_rwlock_t svc_lock = RWLOCK_INITIALIZER; /* protects the RPCBIND address cache */ pthread_rwlock_t rpcbaddr_cache_lock = RWLOCK_INITIALIZER; /* protects authdes cache (svcauth_des.c) */ pthread_mutex_t authdes_lock = MUTEX_INITIALIZER; /* serializes authdes ops initializations */ pthread_mutex_t authdes_ops_lock = MUTEX_INITIALIZER; /* protects des stats list */ pthread_mutex_t svcauthdesstats_lock = MUTEX_INITIALIZER; #ifdef KERBEROS /* auth_kerb.c serialization */ pthread_mutex_t authkerb_lock = MUTEX_INITIALIZER; /* protects kerb stats list */ pthread_mutex_t svcauthkerbstats_lock = MUTEX_INITIALIZER; #endif /* KERBEROS */ /* protects the Auths list (svc_auth.c) */ pthread_mutex_t authsvc_lock = MUTEX_INITIALIZER; /* clnt_raw.c serialization */ pthread_mutex_t clntraw_lock = MUTEX_INITIALIZER; /* domainname and domain_fd (getdname.c) and default_domain (rpcdname.c) */ pthread_mutex_t dname_lock = MUTEX_INITIALIZER; /* dupreq variables (svc_dg.c) */ pthread_mutex_t dupreq_lock = MUTEX_INITIALIZER; /* protects first_time and hostname (key_call.c) */ pthread_mutex_t keyserv_lock = MUTEX_INITIALIZER; /* serializes rpc_trace() (rpc_trace.c) */ pthread_mutex_t libnsl_trace_lock = MUTEX_INITIALIZER; /* loopnconf (rpcb_clnt.c) */ pthread_mutex_t loopnconf_lock = MUTEX_INITIALIZER; /* serializes ops initializations */ pthread_mutex_t ops_lock = MUTEX_INITIALIZER; /* protect svc counters */ pthread_mutex_t svc_ctr_lock = MUTEX_INITIALIZER; /* protects ``port'' static in bindresvport() */ pthread_mutex_t portnum_lock = MUTEX_INITIALIZER; /* protects proglst list (svc_simple.c) */ pthread_mutex_t proglst_lock = MUTEX_INITIALIZER; /* serializes clnt_com_create() (rpc_soc.c) */ pthread_mutex_t rpcsoc_lock = MUTEX_INITIALIZER; /* svc_raw.c serialization */ pthread_mutex_t svcraw_lock = MUTEX_INITIALIZER; /* protects TSD key creation */ pthread_mutex_t tsd_lock = MUTEX_INITIALIZER; /* Library global tsd keys */ thread_key_t clnt_broadcast_key; thread_key_t rpc_call_key = -1; thread_key_t tcp_key = -1; thread_key_t udp_key = -1; thread_key_t nc_key = -1; thread_key_t rce_key = -1; /* xprtlist (svc_generic.c) */ pthread_mutex_t xprtlist_lock = MUTEX_INITIALIZER; /* serializes calls to public key routines */ pthread_mutex_t serialize_pkey = MUTEX_INITIALIZER; #undef rpc_createerr struct rpc_createerr rpc_createerr; struct rpc_createerr *__rpc_createerr(void) { struct rpc_createerr *rce_addr; mutex_lock(&tsd_lock); if (rce_key == -1) thr_keycreate(&rce_key, free); /* XXX */ mutex_unlock(&tsd_lock); rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key); if (!rce_addr) { rce_addr = (struct rpc_createerr *) mem_alloc(sizeof(struct rpc_createerr)); if (!rce_addr || thr_setspecific(rce_key, (void *)rce_addr) != 0) { if (rce_addr) mem_free(rce_addr, 0); return (&rpc_createerr); } memset(rce_addr, 0, sizeof(struct rpc_createerr)); } return (rce_addr); } void tsd_key_delete(void) { if (clnt_broadcast_key != -1) pthread_key_delete(clnt_broadcast_key); if (rpc_call_key != -1) pthread_key_delete(rpc_call_key); if (tcp_key != -1) pthread_key_delete(tcp_key); if (udp_key != -1) pthread_key_delete(udp_key); if (nc_key != -1) pthread_key_delete(nc_key); if (rce_key != -1) pthread_key_delete(rce_key); return; } ntirpc-1.3.1/src/netname.c000066400000000000000000000075071261345040100154020ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * netname utility routines * convert from unix names to network names and vice-versa * This module is operating system dependent! * What we define here will work with any unix system that has adopted * the sun NIS domain architecture. */ #include #include #include "rpc_com.h" #ifdef YP #include #include #endif #include #include #include #include #include #include #ifndef MAXHOSTNAMELEN #define MAXHOSTNAMELEN 256 #endif #ifndef NGROUPS #define NGROUPS 16 #endif #define TYPE_BIT(type) (sizeof(type) * CHAR_BIT) #define TYPE_SIGNED(type) (((type)-1) < 0) /* ** 302 / 1000 is log10(2.0) rounded up. ** Subtract one for the sign bit if the type is signed; ** add one for integer division truncation; ** add one more for a minus sign if the type is signed. */ #define INT_STRLEN_MAXIMUM(type) \ ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + \ TYPE_SIGNED(type)) static char *OPSYS = "unix"; /* * Figure out my fully qualified network name */ int getnetname(char name[MAXNETNAMELEN + 1]) { uid_t uid; uid = geteuid(); if (uid == 0) return (host2netname(name, (char *)NULL, (char *)NULL)); else return (user2netname(name, uid, (char *)NULL)); } /* * Convert unix cred to network-name */ int user2netname(char netname[MAXNETNAMELEN + 1], const uid_t uid, const char *domain) { char *dfltdom; if (domain == NULL) if (__rpc_get_default_domain(&dfltdom) != 0) { return (0); domain = dfltdom; } if (strlen(domain) + 1 + INT_STRLEN_MAXIMUM(u_long) + 1 + strlen(OPSYS) > MAXNETNAMELEN) { return (0); } (void)sprintf(netname, "%s.%ld@%s", OPSYS, (u_long) uid, domain); return (1); } /* * Convert host to network-name */ int host2netname(char netname[MAXNETNAMELEN + 1], const char *host, const char *domain) { char *dfltdom; char hostname[MAXHOSTNAMELEN + 1]; if (domain == NULL) { if (__rpc_get_default_domain(&dfltdom) != 0) return (0); domain = dfltdom; } if (host == NULL) { (void)gethostname(hostname, sizeof(hostname)); host = hostname; } if (strlen(domain) + 1 + strlen(host) + 1 + strlen(OPSYS) > MAXNETNAMELEN) { return (0); } (void)sprintf(netname, "%s.%s@%s", OPSYS, host, domain); return (1); } ntirpc-1.3.1/src/netnamer.c000066400000000000000000000160061261345040100155560ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * netname utility routines convert from unix names to network names and * vice-versa This module is operating system dependent! What we define here * will work with any unix system that has adopted the sun NIS domain * architecture. */ #include #include #include "rpc_com.h" #ifdef YP #include #include #endif #include #include #include #include #include #include #include static char *OPSYS = "unix"; static char *NETID = "netid.byname"; static char *NETIDFILE = "/etc/netid"; static int getnetid(char *, char *); static int _getgroups(char *, gid_t *); #ifndef NGROUPS #define NGROUPS 16 #endif /* * Convert network-name into unix credential */ int netname2user(char netname[MAXNETNAMELEN + 1], uid_t *uidp, gid_t *gidp, int *gidlenp, gid_t *gidlist) { char *p; int gidlen; uid_t uid; long luid; struct passwd *pwd; char val[1024]; char *val1, *val2; char *domain; int vallen; int err; if (getnetid(netname, val)) { char *res = val; p = strsep(&res, ":"); if (p == NULL) return (0); *uidp = (uid_t) atol(p); p = strsep(&res, "\n,"); if (p == NULL) return (0); *gidp = (gid_t) atol(p); gidlen = 0; for (gidlen = 0; gidlen < NGROUPS; gidlen++) { p = strsep(&res, "\n,"); if (p == NULL) break; gidlist[gidlen] = (gid_t) atol(p); } *gidlenp = gidlen; return (1); } val1 = strchr(netname, '.'); if (val1 == NULL) return (0); if (strncmp(netname, OPSYS, (val1 - netname))) return (0); val1++; val2 = strchr(val1, '@'); if (val2 == NULL) return (0); vallen = val2 - val1; if (vallen > (1024 - 1)) vallen = 1024 - 1; (void)strncpy(val, val1, 1024); val[vallen] = 0; err = __rpc_get_default_domain(&domain); /* change to rpc */ if (err) return (0); if (strcmp(val2 + 1, domain)) return (0); /* wrong domain */ if (sscanf(val, "%ld", &luid) != 1) return (0); uid = luid; /* use initgroups method */ pwd = getpwuid(uid); if (pwd == NULL) return (0); *uidp = pwd->pw_uid; *gidp = pwd->pw_gid; *gidlenp = _getgroups(pwd->pw_name, gidlist); return (1); } /* * initgroups */ static int _getgroups(char *uname, gid_t groups[NGROUPS]) { gid_t ngroups = 0; struct group *grp; int i; int j; int filter; setgrent(); while ((grp = getgrent())) { for (i = 0; grp->gr_mem[i]; i++) if (!strcmp(grp->gr_mem[i], uname)) { if (ngroups == NGROUPS) { #ifdef DEBUG fprintf(stderr, "initgroups: %s is in too many groups\n", uname); #endif goto toomany; } /* filter out duplicate group entries */ filter = 0; for (j = 0; j < ngroups; j++) if (groups[j] == grp->gr_gid) { filter++; break; } if (!filter) groups[ngroups++] = grp->gr_gid; } } toomany: endgrent(); return (ngroups); } /* * Convert network-name to hostname */ int netname2host(char netname[MAXNETNAMELEN + 1], char *hostname, int hostlen) { int err; char valbuf[1024]; char *val; char *val2; int vallen; char *domain; if (getnetid(netname, valbuf)) { val = valbuf; if ((*val == '0') && (val[1] == ':')) { (void)strncpy(hostname, val + 2, hostlen); return (1); } } val = strchr(netname, '.'); if (val == NULL) return (0); if (strncmp(netname, OPSYS, (val - netname))) return (0); val++; val2 = strchr(val, '@'); if (val2 == NULL) return (0); vallen = val2 - val; if (vallen > (hostlen - 1)) vallen = hostlen - 1; (void)strncpy(hostname, val, vallen); hostname[vallen] = 0; err = __rpc_get_default_domain(&domain); /* change to rpc */ if (err) return (0); if (strcmp(val2 + 1, domain)) return (0); /* wrong domain */ else return (1); } /* * reads the file /etc/netid looking for a + to optionally go to the * network information service. */ int getnetid(char *key, char *ret) { char buf[1024]; /* big enough */ char *res; char *mkey; char *mval; FILE *fd; #ifdef YP char *domain; int err; char *lookup; int len; #endif fd = fopen(NETIDFILE, "r"); if (fd == NULL) { #ifdef YP res = "+"; goto getnetidyp; #else return (0); #endif } for (;;) { if (fd == NULL) return (0); /* getnetidyp brings us here */ res = fgets(buf, sizeof(buf), fd); if (res == NULL) { fclose(fd); return (0);} if (res[0] == '#') continue; else if (res[0] == '+') { #ifdef YP getnetidyp: err = yp_get_default_domain(&domain); if (err) { continue;} lookup = NULL; err = yp_match(domain, NETID, key, strlen(key), &lookup, &len); if (err) { #ifdef DEBUG fprintf(stderr, "match failed error %d\n", err); #endif continue;} lookup[len] = 0; strcpy(ret, lookup); free(lookup); /* yp allocated with malloc */ if (fd != NULL) fclose(fd); return (2); #else /* YP */ #ifdef DEBUG fprintf(stderr, "Bad record in %s '+' -- NIS not supported in this library copy\n", NETIDFILE); #endif continue; #endif /* YP */ } else { mkey = strsep(&res, "\t "); if (mkey == NULL) { fprintf(stderr, "Bad record in %s -- %s", NETIDFILE, buf); continue;} do { mval = strsep(&res, " \t#\n");} while (mval != NULL && !*mval); if (mval == NULL) { fprintf(stderr, "Bad record in %s val problem - %s", NETIDFILE, buf); continue;} if (strcmp(mkey, key) == 0) { strcpy(ret, mval); fclose(fd); return (1);} } } } ntirpc-1.3.1/src/ntmakefile000066400000000000000000000014221261345040100156370ustar00rootroot00000000000000 # Minimal makefile for compilation with mingw64--almost certain to # be replaced with something more flexible LIBNTIRPC = libntirpc.a SOURCES = \ auth_none.c \ portable.c \ rbtree.c \ rbtree_x.c \ rpc_ctx.c \ rpc_dplx_msg.c \ strlcat.c \ strlcpy.c \ svc.c \ svc_run.c \ xdr.c \ xdr_array.c \ xdr_float.c \ xdr_mem.c \ xdr_rec.c \ xdr_reference.c \ xdr_sizeof.c \ xdr_stdio.c OBJECTS = $(SOURCES:%.c=%.o) # Compiler flags CC = x86_64-w64-mingw32-gcc CFLAGS += -g3 -O0 -I../tirpc/ -D_REENTRANT #LDFLAGS += -L$(CUNIT)/lib $(TIRPC)/src/.libs/libntirpc.a \ # -lcunit -lgssapi_krb5 -lkrb5 -lk5crypto -lcom_err -lpthread \ # -lc -lrt -lgssglue # Targets all : $(LIBNTIRPC) $(LIBNTIRPC) : $(OBJECTS) $(OBJECTS) : $(SOURCES) clean: $(RM) $(OBJECTS) $(LIBTIRPC) ntirpc-1.3.1/src/pmap_clnt.c000066400000000000000000000071161261345040100157240ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * pmap_clnt.c * Client interface to pmap rpc service. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" bool pmap_set(u_long program, u_long version, int protocol, int port) { bool 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); if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { snprintf(buf, sizeof(buf), "0.0.0.0.%d.%d", (((u_int32_t) port) >> 8) & 0xff, port & 0xff); } else if (strcmp(nconf->nc_protofmly, NC_INET6) == 0) { snprintf(buf, sizeof(buf), "::.%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); mem_free(na->buf, na->len); mem_free(na, sizeof *na); freenetconfigent(nconf); return (rslt); } /* * Remove the mapping between program, version and port. * Calls the pmap service remotely to do the un-mapping. */ bool pmap_unset(u_long program, u_long version) { struct netconfig *nconf; bool udp_rslt = false; bool 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); } ntirpc-1.3.1/src/pmap_getmaps.c000066400000000000000000000056341261345040100164270ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #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(struct sockaddr_in *address) { struct pmaplist *head = NULL; int sock = -1; struct timeval minutetimeout; CLIENT *client; AUTH *auth; assert(address != NULL); minutetimeout.tv_sec = 60; minutetimeout.tv_usec = 0; address->sin_port = htons(PMAPPORT); client = clnttcp_ncreate(address, PMAPPROG, PMAPVERS, &sock, 50, 500); if (client != NULL) { auth = authnone_create(); /* idempotent */ if (CLNT_CALL (client, auth, (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); } ntirpc-1.3.1/src/pmap_getport.c000066400000000000000000000061221261345040100164440ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * pmap_getport.c * Client interface to pmap rpc service. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include 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. */ u_short pmap_getport(struct sockaddr_in *address, u_long program, u_long version, u_int protocol) { struct pmap parms; u_short port = 0; int sock = -1; CLIENT *client; AUTH *auth; assert(address != NULL); address->sin_port = htons(PMAPPORT); client = clntudp_nbufcreate(address, PMAPPROG, PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); if (client != NULL) { auth = authnone_create(); /* idempotent */ parms.pm_prog = program; parms.pm_vers = version; parms.pm_prot = protocol; parms.pm_port = 0; /* not needed or used */ if (CLNT_CALL (client, auth, (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_DESTROY(client); } address->sin_port = 0; return (port); } ntirpc-1.3.1/src/pmap_prot.c000066400000000000000000000040511261345040100157430ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * pmap_prot.c * Protocol for the local binder service, or pmap. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include bool xdr_pmap(XDR *xdrs, struct pmap *regs) { assert(xdrs != NULL); assert(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); } ntirpc-1.3.1/src/pmap_prot2.c000066400000000000000000000103041261345040100160230ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * pmap_prot2.c * Protocol for the local binder service, or pmap. * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include /* * 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 xdr_pmaplist(XDR *xdrs, struct pmaplist **rp) { /* * more_elements is pre-computed in case the direction is * XDR_ENCODE or XDR_FREE. more_elements is overwritten by * xdr_bool when the direction is XDR_DECODE. */ int freeing; struct pmaplist **next = NULL; /* pacify gcc */ bool_t more_elements = false; /* yes, bool_t */ assert(xdrs != NULL); assert(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 xdr_pmaplist_ptr(XDR *xdrs, struct pmaplist *rp) { return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp); } ntirpc-1.3.1/src/pmap_rmt.c000066400000000000000000000112711261345040100155630ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * pmap_rmt.c * Client interface to pmap rpc service. * remote call and broadcast service * * Copyright (C) 1984, Sun Microsystems, Inc. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* For the clnttcp_create function * #include */ static const struct timeval timeout = { 3, 0 }; /* * pmapper remote-call-service interface. * This routine is used to call the pmapper remote call service * which will look up a service program in the port maps, and then * remotely call that routine with the given parameters. This allows * programs to do a lookup and call in one step. */ enum clnt_stat pmap_rmtcall(struct sockaddr_in *addr, u_long prog, u_long vers, u_long proc, xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, struct timeval tout, u_long *port_ptr) { int sock = -1; CLIENT *client; AUTH *auth; struct rmtcallargs a; struct rmtcallres r; enum clnt_stat stat; assert(addr != NULL); assert(port_ptr != NULL); addr->sin_port = htons(PMAPPORT); client = clntudp_ncreate(addr, PMAPPROG, PMAPVERS, timeout, &sock); if (client != NULL) { auth = authnone_create(); 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, auth, (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 xdr_rmtcall_args(XDR *xdrs, struct rmtcallargs *cap) { u_int lenposition, argposition, position; assert(xdrs != NULL); assert(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 xdr_rmtcallres(XDR *xdrs, struct rmtcallres *crp) { caddr_t port_ptr; assert(xdrs != NULL); assert(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); } ntirpc-1.3.1/src/portable.c000066400000000000000000000054761261345040100155660ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #include #ifdef __APPLE__ int clock_gettime(clockid_t clock, struct timespec *ts) { struct timeval tv; gettimeofday(&tv, NULL); ts->tv_sec = tv.tv_sec; ts->tv_nsec = tv.tv_usec * 1000UL; return 0; } #endif #if defined(_WIN32) pthread_mutex_t clock_mtx = PTHREAD_MUTEX_INITIALIZER; int clock_gettime(clockid_t clock, struct timespec *ts) { static bool initialized; static LARGE_INTEGER start, freq, ctr, m; static double ftom; bool rslt = false; if (!initialized) { mutex_lock(&clock_mtx); if (!initialized) { QueryPerformanceCounter(&start); (void)QueryPerformanceFrequency(&freq); /* XXXX can be 0, would need to fall back */ ftom = (double)freq.QuadPart / 1000000.; } mutex_unlock(&clock_mtx); } rslt = QueryPerformanceCounter(&ctr); switch (rslt) { case 0: ts->tv_sec = 0; ts->tv_nsec = 0; break; default: ctr.QuadPart -= start.QuadPart; m.QuadPart = ctr.QuadPart / ftom; ctr.QuadPart = m.QuadPart % 1000000; ts->tv_sec = m.QuadPart / 1000000; ts->tv_nsec = ctr.QuadPart * 1000; } return (rslt); } /* XXX this mutex actually -is- serializing calls, however, these * calls should be rare */ pthread_mutex_t warn_mtx = PTHREAD_MUTEX_INITIALIZER; void warnx(const char *fmt, ...) { va_list ap; static char msg[128]; va_start(ap, fmt); if (fmt != NULL) _vsnprintf(msg, 128, fmt, ap); else msg[0] = '\0'; va_end(ap); fprintf(stderr, "%s\n", msg); } #endif /* _WIN32 */ ntirpc-1.3.1/src/rbtree.c000066400000000000000000000271661261345040100152410ustar00rootroot00000000000000/* * Copyright (c) 2008 - 2010 Jason Evans * Copyright (c) 2011 Your File System Inc. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /* Left-leaning rbtree implementation. Originally derived from the FreeBSD * CPP macro definitions by Jason Evans, but extensively modified to * *) Be function, rather than macro based * *) Use parent pointers, rather than calling an embeded comparison fn * *) Use 'NULL' to represent empty nodes, rather than a magic pointer */ #include #include #include "misc/rbtree.h" /* Update the parent pointers for a node which is being replaced. * * If the original node had no parent, then it was the root of the tree, * and the replacement is too. * Otherwise, the original node must have been either the left or right * child of its parent, so update the left (or right) pointer to point * to the replacement as appropriate. */ static inline void update_parent_ptr(struct opr_rbtree *head, struct opr_rbtree_node *old, struct opr_rbtree_node *replacement) { if (old->parent) { if (old->parent->left == old) old->parent->left = replacement; else old->parent->right = replacement; } else head->root = replacement; } /* initialize a tree, cmpf may be NULL--if so, do not call internal * iterating functions (opr_rbtree_lookup, opr_rbtree_insert) */ void opr_rbtree_init(struct opr_rbtree *head, opr_rbtree_cmpf_t cmpf) { head->cmpf = cmpf; head->root = NULL; head->size = 0; head->gen = 0; } struct opr_rbtree_node *opr_rbtree_first(struct opr_rbtree *head) { struct opr_rbtree_node *node; node = head->root; if (node == NULL) return node; while (node->left != NULL) node = node->left; return node; } struct opr_rbtree_node *opr_rbtree_last(struct opr_rbtree *head) { struct opr_rbtree_node *node; node = head->root; if (node == NULL) return node; while (node->right != NULL) node = node->right; return node; } struct opr_rbtree_node *opr_rbtree_next(struct opr_rbtree_node *node) { struct opr_rbtree_node *parent; /* Where there is a right child, the next node is to the right, then * left as far as we can go */ if (node->right != NULL) { node = node->right; while (node->left != NULL) node = node->left; return node; } /* If there is no right hand child, then the next node is above us. * Whenever our ancestor is a right-hand child, the next node is * further up. When it is a left-hand child, it is our next node */ while ((parent = node->parent) != NULL && node == parent->right) node = parent; return parent; } struct opr_rbtree_node *opr_rbtree_prev(struct opr_rbtree_node *node) { struct opr_rbtree_node *parent; if (node->left != NULL) { node = node->left; while (node->right != NULL) node = node->right; return node; } /* Same ancestor logic as for 'next', but in reverse */ while ((parent = node->parent) != NULL && node == parent->left) node = parent; return parent; } static inline void rotateright(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node *left = node->left; node->left = left->right; if (left->right) left->right->parent = node; left->right = node; left->parent = node->parent; update_parent_ptr(head, node, left); node->parent = left; } static inline void rotateleft(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node *right = node->right; node->right = right->left; if (right->left) right->left->parent = node; right->left = node; right->parent = node->parent; update_parent_ptr(head, node, right); node->parent = right; } static inline void swapnode(struct opr_rbtree_node **a, struct opr_rbtree_node **b) { struct opr_rbtree_node *tmp; tmp = *a; *a = *b; *b = tmp; } static void insert_recolour(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node *parent, *gramps; while ((parent = node->parent) && parent->red) { gramps = parent->parent; if (parent == gramps->left) { struct opr_rbtree_node *uncle = gramps->right; if (uncle && uncle->red) { uncle->red = 0; parent->red = 0; gramps->red = 1; node = gramps; continue; } if (parent->right == node) { rotateleft(head, parent); swapnode(&parent, &node); } parent->red = 0; gramps->red = 1; rotateright(head, gramps); } else { struct opr_rbtree_node *uncle = gramps->left; if (uncle && uncle->red) { uncle->red = 0; parent->red = 0; gramps->red = 1; node = gramps; continue; } if (parent->left == node) { rotateright(head, parent); swapnode(&parent, &node); } parent->red = 0; gramps->red = 1; rotateleft(head, gramps); } } head->root->red = 0; } void opr_rbtree_insert_at(struct opr_rbtree *head, struct opr_rbtree_node *parent, struct opr_rbtree_node **childptr, struct opr_rbtree_node *node) { /* Link node 'node' into the tree at position 'parent', using either the * left or right pointers */ node->parent = parent; node->left = node->right = NULL; node->red = 1; node->gen = (uint32_t)(++(head->gen)); if (!node->gen) { /* truncated to zero */ node->gen = (uint32_t)(++(head->gen)); } *childptr = node; /* Rebalance the tree for the newly inserted node */ insert_recolour(head, node); } /* Try to insert node on tree head. If an existing node compares * equal to node, return it--the caller will deal. Else, return * NULL. Do NOT call this if your iteration is external */ struct opr_rbtree_node *opr_rbtree_insert(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node **iter, *parent = NULL; iter = &head->root; while (*iter) { parent = *iter; switch (head->cmpf(node, parent)) { case -1: iter = &parent->left; break; case 1: iter = &parent->right; break; default: return (parent); break; } } /* while */ opr_rbtree_insert_at(head, parent, iter, node); (head->size)++; return (NULL); } /* search for node in tree--do NOT call this if your iteration * is external */ struct opr_rbtree_node *opr_rbtree_lookup(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node *iter, *parent = NULL; iter = head->root; while (iter) { parent = iter; switch (head->cmpf(node, parent)) { case -1: iter = parent->left; break; case 1: iter = parent->right; break; default: return (parent); break; } } /* while */ return (NULL); } static void remove_recolour(struct opr_rbtree *head, struct opr_rbtree_node *parent, struct opr_rbtree_node *node) { struct opr_rbtree_node *other; while ((node == NULL || !node->red) && node != head->root) { if (parent->left == node) { other = parent->right; if (other->red) { other->red = 0; parent->red = 1; rotateleft(head, parent); other = parent->right; } if ((other->left == NULL || !other->left->red) && (other->right == NULL || !other->right->red)) { other->red = 1; node = parent; parent = node->parent; } else { if ((other->right == NULL) || (!other->right->red)) { other->left->red = 0; other->red = 1; rotateright(head, other); other = parent->right; } other->red = parent->red; parent->red = 0; other->right->red = 0; rotateleft(head, parent); node = head->root; break; } } else { other = parent->left; if (other->red) { other->red = 0; parent->red = 1; rotateright(head, parent); other = parent->left; } if ((other->left == NULL || !other->left->red) && (other->right == NULL || !other->right->red)) { other->red = 1; node = parent; parent = node->parent; } else { if (other->left == NULL || !other->left->red) { other->right->red = 0; other->red = 1; rotateleft(head, other); other = parent->left; } other->red = parent->red; parent->red = 0; other->left->red = 0; rotateright(head, parent); node = head->root; break; } } } if (node) node->red = 0; } void opr_rbtree_remove(struct opr_rbtree *head, struct opr_rbtree_node *node) { struct opr_rbtree_node *child = NULL, *parent; int red; if (!node->gen) { /* not in tree */ return; } node->gen = 0; if (node->left == NULL && node->right == NULL) { /* A node with no non-leaf children */ update_parent_ptr(head, node, NULL); if (!node->red) remove_recolour(head, node->parent, NULL); goto done; } if (node->left != NULL && node->right != NULL) { /* A node with two children. * * Move the next node in the tree (which will be a leaf node) * onto our tree current position, then rebalance as required */ struct opr_rbtree_node *old, *left; old = node; /* Set node to the next node in the tree from the current * position, where the next node is the left-most leaf node * in our right child */ node = node->right; while ((left = node->left) != NULL) node = left; /* Move 'node' into the position occupied by 'old', which is * being removed */ update_parent_ptr(head, old, node); child = node->right; parent = node->parent; red = node->red; /* As we're logically just copying the value, must preserve the * old node's colour */ node->red = old->red; /* ... and the old node's linkage */ if (parent == old) parent = node; else { if (child) child->parent = parent; parent->left = child; node->right = old->right; old->right->parent = node; } node->parent = old->parent; node->left = old->left; old->left->parent = node; /* If the node being removed was black, then we must recolour * tree to maintain balance */ if (!red) remove_recolour(head, parent, child); goto done; } /* Only remaining option - node with a single child */ if (node->left == NULL) child = node->right; else if (node->right == NULL) child = node->left; child->parent = node->parent; update_parent_ptr(head, node, child); if (!node->red) remove_recolour(head, node->parent, child); done: (head->size)--; (head->gen)++; return; } void opr_rbtree_replace(struct opr_rbtree *head, struct opr_rbtree_node *old, struct opr_rbtree_node *replacement) { /* Update our parent's pointer to us */ update_parent_ptr(head, old, replacement); /* And our children's pointers to us */ if (old->left) old->left->parent = replacement; if (old->right) old->right->parent = replacement; /* Copy over parent, left, right and colour */ *replacement = *old; } ntirpc-1.3.1/src/rbtree_x.c000066400000000000000000000050251261345040100155560ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #if !defined(_WIN32) #include #include #endif #include #include #include #include #include #include #define RBTX_REC_MAXPART 23 int rbtx_init(struct rbtree_x *xt, opr_rbtree_cmpf_t cmpf, uint32_t npart, uint32_t flags) { int ix, code = 0; pthread_rwlockattr_t rwlock_attr; struct rbtree_x_part *t; xt->flags = flags; if ((npart > RBTX_REC_MAXPART) || (npart % 2 == 0)) { __warnx(TIRPC_DEBUG_FLAG_RBTREE, "rbtx_init: value %d is an unlikely value for npart " "(suggest a small prime)", npart); } if (flags & RBT_X_FLAG_ALLOC) xt->tree = mem_alloc(npart * sizeof(struct rbtree_x_part)); /* prior versions of Linux tirpc are subject to default prefer-reader * behavior (so have potential for writer starvation) */ rwlockattr_init(&rwlock_attr); #ifdef GLIBC pthread_rwlockattr_setkind_np( &rwlock_attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP); #endif xt->npart = npart; for (ix = 0; ix < npart; ++ix) { t = &(xt->tree[ix]); mutex_init(&t->mtx, NULL); rwlock_init(&t->lock, &rwlock_attr); opr_rbtree_init(&t->t, cmpf /* may be NULL */); } return (code); } ntirpc-1.3.1/src/rpc_callmsg.c000066400000000000000000000214171261345040100162350ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * rpc_callmsg.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include #include #include #include #include #include #include #include /* in glibc 2.14+ x86_64, memcpy no longer tries to handle overlapping areas, * see Fedora Bug 691336 (NOTABUG); we dont permit overlapping segments, * so memcpy may be a small win over memmove. */ /* * encode a call message, log error messages */ bool xdr_call_encode(XDR *xdrs, struct rpc_msg *cmsg) { struct opaque_auth *oa; int32_t *buf; if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR cb_cred.oa_length (%u) > %u", __func__, __LINE__, cmsg->rm_call.cb_cred.oa_length, MAX_AUTH_BYTES); return (false); } if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR cb_verf.oa_length (%u) > %u", __func__, __LINE__, 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) { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u INLINE", __func__, __LINE__); IXDR_PUT_INT32(buf, cmsg->rm_xid); IXDR_PUT_ENUM(buf, cmsg->rm_direction); IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers); if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_rpcvers %u != %u", __func__, __LINE__, 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) { memcpy(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) { memcpy(buf, oa->oa_base, oa->oa_length); /* no real need.... buf += RNDUP(oa->oa_length) / sizeof (int32_t); */ } } else { /* nTI-RPC handles multiple buffers */ __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u non-INLINE", __func__, __LINE__); if (!xdr_putuint32(xdrs, &(cmsg->rm_xid))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_xid %u", __func__, __LINE__, cmsg->rm_xid); return (false); } if (!xdr_putenum(xdrs, cmsg->rm_direction)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_direction %u", __func__, __LINE__, cmsg->rm_direction); return (false); } if (!xdr_putuint32(xdrs, &(cmsg->rm_call.cb_rpcvers))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_rpcvers %u", __func__, __LINE__, cmsg->rm_call.cb_rpcvers); return (false); } if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_rpcvers %u != %u", __func__, __LINE__, cmsg->rm_call.cb_rpcvers, RPC_MSG_VERSION); return (false); } if (!xdr_putuint32(xdrs, &(cmsg->rm_call.cb_prog))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_prog %u", __func__, __LINE__, cmsg->rm_call.cb_prog); return (false); } if (!xdr_putuint32(xdrs, &(cmsg->rm_call.cb_vers))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_vers %u", __func__, __LINE__, cmsg->rm_call.cb_vers); return (false); } if (!xdr_putuint32(xdrs, &(cmsg->rm_call.cb_proc))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_proc %u", __func__, __LINE__, cmsg->rm_call.cb_proc); return (false); } if (!inline_auth_encode(xdrs, &(cmsg->rm_call.cb_cred))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (false); } if (!inline_auth_encode(xdrs, &(cmsg->rm_call.cb_verf))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (false); } } return (true); } /* * decode a call message, log error messages * * param[IN] buf 3 more inline */ bool xdr_call_decode(XDR *xdrs, struct rpc_msg *cmsg, int32_t *buf) { if (buf != NULL) { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u INLINE", __func__, __LINE__); cmsg->rm_call.cb_rpcvers = IXDR_GET_U_INT32(buf); } else { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u non-INLINE", __func__, __LINE__); if (!xdr_getuint32(xdrs, &cmsg->rm_call.cb_rpcvers)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_rpcvers", __func__, __LINE__); return (false); } } if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_rpcvers %u != %u", __func__, __LINE__, cmsg->rm_call.cb_rpcvers, RPC_MSG_VERSION); return (false); } if (buf != NULL) { cmsg->rm_call.cb_prog = IXDR_GET_U_INT32(buf); cmsg->rm_call.cb_vers = IXDR_GET_U_INT32(buf); } else if (!xdr_getuint32(xdrs, &(cmsg->rm_call.cb_prog))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_prog", __func__, __LINE__); return (false); } else if (!xdr_getuint32(xdrs, &(cmsg->rm_call.cb_vers))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_vers", __func__, __LINE__); return (false); } buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT); if (buf != NULL) { cmsg->rm_call.cb_proc = IXDR_GET_U_INT32(buf); if (!inline_auth_decode(xdrs, &(cmsg->rm_call.cb_cred), buf)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (false); } } else if (!xdr_getuint32(xdrs, &(cmsg->rm_call.cb_proc))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_call.cb_proc", __func__, __LINE__); return (false); } else if (!inline_auth_decode(xdrs, &(cmsg->rm_call.cb_cred), NULL)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (false); } if (!inline_auth_decode(xdrs, &(cmsg->rm_call.cb_verf), NULL)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (false); } return (true); } /* * XDR a call message, log error messages */ bool xdr_ncallmsg(XDR *xdrs, struct rpc_msg *cmsg) { assert(xdrs != NULL); assert(cmsg != NULL); switch (xdrs->x_op) { case XDR_ENCODE: if (cmsg->rm_direction != CALL) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR cmsg->rm_direction %u != %u", __func__, __LINE__, cmsg->rm_direction, CALL); return (false); } return (xdr_call_encode(xdrs, cmsg)); case XDR_DECODE: if (xdr_dplx_decode(xdrs, cmsg)) { if (cmsg->rm_direction != CALL) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR cmsg->rm_direction %u != %u", __func__, __LINE__, cmsg->rm_direction, CALL); return (false); } return (true); } break; case XDR_FREE: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u xdrs->x_op XDR_FREE", __func__, __LINE__); return (true); default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR xdrs->x_op (%u)", __func__, __LINE__, xdrs->x_op); break; } return (false); } /* xdr_ncallmsg */ ntirpc-1.3.1/src/rpc_com.h000066400000000000000000000073051261345040100153760ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc. */ /* * rpc_com.h, Common definitions for both the server and client side. * All for the topmost layer of rpc * * In Sun's tirpc distribution, this was installed as , * but as it contains only non-exported interfaces, it was moved here. */ #ifndef _TIRPC_RPCCOM_H #define _TIRPC_RPCCOM_H #include #include #include /* #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */ /* * The max size of the transport, if the size cannot be determined * by other means. */ #define RPC_MAXDATASIZE 9000 #define RPC_MAXADDRSIZE 1024 #ifndef __RPC_GETXID #define __RPC_GETXID(now) ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \ (u_int32_t)((now)->tv_nsec)) #endif /* !__RPC_GETXID */ __BEGIN_DECLS extern u_int __rpc_get_a_size(int); extern int __rpc_dtbsize(void); extern struct netconfig *__rpcgettp(int); extern int __rpc_get_default_domain(char **); struct netbuf *__rpc_set_netbuf(struct netbuf *, const void *, size_t); 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 **); struct netbuf *__rpcb_findaddr_timed(rpcprog_t, rpcvers_t, const struct netconfig *, const char *, CLIENT **, struct timeval *); bool __rpc_control(int, void *); char *_get_next_token(char *, int); bool __svc_clean_idle(fd_set *, int, bool); bool __xdrrec_setnonblock(XDR *, int); bool __xdrrec_getrec(XDR *, enum xprt_stat *, bool); void __xprt_unregister_unlocked(SVCXPRT *); /* * Uses allocator with indirections, if any. */ #include static inline char * rpc_strdup(const char *s) { char *t = mem_alloc(strlen(s) + 1); if (t) strcpy(t, s); return (t); } void __rpc_free(void *ptr); __END_DECLS #endif /* _TIRPC_RPCCOM_H */ ntirpc-1.3.1/src/rpc_commondata.c000066400000000000000000000033141261345040100167310ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include /* * This file should only contain common data (global data) that is exported * by public interfaces */ struct opaque_auth _null_auth; ntirpc-1.3.1/src/rpc_crc32.c000066400000000000000000001247531261345040100155360ustar00rootroot00000000000000/*- * COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or * code or tables extracted from it, as desired without restriction. */ /* * First, the polynomial itself and its table of feedback terms. The * polynomial is * X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 * * Note that we take it "backwards" and put the highest-order term in * the lowest-order bit. The X^32 term is "implied"; the LSB is the * X^31 term, etc. The X^0 term (usually shown as "+1") results in * the MSB being 1 * * Note that the usual hardware shift register implementation, which * is what we're using (we're merely optimizing it by doing eight-bit * chunks at a time) shifts bits into the lowest-order term. In our * implementation, that means shifting towards the right. Why do we * do it this way? Because the calculated CRC must be transmitted in * order from highest-order term to lowest-order term. UARTs transmit * characters in order from LSB to MSB. By storing the CRC this way * we hand it to the UART in the order low-byte to high-byte; the UART * sends each low-bit to hight-bit; and the result is transmission bit * by bit from highest- to lowest-order term without requiring any bit * shuffling on our part. Reception works similarly * * The feedback terms table consists of 256, 32-bit entries. Notes * * The table can be generated at runtime if desired; code to do so * is shown later. It might not be obvious, but the feedback * terms simply represent the results of eight shift/xor opera * tions for all combinations of data and CRC register values * * The values must be right-shifted by eight bits by the "updcrc * logic; the shift must be unsigned (bring in zeroes). On some * hardware you could probably optimize the shift in assembler by * using byte-swap instructions * polynomial $edb88320 * * * CRC32 code derived from work by Gary S. Brown. */ #include #include #include #include const uint32_t crc32_tab[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d }; /* * A function that calculates the CRC-32 based on the table above is * given below for documentation purposes. An equivalent implementation * of this function that's actually used in the kernel can be found * in sys/libkern.h, where it can be inlined. * * uint32_t * crc32(const void *buf, size_t size) * { * const uint8_t *p = buf; * uint32_t crc; * * crc = ~0U; * while (size--) * crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8); * return crc ^ ~0U; * } */ /* CRC32C routines, these use a different polynomial */ /*****************************************************************/ /* */ /* CRC LOOKUP TABLE */ /* ================ */ /* The following CRC lookup table was generated automagically */ /* by the Rocksoft^tm Model CRC Algorithm Table Generation */ /* Program V1.0 using the following model parameters: */ /* */ /* Width : 4 bytes. */ /* Poly : 0x1EDC6F41L */ /* Reverse : TRUE. */ /* */ /* For more information on the Rocksoft^tm Model CRC Algorithm, */ /* see the document titled "A Painless Guide to CRC Error */ /* Detection Algorithms" by Ross Williams */ /* (ross@guest.adelaide.edu.au.). This document is likely to be */ /* in the FTP archive "ftp.adelaide.edu.au/pub/rocksoft". */ /* */ /*****************************************************************/ static const uint32_t crc32Table[256] = { 0x00000000L, 0xF26B8303L, 0xE13B70F7L, 0x1350F3F4L, 0xC79A971FL, 0x35F1141CL, 0x26A1E7E8L, 0xD4CA64EBL, 0x8AD958CFL, 0x78B2DBCCL, 0x6BE22838L, 0x9989AB3BL, 0x4D43CFD0L, 0xBF284CD3L, 0xAC78BF27L, 0x5E133C24L, 0x105EC76FL, 0xE235446CL, 0xF165B798L, 0x030E349BL, 0xD7C45070L, 0x25AFD373L, 0x36FF2087L, 0xC494A384L, 0x9A879FA0L, 0x68EC1CA3L, 0x7BBCEF57L, 0x89D76C54L, 0x5D1D08BFL, 0xAF768BBCL, 0xBC267848L, 0x4E4DFB4BL, 0x20BD8EDEL, 0xD2D60DDDL, 0xC186FE29L, 0x33ED7D2AL, 0xE72719C1L, 0x154C9AC2L, 0x061C6936L, 0xF477EA35L, 0xAA64D611L, 0x580F5512L, 0x4B5FA6E6L, 0xB93425E5L, 0x6DFE410EL, 0x9F95C20DL, 0x8CC531F9L, 0x7EAEB2FAL, 0x30E349B1L, 0xC288CAB2L, 0xD1D83946L, 0x23B3BA45L, 0xF779DEAEL, 0x05125DADL, 0x1642AE59L, 0xE4292D5AL, 0xBA3A117EL, 0x4851927DL, 0x5B016189L, 0xA96AE28AL, 0x7DA08661L, 0x8FCB0562L, 0x9C9BF696L, 0x6EF07595L, 0x417B1DBCL, 0xB3109EBFL, 0xA0406D4BL, 0x522BEE48L, 0x86E18AA3L, 0x748A09A0L, 0x67DAFA54L, 0x95B17957L, 0xCBA24573L, 0x39C9C670L, 0x2A993584L, 0xD8F2B687L, 0x0C38D26CL, 0xFE53516FL, 0xED03A29BL, 0x1F682198L, 0x5125DAD3L, 0xA34E59D0L, 0xB01EAA24L, 0x42752927L, 0x96BF4DCCL, 0x64D4CECFL, 0x77843D3BL, 0x85EFBE38L, 0xDBFC821CL, 0x2997011FL, 0x3AC7F2EBL, 0xC8AC71E8L, 0x1C661503L, 0xEE0D9600L, 0xFD5D65F4L, 0x0F36E6F7L, 0x61C69362L, 0x93AD1061L, 0x80FDE395L, 0x72966096L, 0xA65C047DL, 0x5437877EL, 0x4767748AL, 0xB50CF789L, 0xEB1FCBADL, 0x197448AEL, 0x0A24BB5AL, 0xF84F3859L, 0x2C855CB2L, 0xDEEEDFB1L, 0xCDBE2C45L, 0x3FD5AF46L, 0x7198540DL, 0x83F3D70EL, 0x90A324FAL, 0x62C8A7F9L, 0xB602C312L, 0x44694011L, 0x5739B3E5L, 0xA55230E6L, 0xFB410CC2L, 0x092A8FC1L, 0x1A7A7C35L, 0xE811FF36L, 0x3CDB9BDDL, 0xCEB018DEL, 0xDDE0EB2AL, 0x2F8B6829L, 0x82F63B78L, 0x709DB87BL, 0x63CD4B8FL, 0x91A6C88CL, 0x456CAC67L, 0xB7072F64L, 0xA457DC90L, 0x563C5F93L, 0x082F63B7L, 0xFA44E0B4L, 0xE9141340L, 0x1B7F9043L, 0xCFB5F4A8L, 0x3DDE77ABL, 0x2E8E845FL, 0xDCE5075CL, 0x92A8FC17L, 0x60C37F14L, 0x73938CE0L, 0x81F80FE3L, 0x55326B08L, 0xA759E80BL, 0xB4091BFFL, 0x466298FCL, 0x1871A4D8L, 0xEA1A27DBL, 0xF94AD42FL, 0x0B21572CL, 0xDFEB33C7L, 0x2D80B0C4L, 0x3ED04330L, 0xCCBBC033L, 0xA24BB5A6L, 0x502036A5L, 0x4370C551L, 0xB11B4652L, 0x65D122B9L, 0x97BAA1BAL, 0x84EA524EL, 0x7681D14DL, 0x2892ED69L, 0xDAF96E6AL, 0xC9A99D9EL, 0x3BC21E9DL, 0xEF087A76L, 0x1D63F975L, 0x0E330A81L, 0xFC588982L, 0xB21572C9L, 0x407EF1CAL, 0x532E023EL, 0xA145813DL, 0x758FE5D6L, 0x87E466D5L, 0x94B49521L, 0x66DF1622L, 0x38CC2A06L, 0xCAA7A905L, 0xD9F75AF1L, 0x2B9CD9F2L, 0xFF56BD19L, 0x0D3D3E1AL, 0x1E6DCDEEL, 0xEC064EEDL, 0xC38D26C4L, 0x31E6A5C7L, 0x22B65633L, 0xD0DDD530L, 0x0417B1DBL, 0xF67C32D8L, 0xE52CC12CL, 0x1747422FL, 0x49547E0BL, 0xBB3FFD08L, 0xA86F0EFCL, 0x5A048DFFL, 0x8ECEE914L, 0x7CA56A17L, 0x6FF599E3L, 0x9D9E1AE0L, 0xD3D3E1ABL, 0x21B862A8L, 0x32E8915CL, 0xC083125FL, 0x144976B4L, 0xE622F5B7L, 0xF5720643L, 0x07198540L, 0x590AB964L, 0xAB613A67L, 0xB831C993L, 0x4A5A4A90L, 0x9E902E7BL, 0x6CFBAD78L, 0x7FAB5E8CL, 0x8DC0DD8FL, 0xE330A81AL, 0x115B2B19L, 0x020BD8EDL, 0xF0605BEEL, 0x24AA3F05L, 0xD6C1BC06L, 0xC5914FF2L, 0x37FACCF1L, 0x69E9F0D5L, 0x9B8273D6L, 0x88D28022L, 0x7AB90321L, 0xAE7367CAL, 0x5C18E4C9L, 0x4F48173DL, 0xBD23943EL, 0xF36E6F75L, 0x0105EC76L, 0x12551F82L, 0xE03E9C81L, 0x34F4F86AL, 0xC69F7B69L, 0xD5CF889DL, 0x27A40B9EL, 0x79B737BAL, 0x8BDCB4B9L, 0x988C474DL, 0x6AE7C44EL, 0xBE2DA0A5L, 0x4C4623A6L, 0x5F16D052L, 0xAD7D5351L }; static uint32_t singletable_crc32c(uint32_t crc, const void *buf, size_t size) { const uint8_t *p = buf; while (size--) crc = crc32Table[(crc ^ *p++) & 0xff] ^ (crc >> 8); return crc; } /* * Copyright (c) 2004-2006 Intel Corporation - All Rights Reserved * * * This software program is licensed subject to the BSD License, available at * http://www.opensource.org/licenses/bsd-license.html. * * Abstract: * * Tables for software CRC generation */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o32[256] = { 0x00000000, 0xF26B8303, 0xE13B70F7, 0x1350F3F4, 0xC79A971F, 0x35F1141C, 0x26A1E7E8, 0xD4CA64EB, 0x8AD958CF, 0x78B2DBCC, 0x6BE22838, 0x9989AB3B, 0x4D43CFD0, 0xBF284CD3, 0xAC78BF27, 0x5E133C24, 0x105EC76F, 0xE235446C, 0xF165B798, 0x030E349B, 0xD7C45070, 0x25AFD373, 0x36FF2087, 0xC494A384, 0x9A879FA0, 0x68EC1CA3, 0x7BBCEF57, 0x89D76C54, 0x5D1D08BF, 0xAF768BBC, 0xBC267848, 0x4E4DFB4B, 0x20BD8EDE, 0xD2D60DDD, 0xC186FE29, 0x33ED7D2A, 0xE72719C1, 0x154C9AC2, 0x061C6936, 0xF477EA35, 0xAA64D611, 0x580F5512, 0x4B5FA6E6, 0xB93425E5, 0x6DFE410E, 0x9F95C20D, 0x8CC531F9, 0x7EAEB2FA, 0x30E349B1, 0xC288CAB2, 0xD1D83946, 0x23B3BA45, 0xF779DEAE, 0x05125DAD, 0x1642AE59, 0xE4292D5A, 0xBA3A117E, 0x4851927D, 0x5B016189, 0xA96AE28A, 0x7DA08661, 0x8FCB0562, 0x9C9BF696, 0x6EF07595, 0x417B1DBC, 0xB3109EBF, 0xA0406D4B, 0x522BEE48, 0x86E18AA3, 0x748A09A0, 0x67DAFA54, 0x95B17957, 0xCBA24573, 0x39C9C670, 0x2A993584, 0xD8F2B687, 0x0C38D26C, 0xFE53516F, 0xED03A29B, 0x1F682198, 0x5125DAD3, 0xA34E59D0, 0xB01EAA24, 0x42752927, 0x96BF4DCC, 0x64D4CECF, 0x77843D3B, 0x85EFBE38, 0xDBFC821C, 0x2997011F, 0x3AC7F2EB, 0xC8AC71E8, 0x1C661503, 0xEE0D9600, 0xFD5D65F4, 0x0F36E6F7, 0x61C69362, 0x93AD1061, 0x80FDE395, 0x72966096, 0xA65C047D, 0x5437877E, 0x4767748A, 0xB50CF789, 0xEB1FCBAD, 0x197448AE, 0x0A24BB5A, 0xF84F3859, 0x2C855CB2, 0xDEEEDFB1, 0xCDBE2C45, 0x3FD5AF46, 0x7198540D, 0x83F3D70E, 0x90A324FA, 0x62C8A7F9, 0xB602C312, 0x44694011, 0x5739B3E5, 0xA55230E6, 0xFB410CC2, 0x092A8FC1, 0x1A7A7C35, 0xE811FF36, 0x3CDB9BDD, 0xCEB018DE, 0xDDE0EB2A, 0x2F8B6829, 0x82F63B78, 0x709DB87B, 0x63CD4B8F, 0x91A6C88C, 0x456CAC67, 0xB7072F64, 0xA457DC90, 0x563C5F93, 0x082F63B7, 0xFA44E0B4, 0xE9141340, 0x1B7F9043, 0xCFB5F4A8, 0x3DDE77AB, 0x2E8E845F, 0xDCE5075C, 0x92A8FC17, 0x60C37F14, 0x73938CE0, 0x81F80FE3, 0x55326B08, 0xA759E80B, 0xB4091BFF, 0x466298FC, 0x1871A4D8, 0xEA1A27DB, 0xF94AD42F, 0x0B21572C, 0xDFEB33C7, 0x2D80B0C4, 0x3ED04330, 0xCCBBC033, 0xA24BB5A6, 0x502036A5, 0x4370C551, 0xB11B4652, 0x65D122B9, 0x97BAA1BA, 0x84EA524E, 0x7681D14D, 0x2892ED69, 0xDAF96E6A, 0xC9A99D9E, 0x3BC21E9D, 0xEF087A76, 0x1D63F975, 0x0E330A81, 0xFC588982, 0xB21572C9, 0x407EF1CA, 0x532E023E, 0xA145813D, 0x758FE5D6, 0x87E466D5, 0x94B49521, 0x66DF1622, 0x38CC2A06, 0xCAA7A905, 0xD9F75AF1, 0x2B9CD9F2, 0xFF56BD19, 0x0D3D3E1A, 0x1E6DCDEE, 0xEC064EED, 0xC38D26C4, 0x31E6A5C7, 0x22B65633, 0xD0DDD530, 0x0417B1DB, 0xF67C32D8, 0xE52CC12C, 0x1747422F, 0x49547E0B, 0xBB3FFD08, 0xA86F0EFC, 0x5A048DFF, 0x8ECEE914, 0x7CA56A17, 0x6FF599E3, 0x9D9E1AE0, 0xD3D3E1AB, 0x21B862A8, 0x32E8915C, 0xC083125F, 0x144976B4, 0xE622F5B7, 0xF5720643, 0x07198540, 0x590AB964, 0xAB613A67, 0xB831C993, 0x4A5A4A90, 0x9E902E7B, 0x6CFBAD78, 0x7FAB5E8C, 0x8DC0DD8F, 0xE330A81A, 0x115B2B19, 0x020BD8ED, 0xF0605BEE, 0x24AA3F05, 0xD6C1BC06, 0xC5914FF2, 0x37FACCF1, 0x69E9F0D5, 0x9B8273D6, 0x88D28022, 0x7AB90321, 0xAE7367CA, 0x5C18E4C9, 0x4F48173D, 0xBD23943E, 0xF36E6F75, 0x0105EC76, 0x12551F82, 0xE03E9C81, 0x34F4F86A, 0xC69F7B69, 0xD5CF889D, 0x27A40B9E, 0x79B737BA, 0x8BDCB4B9, 0x988C474D, 0x6AE7C44E, 0xBE2DA0A5, 0x4C4623A6, 0x5F16D052, 0xAD7D5351 }; /* * end of the CRC lookup table crc_tableil8_o32 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o40[256] = { 0x00000000, 0x13A29877, 0x274530EE, 0x34E7A899, 0x4E8A61DC, 0x5D28F9AB, 0x69CF5132, 0x7A6DC945, 0x9D14C3B8, 0x8EB65BCF, 0xBA51F356, 0xA9F36B21, 0xD39EA264, 0xC03C3A13, 0xF4DB928A, 0xE7790AFD, 0x3FC5F181, 0x2C6769F6, 0x1880C16F, 0x0B225918, 0x714F905D, 0x62ED082A, 0x560AA0B3, 0x45A838C4, 0xA2D13239, 0xB173AA4E, 0x859402D7, 0x96369AA0, 0xEC5B53E5, 0xFFF9CB92, 0xCB1E630B, 0xD8BCFB7C, 0x7F8BE302, 0x6C297B75, 0x58CED3EC, 0x4B6C4B9B, 0x310182DE, 0x22A31AA9, 0x1644B230, 0x05E62A47, 0xE29F20BA, 0xF13DB8CD, 0xC5DA1054, 0xD6788823, 0xAC154166, 0xBFB7D911, 0x8B507188, 0x98F2E9FF, 0x404E1283, 0x53EC8AF4, 0x670B226D, 0x74A9BA1A, 0x0EC4735F, 0x1D66EB28, 0x298143B1, 0x3A23DBC6, 0xDD5AD13B, 0xCEF8494C, 0xFA1FE1D5, 0xE9BD79A2, 0x93D0B0E7, 0x80722890, 0xB4958009, 0xA737187E, 0xFF17C604, 0xECB55E73, 0xD852F6EA, 0xCBF06E9D, 0xB19DA7D8, 0xA23F3FAF, 0x96D89736, 0x857A0F41, 0x620305BC, 0x71A19DCB, 0x45463552, 0x56E4AD25, 0x2C896460, 0x3F2BFC17, 0x0BCC548E, 0x186ECCF9, 0xC0D23785, 0xD370AFF2, 0xE797076B, 0xF4359F1C, 0x8E585659, 0x9DFACE2E, 0xA91D66B7, 0xBABFFEC0, 0x5DC6F43D, 0x4E646C4A, 0x7A83C4D3, 0x69215CA4, 0x134C95E1, 0x00EE0D96, 0x3409A50F, 0x27AB3D78, 0x809C2506, 0x933EBD71, 0xA7D915E8, 0xB47B8D9F, 0xCE1644DA, 0xDDB4DCAD, 0xE9537434, 0xFAF1EC43, 0x1D88E6BE, 0x0E2A7EC9, 0x3ACDD650, 0x296F4E27, 0x53028762, 0x40A01F15, 0x7447B78C, 0x67E52FFB, 0xBF59D487, 0xACFB4CF0, 0x981CE469, 0x8BBE7C1E, 0xF1D3B55B, 0xE2712D2C, 0xD69685B5, 0xC5341DC2, 0x224D173F, 0x31EF8F48, 0x050827D1, 0x16AABFA6, 0x6CC776E3, 0x7F65EE94, 0x4B82460D, 0x5820DE7A, 0xFBC3FAF9, 0xE861628E, 0xDC86CA17, 0xCF245260, 0xB5499B25, 0xA6EB0352, 0x920CABCB, 0x81AE33BC, 0x66D73941, 0x7575A136, 0x419209AF, 0x523091D8, 0x285D589D, 0x3BFFC0EA, 0x0F186873, 0x1CBAF004, 0xC4060B78, 0xD7A4930F, 0xE3433B96, 0xF0E1A3E1, 0x8A8C6AA4, 0x992EF2D3, 0xADC95A4A, 0xBE6BC23D, 0x5912C8C0, 0x4AB050B7, 0x7E57F82E, 0x6DF56059, 0x1798A91C, 0x043A316B, 0x30DD99F2, 0x237F0185, 0x844819FB, 0x97EA818C, 0xA30D2915, 0xB0AFB162, 0xCAC27827, 0xD960E050, 0xED8748C9, 0xFE25D0BE, 0x195CDA43, 0x0AFE4234, 0x3E19EAAD, 0x2DBB72DA, 0x57D6BB9F, 0x447423E8, 0x70938B71, 0x63311306, 0xBB8DE87A, 0xA82F700D, 0x9CC8D894, 0x8F6A40E3, 0xF50789A6, 0xE6A511D1, 0xD242B948, 0xC1E0213F, 0x26992BC2, 0x353BB3B5, 0x01DC1B2C, 0x127E835B, 0x68134A1E, 0x7BB1D269, 0x4F567AF0, 0x5CF4E287, 0x04D43CFD, 0x1776A48A, 0x23910C13, 0x30339464, 0x4A5E5D21, 0x59FCC556, 0x6D1B6DCF, 0x7EB9F5B8, 0x99C0FF45, 0x8A626732, 0xBE85CFAB, 0xAD2757DC, 0xD74A9E99, 0xC4E806EE, 0xF00FAE77, 0xE3AD3600, 0x3B11CD7C, 0x28B3550B, 0x1C54FD92, 0x0FF665E5, 0x759BACA0, 0x663934D7, 0x52DE9C4E, 0x417C0439, 0xA6050EC4, 0xB5A796B3, 0x81403E2A, 0x92E2A65D, 0xE88F6F18, 0xFB2DF76F, 0xCFCA5FF6, 0xDC68C781, 0x7B5FDFFF, 0x68FD4788, 0x5C1AEF11, 0x4FB87766, 0x35D5BE23, 0x26772654, 0x12908ECD, 0x013216BA, 0xE64B1C47, 0xF5E98430, 0xC10E2CA9, 0xD2ACB4DE, 0xA8C17D9B, 0xBB63E5EC, 0x8F844D75, 0x9C26D502, 0x449A2E7E, 0x5738B609, 0x63DF1E90, 0x707D86E7, 0x0A104FA2, 0x19B2D7D5, 0x2D557F4C, 0x3EF7E73B, 0xD98EEDC6, 0xCA2C75B1, 0xFECBDD28, 0xED69455F, 0x97048C1A, 0x84A6146D, 0xB041BCF4, 0xA3E32483 }; /* * end of the CRC lookup table crc_tableil8_o40 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o48[256] = { 0x00000000, 0xA541927E, 0x4F6F520D, 0xEA2EC073, 0x9EDEA41A, 0x3B9F3664, 0xD1B1F617, 0x74F06469, 0x38513EC5, 0x9D10ACBB, 0x773E6CC8, 0xD27FFEB6, 0xA68F9ADF, 0x03CE08A1, 0xE9E0C8D2, 0x4CA15AAC, 0x70A27D8A, 0xD5E3EFF4, 0x3FCD2F87, 0x9A8CBDF9, 0xEE7CD990, 0x4B3D4BEE, 0xA1138B9D, 0x045219E3, 0x48F3434F, 0xEDB2D131, 0x079C1142, 0xA2DD833C, 0xD62DE755, 0x736C752B, 0x9942B558, 0x3C032726, 0xE144FB14, 0x4405696A, 0xAE2BA919, 0x0B6A3B67, 0x7F9A5F0E, 0xDADBCD70, 0x30F50D03, 0x95B49F7D, 0xD915C5D1, 0x7C5457AF, 0x967A97DC, 0x333B05A2, 0x47CB61CB, 0xE28AF3B5, 0x08A433C6, 0xADE5A1B8, 0x91E6869E, 0x34A714E0, 0xDE89D493, 0x7BC846ED, 0x0F382284, 0xAA79B0FA, 0x40577089, 0xE516E2F7, 0xA9B7B85B, 0x0CF62A25, 0xE6D8EA56, 0x43997828, 0x37691C41, 0x92288E3F, 0x78064E4C, 0xDD47DC32, 0xC76580D9, 0x622412A7, 0x880AD2D4, 0x2D4B40AA, 0x59BB24C3, 0xFCFAB6BD, 0x16D476CE, 0xB395E4B0, 0xFF34BE1C, 0x5A752C62, 0xB05BEC11, 0x151A7E6F, 0x61EA1A06, 0xC4AB8878, 0x2E85480B, 0x8BC4DA75, 0xB7C7FD53, 0x12866F2D, 0xF8A8AF5E, 0x5DE93D20, 0x29195949, 0x8C58CB37, 0x66760B44, 0xC337993A, 0x8F96C396, 0x2AD751E8, 0xC0F9919B, 0x65B803E5, 0x1148678C, 0xB409F5F2, 0x5E273581, 0xFB66A7FF, 0x26217BCD, 0x8360E9B3, 0x694E29C0, 0xCC0FBBBE, 0xB8FFDFD7, 0x1DBE4DA9, 0xF7908DDA, 0x52D11FA4, 0x1E704508, 0xBB31D776, 0x511F1705, 0xF45E857B, 0x80AEE112, 0x25EF736C, 0xCFC1B31F, 0x6A802161, 0x56830647, 0xF3C29439, 0x19EC544A, 0xBCADC634, 0xC85DA25D, 0x6D1C3023, 0x8732F050, 0x2273622E, 0x6ED23882, 0xCB93AAFC, 0x21BD6A8F, 0x84FCF8F1, 0xF00C9C98, 0x554D0EE6, 0xBF63CE95, 0x1A225CEB, 0x8B277743, 0x2E66E53D, 0xC448254E, 0x6109B730, 0x15F9D359, 0xB0B84127, 0x5A968154, 0xFFD7132A, 0xB3764986, 0x1637DBF8, 0xFC191B8B, 0x595889F5, 0x2DA8ED9C, 0x88E97FE2, 0x62C7BF91, 0xC7862DEF, 0xFB850AC9, 0x5EC498B7, 0xB4EA58C4, 0x11ABCABA, 0x655BAED3, 0xC01A3CAD, 0x2A34FCDE, 0x8F756EA0, 0xC3D4340C, 0x6695A672, 0x8CBB6601, 0x29FAF47F, 0x5D0A9016, 0xF84B0268, 0x1265C21B, 0xB7245065, 0x6A638C57, 0xCF221E29, 0x250CDE5A, 0x804D4C24, 0xF4BD284D, 0x51FCBA33, 0xBBD27A40, 0x1E93E83E, 0x5232B292, 0xF77320EC, 0x1D5DE09F, 0xB81C72E1, 0xCCEC1688, 0x69AD84F6, 0x83834485, 0x26C2D6FB, 0x1AC1F1DD, 0xBF8063A3, 0x55AEA3D0, 0xF0EF31AE, 0x841F55C7, 0x215EC7B9, 0xCB7007CA, 0x6E3195B4, 0x2290CF18, 0x87D15D66, 0x6DFF9D15, 0xC8BE0F6B, 0xBC4E6B02, 0x190FF97C, 0xF321390F, 0x5660AB71, 0x4C42F79A, 0xE90365E4, 0x032DA597, 0xA66C37E9, 0xD29C5380, 0x77DDC1FE, 0x9DF3018D, 0x38B293F3, 0x7413C95F, 0xD1525B21, 0x3B7C9B52, 0x9E3D092C, 0xEACD6D45, 0x4F8CFF3B, 0xA5A23F48, 0x00E3AD36, 0x3CE08A10, 0x99A1186E, 0x738FD81D, 0xD6CE4A63, 0xA23E2E0A, 0x077FBC74, 0xED517C07, 0x4810EE79, 0x04B1B4D5, 0xA1F026AB, 0x4BDEE6D8, 0xEE9F74A6, 0x9A6F10CF, 0x3F2E82B1, 0xD50042C2, 0x7041D0BC, 0xAD060C8E, 0x08479EF0, 0xE2695E83, 0x4728CCFD, 0x33D8A894, 0x96993AEA, 0x7CB7FA99, 0xD9F668E7, 0x9557324B, 0x3016A035, 0xDA386046, 0x7F79F238, 0x0B899651, 0xAEC8042F, 0x44E6C45C, 0xE1A75622, 0xDDA47104, 0x78E5E37A, 0x92CB2309, 0x378AB177, 0x437AD51E, 0xE63B4760, 0x0C158713, 0xA954156D, 0xE5F54FC1, 0x40B4DDBF, 0xAA9A1DCC, 0x0FDB8FB2, 0x7B2BEBDB, 0xDE6A79A5, 0x3444B9D6, 0x91052BA8 }; /* * end of the CRC lookup table crc_tableil8_o48 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o56[256] = { 0x00000000, 0xDD45AAB8, 0xBF672381, 0x62228939, 0x7B2231F3, 0xA6679B4B, 0xC4451272, 0x1900B8CA, 0xF64463E6, 0x2B01C95E, 0x49234067, 0x9466EADF, 0x8D665215, 0x5023F8AD, 0x32017194, 0xEF44DB2C, 0xE964B13D, 0x34211B85, 0x560392BC, 0x8B463804, 0x924680CE, 0x4F032A76, 0x2D21A34F, 0xF06409F7, 0x1F20D2DB, 0xC2657863, 0xA047F15A, 0x7D025BE2, 0x6402E328, 0xB9474990, 0xDB65C0A9, 0x06206A11, 0xD725148B, 0x0A60BE33, 0x6842370A, 0xB5079DB2, 0xAC072578, 0x71428FC0, 0x136006F9, 0xCE25AC41, 0x2161776D, 0xFC24DDD5, 0x9E0654EC, 0x4343FE54, 0x5A43469E, 0x8706EC26, 0xE524651F, 0x3861CFA7, 0x3E41A5B6, 0xE3040F0E, 0x81268637, 0x5C632C8F, 0x45639445, 0x98263EFD, 0xFA04B7C4, 0x27411D7C, 0xC805C650, 0x15406CE8, 0x7762E5D1, 0xAA274F69, 0xB327F7A3, 0x6E625D1B, 0x0C40D422, 0xD1057E9A, 0xABA65FE7, 0x76E3F55F, 0x14C17C66, 0xC984D6DE, 0xD0846E14, 0x0DC1C4AC, 0x6FE34D95, 0xB2A6E72D, 0x5DE23C01, 0x80A796B9, 0xE2851F80, 0x3FC0B538, 0x26C00DF2, 0xFB85A74A, 0x99A72E73, 0x44E284CB, 0x42C2EEDA, 0x9F874462, 0xFDA5CD5B, 0x20E067E3, 0x39E0DF29, 0xE4A57591, 0x8687FCA8, 0x5BC25610, 0xB4868D3C, 0x69C32784, 0x0BE1AEBD, 0xD6A40405, 0xCFA4BCCF, 0x12E11677, 0x70C39F4E, 0xAD8635F6, 0x7C834B6C, 0xA1C6E1D4, 0xC3E468ED, 0x1EA1C255, 0x07A17A9F, 0xDAE4D027, 0xB8C6591E, 0x6583F3A6, 0x8AC7288A, 0x57828232, 0x35A00B0B, 0xE8E5A1B3, 0xF1E51979, 0x2CA0B3C1, 0x4E823AF8, 0x93C79040, 0x95E7FA51, 0x48A250E9, 0x2A80D9D0, 0xF7C57368, 0xEEC5CBA2, 0x3380611A, 0x51A2E823, 0x8CE7429B, 0x63A399B7, 0xBEE6330F, 0xDCC4BA36, 0x0181108E, 0x1881A844, 0xC5C402FC, 0xA7E68BC5, 0x7AA3217D, 0x52A0C93F, 0x8FE56387, 0xEDC7EABE, 0x30824006, 0x2982F8CC, 0xF4C75274, 0x96E5DB4D, 0x4BA071F5, 0xA4E4AAD9, 0x79A10061, 0x1B838958, 0xC6C623E0, 0xDFC69B2A, 0x02833192, 0x60A1B8AB, 0xBDE41213, 0xBBC47802, 0x6681D2BA, 0x04A35B83, 0xD9E6F13B, 0xC0E649F1, 0x1DA3E349, 0x7F816A70, 0xA2C4C0C8, 0x4D801BE4, 0x90C5B15C, 0xF2E73865, 0x2FA292DD, 0x36A22A17, 0xEBE780AF, 0x89C50996, 0x5480A32E, 0x8585DDB4, 0x58C0770C, 0x3AE2FE35, 0xE7A7548D, 0xFEA7EC47, 0x23E246FF, 0x41C0CFC6, 0x9C85657E, 0x73C1BE52, 0xAE8414EA, 0xCCA69DD3, 0x11E3376B, 0x08E38FA1, 0xD5A62519, 0xB784AC20, 0x6AC10698, 0x6CE16C89, 0xB1A4C631, 0xD3864F08, 0x0EC3E5B0, 0x17C35D7A, 0xCA86F7C2, 0xA8A47EFB, 0x75E1D443, 0x9AA50F6F, 0x47E0A5D7, 0x25C22CEE, 0xF8878656, 0xE1873E9C, 0x3CC29424, 0x5EE01D1D, 0x83A5B7A5, 0xF90696D8, 0x24433C60, 0x4661B559, 0x9B241FE1, 0x8224A72B, 0x5F610D93, 0x3D4384AA, 0xE0062E12, 0x0F42F53E, 0xD2075F86, 0xB025D6BF, 0x6D607C07, 0x7460C4CD, 0xA9256E75, 0xCB07E74C, 0x16424DF4, 0x106227E5, 0xCD278D5D, 0xAF050464, 0x7240AEDC, 0x6B401616, 0xB605BCAE, 0xD4273597, 0x09629F2F, 0xE6264403, 0x3B63EEBB, 0x59416782, 0x8404CD3A, 0x9D0475F0, 0x4041DF48, 0x22635671, 0xFF26FCC9, 0x2E238253, 0xF36628EB, 0x9144A1D2, 0x4C010B6A, 0x5501B3A0, 0x88441918, 0xEA669021, 0x37233A99, 0xD867E1B5, 0x05224B0D, 0x6700C234, 0xBA45688C, 0xA345D046, 0x7E007AFE, 0x1C22F3C7, 0xC167597F, 0xC747336E, 0x1A0299D6, 0x782010EF, 0xA565BA57, 0xBC65029D, 0x6120A825, 0x0302211C, 0xDE478BA4, 0x31035088, 0xEC46FA30, 0x8E647309, 0x5321D9B1, 0x4A21617B, 0x9764CBC3, 0xF54642FA, 0x2803E842 }; /* * end of the CRC lookup table crc_tableil8_o56 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o64[256] = { 0x00000000, 0x38116FAC, 0x7022DF58, 0x4833B0F4, 0xE045BEB0, 0xD854D11C, 0x906761E8, 0xA8760E44, 0xC5670B91, 0xFD76643D, 0xB545D4C9, 0x8D54BB65, 0x2522B521, 0x1D33DA8D, 0x55006A79, 0x6D1105D5, 0x8F2261D3, 0xB7330E7F, 0xFF00BE8B, 0xC711D127, 0x6F67DF63, 0x5776B0CF, 0x1F45003B, 0x27546F97, 0x4A456A42, 0x725405EE, 0x3A67B51A, 0x0276DAB6, 0xAA00D4F2, 0x9211BB5E, 0xDA220BAA, 0xE2336406, 0x1BA8B557, 0x23B9DAFB, 0x6B8A6A0F, 0x539B05A3, 0xFBED0BE7, 0xC3FC644B, 0x8BCFD4BF, 0xB3DEBB13, 0xDECFBEC6, 0xE6DED16A, 0xAEED619E, 0x96FC0E32, 0x3E8A0076, 0x069B6FDA, 0x4EA8DF2E, 0x76B9B082, 0x948AD484, 0xAC9BBB28, 0xE4A80BDC, 0xDCB96470, 0x74CF6A34, 0x4CDE0598, 0x04EDB56C, 0x3CFCDAC0, 0x51EDDF15, 0x69FCB0B9, 0x21CF004D, 0x19DE6FE1, 0xB1A861A5, 0x89B90E09, 0xC18ABEFD, 0xF99BD151, 0x37516AAE, 0x0F400502, 0x4773B5F6, 0x7F62DA5A, 0xD714D41E, 0xEF05BBB2, 0xA7360B46, 0x9F2764EA, 0xF236613F, 0xCA270E93, 0x8214BE67, 0xBA05D1CB, 0x1273DF8F, 0x2A62B023, 0x625100D7, 0x5A406F7B, 0xB8730B7D, 0x806264D1, 0xC851D425, 0xF040BB89, 0x5836B5CD, 0x6027DA61, 0x28146A95, 0x10050539, 0x7D1400EC, 0x45056F40, 0x0D36DFB4, 0x3527B018, 0x9D51BE5C, 0xA540D1F0, 0xED736104, 0xD5620EA8, 0x2CF9DFF9, 0x14E8B055, 0x5CDB00A1, 0x64CA6F0D, 0xCCBC6149, 0xF4AD0EE5, 0xBC9EBE11, 0x848FD1BD, 0xE99ED468, 0xD18FBBC4, 0x99BC0B30, 0xA1AD649C, 0x09DB6AD8, 0x31CA0574, 0x79F9B580, 0x41E8DA2C, 0xA3DBBE2A, 0x9BCAD186, 0xD3F96172, 0xEBE80EDE, 0x439E009A, 0x7B8F6F36, 0x33BCDFC2, 0x0BADB06E, 0x66BCB5BB, 0x5EADDA17, 0x169E6AE3, 0x2E8F054F, 0x86F90B0B, 0xBEE864A7, 0xF6DBD453, 0xCECABBFF, 0x6EA2D55C, 0x56B3BAF0, 0x1E800A04, 0x269165A8, 0x8EE76BEC, 0xB6F60440, 0xFEC5B4B4, 0xC6D4DB18, 0xABC5DECD, 0x93D4B161, 0xDBE70195, 0xE3F66E39, 0x4B80607D, 0x73910FD1, 0x3BA2BF25, 0x03B3D089, 0xE180B48F, 0xD991DB23, 0x91A26BD7, 0xA9B3047B, 0x01C50A3F, 0x39D46593, 0x71E7D567, 0x49F6BACB, 0x24E7BF1E, 0x1CF6D0B2, 0x54C56046, 0x6CD40FEA, 0xC4A201AE, 0xFCB36E02, 0xB480DEF6, 0x8C91B15A, 0x750A600B, 0x4D1B0FA7, 0x0528BF53, 0x3D39D0FF, 0x954FDEBB, 0xAD5EB117, 0xE56D01E3, 0xDD7C6E4F, 0xB06D6B9A, 0x887C0436, 0xC04FB4C2, 0xF85EDB6E, 0x5028D52A, 0x6839BA86, 0x200A0A72, 0x181B65DE, 0xFA2801D8, 0xC2396E74, 0x8A0ADE80, 0xB21BB12C, 0x1A6DBF68, 0x227CD0C4, 0x6A4F6030, 0x525E0F9C, 0x3F4F0A49, 0x075E65E5, 0x4F6DD511, 0x777CBABD, 0xDF0AB4F9, 0xE71BDB55, 0xAF286BA1, 0x9739040D, 0x59F3BFF2, 0x61E2D05E, 0x29D160AA, 0x11C00F06, 0xB9B60142, 0x81A76EEE, 0xC994DE1A, 0xF185B1B6, 0x9C94B463, 0xA485DBCF, 0xECB66B3B, 0xD4A70497, 0x7CD10AD3, 0x44C0657F, 0x0CF3D58B, 0x34E2BA27, 0xD6D1DE21, 0xEEC0B18D, 0xA6F30179, 0x9EE26ED5, 0x36946091, 0x0E850F3D, 0x46B6BFC9, 0x7EA7D065, 0x13B6D5B0, 0x2BA7BA1C, 0x63940AE8, 0x5B856544, 0xF3F36B00, 0xCBE204AC, 0x83D1B458, 0xBBC0DBF4, 0x425B0AA5, 0x7A4A6509, 0x3279D5FD, 0x0A68BA51, 0xA21EB415, 0x9A0FDBB9, 0xD23C6B4D, 0xEA2D04E1, 0x873C0134, 0xBF2D6E98, 0xF71EDE6C, 0xCF0FB1C0, 0x6779BF84, 0x5F68D028, 0x175B60DC, 0x2F4A0F70, 0xCD796B76, 0xF56804DA, 0xBD5BB42E, 0x854ADB82, 0x2D3CD5C6, 0x152DBA6A, 0x5D1E0A9E, 0x650F6532, 0x081E60E7, 0x300F0F4B, 0x783CBFBF, 0x402DD013, 0xE85BDE57, 0xD04AB1FB, 0x9879010F, 0xA0686EA3 }; /* * end of the CRC lookup table crc_tableil8_o64 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o72[256] = { 0x00000000, 0xEF306B19, 0xDB8CA0C3, 0x34BCCBDA, 0xB2F53777, 0x5DC55C6E, 0x697997B4, 0x8649FCAD, 0x6006181F, 0x8F367306, 0xBB8AB8DC, 0x54BAD3C5, 0xD2F32F68, 0x3DC34471, 0x097F8FAB, 0xE64FE4B2, 0xC00C303E, 0x2F3C5B27, 0x1B8090FD, 0xF4B0FBE4, 0x72F90749, 0x9DC96C50, 0xA975A78A, 0x4645CC93, 0xA00A2821, 0x4F3A4338, 0x7B8688E2, 0x94B6E3FB, 0x12FF1F56, 0xFDCF744F, 0xC973BF95, 0x2643D48C, 0x85F4168D, 0x6AC47D94, 0x5E78B64E, 0xB148DD57, 0x370121FA, 0xD8314AE3, 0xEC8D8139, 0x03BDEA20, 0xE5F20E92, 0x0AC2658B, 0x3E7EAE51, 0xD14EC548, 0x570739E5, 0xB83752FC, 0x8C8B9926, 0x63BBF23F, 0x45F826B3, 0xAAC84DAA, 0x9E748670, 0x7144ED69, 0xF70D11C4, 0x183D7ADD, 0x2C81B107, 0xC3B1DA1E, 0x25FE3EAC, 0xCACE55B5, 0xFE729E6F, 0x1142F576, 0x970B09DB, 0x783B62C2, 0x4C87A918, 0xA3B7C201, 0x0E045BEB, 0xE13430F2, 0xD588FB28, 0x3AB89031, 0xBCF16C9C, 0x53C10785, 0x677DCC5F, 0x884DA746, 0x6E0243F4, 0x813228ED, 0xB58EE337, 0x5ABE882E, 0xDCF77483, 0x33C71F9A, 0x077BD440, 0xE84BBF59, 0xCE086BD5, 0x213800CC, 0x1584CB16, 0xFAB4A00F, 0x7CFD5CA2, 0x93CD37BB, 0xA771FC61, 0x48419778, 0xAE0E73CA, 0x413E18D3, 0x7582D309, 0x9AB2B810, 0x1CFB44BD, 0xF3CB2FA4, 0xC777E47E, 0x28478F67, 0x8BF04D66, 0x64C0267F, 0x507CEDA5, 0xBF4C86BC, 0x39057A11, 0xD6351108, 0xE289DAD2, 0x0DB9B1CB, 0xEBF65579, 0x04C63E60, 0x307AF5BA, 0xDF4A9EA3, 0x5903620E, 0xB6330917, 0x828FC2CD, 0x6DBFA9D4, 0x4BFC7D58, 0xA4CC1641, 0x9070DD9B, 0x7F40B682, 0xF9094A2F, 0x16392136, 0x2285EAEC, 0xCDB581F5, 0x2BFA6547, 0xC4CA0E5E, 0xF076C584, 0x1F46AE9D, 0x990F5230, 0x763F3929, 0x4283F2F3, 0xADB399EA, 0x1C08B7D6, 0xF338DCCF, 0xC7841715, 0x28B47C0C, 0xAEFD80A1, 0x41CDEBB8, 0x75712062, 0x9A414B7B, 0x7C0EAFC9, 0x933EC4D0, 0xA7820F0A, 0x48B26413, 0xCEFB98BE, 0x21CBF3A7, 0x1577387D, 0xFA475364, 0xDC0487E8, 0x3334ECF1, 0x0788272B, 0xE8B84C32, 0x6EF1B09F, 0x81C1DB86, 0xB57D105C, 0x5A4D7B45, 0xBC029FF7, 0x5332F4EE, 0x678E3F34, 0x88BE542D, 0x0EF7A880, 0xE1C7C399, 0xD57B0843, 0x3A4B635A, 0x99FCA15B, 0x76CCCA42, 0x42700198, 0xAD406A81, 0x2B09962C, 0xC439FD35, 0xF08536EF, 0x1FB55DF6, 0xF9FAB944, 0x16CAD25D, 0x22761987, 0xCD46729E, 0x4B0F8E33, 0xA43FE52A, 0x90832EF0, 0x7FB345E9, 0x59F09165, 0xB6C0FA7C, 0x827C31A6, 0x6D4C5ABF, 0xEB05A612, 0x0435CD0B, 0x308906D1, 0xDFB96DC8, 0x39F6897A, 0xD6C6E263, 0xE27A29B9, 0x0D4A42A0, 0x8B03BE0D, 0x6433D514, 0x508F1ECE, 0xBFBF75D7, 0x120CEC3D, 0xFD3C8724, 0xC9804CFE, 0x26B027E7, 0xA0F9DB4A, 0x4FC9B053, 0x7B757B89, 0x94451090, 0x720AF422, 0x9D3A9F3B, 0xA98654E1, 0x46B63FF8, 0xC0FFC355, 0x2FCFA84C, 0x1B736396, 0xF443088F, 0xD200DC03, 0x3D30B71A, 0x098C7CC0, 0xE6BC17D9, 0x60F5EB74, 0x8FC5806D, 0xBB794BB7, 0x544920AE, 0xB206C41C, 0x5D36AF05, 0x698A64DF, 0x86BA0FC6, 0x00F3F36B, 0xEFC39872, 0xDB7F53A8, 0x344F38B1, 0x97F8FAB0, 0x78C891A9, 0x4C745A73, 0xA344316A, 0x250DCDC7, 0xCA3DA6DE, 0xFE816D04, 0x11B1061D, 0xF7FEE2AF, 0x18CE89B6, 0x2C72426C, 0xC3422975, 0x450BD5D8, 0xAA3BBEC1, 0x9E87751B, 0x71B71E02, 0x57F4CA8E, 0xB8C4A197, 0x8C786A4D, 0x63480154, 0xE501FDF9, 0x0A3196E0, 0x3E8D5D3A, 0xD1BD3623, 0x37F2D291, 0xD8C2B988, 0xEC7E7252, 0x034E194B, 0x8507E5E6, 0x6A378EFF, 0x5E8B4525, 0xB1BB2E3C }; /* * end of the CRC lookup table crc_tableil8_o72 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o80[256] = { 0x00000000, 0x68032CC8, 0xD0065990, 0xB8057558, 0xA5E0C5D1, 0xCDE3E919, 0x75E69C41, 0x1DE5B089, 0x4E2DFD53, 0x262ED19B, 0x9E2BA4C3, 0xF628880B, 0xEBCD3882, 0x83CE144A, 0x3BCB6112, 0x53C84DDA, 0x9C5BFAA6, 0xF458D66E, 0x4C5DA336, 0x245E8FFE, 0x39BB3F77, 0x51B813BF, 0xE9BD66E7, 0x81BE4A2F, 0xD27607F5, 0xBA752B3D, 0x02705E65, 0x6A7372AD, 0x7796C224, 0x1F95EEEC, 0xA7909BB4, 0xCF93B77C, 0x3D5B83BD, 0x5558AF75, 0xED5DDA2D, 0x855EF6E5, 0x98BB466C, 0xF0B86AA4, 0x48BD1FFC, 0x20BE3334, 0x73767EEE, 0x1B755226, 0xA370277E, 0xCB730BB6, 0xD696BB3F, 0xBE9597F7, 0x0690E2AF, 0x6E93CE67, 0xA100791B, 0xC90355D3, 0x7106208B, 0x19050C43, 0x04E0BCCA, 0x6CE39002, 0xD4E6E55A, 0xBCE5C992, 0xEF2D8448, 0x872EA880, 0x3F2BDDD8, 0x5728F110, 0x4ACD4199, 0x22CE6D51, 0x9ACB1809, 0xF2C834C1, 0x7AB7077A, 0x12B42BB2, 0xAAB15EEA, 0xC2B27222, 0xDF57C2AB, 0xB754EE63, 0x0F519B3B, 0x6752B7F3, 0x349AFA29, 0x5C99D6E1, 0xE49CA3B9, 0x8C9F8F71, 0x917A3FF8, 0xF9791330, 0x417C6668, 0x297F4AA0, 0xE6ECFDDC, 0x8EEFD114, 0x36EAA44C, 0x5EE98884, 0x430C380D, 0x2B0F14C5, 0x930A619D, 0xFB094D55, 0xA8C1008F, 0xC0C22C47, 0x78C7591F, 0x10C475D7, 0x0D21C55E, 0x6522E996, 0xDD279CCE, 0xB524B006, 0x47EC84C7, 0x2FEFA80F, 0x97EADD57, 0xFFE9F19F, 0xE20C4116, 0x8A0F6DDE, 0x320A1886, 0x5A09344E, 0x09C17994, 0x61C2555C, 0xD9C72004, 0xB1C40CCC, 0xAC21BC45, 0xC422908D, 0x7C27E5D5, 0x1424C91D, 0xDBB77E61, 0xB3B452A9, 0x0BB127F1, 0x63B20B39, 0x7E57BBB0, 0x16549778, 0xAE51E220, 0xC652CEE8, 0x959A8332, 0xFD99AFFA, 0x459CDAA2, 0x2D9FF66A, 0x307A46E3, 0x58796A2B, 0xE07C1F73, 0x887F33BB, 0xF56E0EF4, 0x9D6D223C, 0x25685764, 0x4D6B7BAC, 0x508ECB25, 0x388DE7ED, 0x808892B5, 0xE88BBE7D, 0xBB43F3A7, 0xD340DF6F, 0x6B45AA37, 0x034686FF, 0x1EA33676, 0x76A01ABE, 0xCEA56FE6, 0xA6A6432E, 0x6935F452, 0x0136D89A, 0xB933ADC2, 0xD130810A, 0xCCD53183, 0xA4D61D4B, 0x1CD36813, 0x74D044DB, 0x27180901, 0x4F1B25C9, 0xF71E5091, 0x9F1D7C59, 0x82F8CCD0, 0xEAFBE018, 0x52FE9540, 0x3AFDB988, 0xC8358D49, 0xA036A181, 0x1833D4D9, 0x7030F811, 0x6DD54898, 0x05D66450, 0xBDD31108, 0xD5D03DC0, 0x8618701A, 0xEE1B5CD2, 0x561E298A, 0x3E1D0542, 0x23F8B5CB, 0x4BFB9903, 0xF3FEEC5B, 0x9BFDC093, 0x546E77EF, 0x3C6D5B27, 0x84682E7F, 0xEC6B02B7, 0xF18EB23E, 0x998D9EF6, 0x2188EBAE, 0x498BC766, 0x1A438ABC, 0x7240A674, 0xCA45D32C, 0xA246FFE4, 0xBFA34F6D, 0xD7A063A5, 0x6FA516FD, 0x07A63A35, 0x8FD9098E, 0xE7DA2546, 0x5FDF501E, 0x37DC7CD6, 0x2A39CC5F, 0x423AE097, 0xFA3F95CF, 0x923CB907, 0xC1F4F4DD, 0xA9F7D815, 0x11F2AD4D, 0x79F18185, 0x6414310C, 0x0C171DC4, 0xB412689C, 0xDC114454, 0x1382F328, 0x7B81DFE0, 0xC384AAB8, 0xAB878670, 0xB66236F9, 0xDE611A31, 0x66646F69, 0x0E6743A1, 0x5DAF0E7B, 0x35AC22B3, 0x8DA957EB, 0xE5AA7B23, 0xF84FCBAA, 0x904CE762, 0x2849923A, 0x404ABEF2, 0xB2828A33, 0xDA81A6FB, 0x6284D3A3, 0x0A87FF6B, 0x17624FE2, 0x7F61632A, 0xC7641672, 0xAF673ABA, 0xFCAF7760, 0x94AC5BA8, 0x2CA92EF0, 0x44AA0238, 0x594FB2B1, 0x314C9E79, 0x8949EB21, 0xE14AC7E9, 0x2ED97095, 0x46DA5C5D, 0xFEDF2905, 0x96DC05CD, 0x8B39B544, 0xE33A998C, 0x5B3FECD4, 0x333CC01C, 0x60F48DC6, 0x08F7A10E, 0xB0F2D456, 0xD8F1F89E, 0xC5144817, 0xAD1764DF, 0x15121187, 0x7D113D4F }; /* * end of the CRC lookup table crc_tableil8_o80 */ /* * The following CRC lookup table was generated automagically using the * following model parameters: * * Generator Polynomial = ................. 0x1EDC6F41 * Generator Polynomial Length = .......... 32 bits * Reflected Bits = ....................... TRUE * Table Generation Offset = .............. 32 bits * Number of Slices = ..................... 8 slices * Slice Lengths = ........................ 8 8 8 8 8 8 8 8 * Directory Name = ....................... .\ * File Name = ............................ 8x256_tables.c */ static const uint32_t sctp_crc_tableil8_o88[256] = { 0x00000000, 0x493C7D27, 0x9278FA4E, 0xDB448769, 0x211D826D, 0x6821FF4A, 0xB3657823, 0xFA590504, 0x423B04DA, 0x0B0779FD, 0xD043FE94, 0x997F83B3, 0x632686B7, 0x2A1AFB90, 0xF15E7CF9, 0xB86201DE, 0x847609B4, 0xCD4A7493, 0x160EF3FA, 0x5F328EDD, 0xA56B8BD9, 0xEC57F6FE, 0x37137197, 0x7E2F0CB0, 0xC64D0D6E, 0x8F717049, 0x5435F720, 0x1D098A07, 0xE7508F03, 0xAE6CF224, 0x7528754D, 0x3C14086A, 0x0D006599, 0x443C18BE, 0x9F789FD7, 0xD644E2F0, 0x2C1DE7F4, 0x65219AD3, 0xBE651DBA, 0xF759609D, 0x4F3B6143, 0x06071C64, 0xDD439B0D, 0x947FE62A, 0x6E26E32E, 0x271A9E09, 0xFC5E1960, 0xB5626447, 0x89766C2D, 0xC04A110A, 0x1B0E9663, 0x5232EB44, 0xA86BEE40, 0xE1579367, 0x3A13140E, 0x732F6929, 0xCB4D68F7, 0x827115D0, 0x593592B9, 0x1009EF9E, 0xEA50EA9A, 0xA36C97BD, 0x782810D4, 0x31146DF3, 0x1A00CB32, 0x533CB615, 0x8878317C, 0xC1444C5B, 0x3B1D495F, 0x72213478, 0xA965B311, 0xE059CE36, 0x583BCFE8, 0x1107B2CF, 0xCA4335A6, 0x837F4881, 0x79264D85, 0x301A30A2, 0xEB5EB7CB, 0xA262CAEC, 0x9E76C286, 0xD74ABFA1, 0x0C0E38C8, 0x453245EF, 0xBF6B40EB, 0xF6573DCC, 0x2D13BAA5, 0x642FC782, 0xDC4DC65C, 0x9571BB7B, 0x4E353C12, 0x07094135, 0xFD504431, 0xB46C3916, 0x6F28BE7F, 0x2614C358, 0x1700AEAB, 0x5E3CD38C, 0x857854E5, 0xCC4429C2, 0x361D2CC6, 0x7F2151E1, 0xA465D688, 0xED59ABAF, 0x553BAA71, 0x1C07D756, 0xC743503F, 0x8E7F2D18, 0x7426281C, 0x3D1A553B, 0xE65ED252, 0xAF62AF75, 0x9376A71F, 0xDA4ADA38, 0x010E5D51, 0x48322076, 0xB26B2572, 0xFB575855, 0x2013DF3C, 0x692FA21B, 0xD14DA3C5, 0x9871DEE2, 0x4335598B, 0x0A0924AC, 0xF05021A8, 0xB96C5C8F, 0x6228DBE6, 0x2B14A6C1, 0x34019664, 0x7D3DEB43, 0xA6796C2A, 0xEF45110D, 0x151C1409, 0x5C20692E, 0x8764EE47, 0xCE589360, 0x763A92BE, 0x3F06EF99, 0xE44268F0, 0xAD7E15D7, 0x572710D3, 0x1E1B6DF4, 0xC55FEA9D, 0x8C6397BA, 0xB0779FD0, 0xF94BE2F7, 0x220F659E, 0x6B3318B9, 0x916A1DBD, 0xD856609A, 0x0312E7F3, 0x4A2E9AD4, 0xF24C9B0A, 0xBB70E62D, 0x60346144, 0x29081C63, 0xD3511967, 0x9A6D6440, 0x4129E329, 0x08159E0E, 0x3901F3FD, 0x703D8EDA, 0xAB7909B3, 0xE2457494, 0x181C7190, 0x51200CB7, 0x8A648BDE, 0xC358F6F9, 0x7B3AF727, 0x32068A00, 0xE9420D69, 0xA07E704E, 0x5A27754A, 0x131B086D, 0xC85F8F04, 0x8163F223, 0xBD77FA49, 0xF44B876E, 0x2F0F0007, 0x66337D20, 0x9C6A7824, 0xD5560503, 0x0E12826A, 0x472EFF4D, 0xFF4CFE93, 0xB67083B4, 0x6D3404DD, 0x240879FA, 0xDE517CFE, 0x976D01D9, 0x4C2986B0, 0x0515FB97, 0x2E015D56, 0x673D2071, 0xBC79A718, 0xF545DA3F, 0x0F1CDF3B, 0x4620A21C, 0x9D642575, 0xD4585852, 0x6C3A598C, 0x250624AB, 0xFE42A3C2, 0xB77EDEE5, 0x4D27DBE1, 0x041BA6C6, 0xDF5F21AF, 0x96635C88, 0xAA7754E2, 0xE34B29C5, 0x380FAEAC, 0x7133D38B, 0x8B6AD68F, 0xC256ABA8, 0x19122CC1, 0x502E51E6, 0xE84C5038, 0xA1702D1F, 0x7A34AA76, 0x3308D751, 0xC951D255, 0x806DAF72, 0x5B29281B, 0x1215553C, 0x230138CF, 0x6A3D45E8, 0xB179C281, 0xF845BFA6, 0x021CBAA2, 0x4B20C785, 0x906440EC, 0xD9583DCB, 0x613A3C15, 0x28064132, 0xF342C65B, 0xBA7EBB7C, 0x4027BE78, 0x091BC35F, 0xD25F4436, 0x9B633911, 0xA777317B, 0xEE4B4C5C, 0x350FCB35, 0x7C33B612, 0x866AB316, 0xCF56CE31, 0x14124958, 0x5D2E347F, 0xE54C35A1, 0xAC704886, 0x7734CFEF, 0x3E08B2C8, 0xC451B7CC, 0x8D6DCAEB, 0x56294D82, 0x1F1530A5 }; /* * end of the CRC lookup table crc_tableil8_o88 */ static uint32_t crc32c_sb8_64_bit(uint32_t crc, const unsigned char *p_buf, uint32_t length, uint32_t init_bytes) { uint32_t li; uint32_t term1, term2; uint32_t running_length; uint32_t end_bytes; running_length = ((length - init_bytes) / 8) * 8; end_bytes = length - init_bytes - running_length; for (li = 0; li < init_bytes; li++) crc = sctp_crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8); for (li = 0; li < running_length / 8; li++) { #if BYTE_ORDER == BIG_ENDIAN crc ^= *p_buf++; crc ^= (*p_buf++) << 8; crc ^= (*p_buf++) << 16; crc ^= (*p_buf++) << 24; #else crc ^= *(const uint32_t *)p_buf; p_buf += 4; #endif term1 = sctp_crc_tableil8_o88[crc & 0x000000FF] ^ sctp_crc_tableil8_o80[(crc >> 8) & 0x000000FF]; term2 = crc >> 16; crc = term1 ^ sctp_crc_tableil8_o72[term2 & 0x000000FF] ^ sctp_crc_tableil8_o64[(term2 >> 8) & 0x000000FF]; #if BYTE_ORDER == BIG_ENDIAN crc ^= sctp_crc_tableil8_o56[*p_buf++]; crc ^= sctp_crc_tableil8_o48[*p_buf++]; crc ^= sctp_crc_tableil8_o40[*p_buf++]; crc ^= sctp_crc_tableil8_o32[*p_buf++]; #else term1 = sctp_crc_tableil8_o56[(*(const uint32_t *)p_buf) & 0x000000FF] ^ sctp_crc_tableil8_o48[((*(const uint32_t *)p_buf) >> 8) & 0x000000FF]; term2 = (*(const uint32_t *)p_buf) >> 16; crc = crc ^ term1 ^ sctp_crc_tableil8_o40[term2 & 0x000000FF] ^ sctp_crc_tableil8_o32[(term2 >> 8) & 0x000000FF]; p_buf += 4; #endif } for (li = 0; li < end_bytes; li++) crc = sctp_crc_tableil8_o32[(crc ^ *p_buf++) & 0x000000FF] ^ (crc >> 8); return crc; } static uint32_t multitable_crc32c(uint32_t crc32c, const unsigned char *buffer, unsigned int length) { uint32_t to_even_word; if (length == 0) return (crc32c); to_even_word = (4 - (((uintptr_t) buffer) & 0x3)); return (crc32c_sb8_64_bit(crc32c, buffer, length, to_even_word)); } uint32_t calculate_crc32c(uint32_t crc32c, const unsigned char *buffer, unsigned int length) { if (length < 4) return (singletable_crc32c(crc32c, buffer, length)); else return (multitable_crc32c(crc32c, buffer, length)); } ntirpc-1.3.1/src/rpc_ctx.c000066400000000000000000000160541261345040100154120ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #if !defined(_WIN32) #include #endif #include #include #include #include #include #include #include #include #include "rpc_com.h" #include #include "clnt_internal.h" #include "rpc_dplx_internal.h" #include "rpc_ctx.h" #define tv_to_ms(tv) (1000 * ((tv)->tv_sec) + (tv)->tv_usec/1000) rpc_ctx_t * alloc_rpc_call_ctx(CLIENT *clnt, rpcproc_t proc, xdrproc_t xdr_args, void *args_ptr, xdrproc_t xdr_results, void *results_ptr, struct timeval timeout) { struct x_vc_data *xd = (struct x_vc_data *)clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; rpc_ctx_t *ctx; ctx = mem_alloc(sizeof(rpc_ctx_t)); if (!ctx) goto out; /* potects this */ mutex_init(&ctx->we.mtx, NULL); cond_init(&ctx->we.cv, 0, NULL); /* rec->calls and rbtree protected by (adaptive) mtx */ REC_LOCK(rec); /* XXX we hold the client-fd lock */ ctx->xid = ++(xd->cx.calls.xid); /* some of this looks like overkill; it's here to support future, * fully async calls */ ctx->ctx_u.clnt.clnt = clnt; ctx->ctx_u.clnt.timeout.tv_sec = 0; ctx->ctx_u.clnt.timeout.tv_nsec = 0; timespec_addms(&ctx->ctx_u.clnt.timeout, tv_to_ms(&timeout)); ctx->msg = alloc_rpc_msg(); ctx->flags = 0; /* stash it */ if (opr_rbtree_insert(&xd->cx.calls.t, &ctx->node_k)) { __warnx(TIRPC_DEBUG_FLAG_RPC_CTX, "%s: call ctx insert failed (xid %d client %p)", __func__, ctx->xid, clnt); REC_UNLOCK(rec); mutex_destroy(&ctx->we.mtx); cond_destroy(&ctx->we.cv); mem_free(ctx, sizeof(rpc_ctx_t)); ctx = NULL; goto out; } REC_UNLOCK(rec); out: return (ctx); } void rpc_ctx_next_xid(rpc_ctx_t *ctx, uint32_t flags) { struct x_vc_data *xd = (struct x_vc_data *)ctx->ctx_u.clnt.clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; assert(flags & RPC_CTX_FLAG_LOCKED); REC_LOCK(rec); opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k); ctx->xid = ++(xd->cx.calls.xid); if (opr_rbtree_insert(&xd->cx.calls.t, &ctx->node_k)) { REC_UNLOCK(rec); __warnx(TIRPC_DEBUG_FLAG_RPC_CTX, "%s: call ctx insert failed (xid %d client %p)", __func__, ctx->xid, ctx->ctx_u.clnt.clnt); goto out; } REC_UNLOCK(rec); out: return; } bool rpc_ctx_xfer_replymsg(struct x_vc_data *xd, struct rpc_msg *msg) { rpc_ctx_t ctx_k, *ctx; struct opr_rbtree_node *nv; rpc_dplx_lock_t *lk = &xd->rec->recv.lock; ctx_k.xid = msg->rm_xid; REC_LOCK(xd->rec); nv = opr_rbtree_lookup(&xd->cx.calls.t, &ctx_k.node_k); if (nv) { ctx = opr_containerof(nv, rpc_ctx_t, node_k); opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k); free_rpc_msg(ctx->msg); /* free call header */ ctx->msg = msg; /* and stash reply header */ ctx->flags |= RPC_CTX_FLAG_SYNCDONE; REC_UNLOCK(xd->rec); cond_signal(&lk->we.cv); /* XXX we hold lk->we.mtx */ /* now, we must ourselves wait for the other side to run */ while (!(ctx->flags & RPC_CTX_FLAG_ACKSYNC)) cond_wait(&lk->we.cv, &lk->we.mtx); /* ctx-specific signal--indicates we will make no further * references to ctx whatsoever */ mutex_lock(&ctx->we.mtx); ctx->flags &= ~RPC_CTX_FLAG_WAITSYNC; cond_signal(&ctx->we.cv); mutex_unlock(&ctx->we.mtx); return (true); } REC_UNLOCK(xd->rec); return (false); } int rpc_ctx_wait_reply(rpc_ctx_t *ctx, uint32_t flags) { struct x_vc_data *xd = (struct x_vc_data *)ctx->ctx_u.clnt.clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; rpc_dplx_lock_t *lk = &rec->recv.lock; struct timespec ts; int code = 0; /* we hold recv channel lock */ ctx->flags |= RPC_CTX_FLAG_WAITSYNC; while (!(ctx->flags & RPC_CTX_FLAG_SYNCDONE)) { (void)clock_gettime(CLOCK_REALTIME_FAST, &ts); timespecadd(&ts, &ctx->ctx_u.clnt.timeout); code = cond_timedwait(&lk->we.cv, &lk->we.mtx, &ts); /* if we timed out, check for xprt destroyed (no more * receives) */ if (code == ETIMEDOUT) { SVCXPRT *xprt = rec->hdl.xprt; uint32_t xp_flags; /* dequeue the call */ REC_LOCK(rec); opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k); REC_UNLOCK(rec); mutex_lock(&xprt->xp_lock); xp_flags = xprt->xp_flags; mutex_unlock(&xprt->xp_lock); if (xp_flags & SVC_XPRT_FLAG_DESTROYED) { /* XXX should also set error.re_why, but the * facility is not well developed. */ ctx->error.re_status = RPC_TIMEDOUT; } ctx->flags &= ~RPC_CTX_FLAG_WAITSYNC; goto out; } } ctx->flags &= ~RPC_CTX_FLAG_SYNCDONE; /* switch on direction */ switch (ctx->msg->rm_direction) { case REPLY: if (ctx->msg->rm_xid == ctx->xid) return (RPC_SUCCESS); break; case CALL: /* XXX cond transfer control to svc */ /* */ break; default: break; } out: return (code); } void rpc_ctx_ack_xfer(rpc_ctx_t *ctx) { struct x_vc_data *xd = (struct x_vc_data *)ctx->ctx_u.clnt.clnt->cl_p1; rpc_dplx_lock_t *lk = &xd->rec->recv.lock; ctx->flags |= RPC_CTX_FLAG_ACKSYNC; cond_signal(&lk->we.cv); /* XXX we hold lk->we.mtx */ } void free_rpc_call_ctx(rpc_ctx_t *ctx, uint32_t flags) { struct x_vc_data *xd = (struct x_vc_data *)ctx->ctx_u.clnt.clnt->cl_p1; struct rpc_dplx_rec *rec = xd->rec; struct timespec ts; /* wait for commit of any xfer (ctx specific) */ mutex_lock(&ctx->we.mtx); if (ctx->flags & RPC_CTX_FLAG_WAITSYNC) { /* WAITSYNC is already cleared if the call timed out, but it is * incorrect to wait forever */ (void)clock_gettime(CLOCK_REALTIME_FAST, &ts); timespecadd(&ts, &ctx->ctx_u.clnt.timeout); (void)cond_timedwait(&ctx->we.cv, &ctx->we.mtx, &ts); } REC_LOCK(rec); opr_rbtree_remove(&xd->cx.calls.t, &ctx->node_k); /* interlock */ mutex_unlock(&ctx->we.mtx); REC_UNLOCK(rec); if (ctx->msg) free_rpc_msg(ctx->msg); mutex_destroy(&ctx->we.mtx); cond_destroy(&ctx->we.cv); mem_free(ctx, sizeof(rpc_ctx_t)); } ntirpc-1.3.1/src/rpc_ctx.h000066400000000000000000000036401261345040100154140ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TIRPC_RPC_CTX_H #define TIRPC_RPC_CTX_H #define RPC_CTX_FLAG_NONE 0x0000 #define RPC_CTX_FLAG_LOCKED 0x0001 #define RPC_CTX_FLAG_WAITSYNC 0x0002 #define RPC_CTX_FLAG_SYNCDONE 0x0004 #define RPC_CTX_FLAG_ACKSYNC 0x0008 rpc_ctx_t *alloc_rpc_call_ctx(CLIENT *, rpcproc_t, xdrproc_t, void *, xdrproc_t, void *, struct timeval); void rpc_ctx_next_xid(rpc_ctx_t *, uint32_t); int rpc_ctx_wait_reply(rpc_ctx_t *, uint32_t); bool rpc_ctx_xfer_replymsg(struct x_vc_data *, struct rpc_msg *); void rpc_ctx_ack_xfer(rpc_ctx_t *); void free_rpc_call_ctx(rpc_ctx_t *, uint32_t); #endif /* TIRPC_RPC_CTX_H */ ntirpc-1.3.1/src/rpc_dplx.c000066400000000000000000000240201261345040100155530ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include #ifdef PORTMAP #include #endif /* PORTMAP */ #include "rpc_com.h" #include #include #include "clnt_internal.h" #include "rpc_dplx_internal.h" /* public */ void rpc_dplx_slxi(SVCXPRT *xprt, const char *func, int line) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)xprt->xp_p5; rpc_dplx_lock_t *lk = &rec->send.lock; mutex_lock(&lk->we.mtx); if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_LOCK) { lk->locktrace.func = (char *)func; lk->locktrace.line = line; } } void rpc_dplx_sux(SVCXPRT *xprt) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)xprt->xp_p5; mutex_unlock(&rec->send.lock.we.mtx); } void rpc_dplx_rlxi(SVCXPRT *xprt, const char *func, int line) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)xprt->xp_p5; rpc_dplx_lock_t *lk = &rec->recv.lock; mutex_lock(&lk->we.mtx); if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_LOCK) { lk->locktrace.func = (char *)func; lk->locktrace.line = line; } } void rpc_dplx_rux(SVCXPRT *xprt) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)xprt->xp_p5; mutex_unlock(&rec->recv.lock.we.mtx); } void rpc_dplx_slci(CLIENT *clnt, const char *func, int line) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; rpc_dplx_lock_t *lk = &rec->send.lock; mutex_lock(&lk->we.mtx); if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_LOCK) { lk->locktrace.func = (char *)func; lk->locktrace.line = line; } } void rpc_dplx_suc(CLIENT *clnt) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; mutex_unlock(&rec->send.lock.we.mtx); } void rpc_dplx_rlci(CLIENT *clnt, const char *func, int line) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; rpc_dplx_lock_t *lk = &rec->recv.lock; mutex_lock(&lk->we.mtx); if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_LOCK) { lk->locktrace.func = (char *)func; lk->locktrace.line = line; } } void rpc_dplx_ruc(CLIENT *clnt) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; mutex_unlock(&rec->recv.lock.we.mtx); } /* private */ #define RPC_DPLX_PARTITIONS 17 static bool initialized = false; static struct rpc_dplx_rec_set rpc_dplx_rec_set = { MUTEX_INITIALIZER, /* clnt_fd_lock */ { 0, /* npart */ RBT_X_FLAG_NONE /* flags */ , 0, /* cachesz */ NULL /* tree */ } /* xt */ }; static inline int rpc_dplx_cmpf(const struct opr_rbtree_node *lhs, const struct opr_rbtree_node *rhs) { struct rpc_dplx_rec *lk, *rk; lk = opr_containerof(lhs, struct rpc_dplx_rec, node_k); rk = opr_containerof(rhs, struct rpc_dplx_rec, node_k); if (lk->fd_k < rk->fd_k) return (-1); if (lk->fd_k == rk->fd_k) return (0); return (1); } void rpc_dplx_init() { int code = 0; /* XXX */ mutex_lock(&rpc_dplx_rec_set.clnt_fd_lock); if (initialized) goto unlock; /* one of advantages of this RBT is convenience of external * iteration, we'll go to that shortly */ code = rbtx_init(&rpc_dplx_rec_set.xt, rpc_dplx_cmpf /* NULL (inline) */ , RPC_DPLX_PARTITIONS, RBT_X_FLAG_ALLOC); if (code) __warnx(TIRPC_DEBUG_FLAG_LOCK, "rpc_dplx_init: rbtx_init failed"); initialized = true; unlock: mutex_unlock(&rpc_dplx_rec_set.clnt_fd_lock); } #define cond_init_rpc_dplx() { \ do { \ if (!initialized) \ rpc_dplx_init(); \ } while (0); \ } /* CLNT/SVCXPRT structures keep a reference to their associated rpc_dplx_rec * structures in private data. this way we can make the lock/unlock ops * inline, and the amortized cost of this change for locks is 0. */ static inline struct rpc_dplx_rec * alloc_dplx_rec(void) { struct rpc_dplx_rec *rec = mem_alloc(sizeof(struct rpc_dplx_rec)); if (rec) { rec->refcnt = 0; rec->hdl.xprt = NULL; mutex_init(&rec->locktrace.mtx, NULL); /* send channel */ rpc_dplx_lock_init(&rec->send.lock); /* recv channel */ rpc_dplx_lock_init(&rec->recv.lock); } return (rec); } static inline void free_dplx_rec(struct rpc_dplx_rec *rec) { mutex_destroy(&rec->locktrace.mtx); rpc_dplx_lock_destroy(&rec->send.lock); rpc_dplx_lock_destroy(&rec->recv.lock); mem_free(rec, sizeof(struct rpc_dplx_rec)); } struct rpc_dplx_rec * rpc_dplx_lookup_rec(int fd, uint32_t iflags, uint32_t *oflags) { struct rbtree_x_part *t; struct rpc_dplx_rec rk, *rec = NULL; struct opr_rbtree_node *nv; cond_init_rpc_dplx(); rk.fd_k = fd; t = rbtx_partition_of_scalar(&(rpc_dplx_rec_set.xt), fd); rwlock_rdlock(&t->lock); nv = opr_rbtree_lookup(&t->t, &rk.node_k); /* XXX rework lock+insert case, so that new entries are inserted * locked, and t->lock critical section is reduced */ if (!nv) { rwlock_unlock(&t->lock); rwlock_wrlock(&t->lock); nv = opr_rbtree_lookup(&t->t, &rk.node_k); if (!nv) { rec = alloc_dplx_rec(); if (!rec) { __warnx(TIRPC_DEBUG_FLAG_LOCK, "%s: failed allocating rpc_dplx_rec", __func__); goto unlock; } /* tell the caller */ *oflags = RPC_DPLX_LKP_OFLAG_ALLOC; rec->fd_k = fd; if (opr_rbtree_insert(&t->t, &rec->node_k)) { /* cant happen */ __warnx(TIRPC_DEBUG_FLAG_LOCK, "%s: collision inserting in locked rbtree partition", __func__); free_dplx_rec(rec); rec = NULL; goto unlock; } } else { /* raced */ rec = opr_containerof(nv, struct rpc_dplx_rec, node_k); *oflags = RPC_DPLX_LKP_FLAG_NONE; } } else { rec = opr_containerof(nv, struct rpc_dplx_rec, node_k); *oflags = RPC_DPLX_LKP_FLAG_NONE; } rpc_dplx_ref(rec, (iflags & RPC_DPLX_LKP_IFLAG_LOCKREC) ? RPC_DPLX_FLAG_LOCK : RPC_DPLX_FLAG_NONE); unlock: rwlock_unlock(&t->lock); return (rec); } void rpc_dplx_slfi(int fd, const char *func, int line) { uint32_t oflags; struct rpc_dplx_rec *rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_FLAG_NONE, &oflags); rpc_dplx_lock_t *lk = &rec->send.lock; mutex_lock(&lk->we.mtx); if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_LOCK) { lk->locktrace.func = (char *)func; lk->locktrace.line = line; } } void rpc_dplx_suf(int fd) { uint32_t oflags; struct rpc_dplx_rec *rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_FLAG_NONE, &oflags); /* assert: initialized */ mutex_unlock(&rec->send.lock.we.mtx); } void rpc_dplx_rlfi(int fd, const char *func, int line) { uint32_t oflags; struct rpc_dplx_rec *rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_FLAG_NONE, &oflags); rpc_dplx_lock_t *lk = &rec->recv.lock; mutex_lock(&lk->we.mtx); if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_LOCK) { lk->locktrace.func = (char *)func; lk->locktrace.line = line; } } void rpc_dplx_ruf(int fd) { uint32_t oflags; struct rpc_dplx_rec *rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_FLAG_NONE, &oflags); /* assert: initialized */ mutex_unlock(&rec->recv.lock.we.mtx); } int32_t rpc_dplx_unref(struct rpc_dplx_rec *rec, u_int flags) { struct rbtree_x_part *t; struct opr_rbtree_node *nv; int32_t refcnt; if (!(flags & RPC_DPLX_FLAG_LOCKED)) REC_LOCK(rec); refcnt = --(rec->refcnt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: postunref %p rec->refcnt %u", __func__, rec, refcnt); if (rec->refcnt == 0) { t = rbtx_partition_of_scalar(&rpc_dplx_rec_set.xt, rec->fd_k); REC_UNLOCK(rec); rwlock_wrlock(&t->lock); nv = opr_rbtree_lookup(&t->t, &rec->node_k); rec = NULL; if (nv) { rec = opr_containerof(nv, struct rpc_dplx_rec, node_k); REC_LOCK(rec); if (rec->refcnt == 0) { (void)opr_rbtree_remove(&t->t, &rec->node_k); REC_UNLOCK(rec); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: free rec %p rec->refcnt %u", __func__, rec, refcnt); free_dplx_rec(rec); rec = NULL; } else { refcnt = rec->refcnt; } } rwlock_unlock(&t->lock); } if (rec) { if ((!(flags & RPC_DPLX_FLAG_LOCKED)) || (flags & RPC_DPLX_FLAG_UNLOCK)) REC_UNLOCK(rec); } return (refcnt); } void rpc_dplx_shutdown() { struct rbtree_x_part *t = NULL; struct opr_rbtree_node *n; struct rpc_dplx_rec *rec = NULL; int p_ix; cond_init_rpc_dplx(); /* concurrent, restartable iteration over t */ p_ix = 0; while (p_ix < RPC_DPLX_PARTITIONS) { t = &rpc_dplx_rec_set.xt.tree[p_ix]; rwlock_wrlock(&t->lock); /* t WLOCKED */ n = opr_rbtree_first(&t->t); while (n != NULL) { rec = opr_containerof(n, struct rpc_dplx_rec, node_k); opr_rbtree_remove(&t->t, &rec->node_k); free_dplx_rec(rec); n = opr_rbtree_first(&t->t); } /* curr partition */ rwlock_unlock(&t->lock); /* t !LOCKED */ rwlock_destroy(&t->lock); p_ix++; } /* RPC_DPLX_PARTITIONS */ /* free tree */ mem_free(rpc_dplx_rec_set.xt.tree, RPC_DPLX_PARTITIONS * sizeof(struct rbtree_x_part)); /* set initialized = false? */ } ntirpc-1.3.1/src/rpc_dplx_internal.h000066400000000000000000000134361261345040100174650ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef RPC_DPLX_INTERNAL_H #define RPC_DPLX_INTERNAL_H #include struct rpc_dplx_rec; /* in clnt_internal.h (avoids circular dependency) */ struct rpc_dplx_rec_set { mutex_t clnt_fd_lock; /* XXX check dplx correctness */ struct rbtree_x xt; }; /* XXX perhaps better off as a flag bit (until we can remove it) */ #define rpc_flag_clear 0 #define rpc_lock_value 1 enum rpc_duplex_callpath { RPC_DPLX_CLNT = 1, RPC_DPLX_SVC }; #define RPC_DPLX_FLAG_NONE 0x0000 #define RPC_DPLX_FLAG_LOCKED 0x0001 #define RPC_DPLX_FLAG_LOCK 0x0002 #define RPC_DPLX_FLAG_LOCKREC 0x0004 #define RPC_DPLX_FLAG_RECLOCKED 0x0008 #define RPC_DPLX_FLAG_UNLOCK 0x0010 #ifndef HAVE_STRLCAT extern size_t strlcat(char *, const char *, size_t); #endif #ifndef HAVE_STRLCPY extern size_t strlcpy(char *, const char *src, size_t); #endif #define RPC_DPLX_LKP_FLAG_NONE 0x0000 #define RPC_DPLX_LKP_IFLAG_LOCKREC 0x0001 #define RPC_DPLX_LKP_OFLAG_ALLOC 0x0002 struct rpc_dplx_rec *rpc_dplx_lookup_rec(int, uint32_t, uint32_t *); static inline void rpc_dplx_lock_init(struct rpc_dplx_lock *lock) { lock->lock_flag_value = 0; mutex_init(&lock->we.mtx, NULL); cond_init(&lock->we.cv, 0, NULL); } static inline void rpc_dplx_lock_destroy(struct rpc_dplx_lock *lock) { mutex_destroy(&lock->we.mtx); cond_destroy(&lock->we.cv); } static inline int32_t rpc_dplx_ref(struct rpc_dplx_rec *rec, u_int flags) { int32_t refcnt; if (!(flags & RPC_DPLX_FLAG_LOCKED)) REC_LOCK(rec); refcnt = ++(rec->refcnt); /* release rec lock only if a) we took it and b) caller doesn't * want it returned locked */ if ((!(flags & RPC_DPLX_FLAG_LOCKED)) && (!(flags & RPC_DPLX_FLAG_LOCK))) REC_UNLOCK(rec); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: rec %p rec->refcnt %u", __func__, rec, refcnt); return (refcnt); } int32_t rpc_dplx_unref(struct rpc_dplx_rec *rec, u_int flags); /* swi: send wait impl */ static inline void rpc_dplx_swi(struct rpc_dplx_rec *rec, uint32_t wait_for) { rpc_dplx_lock_t *lk = &rec->send.lock; mutex_lock(&lk->we.mtx); while (lk->lock_flag_value != rpc_flag_clear) cond_wait(&lk->we.cv, &lk->we.mtx); mutex_unlock(&lk->we.mtx); } /* swc: send wait clnt */ static inline void rpc_dplx_swc(CLIENT *clnt, uint32_t wait_for) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; rpc_dplx_swi(rec, wait_for); } /* rwi: recv wait impl */ static inline void rpc_dplx_rwi(struct rpc_dplx_rec *rec, uint32_t wait_for) { rpc_dplx_lock_t *lk = &rec->recv.lock; mutex_lock(&lk->we.mtx); while (lk->lock_flag_value != rpc_flag_clear) cond_wait(&lk->we.cv, &lk->we.mtx); mutex_unlock(&lk->we.mtx); } /* rwc: recv wait clnt */ static inline void rpc_dplx_rwc(CLIENT *clnt, uint32_t wait_for) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; rpc_dplx_rwi(rec, wait_for); } /* ssi: send signal impl */ static inline void rpc_dplx_ssi(struct rpc_dplx_rec *rec, uint32_t flags) { rpc_dplx_lock_t *lk = &rec->send.lock; if (flags & RPC_DPLX_FLAG_LOCK) mutex_lock(&lk->we.mtx); cond_signal(&lk->we.cv); if (flags & RPC_DPLX_FLAG_LOCK) mutex_unlock(&lk->we.mtx); } /* ssc: send signal clnt */ static inline void rpc_dplx_ssc(CLIENT *clnt, uint32_t flags) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; rpc_dplx_ssi(rec, flags); } /* swf: send wait fd */ #define rpc_dplx_swf(fd, wait_for) \ do { \ struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \ rpc_dplx_swi(rec, wait_for); \ } while (0) /* rsi: recv signal impl */ static inline void rpc_dplx_rsi(struct rpc_dplx_rec *rec, uint32_t flags) { rpc_dplx_lock_t *lk = &rec->recv.lock; if (flags & RPC_DPLX_FLAG_LOCK) mutex_lock(&lk->we.mtx); cond_signal(&lk->we.cv); if (flags & RPC_DPLX_FLAG_LOCK) mutex_unlock(&lk->we.mtx); } /* rsc: recv signal clnt */ static inline void rpc_dplx_rsc(CLIENT *clnt, uint32_t flags) { struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)clnt->cl_p2; rpc_dplx_rsi(rec, flags); } /* rwf: recv wait fd */ #define rpc_dplx_rwf(fd, wait_for) \ do { \ struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \ rpc_dplx_rwi(rec, wait_for); \ } while (0) /* ssf: send signal fd */ #define rpc_dplx_ssf(fd, flags) \ do { \ struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \ rpc_dplx_ssi(rec, flags); \ } while (0) /* rsf: send signal fd */ #define rpc_dplx_rsf(fd, flags) \ do { \ struct vc_fd_rec *rec = rpc_dplx_lookup_rec(fd); \ rpc_dplx_rsi(rec, flags); \ } while (0) void rpc_dplx_shutdown(void); #endif /* RPC_DPLX_INTERNAL_H */ ntirpc-1.3.1/src/rpc_dplx_msg.c000066400000000000000000000276261261345040100164400ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * rpc_dplx_msg.c * * Based upon/copied from: * rpc_callmsg.c * * Copyright (C) 1984, Sun Microsystems, Inc. * */ #include #include #include #include #include #include #include #include #include #include static const struct xdr_discrim reply_dscrm[3] = { {(int)MSG_ACCEPTED, (xdrproc_t) xdr_naccepted_reply}, {(int)MSG_DENIED, (xdrproc_t) xdr_nrejected_reply}, {__dontcare__, NULL_xdrproc_t} }; /* in glibc 2.14+ x86_64, memcpy no longer tries to handle overlapping areas, * see Fedora Bug 691336 (NOTABUG); we dont permit overlapping segments, * so memcpy may be a small win over memmove. */ /* * encode a reply message, log error messages */ bool xdr_reply_encode(XDR *xdrs, struct rpc_msg *dmsg) { struct opaque_auth *oa; int32_t *buf; switch (dmsg->rm_reply.rp_stat) { case MSG_ACCEPTED: { struct accepted_reply *ar = (struct accepted_reply *) &(dmsg->rm_reply.ru); oa = &ar->ar_verf; if (oa->oa_length > MAX_AUTH_BYTES) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_verf.oa_length (%u) > %u", __func__, __LINE__, oa->oa_length, MAX_AUTH_BYTES); return (false); } buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT + RNDUP(oa->oa_length)); if (buf != NULL) { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u ACCEPTED INLINE", __func__, __LINE__); IXDR_PUT_INT32(buf, dmsg->rm_xid); IXDR_PUT_ENUM(buf, dmsg->rm_direction); IXDR_PUT_ENUM(buf, dmsg->rm_reply.rp_stat); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_INT32(buf, oa->oa_length); if (oa->oa_length) { memcpy(buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } IXDR_PUT_ENUM(buf, ar->ar_stat); switch (ar->ar_stat) { case SUCCESS: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u SUCCESS", __func__, __LINE__); return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where)); case PROG_MISMATCH: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u MISMATCH", __func__, __LINE__); buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf != NULL) { IXDR_PUT_ENUM(buf, ar->ar_vers.low); IXDR_PUT_ENUM(buf, ar->ar_vers.high); } else if (!xdr_putuint32(xdrs, &(ar->ar_vers.low))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_vers.low %u", __func__, __LINE__, ar->ar_vers.low); return (false); } else if (!xdr_putuint32(xdrs, &(ar->ar_vers.high))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_vers.high %u", __func__, __LINE__, ar->ar_vers.high); return (false); } /* fallthru */ case GARBAGE_ARGS: case SYSTEM_ERR: case PROC_UNAVAIL: case PROG_UNAVAIL: break; }; return (true); } else { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u ACCEPTED non-INLINE", __func__, __LINE__); return (inline_xdr_union(xdrs, (enum_t *) &(dmsg->rm_reply.rp_stat), (caddr_t)(void *)&(dmsg->rm_reply.ru), reply_dscrm, NULL_xdrproc_t)); } /* never arrives here */ break; } case MSG_DENIED: { struct rejected_reply *rr = (struct rejected_reply *) &(dmsg->rm_reply.ru); switch (rr->rj_stat) { case RPC_MISMATCH: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u DENIED MISMATCH", __func__, __LINE__); buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT); if (buf != NULL) { IXDR_PUT_ENUM(buf, rr->rj_stat); IXDR_PUT_U_INT32(buf, rr->rj_vers.low); IXDR_PUT_U_INT32(buf, rr->rj_vers.high); } else if (!xdr_putenum(xdrs, rr->rj_stat)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_stat %u", __func__, __LINE__, rr->rj_stat); return (false); } else if (!xdr_putuint32(xdrs, &(rr->rj_vers.low))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_vers.low %u", __func__, __LINE__, rr->rj_vers.low); return (false); } else if (!xdr_putuint32(xdrs, &(rr->rj_vers.high))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_vers.high %u", __func__, __LINE__, rr->rj_vers.high); return (false); } return (true); /* bugfix */ case AUTH_ERROR: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u DENIED AUTH", __func__, __LINE__); buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT); if (buf != NULL) { IXDR_PUT_ENUM(buf, rr->rj_stat); IXDR_PUT_ENUM(buf, rr->rj_why); } else if (!xdr_putenum(xdrs, rr->rj_stat)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_stat %u", __func__, __LINE__, rr->rj_stat); return (false); } else if (!xdr_putenum(xdrs, rr->rj_why)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_why %u", __func__, __LINE__, rr->rj_why); return (false); } return (true); /* bugfix */ default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rr->rj_stat (%u)", __func__, __LINE__, rr->rj_stat); break; }; break; } default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR dmsg->rm_reply.rp_stat (%u)", __func__, __LINE__, dmsg->rm_reply.rp_stat); break; }; return (false); } /* XDR_ENCODE */ /* * decode a reply message * * param[IN] buf 3 more inline */ bool xdr_reply_decode(XDR *xdrs, struct rpc_msg *dmsg, int32_t *buf) { if (buf != NULL) { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u INLINE", __func__, __LINE__); dmsg->rm_reply.rp_stat = IXDR_GET_ENUM(buf, enum_t); } else { __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u non-INLINE", __func__, __LINE__); if (!xdr_getenum(xdrs, (enum_t *)&(dmsg->rm_reply.rp_stat))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_reply.rp_stat", __func__, __LINE__); return (false); } } switch (dmsg->rm_reply.rp_stat) { case MSG_ACCEPTED: { struct accepted_reply *ar = (struct accepted_reply *) &(dmsg->rm_reply.ru); if (!inline_auth_decode(xdrs, &ar->ar_verf, buf)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (false); } if (!xdr_getenum(xdrs, (enum_t *)&(ar->ar_stat))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_stat", __func__, __LINE__); return (false); } switch (ar->ar_stat) { case SUCCESS: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u SUCCESS", __func__, __LINE__); return ((*(ar->ar_results.proc))(xdrs, &(ar->ar_results.where))); case PROG_MISMATCH: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u MISMATCH", __func__, __LINE__); if (!xdr_getuint32(xdrs, &(ar->ar_vers.low))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_vers.low", __func__, __LINE__); return (false); } if (!xdr_getuint32(xdrs, &(ar->ar_vers.high))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR ar_vers.high", __func__, __LINE__); return (false); } case GARBAGE_ARGS: case SYSTEM_ERR: case PROC_UNAVAIL: case PROG_UNAVAIL: /* true */ break; default: break; }; /* ar_stat */ return (true); } /* MSG_ACCEPTED */ case MSG_DENIED: { /* XXX branch not verified */ struct rejected_reply *rr = (struct rejected_reply *) &(dmsg->rm_reply.ru); __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u MSG_DENIED not verified", __func__, __LINE__); if (buf != NULL) { rr->rj_stat = IXDR_GET_ENUM(buf, enum_t); } else if (!xdr_getenum(xdrs, (enum_t *)&(rr->rj_stat))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_stat", __func__, __LINE__); return (false); } switch (rr->rj_stat) { case RPC_MISMATCH: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u DENIED MISMATCH", __func__, __LINE__); if (buf != NULL) { rr->rj_vers.low = IXDR_GET_U_INT32(buf); } else if (!xdr_getuint32(xdrs, &(rr->rj_vers.low))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_vers.low", __func__, __LINE__); return (false); } if (!xdr_getuint32(xdrs, &(rr->rj_vers.high))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_vers.high", __func__, __LINE__); return (false); } break; case AUTH_ERROR: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u DENIED AUTH", __func__, __LINE__); if (buf != NULL) { rr->rj_why = IXDR_GET_ENUM(buf, enum_t); } else if (!xdr_getenum(xdrs, (enum_t *)&(rr->rj_why))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rj_why", __func__, __LINE__); return (false); } break; }; return (true); } /* MSG_DENIED */ default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR dmsg->rm_reply.rp_stat %u", __func__, __LINE__, dmsg->rm_reply.rp_stat); break; }; /* rm_reply.rp_stat */ return (false); } /* * decode a duplex message, log error messages */ bool xdr_dplx_decode(XDR *xdrs, struct rpc_msg *dmsg) { int32_t *buf; /* * NOTE: 5 here, 3 more in each _decode */ buf = XDR_INLINE(xdrs, 5 * BYTES_PER_XDR_UNIT); if (buf != NULL) { dmsg->rm_xid = IXDR_GET_U_INT32(buf); dmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type); } else { if (!xdr_getuint32(xdrs, &(dmsg->rm_xid))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_xid", __func__, __LINE__); return (false); } if (!xdr_getenum(xdrs, (enum_t *)&(dmsg->rm_direction))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR rm_direction", __func__, __LINE__); return (false); } } switch (dmsg->rm_direction) { case CALL: return (xdr_call_decode(xdrs, dmsg, buf)); case REPLY: return (xdr_reply_decode(xdrs, dmsg, buf)); default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR dmsg->rm_direction (%u)", __func__, __LINE__, dmsg->rm_direction); break; }; return (false); } /* * XDR a duplex message */ bool xdr_dplx_msg(XDR *xdrs, struct rpc_msg *dmsg) { assert(xdrs != NULL); assert(dmsg != NULL); switch (xdrs->x_op) { case XDR_ENCODE: switch (dmsg->rm_direction) { case CALL: return (xdr_call_encode(xdrs, dmsg)); case REPLY: return (xdr_reply_encode(xdrs, dmsg)); default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR dmsg->rm_direction (%u)", __func__, __LINE__, dmsg->rm_direction); break; }; break; case XDR_DECODE: return (xdr_dplx_decode(xdrs, dmsg)); case XDR_FREE: __warnx(TIRPC_DEBUG_FLAG_RPC_MSG, "%s:%u xdrs->x_op XDR_FREE", __func__, __LINE__); return (true); default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR xdrs->x_op (%u)", __func__, __LINE__, xdrs->x_op); break; }; return (false); } /* xdr_dplx_msg */ ntirpc-1.3.1/src/rpc_dtablesize.c000066400000000000000000000043001261345040100167310ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include int _rpc_dtablesize(void); /* XXX */ /* * Cache the result of getdtablesize(), so we don't have to do an * expensive system call every time. */ /* * XXX In FreeBSD 2.x, you can have the maximum number of open file * descriptors be greater than FD_SETSIZE (which us 256 by default). * * Since old programs tend to use this call to determine the first arg * for _select(), having this return > FD_SETSIZE is a Bad Idea(TM)! */ int _rpc_dtablesize(void) { static int size; if (size == 0) { size = getdtablesize(); if (size > FD_SETSIZE) size = FD_SETSIZE; } return (size); } ntirpc-1.3.1/src/rpc_generic.c000066400000000000000000000471211261345040100162270ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code mut retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ #include #include /* * rpc_generic.c, Miscl routines for RPC. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" tirpc_pkg_params __ntirpc_pkg_params = { TIRPC_FLAG_NONE, TIRPC_DEBUG_FLAG_NONE, warnx }; bool tirpc_control(const u_int rq, void *in) { switch (rq) { case TIRPC_GET_FLAGS: *(u_int *) in = __ntirpc_pkg_params.flags; break; case TIRPC_SET_FLAGS: __ntirpc_pkg_params.flags = *(int *)in; break; case TIRPC_GET_DEBUG_FLAGS: *(u_int *) in = __ntirpc_pkg_params.debug_flags; break; case TIRPC_SET_DEBUG_FLAGS: __ntirpc_pkg_params.debug_flags = *(int *)in; break; case TIRPC_GET_WARNX: *(warnx_t *) in = __ntirpc_pkg_params.warnx; break; case TIRPC_SET_WARNX: __ntirpc_pkg_params.warnx = *(warnx_t) in; break; default: return (false); } return (true); } 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(char *); #endif static int getnettype(const char *); /* * Cache the result of getrlimit(), so we don't have to do an * expensive call every time. */ int __rpc_dtbsize(void) { 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(int af, int proto, int size) { 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(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(char *p) { char *t = p; for (; *p; p++) if (isupper(*p)) *p = tolower(*p); return (t); } #endif /* * Returns the type of the network as defined in * If nettype is NULL, it defaults to NETPATH. */ static int getnettype(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() */ struct netconfig * __rpc_getconfip(const char *nettype) { char *netid; char *netid_tcp = (char *)NULL; char *netid_udp = (char *)NULL; struct netconfig *dummy; extern thread_key_t tcp_key, udp_key; extern mutex_t tsd_lock; if (tcp_key == -1) { mutex_lock(&tsd_lock); if (tcp_key == -1) thr_keycreate(&tcp_key, free); /* XXX */ mutex_unlock(&tsd_lock); } netid_tcp = (char *)thr_getspecific(tcp_key); if (udp_key == -1) { mutex_lock(&tsd_lock); if (udp_key == -1) thr_keycreate(&udp_key, free); mutex_unlock(&tsd_lock); } netid_udp = (char *)thr_getspecific(udp_key); if (!netid_udp && !netid_tcp) { struct netconfig *nconf; void *confighandle; confighandle = setnetconfig(); if (!confighandle) { __warnx(TIRPC_DEBUG_FLAG_DEFAULT, "rpc: failed to open %s", NETCONFIG); return (NULL); } while ((nconf = getnetconfig(confighandle)) != NULL) { if (strcmp(nconf->nc_protofmly, NC_INET) == 0 || strcmp(nconf->nc_protofmly, NC_INET6) == 0) { if (strcmp(nconf->nc_proto, NC_TCP) == 0 && netid_tcp == NULL) { netid_tcp = rpc_strdup(nconf->nc_netid); thr_setspecific(tcp_key, (void *)netid_tcp); } else if (strcmp(nconf->nc_proto, NC_UDP) == 0 && netid_udp == NULL) { netid_udp = rpc_strdup(nconf->nc_netid); thr_setspecific(udp_key, (void *)netid_udp); } } } 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(const char *nettype) { struct handle *handle; handle = (struct handle *)mem_zalloc(sizeof(struct handle)); if (handle == NULL) return (NULL); switch (handle->nettype = getnettype(nettype)) { case _RPC_NETPATH: case _RPC_CIRCUIT_N: case _RPC_DATAGRAM_N: handle->nhandle = setnetpath(); if (!handle->nhandle) { mem_free(handle, 0); /* XXX */ return (NULL); } handle->nflag = true; break; case _RPC_VISIBLE: case _RPC_CIRCUIT_V: case _RPC_DATAGRAM_V: case _RPC_TCP: case _RPC_UDP: handle->nhandle = setnetconfig(); if (!handle->nhandle) { __warnx(TIRPC_DEBUG_FLAG_DEFAULT, "rpc: failed to open %s", NETCONFIG); mem_free(handle, 0); return (NULL); } handle->nflag = false; break; default: mem_free(handle, 0); 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(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(void *vhandle) { struct handle *handle; handle = (struct handle *)vhandle; if (handle == NULL) return; if (handle->nflag) endnetpath(handle->nhandle); else endnetconfig(handle->nhandle); mem_free(handle, 0); } /* * Used to ping the NULL procedure for clnt handle. * Returns NULL if fails, else a non-NULL pointer. */ void * rpc_nullproc(CLIENT *clnt) { struct timeval TIMEOUT = { 25, 0 }; AUTH *auth; auth = authnone_create(); /* idempotent */ if (clnt_call (clnt, auth, 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(int fd) { const char *netid; struct __rpc_sockinfo si; if (!__rpc_fd2sockinfo(fd, &si)) return NULL; if (!__rpc_sockinfo2netid(&si, &netid)) return NULL; /*LINTED const castaway */ return getnetconfigent((char *)netid); } int __rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip) { socklen_t len; int type, proto; struct sockaddr_storage ss; len = sizeof(ss); if (getsockname(fd, (struct sockaddr *)&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) { int i; for (i = 0; i < (sizeof(na_cvt)) / (sizeof(struct netid_af)); i++) if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (strcmp(nconf->nc_netid, "unix") == 0 && strcmp(na_cvt[i].netid, "local") == 0)) { 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_flags(const struct netconfig *nconf, int flags) { struct __rpc_sockinfo si; int fd; if (!__rpc_nconf2sockinfo(nconf, &si)) return 0; fd = socket(si.si_af, si.si_socktype | flags, si.si_proto); if ((fd >= 0) && (si.si_af == AF_INET6)) { #ifdef SOL_IPV6 int val = 1; (void) setsockopt(fd, SOL_IPV6, IPV6_V6ONLY, &val, sizeof(val)); #endif } return fd; } int __rpc_nconf2fd(const struct netconfig *nconf) { return __rpc_nconf2fd_flags(nconf, 0); } int __rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid) { int i; struct netconfig *nconf; nconf = getnetconfigent("local"); 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 (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) { if (netid) *netid = "unix"; } else { if (netid) *netid = na_cvt[i].netid; } if (nconf != NULL) freenetconfigent(nconf); return 1; } } if (nconf != NULL) freenetconfigent(nconf); return 0; } char * taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf) { struct __rpc_sockinfo si; 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; 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 = NULL; struct sockaddr_in *sin; struct sockaddr_un *sun; char namebuf[INET_ADDRSTRLEN]; #ifdef INET6 struct sockaddr_in6 *sin6; char namebuf6[INET6_ADDRSTRLEN]; #endif u_int16_t port; if (nbuf->len <= 0) goto out; /* XXX check (fix) this */ ret = mem_zalloc(INET6_ADDRSTRLEN + (2 * 6) + 1); if (!ret) return (NULL); switch (af) { case AF_INET: sin = nbuf->buf; if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof(namebuf)) == NULL) return NULL; port = ntohs(sin->sin_port); if (sprintf (ret, "%s.%u.%u", namebuf, ((u_int32_t) port) >> 8, port & 0xff) < 0) { mem_free(ret, 0); return NULL; } break; #ifdef INET6 case AF_INET6: sin6 = nbuf->buf; if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof(namebuf6)) == NULL) { mem_free(ret, 0); return NULL; } port = ntohs(sin6->sin6_port); if (sprintf (ret, "%s.%u.%u", namebuf6, ((u_int32_t) port) >> 8, port & 0xff) < 0) { mem_free(ret, 0); return NULL; } break; #endif case AF_LOCAL: sun = nbuf->buf; /* if (asprintf(&ret, "%.*s", (int)(sun->sun_len - offsetof(struct sockaddr_un, sun_path)), sun->sun_path) < 0) */ if (sprintf(ret, "%.*s", (int)(sizeof(*sun) - offsetof(struct sockaddr_un, sun_path)), sun->sun_path) < 0) { mem_free(ret, 0); return NULL; } break; default: mem_free(ret, 0); return NULL; } out: 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 *sin; #ifdef INET6 struct sockaddr_in6 *sin6; #endif struct sockaddr_un *sun; port = 0; sin = NULL; addrstr = rpc_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. */ 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 = (struct netbuf *)mem_zalloc(sizeof(*ret)); if (ret == NULL) goto out; switch (af) { case AF_INET: sin = (struct sockaddr_in *)mem_zalloc(sizeof(*sin)); if (sin == NULL) goto out; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_port = htons(port); if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) { mem_free(sin, 0); /* XXX */ mem_free(ret, 0); ret = NULL; goto out; } ret->maxlen = ret->len = sizeof(*sin); ret->buf = sin; break; #ifdef INET6 case AF_INET6: sin6 = (struct sockaddr_in6 *)mem_zalloc(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) { mem_free(sin6, 0); mem_free(ret, 0); ret = NULL; goto out; } ret->maxlen = ret->len = sizeof(*sin6); ret->buf = sin6; break; #endif case AF_LOCAL: sun = (struct sockaddr_un *)mem_zalloc(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 = SUN_LEN(sun); ret->maxlen = sizeof(struct sockaddr_un); ret->buf = sun; break; default: mem_free(ret, 0); ret = NULL; break; } out: mem_free(addrstr, 0); 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. */ 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; 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; union { struct sockaddr_in sin; struct sockaddr_in6 sin6; struct sockaddr_un usin; } u_addr; 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: memcpy(&u_addr.sin, &ss, sizeof(u_addr.sin)); return (u_addr.sin.sin_port != 0); #ifdef INET6 case AF_INET6: memcpy(&u_addr.sin6, &ss, sizeof(u_addr.sin6)); return (u_addr.sin6.sin6_port != 0); #endif case AF_LOCAL: /* XXX check this */ memcpy(&u_addr.usin, &ss, sizeof(u_addr.usin)); return (u_addr.usin.sun_path[0] != 0); default: break; } return 0; } /* * Helper function to set up a netbuf */ struct netbuf * __rpc_set_netbuf(struct netbuf *nb, const void *ptr, size_t len) { if (nb->len != len) { if (nb->len) mem_free(nb->buf, nb->len); nb->buf = mem_zalloc(len); if (nb->buf == NULL) return NULL; nb->maxlen = nb->len = len; } memcpy(nb->buf, ptr, len); return nb; } ntirpc-1.3.1/src/rpc_prot.c000066400000000000000000000202711261345040100155740ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * rpc_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 #include #include #include #include #include static void accepted(enum accept_stat, struct rpc_err *); static void rejected(enum reject_stat, struct rpc_err *); /* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */ extern struct opaque_auth _null_auth; /* * XDR an opaque authentication struct * (see auth.h) */ bool xdr_opaque_auth(XDR *xdrs, struct opaque_auth *ap) { assert(xdrs != NULL); assert(ap != NULL); if (inline_xdr_enum(xdrs, &(ap->oa_flavor))) return (inline_xdr_bytes (xdrs, &ap->oa_base, &ap->oa_length, MAX_AUTH_BYTES)); return (false); } /* * XDR a DES block */ bool xdr_des_block(XDR *xdrs, des_block *blkp) { assert(xdrs != NULL); assert(blkp != NULL); return (inline_xdr_opaque (xdrs, (caddr_t) (void *)blkp, sizeof(des_block))); } /* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */ /* * XDR the MSG_ACCEPTED part of a reply message union */ bool xdr_naccepted_reply(XDR *xdrs, struct accepted_reply *ar) { assert(xdrs != NULL); assert(ar != NULL); /* personalized union, rather than calling xdr_union */ if (!inline_xdr_opaque_auth(xdrs, &(ar->ar_verf))) return (false); if (!inline_xdr_enum(xdrs, (enum_t *) &(ar->ar_stat))) return (false); switch (ar->ar_stat) { case SUCCESS: return ((*(ar->ar_results.proc)) (xdrs, ar->ar_results.where)); case PROG_MISMATCH: if (!inline_xdr_u_int32_t(xdrs, &(ar->ar_vers.low))) return (false); return (inline_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 xdr_nrejected_reply(XDR *xdrs, struct rejected_reply *rr) { assert(xdrs != NULL); assert(rr != NULL); /* personalized union, rather than calling xdr_union */ if (!inline_xdr_enum(xdrs, (enum_t *) &(rr->rj_stat))) return (false); switch (rr->rj_stat) { case RPC_MISMATCH: if (!inline_xdr_u_int32_t(xdrs, &(rr->rj_vers.low))) return (false); return (inline_xdr_u_int32_t(xdrs, &(rr->rj_vers.high))); case AUTH_ERROR: return (inline_xdr_enum(xdrs, (enum_t *) &(rr->rj_why))); } /* NOTREACHED */ assert(0); return (false); } static const struct xdr_discrim reply_dscrm[3] = { {(int)MSG_ACCEPTED, (xdrproc_t) xdr_naccepted_reply}, {(int)MSG_DENIED, (xdrproc_t) xdr_nrejected_reply}, {__dontcare__, NULL_xdrproc_t} }; /* * XDR a reply message */ bool xdr_nreplymsg(XDR *xdrs, struct rpc_msg *rmsg) { assert(xdrs != NULL); assert(rmsg != NULL); if (inline_xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) && inline_xdr_enum(xdrs, (enum_t *) &(rmsg->rm_direction)) && (rmsg->rm_direction == REPLY)) return (inline_xdr_union (xdrs, (enum_t *) &(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 xdr_ncallhdr(XDR *xdrs, struct rpc_msg *cmsg) { assert(xdrs != NULL); assert(cmsg != NULL); cmsg->rm_direction = CALL; cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION; if ((xdrs->x_op == XDR_ENCODE) && inline_xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) && inline_xdr_enum(xdrs, (enum_t *) &(cmsg->rm_direction)) && inline_xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && inline_xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog))) return (inline_xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers))); return (false); } /* ************************** Client utility routine ************* */ static void accepted(enum accept_stat acpt_stat, struct rpc_err *error) { assert(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(enum reject_stat rjct_stat, struct rpc_err *error) { assert(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(struct rpc_msg *msg, struct rpc_err *error) { assert(msg != NULL); assert(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; } } ntirpc-1.3.1/src/rpc_rdma.c000066400000000000000000001515041261345040100155370ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * contributeur : Dominique Martinet * contributeur : William Allen Simpson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * \file rpc_rdma.c * \brief rdma helper * * This was (very) loosely based on the Mooshika library, which in turn * was a mix of diod, rping (librdmacm/examples), and Linux kernel's * net/9p/trans_rdma.c (dual BSD/GPL license). No vestiges remain. */ #if HAVE_CONFIG_H # include #endif #include //printf #include //malloc #include //memcpy #include //INT_MAX #include //ENOMEM #include //warnx #include //sockaddr #include //sockaddr_un #include //pthread_* (think it's included by another one) #include //sem_* (is it a good idea to mix sem and pthread_cond/mutex?) #include //inet_ntop #include //sock_addr_in #include //fcntl #include //fcntl #include #define EPOLL_SIZE (10) /*^ expected number of fd, must be > 0 */ #define EPOLL_EVENTS (16) /*^ maximum number of events per poll */ #define EPOLL_WAIT_MS (1000) /*^ ms check for rpc_rdma_state.run_count (was 100) */ #define IBV_POLL_EVENTS (16) /*^ maximum number of events per poll */ #define NSEC_IN_SEC (1000*1000*1000) #include "misc/portable.h" #include #include #include #include #include #include #include "misc/abstract_atomic.h" #include "rpc_rdma.h" #ifdef HAVE_VALGRIND_MEMCHECK_H # include # ifndef VALGRIND_MAKE_MEM_DEFINED # warning "Valgrind support requested, but VALGRIND_MAKE_MEM_DEFINED not available" # endif #endif #ifndef VALGRIND_MAKE_MEM_DEFINED # define VALGRIND_MAKE_MEM_DEFINED(addr, len) #endif /** defaults **/ #define WORKER_STACK_SIZE (65535) /* was 2116488 */ struct connection_requests { struct rdma_cm_id **id_queue; sem_t q_sem; sem_t u_sem; uint32_t q_head; uint32_t q_tail; u_int q_size; }; struct rpc_rdma_state { LIST_HEAD(pdh_s, rpc_rdma_pd) pdh; /**< Protection Domain list */ mutex_t lock; struct connection_requests c_r; /* never freed??? */ pthread_t cm_thread; /**< Thread id for connection manager */ pthread_t cq_thread; /**< Thread id for completion queue */ pthread_t stats_thread; int cm_epollfd; int cq_epollfd; int stats_epollfd; int32_t run_count; }; /* GLOBAL VARIABLES */ static struct rpc_rdma_state rpc_rdma_state; void rpc_rdma_internals_init(void) { memset(&rpc_rdma_state, 0, sizeof(rpc_rdma_state)); sem_init(&rpc_rdma_state.c_r.q_sem, 0, 0); mutex_init(&rpc_rdma_state.lock, NULL); LIST_INIT(&rpc_rdma_state.pdh); } static void rpc_rdma_internals_join(void) { if (rpc_rdma_state.cm_thread) { pthread_join(rpc_rdma_state.cm_thread, NULL); rpc_rdma_state.cm_thread = 0; } if (rpc_rdma_state.cq_thread) { pthread_join(rpc_rdma_state.cq_thread, NULL); rpc_rdma_state.cq_thread = 0; } if (rpc_rdma_state.stats_thread) { pthread_join(rpc_rdma_state.stats_thread, NULL); rpc_rdma_state.stats_thread = 0; } } void rpc_rdma_internals_fini(void) { rpc_rdma_state.run_count = 0; rpc_rdma_internals_join(); sem_destroy(&rpc_rdma_state.c_r.q_sem); sem_destroy(&rpc_rdma_state.c_r.u_sem); mutex_destroy(&rpc_rdma_state.lock); } /* forward declarations */ static int rpc_rdma_bind_server(RDMAXPRT *xprt); static struct xp_ops rpc_rdma_ops; /* UTILITY FUNCTIONS */ /** * rpc_rdma_pd_by_verbs: register the protection domain for a given xprt * * Since the protection domains seem to be related to the interfaces, * and those are hot-swappable and variable, need a dynamic list of them. * (Cannot reliably count them during initialization.) * * LFU the list to keep access near O(1). * * @param[IN] xprt connection handle * * @return 0, ENOSPC, or EINVAL. */ static int rpc_rdma_pd_by_verbs(RDMAXPRT *xprt) { struct rpc_rdma_pd *pd; struct rpc_rdma_pd *lf; int rc; if (!xprt->cm_id) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() transport missing cm_id", __func__); return EINVAL; } if (!xprt->cm_id->verbs) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() cm_id missing verbs", __func__); /* return EINVAL; legal value for dispatcher??? */ } if (xprt->pd && xprt->pd->context == xprt->cm_id->verbs) { atomic_inc_uint32_t(&xprt->pd->pd_used); return (0); } mutex_lock(&rpc_rdma_state.lock); LIST_FOREACH(pd, &rpc_rdma_state.pdh, pdl) { if (pd->context == xprt->cm_id->verbs) { atomic_inc_uint32_t(&pd->pd_used); lf = LIST_FIRST(&rpc_rdma_state.pdh); if (pd->pd_used > lf->pd_used) { LIST_REMOVE(pd, pdl); LIST_INSERT_HEAD(&rpc_rdma_state.pdh, pd, pdl); } mutex_unlock(&rpc_rdma_state.lock); xprt->pd = pd; return (0); } } pd = mem_zalloc(sizeof(*pd)); if (pd) { rc = 0; pd->context = xprt->cm_id->verbs; pd->pd_used = 1; LIST_INSERT_HEAD(&rpc_rdma_state.pdh, pd, pdl); } else { rc = ENOSPC; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() couldn't malloc rdma pd", __func__); } mutex_unlock(&rpc_rdma_state.lock); xprt->pd = pd; return rc; } /** * rpc_rdma_pd_get: register and setup the protection domain * * @param[IN] xprt connection handle * * @return 0, errno, ENOSPC, or EINVAL. */ static int rpc_rdma_pd_get(RDMAXPRT *xprt) { int rc = rpc_rdma_pd_by_verbs(xprt); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return rc; } if (!xprt->pd->pd) { xprt->pd->pd = ibv_alloc_pd(xprt->cm_id->verbs); if (!xprt->pd->pd) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] ibv_alloc_pd failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } } return (0); } /** * rpc_rdma_pd_put: de-register and teardown the protection domain * * @param[IN] xprt connection handle */ static inline void rpc_rdma_pd_put(RDMAXPRT *xprt) { if (!xprt->pd) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() missing protection domain?", __func__); return; } if (atomic_dec_uint32_t(&xprt->pd->pd_used) == 0) { mutex_lock(&rpc_rdma_state.lock); LIST_REMOVE(xprt->pd, pdl); mutex_unlock(&rpc_rdma_state.lock); if (xprt->pd->pd) ibv_dealloc_pd(xprt->pd->pd); xprt->pd->pd = NULL; if (xprt->pd->srq) ibv_destroy_srq(xprt->pd->srq); xprt->pd->srq = NULL; if (!TAILQ_EMPTY(&xprt->pd->srqh.qh)) { xdr_ioq_destroy_pool(&xprt->pd->srqh); } mem_free(xprt->pd, sizeof(*xprt->pd)); } xprt->pd = NULL; } #ifdef UNUSED void rpc_rdma_print_devinfo(RDMAXPRT *xprt) { struct ibv_device_attr device_attr; ibv_query_device(xprt->cm_id->verbs, &device_attr); uint64_t node_guid = ntohll(device_attr.node_guid); printf("guid: %04x:%04x:%04x:%04x\n", (unsigned) (node_guid >> 48) & 0xffff, (unsigned) (node_guid >> 32) & 0xffff, (unsigned) (node_guid >> 16) & 0xffff, (unsigned) (node_guid >> 0) & 0xffff); } #endif /* UNUSED */ /** * rpc_rdma_thread_create: Simple wrapper around pthread_create */ static int rpc_rdma_thread_create(pthread_t *thrid, size_t stacksize, void *(*routine)(void *), void *arg) { pthread_attr_t attr; int rc; /* Init for thread parameter (mostly for scheduling) */ rc = pthread_attr_init(&attr); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't init pthread's attributes: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = pthread_attr_setscope(&attr, PTHREAD_SCOPE_SYSTEM); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't set pthread's scope: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't set pthread's join state: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = pthread_attr_setstacksize(&attr, stacksize); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't set pthread's stack size: %s (%d)", __func__, strerror(rc), rc); return rc; } return pthread_create(thrid, &attr, routine, arg); } static int rpc_rdma_thread_create_epoll(pthread_t *thrid, void *(*routine)(void *), void *arg, int *epollfd) { int rc = 0; /* all calls set a thrid in rpc_rdma_state, but unlikely conflict */ mutex_lock(&rpc_rdma_state.lock); if (*thrid == 0) do { *epollfd = epoll_create(EPOLL_SIZE); if (*epollfd == -1) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() epoll_create failed: %s (%d)", __func__, strerror(rc), rc); break; } rc = rpc_rdma_thread_create(thrid, WORKER_STACK_SIZE, routine, arg); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() could not create thread: %s (%d)", __func__, strerror(rc), rc); *thrid = 0; break; } __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() thread %lx spawned for epoll %d", __func__, (unsigned long)*thrid, *epollfd); } while (0); mutex_unlock(&rpc_rdma_state.lock); return rc; } static void rpc_rdma_worker_callback(struct work_pool_entry *wpe) { struct rpc_rdma_cbc *cbc = opr_containerof(wpe, struct rpc_rdma_cbc, wpe); RDMAXPRT *xprt = (RDMAXPRT *)wpe->arg; if (cbc->status) { if (cbc->negative_cb) { __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] cbc %p status: %d", __func__, xprt, xprt->state, cbc, cbc->status); cbc->negative_cb(cbc, xprt); } /* wpe->arg referenced before work_pool_submit() */ SVC_RELEASE(&xprt->xprt, SVC_REF_FLAG_NONE); return; } switch (cbc->opcode) { case IBV_WC_SEND: case IBV_WC_RDMA_WRITE: case IBV_WC_RDMA_READ: case IBV_WC_RECV: case IBV_WC_RECV_RDMA_WITH_IMM: if (cbc->positive_cb) { __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] cbc %p opcode: %d", __func__, xprt, xprt->state, cbc, cbc->opcode); cbc->positive_cb(cbc, xprt); } break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p opcode: %d unknown", __func__, xprt, xprt->state, cbc, cbc->opcode); break; } /* wpe->arg referenced before work_pool_submit() */ SVC_RELEASE(&xprt->xprt, SVC_REF_FLAG_NONE); } /** * rpc_rdma_fd_add: Adds fd to the epoll wait * * Returns 0 on success, errno value on error. */ static int rpc_rdma_fd_add(RDMAXPRT *xprt, int fd, int epollfd) { struct epoll_event ev; int flags = fcntl(fd, F_GETFL); int rc = fcntl(fd, F_SETFL, flags | O_NONBLOCK); if (rc < 0) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p Failed to make the channel nonblock: %s (%d)", __func__, xprt, strerror(rc), rc); return rc; } ev.events = EPOLLIN; ev.data.ptr = xprt; rc = epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev); if (rc == -1) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p Failed to add fd to epoll: %s (%d)", __func__, xprt, strerror(rc), rc); return rc; } return 0; } static int rpc_rdma_fd_del(int fd, int epollfd) { int rc = epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL); /* Let epoll deal with multiple deletes of the same fd */ if (rc == -1 && errno != ENOENT) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Failed to del fd to epoll: %s (%d)", __func__, strerror(rc), rc); return rc; } return 0; } static inline int rpc_rdma_stats_add(RDMAXPRT *xprt) { struct sockaddr_un sockaddr; int rc; /* no stats if no prefix */ if (!xprt->xa->statistics_prefix) return 0; /* setup xprt->stats_sock here */ xprt->stats_sock = socket(AF_UNIX, SOCK_STREAM, 0); if (xprt->stats_sock == -1) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() socket on stats socket failed, quitting thread: %s (%d)", __func__, strerror(rc), rc); return rc; } memset(&sockaddr, 0, sizeof(sockaddr)); sockaddr.sun_family = AF_UNIX; snprintf(sockaddr.sun_path, sizeof(sockaddr.sun_path)-1, "%s%p", xprt->xa->statistics_prefix, xprt); unlink(sockaddr.sun_path); rc = bind(xprt->stats_sock, (struct sockaddr*)&sockaddr, sizeof(sockaddr)); if (rc == -1) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() bind on stats socket failed, quitting thread: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = listen(xprt->stats_sock, 5); if (rc == -1) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() listen on stats socket failed, quitting thread: %s (%d)", __func__, strerror(rc), rc); return rc; } return rpc_rdma_fd_add(xprt, xprt->stats_sock, rpc_rdma_state.stats_epollfd); } static inline int rpc_rdma_stats_del(RDMAXPRT *xprt) { /* rpc_rdma_fd_del is called in stats thread on a close event */ char sun_path[108]; snprintf(sun_path, sizeof(sun_path)-1, "%s%p", xprt->xa->statistics_prefix, xprt); unlink(sun_path); return close(xprt->stats_sock); } /** * rpc_rdma_stats_thread: unix socket thread * * Well, a thread. arg = xprt */ static void * rpc_rdma_stats_thread(void *arg) { RDMAXPRT *xprt; struct epoll_event epoll_events[EPOLL_EVENTS]; char stats_str[256]; int childfd; int i; int n; int rc; while (rpc_rdma_state.run_count > 0) { n = epoll_wait(rpc_rdma_state.stats_epollfd, epoll_events, EPOLL_EVENTS, EPOLL_WAIT_MS); if (n == 0) continue; if (n == -1) { if (errno == EINTR) continue; rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() epoll_wait failed: %s (%d)", __func__, strerror(rc), rc); break; } for (i = 0; i < n; ++i) { xprt = (RDMAXPRT*)epoll_events[i].data.ptr; if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no xprt: got an event on a fd that should have been removed!", __func__); continue; } if (epoll_events[i].events == EPOLLERR || epoll_events[i].events == EPOLLHUP) { rpc_rdma_fd_del(xprt->stats_sock, rpc_rdma_state.stats_epollfd); continue; } childfd = accept(xprt->stats_sock, NULL, NULL); if (childfd == -1) { if (errno == EINTR) { continue; } else { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() accept on stats socket failed: %s (%d)", __func__, strerror(errno), errno); continue; } } rc = snprintf(stats_str, sizeof(stats_str), "stats:\n" " tx_bytes\ttx_pkt\ttx_err\n" " %10"PRIu64"\t%"PRIu64"\t%"PRIu64"\n" " rx_bytes\trx_pkt\trx_err\n" " %10"PRIu64"\t%"PRIu64"\t%"PRIu64"\n" " callback time: %lu.%09lu s\n" " completion time: %lu.%09lu s\n", xprt->stats.tx_bytes, xprt->stats.tx_pkt, xprt->stats.tx_err, xprt->stats.rx_bytes, xprt->stats.rx_pkt, xprt->stats.rx_err, xprt->stats.nsec_callback / NSEC_IN_SEC, xprt->stats.nsec_callback % NSEC_IN_SEC, xprt->stats.nsec_compevent / NSEC_IN_SEC, xprt->stats.nsec_compevent % NSEC_IN_SEC); rc = write(childfd, stats_str, rc); rc = close(childfd); } } pthread_exit(NULL); } /** * rpc_rdma_cq_event_handler: completion queue event handler. * * marks contexts back out of use, * calls the appropriate callbacks for each kind of event. * * @return 0 on success, work completion status if not 0 */ static int rpc_rdma_cq_event_handler(RDMAXPRT *xprt) { struct ibv_wc wc[IBV_POLL_EVENTS]; struct ibv_cq *ev_cq; void *ev_ctx; struct rpc_rdma_cbc *cbc; struct xdr_ioq_uv *data; int i; int rc; int npoll = 0; uint32_t len; rc = ibv_get_cq_event(xprt->comp_channel, &ev_cq, &ev_ctx); if (rc) { rc = errno; if (rc != EAGAIN) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() ibv_get_cq_event failed: %d.", __func__, rc); } return rc; } if (ev_cq != xprt->cq) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Unknown cq %p", __func__, ev_cq); ibv_ack_cq_events(ev_cq, 1); return EINVAL; } rc = ibv_req_notify_cq(xprt->cq, 0); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() ibv_req_notify_cq failed: %d.", __func__, rc); } while (rc == 0 && (npoll = ibv_poll_cq(xprt->cq, IBV_POLL_EVENTS, wc)) > 0) { for (i = 0; i < npoll; i++) { if (xprt->bad_recv_wr) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Something was bad on that recv", __func__); } if (xprt->bad_send_wr) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Something was bad on that send", __func__); } cbc = (struct rpc_rdma_cbc *)wc[i].wr_id; cbc->opcode = wc[i].opcode; cbc->status = wc[i].status; cbc->wpe.arg = xprt; if (wc[i].status) { switch (wc[i].opcode) { case IBV_WC_SEND: case IBV_WC_RDMA_WRITE: case IBV_WC_RDMA_READ: xprt->stats.tx_err++; break; case IBV_WC_RECV: case IBV_WC_RECV_RDMA_WITH_IMM: xprt->stats.rx_err++; break; default: break; } SVC_REF(&xprt->xprt, SVC_REF_FLAG_NONE); work_pool_submit(&svc_work_pool, &cbc->wpe); if (xprt->state != RDMAXS_CLOSING && xprt->state != RDMAXS_CLOSED && xprt->state != RDMAXS_ERROR) { rc = wc[i].status; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() cq completion failed status: %s (%d)", __func__, ibv_wc_status_str(rc), rc); } continue; } switch (wc[i].opcode) { case IBV_WC_SEND: case IBV_WC_RDMA_WRITE: case IBV_WC_RDMA_READ: len = wc[i].byte_len; xprt->stats.tx_bytes += len; xprt->stats.tx_pkt++; __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() WC_SEND/RDMA_WRITE/RDMA_READ: %d len %u", __func__, wc[i].opcode, len); if (wc[i].wc_flags & IBV_WC_WITH_IMM) { //FIXME cbc->data->imm_data = ntohl(wc.imm_data); __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() imm_data: %d", __func__, ntohl(wc[i].imm_data)); } SVC_REF(&xprt->xprt, SVC_REF_FLAG_NONE); work_pool_submit(&svc_work_pool, &cbc->wpe); break; case IBV_WC_RECV: case IBV_WC_RECV_RDMA_WITH_IMM: len = wc[i].byte_len; xprt->stats.rx_bytes += len; xprt->stats.rx_pkt++; __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() WC_RECV: %d len %u", __func__, wc[i].opcode, len); if (wc[i].wc_flags & IBV_WC_WITH_IMM) { //FIXME cbc->data->imm_data = ntohl(wc.imm_data); __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() imm_data: %d", __func__, ntohl(wc[i].imm_data)); } /* fill all the sizes in case of multiple sge * assumes _tail was set to _wrap before call */ data = IOQ_(TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh)); while (data && ioquv_length(data) < len) { VALGRIND_MAKE_MEM_DEFINED(data->v.vio_head, ioquv_length(data)); len -= ioquv_length(data); data = IOQ_(TAILQ_NEXT(&data->uvq, q)); } if (data) { data->v.vio_tail = data->v.vio_head + len; VALGRIND_MAKE_MEM_DEFINED(data->v.vio_head, ioquv_length(data)); } else if (len) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() ERROR %d leftover bytes?", __func__, len); } SVC_REF(&xprt->xprt, SVC_REF_FLAG_NONE); work_pool_submit(&svc_work_pool, &cbc->wpe); break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() unknown opcode: %d", __func__, wc[i].opcode); rc = EINVAL; } } } if (npoll < 0) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] ibv_poll_cq failed: %s (%d)", __func__, xprt, xprt->state, strerror(-npoll), -npoll); rc = -npoll; } ibv_ack_cq_events(xprt->cq, 1); return -rc; } /** * rpc_rdma_cq_thread: thread function which waits for new completion events * and gives them to handler (then ack the event) * */ static void * rpc_rdma_cq_thread(void *arg) { RDMAXPRT *xprt; struct epoll_event epoll_events[EPOLL_EVENTS]; int i; int n; int rc; while (rpc_rdma_state.run_count > 0) { n = epoll_wait(rpc_rdma_state.cq_epollfd, epoll_events, EPOLL_EVENTS, EPOLL_WAIT_MS); if (n == 0) continue; if (n == -1) { if (errno == EINTR) continue; rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() epoll_wait failed: %s (%d)", __func__, strerror(rc), rc); break; } for (i = 0; i < n; ++i) { xprt = (RDMAXPRT*)epoll_events[i].data.ptr; if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() got an event on a fd that should have been removed! (no xprt)", __func__); continue; } if (epoll_events[i].events == EPOLLERR || epoll_events[i].events == EPOLLHUP) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() epoll error or hup (%d)", __func__, epoll_events[i].events); continue; } mutex_lock(&xprt->cm_lock); if (xprt->state >= RDMAXS_CLOSING) { /* CLOSING, CLOSED, ERROR */ // closing xprt, skip this, will be done on flush rpc_rdma_fd_del(xprt->comp_channel->fd, rpc_rdma_state.cq_epollfd); mutex_unlock(&xprt->cm_lock); continue; } rc = rpc_rdma_cq_event_handler(xprt); if (rc) { if (xprt->state != RDMAXS_CLOSING && xprt->state != RDMAXS_CLOSED && xprt->state != RDMAXS_ERROR) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() something went wrong with our cq_event_handler", __func__); xprt->state = RDMAXS_ERROR; cond_broadcast(&xprt->cm_cond); } } mutex_unlock(&xprt->cm_lock); } } pthread_exit(NULL); } /** * rpc_rdma_cm_event_handler: handles addr/route resolved events (client side) * and disconnect (everyone) * */ static int rpc_rdma_cm_event_handler(RDMAXPRT *ep_xprt, struct rdma_cm_event *event) { struct rdma_cm_id *cm_id = event->id; RDMAXPRT *xprt = cm_id->context; uint32_t u; int rc = 0; __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p cma_event type %s", __func__, ep_xprt, rdma_event_str(event->event)); if (xprt->bad_recv_wr) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Something was bad on that recv", __func__); } if (xprt->bad_send_wr) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Something was bad on that send", __func__); } switch (event->event) { case RDMA_CM_EVENT_ADDR_RESOLVED: __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p ADDR_RESOLVED", __func__, xprt); mutex_lock(&xprt->cm_lock); xprt->state = RDMAXS_ADDR_RESOLVED; cond_broadcast(&xprt->cm_cond); mutex_unlock(&xprt->cm_lock); break; case RDMA_CM_EVENT_ROUTE_RESOLVED: __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p ROUTE_RESOLVED", __func__, xprt); mutex_lock(&xprt->cm_lock); xprt->state = RDMAXS_ROUTE_RESOLVED; cond_broadcast(&xprt->cm_cond); mutex_unlock(&xprt->cm_lock); break; case RDMA_CM_EVENT_ESTABLISHED: __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p ESTABLISHED", __func__, xprt); xprt->state = RDMAXS_CONNECTED; rc = rpc_rdma_fd_add(xprt, xprt->comp_channel->fd, rpc_rdma_state.cq_epollfd); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); } rpc_rdma_stats_add(xprt); break; case RDMA_CM_EVENT_CONNECT_REQUEST: __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p CONNECT_REQUEST", __func__, xprt); rc = sem_trywait(&rpc_rdma_state.c_r.u_sem); if (rc) { rc = errno; if (EAGAIN != rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] sem_trywait failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p WARNING too many connection requests! " "Need to increase backlog parameter.\n", __func__, xprt); /* After advisory message, wait for available slot. */ rc = sem_wait(&rpc_rdma_state.c_r.u_sem); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] sem_wait failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } } u = atomic_postinc_uint32_t(&rpc_rdma_state.c_r.q_tail); if (u >= rpc_rdma_state.c_r.q_size) { u_int q_mask = rpc_rdma_state.c_r.q_size - 1; /* masking allows update by lock-free tasks, * as long as overrun never 2 * q_size */ u &= q_mask; atomic_clear_uint32_t_bits(&rpc_rdma_state.c_r.q_tail, ~q_mask); } rpc_rdma_state.c_r.id_queue[u] = cm_id; /* signal accept handler */ rc = sem_post(&rpc_rdma_state.c_r.q_sem); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() sem_post failed", __func__, strerror(rc), rc); return rc; } break; case RDMA_CM_EVENT_ADDR_ERROR: case RDMA_CM_EVENT_ROUTE_ERROR: case RDMA_CM_EVENT_CONNECT_ERROR: case RDMA_CM_EVENT_UNREACHABLE: case RDMA_CM_EVENT_REJECTED: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cma event %s, error %d", __func__, xprt, xprt->state, rdma_event_str(event->event), event->status); mutex_lock(&xprt->cm_lock); xprt->state = RDMAXS_ERROR; cond_broadcast(&xprt->cm_cond); mutex_unlock(&xprt->cm_lock); break; case RDMA_CM_EVENT_DISCONNECTED: __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] DISCONNECT EVENT...", __func__, xprt, xprt->state); // don't call completion again if (xprt->comp_channel) rpc_rdma_fd_del(xprt->comp_channel->fd, rpc_rdma_state.cq_epollfd); mutex_lock(&xprt->cm_lock); xprt->state = RDMAXS_CLOSED; cond_broadcast(&xprt->cm_cond); mutex_unlock(&xprt->cm_lock); if (xprt->xa->disconnect_cb) xprt->xa->disconnect_cb(&xprt->xprt); break; case RDMA_CM_EVENT_DEVICE_REMOVAL: __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] cma detected device removal!!!!", __func__, xprt, xprt->state); rc = ENODEV; break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] unhandled event: %s, ignoring %d\n", __func__, xprt, xprt->state, rdma_event_str(event->event), event->event); break; } return rc; } /** * rpc_rdma_cm_thread: thread function which waits for new connection events * and gives them to handler (then ack the event) * */ static void * rpc_rdma_cm_thread(void *nullarg) { RDMAXPRT *xprt; RDMAXPRT *cm_xprt; struct rdma_cm_event *event; struct epoll_event epoll_events[EPOLL_EVENTS]; int i; int n; int rc; while (rpc_rdma_state.run_count > 0) { n = epoll_wait(rpc_rdma_state.cm_epollfd, epoll_events, EPOLL_EVENTS, EPOLL_WAIT_MS); if (n == 0) continue; if (n == -1) { if (errno == EINTR) continue; rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] epoll_wait failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); break; } for (i = 0; i < n; ++i) { xprt = (RDMAXPRT*)epoll_events[i].data.ptr; if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() got an event on a fd that should have been removed! (no xprt)", __func__); continue; } if (epoll_events[i].events == EPOLLERR || epoll_events[i].events == EPOLLHUP) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() epoll error or hup (%d)", __func__, epoll_events[i].events); continue; } if (xprt->state == RDMAXS_CLOSED) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() got a cm event on a closed xprt?", __func__); continue; } if (!xprt->event_channel) { if (xprt->state != RDMAXS_CLOSED) __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no event channel? :D", __func__); continue; } rc = rdma_get_cm_event(xprt->event_channel, &event); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() rdma_get_cm_event failed: %d.", __func__, rc); continue; } cm_xprt = event->id->context; rc = rpc_rdma_cm_event_handler(xprt, event); rdma_ack_cm_event(event); if (rc && (cm_xprt->state != RDMAXS_LISTENING || cm_xprt == xprt)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() rpc_rdma_cm_event_handler: %d.", __func__, rc); } if (cm_xprt->state == RDMAXS_CLOSED && cm_xprt->destroy_on_disconnect) SVC_DESTROY(&cm_xprt->xprt); } } pthread_exit(NULL); } /** * rpc_rdma_flush_buffers: Flush all pending recv/send * * @param[IN] xprt * * @return void */ static void rpc_rdma_flush_buffers(RDMAXPRT *xprt) { int rc; __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u]", __func__, xprt, xprt->state); mutex_lock(&xprt->cm_lock); if (xprt->state != RDMAXS_ERROR) { do { rc = rpc_rdma_cq_event_handler(xprt); } while (rc == 0); if (rc != EAGAIN) __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() couldn't flush pending data in cq: %d", __func__, rc); } #ifdef FIXME /* only flush rx if client or accepting server */ if (xprt->server >= 0) for (i = 0, ctx = xprt->rcb; i < xprt->xa->rq_depth; i++, ctx = (struct rpc_rdma_cbc*)((uint8_t*)ctx + sizeof(struct rpc_rdma_cbc) + xprt->xa->max_recv_sge*sizeof(struct ibv_sge))) if (ctx->used == MSK_CTX_PENDING) rpc_rdma_worker_signal(xprt, ctx, IBV_WC_FATAL_ERR, IBV_WC_RECV); for (i = 0, ctx = (struct rpc_rdma_cbc *)xprt->wcb; i < xprt->xa->sq_depth; i++, ctx = (struct rpc_rdma_cbc*)((uint8_t*)ctx + sizeof(struct rpc_rdma_cbc) + xprt->xa->max_send_sge*sizeof(struct ibv_sge))) if (ctx->used == MSK_CTX_PENDING) rpc_rdma_worker_signal(xprt, ctx, IBV_WC_FATAL_ERR, IBV_WC_SEND); /* only flush rx if client or accepting server */ if (xprt->server >= 0) do { wait = 0; for (i = 0, ctx = xprt->rcb; i < xprt->xa->rq_depth; i++, ctx = rpc_rdma_next_ctx(ctx, xprt->xa->max_recv_sge)) if (ctx->used != MSK_CTX_FREE) wait++; } while (wait && usleep(100000)); do { wait = 0; for (i = 0, ctx = (struct rpc_rdma_cbc *)xprt->wcb; i < xprt->xa->sq_depth; i++, ctx = rpc_rdma_next_ctx(ctx, xprt->xa->max_recv_sge)) if (ctx->used != MSK_CTX_FREE) wait++; } while (wait && usleep(100000)); #endif mutex_unlock(&xprt->cm_lock); } /** * rpc_rdma_destroy_stuff: destroys all qp-related stuff for us * * @param[INOUT] xprt * * @return void, even if the functions _can_ fail we choose to ignore it. //FIXME? */ static void rpc_rdma_destroy_stuff(RDMAXPRT *xprt) { if (xprt->qp) { // flush all pending receive/send buffers to error callback rpc_rdma_flush_buffers(xprt); ibv_destroy_qp(xprt->qp); xprt->qp = NULL; } if (xprt->cq) { ibv_destroy_cq(xprt->cq); xprt->cq = NULL; } if (xprt->comp_channel) { ibv_destroy_comp_channel(xprt->comp_channel); xprt->comp_channel = NULL; } if (!TAILQ_EMPTY(&xprt->cbqh.qh)) { xdr_ioq_destroy_pool(&xprt->cbqh); } } /** * rpc_rdma_destroy: disconnects and free transport data * * @param[IN] xprt pointer to the service transport to destroy */ void rpc_rdma_destroy(SVCXPRT *s_xprt) { RDMAXPRT *xprt = (RDMAXPRT *)s_xprt; /* inhibit repeated destroy */ xprt->destroy_on_disconnect = false; if (xprt->state == RDMAXS_CONNECTED || xprt->state == RDMAXS_CLOSED) { mutex_lock(&xprt->cm_lock); if (xprt->state != RDMAXS_CLOSED && xprt->state != RDMAXS_LISTENING && xprt->state != RDMAXS_ERROR) xprt->state = RDMAXS_CLOSING; if (xprt->cm_id && xprt->cm_id->verbs) rdma_disconnect(xprt->cm_id); while (xprt->state != RDMAXS_CLOSED && xprt->state != RDMAXS_LISTENING && xprt->state != RDMAXS_ERROR) { __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() we're not closed yet, " "waiting for disconnect_event", __func__); cond_wait(&xprt->cm_cond, &xprt->cm_lock); } xprt->state = RDMAXS_CLOSED; mutex_unlock(&xprt->cm_lock); } if (xprt->cm_id) { rdma_destroy_id(xprt->cm_id); xprt->cm_id = NULL; } if (xprt->stats_sock) rpc_rdma_stats_del(xprt); /* event channel is shared between all children, * so don't close it unless it's its own. */ if ((xprt->server != RDMAX_SERVER_CHILD) && xprt->event_channel) { rpc_rdma_fd_del(xprt->event_channel->fd, rpc_rdma_state.cm_epollfd); rdma_destroy_event_channel(xprt->event_channel); xprt->event_channel = NULL; } rpc_rdma_destroy_stuff(xprt); rpc_rdma_pd_put(xprt); if (atomic_dec_int32_t(&rpc_rdma_state.run_count) <= 0) { mutex_lock(&rpc_rdma_state.lock); rpc_rdma_internals_join(); mutex_unlock(&rpc_rdma_state.lock); } /* destroy locking last, was initialized first (below). */ cond_destroy(&xprt->cm_cond); mutex_destroy(&xprt->cm_lock); mutex_destroy(&xprt->xprt.xp_lock); mutex_destroy(&xprt->xprt.xp_auth_lock); mem_free(xprt, sizeof(*xprt)); } /** * rpc_rdma_allocate: allocate rdma transport structures * * @param[IN] xa parameters * * @return xprt on success, NULL on failure */ static RDMAXPRT * rpc_rdma_allocate(struct rpc_rdma_attr *xa) { RDMAXPRT *xprt; int rc; if (!xa) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Invalid argument", __func__); return NULL; } xprt = mem_zalloc(sizeof(RDMAXPRT)); if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Out of memory", __func__); return NULL; } xprt->xprt.xp_type = XPRT_RDMA; xprt->xprt.xp_refs = 1; xprt->xprt.xp_ops = &rpc_rdma_ops; xprt->xa = xa; xprt->conn_type = RDMA_PS_TCP; xprt->destroy_on_disconnect = xa->destroy_on_disconnect; /* initialize locking first, will be destroyed last (above). */ rc = mutex_init(&xprt->xprt.xp_auth_lock, NULL); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() mutex_init xp_auth_lock failed: %s (%d)", __func__, strerror(rc), rc); goto xp_auth_lock; } rc = mutex_init(&xprt->xprt.xp_lock, NULL); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() mutex_init xp_lock failed: %s (%d)", __func__, strerror(rc), rc); goto xp_lock; } rc = mutex_init(&xprt->cm_lock, NULL); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() mutex_init failed: %s (%d)", __func__, strerror(rc), rc); goto cm_lock; } rc = cond_init(&xprt->cm_cond, NULL, NULL); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() cond_init failed: %s (%d)", __func__, strerror(rc), rc); goto cm_cond; } return (xprt); cm_cond: mutex_destroy(&xprt->cm_lock); cm_lock: mutex_destroy(&xprt->xprt.xp_lock); xp_lock: mutex_destroy(&xprt->xprt.xp_auth_lock); xp_auth_lock: mem_free(xprt, sizeof(*xprt)); return NULL; } /** * rpc_rdma_create: initialize rdma transport structures * * @param[IN] xa parameters * * @return xprt on success, NULL on failure */ SVCXPRT * rpc_rdma_create(struct rpc_rdma_attr *xa) { RDMAXPRT *xprt; int rc; if (xa->backlog > 4096) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() backlog (%u) much too large", __func__, xa->backlog); return NULL; } if (xa->worker_count > 256) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() worker_count (%u) much too large", __func__, xa->worker_count); return NULL; } xprt = rpc_rdma_allocate(xa); if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return NULL; } xprt->server = xa->backlog; /* convenient number > 0 */ /* presence of event_channel confirms RDMA, * otherwise, cleanup and quit RDMA dispatcher. */ xprt->event_channel = rdma_create_event_channel(); if (!xprt->event_channel) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() create_event_channel failed: %s (%d)", __func__, strerror(rc), rc); goto failure; } rc = rdma_create_id(xprt->event_channel, &xprt->cm_id, xprt, xprt->conn_type); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() create_id failed: %s (%d)", __func__, strerror(rc), rc); goto failure; } pthread_mutex_lock(&svc_work_pool.pqh.qmutex); if (!svc_work_pool.params.thrd_max) { pthread_mutex_unlock(&svc_work_pool.pqh.qmutex); __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() svc_work_pool already shutdown", __func__); goto failure; } svc_work_pool.params.thrd_max += xa->worker_count; pthread_mutex_unlock(&svc_work_pool.pqh.qmutex); /* round up to the next power of two */ rpc_rdma_state.c_r.q_size = 2; while (rpc_rdma_state.c_r.q_size < xa->backlog) { rpc_rdma_state.c_r.q_size <<= 1; } rpc_rdma_state.c_r.id_queue = mem_alloc(rpc_rdma_state.c_r.q_size * sizeof(struct rdma_cm_id *)); if (!rpc_rdma_state.c_r.id_queue) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Could not allocate connection_requests queue", __func__); goto failure; } sem_init(&rpc_rdma_state.c_r.u_sem, 0, rpc_rdma_state.c_r.q_size); rc = rpc_rdma_bind_server(xprt); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() NFS/RDMA dispatcher could not bind engine", __func__); goto failure; } else { __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() NFS/RDMA engine bound", __func__); } return (&xprt->xprt); failure: rpc_rdma_destroy(&xprt->xprt); return NULL; } /** * rpc_rdma_create_qp: create a qp associated with a xprt * * @param[INOUT] xprt * @param[IN] cm_id * * @return 0 on success, errno value on error */ static int rpc_rdma_create_qp(RDMAXPRT *xprt, struct rdma_cm_id *cm_id) { int rc; struct ibv_qp_init_attr qp_attr = { .cap.max_send_wr = xprt->xa->sq_depth, .cap.max_send_sge = xprt->xa->max_send_sge, .cap.max_recv_wr = xprt->xa->rq_depth, .cap.max_recv_sge = xprt->xa->max_recv_sge, .cap.max_inline_data = 0, // change if IMM .qp_type = (xprt->conn_type == RDMA_PS_UDP ? IBV_QPT_UD : IBV_QPT_RC), .sq_sig_all = 1, .send_cq = xprt->cq, .recv_cq = xprt->cq, .srq = xprt->srq, }; rc = rdma_create_qp(cm_id, xprt->pd->pd, &qp_attr); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_create_qp failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } xprt->qp = cm_id->qp; return 0; } /** * rpc_rdma_setup_stuff: setup pd, qp an' stuff * * @param[INOUT] xprt * * @return 0 on success, errno value on failure */ static int rpc_rdma_setup_stuff(RDMAXPRT *xprt) { int rc; __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u]", __func__, xprt, xprt->state); /* Located in this function for convenience, called by both * client and server. Each is only done once for all connections. */ rc = rpc_rdma_thread_create_epoll(&rpc_rdma_state.cq_thread, rpc_rdma_cq_thread, xprt, &rpc_rdma_state.cq_epollfd); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return rc; } if (xprt->xa->statistics_prefix != NULL && (rc = rpc_rdma_thread_create_epoll(&rpc_rdma_state.stats_thread, rpc_rdma_stats_thread, xprt, &rpc_rdma_state.stats_epollfd))) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return rc; } xprt->comp_channel = ibv_create_comp_channel(xprt->cm_id->verbs); if (!xprt->comp_channel) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] ibv_create_comp_channel failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } xprt->cq = ibv_create_cq(xprt->cm_id->verbs, xprt->xa->sq_depth + xprt->xa->rq_depth, xprt, xprt->comp_channel, 0); if (!xprt->cq) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] ibv_create_cq failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } rc = ibv_req_notify_cq(xprt->cq, 0); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] ibv_req_notify_cq failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } rc = rpc_rdma_create_qp(xprt, xprt->cm_id); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return rc; } __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] created qp %p", __func__, xprt, xprt->state, xprt->qp); return 0; } /** * rpc_rdma_setup_cbq */ static int rpc_rdma_setup_cbq(struct poolq_head *ioqh, u_int depth, u_int sge) { struct rpc_rdma_cbc *cbc; if (ioqh->qsize) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() contexts already allocated", __func__); return EINVAL; } ioqh->qsize = sizeof(struct rpc_rdma_cbc) + sizeof(struct ibv_sge) * sge; TAILQ_INIT(&ioqh->qh); /* individual entries is less efficient than big array -- but uses * "standard" IOQ operations, xdr_ioq_destroy_pool(), and * debugging memory bounds checking of trailing ibv_sge array. */ while (depth--) { cbc = mem_zalloc(ioqh->qsize); if (!cbc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() couldn't mem_zalloc callback context", __func__); return ENOMEM; } xdr_ioq_setup(&cbc->workq); xdr_ioq_setup(&cbc->holdq); cbc->workq.ioq_uv.uvq_fetch = cbc->holdq.ioq_uv.uvq_fetch = xdr_ioq_uv_fetch_nothing; cbc->workq.xdrs[0].x_ops = cbc->holdq.xdrs[0].x_ops = &xdr_ioq_ops; cbc->workq.xdrs[0].x_op = cbc->holdq.xdrs[0].x_op = XDR_FREE; /* catch setup errors */ cbc->workq.ioq_pool = ioqh; cbc->wpe.fun = rpc_rdma_worker_callback; (ioqh->qcount)++; TAILQ_INSERT_TAIL(&ioqh->qh, &cbc->workq.ioq_s, q); } return 0; } /** * rpc_rdma_bind_server * * @param[INOUT] xprt * * @return 0 on success, errno value on failure */ static int rpc_rdma_bind_server(RDMAXPRT *xprt) { struct rdma_addrinfo *res; struct rdma_addrinfo hints; int rc; if (!xprt || xprt->state != RDMAXS_INITIAL) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] must be initialized first!", __func__, xprt, xprt->state); return EINVAL; } if (xprt->server <= 0) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Must be on server side to call this function", __func__); return EINVAL; } memset(&hints, 0, sizeof(hints)); hints.ai_flags = RAI_PASSIVE; hints.ai_port_space = xprt->conn_type; rc = rdma_getaddrinfo(xprt->xa->node, xprt->xa->port, &hints, &res); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_getaddrinfo: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } rc = rdma_bind_addr(xprt->cm_id, res->ai_src_addr); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_bind_addr: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } rdma_freeaddrinfo(res); /* at this point, the cm_id->verbs aren't filled */ rc = rpc_rdma_pd_by_verbs(xprt); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] register pd failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } rc = rdma_listen(xprt->cm_id, xprt->xa->backlog); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_listen failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } xprt->state = RDMAXS_LISTENING; atomic_inc_int32_t(&rpc_rdma_state.run_count); rc = rpc_rdma_thread_create_epoll(&rpc_rdma_state.cm_thread, rpc_rdma_cm_thread, xprt, &rpc_rdma_state.cm_epollfd); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rpc_rdma_thread_create_epoll failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); atomic_dec_int32_t(&rpc_rdma_state.run_count); return rc; } return rpc_rdma_fd_add(xprt, xprt->event_channel->fd, rpc_rdma_state.cm_epollfd); } /** * rpc_rdma_clone: clone child from listener parent * * @param[IN] l_xprt listening (parent) transport * @param[IN] cm_id new rdma connection manager identifier * * @return 0 on success, errno value on failure */ static RDMAXPRT * rpc_rdma_clone(RDMAXPRT *l_xprt, struct rdma_cm_id *cm_id) { RDMAXPRT *xprt = rpc_rdma_allocate(l_xprt->xa); int rc; if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return NULL; } xprt->cm_id = cm_id; xprt->cm_id->context = xprt; xprt->state = RDMAXS_CONNECT_REQUEST; xprt->server = RDMAX_SERVER_CHILD; xprt->event_channel = l_xprt->event_channel; rc = rpc_rdma_pd_get(xprt); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); goto failure; } if (l_xprt->xa->use_srq) { if (!xprt->pd->srq) { struct ibv_srq_init_attr srq_attr = { .attr.max_wr = xprt->xa->rq_depth, .attr.max_sge = xprt->xa->max_recv_sge, }; xprt->pd->srq = ibv_create_srq(xprt->pd->pd, &srq_attr); if (!xprt->pd->srq) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() ibv_create_srq failed: %s (%d)", __func__, strerror(rc), rc); goto failure; } } if (!xprt->pd->srqh.qcount) { rc = rpc_rdma_setup_cbq(&xprt->pd->srqh, xprt->xa->rq_depth, xprt->xa->max_recv_sge); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); goto failure; } } /* only send contexts */ rc = rpc_rdma_setup_cbq(&xprt->cbqh, xprt->xa->sq_depth, xprt->xa->credits); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); goto failure; } } else { rc = rpc_rdma_setup_cbq(&xprt->cbqh, xprt->xa->rq_depth + xprt->xa->sq_depth, xprt->xa->credits); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); goto failure; } } /* srq only used as a boolean here */ xprt->srq = xprt->pd->srq; rc = rpc_rdma_setup_stuff(xprt); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); goto failure; } atomic_inc_int32_t(&rpc_rdma_state.run_count); return xprt; failure: rpc_rdma_destroy(&xprt->xprt); return (NULL); } /** * rpc_rdma_accept_finalize: does the real connection acceptance * N.B. no wait for CM result. CM event thread will handle setup/teardown. * * @param[IN] xprt * * @return 0 on success, the value of errno on error */ int rpc_rdma_accept_finalize(RDMAXPRT *xprt) { struct rdma_conn_param conn_param; int rc; if (!xprt || xprt->state != RDMAXS_CONNECT_REQUEST) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] isn't from a connection request?", __func__, xprt, xprt->state); return EINVAL; } memset(&conn_param, 0, sizeof(conn_param)); conn_param.responder_resources = 1; conn_param.initiator_depth = 1; conn_param.private_data = NULL; conn_param.private_data_len = 0; conn_param.rnr_retry_count = 10; rc = rdma_accept(xprt->cm_id, &conn_param); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_accept failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); } return rc; } /** * rpc_rdma_accept_timedwait: given a listening xprt, * waits till any connection is requested and accepts one, * then clones the listener. * * @param[IN] l_xprt listening (parent) transport * @param[IN] abstime time to wait * * @return 0 on success, errno value on failure */ static RDMAXPRT * rpc_rdma_accept_timedwait(RDMAXPRT *l_xprt, struct timespec *abstime) { struct rdma_cm_id *cm_id; uint32_t u; int rc; if (!l_xprt || l_xprt->state != RDMAXS_LISTENING) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] isn't listening (after bind_server)?", __func__, l_xprt, l_xprt->state); return (NULL); } /* Drain connection_requests */ if (abstime) { rc = sem_timedwait(&rpc_rdma_state.c_r.q_sem, abstime); if (rc) { rc = errno; if (ETIMEDOUT == rc) { __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() ETIMEDOUT", __func__); } else { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() sem_timedwait failed", __func__, strerror(rc), rc); } return (NULL); } } else { rc = sem_wait(&rpc_rdma_state.c_r.q_sem); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() sem_wait failed", __func__, strerror(rc), rc); return (NULL); } } u = atomic_postinc_uint32_t(&rpc_rdma_state.c_r.q_head); if (u >= rpc_rdma_state.c_r.q_size) { u_int q_mask = rpc_rdma_state.c_r.q_size - 1; /* masking allows update by lock-free tasks, * as long as overrun never 2 * q_size */ u &= q_mask; atomic_clear_uint32_t_bits(&rpc_rdma_state.c_r.q_head, ~q_mask); } cm_id = rpc_rdma_state.c_r.id_queue[u]; /* Increase available count */ rc = sem_post(&rpc_rdma_state.c_r.u_sem); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() sem_post failed", __func__, strerror(rc), rc); return (NULL); } __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() thread %lx, q %u, cm_id %p", __func__, pthread_self(), u, cm_id); if (!cm_id) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() missing cm_id", __func__); return (NULL); } return rpc_rdma_clone(l_xprt, cm_id); } RDMAXPRT * rpc_rdma_accept_wait(RDMAXPRT *l_xprt,int msleep) { struct timespec ts; if (msleep == 0) return rpc_rdma_accept_timedwait(l_xprt, NULL); clock_gettime(CLOCK_REALTIME, &ts); ts.tv_sec += msleep / 1000; ts.tv_nsec += (msleep % 1000) * NSEC_IN_SEC; if (ts.tv_nsec >= NSEC_IN_SEC) { ts.tv_nsec -= NSEC_IN_SEC; ts.tv_sec++; } return rpc_rdma_accept_timedwait(l_xprt, &ts); } /** * rpc_rdma_bind_client: resolve addr and route for the client and waits till it's done * (the route and cond_signal is done in the cm thread) * */ static int rpc_rdma_bind_client(RDMAXPRT *xprt) { struct rdma_addrinfo hints; struct rdma_addrinfo *res; int rc; mutex_lock(&xprt->cm_lock); do { memset(&hints, 0, sizeof(hints)); hints.ai_port_space = xprt->conn_type; rc = rdma_getaddrinfo(xprt->xa->node, xprt->xa->port, &hints, &res); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_getaddrinfo: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); break; } rc = rdma_resolve_addr(xprt->cm_id, res->ai_src_addr, res->ai_dst_addr, xprt->xa->timeout); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_resolve_addr failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); break; } rdma_freeaddrinfo(res); while (xprt->state == RDMAXS_INITIAL) { cond_wait(&xprt->cm_cond, &xprt->cm_lock); __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] after cond_wait", __func__, xprt, xprt->state); } if (xprt->state != RDMAXS_ADDR_RESOLVED) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Could not resolve addr", __func__); rc = EINVAL; break; } rc = rdma_resolve_route(xprt->cm_id, xprt->xa->timeout); if (rc) { xprt->state = RDMAXS_ERROR; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_resolve_route failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); break; } while (xprt->state == RDMAXS_ADDR_RESOLVED) { cond_wait(&xprt->cm_cond, &xprt->cm_lock); __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() %p[%u] after cond_wait", __func__, xprt, xprt->state); } if (xprt->state != RDMAXS_ROUTE_RESOLVED) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Could not resolve route", __func__); rc = EINVAL; break; } } while (0); mutex_unlock(&xprt->cm_lock); return rc; } /** * rpc_rdma_connect_finalize: tells the other side we're ready to receive stuff * (does the actual rdma_connect) * N.B. no wait for CM result. CM event thread will handle setup/teardown. * * @param[IN] xprt * * @return 0 on success, errno value on failure */ int rpc_rdma_connect_finalize(RDMAXPRT *xprt) { struct rdma_conn_param conn_param; int rc; if (!xprt || xprt->state != RDMAXS_ROUTE_RESOLVED) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] isn't half-connected?", __func__, xprt, xprt->state); return EINVAL; } memset(&conn_param, 0, sizeof(conn_param)); conn_param.responder_resources = 1; conn_param.initiator_depth = 1; conn_param.rnr_retry_count = 10; conn_param.retry_count = 10; rc = rdma_connect(xprt->cm_id, &conn_param); if (rc) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rdma_connect failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); } return rc; } /** * rpc_rdma_connect: connects a client to a server * * @param[INOUT] xprt must be init first * * @return 0 on success, errno value on failure */ int rpc_rdma_connect(RDMAXPRT *xprt) { int rc; if (!xprt || xprt->state != RDMAXS_INITIAL) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] must be initialized first!", __func__, xprt, xprt->state); return EINVAL; } if (xprt->server) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() only called from client side!", __func__); return EINVAL; } rc = rpc_rdma_thread_create_epoll(&rpc_rdma_state.cm_thread, rpc_rdma_cm_thread, xprt, &rpc_rdma_state.cm_epollfd); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] rpc_rdma_thread_create_epoll failed: %s (%d)", __func__, xprt, xprt->state, strerror(rc), rc); return rc; } rc = rpc_rdma_bind_client(xprt); if (rc) return rc; rc = rpc_rdma_pd_get(xprt); if (rc) return rc; rc = rpc_rdma_setup_stuff(xprt); if (rc) { rpc_rdma_destroy_stuff(xprt); return rc; } rc = rpc_rdma_setup_cbq(&xprt->cbqh, xprt->xa->rq_depth + xprt->xa->sq_depth, xprt->xa->credits); if (rc) return rc; return rpc_rdma_fd_add(xprt, xprt->event_channel->fd, rpc_rdma_state.cm_epollfd); } static struct xp_ops rpc_rdma_ops = { /* XXX wow */ .xp_getargs = (bool(*)(SVCXPRT *, struct svc_req *, xdrproc_t, void *, void *))abort, .xp_reply = (bool(*)(SVCXPRT *, struct svc_req *, struct rpc_msg *))abort, .xp_freeargs = (bool(*)(SVCXPRT *, struct svc_req *, xdrproc_t, void *))abort, }; ntirpc-1.3.1/src/rpc_rdma.h000066400000000000000000000165701261345040100155470ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * Dominique Martinet * contributeur : William Allen Simpson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /** * \file rpc_rdma.h * \brief rdma helper include file * * This was (very) loosely based on the Mooshika library, which in turn * was a mix of diod, rping (librdmacm/examples), and Linux kernel's * net/9p/trans_rdma.c (dual BSD/GPL license). No vestiges remain. */ #ifndef _TIRPC_RPC_RDMA_H #define _TIRPC_RPC_RDMA_H #include #include #include #include typedef union sockaddr_union { struct sockaddr sa; struct sockaddr_in sa_in; struct sockaddr_in6 sa_int6; struct sockaddr_storage sa_stor; } sockaddr_union_t; struct msk_stats { uint64_t rx_bytes; uint64_t rx_pkt; uint64_t rx_err; uint64_t tx_bytes; uint64_t tx_pkt; uint64_t tx_err; /* times only set if debug has MSK_DEBUG_SPEED */ uint64_t nsec_callback; uint64_t nsec_compevent; }; typedef struct rpc_rdma_xprt RDMAXPRT; struct rpc_rdma_cbc; typedef void (*rpc_rdma_callback_t)(struct rpc_rdma_cbc *cbc, RDMAXPRT *xprt); /** * \struct rpc_rdma_cbc * Context data we can use during recv/send callbacks */ struct rpc_rdma_cbc { struct xdr_ioq workq; struct xdr_ioq holdq; struct xdr_ioq_uv *call_uv; void *read_chunk; /* current in indexed list of arrays */ void *write_chunk; /* current in list of arrays */ void *reply_chunk; /* current in array */ void *call_data; struct work_pool_entry wpe; rpc_rdma_callback_t positive_cb; rpc_rdma_callback_t negative_cb; void *callback_arg; union { struct ibv_recv_wr rwr; struct ibv_send_wr wwr; } wr; enum ibv_wc_opcode opcode; enum ibv_wc_status status; struct ibv_sge sg_list[0]; /**< this is actually an array. note that when you malloc you have to add its size */ }; struct rpc_rdma_pd { LIST_ENTRY(rpc_rdma_pd) pdl; struct ibv_context *context; struct ibv_pd *pd; struct ibv_srq *srq; struct poolq_head srqh; /**< shared read contexts */ uint32_t pd_used; }; #define RDMAX_CLIENT 0 #define RDMAX_SERVER_CHILD -1 /** * \struct rpc_rdma_xprt * RDMA transport instance */ struct rpc_rdma_xprt { struct rpc_svcxprt xprt; /**< Transport Independent handle */ struct rpc_rdma_attr *xa; /**< (shared) configured attributes */ struct rdma_event_channel *event_channel; struct rdma_cm_id *cm_id; /**< RDMA CM ID */ struct rpc_rdma_pd *pd; /**< RDMA PD entry */ struct ibv_comp_channel *comp_channel; struct ibv_cq *cq; /**< Completion Queue pointer */ struct ibv_qp *qp; /**< Queue Pair pointer */ struct ibv_srq *srq; /**< Shared Receive Queue pointer */ struct ibv_recv_wr *bad_recv_wr; struct ibv_send_wr *bad_send_wr; struct ibv_mr *mr; u_int8_t *buffer_aligned; size_t buffer_total; /* waiting contexts posted */ struct xdr_ioq waitq; struct xdr_ioq_uv_head inbufs; /* recvsize */ struct xdr_ioq_uv_head outbufs; /* sendsz */ struct poolq_head cbqh; /**< combined callback contexts */ mutex_t cm_lock; /**< lock for connection events */ cond_t cm_cond; /**< cond for connection events */ struct msk_stats stats; int stats_sock; u_int recvsize; u_int sendsize; u_int conn_type; /**< RDMA Port space (RDMA_PS_TCP) */ int server; /**< connection backlog on server, * 0 (RDMAX_CLIENT): * client, * -1 (RDMAX_SERVER_CHILD): * server has accepted connection */ enum rdma_transport_state { RDMAXS_INITIAL, /* assumes zero, never set */ RDMAXS_LISTENING, RDMAXS_ADDR_RESOLVED, RDMAXS_ROUTE_RESOLVED, RDMAXS_CONNECT_REQUEST, RDMAXS_CONNECTED, RDMAXS_CLOSING, RDMAXS_CLOSED, RDMAXS_ERROR, /* always last */ } state; /**< transport state machine */ /* FIXME why configurable??? */ bool destroy_on_disconnect; /**< should perform cleanup */ }; typedef struct rec_rdma_strm { RDMAXPRT *xprt; /* * out-going bits */ int (*writeit)(void *, void *, int); TAILQ_HEAD(out_buffers_head, xdr_ioq_uv) out_buffers; 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 frag_sent; /* true if buffer sent in middle of record */ /* * in-coming bits */ TAILQ_HEAD(in_buffers_head, xdr_ioq_uv) in_buffers; 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 last_frag; u_int sendsize; u_int recvsize; bool nonblock; u_int32_t in_header; char *in_hdrp; int in_hdrlen; int in_reclen; int in_received; int in_maxrec; cond_t cond; mutex_t lock; uint8_t *rdmabuf; struct ibv_mr *mr; int credits; } RECRDMA; static inline void *xdr_encode_hyper(uint32_t *iptr, uint64_t val) { *iptr++ = htonl((uint32_t)((val >> 32) & 0xffffffff)); *iptr++ = htonl((uint32_t)(val & 0xffffffff)); return iptr; } static inline uint64_t xdr_decode_hyper(uint64_t *iptr) { return ((uint64_t) ntohl(((uint32_t*)iptr)[0]) << 32) | (ntohl(((uint32_t*)iptr)[1])); } void rpc_rdma_internals_init(void); void rpc_rdma_internals_fini(void); /* server specific */ int rpc_rdma_accept_finalize(RDMAXPRT *xprt); RDMAXPRT *rpc_rdma_accept_wait(RDMAXPRT *l_xprt, int msleep); void rpc_rdma_destroy(SVCXPRT *s_xprt); /* client */ int rpc_rdma_connect(RDMAXPRT *xprt); int rpc_rdma_connect_finalize(RDMAXPRT *xprt); /* XDR functions */ int xdr_rdma_create(XDR *, RDMAXPRT *, const u_int sendsize, const u_int recvsize, const u_int flags); void xdr_rdma_destroy(XDR *xdrs); bool xdr_rdma_clnt_call(XDR *, u_int32_t); bool xdr_rdma_clnt_reply(XDR *, u_int32_t); bool xdr_rdma_clnt_flushout(XDR *); bool xdr_rdma_svc_recv(struct rpc_rdma_cbc *, u_int32_t); bool xdr_rdma_svc_reply(struct rpc_rdma_cbc *, u_int32_t); bool xdr_rdma_svc_flushout(struct rpc_rdma_cbc *); #endif /* !_TIRPC_RPC_RDMA_H */ ntirpc-1.3.1/src/rpc_soc.c000066400000000000000000000361201261345040100153740ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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. */ #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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" extern mutex_t rpcsoc_lock; static CLIENT *clnt_com_ncreate(struct sockaddr_in *, rpcprog_t, rpcvers_t, int *, u_int, u_int, char *, int); static SVCXPRT *svc_com_ncreate(int, u_int, u_int, char *); static bool rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *); /* XXX */ #define IN4_LOCALHOST_STRING "127.0.0.1" #define IN6_LOCALHOST_STRING "::1" /* XXX */ #ifndef SOCK_CLOEXEC #define SOCK_CLOEXEC 02000000 #endif /* * A common clnt create routine */ static CLIENT * clnt_com_ncreate(struct sockaddr_in *raddr, rpcprog_t prog, rpcvers_t vers, int *sockp, u_int sendsz, u_int recvsz, char *tp, int flags) { CLIENT *cl; int madefd = FALSE; int fd = *sockp; struct netconfig *nconf; struct netbuf bindaddr; mutex_lock(&rpcsoc_lock); nconf = __rpc_getconfip(tp); if (!nconf) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; mutex_unlock(&rpcsoc_lock); return (NULL); } if (fd == RPC_ANYSOCK) { static int have_cloexec; fd = __rpc_nconf2fd_flags(nconf, flags); if (fd == -1) { if ((flags & SOCK_CLOEXEC) && have_cloexec <= 0) { fd = __rpc_nconf2fd(nconf); if (fd == -1) goto syserror; if (flags & SOCK_CLOEXEC) { have_cloexec = -1; (void) fcntl(fd, F_SETFD, FD_CLOEXEC); } } else goto syserror; } else if (flags & SOCK_CLOEXEC) have_cloexec = 1; 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_ncreate(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); } /* XXX suspicious */ CLIENT * __libc_clntudp_nbufcreate(struct sockaddr_in *raddr, u_long prog, u_long vers, struct timeval wait, int *sockp, u_int sendsz, u_int recvsz, int flags) { CLIENT *cl; cl = clnt_com_ncreate(raddr, (rpcprog_t) prog, (rpcvers_t) vers, sockp, sendsz, recvsz, "udp", flags); if (cl == NULL) return (NULL); (void)CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait); return (cl); } CLIENT * clntudp_nbufcreate(struct sockaddr_in *raddr, u_long prog, u_long vers, struct timeval wait, int *sockp, u_int sendsz, u_int recvsz) { CLIENT *cl; cl = clnt_com_ncreate(raddr, (rpcprog_t) prog, (rpcvers_t) vers, sockp, sendsz, recvsz, "udp", 0); if (cl == NULL) return (NULL); (void)CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait); return (cl); } CLIENT * clntudp_create(struct sockaddr_in *raddr, u_long program, u_long version, struct timeval wait, int *sockp) { return clntudp_nbufcreate(raddr, program, version, wait, sockp, UDPMSGSIZE, UDPMSGSIZE); } CLIENT * clnttcp_create(struct sockaddr_in *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) { return clnt_com_ncreate(raddr, (rpcprog_t) prog, (rpcvers_t) vers, sockp, sendsz, recvsz, "tcp", 0); } /* IPv6 version of clnt*_*create */ #ifdef INET6_NOT_USED CLIENT * clntudp6_nbufcreate(struct sockaddr_in6 *raddr, u_long prog, u_long vers, struct timeval wait, int *sockp, u_int sendsz, u_int recvsz) { CLIENT *cl; cl = clnt_com_ncreate(raddr, (rpcprog_t) prog, (rpcvers_t) vers, sockp, sendsz, recvsz, "udp6", 0); if (cl == NULL) return (NULL); (void)CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait); return (cl); } CLIENT * clntudp6_ncreate(struct sockaddr_in6 *raddr, u_long program, u_long version, struct timeval wait, int *sockp) { return clntudp6_nbufcreate(raddr, program, version, wait, sockp, UDPMSGSIZE, UDPMSGSIZE); } CLIENT * clnttcp6_ncreate(struct sockaddr_in6 *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) { return clnt_com_ncreate(raddr, (rpcprog_t) prog, (rpcvers_t) vers, sockp, sendsz, recvsz, "tcp6", 0); } #endif CLIENT * clntraw_create(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_ncreate(int fd, u_int sendsize, u_int recvsize, char *netid) { struct netconfig *nconf; SVCXPRT *svc; int madefd = FALSE; int port; struct sockaddr_in sin; nconf = __rpc_getconfip(netid); if (!nconf) { (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(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; bindresvport(fd, &sin); listen(fd, SOMAXCONN); svc = svc_tli_ncreate(fd, nconf, NULL, sendsize, recvsize); (void)freenetconfigent(nconf); if (svc == NULL) { if (madefd) (void)close(fd); return (NULL); } port = (((struct sockaddr_in *)&svc->xp_local.ss)->sin_port); svc->xp_port = ntohs(port); return (svc); } SVCXPRT * svctcp_create(int fd, u_int sendsize, u_int recvsize) { return svc_com_ncreate(fd, sendsize, recvsize, "tcp"); } SVCXPRT * svcudp_bufcreate(int fd, u_int sendsz, u_int recvsz) { return svc_com_ncreate(fd, sendsz, recvsz, "udp"); } SVCXPRT * svcfd_create(int fd, u_int sendsize, u_int recvsize) { return svc_fd_ncreate(fd, sendsize, recvsize); } SVCXPRT * svcudp_create(int fd) { return svc_com_ncreate(fd, UDPMSGSIZE, UDPMSGSIZE, "udp"); } SVCXPRT * svcraw_create() { return svc_raw_ncreate(); } /* IPV6 version */ #ifdef INET6_NOT_USED SVCXPRT *svcudp6_nbufcreate(int fd, u_int sendsz, u_int recvsz) { return svc_com_ncreate(fd, sendsz, recvsz, "udp6"); } SVCXPRT * svctcp6_ncreate(int fd, u_int sendsize, u_int recvsize) { return svc_com_ncreate(fd, sendsize, recvsize, "tcp6"); } SVCXPRT * svcudp6_ncreate(int fd) { return svc_com_ncreate(fd, UDPMSGSIZE, UDPMSGSIZE, "udp6"); } #endif int get_myaddress(struct sockaddr_in *addr) { 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(const char *host, int prognum, int versnum, int procnum, xdrproc_t inproc, void *in, xdrproc_t outproc, void *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(int prognum, int versnum, int procnum, char *(*progname) (char[UDPMSGSIZE]), xdrproc_t inproc, xdrproc_t outproc) { return rpc_reg((rpcprog_t) prognum, (rpcvers_t) versnum, (rpcproc_t) procnum, progname, inproc, outproc, "udp"); } /* * All the following clnt_broadcast stuff is convulated; it supports * the earlier calling style of the callback function */ extern thread_key_t clnt_broadcast_key; /* * Need to translate the netbuf address into sockaddr_in address. * Dont care about netid here. */ /* ARGSUSED */ static bool rpc_wrap_bcast(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; if (strcmp(nconf->nc_netid, "udp")) return (FALSE); clnt_broadcast_result = (resultproc_t) thr_getspecific(clnt_broadcast_key); return (*clnt_broadcast_result) (resultp, (struct sockaddr_in *)addr->buf); } /* * Broadcasts on UDP transport. Obsoleted by rpc_broadcast(). */ enum clnt_stat clnt_broadcast(u_long prog, /* program number */ u_long vers, /* version number */ u_long proc, /* procedure number */ xdrproc_t xargs, /* xdr routine for args */ void *argsp, /* pointer to args */ xdrproc_t xresults, /* xdr routine for results */ void *resultsp, /* pointer to results */ resultproc_t eachresult /* call with each result obtained */) { extern mutex_t tsd_lock; if (clnt_broadcast_key == -1) { mutex_lock(&tsd_lock); if (clnt_broadcast_key == -1) thr_keycreate(&clnt_broadcast_key, free); /* XXX */ mutex_unlock(&tsd_lock); } thr_setspecific(clnt_broadcast_key, (void *)eachresult); return rpc_broadcast((rpcprog_t) prog, (rpcvers_t) vers, (rpcproc_t) proc, xargs, argsp, xresults, resultsp, (resultproc_t) rpc_wrap_bcast, "udp"); } #if !defined(__APPLE__) #if USE_DES /* * Create the client des authentication object. Obsoleted by * authdes_seccreate(). */ AUTH * authdes_ncreate(char *servername, /* network name of server */ u_int window, /* time to live */ struct sockaddr *syncaddr, /* optional hostaddr to sync with */ des_block *ckey /* optional conversation key to use */) { AUTH *dummy; AUTH *nauth; char hostname[NI_MAXHOST]; if (syncaddr) { /* * Change addr to hostname, because that is the way * new interface takes it. */ if (getnameinfo (syncaddr, sizeof(syncaddr), hostname, sizeof(hostname), NULL, 0, 0) != 0) goto fallback; nauth = authdes_nseccreate(servername, window, hostname, ckey); return (nauth); } fallback: dummy = authdes_nseccreate(servername, window, NULL, ckey); return (dummy); } #endif /* USE_DES */ #endif /* !APPLE */ /* * Create a client handle for a unix connection. Obsoleted by clnt_vc_create() */ CLIENT * clntunix_ncreate(struct sockaddr_un *raddr, u_long prog, u_long vers, int *sockp, u_int sendsz, u_int recvsz) { struct netbuf *svcaddr; CLIENT *cl = NULL; int len; svcaddr = mem_alloc(sizeof(struct netbuf)); if (svcaddr) svcaddr->buf = mem_alloc(sizeof(struct sockaddr_un)); if ((!svcaddr) || (!svcaddr->buf)) { if (svcaddr) mem_free(svcaddr, 0); rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; return (cl); } if (*sockp < 0) { *sockp = socket(AF_LOCAL, SOCK_STREAM, 0); len = SUN_LEN(raddr); if ((*sockp < 0) || (connect(*sockp, (struct sockaddr *)raddr, len) < 0)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; rpc_createerr.cf_error.re_errno = errno; if (*sockp != -1) (void)close(*sockp); goto done; } } svcaddr->buf = raddr; svcaddr->len = sizeof(raddr); svcaddr->maxlen = sizeof(struct sockaddr_un); cl = clnt_vc_ncreate(*sockp, svcaddr, prog, vers, sendsz, recvsz); done: mem_free(svcaddr->buf, 0); mem_free(svcaddr, 0); return (cl); } /* * Creates, registers, and returns a (rpc) unix based transporter. * Obsoleted by svc_vc_create(). */ SVCXPRT * svcunix_ncreate(int sock, u_int sendsize, u_int recvsize, char *path) { struct netconfig *nconf; void *localhandle; struct sockaddr_un sun; struct sockaddr *sa; struct t_bind taddr; SVCXPRT *xprt; int addrlen; xprt = (SVCXPRT *) NULL; localhandle = setnetconfig(); while ((nconf = getnetconfig(localhandle)) != NULL) { if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) break; } if (nconf == NULL) goto done; sock = __rpc_nconf2fd(nconf); if (sock < 0) goto done; memset(&sun, 0, sizeof(sun)); sun.sun_family = AF_LOCAL; strncpy(sun.sun_path, path, sizeof(sun.sun_path)); sun.sun_path[sizeof(sun.sun_path)-1] = 0; addrlen = sizeof(struct sockaddr_un); sa = (struct sockaddr *)&sun; if (bind(sock, sa, addrlen) < 0) goto done; taddr.addr.len = taddr.addr.maxlen = addrlen; taddr.addr.buf = mem_alloc(addrlen); if (taddr.addr.buf == NULL) goto done; memcpy(taddr.addr.buf, sa, addrlen); if (nconf->nc_semantics != NC_TPI_CLTS) { if (listen(sock, SOMAXCONN) < 0) { mem_free(taddr.addr.buf, 0); goto done; } } xprt = (SVCXPRT *) svc_tli_ncreate(sock, nconf, &taddr, sendsize, recvsize); done: endnetconfig(localhandle); if (! xprt) close(sock); return (xprt); } /* * Like svunix_create(), except the routine takes any *open* UNIX file * descriptor as its first input. Obsoleted by svc_fd_create(); */ SVCXPRT * svcunixfd_ncreate(int fd, u_int sendsize, u_int recvsize) { return (svc_fd_create(fd, sendsize, recvsize)); } #endif /* PORTMAP */ ntirpc-1.3.1/src/rpcb_clnt.c000066400000000000000000001024011261345040100157060ustar00rootroot00000000000000/* * Copyright (c) 2010, Oracle America, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of the "Oracle America, Inc." nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * rpcb_clnt.c * interface to rpcbind rpc service. */ #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PORTMAP #include /* FOR IPPROTO_TCP/UDP definitions */ #include #endif /* PORTMAP */ #include #include #include #include #include #include #include #include #include "rpc_com.h" static struct timeval tottimeout = { 60, 0 }; static const struct timeval rmttimeout = { 3, 0 }; static struct timeval rpcbrmttime = { 15, 0 }; extern bool xdr_wrapstring(XDR *, char **); static const char nullstring[] = "\000"; #define RPCB_OWNER_STRING "libntirpc" #define CACHESIZE 6 struct address_cache { char *ac_host; char *ac_netid; char *ac_uaddr; struct netbuf *ac_taddr; struct address_cache *ac_next; }; static struct address_cache *front; static int cachesize; #define CLCR_GET_RPCB_TIMEOUT 1 #define CLCR_SET_RPCB_TIMEOUT 2 extern int __rpc_lowvers; static struct address_cache *check_cache(const char *, const char *); static void delete_cache(struct netbuf *); static void add_cache(const char *, const char *, struct netbuf *, char *); static CLIENT *getclnthandle(const char *, const struct netconfig *, char **); static CLIENT *local_rpcb(void); #ifdef NOTUSED static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *); #endif /* * This routine adjusts the timeout used for calls to the remote rpcbind. * Also, this routine can be used to set the use of portmapper version 2 * only when doing rpc_broadcasts * These are private routines that may not be provided in future releases. */ bool __rpc_control(int request, void *info) { switch (request) { case CLCR_GET_RPCB_TIMEOUT: *(struct timeval *)info = tottimeout; break; case CLCR_SET_RPCB_TIMEOUT: tottimeout = *(struct timeval *)info; break; case CLCR_SET_LOWVERS: __rpc_lowvers = *(int *)info; break; case CLCR_GET_LOWVERS: *(int *)info = __rpc_lowvers; break; default: return (false); } return (true); } /* * It might seem that a reader/writer lock would be more reasonable here. * However because getclnthandle(), the only user of the cache functions, * may do a delete_cache() operation if a check_cache() fails to return an * address useful to clnt_tli_ncreate(), we may as well use a mutex. */ /* * As it turns out, if the cache lock is *not* a reader/writer lock, we will * block all clnt_ncreate's if we are trying to connect to a host that's down, * since the lock will be held all during that time. */ extern rwlock_t rpcbaddr_cache_lock; /* * The routines check_cache(), add_cache(), delete_cache() manage the * cache of rpcbind addresses for (host, netid). */ static struct address_cache * check_cache(const char *host, const char *netid) { struct address_cache *cptr; /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { if (!strcmp(cptr->ac_host, host) && !strcmp(cptr->ac_netid, netid)) { #ifdef ND_DEBUG fprintf(stderr, "Found cache entry for %s: %s\n", host, netid); #endif return (cptr); } } return ((struct address_cache *)NULL); } static void delete_cache(struct netbuf *addr) { struct address_cache *cptr, *prevptr = NULL; /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */ for (cptr = front; cptr != NULL; cptr = cptr->ac_next) { if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) { mem_free(cptr->ac_host, 0); /* XXX */ mem_free(cptr->ac_netid, 0); mem_free(cptr->ac_taddr->buf, 0); mem_free(cptr->ac_taddr, 0); if (cptr->ac_uaddr) mem_free(cptr->ac_uaddr, 0); if (prevptr) prevptr->ac_next = cptr->ac_next; else front = cptr->ac_next; mem_free(cptr, 0); cachesize--; break; } prevptr = cptr; } } static void add_cache(const char *host, const char *netid, struct netbuf *taddr, char *uaddr) { struct address_cache *ad_cache, *cptr, *prevptr; ad_cache = (struct address_cache *) mem_zalloc(sizeof(struct address_cache)); if (!ad_cache) return; ad_cache->ac_host = (host) ? rpc_strdup(host) : NULL; ad_cache->ac_netid = rpc_strdup(netid); ad_cache->ac_uaddr = uaddr ? rpc_strdup(uaddr) : NULL; ad_cache->ac_taddr = (struct netbuf *)mem_zalloc(sizeof(struct netbuf)); if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr || (uaddr && !ad_cache->ac_uaddr)) goto out_free; ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len; ad_cache->ac_taddr->buf = (char *)mem_zalloc(taddr->len); if (ad_cache->ac_taddr->buf == NULL) goto out_free; memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len); #ifdef ND_DEBUG fprintf(stderr, "Added to cache: %s : %s\n", host, netid); #endif /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */ rwlock_wrlock(&rpcbaddr_cache_lock); if (cachesize < CACHESIZE) { ad_cache->ac_next = front; front = ad_cache; cachesize++; } else { /* Free the last entry */ cptr = front; prevptr = NULL; while (cptr->ac_next) { prevptr = cptr; cptr = cptr->ac_next; } #ifdef ND_DEBUG fprintf(stderr, "Deleted from cache: %s : %s\n", cptr->ac_host, cptr->ac_netid); #endif mem_free(cptr->ac_host, 0); /* XXX */ mem_free(cptr->ac_netid, 0); mem_free(cptr->ac_taddr->buf, 0); mem_free(cptr->ac_taddr, 0); if (cptr->ac_uaddr) mem_free(cptr->ac_uaddr, 0); if (prevptr) { prevptr->ac_next = NULL; ad_cache->ac_next = front; front = ad_cache; } else { front = ad_cache; ad_cache->ac_next = NULL; } mem_free(cptr, 0); } rwlock_unlock(&rpcbaddr_cache_lock); return; out_free: mem_free(ad_cache->ac_host, 0); /* XXX */ mem_free(ad_cache->ac_netid, 0); mem_free(ad_cache->ac_uaddr, 0); mem_free(ad_cache->ac_taddr, 0); mem_free(ad_cache, 0); } /* * This routine will return a client handle that is connected to the * rpcbind. If targaddr is non-NULL, the "universal address" of the * host will be stored in *targaddr; the caller is responsible for * freeing this string. * On error, returns NULL and free's everything. */ static CLIENT *getclnthandle(const char *host, const struct netconfig *nconf, char **targaddr) { CLIENT *client; struct netbuf *addr, taddr; struct netbuf addr_to_delete; struct __rpc_sockinfo si; struct addrinfo hints, *res, *tres; struct address_cache *ad_cache; char *tmpaddr; memset(&addr_to_delete, '\0', sizeof(addr_to_delete)); /* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */ /* Get the address of the rpcbind. Check cache first */ client = NULL; if (targaddr) *targaddr = NULL; addr_to_delete.len = 0; rwlock_rdlock(&rpcbaddr_cache_lock); ad_cache = NULL; if (host != NULL) ad_cache = check_cache(host, nconf->nc_netid); if (ad_cache != NULL) { addr = ad_cache->ac_taddr; client = clnt_tli_ncreate(RPC_ANYFD, nconf, addr, (rpcprog_t) RPCBPROG, (rpcvers_t) RPCBVERS4, 0, 0); if (client != NULL) { if (targaddr) *targaddr = rpc_strdup(ad_cache->ac_uaddr); rwlock_unlock(&rpcbaddr_cache_lock); return (client); } addr_to_delete.len = addr->len; addr_to_delete.buf = (char *)mem_zalloc(addr->len); if (addr_to_delete.buf == NULL) addr_to_delete.len = 0; else memcpy(addr_to_delete.buf, addr->buf, addr->len); } rwlock_unlock(&rpcbaddr_cache_lock); if (addr_to_delete.len != 0) { /* * Assume this may be due to cache data being * outdated */ rwlock_wrlock(&rpcbaddr_cache_lock); delete_cache(&addr_to_delete); rwlock_unlock(&rpcbaddr_cache_lock); mem_free(addr_to_delete.buf, 0); /* XXX */ } if (!__rpc_nconf2sockinfo(nconf, &si)) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; assert(client == NULL); goto out_err; } memset(&hints, 0, sizeof(hints)); hints.ai_family = si.si_af; hints.ai_socktype = si.si_socktype; hints.ai_protocol = si.si_proto; #ifdef CLNT_DEBUG __warnx("%s: trying netid %s family %d proto %d socktype %d\n", __func__, nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype); #endif if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) { client = local_rpcb(); if (!client) { #ifdef ND_DEBUG clnt_pcreateerror("rpcbind clnt interface"); #endif goto out_err; } else { struct sockaddr_un sun; if (targaddr) { *targaddr = mem_zalloc(sizeof(sun.sun_path)); strncpy(*targaddr, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); } return (client); } } else { if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) { rpc_createerr.cf_stat = RPC_UNKNOWNHOST; assert(client == NULL); goto out_err; } } for (tres = res; tres != NULL; tres = tres->ai_next) { taddr.buf = tres->ai_addr; taddr.len = taddr.maxlen = tres->ai_addrlen; #ifdef ND_DEBUG { char *ua; ua = taddr2uaddr(nconf, &taddr); fprintf(stderr, "Got it [%s]\n", ua); mem_free(ua, 0); /* XXX */ } #endif #ifdef ND_DEBUG { int i; fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n", taddr.len, taddr.maxlen); fprintf(stderr, "\tAddress is "); for (i = 0; i < taddr.len; i++) fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]); fprintf(stderr, "\n"); } #endif client = clnt_tli_ncreate(RPC_ANYFD, nconf, &taddr, (rpcprog_t) RPCBPROG, (rpcvers_t) RPCBVERS4, 0, 0); #ifdef ND_DEBUG if (!client) clnt_pcreateerror("rpcbind clnt interface"); #endif if (client) { tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL; add_cache(host, nconf->nc_netid, &taddr, tmpaddr); if (targaddr) *targaddr = tmpaddr; break; } } if (res) freeaddrinfo(res); out_err: if (!client && targaddr) mem_free(*targaddr, 0); return (client); } /* * Set a mapping between program, version and address. * Calls the rpcbind service to do the mapping. */ bool rpcb_set(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf, /* Network structure of transport */ const struct netbuf *address /* Services netconfig address */) { RPCB parms; char uidbuf[32]; bool_t rslt = false; /* yes, bool_t */ CLIENT *client; AUTH *auth; /* parameter checking */ if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (false); } if (address == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNADDR; return (false); } client = local_rpcb(); if (!client) return (false); auth = authnone_ncreate(); /* idempotent */ /* convert to universal */ /*LINTED const castaway */ parms.r_addr = taddr2uaddr((struct netconfig *)nconf, (struct netbuf *)address); if (!parms.r_addr) { CLNT_DESTROY(client); rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; return (false); /* no universal address */ } parms.r_prog = program; parms.r_vers = version; parms.r_netid = nconf->nc_netid; /* * Though uid is not being used directly, we still send it for * completeness. For non-unix platforms, perhaps some other * string or an empty string can be sent. */ (void)snprintf(uidbuf, sizeof(uidbuf), "%d", geteuid()); parms.r_owner = uidbuf; CLNT_CALL(client, auth, RPCBPROC_SET, (xdrproc_t) xdr_rpcb, (char *)&parms, (xdrproc_t) xdr_bool, (char *)&rslt, tottimeout); CLNT_DESTROY(client); mem_free(parms.r_addr, 0); return (rslt); } /* * Remove the mapping between program, version and netbuf address. * Calls the rpcbind service to do the un-mapping. * If netbuf is NULL, unset for all the transports, otherwise unset * only for the given transport. */ bool rpcb_unset(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf) { RPCB parms; char uidbuf[32]; bool_t rslt = false; /* yes, bool_t */ CLIENT *client; AUTH *auth; client = local_rpcb(); if (!client) return (false); auth = authnone_ncreate(); /* idempotent */ parms.r_prog = program; parms.r_vers = version; if (nconf) parms.r_netid = nconf->nc_netid; else { /*LINTED const castaway */ parms.r_netid = (char *)&nullstring[0]; /* unsets all */ } /*LINTED const castaway */ parms.r_addr = (char *)&nullstring[0]; (void)snprintf(uidbuf, sizeof(uidbuf), "%d", geteuid()); parms.r_owner = uidbuf; CLNT_CALL(client, auth, RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, (xdrproc_t) xdr_bool, (char *)(void *)&rslt, tottimeout); CLNT_DESTROY(client); return (rslt); } #ifdef NOTUSED /* * From the merged list, find the appropriate entry */ static struct netbuf * got_entry(rpcb_entry_list_ptr relp, const struct netconfig *nconf) { struct netbuf *na = NULL; rpcb_entry_list_ptr sp; rpcb_entry *rmap; for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) { rmap = &sp->rpcb_entry_map; if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) && (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) && (nconf->nc_semantics == rmap->r_nc_semantics) && (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) { na = uaddr2taddr(nconf, rmap->r_maddr); #ifdef ND_DEBUG fprintf(stderr, "\tRemote address is [%s].\n", rmap->r_maddr); if (!na) fprintf(stderr, "\tCouldn't resolve remote address!\n"); #endif break; } } return (na); } #endif /* * Quick check to see if rpcbind is up. Tries to connect over * local transport. */ bool __rpcbind_is_up(void) { struct netconfig *nconf; struct sockaddr_un sun; void *localhandle; int sock; nconf = NULL; localhandle = setnetconfig(); if (localhandle == NULL) return (false); while ((nconf = getnetconfig(localhandle)) != NULL) { if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) break; } endnetconfig(localhandle); if (nconf == NULL) return (false); memset(&sun, 0, sizeof(sun)); sock = socket(AF_LOCAL, SOCK_STREAM, 0); if (sock < 0) return (false); sun.sun_family = AF_LOCAL; strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path)); if (connect(sock, (struct sockaddr *)&sun, sizeof(sun)) < 0) { close(sock); return (false); } close(sock); return (true); } /* * An internal function which optimizes rpcb_getaddr function. It also * returns the client handle that it uses to contact the remote rpcbind. * * The algorithm used: If the transports is TCP or UDP, it first tries * version 2 (portmap), 4 and then 3 (svr4). This order should be * changed in the next OS release to 4, 2 and 3. We are assuming that by * that time, version 4 would be available on many machines on the network. * With this algorithm, we get performance as well as a plan for * obsoleting version 2. * * For all other transports, the algorithm remains as 4 and then 3. * * XXX: Due to some problems with t_connect(), we do not reuse the same client * handle for COTS cases and hence in these cases we do not return the * client handle. This code will change if t_connect() ever * starts working properly. Also look under clnt_vc.c. */ struct netbuf * __rpcb_findaddr_timed(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf, const char *host, CLIENT **clpp, struct timeval *tp) { #ifdef NOTUSED static bool check_rpcbind = true; #endif RPCB parms; enum clnt_stat clnt_st; char *ua = NULL; rpcvers_t vers; struct netbuf *address = NULL; rpcvers_t start_vers = RPCBVERS4; struct netbuf servaddr; CLIENT *client = NULL; AUTH *auth; /* parameter checking */ if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } parms.r_addr = NULL; /* authnone handle */ auth = authnone_ncreate(); /* idempotent */ /* * Use default total timeout if no timeout is specified. */ if (tp == NULL) tp = &tottimeout; #ifdef PORTMAP /* Try version 2 for TCP or UDP */ if (strcmp(nconf->nc_protofmly, NC_INET) == 0) { u_short port = 0; struct netbuf remote; rpcvers_t pmapvers = 2; struct pmap pmapparms; /* * Try UDP only - there are some portmappers out * there that use UDP only. */ if (strcmp(nconf->nc_proto, NC_TCP) == 0) { struct netconfig *newnconf; newnconf = getnetconfigent("udp"); if (!newnconf) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } client = getclnthandle(host, newnconf, &parms.r_addr); freenetconfigent(newnconf); } else if (strcmp(nconf->nc_proto, NC_UDP) == 0) client = getclnthandle(host, nconf, &parms.r_addr); else goto try_rpcbind; if (client == NULL) return (NULL); /* * Set version and retry timeout. */ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers); pmapparms.pm_prog = program; pmapparms.pm_vers = version; pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ? IPPROTO_UDP : IPPROTO_TCP; pmapparms.pm_port = 0; /* not needed */ clnt_st = CLNT_CALL(client, auth, PMAPPROC_GETPORT, (xdrproc_t) xdr_pmap, (caddr_t) (void *)&pmapparms, (xdrproc_t) xdr_u_short, (caddr_t) (void *)&port, *tp); if (clnt_st != RPC_SUCCESS) { if ((clnt_st == RPC_PROGVERSMISMATCH) || (clnt_st == RPC_PROGUNAVAIL)) goto try_rpcbind; rpc_createerr.cf_stat = RPC_PMAPFAILURE; clnt_geterr(client, &rpc_createerr.cf_error); goto error; } else if (port == 0) { address = NULL; rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; goto error; } port = htons(port); CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote); address = (struct netbuf *) mem_zalloc(sizeof(struct netbuf)); if (address) address->buf = (char *) mem_zalloc(remote.len); if ((!address) || (!address->buf)) { rpc_createerr.cf_stat = RPC_SYSTEMERROR; clnt_geterr(client, &rpc_createerr.cf_error); if (address) { mem_free(address, 0); address = NULL; } goto error; } memcpy(address->buf, remote.buf, remote.len); memcpy(&((char *)address->buf)[sizeof(short)], (char *)(void *)&port, sizeof(short)); address->len = address->maxlen = remote.len; goto done; } try_rpcbind: #endif /* PORTMAP */ parms.r_prog = program; parms.r_vers = version; parms.r_netid = nconf->nc_netid; /* * rpcbind ignores the r_owner field in GETADDR requests, but we * need to give xdr_rpcb something to gnaw on. Might as well make * it something human readable for when we see these in captures. */ parms.r_owner = RPCB_OWNER_STRING; /* Now the same transport is to be used to get the address */ if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) || (nconf->nc_semantics == NC_TPI_COTS))) { /* A CLTS type of client - destroy it */ CLNT_DESTROY(client); client = NULL; mem_free(parms.r_addr, 0); parms.r_addr = NULL; } if (client == NULL) { client = getclnthandle(host, nconf, &parms.r_addr); if (client == NULL) goto error; } if (parms.r_addr == NULL) { /*LINTED const castaway */ parms.r_addr = (char *)&nullstring[0]; } /* First try from start_vers(4) and then version 3 (RPCBVERS) */ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime); for (vers = start_vers; vers >= RPCBVERS; vers--) { /* Set the version */ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); clnt_st = CLNT_CALL(client, auth, RPCBPROC_GETADDR, (xdrproc_t) xdr_rpcb, (char *)(void *)&parms, (xdrproc_t) xdr_wrapstring, (char *)(void *)&ua, *tp); if (clnt_st == RPC_SUCCESS) { if ((ua == NULL) || (ua[0] == 0)) { /* address unknown */ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; goto error; } address = uaddr2taddr(nconf, ua); #ifdef ND_DEBUG fprintf(stderr, "\tRemote address is [%s]\n", ua); if (!address) fprintf(stderr, "\tCouldn't resolve remote address!\n"); #endif xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&ua); if (!address) { /* We don't know about your universal address */ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE; goto error; } CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)(void *)&servaddr); __rpc_fixup_addr(address, &servaddr); goto done; } else if (clnt_st == RPC_PROGVERSMISMATCH) { struct rpc_err rpcerr; clnt_geterr(client, &rpcerr); if (rpcerr.re_vers.low > RPCBVERS4) goto error; /* a new version, can't handle */ } else if (clnt_st != RPC_PROGUNAVAIL) { /* Cant handle this error */ rpc_createerr.cf_stat = clnt_st; clnt_geterr(client, &rpc_createerr.cf_error); goto error; } } if ((address == NULL) || (address->len == 0)) { rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED; clnt_geterr(client, &rpc_createerr.cf_error); } error: if (client) { CLNT_DESTROY(client); client = NULL; } done: if (nconf->nc_semantics != NC_TPI_CLTS) { /* This client is the connectionless one */ if (client) { CLNT_DESTROY(client); client = NULL; } } if (clpp) *clpp = client; else if (client) CLNT_DESTROY(client); if (parms.r_addr != NULL && parms.r_addr != nullstring) mem_free(parms.r_addr, 0); return (address); } /* * Helper routine to find mapped address (for NLM). */ extern struct netbuf * rpcb_find_mapped_addr(char *nettype, rpcprog_t prog, rpcvers_t vers, char *local_addr) { struct netbuf *nbuf; void *handle = __rpc_setconf(nettype); struct netconfig *nconf = __rpc_getconf(handle); nbuf = __rpcb_findaddr_timed(prog, vers, nconf, local_addr, NULL, NULL); __rpc_endconf(handle); return (nbuf); } /* * Find the mapped address for program, version. * Calls the rpcbind service remotely to do the lookup. * Uses the transport specified in nconf. * Returns false (0) if no map exists, else returns 1. * * Assuming that the address is all properly allocated */ bool rpcb_getaddr(rpcprog_t program, rpcvers_t version, const struct netconfig *nconf, struct netbuf *address, const char *host) { struct netbuf *na; na = __rpcb_findaddr_timed( program, version, (struct netconfig *)nconf, (char *)host, (CLIENT **) NULL, (struct timeval *)NULL); if (!na) return (false); if (na->len > address->maxlen) { /* Too long address */ mem_free(na->buf, 0); mem_free(na, 0); rpc_createerr.cf_stat = RPC_FAILED; return (false); } memcpy(address->buf, na->buf, (size_t) na->len); address->len = na->len; mem_free(na->buf, 0); mem_free(na, 0); return (true); } /* * Get a copy of the current maps. * Calls the rpcbind service remotely to get the maps. * * It returns only a list of the services * It returns NULL on failure. */ rpcblist * rpcb_getmaps(const struct netconfig *nconf, const char *host) { rpcblist_ptr head = NULL; enum clnt_stat clnt_st; rpcvers_t vers = 0; CLIENT *client; AUTH *auth; client = getclnthandle(host, nconf, NULL); if (client == NULL) return (head); auth = authnone_ncreate(); /* idempotent */ clnt_st = CLNT_CALL(client, auth, RPCBPROC_DUMP, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *)(void *)&head, tottimeout); if (clnt_st == RPC_SUCCESS) goto done; if ((clnt_st != RPC_PROGVERSMISMATCH) && (clnt_st != RPC_PROGUNAVAIL)) { rpc_createerr.cf_stat = RPC_RPCBFAILURE; clnt_geterr(client, &rpc_createerr.cf_error); goto done; } /* fall back to earlier version */ CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); if (vers == RPCBVERS4) { vers = RPCBVERS; CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); if (CLNT_CALL (client, auth, RPCBPROC_DUMP, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *)(void *)&head, tottimeout) == RPC_SUCCESS) goto done; } rpc_createerr.cf_stat = RPC_RPCBFAILURE; clnt_geterr(client, &rpc_createerr.cf_error); done: CLNT_DESTROY(client); return (head); } /* * rpcbinder remote-call-service interface. * This routine is used to call the rpcbind remote call service * which will look up a service program in the address 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 rpcb_rmtcall(const struct netconfig *nconf, /* Netconfig structure */ const char *host, /* Remote host name */ rpcprog_t prog, rpcvers_t vers, rpcproc_t proc,/* Remote proc identifiers */ xdrproc_t xdrargs, caddr_t argsp, xdrproc_t xdrres, caddr_t resp, /* Argument and Result */ struct timeval tout, /* Timeout value for this call */ const struct netbuf *addr_ptr /* Preallocated netbuf address */) { enum clnt_stat stat; struct r_rpcb_rmtcallargs a; struct r_rpcb_rmtcallres r; rpcvers_t rpcb_vers; CLIENT *client; AUTH *auth; stat = 0; client = getclnthandle(host, nconf, NULL); if (client == NULL) return (RPC_FAILED); auth = authnone_ncreate(); /* idempotent */ /*LINTED const castaway */ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout); a.prog = prog; a.vers = vers; a.proc = proc; a.args.args_val = argsp; a.xdr_args = xdrargs; r.addr = NULL; r.results.results_val = resp; r.xdr_res = xdrres; for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) { CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers); stat = CLNT_CALL(client, auth, RPCBPROC_CALLIT, (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a, (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout); if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) { struct netbuf *na; /*LINTED const castaway */ na = uaddr2taddr((struct netconfig *)nconf, r.addr); if (!na) { stat = RPC_N2AXLATEFAILURE; /*LINTED const castaway */ ((struct netbuf *)addr_ptr)->len = 0; goto error; } if (na->len > addr_ptr->maxlen) { /* Too long address */ stat = RPC_FAILED; /* XXX A better error no */ mem_free(na->buf, 0); /* XXX */ mem_free(na, 0); /*LINTED const castaway */ ((struct netbuf *)addr_ptr)->len = 0; goto error; } memcpy(addr_ptr->buf, na->buf, (size_t) na->len); /*LINTED const castaway */ ((struct netbuf *)addr_ptr)->len = na->len; mem_free(na->buf, 0); mem_free(na, 0); break; } else if ((stat != RPC_PROGVERSMISMATCH) && (stat != RPC_PROGUNAVAIL)) { goto error; } } error: CLNT_DESTROY(client); if (r.addr) xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr); return (stat); } /* * Gets the time on the remote host. * Returns 1 if succeeds else 0. */ int boolrpcb_gettime(const char *host, time_t *timep) { void *handle; struct netconfig *nconf; rpcvers_t vers; enum clnt_stat st; CLIENT *client = NULL; AUTH *auth; if ((host == NULL) || (host[0] == 0)) { time(timep); return (true); } handle = __rpc_setconf("netpath"); if (!handle) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (false); } rpc_createerr.cf_stat = RPC_SUCCESS; while (client == NULL) { nconf = __rpc_getconf(handle); if (!nconf) { if (rpc_createerr.cf_stat == RPC_SUCCESS) rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; break; } client = getclnthandle(host, nconf, NULL); if (client) break; } __rpc_endconf(handle); if (client == (CLIENT *) NULL) return (false); auth = authnone_ncreate(); /* idempotent */ st = CLNT_CALL(client, auth, RPCBPROC_GETTIME, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) { CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers); if (vers == RPCBVERS4) { /* fall back to earlier version */ vers = RPCBVERS; CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers); st = CLNT_CALL(client, auth, RPCBPROC_GETTIME, (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout); } } CLNT_DESTROY(client); return (st == RPC_SUCCESS ? true : false); } /* * Converts taddr to universal address. This routine should never * really be called because local n2a libraries are always provided. */ char *rpcb_taddr2uaddr(struct netconfig *nconf, struct netbuf *taddr) { CLIENT *client; AUTH *auth = authnone_ncreate(); char *uaddr = NULL; /* parameter checking */ if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } if (taddr == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNADDR; return (NULL); } client = local_rpcb(); if (!client) return (NULL); CLNT_CALL(client, auth, RPCBPROC_TADDR2UADDR, (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout); CLNT_DESTROY(client); return (uaddr); } /* * Converts universal address to netbuf. This routine should never * really be called because local n2a libraries are always provided. */ struct netbuf *rpcb_uaddr2taddr(struct netconfig *nconf, char *uaddr) { struct netbuf *taddr; CLIENT *client; AUTH *auth; /* parameter checking */ if (nconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; return (NULL); } if (uaddr == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNADDR; return (NULL); } client = local_rpcb(); if (!client) return (NULL); auth = authnone_ncreate(); /* idempotent */ taddr = (struct netbuf *)mem_zalloc(sizeof(struct netbuf)); if (taddr == NULL) { CLNT_DESTROY(client); return (NULL); } if (CLNT_CALL (client, auth, RPCBPROC_UADDR2TADDR, (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, (xdrproc_t) xdr_netbuf, (char *)(void *)taddr, tottimeout) != RPC_SUCCESS) { mem_free(taddr, 0); /* XXX */ taddr = NULL; } CLNT_DESTROY(client); return (taddr); } /* XXX */ #define IN4_LOCALHOST_STRING "127.0.0.1" #define IN6_LOCALHOST_STRING "::1" /* * This routine will return a client handle that is connected to the local * rpcbind. Returns NULL on error and free's everything. */ static CLIENT *local_rpcb(void) { CLIENT *client; static struct netconfig *loopnconf; static char *hostname; extern mutex_t loopnconf_lock; int sock; size_t tsize; struct netbuf nbuf; struct sockaddr_un sun; /* * Try connecting to the local rpcbind through a local socket * first. If this doesn't work, try all transports defined in * the netconfig file. */ memset(&sun, 0, sizeof(sun)); sock = socket(AF_LOCAL, SOCK_STREAM, 0); if (sock < 0) goto try_nconf; sun.sun_family = AF_LOCAL; strcpy(sun.sun_path, _PATH_RPCBINDSOCK); nbuf.len = SUN_LEN(&sun); nbuf.maxlen = sizeof(struct sockaddr_un); nbuf.buf = &sun; tsize = __rpc_get_t_size(AF_LOCAL, 0, 0); client = clnt_vc_ncreate(sock, &nbuf, (rpcprog_t) RPCBPROG, (rpcvers_t) RPCBVERS, tsize, tsize); if (client != NULL) { /* Mark the socket to be closed in destructor */ (void)CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL); return client; } /* Nobody needs this socket anymore; free the descriptor. */ close(sock); try_nconf: /* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */ mutex_lock(&loopnconf_lock); if (loopnconf == NULL) { struct netconfig *nconf, *tmpnconf = NULL; void *nc_handle; int fd; nc_handle = setnetconfig(); if (nc_handle == NULL) { /* fails to open netconfig file */ syslog(LOG_ERR, "rpc: failed to open " NETCONFIG); rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; mutex_unlock(&loopnconf_lock); return (NULL); } while ((nconf = getnetconfig(nc_handle)) != NULL) { #ifdef INET6 if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 || #else if (( #endif strcmp(nconf->nc_protofmly, NC_INET) == 0) && (nconf->nc_semantics == NC_TPI_COTS || nconf->nc_semantics == NC_TPI_COTS_ORD)) { fd = __rpc_nconf2fd(nconf); /* * Can't create a socket, assume that * this family isn't configured in the kernel. */ if (fd < 0) continue; close(fd); tmpnconf = nconf; if (!strcmp(nconf->nc_protofmly, NC_INET)) hostname = IN4_LOCALHOST_STRING; else hostname = IN6_LOCALHOST_STRING; } } if (tmpnconf == NULL) { rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; endnetconfig(nc_handle); mutex_unlock(&loopnconf_lock); return (NULL); } loopnconf = getnetconfigent(tmpnconf->nc_netid); /* loopnconf is never freed */ endnetconfig(nc_handle); } mutex_unlock(&loopnconf_lock); client = getclnthandle(hostname, loopnconf, NULL); return (client); } ntirpc-1.3.1/src/rpcb_prot.c000066400000000000000000000176451261345040100157510ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ /* * rpcb_prot.c * XDR routines for the rpcbinder version 3. * * Copyright (C) 1984, 1988, Sun Microsystems, Inc. */ #include #include #include #include #include bool xdr_rpcb(XDR *xdrs, RPCB *objp) { 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 xdr_rpcblist_ptr(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 = (xdrs->x_op == XDR_FREE); rpcblist_ptr next; rpcblist_ptr next_copy; 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) 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 { rp = &((*rp)->rpcb_next); } } /*NOTREACHED*/} /* * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in * functionality to xdr_rpcblist_ptr(). */ bool xdr_rpcblist(XDR *xdrs, RPCBLIST **rp) { bool dummy; dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *) rp); return (dummy); } bool xdr_rpcb_entry(XDR *xdrs, rpcb_entry *objp) { 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 xdr_rpcb_entry_list_ptr(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 = (xdrs->x_op == XDR_FREE); rpcb_entry_list_ptr next; rpcb_entry_list_ptr next_copy; 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) 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 { rp = &((*rp)->rpcb_entry_next); } } /*NOTREACHED*/} /* * XDR remote call arguments * written for XDR_ENCODE direction only */ bool xdr_rpcb_rmtcallargs(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; 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 xdr_rpcb_rmtcallres(XDR *xdrs, struct rpcb_rmtcallres *p) { bool dummy; struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p; 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 xdr_netbuf(XDR *xdrs, struct netbuf *objp) { bool dummy; if (!xdr_u_int32_t(xdrs, (u_int32_t *) & objp->maxlen)) { return (false); } dummy = xdr_bytes(xdrs, (char **)&(objp->buf), (u_int *) & (objp->len), objp->maxlen); return (dummy); } ntirpc-1.3.1/src/rpcb_st_xdr.c000066400000000000000000000143671261345040100162660ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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 #include #include /* Link list of all the stats about getport and getaddr */ bool xdr_rpcbs_addrlist(XDR *xdrs, rpcbs_addrlist *objp) { 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 **)&objp->next, sizeof(rpcbs_addrlist), (xdrproc_t) xdr_rpcbs_addrlist)) return (false); return (true); } /* Link list of all the stats about rmtcall */ bool xdr_rpcbs_rmtcalllist(XDR *xdrs, rpcbs_rmtcalllist *objp) { int32_t *buf; 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 **)&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 **)&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 **)&objp->next, sizeof(rpcbs_rmtcalllist), (xdrproc_t) xdr_rpcbs_rmtcalllist)) return (false); return (true); } bool xdr_rpcbs_proc(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 xdr_rpcbs_addrlist_ptr(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 xdr_rpcbs_rmtcalllist_ptr(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 xdr_rpcb_stat(XDR *xdrs, rpcb_stat *objp) { 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); if (!xdr_rpcbs_rmtcalllist_ptr(xdrs, &objp->rmtinfo)) return (false); return (true); } /* * One rpcb_stat structure is returned for each version of rpcbind * being monitored. */ bool xdr_rpcb_stat_byvers(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); } ntirpc-1.3.1/src/rpcdname.c000066400000000000000000000047551261345040100155460ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include /* * rpcdname.c * Gets the default domain name */ #include #include #include static char *default_domain; static char *get_default_domain(void) { char temp[256]; if (default_domain) return (default_domain); if (getdomainname(temp, sizeof(temp)) < 0) return (0); if ((int)strlen(temp) > 0) { default_domain = (char *)mem_alloc((strlen(temp) + (unsigned)1)); if (default_domain == 0) return (0); (void)strcpy(default_domain, temp); return (default_domain); } return (0); } /* * This is a wrapper for the system call getdomainname which returns a * ypclnt.h error code in the failure case. It also checks to see that * the domain name is non-null, knowing that the null string is going to * get rejected elsewhere in the NIS client package. */ int __rpc_get_default_domain(char **domain) { *domain = get_default_domain(); if (*domain) return (0); return (-1); } ntirpc-1.3.1/src/strlcat.c000066400000000000000000000032131261345040100154150ustar00rootroot00000000000000/* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef HAVE_STRLCAT #include #include /* * Appends src to string dst of size siz (unlike strncat, siz is the * full size of dst, not space left). At most siz-1 characters * will be copied. Always NUL terminates (unless siz <= strlen(dst)). * Returns strlen(src) + MIN(siz, strlen(initial dst)). * If retval >= siz, truncation occurred. */ size_t strlcat(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; size_t dlen; /* Find the end of dst and adjust bytes left but don't go past end */ while (n-- != 0 && *d != '\0') d++; dlen = d - dst; n = siz - dlen; if (n == 0) return (dlen + strlen(s)); while (*s != '\0') { if (n != 1) { *d++ = *s; n--; } s++; } *d = '\0'; return (dlen + (s - src)); /* count does not include NUL */ } #endif ntirpc-1.3.1/src/strlcpy.c000066400000000000000000000030021261345040100154350ustar00rootroot00000000000000/* * Copyright (c) 1998 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #ifndef HAVE_STRLCPY #include /* * Copy src to string dst of size siz. At most siz-1 characters * will be copied. Always NUL terminates (unless siz == 0). * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t strlcpy(char *dst, const char *src, size_t siz) { register char *d = dst; register const char *s = src; register size_t n = siz; /* Copy as many bytes as will fit */ if (n != 0 && --n != 0) { do { if ((*d++ = *s++) == 0) break; } while (--n != 0); } /* Not enough room in dst, add NUL and traverse rest of src */ if (n == 0) { if (siz != 0) *d = '\0'; /* NUL-terminate dst */ while (*s++); } return (s - src - 1); /* count does not include NUL */ } #endif ntirpc-1.3.1/src/svc.c000066400000000000000000000620221261345040100145370ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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 #include #include #include #include #include #include #include #include #if !defined (_WIN32) #include #include #endif #include #include #include #ifdef PORTMAP #include #endif /* PORTMAP */ #include "rpc_com.h" #include #include #include #include "clnt_internal.h" #include "svc_internal.h" #include "svc_xprt.h" #include "rpc_dplx_internal.h" #include #ifdef USE_RPC_RDMA #include "rpc_rdma.h" #endif #include "svc_ioq.h" #define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */ #define version_keepquiet(xp) ((u_long)(xp)->xp_p3 & SVC_VERSQUIET) /* svc_internal.h */ #ifdef IOV_MAX int __svc_maxiov = IOV_MAX; #else int __svc_maxiov = 1024; /* UIO_MAXIOV value from sys/uio.h */ #endif int __svc_maxrec = 0; extern tirpc_pkg_params __ntirpc_pkg_params; struct svc_params __svc_params[1] = { { false /* !initialized */ , MUTEX_INITIALIZER} }; /* * The services list * Each entry represents a set of procedures (an rpc program). * The dispatch routine takes request structs and runs the * apropriate procedure. * * The service record is factored out to permit exporting the find * routines without exposing the db implementation. */ static struct svc_callout { struct svc_callout *sc_next; struct svc_record rec; } *svc_head; extern rwlock_t svc_lock; extern rwlock_t svc_fd_lock; static struct svc_callout *svc_find(rpcprog_t, rpcvers_t, struct svc_callout **, char *); struct work_pool svc_work_pool; static int svc_work_pool_init() { struct work_pool_params params = { .thrd_max = __svc_params->ioq.thrd_max, .thrd_min = 2 }; return work_pool_init(&svc_work_pool, "svc_work_pool", ¶ms); } /* Package init function. * It is intended that applications which must make use of global state * will call svc_init() before accessing such state and before executing * any svc exported functions. Traditional TI-RPC programs need not * call the function as presently integrated. */ bool svc_init(svc_init_params *params) { mutex_lock(&__svc_params->mtx); if (__svc_params->initialized) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_init: multiple initialization attempt (nothing happens)"); mutex_unlock(&__svc_params->mtx); return true; } __svc_params->max_connections = (params->max_connections) ? params->max_connections : FD_SETSIZE; if (params->flags & SVC_INIT_WARNX) __ntirpc_pkg_params.warnx = params->warnx; else __ntirpc_pkg_params.warnx = warnx; /* svc_vc */ __svc_params->xprt_u.vc.nconns = 0; mutex_init(&__svc_params->xprt_u.vc.mtx, NULL); #if defined(HAVE_BLKIN) if (params->flags & SVC_INIT_BLKIN) { int r = blkin_init(); if (r < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC, "%s: blkn_init failed\n", __func__); } } #endif #if defined(TIRPC_EPOLL) if (params->flags & SVC_INIT_EPOLL) { __svc_params->ev_type = SVC_EVENT_EPOLL; __svc_params->ev_u.evchan.max_events = params->max_events; } #else /* XXX formerly select/fd_set case, now placeholder for new * event systems, reworked select, etc. */ #endif __svc_params->idle_timeout = params->idle_timeout; /* XXX defaults to the legacy max sendsz */ __svc_params->svc_ioq_maxbuf = (params->svc_ioq_maxbuf) ? (params->svc_ioq_maxbuf) : 262144; /* allow consumers to manage all xprt registration */ if (params->flags & SVC_INIT_NOREG_XPRTS) __svc_params->flags |= SVC_FLAG_NOREG_XPRTS; if (params->ioq_thrd_max) __svc_params->ioq.thrd_max = params->ioq_thrd_max; else __svc_params->ioq.thrd_max = 200; /* uses ioq.thrd_max */ if (svc_work_pool_init()) { mutex_unlock(&__svc_params->mtx); return false; } if (params->gss_ctx_hash_partitions) __svc_params->gss.ctx_hash_partitions = params->gss_ctx_hash_partitions; else __svc_params->gss.ctx_hash_partitions = 13; if (params->gss_max_ctx) __svc_params->gss.max_ctx = params->gss_max_ctx; else __svc_params->gss.max_ctx = 1024; if (params->gss_max_idle_gen) __svc_params->gss.max_idle_gen = params->gss_max_idle_gen; else __svc_params->gss.max_idle_gen = 1024; if (params->gss_max_gc) __svc_params->gss.max_gc = params->gss_max_gc; else __svc_params->gss.max_gc = 200; #ifdef USE_RPC_RDMA rpc_rdma_internals_init(); #endif __svc_params->initialized = true; mutex_unlock(&__svc_params->mtx); #if defined(_SC_IOV_MAX) /* IRIX, MacOS X, FreeBSD, Solaris, ... */ __svc_maxiov = sysconf(_SC_IOV_MAX); #endif return true; } struct rpc_msg * alloc_rpc_msg(void) { struct rpc_msg *msg = mem_alloc(sizeof(struct rpc_msg)); if (!msg) goto out; TAILQ_INIT_ENTRY(msg, msg_q); /* avoid separate alloc/free */ msg->rm_call.cb_cred.oa_base = msg->cb_cred_body; msg->rm_call.cb_verf.oa_base = msg->cb_verf_body; /* required for REPLY decodes */ msg->acpted_rply.ar_verf = _null_auth; msg->acpted_rply.ar_results.where = NULL; msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; out: return (msg); } void free_rpc_msg(struct rpc_msg *msg) { mem_free(msg, sizeof(struct rpc_msg)); } static inline void free_req_rpc_msg(struct svc_req *req) { if (req->rq_msg) { struct rpc_msg *msg = req->rq_msg; mem_free(msg, sizeof(struct rpc_msg)); req->rq_msg = NULL; } } /* *************** SVCXPRT related stuff **************** */ /* * This is used to set local and remote addresses in a way legacy * apps can deal with, at the same time setting up a corresponding * netbuf -- with no alloc/free needed. */ void __rpc_set_address(struct rpc_address *rpca, const struct sockaddr_storage *ss, socklen_t sl) { socklen_t l; switch (ss->ss_family) { case AF_INET6: l = sl ? sl : sizeof(struct sockaddr_in6); memcpy(&rpca->ss, ss, l); break; case AF_INET: l = sl ? sl : sizeof(struct sockaddr_in); memcpy(&rpca->ss, ss, l); break; case AF_LOCAL: l = sl ? sl : sizeof(struct sockaddr); memcpy(&rpca->ss, ss, l); break; default: memset(&rpca->ss, 0xfe, sizeof(struct sockaddr_storage)); l = sl ? sl : sizeof(struct sockaddr); rpca->ss.ss_family = AF_UNSPEC; break; } rpca->nb.buf = &rpca->ss; rpca->nb.len = l; rpca->nb.maxlen = sizeof(struct sockaddr_storage); } /* * 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 svc_reg(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, void (*dispatch) (struct svc_req *req, SVCXPRT *xprt), const struct netconfig *nconf) { bool dummy; struct svc_callout *prev; struct svc_callout *s; struct netconfig *tnconf; char *netid = NULL; int flag = 0; /* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */ if (xprt->xp_netid) { netid = rpc_strdup(xprt->xp_netid); flag = 1; } else if (nconf) { netid = rpc_strdup(nconf->nc_netid); flag = 1; } else { tnconf = __rpcgettp(xprt->xp_fd); if (tnconf) { netid = rpc_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); s = svc_find(prog, vers, &prev, netid); if (s) { if (netid) mem_free(netid, 0); if (s->rec.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) mem_free(netid, 0); rwlock_unlock(&svc_lock); return (false); } s->rec.sc_prog = prog; s->rec.sc_vers = vers; s->rec.sc_dispatch = dispatch; s->rec.sc_netid = netid; s->sc_next = svc_head; svc_head = s; if ((xprt->xp_netid == NULL) && (flag == 1) && netid) ((SVCXPRT *) xprt)->xp_netid = rpc_strdup(netid); rpcb_it: rwlock_unlock(&svc_lock); /* now register the information with the local binder service */ if (nconf) { /*LINTED const castaway */ dummy = rpcb_set(prog, vers, (struct netconfig *)nconf, &((SVCXPRT *) xprt)->xp_local.nb); return (dummy); } return (true); } /* * Remove a service program from the callout list. */ void svc_unreg(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->rec.sc_netid) mem_free(s->rec.sc_netid, sizeof(s->rec.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 svc_register(SVCXPRT *xprt, u_long prog, u_long vers, void (*dispatch) (struct svc_req *req, SVCXPRT *xprt), int protocol) { struct svc_callout *prev; struct svc_callout *s; assert(xprt != NULL); assert(dispatch != NULL); s = svc_find((rpcprog_t) prog, (rpcvers_t) vers, &prev, NULL); if (s) { if (s->rec.sc_dispatch == dispatch) goto pmap_it; /* he is registering another xprt */ return (false); } s = mem_alloc(sizeof(struct svc_callout)); if (!s) return (false); s->rec.sc_prog = (rpcprog_t) prog; s->rec.sc_vers = (rpcvers_t) vers; s->rec.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(u_long prog, u_long vers) { struct svc_callout *prev; struct svc_callout *s; s = svc_find((rpcprog_t) prog, (rpcvers_t) vers, &prev, NULL); if (!s) 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(rpcprog_t prog, rpcvers_t vers, struct svc_callout **prev, char *netid) { struct svc_callout *s, *p; assert(prev != NULL); p = NULL; for (s = svc_head; s != NULL; s = s->sc_next) { if (((s->rec.sc_prog == prog) && (s->rec.sc_vers == vers)) && ((netid == NULL) || (s->rec.sc_netid == NULL) || (strcmp(netid, s->rec.sc_netid) == 0))) break; p = s; } *prev = p; return (s); } /* An exported search routing similar to svc_find, but with error reporting * needed by svc_getreq routines. */ svc_lookup_result_t svc_lookup(svc_rec_t **rec, svc_vers_range_t *vrange, rpcprog_t prog, rpcvers_t vers, char *netid, u_int flags) { struct svc_callout *s, *p; svc_lookup_result_t code = SVC_LKP_ERR; bool prog_found, vers_found, netid_found; p = NULL; prog_found = vers_found = netid_found = false; vrange->lowvers = vrange->highvers = 0; for (s = svc_head; s != NULL; s = s->sc_next) { if (s->rec.sc_prog == prog) { prog_found = true; /* track supported versions for SVC_LKP_VERS_NOTFOUND */ if (s->rec.sc_vers > vrange->highvers) vrange->highvers = s->rec.sc_vers; if (vrange->lowvers < s->rec.sc_vers) vrange->lowvers = s->rec.sc_vers; /* vers match */ if (s->rec.sc_vers == vers) { vers_found = true; /* the following semantics are unchanged */ if ((netid == NULL) || (s->rec.sc_netid == NULL) || (strcmp(netid, s->rec.sc_netid) == 0)) { netid_found = true; p = s; } /* netid */ } /* vers */ } /* prog */ } /* for */ if (p != NULL) { *rec = &(p->rec); code = SVC_LKP_SUCCESS; goto out; } if (!prog_found) { code = SVC_LKP_PROG_NOTFOUND; goto out; } if (!vers_found) { code = SVC_LKP_VERS_NOTFOUND; goto out; } if ((netid != NULL) && (!netid_found)) { code = SVC_LKP_NETID_NOTFOUND; goto out; } out: return (code); } /* ******************* REPLY GENERATION ROUTINES ************ */ /* * Send a reply to an rpc request (MT-SAFE). * * XXX Rather than marshal an rpc_msg on the stack, we may * want another variant which takes a message, perhaps one from * a reply cache (e.g., CITI Windows NFS client). * */ bool svc_sendreply(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_results, void *xdr_location) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.rm_xid = req->rq_xid; rply.acpted_rply.ar_verf = req->rq_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, req, &rply)); } /* * No procedure error reply (MT-SAFE) */ void svcerr_noproc(SVCXPRT *xprt, struct svc_req *req) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.rm_xid = req->rq_xid; rply.acpted_rply.ar_verf = req->rq_verf; rply.acpted_rply.ar_stat = PROC_UNAVAIL; SVC_REPLY(xprt, req, &rply); } /* * Can't decode args error reply (MT-SAFE) */ void svcerr_decode(SVCXPRT *xprt, struct svc_req *req) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.rm_xid = req->rq_xid; rply.acpted_rply.ar_verf = req->rq_verf; rply.acpted_rply.ar_stat = GARBAGE_ARGS; SVC_REPLY(xprt, req, &rply); } /* * Some system error (MT-SAFE) */ void svcerr_systemerr(SVCXPRT *xprt, struct svc_req *req) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.rm_xid = req->rq_xid; rply.acpted_rply.ar_verf = req->rq_verf; rply.acpted_rply.ar_stat = SYSTEM_ERR; SVC_REPLY(xprt, req, &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(SVCXPRT *xprt) { u_long tmp; tmp = ((u_long) xprt->xp_p3) | SVC_VERSQUIET; xprt->xp_p3 = tmp; } void __svc_versquiet_off(SVCXPRT *xprt) { u_long tmp; tmp = ((u_long) xprt->xp_p3) & ~SVC_VERSQUIET; xprt->xp_p3 = tmp; } void svc_versquiet(xprt) SVCXPRT *xprt; { __svc_versquiet_on(xprt); } int __svc_versquiet_get(SVCXPRT *xprt) { return ((int)xprt->xp_p3) & SVC_VERSQUIET; } #endif /* * Authentication error reply (MT-SAFE) */ void svcerr_auth(SVCXPRT *xprt, struct svc_req *req, enum auth_stat why) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_DENIED; rply.rm_xid = req->rq_xid; rply.rjcted_rply.rj_stat = AUTH_ERROR; rply.rjcted_rply.rj_why = why; SVC_REPLY(xprt, req, &rply); } /* * Auth too weak error reply (MT-SAFE) */ void svcerr_weakauth(SVCXPRT *xprt, struct svc_req *req) { assert(xprt != NULL); svcerr_auth(xprt, req, AUTH_TOOWEAK); } /* * Program unavailable error reply (MT-SAFE) */ void svcerr_noprog(SVCXPRT *xprt, struct svc_req *req) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.rm_xid = req->rq_xid; rply.acpted_rply.ar_verf = req->rq_verf; rply.acpted_rply.ar_stat = PROG_UNAVAIL; SVC_REPLY(xprt, req, &rply); } /* * Program version mismatch error reply */ void svcerr_progvers(SVCXPRT *xprt, struct svc_req *req, rpcvers_t low_vers, rpcvers_t high_vers) { struct rpc_msg rply; assert(xprt != NULL); rply.rm_direction = REPLY; rply.rm_reply.rp_stat = MSG_ACCEPTED; rply.rm_xid = req->rq_xid; rply.acpted_rply.ar_verf = req->rq_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, req, &rply); } /* ******************* SERVER INPUT STUFF ******************* */ /* * Get server side input from some transport. */ #if !defined(_WIN32) /* XXX */ void svc_getreq(int rdfds) { fd_set readfds; FD_ZERO(&readfds); readfds.fds_bits[0] = rdfds; svc_getreqset(&readfds); } void svc_getreqset(fd_set *readfds) { int bit, fd; fd_mask mask, *maskp; int sock; assert(readfds != NULL); maskp = readfds->fds_bits; for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) { for (mask = *maskp++; (bit = ffsl(mask)) != 0; mask ^= (1L << (bit - 1))) { /* sock has input waiting */ fd = sock + bit - 1; svc_getreq_common(fd); } } } void svc_getreq_poll(struct pollfd *pfdp, int pollretval) { int i; int fds_found; 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 * _poll()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)) svc_getreq_common(p->fd); } } } #endif /* _WIN32 */ #if defined(TIRPC_EPOLL) void svc_getreqset_epoll(struct epoll_event *events, int nfds) { int ix, code __attribute__ ((unused)) = 0; SVCXPRT *xprt; assert(events != NULL); for (ix = 0; ix < nfds; ++ix) { /* XXX should do constant-time validity check */ xprt = (SVCXPRT *) events[ix].data.ptr; code = xprt->xp_ops->xp_getreq(xprt); } } #endif /* TIRPC_EPOLL */ void svc_getreq_common(int fd) { SVCXPRT *xprt; bool code __attribute__ ((unused)); xprt = svc_xprt_get(fd); if (xprt == NULL) return; code = xprt->xp_ops->xp_getreq(xprt); return; } /* Allow internal or external getreq routines to validate xprt * has not been recursively disconnected. (I don't completely buy the * logic, but it should be unchanged (Matt)) */ bool svc_validate_xprt_list(SVCXPRT *xprt) { bool code; code = (xprt == svc_xprt_get(xprt->xp_fd)); return (code); } extern enum auth_stat svc_auth_authenticate(struct svc_req *, struct rpc_msg *, bool *); void svc_dispatch_default(SVCXPRT *xprt, struct rpc_msg **ind_msg) { struct svc_req r; struct rpc_msg *msg = *ind_msg; svc_vers_range_t vrange; svc_lookup_result_t lkp_res; svc_rec_t *svc_rec; enum auth_stat why; bool no_dispatch = false; 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; r.rq_xid = msg->rm_xid; /* first authenticate the message */ why = svc_auth_authenticate(&r, msg, &no_dispatch); if ((why != AUTH_OK) || no_dispatch) { svcerr_auth(xprt, &r, why); return; } lkp_res = svc_lookup(&svc_rec, &vrange, r.rq_prog, r.rq_vers, NULL, 0); switch (lkp_res) { case SVC_LKP_SUCCESS: /* call it */ (*svc_rec->sc_dispatch) (&r, xprt); return; case SVC_LKP_VERS_NOTFOUND: svcerr_progvers(xprt, &r, vrange.lowvers, vrange.highvers); break; default: svcerr_noprog(xprt, &r); break; } } bool svc_getreq_default(SVCXPRT *xprt) { enum xprt_stat stat; struct svc_req req = {.rq_xprt = xprt }; bool no_dispatch = false; /* XXX !MT-SAFE */ /* now receive msgs from xprt (support batch calls) */ do { if (SVC_RECV(xprt, &req)) { /* now find the exported program and call it */ svc_vers_range_t vrange; svc_lookup_result_t lkp_res; svc_rec_t *svc_rec; enum auth_stat why; /* first authenticate the message */ why = svc_auth_authenticate(&req, req.rq_msg, &no_dispatch); if ((why != AUTH_OK) || no_dispatch) { svcerr_auth(xprt, &req, why); goto call_done; } lkp_res = svc_lookup(&svc_rec, &vrange, req.rq_prog, req.rq_vers, NULL, 0); switch (lkp_res) { case SVC_LKP_SUCCESS: (*svc_rec->sc_dispatch) (&req, xprt); goto call_done; break; case SVC_LKP_VERS_NOTFOUND: __warnx(TIRPC_DEBUG_FLAG_SVC, "%s: dispatch prog vers notfound\n", __func__); svcerr_progvers(xprt, &req, vrange.lowvers, vrange.highvers); break; default: __warnx(TIRPC_DEBUG_FLAG_SVC, "%s: dispatch prog notfound\n", __func__); svcerr_noprog(xprt, &req); break; } /* dispose RPC header */ free_req_rpc_msg(&req); } /* SVC_RECV again? */ call_done: /* dispose RPC header */ free_req_rpc_msg(&req); /* SAFE */ stat = SVC_STAT(xprt); if (stat == XPRT_DIED) { __warnx(TIRPC_DEBUG_FLAG_SVC, "%s: stat == XPRT_DIED (%p)\n", __func__, xprt); SVC_DESTROY(xprt); SVC_RELEASE(xprt, SVC_RELEASE_FLAG_NONE); xprt = 0; break; } else { /* * Check if the xprt has been disconnected in a * recursive call in the service dispatch routine. * If so, then break. */ if (!svc_validate_xprt_list(xprt)) { SVC_RELEASE(xprt, SVC_RELEASE_FLAG_NONE); xprt = 0; break; } } } while (stat == XPRT_MOREREQS); if (xprt) { svc_rqst_rearm_events(xprt, SVC_RQST_FLAG_NONE); SVC_RELEASE(xprt, SVC_RELEASE_FLAG_NONE); } return (stat); } bool 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; break; case RPC_SVC_CONNMAXREC_GET: *(int *)arg = __svc_maxrec; break; default: return (false); } return (true); } #if defined(HAVE_BLKIN) void __rpc_set_blkin_endpoint(SVCXPRT *xprt, const char *tag) { struct sockaddr_in *salocal_in; struct sockaddr_in6 *salocal_in6; struct sockaddr *salocal = (struct sockaddr *)&xprt->xp_local.ss; char saddr[INET6_ADDRSTRLEN]; int xp_port = 0; switch (salocal->sa_family) { case AF_INET: salocal_in = (struct sockaddr_in *)salocal; (void) inet_ntop(salocal->sa_family, &salocal_in->sin_addr, saddr, INET6_ADDRSTRLEN); xp_port = ntohs(salocal_in->sin_port); break; case AF_INET6: salocal_in6 = (struct sockaddr_in6 *)salocal; (void) inet_ntop(salocal->sa_family, &salocal_in6->sin6_addr, saddr, INET6_ADDRSTRLEN); xp_port = ntohs(salocal_in6->sin6_port); break; } /* in Zipkin, traces are localized by a service name at an endpoint, * plus an "address" which * a) is represented by an integer * b) is treated by libraries as if it is an ipv4 address * c) is mostly ignored if it converts as 0 (see below) * * the blkin c interface doesn't copy the endpoint string, so we * allocate one; */ xprt->blkin.svc_name = mem_zalloc(2*INET6_ADDRSTRLEN); snprintf(xprt->blkin.svc_name, 2*INET6_ADDRSTRLEN, "ntirpc-%s:%s:%d", tag, saddr, xp_port); blkin_init_endpoint(&xprt->blkin.endp, "0.0.0.0", xp_port, xprt->blkin.svc_name); } #endif int svc_shutdown(u_long flags) { int code = 0; #ifdef USE_RPC_RDMA /* wait until RDMA control threads have finished */ rpc_rdma_internals_fini(); #endif /* finalize ioq */ work_pool_shutdown(&svc_work_pool); /* dispose all xprts and support */ svc_xprt_shutdown(); /* release fd lock records */ rpc_dplx_shutdown(); /* release request event channels */ svc_rqst_shutdown(); /* XXX assert quiescent */ return (code); } ntirpc-1.3.1/src/svc_auth.c000066400000000000000000000131531261345040100155610ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ /* * svc_auth.c, Server-side rpc authenticator interface. * */ #include #include #include #include #include #include #include /* * 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) (struct svc_req *, struct rpc_msg *); struct authsvc *next; }; static struct authsvc *Auths; /* * 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 req->rq_verf to the appropriate response verifier; * sets req->rq_client_cred to the "cooked" form of the credentials. * * NB: req->rq_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 * req->rq_client_cred, the cooked credentials. * * There is an assumption that any flavour less than AUTH_NULL is invalid. */ enum auth_stat svc_auth_authenticate(struct svc_req *req, struct rpc_msg *msg, bool *no_dispatch) { int cred_flavor; struct authsvc *asp; enum auth_stat rslt; extern mutex_t authsvc_lock; /* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */ req->rq_cred = msg->rm_call.cb_cred; req->rq_verf.oa_flavor = _null_auth.oa_flavor; req->rq_verf.oa_length = 0; cred_flavor = req->rq_cred.oa_flavor; switch (cred_flavor) { case RPCSEC_GSS: rslt = _svcauth_gss(req, msg, no_dispatch); return (rslt); case AUTH_NONE: rslt = _svcauth_none(req, msg); return (rslt); break; case AUTH_SYS: rslt = _svcauth_unix(req, msg); return (rslt); case AUTH_SHORT: rslt = _svcauth_short(req, msg); return (rslt); #ifdef DES_BUILTIN case AUTH_DES: rslt = _svcauth_des(req, msg); return (rslt); #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) (req, msg); mutex_unlock(&authsvc_lock); return (as); } } mutex_unlock(&authsvc_lock); return (AUTH_REJECTEDCRED); } /* * 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(int cred_flavor, enum auth_stat (*handler) (struct svc_req *, struct rpc_msg *)) { struct authsvc *asp; extern mutex_t authsvc_lock; switch (cred_flavor) { case AUTH_NULL: case AUTH_SYS: case AUTH_SHORT: case RPCSEC_GSS: #ifdef DES_BUILTIN 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); } ntirpc-1.3.1/src/svc_auth_des.c000066400000000000000000000333351261345040100164200ustar00rootroot00000000000000 /* * Copyright (c) 1988 by Sun Microsystems, Inc. */ /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * svcauth_des.c, server-side des authentication * * We insure for the service the following: * (1) The timestamp microseconds do not exceed 1 million. * (2) The timestamp plus the window is less than the current time. * (3) The timestamp is not less than the one previously * seen in the current session. * * It is up to the server to determine if the window size is * too small . * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) #include #endif extern int key_decryptsession_pk(const char *, netobj *, des_block *); #define debug(msg) __warnx("svcauth_des: %s\n", (msg)) #define USEC_PER_SEC ((u_long) 1000000L) #define BEFORE(t1, t2) timercmp(t1, t2, <) /* * LRU cache of conversation keys and some other useful items. */ #define AUTHDES_CACHESZ 64 struct cache_entry { des_block key; /* conversation key */ char *rname; /* client's name */ u_int window; /* credential lifetime window */ struct timeval laststamp; /* detect replays of creds */ char *localcred; /* generic local credential */ }; static struct cache_entry *authdes_cache /* [AUTHDES_CACHESZ] */; static short *authdes_lru /* [AUTHDES_CACHESZ] */; static void cache_init(void); /* initialize the cache */ static short cache_spot(void); /* find an entry in the cache */ static void cache_ref(short sid); /* note that sid was ref'd */ static void invalidate(void); /* invalidate entry in cache */ /* * cache statistics */ static struct { u_long ncachehits; /* times cache hit, and is not replay */ u_long ncachereplays; /* times cache hit, and is replay */ u_long ncachemisses; /* times cache missed */ } svcauthdes_stats; /* * Service side authenticator for AUTH_DES */ enum auth_stat _svcauth_des(struct svc_req *req, struct rpc_msg *msg) { long *ixdr; des_block cryptbuf[2]; struct authdes_cred *cred; struct authdes_verf verf; int status; struct cache_entry *entry; short sid = 0; des_block *sessionkey; des_block ivec; u_int window; struct timeval timestamp; u_long namelen; struct area { struct authdes_cred area_cred; char area_netname[MAXNETNAMELEN + 1]; } *area; /* Initialize reply. */ req->rq_verf = _null_auth; if (!authdes_cache) cache_init(); area = (struct area *)req->rq_clntcred; cred = (struct authdes_cred *)&area->area_cred; /* * Get the credential */ ixdr = (long *)msg->rm_call.cb_cred.oa_base; cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind); switch (cred->adc_namekind) { case ADN_FULLNAME: namelen = IXDR_GET_U_LONG(ixdr); if (namelen > MAXNETNAMELEN) return (AUTH_BADCRED); cred->adc_fullname.name = area->area_netname; bcopy((char *)ixdr, cred->adc_fullname.name, (u_int) namelen); cred->adc_fullname.name[namelen] = 0; ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT); cred->adc_fullname.key.key.high = (u_long) *ixdr++; cred->adc_fullname.key.key.low = (u_long) *ixdr++; cred->adc_fullname.window = (u_long) *ixdr++; break; case ADN_NICKNAME: cred->adc_nickname = (u_long) *ixdr++; break; default: return (AUTH_BADCRED); } /* * Get the verifier */ ixdr = (long *)msg->rm_call.cb_verf.oa_base; verf.adv_xtimestamp.key.high = (u_long) *ixdr++; verf.adv_xtimestamp.key.low = (u_long) *ixdr++; verf.adv_int_u = (u_long) *ixdr++; /* * Get the conversation key */ if (cred->adc_namekind == ADN_FULLNAME) { netobj pkey; char pkey_data[1024]; sessionkey = &cred->adc_fullname.key; if (!getpublickey(cred->adc_fullname.name, pkey_data)) { debug("getpublickey"); return (AUTH_BADCRED); } pkey.n_bytes = pkey_data; pkey.n_len = strlen(pkey_data) + 1; if (key_decryptsession_pk (cred->adc_fullname.name, &pkey, sessionkey) < 0) { debug("decryptsessionkey"); return (AUTH_BADCRED); /* key not found */ } } else { /* ADN_NICKNAME */ sid = (short)cred->adc_nickname; if (sid < 0 || sid >= AUTHDES_CACHESZ) { debug("bad nickname"); return (AUTH_BADCRED); /* garbled credential */ } sessionkey = &authdes_cache[sid].key; } /* * Decrypt the timestamp */ cryptbuf[0] = verf.adv_xtimestamp; if (cred->adc_namekind == ADN_FULLNAME) { cryptbuf[1].key.high = cred->adc_fullname.window; cryptbuf[1].key.low = verf.adv_winverf; ivec.key.high = ivec.key.low = 0; status = cbc_crypt((char *)sessionkey, (char *)cryptbuf, 2 * sizeof(des_block), DES_DECRYPT | DES_HW, (char *)&ivec); } else { status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, sizeof(des_block), DES_DECRYPT | DES_HW); } if (DES_FAILED(status)) { debug("decryption failure"); return (AUTH_FAILED); /* system error */ } /* * XDR the decrypted timestamp */ ixdr = (long *)cryptbuf; timestamp.tv_sec = IXDR_GET_LONG(ixdr); timestamp.tv_usec = IXDR_GET_LONG(ixdr); /* * Check for valid credentials and verifiers. * They could be invalid because the key was flushed * out of the cache, and so a new session should begin. * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case. */ { struct timeval current; int nick; int winverf; if (cred->adc_namekind == ADN_FULLNAME) { window = IXDR_GET_U_LONG(ixdr); winverf = IXDR_GET_U_LONG(ixdr); if (winverf != window - 1) { debug("window verifier mismatch"); return (AUTH_BADCRED); /* garbled credential */ } sid = cache_spot(sessionkey, cred->adc_fullname.name, ×tamp); if (sid < 0) { debug("replayed credential"); return (AUTH_REJECTEDCRED); /* replay */ } nick = 0; } else { /* ADN_NICKNAME */ window = authdes_cache[sid].window; nick = 1; } if ((u_long) timestamp.tv_usec >= USEC_PER_SEC) { debug("invalid usecs"); /* cached out (bad key), or garbled verifier */ return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF); } if (nick && BEFORE(×tamp, &authdes_cache[sid].laststamp)) { debug("timestamp before last seen"); return (AUTH_REJECTEDVERF); /* replay */ } (void)gettimeofday(¤t, (struct timezone *)NULL); current.tv_sec -= window; /* allow for expiration */ if (!BEFORE(¤t, ×tamp)) { debug("timestamp expired"); /* replay, or garbled credential */ return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED); } } /* * Set up the reply verifier */ verf.adv_nickname = (u_long) sid; /* * xdr the timestamp before encrypting */ ixdr = (long *)cryptbuf; IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1); IXDR_PUT_LONG(ixdr, timestamp.tv_usec); /* * encrypt the timestamp */ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, sizeof(des_block), DES_ENCRYPT | DES_HW); if (DES_FAILED(status)) { debug("encryption failure"); return (AUTH_FAILED); /* system error */ } verf.adv_xtimestamp = cryptbuf[0]; /* * Serialize the reply verifier, and update req */ ixdr = (long *)msg->rm_call.cb_verf.oa_base; *ixdr++ = (long)verf.adv_xtimestamp.key.high; *ixdr++ = (long)verf.adv_xtimestamp.key.low; *ixdr++ = (long)verf.adv_int_u; req->rq_verf.oa_flavor = AUTH_DES; req->rq_verf.oa_base = msg->rm_call.cb_verf.oa_base; req->rq_verf.oa_length = (char *)ixdr - msg->rm_call.cb_verf.oa_base; /* * We succeeded, commit the data to the cache now and * finish cooking the credential. */ entry = &authdes_cache[sid]; entry->laststamp = timestamp; cache_ref(sid); if (cred->adc_namekind == ADN_FULLNAME) { cred->adc_fullname.window = window; cred->adc_nickname = (u_long) sid; /* save nickname */ if (entry->rname != NULL) mem_free(entry->rname, strlen(entry->rname) + 1); entry->rname = (char *)mem_alloc((u_int) strlen(cred->adc_fullname.name) + 1); if (entry->rname != NULL) (void)strcpy(entry->rname, cred->adc_fullname.name); else debug("out of memory"); entry->key = *sessionkey; entry->window = window; invalidate(entry->localcred); /* mark any cached cred invalid */ } else { /* ADN_NICKNAME */ /* * nicknames are cooked into fullnames */ cred->adc_namekind = ADN_FULLNAME; cred->adc_fullname.name = entry->rname; cred->adc_fullname.key = entry->key; cred->adc_fullname.window = entry->window; } return (AUTH_OK); /* we made it! */ } /* * Initialize the cache */ static void cache_init(void) { int i; authdes_cache = (struct cache_entry *) mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ); bzero((char *)authdes_cache, sizeof(struct cache_entry) * AUTHDES_CACHESZ); authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ); /* * Initialize the lru list */ for (i = 0; i < AUTHDES_CACHESZ; i++) { /* suppress block warning */ authdes_lru[i] = i; } } /* * Find the lru victim */ static short cache_victim(void) { return (authdes_lru[AUTHDES_CACHESZ - 1]); } /* * Note that sid was referenced */ static void cache_ref(short sid) { int i; short curr; short prev; prev = authdes_lru[0]; authdes_lru[0] = sid; for (i = 1; prev != sid; i++) { curr = authdes_lru[i]; authdes_lru[i] = prev; prev = curr; } } /* * Find a spot in the cache for a credential containing * the items given. Return -1 if a replay is detected, otherwise * return the spot in the cache. */ static short cache_spot(des_block *key, char *name, struct timeval *timestamp) { struct cache_entry *cp; int i; u_long hi; hi = key->key.high; for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) { if (cp->key.key.high == hi && cp->key.key.low == key->key.low && cp->rname != NULL && bcmp(cp->rname, name, strlen(name) + 1) == 0) { if (BEFORE(timestamp, &cp->laststamp)) { svcauthdes_stats.ncachereplays++; return (-1); /* replay */ } svcauthdes_stats.ncachehits++; return (i); /* refresh */ } } svcauthdes_stats.ncachemisses++; return (cache_victim()); /* new credential */ } #if (defined(sun) || defined(vax) || defined(__FreeBSD__)) /* * Local credential handling stuff. * NOTE: bsd unix dependent. * Other operating systems should put something else here. */ #define UNKNOWN -2 /* grouplen, if cached cred is unknown user */ #define INVALID -1 /* grouplen, if cache entry is invalid */ struct bsdcred { short uid; /* cached uid */ short gid; /* cached gid */ short grouplen; /* length of cached groups */ short groups[NGROUPS]; /* cached groups */ }; /* * Map a des credential into a unix cred. * We cache the credential here so the application does * not have to make an rpc call every time to interpret * the credential. */ int authdes_getucred(struct authdes_cred *adc, uid_t *uid, gid_t *gid, int *grouplen, gid_t *groups) { unsigned sid; int i; uid_t i_uid; gid_t i_gid; int i_grouplen; struct bsdcred *cred; sid = adc->adc_nickname; if (sid >= AUTHDES_CACHESZ) { debug("invalid nickname"); return (0); } cred = (struct bsdcred *)authdes_cache[sid].localcred; if (cred == NULL) { cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred)); authdes_cache[sid].localcred = (char *)cred; cred->grouplen = INVALID; } if (cred->grouplen == INVALID) { /* * not in cache: lookup */ if (!netname2user (adc->adc_fullname.name, &i_uid, &i_gid, &i_grouplen, groups)) { debug("unknown netname"); cred->grouplen = UNKNOWN; /* mark as lookup up, but * not found */ return (0); } debug("missed ucred cache"); *uid = cred->uid = i_uid; *gid = cred->gid = i_gid; *grouplen = cred->grouplen = i_grouplen; for (i = i_grouplen - 1; i >= 0; i--) { /* suppress block warning */ cred->groups[i] = groups[i]; /* int to short */ } return (1); } else if (cred->grouplen == UNKNOWN) { /* * Already lookup up, but no match found */ return (0); } /* * cached credentials */ *uid = cred->uid; *gid = cred->gid; *grouplen = cred->grouplen; for (i = cred->grouplen - 1; i >= 0; i--) { /* suppress block warning */ groups[i] = cred->groups[i]; /* short to int */ } return (1); } static void invalidate(char *cred) { if (cred == NULL) return; ((struct bsdcred *)cred)->grouplen = INVALID; } #endif ntirpc-1.3.1/src/svc_auth_gss.c000066400000000000000000000465211261345040100164420ustar00rootroot00000000000000/* svc_auth_gss.c Copyright (c) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (c) 2000 Dug Song . All rights reserved, all wrongs reversed. 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 University 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 ``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 REGENTS 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 #include #include #include #include #include #include #include "rpc_com.h" #include #include static bool svcauth_gss_wrap(SVCAUTH *, struct svc_req *, XDR *, xdrproc_t, caddr_t); static bool svcauth_gss_unwrap(SVCAUTH *, struct svc_req *, XDR *, xdrproc_t, caddr_t); static bool svcauth_gss_release(SVCAUTH *, struct svc_req *); bool svcauth_gss_destroy(SVCAUTH *); struct svc_auth_ops svc_auth_gss_ops = { svcauth_gss_wrap, svcauth_gss_unwrap, svcauth_gss_release, svcauth_gss_destroy }; #define SVCAUTH_PRIVATE(auth) \ ((struct svc_rpc_gss_data *)(auth)->svc_ah_private) /* Global server credentials. */ gss_cred_id_t svcauth_gss_creds; static gss_name_t svcauth_gss_name; static int64_t svcauth_gss_creds_expires; static mutex_t svcauth_gss_creds_lock = MUTEX_INITIALIZER; static gss_cred_id_t svcauth_prev_gss_creds; bool svcauth_gss_set_svc_name(gss_name_t name) { OM_uint32 maj_stat, min_stat; if (svcauth_gss_name != NULL) { maj_stat = gss_release_name(&min_stat, &svcauth_gss_name); if (maj_stat != GSS_S_COMPLETE) return (false); svcauth_gss_name = NULL; } /* XXX Ganesha */ if (svcauth_gss_name == GSS_C_NO_NAME) return (true); maj_stat = gss_duplicate_name(&min_stat, name, &svcauth_gss_name); if (maj_stat != GSS_S_COMPLETE) return (false); return (true); } bool svcauth_gss_import_name(char *service) { gss_name_t name; gss_buffer_desc namebuf; OM_uint32 maj_stat, min_stat; namebuf.value = service; namebuf.length = strlen(service); maj_stat = gss_import_name(&min_stat, &namebuf, (gss_OID) GSS_C_NT_HOSTBASED_SERVICE, &name); if (maj_stat != GSS_S_COMPLETE) return (false); if (svcauth_gss_set_svc_name(name) != true) { gss_release_name(&min_stat, &name); return (false); } /* discard duplicate name */ gss_release_name(&min_stat, &name); return (true); } #ifdef __APPLE__ /* there's also mach_absolute_time() - don't know if it's faster */ #define get_time_fast() time(0) #else static inline int64_t get_time_fast(void) { struct timespec ts[1]; (void)clock_gettime(CLOCK_MONOTONIC_FAST, ts); return ts->tv_sec; } #endif bool svcauth_gss_acquire_cred(void) { OM_uint32 maj_stat, min_stat; int64_t now; OM_uint32 timerec; gss_cred_id_t old_creds, ancient_creds; now = get_time_fast(); if (svcauth_gss_creds && (!svcauth_gss_creds_expires || svcauth_gss_creds_expires > now)) return (true); mutex_lock(&svcauth_gss_creds_lock); if (svcauth_gss_creds && (!svcauth_gss_creds_expires || svcauth_gss_creds_expires > now)) { maj_stat = GSS_S_COMPLETE; } else { ancient_creds = svcauth_prev_gss_creds; old_creds = svcauth_gss_creds; timerec = 0; now = get_time_fast(); maj_stat = gss_acquire_cred(&min_stat, svcauth_gss_name, 0, GSS_C_NULL_OID_SET, GSS_C_ACCEPT, &svcauth_gss_creds, NULL, &timerec); if (maj_stat == GSS_S_COMPLETE) { if (timerec == GSS_C_INDEFINITE) svcauth_gss_creds_expires = 0; else svcauth_gss_creds_expires = now + timerec; if (old_creds) { svcauth_prev_gss_creds = old_creds; } if (ancient_creds) { (void) gss_release_cred(&min_stat, &ancient_creds); } } } mutex_unlock(&svcauth_gss_creds_lock); if (maj_stat != GSS_S_COMPLETE) return (false); return (true); } bool svcauth_gss_release_cred(void) { #if 0 OM_uint32 maj_stat, min_stat; maj_stat = gss_release_cred(&min_stat, &svcauth_gss_creds); if (maj_stat != GSS_S_COMPLETE) return (false); svcauth_gss_creds = NULL; #else svcauth_gss_creds_expires = 1; /* make any future callers to svcauth_gss_acquire_cred() should get a new cred. */ #endif return (true); } static bool svcauth_gss_accept_sec_context(struct svc_req *req, struct svc_rpc_gss_data *gd, struct rpc_gss_init_res *gr) { struct rpc_gss_cred *gc; gss_buffer_desc recv_tok, seqbuf, checksum; gss_OID mech; OM_uint32 maj_stat = 0, min_stat = 0, ret_flags, seq; #define INDEF_EXPIRE 60*60*24 /* from mit k5 src/lib/rpc/svc_auth_gssapi.c */ OM_uint32 time_rec; gc = (struct rpc_gss_cred *)req->rq_clntcred; memset(gr, 0, sizeof(*gr)); /* Deserialize arguments. */ memset(&recv_tok, 0, sizeof(recv_tok)); if (!svc_getargs (req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_args, (caddr_t) &recv_tok, NULL /* u_data */)) return (false); gr->gr_major = gss_accept_sec_context(&gr->gr_minor, &gd->ctx, svcauth_gss_creds, &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &gd->client_name, &mech, &gr->gr_token, &ret_flags, &time_rec, NULL); svc_freeargs(req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_args, (caddr_t) &recv_tok); if ((gr->gr_major != GSS_S_COMPLETE) && (gr->gr_major != GSS_S_CONTINUE_NEEDED)) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: auth failed major=%u minor=%u", __func__, gr->gr_major, gr->gr_minor); gd->ctx = GSS_C_NO_CONTEXT; gss_release_buffer(&min_stat, &gr->gr_token); return (false); } /* ANDROS: krb5 mechglue returns ctx of size 8 - two pointers, * one to the mechanism oid, one to the internal_ctx_id */ gr->gr_ctx.value = mem_alloc(sizeof(gss_union_ctx_id_desc)); if (!gr->gr_ctx.value) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: out of memory", __func__); gss_release_buffer(&min_stat, &gr->gr_token); return (false); } memcpy(gr->gr_ctx.value, gd->ctx, sizeof(gss_union_ctx_id_desc)); gr->gr_ctx.length = sizeof(gss_union_ctx_id_desc); /* ANDROS: change for debugging linux kernel version... gr->gr_win = 0x00000005; */ gr->gr_win = sizeof(gd->seqmask) * 8; /* Save client info. */ gd->sec.mech = mech; gd->sec.qop = GSS_C_QOP_DEFAULT; gd->sec.svc = gc->gc_svc; gd->win = gr->gr_win; if (time_rec == GSS_C_INDEFINITE) time_rec = INDEF_EXPIRE; if (time_rec > 10) time_rec -= 5; gd->endtime = time_rec + get_time_fast(); if (gr->gr_major == GSS_S_COMPLETE) { maj_stat = gss_display_name(&min_stat, gd->client_name, &gd->cname, &gd->sec.mech); if (maj_stat != GSS_S_COMPLETE) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: display_name major=%u minor=%u", __func__, maj_stat, min_stat); gss_release_buffer(&min_stat, &gr->gr_token); return (false); } #ifdef DEBUG #ifdef HAVE_KRB5 { gss_buffer_desc mechname; gss_oid_to_str(&min_stat, mech, &mechname); __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: accepted context for %.*s with " "", __func__, gd->cname.length, (char *)gd->cname.value, mechname.length, (char *)mechname.value, gd->sec.qop, gd->sec.svc); gss_release_buffer(&min_stat, &mechname); } #elif HAVE_HEIMDAL __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: accepted context for %.*s with " "", __func__, gd->cname.length, (char *)gd->cname.value, gd->sec.qop, gd->sec.svc); #endif #endif /* DEBUG */ seq = htonl(gr->gr_win); seqbuf.value = &seq; seqbuf.length = sizeof(seq); gss_release_buffer(&min_stat, &gd->checksum); maj_stat = gss_sign(&min_stat, gd->ctx, GSS_C_QOP_DEFAULT, &seqbuf, &checksum); if (maj_stat != GSS_S_COMPLETE) { gss_release_buffer(&min_stat, &gr->gr_token); return (false); } /* XXX ref? (assert gd->locked?) */ req->rq_verf.oa_flavor = RPCSEC_GSS; req->rq_verf.oa_base = checksum.value; req->rq_verf.oa_length = checksum.length; } return (true); } #define RPCHDR_LEN ((10 * BYTES_PER_XDR_UNIT) + MAX_AUTH_BYTES) static int svcauth_gss_validate(struct svc_req *req, struct svc_rpc_gss_data *gd, struct rpc_msg *msg) { struct opaque_auth *oa; gss_buffer_desc rpcbuf, checksum; OM_uint32 maj_stat, min_stat, qop_state; u_char rpchdr[RPCHDR_LEN]; int32_t *buf; memset(rpchdr, 0, RPCHDR_LEN); /* XXX - Reconstruct RPC header for signing (from xdr_callmsg). */ oa = &msg->rm_call.cb_cred; if (oa->oa_length > MAX_AUTH_BYTES) return GSS_S_CALL_BAD_STRUCTURE; /* XXX since MAX_AUTH_BYTES is 400, the following code trivially * overruns (up to 431 per Coverity, but compare RPCHDR_LEN with * what is marshalled below). */ buf = (int32_t *) rpchdr; IXDR_PUT_LONG(buf, msg->rm_xid); IXDR_PUT_ENUM(buf, msg->rm_direction); IXDR_PUT_LONG(buf, msg->rm_call.cb_rpcvers); IXDR_PUT_LONG(buf, msg->rm_call.cb_prog); IXDR_PUT_LONG(buf, msg->rm_call.cb_vers); IXDR_PUT_LONG(buf, msg->rm_call.cb_proc); IXDR_PUT_ENUM(buf, oa->oa_flavor); IXDR_PUT_LONG(buf, oa->oa_length); if (oa->oa_length) { memcpy((caddr_t) buf, oa->oa_base, oa->oa_length); buf += RNDUP(oa->oa_length) / sizeof(int32_t); } rpcbuf.value = rpchdr; rpcbuf.length = (u_char *) buf - rpchdr; checksum.value = msg->rm_call.cb_verf.oa_base; checksum.length = msg->rm_call.cb_verf.oa_length; maj_stat = gss_verify_mic(&min_stat, gd->ctx, &rpcbuf, &checksum, &qop_state); if (maj_stat != GSS_S_COMPLETE) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: %d %d", __func__, maj_stat, min_stat); return (maj_stat); } return GSS_S_COMPLETE; } bool svcauth_gss_nextverf(struct svc_req *req, struct svc_rpc_gss_data *gd, u_int num) { gss_buffer_desc signbuf, checksum; OM_uint32 maj_stat, min_stat; signbuf.value = # signbuf.length = sizeof(num); maj_stat = gss_get_mic(&min_stat, gd->ctx, gd->sec.qop, &signbuf, &checksum); if (maj_stat != GSS_S_COMPLETE) { log_status("gss_get_mic", maj_stat, min_stat); return (false); } req->rq_verf.oa_flavor = RPCSEC_GSS; req->rq_verf.oa_base = (caddr_t) checksum.value; req->rq_verf.oa_length = (u_int) checksum.length; return (true); } #define svcauth_gss_return(code) \ do { \ if (gc) \ xdr_free((xdrproc_t) xdr_rpc_gss_cred, gc); \ if (gd_locked) \ mutex_unlock(&gd->lock); \ return (code); \ } while (0) enum auth_stat _svcauth_gss(struct svc_req *req, struct rpc_msg *msg, bool *no_dispatch) { XDR xdrs[1]; SVCAUTH *auth; struct svc_rpc_gss_data *gd = NULL; struct rpc_gss_cred *gc = NULL; struct rpc_gss_init_res gr; int call_stat, offset; OM_uint32 min_stat; bool gd_locked = false; bool gd_hashed = false; /* Initialize reply. */ req->rq_verf = _null_auth; /* Unserialize client credentials. */ if (req->rq_cred.oa_length <= 0) svcauth_gss_return(AUTH_BADCRED); gc = (struct rpc_gss_cred *)req->rq_clntcred; memset(gc, 0, sizeof(struct rpc_gss_cred)); xdrmem_create(xdrs, req->rq_cred.oa_base, req->rq_cred.oa_length, XDR_DECODE); if (!xdr_rpc_gss_cred(xdrs, gc)) { XDR_DESTROY(xdrs); svcauth_gss_return(AUTH_BADCRED); } XDR_DESTROY(xdrs); /* Check version. */ if (gc->gc_v != RPCSEC_GSS_VERSION) svcauth_gss_return(AUTH_BADCRED); if (gc->gc_seq > RPCSEC_GSS_MAXSEQ) svcauth_gss_return(RPCSEC_GSS_CTXPROBLEM); if (gc->gc_proc > RPCSEC_GSS_MAXPROC) svcauth_gss_return(AUTH_BADCRED); /* Check RPCSEC_GSS service. */ if (gc->gc_svc != RPCSEC_GSS_SVC_NONE && gc->gc_svc != RPCSEC_GSS_SVC_INTEGRITY && gc->gc_svc != RPCSEC_GSS_SVC_PRIVACY) svcauth_gss_return(AUTH_BADCRED); /* Context lookup. */ if ((gc->gc_proc == RPCSEC_GSS_DATA) || (gc->gc_proc == RPCSEC_GSS_DESTROY)) { /* XXX fix prototype, toss junk args */ gd = authgss_ctx_hash_get(gc); if (!gd) svcauth_gss_return(AUTH_REJECTEDCRED); gd_hashed = true; if (gc->gc_svc != gd->sec.svc) gd->sec.svc = gc->gc_svc; } if (!gd) { /* Allocate and set up server auth handle. */ auth = mem_alloc(sizeof(SVCAUTH)); if (!auth) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "%s: alloc auth failed", __func__); svcauth_gss_return(AUTH_FAILED); } gd = alloc_svc_rpc_gss_data(); if (!gd) { __warnx(TIRPC_DEBUG_FLAG_RPCSEC_GSS, "%s: alloc svc_rpc_gss_data failed", __func__); mem_free(auth, sizeof(SVCAUTH)); svcauth_gss_return(AUTH_FAILED); } auth->svc_ah_ops = &svc_auth_gss_ops; auth->svc_ah_private = (caddr_t) gd; gd->auth = auth; } /* Serialize context. */ mutex_lock(&gd->lock); gd_locked = true; /* thread auth */ req->rq_auth = gd->auth; /* Check sequence number. */ if (gd->established) { if (get_time_fast() >= gd->endtime) { *no_dispatch = true; svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM); } /* XXX implied serialization? or just fudging? advance if * greater? */ offset = gd->seqlast - gc->gc_seq; if (offset < 0) { gd->seqlast = gc->gc_seq; offset = 0 - offset; gd->seqmask <<= offset; offset = 0; } else if (offset >= gd->win || (gd->seqmask & (1 << offset))) { *no_dispatch = true; svcauth_gss_return(AUTH_OK); } gd->seqmask |= (1 << offset); /* XXX harmless */ req->rq_ap1 = (void *)(uintptr_t) gc->gc_seq; /* GCC casts */ req->rq_clntname = (char *) gd->client_name; req->rq_svcname = (char *) gd->ctx; } /* gd->established */ /* Handle RPCSEC_GSS control procedure. */ switch (gc->gc_proc) { case RPCSEC_GSS_INIT: case RPCSEC_GSS_CONTINUE_INIT: if (req->rq_proc != NULLPROC) svcauth_gss_return(AUTH_FAILED); /* XXX ? */ /* XXX why unconditionally acquire creds? */ if (!svcauth_gss_acquire_cred()) svcauth_gss_return(AUTH_FAILED); if (!svcauth_gss_accept_sec_context(req, gd, &gr)) svcauth_gss_return(AUTH_REJECTEDCRED); if (!svcauth_gss_nextverf(req, gd, htonl(gr.gr_win))) { /* XXX check */ gss_release_buffer(&min_stat, &gr.gr_token); mem_free(gr.gr_ctx.value, 0); svcauth_gss_return(AUTH_FAILED); } *no_dispatch = true; call_stat = svc_sendreply(req->rq_xprt, req, (xdrproc_t) xdr_rpc_gss_init_res, (caddr_t) &gr); /* XXX */ gss_release_buffer(&min_stat, &gr.gr_token); gss_release_buffer(&min_stat, &gd->checksum); mem_free(gr.gr_ctx.value, 0); if (!call_stat) svcauth_gss_return(AUTH_FAILED); if (gr.gr_major == GSS_S_COMPLETE) { gd->established = true; if (!gd_hashed) { /* krb5 pac -- try all that apply */ gss_buffer_desc attr, display_buffer; /* completely generic */ int auth = 1, comp = 0, more = -1; memset(&gd->pac.ms_pac, 0, sizeof(gss_buffer_desc)); memset(&display_buffer, 0, sizeof(gss_buffer_desc)); /* MS AD */ attr.value = "urn:mspac:"; attr.length = 10; gr.gr_major = gss_get_name_attribute(&gr.gr_minor, gd->client_name, &attr, &auth, &comp, &gd->pac.ms_pac, &display_buffer, &more); if (gr.gr_major == GSS_S_COMPLETE) { /* dont need it */ gss_release_buffer(&gr.gr_minor, &display_buffer); gd->flags |= SVC_RPC_GSS_FLAG_MSPAC; } (void)authgss_ctx_hash_set(gd); } } break; /* XXX next 2 cases: is it correct to leave gd in cache * after a validate or verf failure ? */ case RPCSEC_GSS_DATA: call_stat = svcauth_gss_validate(req, gd, msg); switch (call_stat) { default: svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM); case 0: break; } if (!svcauth_gss_nextverf(req, gd, htonl(gc->gc_seq))) svcauth_gss_return(AUTH_FAILED); break; case RPCSEC_GSS_DESTROY: if (req->rq_proc != NULLPROC) svcauth_gss_return(AUTH_FAILED); /* XXX ? */ if (svcauth_gss_validate(req, gd, msg)) svcauth_gss_return(RPCSEC_GSS_CREDPROBLEM); if (!svcauth_gss_nextverf(req, gd, htonl(gc->gc_seq))) svcauth_gss_return(AUTH_FAILED); *no_dispatch = true; (void)authgss_ctx_hash_del(gd); /* unrefs, can destroy gd */ /* avoid lock order reversal gd->lock, xprt->xp_lock */ mutex_unlock(&gd->lock); gd_locked = false; call_stat = svc_sendreply(req->rq_xprt, req, (xdrproc_t) xdr_void, (caddr_t) NULL); req->rq_auth = &svc_auth_none; break; default: svcauth_gss_return(AUTH_REJECTEDCRED); break; } svcauth_gss_return(AUTH_OK); } static bool svcauth_gss_release(SVCAUTH *auth, struct svc_req *req) { struct svc_rpc_gss_data *gd; caddr_t last_oa_base; gd = SVCAUTH_PRIVATE(auth); if (gd) unref_svc_rpc_gss_data(gd, SVC_RPC_GSS_FLAG_NONE); req->rq_auth = NULL; if ((last_oa_base = req->rq_verf.oa_base)) { /* XXX wrapper conflict: mem_free vs. gssalloc_free ? */ /* ... but this only matters for win32 | kernel */ req->rq_verf.oa_base = 0; mem_free(last_oa_base, req->rq_verf.oa_length); } return (true); } bool svcauth_gss_destroy(SVCAUTH *auth) { struct svc_rpc_gss_data *gd; OM_uint32 min_stat; gd = SVCAUTH_PRIVATE(auth); gss_delete_sec_context(&min_stat, &gd->ctx, GSS_C_NO_BUFFER); gss_release_buffer(&min_stat, &gd->cname); if (gd->client_name) gss_release_name(&min_stat, &gd->client_name); if (gd->flags & SVC_RPC_GSS_FLAG_MSPAC) gss_release_buffer(&min_stat, &gd->pac.ms_pac); gss_release_buffer(&min_stat, &gd->checksum); mutex_destroy(&gd->lock); mem_free(gd, sizeof(struct svc_rpc_gss_data)); mem_free(auth, sizeof(*auth)); return (true); } bool svcauth_gss_wrap(SVCAUTH *auth, struct svc_req *req, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) { bool result; struct svc_rpc_gss_data *gd = SVCAUTH_PRIVATE(req->rq_auth); u_int gc_seq = (u_int) (uintptr_t) req->rq_ap1; if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) return ((*xdr_func) (xdrs, xdr_ptr)); mutex_lock(&gd->lock); result = xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr, gd->ctx, gd->sec.qop, gd->sec.svc, gc_seq); mutex_unlock(&gd->lock); return (result); } bool svcauth_gss_unwrap(SVCAUTH *auth, struct svc_req *req, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) { bool result; struct svc_rpc_gss_data *gd = SVCAUTH_PRIVATE(req->rq_auth); u_int gc_seq = (u_int) (uintptr_t) req->rq_ap1; if (!gd->established || gd->sec.svc == RPCSEC_GSS_SVC_NONE) return ((*xdr_func) (xdrs, xdr_ptr)); mutex_lock(&gd->lock); result = xdr_rpc_gss_data(xdrs, xdr_func, xdr_ptr, gd->ctx, gd->sec.qop, gd->sec.svc, gc_seq); mutex_unlock(&gd->lock); return (result); } char * svcauth_gss_get_principal(SVCAUTH *auth) { struct svc_rpc_gss_data *gd; char *pname; gd = SVCAUTH_PRIVATE(auth); if (gd->cname.length == 0) return (NULL); pname = mem_alloc(gd->cname.length + 1); if (!pname) return (NULL); memcpy(pname, gd->cname.value, gd->cname.length); pname[gd->cname.length] = '\0'; return (pname); } ntirpc-1.3.1/src/svc_auth_none.c000066400000000000000000000053011261345040100165740ustar00rootroot00000000000000/* svc_auth_none.c Copyright (c) 2000 The Regents of the University of Michigan. All rights reserved. Copyright (c) 2000 Dug Song . All rights reserved, all wrongs reversed. 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 University 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 ``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 REGENTS 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. $Id: svc_auth_none.c,v 1.1 2004/10/22 17:24:30 bfields Exp $ */ #include #include #include #include static bool svcauth_none_wrap(SVCAUTH *, struct svc_req *, XDR *, xdrproc_t, caddr_t); static bool svcauth_none_release(SVCAUTH *, struct svc_req *); static bool svcauth_none_destroy(SVCAUTH *); struct svc_auth_ops svc_auth_none_ops = { svcauth_none_wrap, svcauth_none_wrap, svcauth_none_release, svcauth_none_destroy }; SVCAUTH svc_auth_none = { &svc_auth_none_ops, NULL, }; /* aka, unwrap */ static bool svcauth_none_wrap(SVCAUTH * __attribute__ ((unused)) auth, struct svc_req * __attribute__ ((unused)) req, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) { return ((*xdr_func) (xdrs, xdr_ptr)); } static bool svcauth_none_release(SVCAUTH * __attribute__ ((unused)) auth, struct svc_req * __attribute__ ((unused)) req) { return (true); } static bool svcauth_none_destroy(SVCAUTH *auth) { return (true); } enum auth_stat _svcauth_none(struct svc_req *req, struct rpc_msg *msg) { req->rq_auth = &svc_auth_none; return (AUTH_OK); } ntirpc-1.3.1/src/svc_auth_unix.c000066400000000000000000000112231261345040100166200ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * 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 #include #include #include #include #include #include #include extern SVCAUTH svc_auth_none; /* * Unix longhand authenticator */ enum auth_stat _svcauth_unix(struct svc_req *req, struct rpc_msg *msg) { enum auth_stat stat; XDR xdrs; struct authunix_parms *aup; int32_t *buf; struct area { struct authunix_parms area_aup; char area_machname[MAX_MACHINE_NAME + 1]; gid_t area_gids[NGRPS]; } *area; u_int auth_len; size_t str_len, gid_len; u_int i; assert(req != NULL); assert(msg != NULL); req->rq_auth = &svc_auth_none; area = (struct area *)req->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++) { /* suppress block warning */ 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) { __warnx(TIRPC_DEBUG_FLAG_AUTH, "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; } /* get the verifier */ if ((u_int) msg->rm_call.cb_verf.oa_length) { req->rq_verf.oa_flavor = msg->rm_call.cb_verf.oa_flavor; req->rq_verf.oa_base = msg->rm_call.cb_verf.oa_base; req->rq_verf.oa_length = msg->rm_call.cb_verf.oa_length; } else { req->rq_verf.oa_flavor = AUTH_NULL; req->rq_verf.oa_length = 0; } stat = AUTH_OK; done: XDR_DESTROY(&xdrs); return (stat); } /* * Shorthand unix authenticator * Looks up longhand in a cache. */ /*ARGSUSED*/ enum auth_stat _svcauth_short(struct svc_req *req, struct rpc_msg *msg) { req->rq_auth = &svc_auth_none; return (AUTH_REJECTEDCRED); } ntirpc-1.3.1/src/svc_dg.c000066400000000000000000000567271261345040100152300ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ #include /* * svc_dg.c, Server side for connectionless RPC. * * Does some caching in the hopes of achieving execute-at-most-once semantics. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include "svc_internal.h" #include "clnt_internal.h" #include "svc_xprt.h" #include "rpc_dplx_internal.h" #include #include #include extern tirpc_pkg_params __ntirpc_pkg_params; extern struct svc_params __svc_params[1]; #define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2)) /* XXX */ #define rpc_buffer(xprt) ((xprt)->xp_p1) #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif static void svc_dg_ops(SVCXPRT *); static int svc_dg_cache_get(SVCXPRT *, struct rpc_msg *, char **, size_t *); static void svc_dg_cache_set(SVCXPRT *, size_t); static void svc_dg_enable_pktinfo(int, const struct __rpc_sockinfo *); static int svc_dg_store_pktinfo(struct msghdr *, struct svc_req *); /* * Usage: * xprt = svc_dg_ncreate(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_ncreate: %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_ncreate(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; uint32_t oflags; if (!__rpc_fd2sockinfo(fd, &si)) { __warnx(TIRPC_DEBUG_FLAG_SVC_DG, 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(TIRPC_DEBUG_FLAG_SVC_DG, svc_dg_str, svc_dg_err2); return (NULL); } xprt = mem_zalloc(sizeof(SVCXPRT)); if (xprt == NULL) goto freedata; /* Init SVCXPRT locks, etc */ mutex_init(&xprt->xp_lock, NULL); mutex_init(&xprt->xp_auth_lock, NULL); su = mem_alloc(sizeof(*su)); if (su == NULL) goto freedata; su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4; rpc_buffer(xprt) = mem_alloc(su->su_iosz); if (!rpc_buffer(xprt)) goto freedata; xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz, XDR_DECODE); su->su_cache = NULL; xprt->xp_flags = SVC_XPRT_FLAG_NONE; xprt->xp_refs = 1; xprt->xp_fd = fd; xprt->xp_p2 = su; svc_dg_ops(xprt); slen = sizeof(ss); if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) goto freedata; __rpc_set_address(&xprt->xp_local, &ss, slen); switch (ss.ss_family) { case AF_INET: xprt->xp_port = ntohs(((struct sockaddr_in *)&ss)->sin_port); break; #ifdef INET6 case AF_INET6: xprt->xp_port = ntohs(((struct sockaddr_in6 *)&ss)->sin6_port); break; #endif case AF_LOCAL: /* no port */ break; default: break; } /* Enable reception of IP*_PKTINFO control msgs */ svc_dg_enable_pktinfo(fd, &si); /* Make reachable */ xprt->xp_p5 = rpc_dplx_lookup_rec( xprt->xp_fd, RPC_DPLX_FLAG_NONE, &oflags); /* ref+1 */ svc_rqst_init_xprt(xprt); /* Conditional xprt_register */ if (!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)) xprt_register(xprt); #if defined(HAVE_BLKIN) __rpc_set_blkin_endpoint(xprt, "svc_dg"); #endif return (xprt); freedata: __warnx(TIRPC_DEBUG_FLAG_SVC_DG, svc_dg_str, __no_mem_str); if (xprt) { if (su) (void)mem_free(su, sizeof(*su)); xprt_unregister(xprt); (void)mem_free(xprt, sizeof(SVCXPRT)); } return (NULL); } /*ARGSUSED*/ static enum xprt_stat svc_dg_stat(SVCXPRT *xprt) { return (XPRT_IDLE); } static void svc_dg_set_pktinfo(struct cmsghdr *cmsg, struct svc_req *req) { switch (req->rq_daddr.ss_family) { case AF_INET: { struct in_pktinfo *pki = (struct in_pktinfo *)CMSG_DATA(cmsg); struct sockaddr_in *daddr = (struct sockaddr_in *)&req->rq_daddr; cmsg->cmsg_level = SOL_IP; cmsg->cmsg_type = IP_PKTINFO; pki->ipi_ifindex = 0; #ifdef __FreeBSD__ pki->ipi_addr = daddr->sin_addr; #else pki->ipi_spec_dst = daddr->sin_addr; #endif cmsg->cmsg_len = CMSG_LEN(sizeof(*pki)); break; } case AF_INET6: { struct in6_pktinfo *pki = (struct in6_pktinfo *)CMSG_DATA(cmsg); struct sockaddr_in6 *daddr = (struct sockaddr_in6 *)&req->rq_daddr; cmsg->cmsg_level = SOL_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; pki->ipi6_ifindex = daddr->sin6_scope_id; pki->ipi6_addr = daddr->sin6_addr; cmsg->cmsg_len = CMSG_LEN(sizeof(*pki)); break; } default: break; } } static bool svc_dg_recv(SVCXPRT *xprt, struct svc_req *req) { struct svc_dg_data *su = su_data(xprt); XDR *xdrs = &(su->su_xdrs); char *reply; struct sockaddr_storage ss; struct sockaddr *sp = (struct sockaddr *)&ss; struct msghdr *mesgp; struct iovec iov; size_t replylen; ssize_t rlen; memset(&ss, 0xff, sizeof(struct sockaddr_storage)); /* Magic marker value to see if we didn't get the header. */ req->rq_msg = alloc_rpc_msg(); again: iov.iov_base = rpc_buffer(xprt); iov.iov_len = su->su_iosz; mesgp = &su->su_msghdr; memset(mesgp, 0, sizeof(*mesgp)); mesgp->msg_iov = &iov; mesgp->msg_iovlen = 1; mesgp->msg_name = (struct sockaddr *)(void *)&ss; sp->sa_family = (sa_family_t) 0xffff; mesgp->msg_namelen = sizeof(struct sockaddr_storage); mesgp->msg_control = su->su_cmsg; mesgp->msg_controllen = sizeof(su->su_cmsg); rlen = recvmsg(xprt->xp_fd, mesgp, 0); if (sp->sa_family == (sa_family_t) 0xffff) return false; if (rlen == -1 && errno == EINTR) goto again; if (rlen == -1 || (rlen < (ssize_t) (4 * sizeof(u_int32_t)))) return (false); __rpc_set_address(&xprt->xp_remote, &ss, mesgp->msg_namelen); /* Check whether there's an IP_PKTINFO or IP6_PKTINFO control message. * If yes, preserve it for svc_dg_reply; otherwise just zap any cmsgs */ if (!svc_dg_store_pktinfo(mesgp, req)) { mesgp->msg_control = NULL; mesgp->msg_controllen = 0; req->rq_daddr_len = 0; } xdrs->x_op = XDR_DECODE; XDR_SETPOS(xdrs, 0); if (!xdr_callmsg(xdrs, req->rq_msg)) return (false); req->rq_xprt = xprt; req->rq_prog = req->rq_msg->rm_call.cb_prog; req->rq_vers = req->rq_msg->rm_call.cb_vers; req->rq_proc = req->rq_msg->rm_call.cb_proc; req->rq_xid = req->rq_msg->rm_xid; req->rq_clntcred = req->rq_msg->rq_cred_body; /* save remote address */ req->rq_raddr_len = xprt->xp_remote.nb.len; memcpy(&req->rq_raddr, xprt->xp_remote.nb.buf, req->rq_raddr_len); /* the checksum */ req->rq_cksum = #if 1 CityHash64WithSeed(iov.iov_base, MIN(256, iov.iov_len), 103); #else calculate_crc32c(0, iov.iov_base, MIN(256, iov.iov_len)); #endif /* XXX su->su_xid !MT-SAFE */ su->su_xid = req->rq_msg->rm_xid; if (su->su_cache != NULL) { if (svc_dg_cache_get(xprt, req->rq_msg, &reply, &replylen)) { iov.iov_base = reply; iov.iov_len = replylen; /* Set source IP address of the reply message in * PKTINFO */ if (req->rq_daddr_len != 0) { struct cmsghdr *cmsg; cmsg = (struct cmsghdr *)mesgp->msg_control; svc_dg_set_pktinfo(cmsg, req); #ifndef CMSG_ALIGN #define CMSG_ALIGN(len) (len) #endif mesgp->msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); } (void)sendmsg(xprt->xp_fd, mesgp, 0); return (false); } } return (true); } static bool svc_dg_reply(SVCXPRT *xprt, struct svc_req *req, struct rpc_msg *msg) { struct svc_dg_data *su = su_data(xprt); XDR *xdrs = &(su->su_xdrs); bool stat = false; size_t slen; xdrproc_t xdr_results; caddr_t xdr_location; bool has_args; if (msg->rm_reply.rp_stat == MSG_ACCEPTED && msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { has_args = true; xdr_results = msg->acpted_rply.ar_results.proc; xdr_location = msg->acpted_rply.ar_results.where; msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; msg->acpted_rply.ar_results.where = NULL; } else { xdr_results = NULL; xdr_location = NULL; has_args = false; } xdrs->x_op = XDR_ENCODE; XDR_SETPOS(xdrs, 0); if (xdr_replymsg(xdrs, msg) && req->rq_raddr_len && (!has_args || (SVCAUTH_WRAP (req->rq_auth, req, xdrs, xdr_results, xdr_location)))) { struct msghdr *msg = &su->su_msghdr; struct cmsghdr *cmsg; struct iovec iov; iov.iov_base = rpc_buffer(xprt); iov.iov_len = slen = XDR_GETPOS(xdrs); msg->msg_iov = &iov; msg->msg_iovlen = 1; msg->msg_name = (struct sockaddr *)&req->rq_raddr; msg->msg_namelen = req->rq_raddr_len; /* Set source IP address of the reply message in PKTINFO */ if (req->rq_daddr_len != 0) { msg->msg_control = su->su_cmsg; cmsg = (struct cmsghdr *)msg->msg_control; svc_dg_set_pktinfo(cmsg, req); msg->msg_controllen = CMSG_ALIGN(cmsg->cmsg_len); } if (sendmsg(xprt->xp_fd, msg, 0) == (ssize_t) slen) { stat = true; if (su->su_cache) svc_dg_cache_set(xprt, slen); } } return (stat); } static bool svc_dg_freeargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr) { return xdr_free(xdr_args, args_ptr); } static bool svc_dg_getargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr, void *u_data) { struct svc_dg_data *su = su_data(xprt); XDR *xdrs = &(su->su_xdrs); bool rslt; /* threads u_data for advanced decoders */ xdrs->x_public = u_data; rslt = SVCAUTH_UNWRAP(req->rq_auth, req, xdrs, xdr_args, args_ptr); if (!rslt) { svc_dg_freeargs(xprt, req, xdr_args, args_ptr); } return (rslt); } static void svc_dg_lock(SVCXPRT *xprt, uint32_t flags, const char *file, int line) { rpc_dplx_rlxi(xprt, file, line); rpc_dplx_slxi(xprt, file, line); } static void svc_dg_unlock(SVCXPRT *xprt, uint32_t flags, const char *file, int line) { rpc_dplx_rux(xprt); rpc_dplx_sux(xprt); } static void svc_dg_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line) { struct svc_dg_data *su = su_data(xprt); /* clears xprt from the xprt table (eg, idle scans) */ xprt_unregister(xprt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s() %p xp_refs %" PRIu32 " should actually destroy things @ %s:%d", __func__, xprt, xprt->xp_refs, tag, line); 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_tp) (void)free(xprt->xp_tp); rpc_dplx_unref((struct rpc_dplx_rec *)xprt->xp_p5, RPC_DPLX_FLAG_NONE); if (xprt->xp_ops->xp_free_user_data) { /* call free hook */ xprt->xp_ops->xp_free_user_data(xprt); } #if defined(HAVE_BLKIN) if (xprt->blkin.svc_name) mem_free(xprt->blkin.svc_name, 2*INET6_ADDRSTRLEN); #endif (void)mem_free(xprt, sizeof(SVCXPRT)); } extern mutex_t ops_lock; /*ARGSUSED*/ static bool svc_dg_control(SVCXPRT *xprt, const u_int rq, void *in) { switch (rq) { case SVCGET_XP_FLAGS: *(u_int *) in = xprt->xp_flags; break; case SVCSET_XP_FLAGS: xprt->xp_flags = *(u_int *) in; break; case SVCGET_XP_RECV: mutex_lock(&ops_lock); *(xp_recv_t *) in = xprt->xp_ops->xp_recv; mutex_unlock(&ops_lock); break; case SVCSET_XP_RECV: mutex_lock(&ops_lock); xprt->xp_ops->xp_recv = *(xp_recv_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_GETREQ: mutex_lock(&ops_lock); *(xp_getreq_t *) in = xprt->xp_ops->xp_getreq; mutex_unlock(&ops_lock); break; case SVCSET_XP_GETREQ: mutex_lock(&ops_lock); xprt->xp_ops->xp_getreq = *(xp_getreq_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_DISPATCH: mutex_lock(&ops_lock); *(xp_dispatch_t *) in = xprt->xp_ops->xp_dispatch; mutex_unlock(&ops_lock); break; case SVCSET_XP_DISPATCH: mutex_lock(&ops_lock); xprt->xp_ops->xp_dispatch = *(xp_dispatch_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); *(xp_free_user_data_t *) in = xprt->xp_ops->xp_free_user_data; mutex_unlock(&ops_lock); break; case SVCSET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); xprt->xp_ops->xp_free_user_data = *(xp_free_user_data_t) in; mutex_unlock(&ops_lock); break; default: return (false); } return (true); } static void svc_dg_ops(SVCXPRT *xprt) { static struct xp_ops ops; /* VARIABLES PROTECTED BY ops_lock: ops, xp_type */ mutex_lock(&ops_lock); /* Fill in type of service */ xprt->xp_type = XPRT_UDP; 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; ops.xp_control = svc_dg_control; ops.xp_lock = svc_dg_lock; ops.xp_unlock = svc_dg_unlock; ops.xp_getreq = svc_getreq_default; ops.xp_dispatch = svc_dispatch_default; ops.xp_recv_user_data = NULL; /* no default */ ops.xp_free_user_data = NULL; /* no default */ } xprt->xp_ops = &ops; mutex_unlock(&ops_lock); } /* * 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(SVCXPRT *transp, u_int size) { struct svc_dg_data *su = su_data(transp); struct cl_cache *uc; mutex_lock(&dupreq_lock); if (su->su_cache != NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_DG, cache_enable_str, enable_err, " "); mutex_unlock(&dupreq_lock); return (0); } uc = ALLOC(struct cl_cache, 1); if (uc == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_DG, 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(TIRPC_DEBUG_FLAG_SVC_DG, 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(TIRPC_DEBUG_FLAG_SVC_DG, 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 svc_dg_cache_get() for the same procedure. This will * always happen because svc_dg_cache_get() is calle by svc_dg_recv and * svc_dg_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 svc_dg_cache_set(SVCXPRT *xprt, size_t replylen) { cache_ptr victim; cache_ptr *vicp; struct svc_dg_data *su = su_data(xprt); struct cl_cache *uc = (struct cl_cache *)su->su_cache; u_int loc; char *newbuf; struct netconfig *nconf; char *uaddr; 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(TIRPC_DEBUG_FLAG_SVC_DG, 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(TIRPC_DEBUG_FLAG_SVC_DG, cache_set_str, cache_set_err2); mutex_unlock(&dupreq_lock); return; } newbuf = mem_alloc(su->su_iosz); if (newbuf == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_DG, cache_set_str, cache_set_err3); FREE(victim, struct cache_node, 1); mutex_unlock(&dupreq_lock); return; } } /* * Store it away */ if (__ntirpc_pkg_params.debug_flags & TIRPC_DEBUG_FLAG_RPC_CACHE) { nconf = getnetconfigent(xprt->xp_netid); if (nconf) { uaddr = taddr2uaddr(nconf, &xprt->xp_remote.nb); freenetconfigent(nconf); __warnx(TIRPC_DEBUG_FLAG_SVC_DG, "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); mem_free(uaddr, 0); /* XXX */ } } /* DEBUG_RPC_CACHE */ 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_remote.nb; victim->cache_addr.buf = ALLOC(char, xprt->xp_remote.nb.len); (void)memcpy(victim->cache_addr.buf, xprt->xp_remote.nb.buf, (size_t) xprt->xp_remote.nb.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 svc_dg_cache_set() */ static int svc_dg_cache_get(SVCXPRT *xprt, struct rpc_msg *msg, char **replyp, size_t *replylenp) { u_int loc; cache_ptr ent; struct svc_dg_data *su = su_data(xprt); struct cl_cache *uc = (struct cl_cache *)su->su_cache; struct netconfig *nconf; char *uaddr; 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_remote.nb.len && (memcmp (ent->cache_addr.buf, xprt->xp_remote.nb.buf, xprt->xp_remote.nb.len) == 0)) { if (__ntirpc_pkg_params. debug_flags & TIRPC_DEBUG_FLAG_RPC_CACHE) { nconf = getnetconfigent(xprt->xp_netid); if (nconf) { uaddr = taddr2uaddr(nconf, &xprt->xp_remote.nb); freenetconfigent(nconf); __warnx(TIRPC_DEBUG_FLAG_SVC_DG, "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); mem_free(uaddr, 0); } } /* RPC_CACHE_DEBUG */ *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); } /* * Enable reception of PKTINFO control messages */ void svc_dg_enable_pktinfo(int fd, const struct __rpc_sockinfo *si) { int val = 1; switch (si->si_af) { case AF_INET: #ifdef SOL_IP (void)setsockopt(fd, SOL_IP, IP_PKTINFO, &val, sizeof(val)); #endif break; case AF_INET6: #ifdef SOL_IPV6 (void)setsockopt(fd, SOL_IP, IP_PKTINFO, &val, sizeof(val)); (void)setsockopt(fd, SOL_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val)); #endif break; } } static int svc_dg_store_in_pktinfo(struct cmsghdr *cmsg, struct svc_req *req) { if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_PKTINFO && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in_pktinfo))) { struct in_pktinfo *pkti; struct sockaddr_in *daddr; pkti = (struct in_pktinfo *)CMSG_DATA(cmsg); daddr = (struct sockaddr_in *)&req->rq_daddr; daddr->sin_family = AF_INET; #ifdef __FreeBSD__ daddr->sin_addr = pkti->ipi_addr; #else daddr->sin_addr.s_addr = pkti->ipi_spec_dst.s_addr; #endif req->rq_daddr_len = sizeof(struct sockaddr_in); return 1; } else { return 0; } } static int svc_dg_store_in6_pktinfo(struct cmsghdr *cmsg, struct svc_req *req) { if (cmsg->cmsg_level == SOL_IPV6 && cmsg->cmsg_type == IPV6_PKTINFO && cmsg->cmsg_len >= CMSG_LEN(sizeof(struct in6_pktinfo))) { struct in6_pktinfo *pkti; struct sockaddr_in6 *daddr; pkti = (struct in6_pktinfo *)CMSG_DATA(cmsg); daddr = (struct sockaddr_in6 *) &req->rq_daddr; daddr->sin6_family = AF_INET6; daddr->sin6_addr = pkti->ipi6_addr; daddr->sin6_scope_id = pkti->ipi6_ifindex; req->rq_daddr_len = sizeof(struct sockaddr_in6); return 1; } else { return 0; } } /* * When given a control message received from the socket * layer, check whether it contains valid PKTINFO data. * If so, store the data in the request. */ static int svc_dg_store_pktinfo(struct msghdr *msg, struct svc_req *req) { struct cmsghdr *cmsg; if (!msg->msg_name) return 0; if (msg->msg_flags & MSG_CTRUNC) return 0; cmsg = CMSG_FIRSTHDR(msg); if (cmsg == NULL || CMSG_NXTHDR(msg, cmsg) != NULL) return 0; switch (((struct sockaddr *)msg->msg_name)->sa_family) { case AF_INET: #ifdef SOL_IP if (svc_dg_store_in_pktinfo(cmsg, req)) return 1; #endif break; case AF_INET6: #ifdef SOL_IPV6 /* Handle IPv4 PKTINFO as well on IPV6 interface */ if (svc_dg_store_in_pktinfo(cmsg, req)) return 1; if (svc_dg_store_in6_pktinfo(cmsg, req)) return 1; #endif break; default: break; } return 0; } ntirpc-1.3.1/src/svc_generic.c000066400000000000000000000214421261345040100162340ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ /* * svc_generic.c, Server side for RPC. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include extern int __svc_vc_setflag(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_ncreate() is called multiple times, it uses the handle * created earlier instead of creating a new handle every time. */ int svc_ncreate(void (*dispatch) (struct svc_req *req, SVCXPRT *xprt), rpcprog_t prognum, 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; extern mutex_t xprtlist_lock; /* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */ handle = __rpc_setconf(nettype); if (!handle) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_ncreate: 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(TIRPC_DEBUG_FLAG_SVC, "svc_ncreate: 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_ncreate(dispatch, prognum, versnum, nconf); if (xprt) { l = (struct xlist *)mem_alloc(sizeof(*l)); if (l == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_ncreate: no memory"); mutex_unlock(&xprtlist_lock); __rpc_endconf(handle); 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_ncreate(). * It tries to create a server for "nconf" and registers the service * with the rpcbind. It calls svc_tli_ncreate(); */ SVCXPRT * svc_tp_ncreate(void (*dispatch) (struct svc_req *req, SVCXPRT *xprt), rpcprog_t prognum, /* Program number */ rpcvers_t versnum, /* Version number */ const struct netconfig *nconf /* Network */) { SVCXPRT *xprt; if (nconf == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_tp_ncreate: invalid netconfig structure for prog %u " "vers %u", (unsigned)prognum, (unsigned)versnum); return (NULL); } xprt = svc_tli_ncreate(RPC_ANYFD, nconf, NULL, 0, 0); if (xprt == NULL) return (NULL); /*LINTED const castaway */ (void)rpcb_unset(prognum, versnum, (struct netconfig *)nconf); if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == false) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_tp_ncreate: 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_ncreate(int fd, /* Connection end point */ const struct netconfig *nconf, /* 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 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(TIRPC_DEBUG_FLAG_SVC, "svc_tli_ncreate: invalid netconfig"); return (NULL); } fd = __rpc_nconf2fd(nconf); if (fd == -1) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_tli_ncreate: could not open connection for %s", nconf->nc_netid); return (NULL); } if (!__rpc_nconf2sockinfo(nconf, &si)) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_tli_create: could not get netconfig information"); close(fd); return (NULL); } madefd = true; } else { /* * It is an open descriptor. Get the transport info. */ if (!__rpc_fd2sockinfo(fd, &si)) { __warnx(TIRPC_DEBUG_FLAG_SVC, "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; if (bind (fd, (struct sockaddr *)(void *)&ss, (socklen_t) si.si_alen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_tli_ncreate: 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(TIRPC_DEBUG_FLAG_SVC, "svc_tli_ncreate: 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_ncreate(fd, sendsz, recvsz); } else xprt = svc_vc_ncreate(fd, sendsz, recvsz); if (!nconf || !xprt) break; #if 0 /* XXX fvdl *//* XXXX check matt */ 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_ncreate(fd, sendsz, recvsz); break; default: __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_tli_ncreate: bad service type"); goto freedata; } if (xprt == NULL) /* * The error messages here are produced by the lower layers: * svc_vc_ncreate(), svc_fd_ncreate() and svc_dg_ncreate(). */ goto freedata; /* Fill in type of service */ xprt->xp_si_type = __rpc_socktype2seman(si.si_socktype); if (nconf) { xprt->xp_netid = rpc_strdup(nconf->nc_netid); xprt->xp_tp = rpc_strdup(nconf->nc_device); } return (xprt); freedata: if (madefd) (void)close(fd); if (xprt) { if (!madefd) /* so that svc_destroy doesnt close fd */ xprt->xp_fd = RPC_ANYFD; SVC_DESTROY(xprt); } return (NULL); } ntirpc-1.3.1/src/svc_internal.h000066400000000000000000000125411261345040100164410ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TIRPC_SVC_INTERNAL_H #define TIRPC_SVC_INTERNAL_H #include extern int __svc_maxiov; extern int __svc_maxrec; /* threading fdsets around is annoying */ struct svc_params { bool initialized; mutex_t mtx; u_long flags; /* package global event handling--may be overridden using the * svc_rqst interface */ enum svc_event_type ev_type; union { struct { uint32_t id; uint32_t max_events; } evchan; struct { fd_set set; /* select/fd_set (currently unhooked) */ } fd; } ev_u; int32_t idle_timeout; u_int max_connections; u_int svc_ioq_maxbuf; union { struct { mutex_t mtx; u_int nconns; } vc; } xprt_u; struct { int ctx_hash_partitions; int max_ctx; int max_idle_gen; int max_gc; } gss; struct { u_int thrd_max; } ioq; }; extern struct svc_params __svc_params[1]; #define svc_cond_init() \ do { \ if (!__svc_params->initialized) { \ (void)svc_init(&(svc_init_params) \ { .flags = SVC_INIT_EPOLL, \ .max_connections = 8192, \ .max_events = 512, \ .gss_ctx_hash_partitions = 13,\ .gss_max_ctx = 1024, \ .gss_max_idle_gen = 1024, \ .gss_max_gc = 200 \ }); \ } \ } while (0) static inline bool svc_vc_new_conn_ok(void) { bool ok = false; svc_cond_init(); mutex_lock((&__svc_params->xprt_u.vc.mtx)); if (__svc_params->xprt_u.vc.nconns < __svc_params->max_connections) { ++(__svc_params->xprt_u.vc.nconns); ok = true; } mutex_unlock(&(__svc_params->xprt_u.vc.mtx)); return (ok); } #define svc_vc_dec_nconns() \ do { \ mutex_lock((&__svc_params->xprt_u.vc.mtx)); \ --(__svc_params->xprt_u.vc.nconns); \ mutex_unlock(&(__svc_params->xprt_u.vc.mtx)); \ } while (0) struct __svc_ops { bool (*svc_clean_idle) (fd_set *fds, int timeout, bool cleanblock); void (*svc_run) (void); void (*svc_getreq) (int rdfds); /* XXX */ void (*svc_getreqset) (fd_set *readfds); /* XXX */ void (*svc_exit) (void); }; extern struct __svc_ops *svc_ops; #define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2)) /* 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) \ ((type *) 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 hashing function */ #define CACHE_LOC(transp, xid) \ (xid % (SPARSENESS * ((struct cl_cache *) \ su_data(transp)->su_cache)->uc_size)) extern mutex_t dupreq_lock; /* * 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 */ }; /* Epoll interface change */ #ifndef EPOLL_CLOEXEC #define EPOLL_CLOEXEC 02000000 static inline int epoll_create_wr(size_t size, int flags) { return (epoll_create(size)); } #else static inline int epoll_create_wr(size_t size, int flags) { return (epoll_create1(flags)); } #endif #if defined(HAVE_BLKIN) extern void __rpc_set_blkin_endpoint(SVCXPRT *xprt, const char *tag); #endif void svc_rqst_shutdown(void); #endif /* TIRPC_SVC_INTERNAL_H */ ntirpc-1.3.1/src/svc_ioq.c000066400000000000000000000147321261345040100154140ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include "clnt_internal.h" #include "svc_internal.h" #include "svc_xprt.h" #include "rpc_dplx_internal.h" #include "rpc_ctx.h" #include #include #include #include #include #include "svc_ioq.h" static inline void cfconn_set_dead(SVCXPRT *xprt, struct x_vc_data *xd) { mutex_lock(&xprt->xp_lock); xd->sx.strm_stat = XPRT_DIED; mutex_unlock(&xprt->xp_lock); } #define LAST_FRAG ((u_int32_t)(1 << 31)) #define MAXALLOCA (256) static inline void ioq_flushv(SVCXPRT *xprt, struct x_vc_data *xd, struct xdr_ioq *xioq) { struct iovec *iov, *tiov, *wiov; struct poolq_entry *have; struct xdr_ioq_uv *data; ssize_t result; u_int32_t frag_header; u_int32_t fbytes; u_int32_t remaining = 0; u_int32_t vsize = (xioq->ioq_uv.uvqh.qcount + 1) * sizeof(struct iovec); int iw = 0; int ix = 1; if (unlikely(vsize > MAXALLOCA)) { iov = mem_alloc(vsize); if (unlikely(iov == NULL)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() malloc failed (%d)\n", __func__, errno); cfconn_set_dead(xprt, xd); return; } } else { iov = alloca(vsize); } wiov = iov; /* position at initial fragment header */ /* update the most recent data length, just in case */ xdr_tail_update(xioq->xdrs); /* build list after initial fragment header (ix = 1 above) */ TAILQ_FOREACH(have, &(xioq->ioq_uv.uvqh.qh), q) { data = IOQ_(have); tiov = iov + ix; tiov->iov_base = data->v.vio_head; tiov->iov_len = ioquv_length(data); remaining += tiov->iov_len; ix++; } while (remaining > 0) { if (iw == 0) { /* new fragment header, determine last iov */ fbytes = 0; for (tiov = &wiov[++iw]; (tiov < &iov[ix]) && (iw < __svc_maxiov); ++tiov, ++iw) { fbytes += tiov->iov_len; /* check for fragment value overflow */ /* never happens, see ganesha FSAL_MAXIOSIZE */ if (unlikely(fbytes >= LAST_FRAG)) { fbytes -= tiov->iov_len; break; } } /* for */ /* fragment length doesn't include fragment header */ if (&wiov[iw] < &iov[ix]) { frag_header = htonl((u_int32_t) (fbytes)); } else { frag_header = htonl((u_int32_t) (fbytes | LAST_FRAG)); } wiov->iov_base = &(frag_header); wiov->iov_len = sizeof(u_int32_t); /* writev return includes fragment header */ remaining += sizeof(u_int32_t); fbytes += sizeof(u_int32_t); } /* blocking write */ result = writev(xprt->xp_fd, wiov, iw); remaining -= result; if (result == fbytes) { wiov += iw - 1; iw = 0; continue; } if (unlikely(result < 0)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() writev failed (%d)\n", __func__, errno); cfconn_set_dead(xprt, xd); break; } fbytes -= result; /* rare? writev underrun? (assume never overrun) */ for (tiov = wiov; iw > 0; ++tiov, --iw) { if (tiov->iov_len > result) { tiov->iov_len -= result; tiov->iov_base += result; wiov = tiov; break; } else { result -= tiov->iov_len; } } /* for */ } /* while */ if (unlikely(vsize > MAXALLOCA)) { mem_free(iov, vsize); } } static void svc_ioq_callback(struct work_pool_entry *wpe) { struct x_vc_data *xd = (struct x_vc_data *)wpe; SVCXPRT *xprt = (SVCXPRT *)wpe->arg; struct poolq_entry *have; struct xdr_ioq *xioq; /* qmutex more fine grained than xp_lock */ for (;;) { mutex_lock(&xd->shared.ioq.qmutex); have = TAILQ_FIRST(&xd->shared.ioq.qh); if (unlikely(!have)) { xd->shared.active = false; mutex_unlock(&xd->shared.ioq.qmutex); SVC_RELEASE(xprt, SVC_RELEASE_FLAG_NONE); return; } TAILQ_REMOVE(&xd->shared.ioq.qh, have, q); (xd->shared.ioq.qcount)--; /* do i/o unlocked */ mutex_unlock(&xd->shared.ioq.qmutex); xioq = _IOQ(have); if (svc_work_pool.params.thrd_max && !(xprt->xp_flags & SVC_XPRT_FLAG_DESTROYED)) { /* all systems are go! */ ioq_flushv(xprt, xd, xioq); } XDR_DESTROY(xioq->xdrs); } return; } void svc_ioq_append(SVCXPRT *xprt, struct x_vc_data *xd, XDR *xdrs) { if (unlikely(!svc_work_pool.params.thrd_max || (xprt->xp_flags & SVC_XPRT_FLAG_DESTROYED))) { /* discard */ XDR_DESTROY(xdrs); return; } /* qmutex more fine grained than xp_lock */ mutex_lock(&xd->shared.ioq.qmutex); (xd->shared.ioq.qcount)++; TAILQ_INSERT_TAIL(&xd->shared.ioq.qh, &(XIOQ(xdrs)->ioq_s), q); if (!xd->shared.active) { xd->shared.active = true; xd->wpe.fun = svc_ioq_callback; xd->wpe.arg = xprt; mutex_unlock(&xd->shared.ioq.qmutex); SVC_REF(xprt, SVC_REF_FLAG_NONE); work_pool_submit(&svc_work_pool, &xd->wpe); } else { /* queuing multiple output requests for worker efficiency */ mutex_unlock(&xd->shared.ioq.qmutex); } } ntirpc-1.3.1/src/svc_ioq.h000066400000000000000000000027571261345040100154250ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef SVC_IOQ_H #define SVC_IOQ_H #include #include #include "clnt_internal.h" void svc_ioq_append(SVCXPRT *, struct x_vc_data *, XDR *); #endif /* SVC_IOQ_H */ ntirpc-1.3.1/src/svc_raw.c000066400000000000000000000137041261345040100154130ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ /* * 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 #include #include #include #include #include #include #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; extern mutex_t svcraw_lock; static void svc_raw_ops(SVCXPRT *); char *__rpc_rawcombuf = NULL; SVCXPRT * svc_raw_ncreate(void) { 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 = (struct svc_raw_private *)mem_alloc(sizeof(*srp)); if (srp == NULL) { mutex_unlock(&svcraw_lock); return (NULL); } if (__rpc_rawcombuf == NULL) __rpc_rawcombuf = mem_alloc(UDPMSGSIZE * sizeof(char)); 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); /* XXX check and or fixme */ #if 0 srp->server.xp_verf.oa_base = srp->verf_body; #endif xdrmem_create(&srp->xdr_stream, srp->raw_buf, UDPMSGSIZE, XDR_DECODE); xprt_register(&srp->server); mutex_unlock(&svcraw_lock); return (&srp->server); } /*ARGSUSED*/ static enum xprt_stat svc_raw_stat(SVCXPRT *xprt) { return (XPRT_IDLE); } /*ARGSUSED*/ static bool svc_raw_recv(SVCXPRT *xprt, struct svc_req *req) { struct rpc_msg *msg = req->rq_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 svc_raw_reply(SVCXPRT *xprt, struct svc_req *req, 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 svc_raw_freeargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *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 bool svc_raw_getargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr, void *u_data) { 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 void svc_raw_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line) { } /*ARGSUSED*/ static bool svc_raw_control(SVCXPRT *xprt, const u_int rq, void *in) { return (false); } static void svc_raw_ops(SVCXPRT *xprt) { static struct xp_ops ops; extern mutex_t ops_lock; /* 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; ops.xp_control = svc_raw_control; ops.xp_lock = NULL; /* no default */ ops.xp_unlock = NULL; /* no default */ ops.xp_getreq = svc_getreq_default; ops.xp_dispatch = svc_dispatch_default; ops.xp_recv_user_data = NULL; /* no default */ ops.xp_free_user_data = NULL; /* no default */ } xprt->xp_ops = &ops; mutex_unlock(&ops_lock); } ntirpc-1.3.1/src/svc_rdma.c000066400000000000000000000245171261345040100155510ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * Dominique Martinet * contributeur : William Allen Simpson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Implements connection server side RPC/RDMA. */ #include #include #include #include #include #include #include #include #if defined(TIRPC_EPOLL) #include /* before rpc.h */ #endif #include #include #include #include #include #include #include #include #include "rpc_com.h" #include "misc/city.h" #include "rpc/xdr_inrec.h" #include "svc_internal.h" #include "clnt_internal.h" #include "svc_xprt.h" #include "rpc_rdma.h" #include #include /* * kept in xprt->xp_p2 (sm_data(xprt)) */ struct svc_rdma_xdr { XDR sm_xdrs; /* XDR handle *MUST* be top */ char sm_verfbody[MAX_AUTH_BYTES]; /* verifier body */ struct msghdr sm_msghdr; /* msghdr received from clnt */ unsigned char sm_cmsg[64]; /* cmsghdr received from clnt */ size_t sm_iosz; /* size of send.recv buffer */ }; #define sm_data(xprt) ((struct svc_rdma_xdr *)(xprt->xp_p2)) extern struct svc_params __svc_params[1]; static void svc_rdma_ops(SVCXPRT *); /* * svc_rdma_ncreate: waits for connection request and returns transport */ SVCXPRT * svc_rdma_ncreate(void *arg, const u_int sendsize, const u_int recvsize, const u_int flags) { struct svc_rdma_xdr *sm; struct sockaddr_storage *ss; RDMAXPRT *l_xprt = arg; RDMAXPRT *xprt = rpc_rdma_accept_wait(l_xprt, l_xprt->xa->timeout); if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s:%u ERROR (return)", __func__, __LINE__); return (NULL); } sm = mem_zalloc(sizeof (*sm)); if (sm == NULL) goto freedata; sm->sm_xdrs.x_lib[1] = xprt; xprt->xprt.xp_p2 = sm; xprt->xprt.xp_flags = flags; /* fixme: put something here, but make it not work on fd operations. */ xprt->xprt.xp_fd = -1; ss = (struct sockaddr_storage *)rdma_get_local_addr(xprt->cm_id); __rpc_set_address(&xprt->xprt.xp_local, ss, 0); ss = (struct sockaddr_storage *)rdma_get_peer_addr(xprt->cm_id); __rpc_set_address(&xprt->xprt.xp_remote, ss, 0); svc_rdma_ops(&xprt->xprt); if (xdr_rdma_create(&sm->sm_xdrs, xprt, sendsize, recvsize, flags)) { goto freedata; } if (rpc_rdma_accept_finalize(xprt)) { goto freedata; } return (&xprt->xprt); freedata: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() out of memory", __func__); if (sm) { (void) mem_free(sm, sizeof (*sm)); xprt->xprt.xp_p2 = NULL; } xprt_unregister(&xprt->xprt); return (NULL); } /*ARGSUSED*/ static enum xprt_stat svc_rdma_stat(SVCXPRT *xprt) { /* note: RDMAXPRT is this xprt! */ switch(((RDMAXPRT *)xprt)->state) { case RDMAXS_LISTENING: case RDMAXS_CONNECTED: return (XPRT_IDLE); /* any point in adding a break? */ default: /* suppose anything else means a problem */ return (XPRT_DIED); } } static bool svc_rdma_recv(SVCXPRT *xprt, struct svc_req *req) { struct rpc_rdma_cbc *cbc = req->rq_context; XDR *xdrs = cbc->holdq.xdrs; __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s() xprt %p cbc %p incoming xdr %p\n", __func__, xprt, cbc, xdrs); req->rq_msg = alloc_rpc_msg(); if (!xdr_rdma_svc_recv(cbc, 0)){ __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s: xdr_rdma_svc_recv failed (will set dead)", __func__); return (FALSE); } xdrs->x_op = XDR_DECODE; /* No need, already positioned to beginning ... XDR_SETPOS(xdrs, 0); */ if (!xdr_dplx_decode(xdrs, req->rq_msg)) { __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s: xdr_dplx_decode failed (will set dead)", __func__); return (FALSE); } req->rq_xprt = xprt; req->rq_prog = req->rq_msg->rm_call.cb_prog; req->rq_vers = req->rq_msg->rm_call.cb_vers; req->rq_proc = req->rq_msg->rm_call.cb_proc; req->rq_xid = req->rq_msg->rm_xid; req->rq_clntcred = req->rq_msg->rq_cred_body; /* the checksum */ req->rq_cksum = 0; return (TRUE); } static bool svc_rdma_reply(SVCXPRT *xprt, struct svc_req *req, struct rpc_msg *msg) { struct rpc_rdma_cbc *cbc = req->rq_context; XDR *xdrs = cbc->holdq.xdrs; xdrproc_t proc; void *where; bool has_args; __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s() xprt %p cbc %p outgoing xdr %p\n", __func__, xprt, cbc, xdrs); if (msg->rm_reply.rp_stat == MSG_ACCEPTED && msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { has_args = TRUE; proc = msg->acpted_rply.ar_results.proc; where = msg->acpted_rply.ar_results.where; msg->acpted_rply.ar_results.proc = (xdrproc_t)xdr_void; msg->acpted_rply.ar_results.where = NULL; } else { has_args = FALSE; proc = NULL; where = NULL; } if (!xdr_rdma_svc_reply(cbc, 0)){ __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s: xdr_rdma_svc_reply failed (will set dead)", __func__); return (FALSE); } xdrs->x_op = XDR_ENCODE; if (!xdr_reply_encode(xdrs, msg)) { __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s: xdr_reply_encode failed (will set dead)", __func__); return (FALSE); } xdr_tail_update(xdrs); if (has_args && req->rq_auth && !SVCAUTH_WRAP(req->rq_auth, req, xdrs, proc, where)) { __warnx(TIRPC_DEBUG_FLAG_SVC_RDMA, "%s: SVCAUTH_WRAP failed (will set dead)", __func__); return (FALSE); } xdr_tail_update(xdrs); return xdr_rdma_svc_flushout(cbc); } static bool svc_rdma_freeargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr) { struct rpc_rdma_cbc *cbc = req->rq_context; XDR *xdrs = cbc->holdq.xdrs; xdrs->x_op = XDR_FREE; return (*xdr_args)(xdrs, args_ptr); } static bool svc_rdma_getargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr, void *u_data) { struct rpc_rdma_cbc *cbc = req->rq_context; XDR *xdrs = cbc->holdq.xdrs; bool rslt; /* threads u_data for advanced decoders*/ xdrs->x_public = u_data; rslt = SVCAUTH_UNWRAP(req->rq_auth, req, xdrs, xdr_args, args_ptr); if (!rslt) svc_rdma_freeargs(xprt, req, xdr_args, args_ptr); return (rslt); } static void svc_rdma_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line) { struct svc_rdma_xdr *sm = sm_data(xprt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s() %p xp_refs %" PRId32 " should actually destroy things @ %s:%d", __func__, xprt, xprt->xp_refs, tag, line); xdr_rdma_destroy(&(sm->sm_xdrs)); (void) mem_free(sm, sizeof (*sm)); if (xprt->xp_ops->xp_free_user_data) { /* call free hook */ xprt->xp_ops->xp_free_user_data(xprt); } rpc_rdma_destroy(xprt); } extern mutex_t ops_lock; static void svc_rdma_lock(SVCXPRT *xprt, uint32_t flags, const char *file, int line) { /* pretend we lock for now */ } static void svc_rdma_unlock(SVCXPRT *xprt, uint32_t flags, const char *file, int line) { } static bool /*ARGSUSED*/ svc_rdma_control(SVCXPRT *xprt, const u_int rq, void *in) { switch (rq) { case SVCGET_XP_FLAGS: *(u_int *)in = xprt->xp_flags; break; case SVCSET_XP_FLAGS: xprt->xp_flags = *(u_int *)in; break; case SVCGET_XP_RECV: mutex_lock(&ops_lock); *(xp_recv_t *)in = xprt->xp_ops->xp_recv; mutex_unlock(&ops_lock); break; case SVCSET_XP_RECV: mutex_lock(&ops_lock); xprt->xp_ops->xp_recv = *(xp_recv_t)in; mutex_unlock(&ops_lock); break; case SVCGET_XP_GETREQ: mutex_lock(&ops_lock); *(xp_getreq_t *)in = xprt->xp_ops->xp_getreq; mutex_unlock(&ops_lock); break; case SVCSET_XP_GETREQ: mutex_lock(&ops_lock); xprt->xp_ops->xp_getreq = *(xp_getreq_t)in; mutex_unlock(&ops_lock); break; case SVCGET_XP_DISPATCH: mutex_lock(&ops_lock); *(xp_dispatch_t *)in = xprt->xp_ops->xp_dispatch; mutex_unlock(&ops_lock); break; case SVCSET_XP_DISPATCH: mutex_lock(&ops_lock); xprt->xp_ops->xp_dispatch = *(xp_dispatch_t)in; mutex_unlock(&ops_lock); break; case SVCGET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); *(xp_free_user_data_t *)in = xprt->xp_ops->xp_free_user_data; mutex_unlock(&ops_lock); break; case SVCSET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); xprt->xp_ops->xp_free_user_data = *(xp_free_user_data_t)in; mutex_unlock(&ops_lock); break; default: return (FALSE); } return (TRUE); } static void svc_rdma_ops(SVCXPRT *xprt) { static struct xp_ops ops; /* VARIABLES PROTECTED BY ops_lock: ops, xp_type */ mutex_lock(&ops_lock); /* Fill in type of service */ xprt->xp_type = XPRT_RDMA; if (ops.xp_recv == NULL) { ops.xp_recv = svc_rdma_recv; ops.xp_stat = svc_rdma_stat; ops.xp_getargs = svc_rdma_getargs; ops.xp_reply = svc_rdma_reply; ops.xp_freeargs = svc_rdma_freeargs; ops.xp_destroy = svc_rdma_destroy, ops.xp_control = svc_rdma_control; ops.xp_lock = svc_rdma_lock; ops.xp_unlock = svc_rdma_unlock; ops.xp_getreq = svc_getreq_default; ops.xp_dispatch = svc_dispatch_default; ops.xp_recv_user_data = NULL; /* no default */ ops.xp_free_user_data = NULL; /* no default */ } xprt->xp_ops = &ops; mutex_unlock(&ops_lock); } ntirpc-1.3.1/src/svc_rqst.c000066400000000000000000000637361261345040100156250ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include #include #include #ifdef PORTMAP #include #endif /* PORTMAP */ #include #include "rpc_com.h" #include #include #include #include "clnt_internal.h" #include "svc_internal.h" #include #include "svc_xprt.h" /* * The TI-RPC instance should be able to reach every registered * handler, and potentially each SVCXPRT registered on it. * * Each SVCXPRT points to its own handler, however, so operations to * block/unblock events (for example) given an existing xprt handle * are O(1) without any ordered or hashed representation. */ #define SVC_RQST_PARTITIONS 7 static bool initialized; struct svc_rqst_set { mutex_t mtx; struct rbtree_x xt; uint32_t next_id; }; static struct svc_rqst_set svc_rqst_set = { MUTEX_INITIALIZER, /* mtx */ { 0, /* npart */ RBT_X_FLAG_NONE, /* flags */ 23, /* cachesz */ NULL /* tree */ }, /* xt */ 0 /* next_id */ }; extern struct svc_params __svc_params[1]; #define cond_init_svc_rqst() { \ do { \ if (!initialized) \ svc_rqst_init(); \ } while (0); \ } struct svc_rqst_rec { struct opr_rbtree_node node_k; TAILQ_HEAD(evq_head, rpc_svcxprt) xprt_q; /* xprt handles */ pthread_mutex_t mtx; void *u_data; /* user-installable opaque data */ uint64_t gen; /* generation number */ int sv[2]; uint32_t id_k; /* chan id */ uint32_t states; uint32_t signals; uint32_t refcnt; uint16_t flags; /* * union of event processor types */ enum svc_event_type ev_type; union { #if defined(TIRPC_EPOLL) struct { int epoll_fd; struct epoll_event ctrl_ev; struct epoll_event *events; u_int max_events; /* max epoll events */ } epoll; #endif struct { fd_set set; /* select/fd_set (currently unhooked) */ } fd; } ev_u; }; static inline int rqst_thrd_cmpf(const struct opr_rbtree_node *lhs, const struct opr_rbtree_node *rhs) { struct svc_rqst_rec *lk, *rk; lk = opr_containerof(lhs, struct svc_rqst_rec, node_k); rk = opr_containerof(rhs, struct svc_rqst_rec, node_k); if (lk->id_k < rk->id_k) return (-1); if (lk->id_k == rk->id_k) return (0); return (1); } /* forward declaration in lieu of moving code {WAS} */ static int svc_rqst_evchan_unreg(uint32_t chan_id, SVCXPRT *xprt, uint32_t flags); static int svc_rqst_unhook_events(SVCXPRT *, struct svc_rqst_rec *); static int svc_rqst_hook_events(SVCXPRT *, struct svc_rqst_rec *); static inline void SetNonBlock(int fd) { int s_flags = fcntl(fd, F_GETFL, 0); (void)fcntl(fd, F_SETFL, (s_flags | O_NONBLOCK)); } void svc_rqst_init() { int ix, code = 0; mutex_lock(&svc_rqst_set.mtx); if (initialized) goto unlock; code = rbtx_init(&svc_rqst_set.xt, rqst_thrd_cmpf, SVC_RQST_PARTITIONS, RBT_X_FLAG_ALLOC | RBT_X_FLAG_CACHE_RT); if (code) __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: rbtx_init failed", __func__); /* init read-through cache */ for (ix = 0; ix < SVC_RQST_PARTITIONS; ++ix) { struct rbtree_x_part *xp = &(svc_rqst_set.xt.tree[ix]); xp->cache = mem_zalloc(svc_rqst_set.xt.cachesz * sizeof(struct opr_rbtree_node *)); if (!xp->cache) { __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: rbtx cache partition alloc failed", __func__); svc_rqst_set.xt.cachesz = 0; break; } } initialized = true; unlock: mutex_unlock(&svc_rqst_set.mtx); } void svc_rqst_init_xprt(SVCXPRT *xprt) { /* reachable */ svc_xprt_set(xprt, SVC_XPRT_FLAG_UNLOCK); /* !!! not checking for duplicate xp_fd ??? */ } /** * @brief Lookup a channel * @note Locking * - SVC_RQST_FLAG_PART_UNLOCK - Unlock the tree partition before returning. * Otherwise, it is returned locked. * - SVC_RQST_FLAG_SREC_LOCKED - The sr_rec is already locked; don't lock it * again. * - SVC_RQST_FLAG_SREC_UNLOCK - Unlock the sr_rec before returning. Otherwise, * it is returned locked. */ static inline struct svc_rqst_rec * svc_rqst_lookup_chan(uint32_t chan_id, struct rbtree_x_part **ref_t, uint32_t flags) { struct svc_rqst_rec trec; struct rbtree_x_part *t; struct opr_rbtree_node *ns; struct svc_rqst_rec *sr_rec = NULL; cond_init_svc_rqst(); trec.id_k = chan_id; t = rbtx_partition_of_scalar(&svc_rqst_set.xt, trec.id_k); *ref_t = t; mutex_lock(&t->mtx); ns = rbtree_x_cached_lookup(&svc_rqst_set.xt, t, &trec.node_k, trec.id_k); if (ns) { sr_rec = opr_containerof(ns, struct svc_rqst_rec, node_k); if (!(flags & SVC_RQST_FLAG_SREC_LOCKED)) mutex_lock(&sr_rec->mtx); ++(sr_rec->refcnt); if (flags & SVC_RQST_FLAG_SREC_UNLOCK) mutex_unlock(&sr_rec->mtx); } if (flags & SVC_RQST_FLAG_PART_UNLOCK) mutex_unlock(&t->mtx); return (sr_rec); } int svc_rqst_new_evchan(uint32_t *chan_id /* OUT */, void *u_data, uint32_t flags) { uint32_t n_id; struct svc_rqst_rec *sr_rec; struct rbtree_x_part *t; bool rslt __attribute__ ((unused)); int code = 0; cond_init_svc_rqst(); flags |= SVC_RQST_FLAG_EPOLL; /* XXX */ sr_rec = mem_alloc(sizeof(struct svc_rqst_rec)); if (!sr_rec) { __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: failed allocating svc_rqst_rec", __func__); goto out; } memset(sr_rec, 0, sizeof(struct svc_rqst_rec)); /* create a pair of anonymous sockets for async event channel wakeups */ code = socketpair(AF_UNIX, SOCK_STREAM, 0, sr_rec->sv); if (code) { __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: failed creating event signal socketpair", __func__); mem_free(sr_rec, sizeof(struct svc_rqst_rec)); goto out; } /* set non-blocking */ SetNonBlock(sr_rec->sv[0]); SetNonBlock(sr_rec->sv[1]); #if defined(TIRPC_EPOLL) if (flags & SVC_RQST_FLAG_EPOLL) { sr_rec->flags = flags & SVC_RQST_FLAG_MASK; sr_rec->ev_type = SVC_EVENT_EPOLL; /* XXX improve this too */ sr_rec->ev_u.epoll.max_events = __svc_params->ev_u.evchan.max_events; sr_rec->ev_u.epoll.events = (struct epoll_event *) mem_alloc(sr_rec->ev_u.epoll.max_events * sizeof(struct epoll_event)); if (!sr_rec->ev_u.epoll.events) { mem_free(sr_rec, sizeof(struct svc_rqst_rec)); code = ENOMEM; goto out; } /* create epoll fd */ sr_rec->ev_u.epoll.epoll_fd = epoll_create_wr(sr_rec->ev_u.epoll.max_events, EPOLL_CLOEXEC); if (sr_rec->ev_u.epoll.epoll_fd == -1) { __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: epoll_create failed (%d)", __func__, errno); mem_free(sr_rec->ev_u.epoll.events, sr_rec->ev_u.epoll.max_events * sizeof(struct epoll_event)); mem_free(sr_rec, sizeof(struct svc_rqst_rec)); code = EINVAL; goto out; } /* permit wakeup of threads blocked in epoll_wait, with a * couple of possible semantics */ sr_rec->ev_u.epoll.ctrl_ev.events = EPOLLIN | EPOLLRDHUP; sr_rec->ev_u.epoll.ctrl_ev.data.fd = sr_rec->sv[1]; code = epoll_ctl(sr_rec->ev_u.epoll.epoll_fd, EPOLL_CTL_ADD, sr_rec->sv[1], &sr_rec->ev_u.epoll.ctrl_ev); if (code == -1) __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: add control socket failed (%d)", __func__, errno); } else { /* legacy fdset (currently unhooked) */ sr_rec->ev_type = SVC_EVENT_FDSET; } #else sr_rec->ev_type = SVC_EVENT_FDSET; #endif mutex_lock(&svc_rqst_set.mtx); n_id = ++(svc_rqst_set.next_id); mutex_unlock(&svc_rqst_set.mtx); sr_rec->id_k = n_id; sr_rec->states = SVC_RQST_STATE_NONE; sr_rec->u_data = u_data; sr_rec->refcnt = 1; /* svc_rqst_set ref */ sr_rec->gen = 0; mutex_init(&sr_rec->mtx, NULL); TAILQ_INIT(&sr_rec->xprt_q); t = rbtx_partition_of_scalar(&svc_rqst_set.xt, sr_rec->id_k); mutex_lock(&t->mtx); rslt = rbtree_x_cached_insert(&svc_rqst_set.xt, t, &sr_rec->node_k, sr_rec->id_k); mutex_unlock(&t->mtx); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: create evchan %d socketpair %d:%d", __func__, n_id, sr_rec->sv[0], sr_rec->sv[1]); *chan_id = n_id; out: return (code); } /* * @note Lock flags * - Locks xprt unless SVC_RQST_FLAG_LOCKED is passed * - Locks sr_rec unless RVC_RQST_FLAG_SREC_LOCKED is passed * - Returns with xprt locked unless SVC_RQST_FLAG_UNLOCK is passed * - Returns with sr_rec locked unless SVC_RQST_FLAG_SREC_UNLOCKED is passed */ static inline void evchan_unreg_impl(struct svc_rqst_rec *sr_rec, SVCXPRT *xprt, uint32_t flags) { if (!(flags & SVC_RQST_FLAG_SREC_LOCKED)) mutex_lock(&sr_rec->mtx); if (!(flags & SVC_RQST_FLAG_LOCKED)) mutex_lock(&xprt->xp_lock); TAILQ_REMOVE(&sr_rec->xprt_q, xprt, xp_evq); /* clear events */ (void)svc_rqst_unhook_events(xprt, sr_rec); /* both LOCKED */ /* unlink from xprt */ xprt->xp_ev = NULL; __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: %p xp_refs %" PRIu32 " after remove, before channel release", __func__, xprt, xprt->xp_refs); if (flags & SVC_RQST_FLAG_UNLOCK) mutex_unlock(&xprt->xp_lock); if (flags & SVC_RQST_FLAG_SREC_UNLOCK) mutex_unlock(&sr_rec->mtx); } /* * Write 4-byte value to shared event-notification channel. The * value as presently implemented can be interpreted only by one consumer, * so is not relied on. */ static inline void ev_sig(int fd, uint32_t sig) { int code = write(fd, &sig, sizeof(uint32_t)); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: fd %d sig %d", __func__, fd, sig); if (code < 1) __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: error writing to event socket (%d:%d)", __func__, code, errno); } /* * Read a single 4-byte value from the shared event-notification channel, * the socket is in non-blocking mode. The value read is returned. */ static inline uint32_t consume_ev_sig_nb(int fd) { uint32_t sig = 0; int code __attribute__ ((unused)); code = read(fd, &sig, sizeof(uint32_t)); return (sig); } /** * Release a request * @note Locking * - sr_req is locked unless SVC_RQST_FLAG_SREC_LOCKED is passed * - sr_req is unlocked unless SR_REQ_RELEASE_KEEP_LOCKED is passed */ static inline void sr_rec_release(struct svc_rqst_rec *sr_rec, uint32_t flags) { uint32_t refcnt; if (!(flags & SVC_RQST_FLAG_SREC_LOCKED)) mutex_lock(&sr_rec->mtx); refcnt = --(sr_rec->refcnt); if (!(flags & SR_REQ_RELEASE_KEEP_LOCKED)) mutex_unlock(&sr_rec->mtx); if (refcnt == 0) { if (flags & SR_REQ_RELEASE_KEEP_LOCKED) mutex_unlock(&sr_rec->mtx); /* assert sr_rec DESTROYED */ mutex_destroy(&sr_rec->mtx); mem_free(sr_rec, sizeof(struct svc_rqst_rec)); } } static int svc_rqst_delete_evchan(uint32_t chan_id) { struct svc_rqst_rec *sr_rec; struct rbtree_x_part *t; SVCXPRT *next; SVCXPRT *xprt = NULL; int code = 0; sr_rec = svc_rqst_lookup_chan(chan_id, &t, SVC_XPRT_FLAG_NONE); if (!sr_rec) { mutex_unlock(&t->mtx); code = ENOENT; goto out; } /* traverse sr_req->xprt_q inorder */ /* sr_rec LOCKED */ xprt = TAILQ_FIRST(&sr_rec->xprt_q); while (xprt) { next = TAILQ_NEXT(xprt, xp_evq); /* indirect on xp_ev */ /* stop processing events */ evchan_unreg_impl(sr_rec, xprt, (SVC_RQST_FLAG_UNLOCK | SVC_RQST_FLAG_SREC_LOCKED)); /* wake up */ ev_sig(sr_rec->sv[0], 0); switch (sr_rec->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: code = epoll_ctl(sr_rec->ev_u.epoll.epoll_fd, EPOLL_CTL_DEL, sr_rec->sv[1], &sr_rec->ev_u.epoll.ctrl_ev); if (code == -1) __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: epoll del control socket failed (%d)", __func__, errno); break; #endif default: break; } xprt = next; } /* now remove sr_rec */ rbtree_x_cached_remove(&svc_rqst_set.xt, t, &sr_rec->node_k, sr_rec->id_k); mutex_unlock(&t->mtx); switch (sr_rec->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: close(sr_rec->ev_u.epoll.epoll_fd); mem_free(sr_rec->ev_u.epoll.events, sr_rec->ev_u.epoll.max_events * sizeof(struct epoll_event)); break; #endif default: /* XXX */ break; } sr_rec->states = SVC_RQST_STATE_DESTROYED; sr_rec->id_k = 0; /* no chan */ /* ref count here should be 2: * 1 initial create/rbt ref we just deleted * +1 lookup (top of this routine through here) * so, DROP one ref here so the final release will go to 0. */ --(sr_rec->refcnt); /* DROP one extra ref - initial create */ sr_rec_release(sr_rec, SVC_RQST_FLAG_SREC_LOCKED); out: return (code); } int svc_rqst_evchan_reg(uint32_t chan_id, SVCXPRT *xprt, uint32_t flags) { struct svc_rqst_rec *sr_rec; struct rbtree_x_part *t; int code = 0; if (chan_id == 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: called with chan_id 0, fatal (bug)", __func__); goto out; } sr_rec = svc_rqst_lookup_chan(chan_id, &t, SVC_XPRT_FLAG_NONE); if (!sr_rec) { mutex_unlock(&t->mtx); code = ENOENT; goto out; } mutex_lock(&xprt->xp_lock); if (flags & SVC_RQST_FLAG_XPRT_UREG) { if (chan_id != __svc_params->ev_u.evchan.id) { svc_rqst_evchan_unreg(__svc_params->ev_u.evchan.id, xprt, (SVC_RQST_FLAG_LOCKED | SVC_RQST_FLAG_SREC_LOCKED)); svc_xprt_clear(xprt, SVC_XPRT_FLAG_LOCKED); } } TAILQ_INSERT_TAIL(&sr_rec->xprt_q, xprt, xp_evq); /* link from xprt */ xprt->xp_ev = sr_rec; /* register on event channel */ (void)svc_rqst_hook_events(xprt, sr_rec); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: pre channel %p xp_refs %" PRIu32, __func__, xprt, xprt->xp_refs); mutex_unlock(&xprt->xp_lock); sr_rec_release(sr_rec, SVC_RQST_FLAG_SREC_LOCKED); mutex_unlock(&t->mtx); out: return (code); } /** * Unregister an evchan * @note Locking * - Takes sr_req lock, unless SVC_RQST_FLAG_SREC_LOCKED is passed * - Takes xprt lock, unless SVC_RQST_FLAG_LOCKED is passed * - Returns with sr_req locked and xprt locked at all times */ static int svc_rqst_evchan_unreg(uint32_t chan_id, SVCXPRT *xprt, uint32_t flags) { struct svc_rqst_rec *sr_rec; struct rbtree_x_part *t; int code = EINVAL; /* Don't let them force unlocking of the part; we need that */ flags &= ~(SVC_RQST_FLAG_PART_UNLOCK | SVC_RQST_FLAG_SREC_UNLOCK); sr_rec = svc_rqst_lookup_chan(chan_id, &t, flags); if (!sr_rec) { code = ENOENT; goto unlock; } evchan_unreg_impl(sr_rec, xprt, (flags | SVC_RQST_FLAG_SREC_LOCKED)); unlock: mutex_unlock(&t->mtx); if (sr_rec) sr_rec_release(sr_rec, SVC_RQST_FLAG_SREC_LOCKED | SR_REQ_RELEASE_KEEP_LOCKED); return (code); } static int svc_rqst_unhook_events(SVCXPRT *xprt /* LOCKED */ , struct svc_rqst_rec *sr_rec /* LOCKED */) { int code; cond_init_svc_rqst(); atomic_set_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_BLOCKED); switch (sr_rec->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: { struct epoll_event *ev = &xprt->ev_u.epoll.event; /* clear epoll vector */ code = epoll_ctl(sr_rec->ev_u.epoll.epoll_fd, EPOLL_CTL_DEL, xprt->xp_fd, ev); if (code) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: %p epoll del failed fd %d " "sr_rec %p epoll_fd %d " "control fd pair (%d:%d) (%d, %d)", sr_rec, sr_rec->ev_u.epoll.epoll_fd, sr_rec->sv[0], sr_rec->sv[1], code, errno); code = errno; } else { atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_ADDED); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: %p epoll del fd %d " "sr_rec %p epoll_fd %d " "control fd pair (%d:%d) (%d, %d)", __func__, xprt, xprt->xp_fd, sr_rec, sr_rec->ev_u.epoll.epoll_fd, sr_rec->sv[0], sr_rec->sv[1], code, errno); } break; } #endif default: /* XXX formerly select/fd_set case, now placeholder for new * event systems, reworked select, etc. */ break; } /* switch */ return (0); } int svc_rqst_rearm_events(SVCXPRT *xprt, uint32_t __attribute__ ((unused)) flags) { struct svc_rqst_rec *sr_rec; int code; cond_init_svc_rqst(); sr_rec = (struct svc_rqst_rec *)xprt->xp_ev; /* Don't rearm a destroyed (but not yet collected) xprx */ if (xprt->xp_flags & SVC_XPRT_FLAG_DESTROYED) goto out; /* MUST follow the destroyed check above */ assert(sr_rec); mutex_lock(&sr_rec->mtx); if (atomic_fetch_uint16_t(&xprt->xp_flags) & SVC_XPRT_FLAG_ADDED) { switch (sr_rec->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: { struct epoll_event *ev = &xprt->ev_u.epoll.event; /* set up epoll user data */ /* ev->data.ptr = xprt; *//* XXX already set */ ev->events = EPOLLIN | EPOLLONESHOT; /* rearm in epoll vector */ code = epoll_ctl(sr_rec->ev_u.epoll.epoll_fd, EPOLL_CTL_MOD, xprt->xp_fd, ev); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: %p epoll arm fd %d " "sr_rec %p epoll_fd %d " "control fd pair (%d:%d) (%d, %d)", __func__, xprt, xprt->xp_fd, sr_rec, sr_rec->ev_u.epoll.epoll_fd, sr_rec->sv[0], sr_rec->sv[1], code, errno); break; } #endif default: /* XXX formerly select/fd_set case, now placeholder * for new event systems, reworked select, etc. */ break; } /* switch */ } mutex_unlock(&sr_rec->mtx); out: return (0); } static int svc_rqst_hook_events(SVCXPRT *xprt /* LOCKED */ , struct svc_rqst_rec *sr_rec /* LOCKED */) { int code; cond_init_svc_rqst(); atomic_clear_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_BLOCKED); switch (sr_rec->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: { struct epoll_event *ev = &xprt->ev_u.epoll.event; /* set up epoll user data */ ev->data.ptr = xprt; /* wait for read events, level triggered, oneshot */ ev->events = EPOLLIN | EPOLLONESHOT; /* add to epoll vector */ code = epoll_ctl(sr_rec->ev_u.epoll.epoll_fd, EPOLL_CTL_ADD, xprt->xp_fd, ev); if (code) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s: %p epoll add failed fd %d " "sr_rec %p epoll_fd %d " "control fd pair (%d:%d) (%d, %d)", __func__, xprt, xprt->xp_fd, sr_rec, sr_rec->ev_u.epoll.epoll_fd, sr_rec->sv[0], sr_rec->sv[1], code, errno); code = errno; } else { atomic_set_uint16_t_bits(&xprt->xp_flags, SVC_XPRT_FLAG_ADDED); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: %p epoll add fd %d " "sr_rec %p epoll_fd %d " "control fd pair (%d:%d) (%d, %d)", __func__, xprt, xprt->xp_fd, sr_rec, sr_rec->ev_u.epoll.epoll_fd, sr_rec->sv[0], sr_rec->sv[1], code, errno); } break; } #endif default: /* XXX formerly select/fd_set case, now placeholder for new * event systems, reworked select, etc. */ break; } /* switch */ ev_sig(sr_rec->sv[0], 0); /* send wakeup */ return (0); } /* register newxprt on an event channel, based on various * parameters */ int svc_rqst_xprt_register(SVCXPRT *xprt, SVCXPRT *newxprt) { struct svc_rqst_rec *sr_rec; int code = 0; cond_init_svc_rqst(); /* do nothing if event registration is globally disabled */ if (__svc_params->flags & SVC_FLAG_NOREG_XPRTS) goto out; /* use global registration if no parent xprt */ if (!xprt) { xprt_register(newxprt); goto out; } sr_rec = (struct svc_rqst_rec *)xprt->xp_ev; /* or if parent xprt has no dedicated event channel */ if (!sr_rec) { xprt_register(newxprt); goto out; } /* follow policy if applied. the client code will still normally * be called back to, e.g., adjust channel assignment */ if (sr_rec->flags & SVC_RQST_FLAG_CHAN_AFFINITY) svc_rqst_evchan_reg(sr_rec->id_k, newxprt, SVC_RQST_FLAG_NONE); else xprt_register(newxprt); out: return (code); } void xprt_unregister(SVCXPRT *xprt) { struct svc_rqst_rec *sr_rec = (struct svc_rqst_rec *)xprt->xp_ev; /* if xprt is is on a dedicated channel? */ if (sr_rec && sr_rec->id_k) { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s:%u %p xp_refs %" PRIu32, __func__, __LINE__, xprt, xprt->xp_refs); evchan_unreg_impl(sr_rec, xprt, SVC_RQST_FLAG_NONE); } else { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s:%u %p xp_refs %" PRIu32, __func__, __LINE__, xprt, xprt->xp_refs); (void)svc_rqst_evchan_unreg(__svc_params->ev_u.evchan.id, xprt, SVC_RQST_FLAG_PART_UNLOCK); } /* remove xprt from xprt table */ svc_xprt_clear(xprt, SVC_XPRT_FLAG_LOCKED); /* free state */ xprt->xp_ev = NULL; /* xprt must be unlocked before sr_rec */ mutex_unlock(&xprt->xp_lock); if (sr_rec) mutex_unlock(&sr_rec->mtx); } bool_t __svc_clean_idle2(int timeout, bool_t cleanblock); #ifdef TIRPC_EPOLL static inline void svc_rqst_handle_event(struct svc_rqst_rec *sr_rec, struct epoll_event *ev, uint32_t wakeups) { SVCXPRT *xprt; int code __attribute__ ((unused)); if (ev->data.fd != sr_rec->sv[1]) { xprt = (SVCXPRT *) ev->data.ptr; if (!(atomic_fetch_uint16_t(&xprt->xp_flags) & (SVC_XPRT_FLAG_BLOCKED | SVC_XPRT_FLAG_DESTROYED)) && (xprt->xp_refs > 0)) { /* check for valid xprt. No need for lock; * (idempotent) xp_flags and xp_refs are set atomic. */ __warnx(TIRPC_DEBUG_FLAG_REFCNT | TIRPC_DEBUG_FLAG_SVC_RQST, "%s: %p xp_refs %" PRIu32 " fd %d or ptr %p EPOLL event %d", __func__, xprt, xprt->xp_refs, ev->data.fd, ev->data.ptr, ev->events); /* take extra ref, callout will release */ SVC_REF(xprt, SVC_REF_FLAG_NONE); /* ! LOCKED */ code = xprt->xp_ops->xp_getreq(xprt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: %p xp_refs %" PRIu32 " post xp_getreq", __func__, xprt, xprt->xp_refs); } /* XXX failsafe idle processing */ if ((wakeups % 1000) == 0) __svc_clean_idle2(__svc_params->idle_timeout, true); } else { /* signalled -- there was a wakeup on ctrl_ev (see * top-of-loop) */ __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: wakeup fd %d (sr_rec %p)", __func__, sr_rec->sv[1], sr_rec); (void)consume_ev_sig_nb(sr_rec->sv[1]); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: after consume sig fd %d (sr_rec %p)", __func__, sr_rec->sv[1], sr_rec); } } static inline int svc_rqst_thrd_run_epoll(struct svc_rqst_rec *sr_rec, uint32_t __attribute__ ((unused)) flags) { struct epoll_event *ev; int ix, code = 0; int timeout_ms = 120 * 1000; /* XXX */ int n_events; static uint32_t wakeups; for (;;) { mutex_lock(&sr_rec->mtx); ++(wakeups); /* check for signals */ if (sr_rec->signals & SVC_RQST_SIGNAL_SHUTDOWN) { mutex_unlock(&sr_rec->mtx); break; } mutex_unlock(&sr_rec->mtx); __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: before epoll_wait fd %d", __func__, sr_rec->ev_u.epoll.epoll_fd); switch (n_events = epoll_wait(sr_rec->ev_u.epoll.epoll_fd, sr_rec->ev_u.epoll.events, sr_rec->ev_u.epoll.max_events, timeout_ms)) { case -1: if (errno == EINTR) continue; __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "%s: epoll_wait failed %d", __func__, errno); break; case 0: /* timed out (idle) */ __svc_clean_idle2(__svc_params->idle_timeout, true); continue; default: /* new events */ for (ix = 0; ix < n_events; ++ix) { ev = &(sr_rec->ev_u.epoll.events[ix]); svc_rqst_handle_event(sr_rec, ev, wakeups); } } } return (code); } #endif int svc_rqst_thrd_run(uint32_t chan_id, __attribute__ ((unused)) uint32_t flags) { struct svc_rqst_rec *sr_rec = NULL; struct rbtree_x_part *t; int code = 0; sr_rec = svc_rqst_lookup_chan(chan_id, &t, (SVC_RQST_FLAG_PART_UNLOCK)); if (!sr_rec) { __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "svc_rqst_thrd_run: unknown chan_id %d", chan_id); code = ENOENT; goto out; } /* serialization model for srec is mutual exclusion on mutation only, * with a secondary state machine to detect inconsistencies (e.g., * trying to unregister a channel when it is active) */ sr_rec->states |= SVC_RQST_STATE_ACTIVE; mutex_unlock(&sr_rec->mtx); /* enter event loop */ switch (sr_rec->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: code = svc_rqst_thrd_run_epoll(sr_rec, flags); break; #endif default: /* XXX formerly select/fd_set case, now placeholder for new * event systems, reworked select, etc. */ __warnx(TIRPC_DEBUG_FLAG_SVC_RQST, "svc_rqst_thrd_run: unsupported event type"); break; } /* switch */ if (sr_rec) sr_rec_release(sr_rec, SVC_RQST_FLAG_NONE); out: return (code); } int svc_rqst_thrd_signal(uint32_t chan_id, uint32_t flags) { struct svc_rqst_rec *sr_rec; struct rbtree_x_part *t; int code = 0; sr_rec = svc_rqst_lookup_chan(chan_id, &t, SVC_RQST_FLAG_PART_UNLOCK); if (!sr_rec) { code = ENOENT; goto out; } sr_rec->signals |= (flags & SVC_RQST_SIGNAL_MASK); ev_sig(sr_rec->sv[0], flags); /* send wakeup */ mutex_unlock(&sr_rec->mtx); out: if (sr_rec) sr_rec_release(sr_rec, SVC_RQST_FLAG_NONE); return (code); } /* * Activate a transport handle. */ void xprt_register(SVCXPRT *xprt) { int code __attribute__ ((unused)) = 0; /* Create a legacy/global event channel */ if (!(__svc_params->ev_u.evchan.id)) { code = svc_rqst_new_evchan(&(__svc_params->ev_u.evchan.id), NULL /* u_data */ , SVC_RQST_FLAG_CHAN_AFFINITY); } /* and bind xprt to it */ code = svc_rqst_evchan_reg(__svc_params->ev_u.evchan.id, xprt, SVC_RQST_FLAG_CHAN_AFFINITY); } /* xprt_register */ void svc_rqst_shutdown(void) { if (__svc_params->ev_u.evchan.id) { svc_rqst_delete_evchan(__svc_params->ev_u.evchan.id); __svc_params->ev_u.evchan.id = 0; } } ntirpc-1.3.1/src/svc_run.c000066400000000000000000000063021261345040100154220ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * This is the rpc server side idle loop * Wait for input, call server program. */ #include #if !defined(_WIN32) #include #include #endif #include #include #include #include /* before portable.h */ #include #include #include "rpc_com.h" #include "clnt_internal.h" #include "svc_internal.h" #include "svc_xprt.h" #include "rpc_dplx_internal.h" #include extern struct svc_params __svc_params[1]; bool __svc_clean_idle2(int timeout, bool cleanblock); #if defined(TIRPC_EPOLL) void svc_getreqset_epoll(struct epoll_event *events, int nfds); /* static */ void svc_run_epoll(void) { (void)svc_rqst_thrd_run(__svc_params->ev_u.evchan.id, SVC_RQST_FLAG_NONE); } #endif /* TIRPC_EPOLL */ void svc_run(void) { switch (__svc_params->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: svc_run_epoll(); break; #endif default: /* XXX formerly select/fd_set case, now placeholder for new * event systems, reworked select, etc. */ __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_run: unsupported event type"); break; } /* switch */ } /* * This function causes svc_run() to exit by telling it that it has no * more work to do. */ void svc_exit() { switch (__svc_params->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: /* signal shutdown backchannel */ (void) svc_rqst_thrd_signal(__svc_params->ev_u.evchan.id, SVC_RQST_SIGNAL_SHUTDOWN); break; #endif default: /* XXX formerly select/fd_set case, now placeholder for new * event systems, reworked select, etc. */ break; } /* switch */ } ntirpc-1.3.1/src/svc_simple.c000066400000000000000000000215371261345040100161160ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * Copyright (c) 1986-1991 by Sun Microsystems Inc. */ #include #include /* * 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 #include #include #include #include #include #include #include #include #include "rpc_com.h" static void universal(struct svc_req *, SVCXPRT *); static struct proglst { char *(*p_progname) (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(rpcprog_t prognum, rpcvers_t versnum, rpcproc_t procnum, char *(*progname) (char *), xdrproc_t inproc, xdrproc_t outproc, char *nettype) { struct netconfig *nconf; int done = false; void *handle; extern mutex_t proglst_lock; if (procnum == NULLPROC) { __warnx(TIRPC_DEBUG_FLAG_SVC, "%s can't reassign procedure number %u", rpc_reg_msg, NULLPROC); return (-1); } if (nettype == NULL) nettype = "netpath"; /* The default behavior */ handle = __rpc_setconf(nettype); if (!handle) { __warnx(TIRPC_DEBUG_FLAG_SVC, 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 = 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_ncreate(RPC_ANYFD, nconf, NULL, 0, 0); if (svcxprt == NULL) continue; if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) { __warnx(TIRPC_DEBUG_FLAG_SVC, 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(TIRPC_DEBUG_FLAG_SVC, rpc_reg_err, rpc_reg_msg, __reg_err3); SVC_DESTROY(svcxprt); continue; } xdrbuf = mem_alloc((unsigned)recvsz); if (xdrbuf) netid = rpc_strdup(nconf->nc_netid); if ((!xdrbuf) || (!netid)) { if (xdrbuf) mem_free(xdrbuf, (unsigned)recvsz); __warnx(TIRPC_DEBUG_FLAG_SVC, rpc_reg_err, rpc_reg_msg, __no_mem_str); 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(TIRPC_DEBUG_FLAG_SVC, "%s couldn't register prog %u vers %u for %s", rpc_reg_msg, (unsigned)prognum, (unsigned)versnum, netid); if (madenow) { SVC_DESTROY(svcxprt); mem_free(xdrbuf, 0); mem_free(netid, 0); } continue; } pl = mem_alloc(sizeof(struct proglst)); if (pl == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC, rpc_reg_err, rpc_reg_msg, __no_mem_str); if (madenow) { SVC_DESTROY(svcxprt); mem_free(xdrbuf, 0); mem_free(netid, 0); } 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(TIRPC_DEBUG_FLAG_SVC, "%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(struct svc_req *req, SVCXPRT *transp) { rpcprog_t prog; rpcvers_t vers; rpcproc_t proc; char *outdata; char *xdrbuf; struct proglst *pl; extern mutex_t proglst_lock; /* * enforce "procnum 0 is echo" convention */ if (req->rq_proc == NULLPROC) { if (svc_sendreply(transp, req, (xdrproc_t) xdr_void, NULL) == false) { __warnx(TIRPC_DEBUG_FLAG_SVC, "svc_sendreply failed"); } return; } prog = req->rq_prog; vers = req->rq_vers; proc = req->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, sizeof(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, req, pl->p_inproc, xdrbuf, NULL)) { svcerr_decode(transp, req); 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, req, pl->p_outproc, outdata)) { __warnx(TIRPC_DEBUG_FLAG_SVC, "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, req, pl->p_inproc, xdrbuf); mutex_unlock(&proglst_lock); return; } mutex_unlock(&proglst_lock); /* This should never happen */ __warnx(TIRPC_DEBUG_FLAG_SVC, "rpc: rpc_reg: never registered prog %u vers %u", (unsigned)prog, (unsigned)vers); return; } ntirpc-1.3.1/src/svc_vc.c000066400000000000000000001060001261345040100152220ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include /* * svc_vc.c, Server side for Connection Oriented RPC. * * Actually implements two flavors of transporter - * a tcp rendezvouser (a listner and connection establisher) * and a record/tcp stream. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include "clnt_internal.h" #include "svc_internal.h" #include "svc_xprt.h" #include "rpc_dplx_internal.h" #include "rpc_ctx.h" #include #include #include #include #include "svc_ioq.h" int generic_read_vc(XDR *, void *, void *, int); int generic_write_vc(XDR *, void *, void *, int); static void svc_vc_rendezvous_ops(SVCXPRT *); static void svc_vc_ops(SVCXPRT *); static void svc_vc_override_ops(SVCXPRT *, SVCXPRT *); bool __svc_clean_idle2(int, bool); static SVCXPRT *makefd_xprt(int, u_int, u_int, bool *); extern pthread_mutex_t svc_ctr_lock; /* * Usage: * xprt = svc_vc_ncreate(sock, send_buf_size, recv_buf_size); * * Creates, registers, and returns a (rpc) tcp based transport. * Once *xprt is initialized, it is registered as a transport * see (svc.h, xprt_register). This routine returns * a NULL if a problem occurred. * * 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. * * Added svc_vc_ncreate2 with flags argument, has the behavior of the * original function if flags are SVC_VC_FLAG_NONE (0). * */ SVCXPRT * svc_vc_ncreate2(int fd, u_int sendsize, u_int recvsize, u_int flags) { SVCXPRT *xprt = NULL; struct cf_rendezvous *rdvs = NULL; struct __rpc_sockinfo si; struct sockaddr_storage sslocal; struct sockaddr *salocal; struct sockaddr_in *salocal_in; struct sockaddr_in6 *salocal_in6; struct rpc_dplx_rec *rec = NULL; struct x_vc_data *xd = NULL; const char *netid; uint32_t oflags; socklen_t slen; if (!__rpc_fd2sockinfo(fd, &si)) return NULL; if (!__rpc_sockinfo2netid(&si, &netid)) return NULL; rdvs = mem_alloc(sizeof(struct cf_rendezvous)); if (rdvs == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc_ncreate: out of memory"); goto err; } rdvs->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); rdvs->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); rdvs->maxrec = __svc_maxrec; /* atomically find or create shared fd state */ rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_LKP_IFLAG_LOCKREC, &oflags); if (!rec) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc: makefd_xprt: rpc_dplx_lookup_rec failed"); goto err; } /* attach shared state */ if ((oflags & RPC_DPLX_LKP_OFLAG_ALLOC) || (!rec->hdl.xd)) { xd = rec->hdl.xd = alloc_x_vc_data(); if (xd == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc: makefd_xprt: out of memory"); goto err; } xd->rec = rec; /* XXX tracks outstanding calls */ opr_rbtree_init(&xd->cx.calls.t, call_xid_cmpf); xd->cx.calls.xid = 0; /* next call xid is 1 */ xd->refcnt = 1; xd->shared.sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize); xd->shared.recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize); /* duplex streams are not used by the rendevous transport */ memset(&xd->shared.xdrs_in, 0, sizeof xd->shared.xdrs_in); memset(&xd->shared.xdrs_out, 0, sizeof xd->shared.xdrs_out); } else { xd = (struct x_vc_data *)rec->hdl.xd; /* dont return destroyed xprts */ if (!(xd->flags & X_VC_DATA_FLAG_SVC_DESTROYED)) { if (rec->hdl.xprt) { xprt = rec->hdl.xprt; /* inc xprt refcnt */ SVC_REF(xprt, SVC_REF_FLAG_NONE); mem_free(rdvs, sizeof(struct cf_rendezvous)); goto done; } else ++(xd->refcnt); } /* return extra ref */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED | RPC_DPLX_FLAG_UNLOCK); } xprt = mem_zalloc(sizeof(SVCXPRT)); if (xprt == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc_ncreate: out of memory"); goto err; } xprt->xp_flags = SVC_XPRT_FLAG_NONE; xprt->xp_refs = 1; svc_vc_rendezvous_ops(xprt); xprt->xp_p1 = rdvs; xprt->xp_p2 = xd; xprt->xp_p5 = rec; xprt->xp_fd = fd; mutex_init(&xprt->xp_lock, NULL); /* caller should know what it's doing */ if (flags & SVC_VC_CREATE_LISTEN) listen(fd, SOMAXCONN); slen = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc_create: could not retrieve local addr"); goto err; } /* XXX following breaks strict aliasing? */ salocal = (struct sockaddr *)&sslocal; switch (salocal->sa_family) { case AF_INET: salocal_in = (struct sockaddr_in *)salocal; xprt->xp_port = ntohs(salocal_in->sin_port); break; case AF_INET6: salocal_in6 = (struct sockaddr_in6 *)salocal; xprt->xp_port = ntohs(salocal_in6->sin6_port); break; } __rpc_set_address(&xprt->xp_local, &sslocal, slen); xprt->xp_netid = rpc_strdup(netid); /* make reachable from rec */ rec->hdl.xprt = xprt; /* release rec */ REC_UNLOCK(rec); /* make reachable from xprt list */ svc_rqst_init_xprt(xprt); /* conditional xprt_register */ if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)) && (!(flags & SVC_VC_CREATE_XPRT_NOREG))) xprt_register(xprt); #if defined(HAVE_BLKIN) __rpc_set_blkin_endpoint(xprt, "svc_vc"); #endif done: return (xprt); err: if (rdvs) mem_free(rdvs, sizeof(struct cf_rendezvous)); if (xprt) { #if defined(HAVE_BLKIN) if (xprt->blkin.svc_name) mem_free(xprt->blkin.svc_name, 2*INET6_ADDRSTRLEN); #endif mem_free(xprt, sizeof(SVCXPRT)); } if (rec) { rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED | RPC_DPLX_FLAG_UNLOCK); } return (NULL); } SVCXPRT * svc_vc_ncreate(int fd, u_int sendsize, u_int recvsize) { return (svc_vc_ncreate2(fd, sendsize, recvsize, SVC_VC_CREATE_NONE)); } /* * Like svtcp_ncreate(), except the routine takes any *open* UNIX file * descriptor as its first input. */ SVCXPRT * svc_fd_ncreate(int fd, u_int sendsize, u_int recvsize) { struct sockaddr_storage ss; socklen_t slen; SVCXPRT *xprt; bool xprt_allocd; assert(fd != -1); xprt = makefd_xprt(fd, sendsize, recvsize, &xprt_allocd); if ((!xprt) || (!xprt_allocd)) /* ref'd existing xprt handle */ goto done; /* conditional xprt_register */ if (!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)) xprt_register(xprt); slen = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_fd_create: could not retrieve local addr"); goto freedata; } __rpc_set_address(&xprt->xp_local, &ss, slen); slen = sizeof(struct sockaddr_storage); if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_fd_create: could not retrieve remote addr"); goto freedata; } __rpc_set_address(&xprt->xp_remote, &ss, slen); done: return (xprt); freedata: return (NULL); } /* * Like sv_fd_ncreate(), except export flags for additional control. */ SVCXPRT * svc_fd_ncreate2(int fd, u_int sendsize, u_int recvsize, u_int flags) { struct sockaddr_storage ss; socklen_t slen; SVCXPRT *xprt; bool xprt_allocd; assert(fd != -1); xprt = makefd_xprt(fd, sendsize, recvsize, &xprt_allocd); if ((!xprt) || (!xprt_allocd)) /* ref'd existing xprt handle */ return (xprt); slen = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_fd_ncreate: could not retrieve local addr"); return (NULL); } __rpc_set_address(&xprt->xp_local, &ss, slen); slen = sizeof(struct sockaddr_storage); if (getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_fd_ncreate: could not retrieve remote addr"); return (NULL); } __rpc_set_address(&xprt->xp_remote, &ss, slen); /* conditional xprt_register */ if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)) && (!(flags & SVC_VC_CREATE_XPRT_NOREG))) xprt_register(xprt); return (xprt); } static SVCXPRT * makefd_xprt(int fd, u_int sendsz, u_int recvsz, bool *allocated) { SVCXPRT *xprt = NULL; struct x_vc_data *xd = NULL; struct rpc_dplx_rec *rec; struct __rpc_sockinfo si; const char *netid; uint32_t oflags; bool newxd = false; *allocated = false; assert(fd != -1); if (!svc_vc_new_conn_ok()) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: makefd_xprt: max_connections exceeded\n", __func__); goto done; } /* atomically find or create shared fd state */ rec = rpc_dplx_lookup_rec(fd, RPC_DPLX_LKP_IFLAG_LOCKREC, &oflags); if (!rec) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc: makefd_xprt: rpc_dplx_lookup_rec failed"); goto done; } /* attach shared state */ if ((oflags & RPC_DPLX_LKP_OFLAG_ALLOC) || (!rec->hdl.xd)) { newxd = true; xd = rec->hdl.xd = alloc_x_vc_data(); if (xd == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc: makefd_xprt: out of memory"); /* return extra ref */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED | RPC_DPLX_FLAG_UNLOCK); mem_free(xprt, sizeof(SVCXPRT)); goto done; } xd->rec = rec; /* XXX tracks outstanding calls */ opr_rbtree_init(&xd->cx.calls.t, call_xid_cmpf); xd->cx.calls.xid = 0; /* next call xid is 1 */ xd->refcnt = 1; if (__rpc_fd2sockinfo(fd, &si)) { xd->shared.sendsz = __rpc_get_t_size( si.si_af, si.si_proto, (int)sendsz); xd->shared.recvsz = __rpc_get_t_size( si.si_af, si.si_proto, (int)recvsz); } /* duplex streams */ xdr_inrec_create(&(xd->shared.xdrs_in), recvsz, xd, generic_read_vc); xd->shared.xdrs_in.x_op = XDR_DECODE; xdrrec_create(&(xd->shared.xdrs_out), sendsz, recvsz, xd, generic_read_vc, generic_write_vc); xd->shared.xdrs_out.x_op = XDR_ENCODE; } else { xd = (struct x_vc_data *)rec->hdl.xd; /* dont return destroyed xprts */ if (!(xd->flags & X_VC_DATA_FLAG_SVC_DESTROYED)) { if (rec->hdl.xprt) { xprt = rec->hdl.xprt; /* inc xprt refcnt */ SVC_REF(xprt, SVC_REF_FLAG_NONE); } else ++(xd->refcnt); } /* return extra ref */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED | RPC_DPLX_FLAG_UNLOCK); *allocated = FALSE; /* return ref'd xprt */ goto done_xprt; } /* XXX bi-directional? initially I had assumed that explicit * routines to create a clnt or svc handle from an already-connected * handle of the other type, but perhaps it is more natural to * just discover it */ /* new xprt (the common case) */ xprt = mem_zalloc(sizeof(SVCXPRT)); if (xprt == NULL) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "svc_vc: makefd_xprt: out of memory"); /* return extra ref */ rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED | RPC_DPLX_FLAG_UNLOCK); goto done; } *allocated = TRUE; xprt->xp_p5 = rec; mutex_init(&xprt->xp_lock, NULL); /* XXX take xp_lock? */ mutex_init(&xprt->xp_auth_lock, NULL); xprt->xp_refs = 1; xprt->xp_fd = fd; /* the SVCXPRT created in svc_vc_create accepts new connections * in its xp_recv op, the rendezvous_request method, but xprt is * a call channel */ svc_vc_ops(xprt); xd->sx.strm_stat = XPRT_IDLE; xprt->xp_p1 = xd; if (newxd /* ensures valid si */ && __rpc_sockinfo2netid(&si, &netid)) xprt->xp_netid = rpc_strdup(netid); /* make reachable from rec */ rec->hdl.xprt = xprt; /* release */ REC_UNLOCK(rec); /* Make reachable from xprt list. Registration deferred. */ svc_rqst_init_xprt(xprt); done_xprt: done: return (xprt); } /*ARGSUSED*/ static bool rendezvous_request(SVCXPRT *xprt, struct svc_req *req) { int fd; socklen_t len; struct cf_rendezvous *rdvs; struct x_vc_data *xd; struct sockaddr_storage addr; struct __rpc_sockinfo si; socklen_t slen; SVCXPRT *newxprt; bool xprt_allocd; static int n = 1; rdvs = (struct cf_rendezvous *)xprt->xp_p1; again: len = sizeof(addr); fd = accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr, &len); if (fd < 0) { if (errno == EINTR) goto again; /* * Clean out the most idle file descriptor when we're * running out. */ if (errno == EMFILE || errno == ENFILE) { switch (__svc_params->ev_type) { #if defined(TIRPC_EPOLL) case SVC_EVENT_EPOLL: break; #endif default: abort(); /* XXX */ break; } /* switch */ goto again; } return (FALSE); } (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &n, sizeof(n)); /* * make a new transport (re-uses xprt) */ newxprt = makefd_xprt(fd, rdvs->sendsize, rdvs->recvsize, &xprt_allocd); if ((!newxprt) || (!xprt_allocd)) /* ref'd existing xprt handle */ return (FALSE); /* * propagate special ops */ svc_vc_override_ops(xprt, newxprt); /* move xprt_register() out of makefd_xprt */ (void)svc_rqst_xprt_register(xprt, newxprt); __rpc_set_address(&newxprt->xp_remote, &addr, len); XPRT_TRACE(newxprt, __func__, __func__, __LINE__); /* XXX fvdl - is this useful? (Yes. Matt) */ if (__rpc_fd2sockinfo(fd, &si) && si.si_proto == IPPROTO_TCP) { len = 1; (void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &len, sizeof(len)); } slen = sizeof(struct sockaddr_storage); if (getsockname(fd, (struct sockaddr *)(void *)&addr, &slen) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: could not retrieve local addr", __func__); } else { __rpc_set_address(&newxprt->xp_local, &addr, slen); } #if defined(HAVE_BLKIN) __rpc_set_blkin_endpoint(newxprt, "svc_vc"); #endif xd = (struct x_vc_data *)newxprt->xp_p1; xd->shared.recvsz = rdvs->recvsize; xd->shared.sendsz = rdvs->sendsize; xd->sx.maxrec = rdvs->maxrec; #if 0 /* XXX vrec wont support atm (and it seems to need work) */ if (cd->maxrec != 0) { flags = fcntl(fd, F_GETFL, 0); if (flags == -1) return (FALSE); if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) == -1) return (FALSE); if (xd->shared.recvsz > xd->sx.maxrec) xd->shared.recvsz = xd->sx.maxrec; xd->shared.nonblock = TRUE; __xdrrec_setnonblock(&xd->shared.xdrs_in, xd->sx.maxrec); __xdrrec_setnonblock(&xd->shared.xdrs_out, xd->sx.maxrec); } else cd->nonblock = FALSE; #else xd->shared.nonblock = FALSE; #endif (void)clock_gettime(CLOCK_MONOTONIC_FAST, &xd->sx.last_recv); /* if parent has xp_recv_user_data, use it */ if (xprt->xp_ops->xp_recv_user_data) xprt->xp_ops->xp_recv_user_data(xprt, newxprt, SVC_RQST_FLAG_NONE, NULL); return (FALSE); /* there is never an rpc msg to be processed */ } /*ARGSUSED*/ static enum xprt_stat rendezvous_stat(SVCXPRT *xprt) { return (XPRT_IDLE); } /* XXX pending further unification * * note: currently, rdvs xprt handles have a rec structure, * but no xd structure, etc. * (they do too have an xd -- to track "destroyed" flag -- fixme?) * */ static void svc_rdvs_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line) { struct cf_rendezvous *rdvs = (struct cf_rendezvous *)xprt->xp_p1; struct x_vc_data *xd = (struct x_vc_data *)xprt->xp_p2; struct rpc_dplx_rec *rec = (struct rpc_dplx_rec *)xprt->xp_p5; int refcnt; /* clears xprt from the xprt table (eg, idle scans) */ xprt_unregister(xprt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s() %p xp_refs %" PRIu32 " should actually destroy things @ %s:%d", __func__, xprt, xprt->xp_refs, tag, line); if (xprt->xp_fd != RPC_ANYFD) (void)close(xprt->xp_fd); if (xprt->xp_ops->xp_free_user_data) { /* call free hook */ xprt->xp_ops->xp_free_user_data(xprt); } REC_LOCK(rec); mutex_destroy(&xprt->xp_lock); if (xprt->xp_tp) mem_free(xprt->xp_tp, 0); if (xprt->xp_netid) mem_free(xprt->xp_netid, 0); mem_free(rdvs, sizeof(struct cf_rendezvous)); mem_free(xprt, sizeof(SVCXPRT)); refcnt = rpc_dplx_unref(rec, RPC_DPLX_FLAG_LOCKED | RPC_DPLX_FLAG_UNLOCK); if (!refcnt) mem_free(xd, sizeof(struct x_vc_data)); } static void svc_vc_destroy(SVCXPRT *xprt, u_int flags, const char *tag, const int line) { struct x_vc_data *xd = (struct x_vc_data *)xprt->xp_p1; struct rpc_dplx_rec *rec = xd->rec; uint32_t xd_refcnt; /* connection tracking--decrement now, he's dead jim */ svc_vc_dec_nconns(); /* clears xprt from the xprt table (eg, idle scans) */ xprt_unregister(xprt); /* bidirectional */ REC_LOCK(rec); xd->flags |= X_VC_DATA_FLAG_SVC_DESTROYED; xd_refcnt = --(xd->refcnt); __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: postfinalize %p xp_refs %" PRIu32 " xd_refcnt %u", __func__, xprt, xprt->xp_refs, xd_refcnt); /* conditional destroy */ if (xd_refcnt == 0) { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: %p xp_refs %" PRIu32 " xd_refcnt %" PRIu32 " calling vc_shared_destroy @ %s:%d", __func__, xprt, xprt->xp_refs, xd_refcnt, tag, line); vc_shared_destroy(xd); /* RECLOCKED */ } else { __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s: %p xp_refs %" PRIu32 " xd_refcnt %" PRIu32 " omit vc_shared_destroy @ %s:%d", __func__, xprt, xprt->xp_refs, xd_refcnt, tag, line); REC_UNLOCK(rec); } } extern mutex_t ops_lock; /*ARGSUSED*/ static bool svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in) { switch (rq) { case SVCGET_XP_FLAGS: *(u_int *) in = xprt->xp_flags; break; case SVCSET_XP_FLAGS: xprt->xp_flags = *(u_int *) in; break; case SVCGET_XP_RECV: mutex_lock(&ops_lock); *(xp_recv_t *) in = xprt->xp_ops->xp_recv; mutex_unlock(&ops_lock); break; case SVCSET_XP_RECV: mutex_lock(&ops_lock); xprt->xp_ops->xp_recv = *(xp_recv_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_GETREQ: mutex_lock(&ops_lock); *(xp_getreq_t *) in = xprt->xp_ops->xp_getreq; mutex_unlock(&ops_lock); break; case SVCSET_XP_GETREQ: mutex_lock(&ops_lock); xprt->xp_ops->xp_getreq = *(xp_getreq_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_DISPATCH: mutex_lock(&ops_lock); *(xp_dispatch_t *) in = xprt->xp_ops->xp_dispatch; mutex_unlock(&ops_lock); break; case SVCSET_XP_DISPATCH: mutex_lock(&ops_lock); xprt->xp_ops->xp_dispatch = *(xp_dispatch_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_RECV_USER_DATA: mutex_lock(&ops_lock); *(xp_recv_user_data_t *) in = xprt->xp_ops->xp_recv_user_data; mutex_unlock(&ops_lock); break; case SVCSET_XP_RECV_USER_DATA: mutex_lock(&ops_lock); xprt->xp_ops->xp_recv_user_data = *(xp_recv_user_data_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); *(xp_free_user_data_t *) in = xprt->xp_ops->xp_free_user_data; mutex_unlock(&ops_lock); break; case SVCSET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); xprt->xp_ops->xp_free_user_data = *(xp_free_user_data_t) in; mutex_unlock(&ops_lock); break; default: return (FALSE); } return (TRUE); } static bool svc_vc_rendezvous_control(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; case SVCGET_XP_RECV: mutex_lock(&ops_lock); *(xp_recv_t *) in = xprt->xp_ops->xp_recv; mutex_unlock(&ops_lock); break; case SVCSET_XP_RECV: mutex_lock(&ops_lock); xprt->xp_ops->xp_recv = *(xp_recv_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_GETREQ: mutex_lock(&ops_lock); *(xp_getreq_t *) in = xprt->xp_ops->xp_getreq; mutex_unlock(&ops_lock); break; case SVCSET_XP_GETREQ: mutex_lock(&ops_lock); xprt->xp_ops->xp_getreq = *(xp_getreq_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_DISPATCH: mutex_lock(&ops_lock); *(xp_dispatch_t *) in = xprt->xp_ops->xp_dispatch; mutex_unlock(&ops_lock); break; case SVCSET_XP_DISPATCH: mutex_lock(&ops_lock); xprt->xp_ops->xp_dispatch = *(xp_dispatch_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_RECV_USER_DATA: mutex_lock(&ops_lock); *(xp_recv_user_data_t *) in = xprt->xp_ops->xp_recv_user_data; mutex_unlock(&ops_lock); break; case SVCSET_XP_RECV_USER_DATA: mutex_lock(&ops_lock); xprt->xp_ops->xp_recv_user_data = *(xp_recv_user_data_t) in; mutex_unlock(&ops_lock); break; case SVCGET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); *(xp_free_user_data_t *) in = xprt->xp_ops->xp_free_user_data; mutex_unlock(&ops_lock); break; case SVCSET_XP_FREE_USER_DATA: mutex_lock(&ops_lock); xprt->xp_ops->xp_free_user_data = *(xp_free_user_data_t) in; mutex_unlock(&ops_lock); break; default: return (FALSE); } return (TRUE); } static enum xprt_stat svc_vc_stat(SVCXPRT *xprt) { struct x_vc_data *xd = (struct x_vc_data *)xprt->xp_p1; if (xprt->xp_flags & SVC_XPRT_FLAG_DESTROYED) return (XPRT_DESTROYED); if (!xd) return (XPRT_IDLE); /* we hold the recv lock */ if (xd->sx.strm_stat == XPRT_DIED) return (XPRT_DIED); if (!xdr_inrec_eof(&(xd->shared.xdrs_in))) return (XPRT_MOREREQS); return (XPRT_IDLE); } static bool svc_vc_recv(SVCXPRT *xprt, struct svc_req *req) { struct x_vc_data *xd = (struct x_vc_data *)xprt->xp_p1; XDR *xdrs = &(xd->shared.xdrs_in); /* recv queue */ /* XXX assert(! cd->nonblock) */ if (xd->shared.nonblock) { if (!__xdrrec_getrec(xdrs, &xd->sx.strm_stat, TRUE)) return FALSE; } xdrs->x_op = XDR_DECODE; xdrs->x_lib[0] = (void *)RPC_DPLX_SVC; xdrs->x_lib[1] = (void *)xprt; /* transiently thread xprt */ /* Consumes any remaining -fragment- bytes, and clears last_frag */ (void)xdr_inrec_skiprecord(xdrs); req->rq_msg = alloc_rpc_msg(); req->rq_clntcred = req->rq_msg->rq_cred_body; /* Advances to next record, will read up to 1024 bytes * into the stream. */ (void)xdr_inrec_readahead(xdrs, 1024); if (xdr_dplx_decode(xdrs, req->rq_msg)) { switch (req->rq_msg->rm_direction) { case CALL: /* an ordinary call header */ req->rq_xprt = xprt; req->rq_prog = req->rq_msg->rm_call.cb_prog; req->rq_vers = req->rq_msg->rm_call.cb_vers; req->rq_proc = req->rq_msg->rm_call.cb_proc; req->rq_xid = req->rq_msg->rm_xid; return (TRUE); break; case REPLY: /* reply header (xprt OK) */ rpc_ctx_xfer_replymsg(xd, req->rq_msg); req->rq_msg = NULL; break; default: /* not good (but xprt OK) */ break; } /* XXX skiprecord? */ return (FALSE); } __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: xdr_dplx_msg_decode failed (will set dead)", __func__); return (FALSE); } static bool svc_vc_freeargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr) { return xdr_free(xdr_args, args_ptr); } static bool svc_vc_getargs(SVCXPRT *xprt, struct svc_req *req, xdrproc_t xdr_args, void *args_ptr, void *u_data) { struct x_vc_data *xd = (struct x_vc_data *)xprt->xp_p1; XDR *xdrs = &xd->shared.xdrs_in; /* recv queue */ bool rslt; /* threads u_data for advanced decoders */ xdrs->x_public = u_data; rslt = SVCAUTH_UNWRAP(req->rq_auth, req, xdrs, xdr_args, args_ptr); /* XXX Upstream TI-RPC lacks this call, but -does- call svc_dg_freeargs * in svc_dg_getargs if SVCAUTH_UNWRAP fails. */ if (rslt) req->rq_cksum = xdr_inrec_cksum(xdrs); else svc_vc_freeargs(xprt, req, xdr_args, args_ptr); return (rslt); } static bool svc_vc_reply(SVCXPRT *xprt, struct svc_req *req, struct rpc_msg *msg) { struct x_vc_data *xd = (struct x_vc_data *)xprt->xp_p1; XDR *xdrs_2; xdrproc_t xdr_results; caddr_t xdr_location; bool rstat = false; bool has_args; bool gss; if (msg->rm_reply.rp_stat == MSG_ACCEPTED && msg->rm_reply.rp_acpt.ar_stat == SUCCESS) { has_args = TRUE; xdr_results = msg->acpted_rply.ar_results.proc; xdr_location = msg->acpted_rply.ar_results.where; msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void; msg->acpted_rply.ar_results.where = NULL; } else { has_args = FALSE; xdr_results = NULL; xdr_location = NULL; } /* XXX Until gss_get_mic and gss_wrap can be replaced with * iov equivalents, replies with RPCSEC_GSS security must be * encoded in a contiguous buffer. * * Nb, we should probably use getpagesize() on Unix. Need * an equivalent for Windows. */ gss = (req->rq_cred.oa_flavor == RPCSEC_GSS); xdrs_2 = xdr_ioq_create(8192 /* default segment size */ , __svc_params->svc_ioq_maxbuf + 8192, gss ? UIO_FLAG_REALLOC | UIO_FLAG_FREE : UIO_FLAG_FREE); if (xdr_replymsg(xdrs_2, msg) && (!has_args || (req->rq_auth && SVCAUTH_WRAP(req->rq_auth, req, xdrs_2, xdr_results, xdr_location)))) { rstat = TRUE; } svc_ioq_append(xprt, xd, xdrs_2); return (rstat); } static void svc_vc_lock(SVCXPRT *xprt, uint32_t flags, const char *func, int line) { if (flags & XP_LOCK_RECV) rpc_dplx_rlxi(xprt, func, line); if (flags & XP_LOCK_SEND) rpc_dplx_slxi(xprt, func, line); } static void svc_vc_unlock(SVCXPRT *xprt, uint32_t flags, const char *func, int line) { if (flags & XP_LOCK_RECV) rpc_dplx_rux(xprt); if (flags & XP_LOCK_SEND) rpc_dplx_sux(xprt); } static void svc_vc_ops(SVCXPRT *xprt) { static struct xp_ops ops; /* VARIABLES PROTECTED BY ops_lock: ops, xp_type */ mutex_lock(&ops_lock); xprt->xp_type = XPRT_TCP; 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; ops.xp_control = svc_vc_control; ops.xp_lock = svc_vc_lock; ops.xp_unlock = svc_vc_unlock; ops.xp_getreq = svc_getreq_default; ops.xp_dispatch = svc_dispatch_default; ops.xp_recv_user_data = NULL; /* no default */ ops.xp_free_user_data = NULL; /* no default */ } xprt->xp_ops = &ops; mutex_unlock(&ops_lock); } static void svc_vc_override_ops(SVCXPRT *xprt, SVCXPRT *newxprt) { if (xprt->xp_ops->xp_getreq) newxprt->xp_ops->xp_getreq = xprt->xp_ops->xp_getreq; if (xprt->xp_ops->xp_dispatch) newxprt->xp_ops->xp_dispatch = xprt->xp_ops->xp_dispatch; if (xprt->xp_ops->xp_recv_user_data) newxprt->xp_ops->xp_recv_user_data = xprt->xp_ops->xp_recv_user_data; if (xprt->xp_ops->xp_free_user_data) newxprt->xp_ops->xp_free_user_data = xprt->xp_ops->xp_free_user_data; } static void svc_vc_rendezvous_ops(SVCXPRT *xprt) { static struct xp_ops ops; extern mutex_t ops_lock; mutex_lock(&ops_lock); xprt->xp_type = XPRT_TCP_RENDEZVOUS; if (ops.xp_recv == NULL) { ops.xp_recv = rendezvous_request; ops.xp_stat = rendezvous_stat; /* XXX wow */ ops.xp_getargs = (bool(*) (SVCXPRT *, struct svc_req *, xdrproc_t, void *, void *))abort; ops.xp_reply = (bool(*) (SVCXPRT *, struct svc_req *req, struct rpc_msg *))abort; ops.xp_freeargs = (bool(*) (SVCXPRT *, struct svc_req *, xdrproc_t, void *))abort; ops.xp_destroy = svc_rdvs_destroy; ops.xp_control = svc_vc_rendezvous_control; ops.xp_lock = svc_vc_lock; ops.xp_unlock = svc_vc_unlock; ops.xp_getreq = svc_getreq_default; ops.xp_dispatch = svc_dispatch_default; ops.xp_recv_user_data = NULL; /* no default */ ops.xp_free_user_data = NULL; /* no default */ } xprt->xp_ops = &ops; mutex_unlock(&ops_lock); } /* * Get the effective UID of the sending process. Used by rpcbind, keyserv * and rpc.yppasswdd on AF_LOCAL. */ int __rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) { int sock, ret; gid_t egid; uid_t euid; struct sockaddr *sa; sock = transp->xp_fd; sa = (struct sockaddr *)&transp->xp_remote.ss; if (sa->sa_family == AF_LOCAL) { ret = getpeereid(sock, &euid, &egid); if (ret == 0) *uid = euid; return (ret); } else return (-1); } /* * 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. * * Though this is not a publicly documented interface, some versions of * rpcbind are known to call this function. Do not alter or remove this * API without changing the library's sonum. */ bool __svc_clean_idle(fd_set *fds, int timeout, bool cleanblock) { return (__svc_clean_idle2(timeout, cleanblock)); } /* __svc_clean_idle */ /* * Like __svc_clean_idle but event-type independent. For now no cleanfds. */ struct svc_clean_idle_arg { SVCXPRT *least_active; struct timespec ts, tmax; int cleanblock, ncleaned, timeout; }; static uint32_t svc_clean_idle2_func(SVCXPRT *xprt, void *arg) { struct timespec tdiff; struct svc_clean_idle_arg *acc = (struct svc_clean_idle_arg *)arg; uint32_t rflag = SVC_XPRT_FOREACH_NONE; if (!acc->cleanblock) goto out; mutex_lock(&xprt->xp_lock); /* invalid xprt (error) */ if (xprt->xp_ops == NULL) goto unlock; if (xprt->xp_flags & SVC_XPRT_FLAG_DESTROYED) { /* XXX should not happen--but do no harm */ __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: destroyed xprt %p seen in clean idle\n", __func__, xprt); goto unlock; } if (xprt->xp_ops->xp_recv != svc_vc_recv) goto unlock; { /* XXX nb., safe because xprt type is verfied */ struct x_vc_data *xd = xprt->xp_p1; if (!xd->shared.nonblock) goto unlock; if (acc->timeout == 0) { tdiff = acc->ts; timespecsub(&tdiff, &xd->sx.last_recv); if (timespeccmp(&tdiff, &acc->tmax, >)) { acc->tmax = tdiff; acc->least_active = xprt; } goto unlock; } if (acc->ts.tv_sec - xd->sx.last_recv.tv_sec > acc->timeout) { rflag = SVC_XPRT_FOREACH_CLEAR; mutex_unlock(&xprt->xp_lock); SVC_DESTROY(xprt); acc->ncleaned++; goto out; } } unlock: mutex_unlock(&xprt->xp_lock); out: return (rflag); } /* XXX move to svc_run */ void authgss_ctx_gc_idle(void); bool __svc_clean_idle2(int timeout, bool cleanblock) { struct svc_clean_idle_arg acc; static mutex_t active_mtx = MUTEX_INITIALIZER; static uint32_t active; bool_t rslt = FALSE; if (mutex_trylock(&active_mtx) != 0) goto out; if (active > 0) goto unlock; ++active; /* trim gss context cache */ authgss_ctx_gc_idle(); /* trim xprts (not sorted, not aggressive [but self limiting]) */ memset(&acc, 0, sizeof(struct svc_clean_idle_arg)); (void)clock_gettime(CLOCK_MONOTONIC_FAST, &acc.ts); acc.cleanblock = cleanblock; acc.timeout = timeout; svc_xprt_foreach(svc_clean_idle2_func, (void *)&acc); if (timeout == 0 && acc.least_active != NULL) { SVC_DESTROY(acc.least_active); acc.ncleaned++; } rslt = (acc.ncleaned > 0) ? TRUE : FALSE; --active; unlock: mutex_unlock(&active_mtx); out: return (rslt); } /* __svc_clean_idle2 */ /* * Create an RPC client handle from an active service transport * handle, i.e., to issue calls on the channel. * * If flags & SVC_VC_CLNT_CREATE_DEDICATED, the supplied xprt will be * unregistered and disposed inline. */ CLIENT * clnt_vc_ncreate_svc(SVCXPRT *xprt, const rpcprog_t prog, const rpcvers_t vers, const uint32_t flags) { struct x_vc_data *xd; CLIENT *clnt; mutex_lock(&xprt->xp_lock); xd = (struct x_vc_data *)xprt->xp_p1; /* XXX return allocated client structure, or allocate one if none * is currently allocated */ clnt = clnt_vc_ncreate2(xprt->xp_fd, &xprt->xp_remote.nb, prog, vers, xd->shared.sendsz, xd->shared.recvsz, CLNT_CREATE_FLAG_SVCXPRT); mutex_unlock(&xprt->xp_lock); /* for a dedicated channel, unregister and free xprt */ if ((flags & SVC_VC_CREATE_ONEWAY) && (flags & SVC_VC_CREATE_DISPOSE)) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: disposing--calls svc_vc_destroy\n", __func__); svc_vc_destroy(xprt, 0, __func__, __LINE__); } return (clnt); } /* * Create an RPC SVCXPRT handle from an active client transport * handle, i.e., to service RPC requests. * * If flags & SVC_VC_CREATE_CL_FLAG_DEDICATED, then clnt is also * deallocated without closing cl->cl_p1->ct_fd. */ SVCXPRT * svc_vc_ncreate_clnt(CLIENT *clnt, const u_int sendsz, const u_int recvsz, const uint32_t flags) { int fd; socklen_t len; struct x_vc_data *xd = (struct x_vc_data *)clnt->cl_p1; struct ct_data *ct = &xd->cx.data; struct sockaddr_storage addr; struct __rpc_sockinfo si; SVCXPRT *xprt = NULL; bool xprt_allocd; fd = ct->ct_fd; rpc_dplx_rlc(clnt); rpc_dplx_slc(clnt); len = sizeof(struct sockaddr_storage); if (getpeername(fd, (struct sockaddr *)(void *)&addr, &len) < 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: could not retrieve remote addr", __func__); goto unlock; } /* * make a new transport */ xprt = makefd_xprt(fd, sendsz, recvsz, &xprt_allocd); if ((!xprt) || (!xprt_allocd)) /* ref'd existing xprt handle */ goto unlock; __rpc_set_address(&xprt->xp_remote, &addr, len); if (__rpc_fd2sockinfo(fd, &si) && si.si_proto == IPPROTO_TCP) { len = 1; (void) setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &len, sizeof(len)); } xd->sx.maxrec = __svc_maxrec; /* XXX check */ #if 0 /* XXX wont currently support */ if (xd->sx.maxrec != 0) { fflags = fcntl(fd, F_GETFL, 0); if (fflags == -1) return (FALSE); if (fcntl(fd, F_SETFL, fflags | O_NONBLOCK) == -1) return (FALSE); if (xd->shared.recvsz > xd->sx.maxrec) xd->shared.recvsz = xd->sx.maxrec; cd->nonblock = TRUE; __xdrrec_setnonblock(&cd->xdrs, xd->sx.maxrec); } else xd->shared.nonblock = FALSE; #else xd->shared.nonblock = FALSE; #endif (void)clock_gettime(CLOCK_MONOTONIC_FAST, &xd->sx.last_recv); /* conditional xprt_register */ if ((!(__svc_params->flags & SVC_FLAG_NOREG_XPRTS)) && (!(flags & SVC_VC_CREATE_XPRT_NOREG))) xprt_register(xprt); /* If creating a dedicated channel collect the supplied client * without closing fd */ if ((flags & SVC_VC_CREATE_ONEWAY) && (flags & SVC_VC_CREATE_DISPOSE)) { ct->ct_closeit = FALSE; /* must not close */ rpc_dplx_ruc(clnt); rpc_dplx_suc(clnt); CLNT_DESTROY(clnt); /* clean up immediately */ goto out; } unlock: rpc_dplx_ruc(clnt); rpc_dplx_suc(clnt); out: return (xprt); } ntirpc-1.3.1/src/svc_xprt.c000066400000000000000000000207351261345040100156210ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include #include #ifdef PORTMAP #include #endif /* PORTMAP */ #include "rpc_com.h" #include #include #include #include "clnt_internal.h" #include "rpc_dplx_internal.h" #include "svc_xprt.h" #define SVC_XPRT_PARTITIONS 7 static bool initialized; struct svc_xprt_fd { mutex_t lock; struct rbtree_x xt; }; static struct svc_xprt_fd svc_xprt_fd = { MUTEX_INITIALIZER /* svc_xprt_lock */ , { 0, /* npart */ RBT_X_FLAG_NONE, /* flags */ 0, /* cachesz */ NULL /* tree */ } /* xt */ }; static inline int svc_xprt_fd_cmpf(const struct opr_rbtree_node *lhs, const struct opr_rbtree_node *rhs) { SVCXPRT *lk, *rk; lk = opr_containerof(lhs, struct rpc_svcxprt, xp_fd_node); rk = opr_containerof(rhs, struct rpc_svcxprt, xp_fd_node); if (lk->xp_fd < rk->xp_fd) return (-1); if (lk->xp_fd == rk->xp_fd) return (0); return (1); } void svc_xprt_init() { int code = 0; mutex_lock(&svc_xprt_fd.lock); if (initialized) goto unlock; /* one of advantages of this RBT is convenience of external * iteration, we'll go to that shortly */ code = rbtx_init(&svc_xprt_fd.xt, svc_xprt_fd_cmpf /* NULL (inline) */ , SVC_XPRT_PARTITIONS, RBT_X_FLAG_ALLOC); if (code) __warnx(TIRPC_DEBUG_FLAG_SVC_XPRT, "svc_xprt_init: rbtx_init failed"); initialized = true; unlock: mutex_unlock(&svc_xprt_fd.lock); } #define cond_init_svc_xprt() { \ do { \ if (!initialized) \ svc_xprt_init(); \ } while (0); \ } SVCXPRT * svc_xprt_get(int fd) { struct rpc_svcxprt sk; struct rbtree_x_part *t; struct opr_rbtree_node *nv; SVCXPRT *srec = NULL; cond_init_svc_xprt(); sk.xp_fd = fd; t = rbtx_partition_of_scalar(&svc_xprt_fd.xt, fd); rwlock_rdlock(&t->lock); nv = opr_rbtree_lookup(&t->t, &sk.xp_fd_node); rwlock_unlock(&t->lock); /* XXX safe, even if tree is reorganizing */ if (nv) srec = opr_containerof(nv, struct rpc_svcxprt, xp_fd_node); return (srec); } SVCXPRT * svc_xprt_set(SVCXPRT *xprt, uint32_t flags) { struct rbtree_x_part *t; struct opr_rbtree_node *nv; SVCXPRT *srec = NULL; cond_init_svc_xprt(); if (!(flags & SVC_XPRT_FLAG_LOCKED)) mutex_lock(&xprt->xp_lock); t = rbtx_partition_of_scalar(&svc_xprt_fd.xt, xprt->xp_fd); rwlock_wrlock(&t->lock); nv = opr_rbtree_insert(&t->t, &xprt->xp_fd_node); if (nv) { srec = opr_containerof(nv, struct rpc_svcxprt, xp_fd_node); __warnx(TIRPC_DEBUG_FLAG_SVC_XPRT, "%s: %p xp_refs %" PRIu32 " insert collision with %p xp_refs %" PRIu32, __func__, srec, srec->xp_refs, xprt, xprt->xp_refs); } rwlock_unlock(&t->lock); if (flags & SVC_XPRT_FLAG_UNLOCK) mutex_unlock(&xprt->xp_lock); return (srec); } /** * Clear an xprt * * @note Locking * - xprt is locked, unless SVC_XPRT_FLAG_LOCKED is passed * - xprt is unlocked if SVC_XPRT_FLAG_UNLOCK is passed, otherwise it is * returned locked */ void svc_xprt_clear(SVCXPRT *xprt, uint32_t flags) { struct rbtree_x_part *t; cond_init_svc_xprt(); if (!(flags & SVC_XPRT_FLAG_LOCKED)) mutex_lock(&xprt->xp_lock); if (opr_rbtree_node_valid(&xprt->xp_fd_node)) { t = rbtx_partition_of_scalar(&svc_xprt_fd.xt, xprt->xp_fd); rwlock_wrlock(&t->lock); opr_rbtree_remove(&t->t, &xprt->xp_fd_node); rwlock_unlock(&t->lock); } if (flags & SVC_XPRT_FLAG_UNLOCK) mutex_unlock(&xprt->xp_lock); } int svc_xprt_foreach(svc_xprt_each_func_t each_f, void *arg) { struct rpc_svcxprt sk; struct rbtree_x_part *t; struct opr_rbtree_node *n; SVCXPRT *xprt; uint64_t tgen; uint32_t rflag; int p_ix; int x_ix; int restarts; cond_init_svc_xprt(); /* concurrent, restartable iteration over t */ p_ix = 0; while (p_ix < SVC_XPRT_PARTITIONS) { t = &svc_xprt_fd.xt.tree[p_ix]; restarts = 0; /* TI-RPC __svc_clean_idle held global svc_fd_lock * exclusive locked for a full scan of the legacy svc_xprts * array. We avoid this via tree partitioning and by * operating mostly unlocked. */ restart: if (++restarts > 5) return (1); /* start with rlock */ rwlock_rdlock(&t->lock); /* t RLOCKED */ tgen = t->t.gen; x_ix = 0; n = opr_rbtree_first(&t->t); while (n != NULL) { ++x_ix; /* diagnostic, index into logical srec * sequence */ xprt = opr_containerof(n, struct rpc_svcxprt, xp_fd_node); sk.xp_fd = xprt->xp_fd; /* call each_func with t !LOCKED */ rwlock_unlock(&t->lock); /* restart if each_f disposed xprt */ rflag = each_f(xprt, arg); if (rflag == SVC_XPRT_FOREACH_CLEAR) goto restart; /* validate */ rwlock_rdlock(&t->lock); if (tgen != t->t.gen) { n = opr_rbtree_lookup(&t->t, &sk.xp_fd_node); if (!n) { /* invalidated, try harder */ rwlock_unlock(&t->lock); /* t !LOCKED */ goto restart; } } n = opr_rbtree_next(n); } /* curr partition */ rwlock_unlock(&t->lock); /* t !LOCKED */ p_ix++; } /* SVC_XPRT_PARTITIONS */ return (0); } void svc_xprt_dump_xprts(const char *tag) { struct rbtree_x_part *t = NULL; struct opr_rbtree_node *n; SVCXPRT *xprt; int p_ix; if (!initialized) goto out; p_ix = 0; while (p_ix < SVC_XPRT_PARTITIONS) { t = &svc_xprt_fd.xt.tree[p_ix]; rwlock_rdlock(&t->lock); /* t RLOCKED */ __warnx(TIRPC_DEBUG_FLAG_SVC_XPRT, "xprts at %s: tree %d size %d", tag, p_ix, t->t.size); n = opr_rbtree_first(&t->t); while (n != NULL) { xprt = opr_containerof(n, struct rpc_svcxprt, xp_fd_node); __warnx(TIRPC_DEBUG_FLAG_SVC_XPRT, "xprts at %s: %p xp_fd %d", tag, xprt, xprt->xp_fd); n = opr_rbtree_next(n); } /* curr partition */ rwlock_unlock(&t->lock); /* t !LOCKED */ p_ix++; } /* SVC_XPRT_PARTITIONS */ out: return; } void svc_xprt_shutdown() { struct rbtree_x_part *t; struct opr_rbtree_node *n; SVCXPRT *xprt; int p_ix; if (!initialized) return; p_ix = 0; while (p_ix < SVC_XPRT_PARTITIONS) { t = &svc_xprt_fd.xt.tree[p_ix]; rwlock_wrlock(&t->lock); /* t WLOCKED */ n = opr_rbtree_first(&t->t); while (n != NULL) { xprt = opr_containerof(n, struct rpc_svcxprt, xp_fd_node); n = opr_rbtree_next(n); /* prevent repeats, see svc_xprt_clear() */ mutex_lock(&xprt->xp_lock); opr_rbtree_remove(&t->t, &xprt->xp_fd_node); mutex_unlock(&xprt->xp_lock); SVC_DESTROY(xprt); } /* curr partition */ rwlock_unlock(&t->lock); /* t !LOCKED */ rwlock_destroy(&t->lock); p_ix++; } /* SVC_XPRT_PARTITIONS */ /* free tree */ mem_free(svc_xprt_fd.xt.tree, SVC_XPRT_PARTITIONS * sizeof(struct rbtree_x_part)); } void svc_xprt_trace(SVCXPRT *xprt, const char *func, const char *tag, const int line) { struct sockaddr_storage *ss = (struct sockaddr_storage *) &(xprt->xp_remote.ss); int port; switch (ss->ss_family) { case AF_INET6: port = ntohs(((struct sockaddr_in6 *)ss)->sin6_port); break; case AF_INET: port = ntohs(((struct sockaddr_in *)ss)->sin_port); break; default: port = -1; break; } __warnx(TIRPC_DEBUG_FLAG_REFCNT, "%s() %p xp_refs %" PRId32 " fd %d port %d @ %s:%d", func, xprt, xprt->xp_refs, xprt->xp_fd, port, tag, line); } ntirpc-1.3.1/src/svc_xprt.h000066400000000000000000000037031261345040100156220ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef TIRPC_SVC_XPRT_H #define TIRPC_SVC_XPRT_H #include #include #include /** ** Maintains a tree of all extant transports by fd **/ SVCXPRT *svc_xprt_get(int); SVCXPRT *svc_xprt_set(SVCXPRT *, uint32_t); void svc_xprt_clear(SVCXPRT *, uint32_t); /* iterator callback prototype */ #define SVC_XPRT_FOREACH_NONE 0x0000 #define SVC_XPRT_FOREACH_CLEAR 0x0001 /* each_f destroyed xprt */ typedef uint32_t(*svc_xprt_each_func_t) (SVCXPRT *, void *); int svc_xprt_foreach(svc_xprt_each_func_t, void *); void svc_xprt_dump_xprts(const char *); void svc_xprt_shutdown(); #endif /* TIRPC_SVC_XPRT_H */ ntirpc-1.3.1/src/thrdpool.c000066400000000000000000000145151261345040100156030ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #if !defined(_WIN32) #include #include #endif #include #include "rpc_com.h" #include #include #include #include #include #include #include #include #include #include int thrdpool_init(struct thrdpool *pool, const char *name, struct thrdpool_params *params) { memset(pool, 0, sizeof(struct thrdpool)); init_wait_entry(&pool->we); mutex_lock(&pool->we.mtx); pool->name = rpc_strdup(name); pool->params = *params; TAILQ_INIT(&pool->idle_q); TAILQ_INIT(&pool->work_q); (void)pthread_attr_init(&pool->attr); (void)pthread_attr_setscope(&pool->attr, PTHREAD_SCOPE_SYSTEM); (void)pthread_attr_setdetachstate(&pool->attr, PTHREAD_CREATE_DETACHED); mutex_unlock(&pool->we.mtx); return 0; } static bool thrd_wait(struct thrd *thrd) { bool code = false; struct thrdpool *pool = thrd->pool; struct timespec ts; struct work *work; int rc; mutex_lock(&pool->we.mtx); if (pool->flags & THRD_FLAG_SHUTDOWN) { mutex_unlock(&pool->we.mtx); goto out; } TAILQ_FOREACH(work, &pool->work_q, tailq) { TAILQ_REMOVE(&pool->work_q, work, tailq); thrd->ctx.work = work; code = true; mutex_unlock(&pool->we.mtx); goto out; } TAILQ_INSERT_TAIL(&pool->idle_q, thrd, tailq); ++(pool->n_idle); mutex_lock(&thrd->ctx.we.mtx); thrd->idle = true; mutex_unlock(&pool->we.mtx); while (1) { clock_gettime(CLOCK_REALTIME_FAST, &ts); timespec_addms(&ts, 1000 * 120); if (pool->flags & THRD_FLAG_SHUTDOWN) { rc = ETIMEDOUT; } else { rc = cond_timedwait(&thrd->ctx.we.cv, &thrd->ctx.we.mtx, &ts); } if (rc == ETIMEDOUT) { mutex_unlock(&thrd->ctx.we.mtx); mutex_lock(&pool->we.mtx); mutex_lock(&thrd->ctx.we.mtx); if (!thrd->idle) { /* raced */ code = true; mutex_unlock(&thrd->ctx.we.mtx); mutex_unlock(&pool->we.mtx); goto out; } code = false; TAILQ_REMOVE(&pool->idle_q, thrd, tailq); --(pool->n_idle); thrd->idle = false; mutex_unlock(&thrd->ctx.we.mtx); mutex_unlock(&pool->we.mtx); goto out; } /* signalled */ code = !thrd->idle; mutex_unlock(&thrd->ctx.we.mtx); break; } out: return (code); } static void *thrdpool_start_routine(void *arg) { struct thrd *thrd = arg; struct thrdpool *pool = thrd->pool; bool reschedule; do { struct work *work = thrd->ctx.work; work->func(work->arg); thrd->ctx.work = 0; mem_free(work, sizeof(struct work)); reschedule = thrd_wait(thrd); } while (reschedule); /* cleanup thread context */ destroy_wait_entry(&thrd->ctx.we); --(thrd->pool->n_threads); mutex_lock(&pool->we.mtx); cond_signal(&pool->we.cv); mutex_unlock(&pool->we.mtx); mem_free(thrd, 0); return (NULL); } static inline bool thrdpool_dispatch(struct thrdpool *pool, struct work *work) { struct thrd *thrd; TAILQ_FOREACH(thrd, &pool->idle_q, tailq) { mutex_lock(&thrd->ctx.we.mtx); TAILQ_REMOVE(&pool->idle_q, thrd, tailq); --(pool->n_idle); thrd->idle = false; thrd->ctx.work = work; cond_signal(&thrd->ctx.we.cv); mutex_unlock(&thrd->ctx.we.mtx); break; } return (true); } static inline bool thrdpool_spawn(struct thrdpool *pool, struct work *work) { int code; struct thrd *thrd = mem_alloc(sizeof(struct thrd)); memset(thrd, 0, sizeof(struct thrd)); init_wait_entry(&thrd->ctx.we); thrd->pool = pool; thrd->ctx.work = work; ++(pool->n_threads); code = pthread_create(&thrd->ctx.id, &pool->attr, thrdpool_start_routine, thrd); if (code != 0) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "pthread_create failed %d\n", __func__, errno); } return (true); } int thrdpool_submit_work(struct thrdpool *pool, thrd_func_t func, void *arg) { int code = 0; struct work *work; /* queue is draining */ mutex_lock(&pool->we.mtx); if (unlikely(pool->flags & THRD_FLAG_SHUTDOWN)) goto unlock; work = mem_zalloc(sizeof(struct work)); if (unlikely(!work)) { code = -1; goto unlock; } work->func = func; work->arg = arg; /* idle thread(s) available */ if (pool->n_idle > 0) { if (thrdpool_dispatch(pool, work)) goto unlock; } /* need a thread */ if ((pool->params.thrd_max == 0) || (pool->n_threads < pool->params.thrd_max)) { code = thrdpool_spawn(pool, work); goto unlock; } TAILQ_INSERT_TAIL(&pool->work_q, work, tailq); unlock: mutex_unlock(&pool->we.mtx); return (code); } int thrdpool_shutdown(struct thrdpool *pool) { struct timespec ts; int wait = 1; struct thrd *thrd; struct work *work; mutex_lock(&pool->we.mtx); pool->flags |= THRD_FLAG_SHUTDOWN; TAILQ_FOREACH(thrd, &pool->idle_q, tailq) { cond_signal(&thrd->ctx.we.cv); } TAILQ_FOREACH(work, &pool->work_q, tailq) { work->func(work->arg); } while (pool->n_threads > 0) { clock_gettime(CLOCK_REALTIME_FAST, &ts); timespec_addms(&ts, 1000 * wait); (void)cond_timedwait(&pool->we.cv, &pool->we.mtx, &ts); /* wait a bit longer */ wait = 5; } mem_free(pool->name, 0); mutex_unlock(&pool->we.mtx); destroy_wait_entry(&pool->we); return (0); } ntirpc-1.3.1/src/vc_generic.c000066400000000000000000000176351261345040100160620ustar00rootroot00000000000000/* * Copyright (c) 2012 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include #include "clnt_internal.h" #include "svc_internal.h" #include "rpc_dplx_internal.h" #include "rpc_ctx.h" static inline int clnt_read_vc(XDR *xdrs, void *ctp, void *buf, int len) { struct x_vc_data *xd = (struct x_vc_data *)ctp; struct ct_data *ct = &xd->cx.data; rpc_ctx_t *ctx = (rpc_ctx_t *) xdrs->x_lib[1]; struct pollfd fd; int milliseconds = (int)((ct->ct_wait.tv_sec * 1000) + (ct->ct_wait.tv_usec / 1000)); if (len == 0) return (0); fd.fd = xd->cx.data.ct_fd; fd.events = POLLIN; for (;;) { switch (poll(&fd, 1, milliseconds)) { case 0: ctx->error.re_status = RPC_TIMEDOUT; return (-1); case -1: if (errno == EINTR) continue; ctx->error.re_status = RPC_CANTRECV; ctx->error.re_errno = errno; return (-1); } break; } len = read(xd->cx.data.ct_fd, buf, (size_t) len); switch (len) { case 0: /* premature eof */ ctx->error.re_errno = ECONNRESET; ctx->error.re_status = RPC_CANTRECV; len = -1; /* it's really an error */ break; case -1: ctx->error.re_errno = errno; ctx->error.re_status = RPC_CANTRECV; break; } return (len); } static inline int clnt_write_vc(XDR *xdrs, void *ctp, void *buf, int len) { struct x_vc_data *xd = (struct x_vc_data *)ctp; rpc_ctx_t *ctx = (rpc_ctx_t *) xdrs->x_lib[1]; int i = 0, cnt; for (cnt = len; cnt > 0; cnt -= i, buf += i) { i = write(xd->cx.data.ct_fd, buf, (size_t) cnt); if (i == -1) { ctx->error.re_errno = errno; ctx->error.re_status = RPC_CANTSEND; return (-1); } } return (len); } static inline void cfconn_set_dead(SVCXPRT *xprt, struct x_vc_data *xd) { mutex_lock(&xprt->xp_lock); xd->sx.strm_stat = XPRT_DIED; mutex_unlock(&xprt->xp_lock); } /* * reads data from the tcp or udp 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. */ #define EARLY_DEATH_DEBUG 1 static inline int svc_read_vc(XDR *xdrs, void *ctp, void *buf, int len) { SVCXPRT *xprt; int milliseconds = 35 * 1000; /* XXX configurable? */ struct pollfd pollfd; struct x_vc_data *xd; xd = (struct x_vc_data *)ctp; xprt = xd->rec->hdl.xprt; if (xd->shared.nonblock) { len = read(xprt->xp_fd, buf, (size_t) len); if (len < 0) { if (errno == EAGAIN) len = 0; else goto fatal_err; } if (len != 0) (void)clock_gettime(CLOCK_MONOTONIC_FAST, &xd->sx.last_recv); return len; } do { pollfd.fd = xprt->xp_fd; pollfd.events = POLLIN; pollfd.revents = 0; switch (poll(&pollfd, 1, milliseconds)) { case -1: if (errno == EINTR) continue; /*FALLTHROUGH*/ case 0: __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: poll returns 0 (will set dead)", __func__); goto fatal_err; default: break; } } while ((pollfd.revents & POLLIN) == 0); len = read(xprt->xp_fd, buf, (size_t) len); if (len > 0) { (void) clock_gettime(CLOCK_MONOTONIC_FAST, &xd->sx.last_recv); return (len); } fatal_err: cfconn_set_dead(xprt, xd); return (-1); } /* * writes data to the tcp connection. * Any error is fatal and the connection is closed. */ static inline int svc_write_vc(XDR *xdrs, void *ctp, void *buf, int len) { SVCXPRT *xprt; struct x_vc_data *xd; struct timespec ts0, ts1; int i, cnt; xd = (struct x_vc_data *)ctp; xprt = xd->rec->hdl.xprt; if (xd->shared.nonblock) (void)clock_gettime(CLOCK_MONOTONIC_FAST, &ts0); for (cnt = len; cnt > 0; cnt -= i, buf += i) { i = write(xprt->xp_fd, buf, (size_t) cnt); if (i < 0) { if (errno != EAGAIN || !xd->shared.nonblock) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: short write !EAGAIN (will set dead)", __func__); cfconn_set_dead(xprt, xd); return (-1); } if (xd->shared.nonblock && i != cnt) { /* * For non-blocking connections, do not * take more than 2 seconds writing the * data out. * * XXX 2 is an arbitrary amount. */ (void)clock_gettime(CLOCK_MONOTONIC_FAST, &ts1); if (ts1.tv_sec - ts0.tv_sec >= 2) { __warnx(TIRPC_DEBUG_FLAG_SVC_VC, "%s: short write !EAGAIN (will set dead)", __func__); cfconn_set_dead(xprt, xd); return (-1); } } } } return (len); } /* generic read and write callbacks */ int generic_read_vc(XDR *xdrs, void *ctp, void *buf, int len) { switch ((enum rpc_duplex_callpath)xdrs->x_lib[0]) { case RPC_DPLX_CLNT: return (clnt_read_vc(xdrs, ctp, buf, len)); break; case RPC_DPLX_SVC: return (svc_read_vc(xdrs, ctp, buf, len)); break; default: /* better not */ abort(); } } int generic_write_vc(XDR *xdrs, void *ctp, void *buf, int len) { switch ((enum rpc_duplex_callpath)xdrs->x_lib[0]) { case RPC_DPLX_CLNT: return (clnt_write_vc(xdrs, ctp, buf, len)); break; case RPC_DPLX_SVC: return (svc_write_vc(xdrs, ctp, buf, len)); break; default: /* better not */ abort(); } } void vc_shared_destroy(struct x_vc_data *xd) { struct rpc_dplx_rec *rec = xd->rec; struct ct_data *ct = &xd->cx.data; SVCXPRT *xprt; bool closed = false; bool xdrs_destroyed = false; /* RECLOCKED */ if (ct->ct_closeit && ct->ct_fd != RPC_ANYFD) { (void)close(ct->ct_fd); closed = true; } /* destroy shared XDR record streams (once) */ XDR_DESTROY(&xd->shared.xdrs_in); XDR_DESTROY(&xd->shared.xdrs_out); xdrs_destroyed = true; if (ct->ct_addr.buf) mem_free(ct->ct_addr.buf, 0); /* XXX */ /* svc_vc */ xprt = rec->hdl.xprt; if (xprt) { XPRT_TRACE(xprt, __func__, __func__, __LINE__); rec->hdl.xprt = NULL; /* unreachable */ if (!closed) { if (xprt->xp_fd != RPC_ANYFD) (void)close(xprt->xp_fd); } /* request socket */ if (!xdrs_destroyed) { XDR_DESTROY(&(xd->shared.xdrs_in)); XDR_DESTROY(&(xd->shared.xdrs_out)); } if (xprt->xp_tp) mem_free(xprt->xp_tp, 0); if (xprt->xp_netid) mem_free(xprt->xp_netid, 0); if (xprt->xp_ops->xp_free_user_data) { /* call free hook */ xprt->xp_ops->xp_free_user_data(xprt); } mem_free(xprt, sizeof(SVCXPRT)); } rec->hdl.xd = NULL; /* unref shared */ REC_UNLOCK(rec); if (xprt) rpc_dplx_unref(rec, RPC_DPLX_FLAG_NONE); /* free xd itself */ mem_free(xd, sizeof(struct x_vc_data)); } ntirpc-1.3.1/src/work_pool.c000066400000000000000000000201431261345040100157550ustar00rootroot00000000000000/* * Copyright (c) 2013-2015 CohortFS, LLC. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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. */ /** * @file work_pool.c * @author William Allen Simpson * @brief Pthreads-based work queue package * * @section DESCRIPTION * * This provides simple work queues using pthreads and TAILQ primitives. * * @note Loosely based upon previous thrdpool by * Matt Benjamin */ #include #include #if !defined(_WIN32) #include #include #endif #include #include "rpc_com.h" #include #include #include #include #include #include #include #include #include #define WORK_POOL_STACK_SIZE MAX(64 * 1024, PTHREAD_STACK_MIN) #define WORK_POOL_TIMEOUT_MS (120000) /* forward declaration in lieu of moving code, was inline */ static int work_pool_spawn(struct work_pool *pool); int work_pool_init(struct work_pool *pool, const char *name, struct work_pool_params *params) { int rc; memset(pool, 0, sizeof(*pool)); poolq_head_setup(&pool->pqh); pool->name = rpc_strdup(name); pool->params = *params; if (pool->params.thrd_max < 1) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() thrd_max (%d) < 1", __func__, pool->params.thrd_max); pool->params.thrd_max = 1; }; if (pool->params.thrd_min < 1) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() thrd_min (%d) < 1", __func__, pool->params.thrd_min); pool->params.thrd_min = 1; }; rc = pthread_attr_init(&pool->attr); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't init pthread's attributes: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = pthread_attr_setscope(&pool->attr, PTHREAD_SCOPE_SYSTEM); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't set pthread's scope: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = pthread_attr_setdetachstate(&pool->attr, PTHREAD_CREATE_DETACHED); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't set pthread's join state: %s (%d)", __func__, strerror(rc), rc); return rc; } rc = pthread_attr_setstacksize(&pool->attr, WORK_POOL_STACK_SIZE); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() can't set pthread's stack size: %s (%d)", __func__, strerror(rc), rc); } /* initial spawn will spawn more threads as needed */ return work_pool_spawn(pool); } static inline int work_pool_wait(struct work_pool *pool, struct work_pool_thread *wpt) { struct timespec ts; int rc; clock_gettime(CLOCK_REALTIME_FAST, &ts); timespec_addms(&ts, WORK_POOL_TIMEOUT_MS); /* Note: the mutex is the pool _head, * but the condition is per worker, * making the signal efficient! */ rc = pthread_cond_timedwait(&wpt->pqcond, &pool->pqh.qmutex, &ts); if (rc) { if (!wpt->work) { /* Allow for possible timing race: work entry can be * set by another thread with the timeout result? * Then, has already been removed there. * Only remove with no work here. */ TAILQ_REMOVE(&pool->pqh.qh, &wpt->pqe, q); ++(pool->pqh.qcount); } if (rc != ETIMEDOUT) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() cond_timedwait failed (%d)\n", __func__, rc); return (rc); } } return (0); } /** * @brief The worker thread * * This is the body of the worker thread. The argument is a pointer to * its working context, kept in a list for each pool. * * @param[in] arg thread context */ static void * work_pool_thread(void *arg) { struct work_pool_thread *wpt = arg; struct work_pool *pool = wpt->pool; struct poolq_entry *have; atomic_inc_uint32_t(&pool->n_threads); pthread_cond_init(&wpt->pqcond, NULL); do { /* testing at top of loop allows pre-specification of work, * and thread termination after timeout with no work (below). */ if (wpt->work) { if (pool->pqh.qcount > -pool->params.thrd_min && pool->n_threads < pool->params.thrd_max) { /* busy, so dynamically add another thread */ (void)work_pool_spawn(pool); } __warnx(TIRPC_DEBUG_FLAG_EVENT, "%s() %s task %p", __func__, pool->name, wpt->work); wpt->work->fun(wpt->work); wpt->work = NULL; } pthread_mutex_lock(&pool->pqh.qmutex); if (0 < pool->pqh.qcount--) { /* positive for task(s) */ have = TAILQ_FIRST(&pool->pqh.qh); TAILQ_REMOVE(&pool->pqh.qh, have, q); wpt->work = (struct work_pool_entry *)have; } else { /* negative for waiting worker(s): * use the otherwise empty pool to hold them, * simplifying mutex and pointer setup. */ TAILQ_INSERT_TAIL(&pool->pqh.qh, &wpt->pqe, q); __warnx(TIRPC_DEBUG_FLAG_EVENT, "%s() %s waiting for task", __func__, pool->name); if (unlikely(work_pool_wait(pool, wpt))) { /* failed, not timeout */ pthread_mutex_unlock(&pool->pqh.qmutex); break; } } pthread_mutex_unlock(&pool->pqh.qmutex); } while (wpt->work || pool->n_threads <= pool->params.thrd_min); /* cleanup thread context */ atomic_dec_uint32_t(&pool->n_threads); cond_destroy(&wpt->pqcond); mem_free(wpt, sizeof(*wpt)); return (NULL); } static inline void work_pool_dispatch(struct work_pool *pool, struct work_pool_entry *work) { struct work_pool_thread *wpt = (struct work_pool_thread *) TAILQ_FIRST(&pool->pqh.qh); TAILQ_REMOVE(&pool->pqh.qh, &wpt->pqe, q); wpt->work = work; /* Note: the mutex is the pool _head, * but the condition is per worker, * making the signal efficient! */ pthread_cond_signal(&wpt->pqcond); } static int work_pool_spawn(struct work_pool *pool) { int rc; struct work_pool_thread *wpt = mem_zalloc(sizeof(*wpt)); if (!wpt) { rc = errno; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() mem_zalloc failed (%d)\n", __func__, rc); return rc; } wpt->pool = pool; rc = pthread_create(&wpt->id, &pool->attr, work_pool_thread, wpt); if (rc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() pthread_create failed (%d)\n", __func__, rc); return rc; } return (0); } int work_pool_submit(struct work_pool *pool, struct work_pool_entry *work) { int rc = 0; if (unlikely(!pool->params.thrd_max)) { /* queue is draining */ return (0); } pthread_mutex_lock(&pool->pqh.qmutex); if (likely(0 > pool->pqh.qcount++)) { /* negative for waiting worker(s) */ work_pool_dispatch(pool, work); } else { /* positive for task(s) */ TAILQ_INSERT_TAIL(&pool->pqh.qh, &work->pqe, q); } pthread_mutex_unlock(&pool->pqh.qmutex); return rc; } int work_pool_shutdown(struct work_pool *pool) { struct timespec ts = { .tv_sec = 5, .tv_nsec = 0, }; pool->params.thrd_max = pool->params.thrd_min = 0; pthread_mutex_lock(&pool->pqh.qmutex); while (0 > pool->pqh.qcount) { /* unlike _submit, only increment negatives */ pool->pqh.qcount++; work_pool_dispatch(pool, NULL); } pthread_mutex_unlock(&pool->pqh.qmutex); while (pool->n_threads > 0) { nanosleep(&ts, NULL); } mem_free(pool->name, 0); poolq_head_destroy(&pool->pqh); return (0); } ntirpc-1.3.1/src/xdr.c000066400000000000000000000402771261345040100145510ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * xdr.c, Generic XDR routines implementation. * * Copyright (C) 1986, Sun Microsystems, Inc. * * These are the "generic" xdr routines used to serialize and de-serialize * most common data items. See xdr.h for more info on the interface to * xdr. */ #include #include #include #include #include #include #include typedef quad_t longlong_t; /* ANSI long long type */ typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */ /* * constants specific to the xdr "protocol" */ #define XDR_FALSE ((long) 0) #define XDR_TRUE ((long) 1) #define LASTUNSIGNED ((u_int) 0-1) /* * for unit alignment */ static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 }; /* * for cleanup */ XDR xdr_free_null_stream = { .x_op = XDR_FREE, .x_public = NULL, .x_private = NULL, .x_lib = {NULL, NULL}, .x_base = NULL, .x_v = {NULL, NULL, NULL, NULL}, }; /* * XDR nothing */ bool xdr_void(void) { return (true); } /* * XDR integers */ bool xdr_int(XDR *xdrs, int *ip) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*ip; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *ip = (int)l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned integers */ bool xdr_u_int(XDR *xdrs, u_int *up) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *up; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *up = (u_int) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR long integers * same as xdr_u_long - open coded to save a proc call! */ bool xdr_long(XDR *xdrs, long *lp) { switch (xdrs->x_op) { case XDR_ENCODE: return (XDR_PUTLONG(xdrs, lp)); case XDR_DECODE: return (XDR_GETLONG(xdrs, lp)); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned long integers * same as xdr_long - open coded to save a proc call! */ bool xdr_u_long(XDR *xdrs, u_long *ulp) { switch (xdrs->x_op) { case XDR_ENCODE: return (XDR_PUTLONG(xdrs, (long *)ulp)); case XDR_DECODE: return (XDR_GETLONG(xdrs, (long *)ulp)); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR 32-bit integers * same as xdr_u_int32_t - open coded to save a proc call! */ bool xdr_int32_t(XDR *xdrs, int32_t *int32_p) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*int32_p; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *int32_p = (int32_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 32-bit integers * same as xdr_int32_t - open coded to save a proc call! */ bool xdr_u_int32_t(XDR *xdrs, u_int32_t *u_int32_p) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *u_int32_p; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *u_int32_p = (u_int32_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 32-bit integers * same as xdr_int32_t - open coded to save a proc call! */ bool xdr_uint32_t(XDR *xdrs, u_int32_t *uint32_p) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *uint32_p; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *uint32_p = (uint32_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR short integers */ bool xdr_short(XDR *xdrs, short *sp) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*sp; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *sp = (short)l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned short integers */ bool xdr_u_short(XDR *xdrs, u_short *usp) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *usp; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *usp = (u_short) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR 16-bit integers */ bool xdr_int16_t(XDR *xdrs, int16_t *int16_p) { long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (long)*int16_p; return (XDR_PUTLONG(xdrs, &l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &l)) return (false); *int16_p = (int16_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 16-bit integers */ bool xdr_u_int16_t(XDR *xdrs, u_int16_t *u_int16_p) { u_long l; switch (xdrs->x_op) { case XDR_ENCODE: l = (u_long) *u_int16_p; return (XDR_PUTLONG(xdrs, (long *)&l)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, (long *)&l)) return (false); *u_int16_p = (u_int16_t) l; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR a char */ bool xdr_char(XDR *xdrs, char *cp) { int i; i = (*cp); if (!xdr_int(xdrs, &i)) return (false); *cp = i; return (true); } /* * XDR an unsigned char */ bool xdr_u_char(XDR *xdrs, u_char *cp) { u_int u; u = (*cp); if (!xdr_u_int(xdrs, &u)) return (false); *cp = u; return (true); } /* * XDR booleans */ bool xdr_bool(XDR *xdrs, bool_t *bp) { long lb; switch (xdrs->x_op) { case XDR_ENCODE: lb = *bp ? XDR_TRUE : XDR_FALSE; return (XDR_PUTLONG(xdrs, &lb)); case XDR_DECODE: if (!XDR_GETLONG(xdrs, &lb)) return (false); *bp = (lb == XDR_FALSE) ? false : true; return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR enumerations */ bool xdr_enum(XDR *xdrs, enum_t *ep) { enum sizecheck { SIZEVAL }; /* used to find the size of an enum */ /* * enums are treated as ints */ if (sizeof(enum sizecheck) == sizeof(long)) { return (xdr_long(xdrs, (long *)(void *)ep)); } else if (sizeof(enum sizecheck) == sizeof(int)) { return (xdr_int(xdrs, (int *)(void *)ep)); } else if (sizeof(enum sizecheck) == sizeof(short)) { return (xdr_short(xdrs, (short *)(void *)ep)); } else { return (false); } } /* * XDR opaque data * Allows the specification of a fixed size sequence of opaque bytes. * cp points to the opaque object and cnt gives the byte length. */ bool xdr_opaque(XDR *xdrs, caddr_t cp, u_int cnt) { u_int rndup; static int crud[BYTES_PER_XDR_UNIT]; /* * if no data we are done */ if (cnt == 0) return (true); /* * round byte count to full xdr units */ rndup = cnt % BYTES_PER_XDR_UNIT; if (rndup > 0) rndup = BYTES_PER_XDR_UNIT - rndup; if (xdrs->x_op == XDR_DECODE) { if (!XDR_GETBYTES(xdrs, cp, cnt)) return (false); if (rndup == 0) return (true); return (XDR_GETBYTES(xdrs, (caddr_t) (void *)crud, rndup)); } if (xdrs->x_op == XDR_ENCODE) { if (!XDR_PUTBYTES(xdrs, cp, cnt)) return (false); if (rndup == 0) return (true); return (XDR_PUTBYTES(xdrs, xdr_zero, rndup)); } if (xdrs->x_op == XDR_FREE) return (true); return (false); } /* * XDR counted bytes * *cpp is a pointer to the bytes, *sizep is the count. * If *cpp is NULL maxsize bytes are allocated */ bool xdr_bytes(XDR *xdrs, char **cpp, u_int *sizep, u_int maxsize) { char *sp = *cpp; /* sp is the actual string pointer */ u_int nodesize; /* * first deal with the length since xdr bytes are counted */ if (!xdr_u_int(xdrs, sizep)) return (false); nodesize = *sizep; if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) return (false); /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (nodesize == 0) return (true); if (sp == NULL) *cpp = sp = mem_alloc(nodesize); if (sp == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDR, "xdr_bytes: out of memory"); return (false); } /* FALLTHROUGH */ case XDR_ENCODE: return (xdr_opaque(xdrs, sp, nodesize)); case XDR_FREE: if (sp != NULL) { mem_free(sp, nodesize); *cpp = NULL; } return (true); } /* NOTREACHED */ return (false); } /* * Implemented here due to commonality of the object. */ bool xdr_netobj(XDR *xdrs, struct netobj *np) { return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ)); } /* * XDR a descriminated union * Support routine for discriminated unions. * You create an array of xdrdiscrim structures, terminated with * an entry with a null procedure pointer. The routine gets * the discriminant value and then searches the array of xdrdiscrims * looking for that value. It calls the procedure given in the xdrdiscrim * to handle the discriminant. If there is no specific routine a default * routine may be called. * If there is no specific or default routine an error is returned. */ bool xdr_union(XDR *xdrs, enum_t *dscmp, /* enum to decide which arm to work on */ char *unp, /* the union itself */ const struct xdr_discrim *choices, /* [value, xdr proc] for each arm */ xdrproc_t dfault /* default xdr routine */) { enum_t dscm; /* * we deal with the discriminator; it's an enum */ if (!xdr_enum(xdrs, dscmp)) return (false); dscm = *dscmp; /* * search choices for a value that matches the discriminator. * if we find one, execute the xdr routine for that value. */ for (; choices->proc != NULL_xdrproc_t; choices++) { if (choices->value == dscm) return ((*(choices->proc)) (xdrs, unp)); } /* * no match - execute the default xdr routine if there is one */ return ((dfault == NULL_xdrproc_t) ? false : (*dfault) (xdrs, unp)); } /* * Non-portable xdr primitives. * Care should be taken when moving these routines to new architectures. */ /* * XDR null terminated ASCII strings * xdr_string deals with "C strings" - arrays of bytes that are * terminated by a NULL character. The parameter cpp references a * pointer to storage; If the pointer is null, then the necessary * storage is allocated. The last parameter is the max allowed length * of the string as specified by a protocol. */ bool xdr_string(XDR *xdrs, char **cpp, u_int maxsize) { char *sp = *cpp; /* sp is the actual string pointer */ u_int size = 0; u_int nodesize; /* * first deal with the length since xdr strings are counted-strings */ switch (xdrs->x_op) { case XDR_FREE: if (sp == NULL) return (true); /* already free */ /* FALLTHROUGH */ case XDR_ENCODE: if (sp == NULL) return false; size = strlen(sp); break; case XDR_DECODE: break; } if (!xdr_u_int(xdrs, &size)) return (false); if (size > maxsize) return (false); nodesize = size + 1; if (nodesize == 0) { /* This means an overflow. It a bug in the caller which * provided a too large maxsize but nevertheless catch it * here. */ return false; } /* * now deal with the actual bytes */ switch (xdrs->x_op) { case XDR_DECODE: if (sp == NULL) *cpp = sp = mem_alloc(nodesize); if (sp == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDR, "xdr_string: out of memory"); return (false); } sp[size] = 0; /* FALLTHROUGH */ case XDR_ENCODE: return (xdr_opaque(xdrs, sp, size)); case XDR_FREE: mem_free(sp, nodesize); *cpp = NULL; return (true); } /* NOTREACHED */ return (false); } /* * Wrapper for xdr_string that can be called directly from * routines like clnt_call */ bool xdr_wrapstring(XDR *xdrs, char **cpp) { return xdr_string(xdrs, cpp, LASTUNSIGNED); } /* * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t() * are in the "non-portable" section because they require that a `long long' * be a 64-bit type. * * --thorpej@netbsd.org, November 30, 1999 */ /* * XDR 64-bit integers */ bool xdr_int64_t(XDR *xdrs, int64_t *llp) { u_long ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: ul[0] = (u_long) ((u_int64_t) *llp >> 32) & 0xffffffff; ul[1] = (u_long) ((u_int64_t) *llp) & 0xffffffff; if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == false) return (false); return (XDR_PUTLONG(xdrs, (long *)&ul[1])); case XDR_DECODE: if (XDR_GETLONG(xdrs, (long *)&ul[0]) == false) return (false); if (XDR_GETLONG(xdrs, (long *)&ul[1]) == false) return (false); *llp = (int64_t) (((u_int64_t) ul[0] << 32) | ((u_int64_t) ul[1])); return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 64-bit integers */ bool xdr_u_int64_t(XDR *xdrs, u_int64_t *ullp) { u_long ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: ul[0] = (u_long) (*ullp >> 32) & 0xffffffff; ul[1] = (u_long) (*ullp) & 0xffffffff; if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == false) return (false); return (XDR_PUTLONG(xdrs, (long *)&ul[1])); case XDR_DECODE: if (XDR_GETLONG(xdrs, (long *)&ul[0]) == false) return (false); if (XDR_GETLONG(xdrs, (long *)&ul[1]) == false) return (false); *ullp = (u_int64_t) (((u_int64_t) ul[0] << 32) | ((u_int64_t) ul[1])); return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR unsigned 64-bit integers */ bool xdr_uint64_t(XDR *xdrs, uint64_t *ullp) { u_long ul[2]; switch (xdrs->x_op) { case XDR_ENCODE: ul[0] = (u_long) (*ullp >> 32) & 0xffffffff; ul[1] = (u_long) (*ullp) & 0xffffffff; if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == false) return (false); return (XDR_PUTLONG(xdrs, (long *)&ul[1])); case XDR_DECODE: if (XDR_GETLONG(xdrs, (long *)&ul[0]) == false) return (false); if (XDR_GETLONG(xdrs, (long *)&ul[1]) == false) return (false); *ullp = (uint64_t) (((uint64_t) ul[0] << 32) | ((uint64_t) ul[1])); return (true); case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } /* * XDR hypers */ bool xdr_hyper(XDR *xdrs, longlong_t *llp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_int64_t(). */ return (xdr_int64_t(xdrs, (int64_t *) llp)); } /* * XDR unsigned hypers */ bool xdr_u_hyper(XDR *xdrs, u_longlong_t *ullp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_u_int64_t(). */ return (xdr_u_int64_t(xdrs, (u_int64_t *) ullp)); } /* * XDR longlong_t's */ bool xdr_longlong_t(XDR *xdrs, longlong_t *llp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_int64_t(). */ return (xdr_int64_t(xdrs, (int64_t *) llp)); } /* * XDR u_longlong_t's */ bool xdr_u_longlong_t(XDR *xdrs, u_longlong_t *ullp) { /* * Don't bother open-coding this; it's a fair amount of code. Just * call xdr_u_int64_t(). */ return (xdr_u_int64_t(xdrs, (u_int64_t *) ullp)); } ntirpc-1.3.1/src/xdr_array.c000066400000000000000000000104631261345040100157410ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * xdr_array.c, Generic XDR routines impelmentation. * * Copyright (C) 1984, Sun Microsystems, Inc. * * These are the "non-trivial" xdr primitives used to serialize and * de-serialize arrays. See xdr.h for more info on the interface to xdr. */ #include "namespace.h" #if !defined(_WIN32) #include #endif #include #include #include #include #include #include #include #include "un-namespace.h" /* * 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 xdr_array(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 stat = true; u_int nodesize; /* like strings, arrays are really counted arrays */ if (!inline_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(TIRPC_DEBUG_FLAG_XDR, "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 xdr_vector(XDR *xdrs, char *basep, u_int nelem, u_int elemsize, xdrproc_t xdr_elem) { u_int i; char *elptr; elptr = basep; for (i = 0; i < nelem; i++) { if (!(*xdr_elem) (xdrs, elptr)) return (false); elptr += elemsize; } return (true); } ntirpc-1.3.1/src/xdr_float.c000066400000000000000000000170271261345040100157330ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * 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 #include #include #include #include #include "un-namespace.h" /* * NB: Not portable. * This routine works on machines with IEEE754 FP and Vaxen. */ #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 */ }; #else #if defined(__linux__) #include #elif defined(_WIN32) /* XXX */ #elif defined(__APPLE__) #include #else #include #endif #define IEEEFP #endif /* vax */ bool xdr_float(XDR *xdrs, float *fp) { #ifndef IEEEFP struct ieee_single is; struct vax_single vs, *vsp; struct sgl_limits *lim; int i; #endif switch (xdrs->x_op) { case XDR_ENCODE: #ifdef IEEEFP return (XDR_PUTINT32(xdrs, (int32_t *) 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 *) &is)); #endif case XDR_DECODE: #ifdef IEEEFP return (XDR_GETINT32(xdrs, (int32_t *) fp)); #else vsp = (struct vax_single *)fp; if (!XDR_GETINT32(xdrs, (int32_t *) &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 xdr_double(XDR *xdrs, double *dp) { #ifdef IEEEFP int32_t *i32p; bool rv; #else int32_t *lp; struct ieee_double id; struct vax_double vd; struct dbl_limits *lim; int i; #endif switch (xdrs->x_op) { case XDR_ENCODE: #ifdef IEEEFP i32p = (int32_t *) (void *)dp; #if BYTE_ORDER == BIG_ENDIAN 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 *) &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 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 *) &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 *)&vd); return (true); #endif case XDR_FREE: return (true); } /* NOTREACHED */ return (false); } ntirpc-1.3.1/src/xdr_inrec.c000066400000000000000000000346251261345040100157310ustar00rootroot00000000000000/* * Copyright (c) 2009,s Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include /* * 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 #if !defined(_WIN32) #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include #include #include static bool xdr_inrec_getlong(XDR *, long *); static bool xdr_inrec_putlong(XDR *, const long *); static bool xdr_inrec_getbytes(XDR *, char *, u_int); static bool xdr_inrec_putbytes(XDR *, const char *, u_int); static u_int xdr_inrec_getpos(XDR *); static bool xdr_inrec_setpos(XDR *, u_int); static int32_t *xdr_inrec_inline(XDR *, u_int); static void xdr_inrec_destroy(XDR *); static bool xdr_inrec_noop(void); extern bool xdr_inrec_readahead(XDR *, u_int); typedef bool (*dummyfunc3) (XDR *, int, void *); typedef bool (*dummy_getbufs) (XDR *, xdr_uio *, u_int); typedef bool (*dummy_putbufs) (XDR *, xdr_uio *, u_int); static const struct xdr_ops xdr_inrec_ops = { xdr_inrec_getlong, xdr_inrec_putlong, xdr_inrec_getbytes, xdr_inrec_putbytes, xdr_inrec_getpos, xdr_inrec_setpos, xdr_inrec_inline, xdr_inrec_destroy, (dummyfunc3) xdr_inrec_noop, /* x_control */ (dummy_getbufs) xdr_inrec_noop, /* x_getbufs */ (dummy_putbufs) xdr_inrec_noop /* x_putbufs */ }; /* * 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 { XDR *xdrs; char *tcp_handle; /* * in-coming bits */ int (*readit) (XDR *, void *, void *, int); u_int32_t 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 */ int32_t fbtbc; /* fragment bytes to be consumed */ int32_t offset; bool last_frag; u_int recvsize; uint64_t cksum; uint32_t cklen; bool in_haveheader; u_int32_t in_header; int in_maxrec; } RECSTREAM; static u_int fix_buf_size(u_int); static bool fill_input_buf(RECSTREAM *, int32_t); static bool get_input_bytes(RECSTREAM *, char *, int32_t, int32_t); static bool set_input_fragment(RECSTREAM *, int32_t); static bool skip_input_bytes(RECSTREAM *, long); static void compute_buffer_cksum(RECSTREAM *); /* * Create an xdr handle for xdrrec * xdr_inrec_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 xdr_inrec_create(XDR *xdrs, u_int recvsize, void *tcp_handle, /* like read, but pass it a tcp_handle, not sock */ int (*readit) (XDR *, void *, void *, int)) { RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); if (rstrm == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDRREC, "xdr_inrec_create: out of memory"); /* * This is bad. Should rework xdr_inrec_create to * return a handle, and in this case return NULL */ return; } rstrm->recvsize = recvsize = fix_buf_size(recvsize); rstrm->in_base = mem_alloc(recvsize); if (rstrm->in_base == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDRREC, "xdr_inrec_create: out of memory"); mem_free(rstrm, sizeof(RECSTREAM)); return; } /* * now the rest ... */ xdrs->x_ops = &xdr_inrec_ops; xdrs->x_lib[0] = NULL; xdrs->x_lib[1] = NULL; xdrs->x_public = NULL; xdrs->x_private = rstrm; xdrs->x_flags = XDR_FLAG_CKSUM; rstrm->xdrs = xdrs; rstrm->tcp_handle = tcp_handle; rstrm->readit = readit; 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->offset = 0; rstrm->cksum = 0; rstrm->cklen = 256; } /* Compute 64-bit checksum of the first cnt bytes (or offset, whichever is * less) in the receive buffer. Use only as directed. */ uint64_t xdr_inrec_cksum(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); /* handle checksumming if requested (short request case) */ if (xdrs->x_flags & XDR_FLAG_CKSUM) { if (!(rstrm->cksum)) { if (rstrm->cklen) compute_buffer_cksum(rstrm); } } return (rstrm->cksum); } /* * The routines defined below are the xdr ops which will go into the * xdr handle filled in by xdr_inrec_create. */ static bool xdr_inrec_getlong(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 >= sizeof(int32_t)) && ((PtrToUlong(rstrm->in_boundry) - PtrToUlong(buflp)) >= sizeof(int32_t))) { *lp = (long)ntohl((u_int32_t) (*buflp)); rstrm->fbtbc -= sizeof(int32_t); rstrm->in_finger += sizeof(int32_t); } else { if (!xdr_inrec_getbytes (xdrs, (char *)(void *)&mylong, sizeof(int32_t))) return (false); *lp = (long)ntohl((u_int32_t) mylong); } return (true); } static bool xdr_inrec_putlong(XDR *xdrs, const long *lp) { return (false); } static bool xdr_inrec_getbytes(XDR *xdrs, char *addr, u_int len) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); int current; while (len > 0) { current = (int)rstrm->fbtbc; if (current == 0) { if (rstrm->last_frag) return (false); if (!set_input_fragment(rstrm, INT_MAX)) return (false); continue; } current = (len < current) ? len : current; if (!get_input_bytes(rstrm, addr, current, INT_MAX)) return (false); addr += current; rstrm->fbtbc -= current; len -= current; /* handle checksumming if requested */ if (xdrs->x_flags & XDR_FLAG_CKSUM) { if (rstrm->cklen) { if (!(rstrm->cksum)) { if (rstrm->offset >= rstrm->cklen) compute_buffer_cksum(rstrm); } } } } return (true); } static bool xdr_inrec_putbytes(XDR *xdrs, const char *addr, u_int len) { return (false); } static u_int xdr_inrec_getpos(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; off_t pos; switch (xdrs->x_op) { case XDR_DECODE: pos = rstrm->in_boundry - rstrm->in_finger - BYTES_PER_XDR_UNIT; break; default: /* XXX annoys Coverity */ pos = (off_t) -1; break; } return ((u_int) pos); } static bool xdr_inrec_setpos(XDR *xdrs, u_int pos) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; u_int currpos = xdr_inrec_getpos(xdrs); int delta = currpos - pos; char *newpos; if ((int)currpos != -1) switch (xdrs->x_op) { 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_ENCODE: case XDR_FREE: break; } return (false); } bool xdr_inrec_readahead(XDR *xdrs, u_int maxfraglen) { RECSTREAM *rstrm; int current; rstrm = (RECSTREAM *) xdrs->x_private; current = (int)rstrm->fbtbc; if (current == 0) { if (rstrm->last_frag) return (false); if (!set_input_fragment(rstrm, maxfraglen)) return (false); } return (true); } static int32_t * xdr_inrec_inline(XDR *xdrs, u_int len) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; int32_t *buf = NULL; switch (xdrs->x_op) { case XDR_DECODE: if ((len <= 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_ENCODE: case XDR_FREE: break; } return (buf); } static void xdr_inrec_destroy(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; 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 xdr_inrec_skiprecord(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) { if (!skip_input_bytes(rstrm, rstrm->fbtbc)) return (false); rstrm->fbtbc = 0; if ((!rstrm->last_frag) && (!set_input_fragment(rstrm, INT_MAX))) return (false); } rstrm->last_frag = false; rstrm->offset = 0; rstrm->cksum = 0; return (true); } /* * Look ahead function. * Returns true iff there is no more input in the buffer * after consuming the rest of the current record. */ bool xdr_inrec_eof(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) { if (!skip_input_bytes(rstrm, rstrm->fbtbc)) return (true); rstrm->fbtbc = 0; if ((!rstrm->last_frag) && (!set_input_fragment(rstrm, INT_MAX))) return (true); } if (rstrm->in_finger == rstrm->in_boundry) return (true); return (false); } static bool fill_input_buf(RECSTREAM *rstrm, int32_t maxreadahead) { char *where; u_int32_t i; int len; where = rstrm->in_base; i = (u_int32_t) (PtrToUlong(rstrm->in_boundry) % BYTES_PER_XDR_UNIT); where += i; len = MIN(((u_int32_t) (rstrm->in_size - i)), maxreadahead); len = (*(rstrm->readit)) (rstrm->xdrs, rstrm->tcp_handle, where, len); if (len == -1) return (false); rstrm->in_finger = where; where += len; rstrm->in_boundry = where; /* cksum lookahead */ rstrm->offset += len; return (true); } static bool get_input_bytes(RECSTREAM *rstrm, char *addr, int32_t len, int32_t maxreadahead) { int32_t current; while (len > 0) { current = (PtrToUlong(rstrm->in_boundry) - PtrToUlong(rstrm->in_finger)); if (current == 0) { if (!fill_input_buf(rstrm, maxreadahead)) 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 set_input_fragment(RECSTREAM *rstrm, int32_t maxreadahead) { u_int32_t header; if (!get_input_bytes (rstrm, (char *)(void *)&header, sizeof(header), maxreadahead)) 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 skip_input_bytes(RECSTREAM *rstrm, long cnt) { u_int32_t current; while (cnt > 0) { current = (size_t) (PtrToUlong(rstrm->in_boundry) - PtrToUlong(rstrm->in_finger)); if (current == 0) { if (!fill_input_buf(rstrm, INT_MAX)) return (false); continue; } current = (u_int32_t) ((cnt < current) ? cnt : current); rstrm->in_finger += current; cnt -= current; } return (true); } static u_int fix_buf_size(u_int s) { if (s < 100) s = 4000; return (RNDUP(s)); } static void compute_buffer_cksum(RECSTREAM *rstrm) { #if 1 /* CithHash64 is -substantially- faster than crc32c from FreeBSD * SCTP, so prefer it until fast crc32c bests it */ rstrm->cksum = CityHash64WithSeed(rstrm->in_base, MIN(rstrm->cklen, rstrm->offset), 103); #else rstrm->cksum = calculate_crc32c(0, rstrm->in_base, MIN(rstrm->cklen, rstrm->offset)); #endif } static bool xdr_inrec_noop(void) { return (false); } ntirpc-1.3.1/src/xdr_ioq.c000066400000000000000000000462271261345040100154220ustar00rootroot00000000000000/* * Copyright (c) 2013 Linux Box Corporation. * 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. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `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 AUTHOR 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 #include #if !defined(_WIN32) #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" #include static bool xdr_ioq_noop(void) __attribute__ ((unused)); #define VREC_MAXBUFS 24 static uint64_t next_id; #if 0 /* jemalloc docs warn about reclaim */ #define alloc_buffer(size) mem_alloc_aligned(0x8, (size)) #else #define alloc_buffer(size) mem_alloc((size)) #endif /* 0 */ #define free_buffer(addr,size) mem_free((addr), size) struct xdr_ioq_uv * xdr_ioq_uv_create(u_int size, u_int uio_flags) { struct xdr_ioq_uv *uv = mem_zalloc(sizeof(struct xdr_ioq_uv)); if (!uv) return (NULL); if (size) { uv->v.vio_base = alloc_buffer(size); if (!uv->v.vio_base) { mem_free(uv, sizeof(struct xdr_ioq_uv)); return (NULL); } uv->v.vio_head = uv->v.vio_base; uv->v.vio_tail = uv->v.vio_base; uv->v.vio_wrap = uv->v.vio_base + size; /* ensure not wrapping to zero */ assert(uv->v.vio_base < uv->v.vio_wrap); } uv->u.uio_flags = uio_flags; uv->u.uio_references = 1; /* starting one */ return (uv); } struct poolq_entry * xdr_ioq_uv_fetch(struct xdr_ioq *xioq, struct poolq_head *ioqh, char *comment, u_int count, u_int ioq_flags) { struct poolq_entry *have = NULL; __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() %u %s", __func__, count, comment); pthread_mutex_lock(&ioqh->qmutex); while (count--) { if (likely(0 < ioqh->qcount--)) { /* positive for buffer(s) */ have = TAILQ_FIRST(&ioqh->qh); TAILQ_REMOVE(&ioqh->qh, have, q); /* added directly to the queue. * this lock is needed for context header queues, * but is not a burden on uncontested data queues. */ pthread_mutex_lock(&xioq->ioq_uv.uvqh.qmutex); (xioq->ioq_uv.uvqh.qcount)++; TAILQ_INSERT_TAIL(&xioq->ioq_uv.uvqh.qh, have, q); pthread_mutex_unlock(&xioq->ioq_uv.uvqh.qmutex); } else { u_int saved = xioq->xdrs[0].x_handy; /* negative for waiting worker(s): * use the otherwise empty pool to hold them, * simplifying mutex and pointer setup. */ TAILQ_INSERT_TAIL(&ioqh->qh, &xioq->ioq_s, q); __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() waiting for %u %s", __func__, count, comment); /* Note: the mutex is the pool _head, * but the condition is per worker, * making the signal efficient! * * Nota Bene: count was already decremented, * will be zero for last one needed, * then will wrap as unsigned. */ xioq->xdrs[0].x_handy = count; pthread_cond_wait(&xioq->ioq_cond, &ioqh->qmutex); xioq->xdrs[0].x_handy = saved; /* entry was already added directly to the queue */ have = TAILQ_LAST(&xioq->ioq_uv.uvqh.qh, q_head); } } pthread_mutex_unlock(&ioqh->qmutex); return have; } struct poolq_entry * xdr_ioq_uv_fetch_nothing(struct xdr_ioq *xioq, struct poolq_head *ioqh, char *comment, u_int count, u_int ioq_flags) { return NULL; } static inline void xdr_ioq_uv_recycle(struct poolq_head *ioqh, struct poolq_entry *have) { pthread_mutex_lock(&ioqh->qmutex); if (likely(0 <= ioqh->qcount++)) { /* positive for buffer(s) */ TAILQ_INSERT_TAIL(&ioqh->qh, have, q); } else { /* negative for waiting worker(s) */ struct xdr_ioq *wait = _IOQ(TAILQ_FIRST(&ioqh->qh)); /* added directly to the queue. * no need to lock here, the mutex is the pool _head. */ (wait->ioq_uv.uvqh.qcount)++; TAILQ_INSERT_TAIL(&wait->ioq_uv.uvqh.qh, have, q); /* Nota Bene: x_handy was decremented count, * will be zero for last one needed, * then will wrap as unsigned. */ if (0 < wait->xdrs[0].x_handy--) { /* not removed */ ioqh->qcount--; } else { TAILQ_REMOVE(&ioqh->qh, &wait->ioq_s, q); pthread_cond_signal(&wait->ioq_cond); } } pthread_mutex_unlock(&ioqh->qmutex); } void xdr_ioq_uv_release(struct xdr_ioq_uv *uv) { if (uv->u.uio_refer) { /* not optional in this case! */ uv->u.uio_refer->uio_release(uv->u.uio_refer, UIO_FLAG_NONE); uv->u.uio_refer = NULL; } if (!(--uv->u.uio_references)) { if (uv->u.uio_release) { /* handle both xdr_ioq_uv and vio */ uv->u.uio_release(&uv->u, UIO_FLAG_NONE); } else if (uv->u.uio_flags & UIO_FLAG_FREE) { free_buffer(uv->v.vio_base, ioquv_size(uv)); mem_free(uv, sizeof(*uv)); } else if (uv->u.uio_flags & UIO_FLAG_BUFQ) { uv->u.uio_references = 1; /* keeping one */ xdr_ioq_uv_recycle(uv->u.uio_p1, &uv->uvq); } else { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() memory leak, no release flags (%u)\n", __func__, uv->u.uio_flags); abort(); } } } /* * Set initial read/insert or fill position. * * Note: must be done before any XDR_[GET|SET]POS() */ void xdr_ioq_reset(struct xdr_ioq *xioq, u_int wh_pos) { struct xdr_ioq_uv *uv = IOQ_(TAILQ_FIRST(&xioq->ioq_uv.uvqh.qh)); xioq->ioq_uv.plength = xioq->ioq_uv.pcount = 0; if (wh_pos >= ioquv_size(uv)) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() xioq %p wh_pos %d too big, ignored!\n", __func__, xioq, wh_pos); } else { uv->v.vio_head = uv->v.vio_base + wh_pos; } xioq->xdrs[0].x_v = uv->v; xioq->xdrs[0].x_base = &uv->v; xioq->xdrs[0].x_private = uv->v.vio_head; __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() xioq %p head %p wh_pos %d", __func__, xioq, uv->v.vio_head, wh_pos); } void xdr_ioq_setup(struct xdr_ioq *xioq) { XDR *xdrs = xioq->xdrs; /* the XDR is the top element of struct xdr_ioq */ assert((void *)xdrs == (void *)xioq); TAILQ_INIT_ENTRY(&xioq->ioq_s, q); xioq->ioq_s.qflags = IOQ_FLAG_NONE; poolq_head_setup(&xioq->ioq_uv.uvqh); pthread_cond_init(&xioq->ioq_cond, NULL); xdrs->x_ops = &xdr_ioq_ops; xdrs->x_op = XDR_ENCODE; xdrs->x_public = NULL; xdrs->x_private = NULL; xdrs->x_base = NULL; xdrs->x_flags = XDR_FLAG_VIO; xioq->id = atomic_inc_uint64_t(&next_id); } XDR * xdr_ioq_create(u_int min_bsize, u_int max_bsize, u_int uio_flags) { struct xdr_ioq *xioq = mem_zalloc(sizeof(struct xdr_ioq)); xdr_ioq_setup(xioq); xioq->ioq_uv.min_bsize = min_bsize; xioq->ioq_uv.max_bsize = max_bsize; if (!(uio_flags & UIO_FLAG_BUFQ)) { struct xdr_ioq_uv *uv = xdr_ioq_uv_create(min_bsize, uio_flags); xioq->ioq_uv.uvqh.qcount = 1; TAILQ_INSERT_HEAD(&xioq->ioq_uv.uvqh.qh, &uv->uvq, q); xdr_ioq_reset(xioq, 0); } return (xioq->xdrs); } /* * Advance read/insert or fill position. * * Update the logical and physical offsets and lengths, * based upon the most recent position information. * All such updates are consolidated here and getpos/setpos, * reducing computations in the get/put/inline routines. */ static inline struct xdr_ioq_uv * xdr_ioq_uv_next(struct xdr_ioq *xioq, u_int ioq_flags) { struct xdr_ioq_uv *uv = IOQV(xioq->xdrs[0].x_base); size_t len; /* update the most recent data length */ xdr_tail_update(xioq->xdrs); len = ioquv_length(uv); xioq->ioq_uv.plength += len; /* next buffer, if any */ uv = IOQ_(TAILQ_NEXT(&uv->uvq, q)); /* append new segments, iif requested */ if ((!uv) && likely(ioq_flags & IOQ_FLAG_XTENDQ)) { uv = IOQV(xioq->xdrs[0].x_base); if (xioq->ioq_uv.uvq_fetch) { /* more of the same kind */ struct poolq_entry *have = xioq->ioq_uv.uvq_fetch(xioq, uv->u.uio_p1, "next buffer", 1, IOQ_FLAG_NONE); /* poolq_entry is the top element of xdr_ioq_uv */ uv = IOQ_(have); assert((void *)uv == (void *)have); } else if (ioq_flags & IOQ_FLAG_BALLOC) { /* XXX workaround for lack of segmented buffer * interfaces in some callers (e.g, GSS_WRAP) */ if (uv->u.uio_flags & UIO_FLAG_REALLOC) { void *base; size_t size = ioquv_size(uv); size_t delta = xdr_tail_inline(xioq->xdrs); /* bail if we have reached max bufsz */ if (size >= xioq->ioq_uv.max_bsize) return (NULL); /* backtrack */ xioq->ioq_uv.plength -= len; assert(uv->u.uio_flags & UIO_FLAG_FREE); base = mem_alloc(xioq->ioq_uv.max_bsize); memcpy(base, uv->v.vio_head, len); mem_free(uv->v.vio_base, size); uv->v.vio_base = uv->v.vio_head = base + 0; uv->v.vio_tail = base + len; uv->v.vio_wrap = base + xioq->ioq_uv.max_bsize; xioq->xdrs[0].x_v = uv->v; xioq->xdrs[0].x_private = uv->v.vio_tail - delta; return (uv); } uv = xdr_ioq_uv_create(xioq->ioq_uv.min_bsize, UIO_FLAG_FREE); } else { /* XXX empty buffer slot (not supported for now) */ uv = xdr_ioq_uv_create(0, UIO_FLAG_NONE); } } if (uv) { if (!xioq->ioq_uv.uvq_fetch) { /* new xdr_ioq_uv */ (xioq->ioq_uv.uvqh.qcount)++; TAILQ_INSERT_TAIL(&xioq->ioq_uv.uvqh.qh, &uv->uvq, q); } /* advance iterator */ xioq->xdrs[0].x_private = uv->v.vio_head; xioq->xdrs[0].x_base = &uv->v; xioq->xdrs[0].x_v = uv->v; (xioq->ioq_uv.pcount)++; /* xioq->ioq_uv.plength is unchanged (calculated above) */ } return (uv); } static bool xdr_ioq_getlong(XDR *xdrs, long *lp) { struct xdr_ioq_uv *uv; void *future = xdrs->x_private + sizeof(uint32_t); while (future > xdrs->x_v.vio_tail) { if (unlikely(xdrs->x_private != xdrs->x_v.vio_tail)) { /* FIXME: insufficient data or unaligned? stop! */ __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() x_private != x_v.vio_tail\n", __func__); return (false); } uv = xdr_ioq_uv_next(XIOQ(xdrs), IOQ_FLAG_NONE); if (!uv) { return (false); } /* fill pointer has changed */ future = xdrs->x_private + sizeof(uint32_t); } *lp = (long)ntohl(*((uint32_t *) (xdrs->x_private))); xdrs->x_private = future; return (true); } static bool xdr_ioq_putlong(XDR *xdrs, const long *lp) { struct xdr_ioq_uv *uv; void *future = xdrs->x_private + sizeof(uint32_t); while (future > xdrs->x_v.vio_wrap) { /* advance fill pointer, skipping unaligned */ uv = xdr_ioq_uv_next(XIOQ(xdrs), IOQ_FLAG_XTENDQ | IOQ_FLAG_BALLOC); if (!uv) { return (false); } /* fill pointer has changed */ future = xdrs->x_private + sizeof(uint32_t); } *((int32_t *) (xdrs->x_private)) = (int32_t) htonl((int32_t) (*lp)); xdrs->x_private = future; return (true); } /* in glibc 2.14+ x86_64, memcpy no longer tries to handle overlapping areas, * see Fedora Bug 691336 (NOTABUG); we dont permit overlapping segments, * so memcpy may be a small win over memmove. */ static bool xdr_ioq_getbytes(XDR *xdrs, char *addr, u_int len) { struct xdr_ioq_uv *uv; ssize_t delta; while (len > 0 && XIOQ(xdrs)->ioq_uv.pcount < XIOQ(xdrs)->ioq_uv.uvqh.qcount) { delta = (uintptr_t)xdrs->x_v.vio_tail - (uintptr_t)xdrs->x_private; if (unlikely(delta > len)) { delta = len; } else if (unlikely(!delta)) { /* advance fill pointer */ uv = xdr_ioq_uv_next(XIOQ(xdrs), IOQ_FLAG_NONE); if (!uv) { return (false); } continue; } memcpy(addr, xdrs->x_private, delta); xdrs->x_private += delta; addr += delta; len -= delta; } /* assert(len == 0); */ return (true); } static bool xdr_ioq_putbytes(XDR *xdrs, const char *addr, u_int len) { struct xdr_ioq_uv *uv; ssize_t delta; while (len > 0) { delta = (uintptr_t)xdrs->x_v.vio_wrap - (uintptr_t)xdrs->x_private; if (unlikely(delta > len)) { delta = len; } else if (!delta) { /* advance fill pointer */ uv = xdr_ioq_uv_next(XIOQ(xdrs), IOQ_FLAG_XTENDQ | IOQ_FLAG_BALLOC); if (!uv) { return (false); } continue; } memcpy(xdrs->x_private, addr, delta); xdrs->x_private += delta; addr += delta; len -= delta; } return (true); } /* Get buffers from the queue. */ static bool xdr_ioq_getbufs(XDR *xdrs, xdr_uio *uio, u_int flags) { /* XXX finalize */ #if 0 struct xdr_ioq_uv *uv; ssize_t delta; int ix; /* allocate sufficient slots to empty the queue, else MAX */ uio->xbs_cnt = XIOQ(xdrs)->ioq_uv.uvqh.qsize - XIOQ(xdrs)->ioq_uv.pcount; if (uio->xbs_cnt > VREC_MAXBUFS) { uio->xbs_cnt = VREC_MAXBUFS; } /* fail if no segments available */ if (unlikely(! uio->xbs_cnt)) return (FALSE); uio->xbs_buf = mem_alloc(uio->xbs_cnt); uio->xbs_resid = 0; ix = 0; /* re-consuming bytes in a stream (after SETPOS/rewind) */ while (len > 0 && XIOQ(xdrs)->ioq_uv.pcount < XIOQ(xdrs)->ioq_uv.uvqh.qcount) { delta = (uintptr_t)XDR_VIO(xioq->xdrs)->vio_tail - (uintptr_t)xdrs->x_private; if (unlikely(delta > len)) { delta = len; } else if (unlikely(!delta)) { uv = xdr_ioq_uv_next(XIOQ(xdrs), IOQ_FLAG_NONE); if (!uv) return (false); continue; } (uio->xbs_buf[ix]).xb_p1 = uv; uv->u.uio_references)++; (uio->xbs_buf[ix]).xb_base = xdrs->x_private; XIOQ(xdrs)->ioq_uv.plength += delta; xdrs->x_private += delta; len -= delta; } #endif /* 0 */ /* assert(len == 0); */ return (TRUE); } /* Post buffers on the queue, or, if indicated in flags, return buffers * referenced with getbufs. */ static bool xdr_ioq_putbufs(XDR *xdrs, xdr_uio *uio, u_int flags) { struct xdr_ioq_uv *uv; xdr_vio *v; int ix; for (ix = 0; ix < uio->uio_count; ++ix) { /* advance fill pointer, do not allocate buffers, refs =1 */ if (!(flags & IOQ_FLAG_XTENDQ)) return (FALSE); uv = xdr_ioq_uv_next(XIOQ(xdrs), flags); if (!uv) return (FALSE); v = &(uio->uio_vio[ix]); uv->u.uio_flags = UIO_FLAG_NONE; /* !RECLAIM */ uv->v = *v; #if 0 Saved for later golden buttery results -- Matt if (flags & XDR_PUTBUFS_FLAG_BRELE) { /* the caller is returning buffers */ for (ix = 0; ix < uio->xbs_cnt; ++ix) { uv = (struct xdr_ioq_uv *)(uio->xbs_buf[ix]).xb_p1; xdr_ioq_uv_release(uv); } mem_free(uio->xbs_buf, 0); break; } else { for (ix = 0; ix < uio->xbs_cnt; ++ix) { /* advance fill pointer, do not allocate buffers */ *uv = xdr_ioq_uv_next(XIOQ(xdrs), IOQ_FLAG_XTENDQ); if (!uv) return (false); xbuf = &(uio->xbs_buf[ix]); XIOQ(xdrs)->ioq_uv.plength += xbuf->xb_len; uv->u.uio_flags = UIO_FLAG_NONE; /* !RECLAIM */ uv->u.uio_references = (xbuf->xb_flags & UIO_FLAG_GIFT) ? 0 : 1; uv->v.vio_base = xbuf->xb_base; uv->v.vio_wrap = xbuf->xb_len; uv->v.vio_tail = xbuf->xb_len; uv->v.vio_head = 0; } } #endif /* save original buffer sequence for rele */ if (ix == 0) { uv->u.uio_refer = uio; (uio->uio_references)++; } } return (TRUE); } /* * Get read/insert or fill position. * * Update the logical and physical offsets and lengths, * based upon the most recent position information. * All such updates are consolidated here and xdr_ioq_uv_next, * reducing computations in the get/put/inline routines. */ static u_int xdr_ioq_getpos(XDR *xdrs) { /* update the most recent data length, just in case */ xdr_tail_update(xdrs); return (XIOQ(xdrs)->ioq_uv.plength + ((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_v.vio_head)); } /* * Set read/insert or fill position. * * Update the logical and physical offsets and lengths, * based upon the most recent position information. * All such updates are consolidated here and xdr_ioq_uv_next, * reducing computations in the get/put/inline routines. */ static bool xdr_ioq_setpos(XDR *xdrs, u_int pos) { struct poolq_entry *have; /* update the most recent data length, just in case */ xdr_tail_update(xdrs); XIOQ(xdrs)->ioq_uv.plength = XIOQ(xdrs)->ioq_uv.pcount = 0; TAILQ_FOREACH(have, &(XIOQ(xdrs)->ioq_uv.uvqh.qh), q) { struct xdr_ioq_uv *uv = IOQ_(have); u_int len = ioquv_length(uv); u_int full = (uintptr_t)xdrs->x_v.vio_wrap - (uintptr_t)xdrs->x_v.vio_head; if (pos <= full) { /* allow up to the end of the buffer, * assuming next operation will extend. */ xdrs->x_private = uv->v.vio_head + pos; xdrs->x_base = &uv->v; xdrs->x_v = uv->v; return (true); } pos -= len; XIOQ(xdrs)->ioq_uv.plength += len; XIOQ(xdrs)->ioq_uv.pcount++; } return (false); } static int32_t * xdr_ioq_inline(XDR *xdrs, u_int len) { /* bugfix: return fill pointer, not head! */ int32_t *buf = (int32_t *)xdrs->x_private; void *future = xdrs->x_private + len; /* bugfix: do not move fill position beyond tail or wrap */ switch (xdrs->x_op) { case XDR_ENCODE: if (future <= xdrs->x_v.vio_wrap) { /* bugfix: do not move head! */ xdrs->x_private = future; /* bugfix: do not move tail beyond pfoff or wrap! */ xdr_tail_update(xdrs); return (buf); } break; case XDR_DECODE: /* re-consuming bytes in a stream * (after SETPOS/rewind) */ if (future <= xdrs->x_v.vio_tail) { /* bugfix: do not move head! */ xdrs->x_private = future; /* bugfix: do not move tail! */ return (buf); } break; default: abort(); break; }; return (NULL); } void xdr_ioq_release(struct poolq_head *ioqh) { struct poolq_entry *have = TAILQ_FIRST(&ioqh->qh); /* release queued buffers */ while (have) { struct poolq_entry *next = TAILQ_NEXT(have, q); TAILQ_REMOVE(&ioqh->qh, have, q); (ioqh->qcount)--; xdr_ioq_uv_release(IOQ_(have)); have = next; } assert(ioqh->qcount == 0); } void xdr_ioq_destroy(struct xdr_ioq *xioq, size_t qsize) { xdr_ioq_release(&xioq->ioq_uv.uvqh); if (xioq->ioq_pool) { xdr_ioq_uv_recycle(xioq->ioq_pool, &xioq->ioq_s); } else { poolq_head_destroy(&xioq->ioq_uv.uvqh); mem_free(xioq, qsize); } } static void xdr_ioq_destroy_internal(XDR *xdrs) { xdr_ioq_destroy(XIOQ(xdrs), sizeof(struct xdr_ioq)); } void xdr_ioq_destroy_pool(struct poolq_head *ioqh) { struct poolq_entry *have = TAILQ_FIRST(&ioqh->qh); while (have) { struct poolq_entry *next = TAILQ_NEXT(have, q); TAILQ_REMOVE(&ioqh->qh, have, q); (ioqh->qcount)--; _IOQ(have)->ioq_pool = NULL; xdr_ioq_destroy(_IOQ(have), have->qsize); have = next; } assert(ioqh->qcount == 0); poolq_head_destroy(ioqh); } static bool xdr_ioq_control(XDR *xdrs, /* const */ int rq, void *in) { return (true); } static bool xdr_ioq_noop(void) { return (false); } const struct xdr_ops xdr_ioq_ops = { xdr_ioq_getlong, xdr_ioq_putlong, xdr_ioq_getbytes, xdr_ioq_putbytes, xdr_ioq_getpos, xdr_ioq_setpos, xdr_ioq_inline, xdr_ioq_destroy_internal, xdr_ioq_control, xdr_ioq_getbufs, xdr_ioq_putbufs }; ntirpc-1.3.1/src/xdr_mem.c000066400000000000000000000156541261345040100154100ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * 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 #if !defined(_WIN32) #include #endif #include #include #include #include #include "un-namespace.h" typedef bool (*dummyfunc3)(XDR *, int, void *); typedef bool (*dummy_getbufs)(XDR *, xdr_uio *, u_int); typedef bool (*dummy_putbufs)(XDR *, xdr_uio *, u_int); static const struct xdr_ops xdrmem_ops_aligned; static const struct xdr_ops xdrmem_ops_unaligned; /* * The procedure xdrmem_create initializes a stream descriptor for a * memory buffer. */ void xdrmem_ncreate(XDR *xdrs, char *addr, u_int size, enum xdr_op op) { xdrs->x_op = op; if ((uintptr_t)addr & (sizeof(int32_t) - 1)) { xdrs->x_ops = &xdrmem_ops_unaligned; } else { xdrs->x_ops = &xdrmem_ops_aligned; xdrs->x_flags = XDR_FLAG_VIO; } xdrs->x_lib[0] = NULL; xdrs->x_lib[1] = NULL; xdrs->x_public = NULL; xdrs->x_private = addr; xdrs->x_v.vio_base = addr; xdrs->x_v.vio_head = addr; switch (op) { case XDR_ENCODE: xdrs->x_v.vio_tail = addr; break; case XDR_DECODE: xdrs->x_v.vio_tail = addr + size; break; default: abort(); break; }; xdrs->x_v.vio_wrap = addr + size; xdrs->x_base = &xdrs->x_v; } static bool xdrmem_getlong_aligned(XDR *xdrs, long *lp) { void *future = xdrs->x_private + sizeof(uint32_t); if (future > xdrs->x_v.vio_tail) return (false); *lp = ntohl(*(u_int32_t *) xdrs->x_private); xdrs->x_private = future; return (true); } static bool xdrmem_putlong_aligned(XDR *xdrs, const long *lp) { void *future = xdrs->x_private + sizeof(uint32_t); if (future > xdrs->x_v.vio_wrap) return (false); *(u_int32_t *) xdrs->x_private = htonl((u_int32_t) *lp); xdrs->x_private = future; return (true); } /* in glibc 2.14+ x86_64, memcpy no longer tries to handle overlapping areas, * see Fedora Bug 691336 (NOTABUG); we dont permit overlapping segments, * so memcpy may be a small win over memmove. */ static bool xdrmem_getlong_unaligned(XDR *xdrs, long *lp) { u_int32_t l; void *future = xdrs->x_private + sizeof(uint32_t); if (future > xdrs->x_v.vio_tail) return (false); memcpy(&l, xdrs->x_private, sizeof(int32_t)); *lp = ntohl(l); xdrs->x_private = future; return (true); } static bool xdrmem_putlong_unaligned(XDR *xdrs, const long *lp) { u_int32_t l; void *future = xdrs->x_private + sizeof(uint32_t); if (future > xdrs->x_v.vio_wrap) return (false); l = htonl((u_int32_t) *lp); memcpy(xdrs->x_private, &l, sizeof(int32_t)); xdrs->x_private = future; return (true); } static bool xdrmem_getbytes(XDR *xdrs, char *addr, u_int len) { void *future = xdrs->x_private + len; if (future > xdrs->x_v.vio_tail) return (false); memmove(addr, xdrs->x_private, len); xdrs->x_private = future; return (true); } static bool xdrmem_putbytes(XDR *xdrs, const char *addr, u_int len) { void *future = xdrs->x_private + len; if (future > xdrs->x_v.vio_wrap) return (false); memmove(xdrs->x_private, addr, len); xdrs->x_private = future; return (true); } static u_int xdrmem_getpos(XDR *xdrs) { /* update the most recent data length, just in case */ xdr_tail_update(xdrs); return ((uintptr_t)xdrs->x_private - (uintptr_t)xdrs->x_v.vio_head); } static bool xdrmem_setpos(XDR *xdrs, u_int pos) { void *newaddr = xdrs->x_v.vio_head + pos; /* update the most recent data length, just in case */ xdr_tail_update(xdrs); if (newaddr > xdrs->x_v.vio_wrap) return (false); xdrs->x_private = newaddr; return (true); } static int32_t * xdrmem_inline_aligned(XDR *xdrs, u_int len) { int32_t *buf = (int32_t *)xdrs->x_private; void *future = xdrs->x_private + len; switch (xdrs->x_op) { case XDR_ENCODE: if (future <= xdrs->x_v.vio_wrap) { xdrs->x_private = future; xdr_tail_update(xdrs); /* temporarily backward compatible */ xdrs->x_handy = xdrs->x_v.vio_wrap - xdrs->x_private; return (buf); } break; case XDR_DECODE: /* re-consuming bytes in a stream * (after SETPOS/rewind) */ if (future <= xdrs->x_v.vio_tail) { xdrs->x_private = future; /* temporarily backward compatible */ xdrs->x_handy = xdrs->x_v.vio_tail - xdrs->x_private; return (buf); } break; default: abort(); break; }; return (NULL); } /* ARGSUSED */ static int32_t * xdrmem_inline_unaligned(XDR *xdrs, u_int len) { return (NULL); } /* ARGSUSED */ static void xdrmem_destroy(XDR *xdrs) { } static bool xdrmem_noop(void) { return (false); } 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, (dummyfunc3) xdrmem_noop, /* x_control */ (dummy_getbufs) xdrmem_noop, /* x_getbufs */ (dummy_putbufs) xdrmem_noop, /* x_putbufs */ }; 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, (dummyfunc3) xdrmem_noop, /* x_control */ (dummy_getbufs) xdrmem_noop, /* x_getbufs */ (dummy_putbufs) xdrmem_noop, /* x_putbufs */ }; ntirpc-1.3.1/src/xdr_rdma.c000066400000000000000000001177651261345040100155630ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * Dominique Martinet * contributeur : William Allen Simpson * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include "namespace.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "un-namespace.h" #include "rpc_rdma.h" /* NOTA BENE: as in xdr_ioq.c, although indications of failure are returned, * they are rarely checked. */ #define CALLQ_SIZE (2) #define RFC5666_BUFFER_SIZE (1024) static const struct xdr_ops xdr_rdma_ops_aligned; static const struct xdr_ops xdr_rdma_ops_unaligned; #define x_xprt(xdrs) ((RDMAXPRT *)((xdrs)->x_lib[1])) //#define rpcrdma_dump_msg(data, comment, xid) #ifndef rpcrdma_dump_msg #define DUMP_BYTES_PER_GROUP (4) #define DUMP_GROUPS_PER_LINE (4) #define DUMP_BYTES_PER_LINE (DUMP_BYTES_PER_GROUP * DUMP_GROUPS_PER_LINE) static void rpcrdma_dump_msg(struct xdr_ioq_uv *data, char *comment, uint32_t xid) { char *buffer; uint8_t *datum = data->v.vio_head; int sized = ioquv_length(data); int buffered = (((sized / DUMP_BYTES_PER_LINE) + 1 /*partial line*/) * (12 /* heading */ + (((DUMP_BYTES_PER_GROUP * 2 /*%02X*/) + 1 /*' '*/) * DUMP_GROUPS_PER_LINE))) + 1 /*'\0'*/; int i = 0; int m = 0; xid = ntohl(xid); if (sized == 0) { __warnx(TIRPC_DEBUG_FLAG_XDR, "rpcrdma 0x%" PRIx32 "(%" PRIu32 ") %s?", xid, xid, comment); return; } buffer = (char *)mem_alloc(buffered); while (sized > i) { int j = sized - i; int k = j < DUMP_BYTES_PER_LINE ? j : DUMP_BYTES_PER_LINE; int l = 0; int r = sprintf(&buffer[m], "\n%10d:", i); /* heading */ if (r < 0) goto quit; m += r; for (; l < k; l++) { if (l % DUMP_BYTES_PER_GROUP == 0) buffer[m++] = ' '; r = sprintf(&buffer[m], "%02X", datum[i++]); if (r < 0) goto quit; m += r; } } quit: buffer[m] = '\0'; /* in case of error */ __warnx(TIRPC_DEBUG_FLAG_XDR, "rpcrdma 0x%" PRIx32 "(%" PRIu32 ") %s:%s\n", xid, xid, comment, buffer); mem_free(buffer, buffered); } #endif /* rpcrdma_dump_msg */ /* ** match RFC-5666 as cloely as possible */ struct xdr_rdma_segment { uint32_t handle; /* Registered memory handle */ uint32_t length; /* Length of the chunk in bytes */ uint64_t offset; /* Chunk virtual address or offset */ }; struct xdr_read_list { uint32_t present; /* 1 indicates presence */ uint32_t position; /* Position in XDR stream */ struct xdr_rdma_segment target; }; struct xdr_write_chunk { struct xdr_rdma_segment target; }; struct xdr_write_list { uint32_t present; /* 1 indicates presence */ uint32_t elements; /* Number of array elements */ struct xdr_write_chunk entry[0]; }; struct rpc_rdma_header { uint32_t rdma_reads; uint32_t rdma_writes; uint32_t rdma_reply; /* rpc body follows */ }; struct rpc_rdma_header_nomsg { uint32_t rdma_reads; uint32_t rdma_writes; uint32_t rdma_reply; }; struct rpc_rdma_header_padded { uint32_t rdma_align; /* Padding alignment */ uint32_t rdma_thresh; /* Padding threshold */ uint32_t rdma_reads; uint32_t rdma_writes; uint32_t rdma_reply; /* rpc body follows */ }; enum rdma_proc { RDMA_MSG = 0, /* An RPC call or reply msg */ RDMA_NOMSG = 1, /* An RPC call or reply msg - separate body */ RDMA_MSGP = 2, /* An RPC call or reply msg with padding */ RDMA_DONE = 3, /* Client signals reply completion */ RDMA_ERROR = 4 /* An RPC RDMA encoding error */ }; struct rdma_msg { uint32_t rdma_xid; /* Mirrors the RPC header xid */ uint32_t rdma_vers; /* Version of this protocol */ uint32_t rdma_credit; /* Buffers requested/granted */ uint32_t rdma_type; /* Type of message (enum rdma_proc) */ union { struct rpc_rdma_header rdma_msg; struct rpc_rdma_header_nomsg rdma_nomsg; struct rpc_rdma_header_padded rdma_padmsg; } rdma_body; }; /***********************************/ /****** Utilities for buffers ******/ /***********************************/ static void xdr_rdma_chunk_in(struct poolq_entry *have, u_int k, u_int m, u_int sized) { /* final buffer limited to truncated length */ IOQ_(have)->v.vio_head = IOQ_(have)->v.vio_base; IOQ_(have)->v.vio_tail = (char *)IOQ_(have)->v.vio_base + m; IOQ_(have)->v.vio_wrap = (char *)IOQ_(have)->v.vio_base + sized; while (0 < --k && NULL != (have = TAILQ_PREV(have, q_head, q))) { /* restore defaults after previous usage */ IOQ_(have)->v.vio_head = IOQ_(have)->v.vio_base; IOQ_(have)->v.vio_tail = IOQ_(have)->v.vio_wrap = (char *)IOQ_(have)->v.vio_base + sized; } } static void xdr_rdma_chunk_out(struct poolq_entry *have, u_int k, u_int m, u_int sized) { /* final buffer limited to truncated length */ IOQ_(have)->v.vio_head = IOQ_(have)->v.vio_tail = IOQ_(have)->v.vio_base; IOQ_(have)->v.vio_wrap = (char *)IOQ_(have)->v.vio_base + m; while (0 < --k && NULL != (have = TAILQ_PREV(have, q_head, q))) { /* restore defaults after previous usage */ IOQ_(have)->v.vio_head = IOQ_(have)->v.vio_tail = IOQ_(have)->v.vio_base; IOQ_(have)->v.vio_wrap = (char *)IOQ_(have)->v.vio_base + sized; } } static uint32_t xdr_rdma_chunk_fetch(struct xdr_ioq *xioq, struct poolq_head *ioqh, char *comment, u_int length, u_int sized, u_int max_sge, void (*setup)(struct poolq_entry *, u_int, u_int, u_int)) { struct poolq_entry *have; uint32_t k = length / sized; uint32_t m = length % sized; if (m) { /* need fractional buffer */ k++; } else { /* have full-sized buffer */ m = sized; } /* ensure never asking for more buffers than allowed */ if (k > max_sge) { __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() requested chunk %" PRIu32 " is too long (%" PRIu32 ">%" PRIu32 ")", __func__, length, k, max_sge); k = max_sge; m = sized; } /* ensure we can get all of our buffers without deadlock * (wait for them all to be appended) */ have = xdr_ioq_uv_fetch(xioq, ioqh, comment, k, IOQ_FLAG_NONE); (*setup)(have, k, m, sized); return k; } /***********************/ /****** Callbacks ******/ /***********************/ /* note parameter order matching svc.h svc_req callbacks */ static void xdr_rdma_respond_callback(struct rpc_rdma_cbc *cbc, RDMAXPRT *xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p\n", __func__, xprt, xprt->state, cbc); mutex_lock(&xprt->waitq.ioq_uv.uvqh.qmutex); TAILQ_REMOVE(&xprt->waitq.ioq_uv.uvqh.qh, &cbc->workq.ioq_s, q); (xprt->waitq.ioq_uv.uvqh.qcount)--; mutex_unlock(&xprt->waitq.ioq_uv.uvqh.qmutex); xdr_ioq_destroy(&cbc->workq, sizeof(*cbc)); } static void xdr_rdma_destroy_callback(struct rpc_rdma_cbc *cbc, RDMAXPRT *xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p\n", __func__, xprt, xprt->state, cbc); mutex_lock(&xprt->waitq.ioq_uv.uvqh.qmutex); TAILQ_REMOVE(&xprt->waitq.ioq_uv.uvqh.qh, &cbc->workq.ioq_s, q); (xprt->waitq.ioq_uv.uvqh.qcount)--; mutex_unlock(&xprt->waitq.ioq_uv.uvqh.qmutex); xdr_ioq_destroy(&cbc->workq, sizeof(*cbc)); } /** * xdr_rdma_wait_callback: send/recv callback that just unlocks a mutex. * */ static void xdr_rdma_wait_callback(struct rpc_rdma_cbc *cbc, RDMAXPRT *xprt) { mutex_t *lock = cbc->callback_arg; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p\n", __func__, xprt, xprt->state, cbc); mutex_unlock(lock); } /** * xdr_rdma_warn_callback: send/recv callback that just unlocks a mutex. * */ static void xdr_rdma_warn_callback(struct rpc_rdma_cbc *cbc, RDMAXPRT *xprt) { mutex_t *lock = cbc->callback_arg; __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p\n", __func__, xprt, xprt->state, cbc); mutex_unlock(lock); } /***********************************/ /***** Utilities from Mooshika *****/ /***********************************/ /** * xdr_rdma_post_recv_n: Post receive chunk(s). * * Need to post recv buffers before the opposite side tries to send anything! * @param[IN] xprt * @param[INOUT] cbc CallBack Context xdr_ioq and xdr_ioq_uv(s) * @param[IN] sge scatter/gather elements to register * * Must be set in advance: * @param[IN] positive_cb function that'll be called when done * @param[IN] negative_cb function that'll be called on error * @param[IN] callback_arg argument to give to the callback * @return 0 on success, the value of errno on error */ static int xdr_rdma_post_recv_n(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge) { struct poolq_entry *have = TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh); int i = 0; int ret; if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() xprt state missing", __func__); return EINVAL; } switch (xprt->state) { case RDMAXS_CONNECTED: case RDMAXS_ROUTE_RESOLVED: case RDMAXS_CONNECT_REQUEST: __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() %p[%u] cbc %p posting recv", __func__, xprt, xprt->state, cbc); break; default: __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() %p[%u] != " "connect request, connected, or resolved", __func__, xprt, xprt->state); return EINVAL; } while (have && i < sge) { struct ibv_mr *mr = IOQ_(have)->u.uio_p2; if (!mr) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Missing mr: Not requesting.", __func__); return EINVAL; } cbc->sg_list[i].addr = (uintptr_t)(IOQ_(have)->v.vio_head); cbc->sg_list[i].length = ioquv_length(IOQ_(have)); __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() %" PRIx64 ", %" PRIu32 " [%" PRIx32 "]", __func__, cbc->sg_list[i].addr, cbc->sg_list[i].length, mr->lkey); cbc->sg_list[i++].lkey = mr->lkey; have = TAILQ_NEXT(have, q); } cbc->wr.rwr.next = NULL; cbc->wr.rwr.wr_id = (uintptr_t)cbc; cbc->wr.rwr.sg_list = cbc->sg_list; cbc->wr.rwr.num_sge = i; if (xprt->srq) ret = ibv_post_srq_recv(xprt->srq, &cbc->wr.rwr, &xprt->bad_recv_wr); else ret = ibv_post_recv(xprt->qp, &cbc->wr.rwr, &xprt->bad_recv_wr); if (ret) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p ibv_post_recv failed: %s (%d)", __func__, xprt, xprt->state, cbc, strerror(ret), ret); return ret; // FIXME np_uerror(ret) } return 0; } /** * xdr_rdma_post_recv_cb: Post receive chunk(s) with standard callbacks. * * Need to post recv buffers before the opposite side tries to send anything! * @param[IN] xprt * @param[INOUT] cbc CallBack Context xdr_ioq and xdr_ioq_uv(s) * @param[IN] sge scatter/gather elements to register * * @return 0 on success, the value of errno on error */ static int xdr_rdma_post_recv_cb(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge) { cbc->positive_cb = (rpc_rdma_callback_t)xprt->xa->request_cb; cbc->negative_cb = xdr_rdma_destroy_callback; cbc->callback_arg = NULL; return xdr_rdma_post_recv_n(xprt, cbc, sge); } /** * Post a work chunk. * * @param[IN] xprt * @param[IN] cbc CallBack Context xdr_ioq and xdr_ioq_uv(s) * @param[IN] sge scatter/gather elements to send * @param[IN] rs remote segment * @param[IN] opcode * * Must be set in advance: * @param[IN] positive_cb function that'll be called when done * @param[IN] negative_cb function that'll be called on error * @param[IN] callback_arg argument to give to the callback * * @return 0 on success, the value of errno on error */ static int xdr_rdma_post_send_n(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge, struct xdr_rdma_segment *rs, enum ibv_wr_opcode opcode) { struct poolq_entry *have = TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh); uint32_t totalsize = 0; int i = 0; int ret; if (!xprt) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() xprt state missing", __func__); return EINVAL; } switch (xprt->state) { case RDMAXS_CONNECTED: __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() %p[%u] cbc %p posting a send with op %d", __func__, xprt, xprt->state, cbc, opcode); break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] != " "connected", __func__, xprt, xprt->state); return EINVAL; } // opcode-specific checks: switch (opcode) { case IBV_WR_RDMA_WRITE: case IBV_WR_RDMA_READ: if (!rs) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Cannot do rdma without a remote location!", __func__); return EINVAL; } break; case IBV_WR_SEND: case IBV_WR_SEND_WITH_IMM: break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() unsupported op code: %d", __func__, opcode); return EINVAL; } while (have && i < sge) { struct ibv_mr *mr = IOQ_(have)->u.uio_p2; uint32_t length = ioquv_length(IOQ_(have)); if (!length) { __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() Empty buffer: Not sending.", __func__); break; } if (!mr) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() Missing mr: Not sending.", __func__); return EINVAL; } cbc->sg_list[i].addr = (uintptr_t)(IOQ_(have)->v.vio_head); cbc->sg_list[i].length = length; __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() %" PRIx64 ", %" PRIu32 " [%" PRIx32 "]", __func__, cbc->sg_list[i].addr, cbc->sg_list[i].length, mr->lkey); cbc->sg_list[i++].lkey = mr->lkey; totalsize += length; have = TAILQ_NEXT(have, q); } cbc->wr.wwr.next = NULL; cbc->wr.wwr.wr_id = (uint64_t)cbc; cbc->wr.wwr.opcode = opcode; //FIXME cbc->wr.wwr.imm_data = htonl(data->imm_data); cbc->wr.wwr.send_flags = IBV_SEND_SIGNALED; cbc->wr.wwr.sg_list = cbc->sg_list; cbc->wr.wwr.num_sge = i; if (rs) { cbc->wr.wwr.wr.rdma.rkey = ntohl(rs->handle); cbc->wr.wwr.wr.rdma.remote_addr = xdr_decode_hyper(&rs->offset); if (ntohl(rs->length) < totalsize) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() chunk bigger than the remote buffer " "(%" PRIu32 ">%" PRIu32 ")", __func__, totalsize, ntohl(rs->length)); return EMSGSIZE; } else { /* save in place for posterity */ rs->length = htonl(totalsize); } } ret = ibv_post_send(xprt->qp, &cbc->wr.wwr, &xprt->bad_send_wr); if (ret) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] cbc %p ibv_post_send failed: %s (%d)", __func__, xprt, xprt->state, cbc, strerror(ret), ret); return ret; // FIXME np_uerror(ret) } return 0; } /** * Post a work chunk with standard callbacks. * * @param[IN] xprt * @param[IN] cbc CallBack Context xdr_ioq and xdr_ioq_uv(s) * @param[IN] sge scatter/gather elements to send * * @return 0 on success, the value of errno on error */ static inline int xdr_rdma_post_send_cb(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge) { cbc->positive_cb = xdr_rdma_respond_callback; cbc->negative_cb = xdr_rdma_destroy_callback; cbc->callback_arg = cbc; return xdr_rdma_post_send_n(xprt, cbc, sge, NULL, IBV_WR_SEND); } #ifdef UNUSED /** * Post a receive chunk and waits for _that one and not any other_ to be filled. * Generally a bad idea to use that one unless only that one is used. * * @param[IN] xprt * @param[INOUT] cbc CallBack Context xdr_ioq and xdr_ioq_uv(s) * * @return 0 on success, the value of errno on error */ static int xdr_rdma_wait_recv_n(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc) { mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int ret; cbc->positive_cb = xdr_rdma_wait_callback; cbc->negative_cb = xdr_rdma_warn_callback; cbc->callback_arg = &lock; mutex_lock(&lock); ret = xdr_rdma_post_recv_n(xprt, cbc); if (!ret) { mutex_lock(&lock); mutex_unlock(&lock); } mutex_destroy(&lock); return ret; } /** * Post a send chunk and waits for that one to be completely sent * @param[IN] xprt * @param[IN] cbc CallBack Context xdr_ioq and xdr_ioq_uv(s) * @param[IN] sge scatter/gather elements to send * * @return 0 on success, the value of errno on error */ static int xdr_rdma_wait_send_n(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge) { mutex_t lock = PTHREAD_MUTEX_INITIALIZER; int ret; cbc->positive_cb = xdr_rdma_wait_callback; cbc->negative_cb = xdr_rdma_warn_callback; cbc->callback_arg = &lock; mutex_lock(&lock); ret = xdr_rdma_post_send_n(xprt, cbc, sge, NULL, IBV_WR_SEND); if (!ret) { mutex_lock(&lock); mutex_unlock(&lock); } mutex_destroy(&lock); return ret; } static inline int xdr_rdma_post_read_cb(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge, struct xdr_rdma_segment *rs) { cbc->positive_cb = xdr_rdma_respond_callback; cbc->negative_cb = xdr_rdma_destroy_callback; cbc->callback_arg = cbc; return xdr_rdma_post_send_n(xprt, cbc, sge, rs, IBV_WR_RDMA_READ); } static inline int xdr_rdma_post_write_cb(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge, struct xdr_rdma_segment *rs) { cbc->positive_cb = xdr_rdma_respond_callback; cbc->negative_cb = xdr_rdma_destroy_callback; cbc->callback_arg = cbc; return xdr_rdma_post_send_n(xprt, cbc, sge, rs, IBV_WR_RDMA_WRITE); } #endif /* UNUSED */ static int xdr_rdma_wait_read_cb(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge, struct xdr_rdma_segment *rs) { mutex_t lock = MUTEX_INITIALIZER; int ret; cbc->positive_cb = xdr_rdma_wait_callback; cbc->negative_cb = xdr_rdma_warn_callback; cbc->callback_arg = &lock; mutex_lock(&lock); ret = xdr_rdma_post_send_n(xprt, cbc, sge, rs, IBV_WR_RDMA_READ); if (!ret) { mutex_lock(&lock); mutex_unlock(&lock); } mutex_destroy(&lock); return ret; } static int xdr_rdma_wait_write_cb(RDMAXPRT *xprt, struct rpc_rdma_cbc *cbc, int sge, struct xdr_rdma_segment *rs) { mutex_t lock = MUTEX_INITIALIZER; int ret; cbc->positive_cb = xdr_rdma_wait_callback; cbc->negative_cb = xdr_rdma_warn_callback; cbc->callback_arg = &lock; mutex_lock(&lock); ret = xdr_rdma_post_send_n(xprt, cbc, sge, rs, IBV_WR_RDMA_WRITE); if (!ret) { mutex_lock(&lock); mutex_unlock(&lock); } mutex_destroy(&lock); return ret; } /***********************************/ /****** Utilities for rpcrdma ******/ /***********************************/ #define m_(ptr) ((struct rdma_msg *)ptr) #define rl(ptr) ((struct xdr_read_list*)ptr) typedef struct xdr_write_list wl_t; #define wl(ptr) ((struct xdr_write_list*)ptr) static inline void xdr_rdma_skip_read_list(uint32_t **pptr) { while (rl(*pptr)->present) { *pptr += sizeof(struct xdr_read_list) / sizeof(**pptr); } (*pptr)++; } static inline void xdr_rdma_skip_write_list(uint32_t **pptr) { if (wl(*pptr)->present) { *pptr += (sizeof(struct xdr_write_list) + sizeof(struct xdr_write_chunk) * ntohl(wl(*pptr)->elements)) / sizeof(**pptr); } (*pptr)++; } static inline void xdr_rdma_skip_reply_array(uint32_t **pptr) { if (wl(*pptr)->present) { *pptr += (sizeof(struct xdr_write_list) + sizeof(struct xdr_write_chunk) * ntohl(wl(*pptr)->elements)) / sizeof(**pptr); } else { (*pptr)++; } } static inline uint32_t * xdr_rdma_get_read_list(void *data) { return &m_(data)->rdma_body.rdma_msg.rdma_reads; } #ifdef UNUSED static inline uint32_t * xdr_rdma_get_write_array(void *data) { uint32_t *ptr = xdr_rdma_get_read_list(data); xdr_rdma_skip_read_list(&ptr); return ptr; } #endif /* UNUSED */ static inline uint32_t * xdr_rdma_get_reply_array(void *data) { uint32_t *ptr = xdr_rdma_get_read_list(data); xdr_rdma_skip_read_list(&ptr); xdr_rdma_skip_write_list(&ptr); return ptr; } static inline uint32_t * xdr_rdma_skip_header(struct rdma_msg *rmsg) { uint32_t *ptr = &rmsg->rdma_body.rdma_msg.rdma_reads; xdr_rdma_skip_read_list(&ptr); xdr_rdma_skip_write_list(&ptr); xdr_rdma_skip_reply_array(&ptr); return ptr; } static inline uintptr_t xdr_rdma_header_length(struct rdma_msg *rmsg) { uint32_t *ptr = xdr_rdma_skip_header(rmsg); return ((uintptr_t)ptr - (uintptr_t)rmsg); } #ifdef UNUSED int xdr_rdma_encode_error(struct svcxprt_rdma *xprt, struct rdma_msg *rmsgp, enum xdr_rdma_errcode err, u32 *va) { u32 *startp = va; *va++ = htonl(rmsgp->rdma_xid); *va++ = htonl(rmsgp->rdma_vers); *va++ = htonl(xprt->sc_max_requests); *va++ = htonl(RDMA_ERROR); *va++ = htonl(err); if (err == ERR_VERS) { *va++ = htonl(RPCRDMA_VERSION); *va++ = htonl(RPCRDMA_VERSION); } return (int)((unsigned long)va - (unsigned long)startp); } void xdr_rdma_encode_reply_array(wl_t *ary, int chunks) { ary->present = xdr_one; ary->elements = htonl(chunks); } void xdr_rdma_encode_array_chunk(wl_t *ary, int chunk_no, u32 handle, u64 offset, u32 write_len) { struct xdr_rdma_segment *seg = &ary->entry[chunk_no].target; seg->handle = htonl(handle); seg->length = htonl(write_len); xdr_encode_hyper((u32 *) &seg->offset, offset); } void xdr_rdma_encode_reply_header(struct svcxprt_rdma *xprt, struct rdma_msg *rdma_argp, struct rdma_msg *rdma_resp, enum rdma_proc rdma_type) { rdma_resp->rdma_xid = htonl(rdma_argp->rdma_xid); rdma_resp->rdma_vers = htonl(rdma_argp->rdma_vers); rdma_resp->rdma_credit = htonl(xprt->sc_max_requests); rdma_resp->rdma_type = htonl(rdma_type); /* Encode chunks lists */ rdma_resp->rdma_body.rm_chunks[0] = xdr_zero; rdma_resp->rdma_body.rm_chunks[1] = xdr_zero; rdma_resp->rdma_body.rm_chunks[2] = xdr_zero; } #endif /* UNUSED */ /* post recv buffers. * keep at least 2 spare waiting for calls, * the remainder can be used for incoming rdma buffers. */ static void xdr_rdma_callq(RDMAXPRT *xprt) { struct poolq_entry *have = xdr_ioq_uv_fetch(&xprt->waitq, &xprt->cbqh, "callq context", 1, IOQ_FLAG_NONE); struct rpc_rdma_cbc *cbc = (struct rpc_rdma_cbc *)(_IOQ(have)); have = xdr_ioq_uv_fetch(&cbc->workq, &xprt->inbufs.uvqh, "callq buffer", 1, IOQ_FLAG_NONE); /* input positions */ IOQ_(have)->v.vio_head = IOQ_(have)->v.vio_base; IOQ_(have)->v.vio_tail = IOQ_(have)->v.vio_wrap; IOQ_(have)->v.vio_wrap = (char *)IOQ_(have)->v.vio_base + xprt->recvsize; cbc->workq.xdrs[0].x_lib[1] = cbc->holdq.xdrs[0].x_lib[1] = xprt; xdr_rdma_post_recv_cb(xprt, cbc, 1); } /****************************/ /****** Main functions ******/ /****************************/ void xdr_rdma_destroy(XDR *xdrs) { RDMAXPRT *xprt; if (!xdrs) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no xdrs?", __func__); return; } xprt = x_xprt(xdrs); if (xprt->mr) { ibv_dereg_mr(xprt->mr); xprt->mr = NULL; } xdr_ioq_destroy_pool(&xprt->waitq.ioq_uv.uvqh); /* must be after queues, xdr_ioq_destroy() moves them here */ xdr_ioq_release(&xprt->inbufs.uvqh); poolq_head_destroy(&xprt->inbufs.uvqh); xdr_ioq_release(&xprt->outbufs.uvqh); poolq_head_destroy(&xprt->outbufs.uvqh); /* must be after pools */ if (xprt->buffer_aligned) { mem_free(xprt->buffer_aligned, xprt->buffer_total); xprt->buffer_aligned = NULL; } xdrs->x_lib[0] = NULL; xdrs->x_lib[1] = NULL; } /* * initializes a stream descriptor for a memory buffer. * * XDR has already been created and passed as arg. * * credits is the number of buffers used */ int xdr_rdma_create(XDR *xdrs, RDMAXPRT *xprt, const u_int sendsize, const u_int recvsize, const u_int flags) { uint8_t *b; long ps = sysconf(_SC_PAGESIZE); if (!xprt->pd || !xprt->pd->pd) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() %p[%u] xdr %p missing Protection Domain", __func__, xprt, xprt->state, xdrs); xdr_rdma_destroy(xdrs); return ENODEV; } /* buffer sizes MUST be page sized */ xprt->sendsize = sendsize & ~(ps - 1); xprt->sendsize = xprt->sendsize >= ps ? xprt->sendsize : ps; xprt->recvsize = recvsize & ~(ps - 1); xprt->recvsize = xprt->recvsize >= ps ? xprt->recvsize : ps; /* pre-allocated buffer_total: * the number of credits is irrelevant here. * instead, allocate buffers to match the read/write contexts. * more than one buffer can be chained to one ioq_uv head, * but never need more ioq_uv heads than buffers. */ xprt->buffer_total = recvsize * xprt->xa->rq_depth + sendsize * xprt->xa->sq_depth; xprt->buffer_aligned = mem_alloc_aligned(xprt->buffer_total, ps); if (xprt->buffer_aligned == NULL) goto err; __warnx(TIRPC_DEBUG_FLAG_RPC_RDMA, "%s() buffer_aligned at %p", __func__, xprt->buffer_aligned); /* register it in two chunks for read and write??? */ xprt->mr = ibv_reg_mr(xprt->pd->pd, xprt->buffer_aligned, xprt->buffer_total, IBV_ACCESS_LOCAL_WRITE | IBV_ACCESS_REMOTE_WRITE | IBV_ACCESS_REMOTE_READ); poolq_head_setup(&xprt->inbufs.uvqh); xprt->inbufs.min_bsize = ps; xprt->inbufs.max_bsize = xprt->recvsize; poolq_head_setup(&xprt->outbufs.uvqh); xprt->outbufs.min_bsize = ps; xprt->outbufs.max_bsize = xprt->sendsize; /* Each pre-allocated buffer has a corresponding xdr_ioq_uv, * stored on the pool queues. */ b = xprt->buffer_aligned; for (xprt->inbufs.uvqh.qcount = 0; xprt->inbufs.uvqh.qcount < xprt->xa->rq_depth; xprt->inbufs.uvqh.qcount++) { struct xdr_ioq_uv *data = xdr_ioq_uv_create(0, UIO_FLAG_BUFQ); data->v.vio_base = data->v.vio_head = data->v.vio_tail = b; data->v.vio_wrap = (char *)b + xprt->recvsize; data->u.uio_p1 = &xprt->inbufs.uvqh; data->u.uio_p2 = xprt->mr; TAILQ_INSERT_TAIL(&xprt->inbufs.uvqh.qh, &data->uvq, q); b += xprt->recvsize; } for (xprt->outbufs.uvqh.qcount = 0; xprt->outbufs.uvqh.qcount < xprt->xa->sq_depth; xprt->outbufs.uvqh.qcount++) { struct xdr_ioq_uv *data = xdr_ioq_uv_create(0, UIO_FLAG_BUFQ); data->v.vio_base = data->v.vio_head = data->v.vio_tail = b; data->v.vio_wrap = (char *)b + xprt->sendsize; data->u.uio_p1 = &xprt->outbufs.uvqh; data->u.uio_p2 = xprt->mr; TAILQ_INSERT_TAIL(&xprt->outbufs.uvqh.qh, &data->uvq, q); b += xprt->sendsize; } xdr_ioq_setup(&xprt->waitq); while (xprt->waitq.ioq_uv.uvqh.qcount < CALLQ_SIZE) { xdr_rdma_callq(xprt); } return 0; err: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() out of memory", __func__); xdr_rdma_destroy(xdrs); return ENOMEM; } /** xdr_rdma_clnt_call * * Client processes a call request * * @param[IN] xdrs cm_data * * called by clnt_rdma_call() */ bool xdr_rdma_clnt_call(XDR *xdrs, u_int32_t xid) { struct rpc_rdma_cbc *cbc = (struct rpc_rdma_cbc *)xdrs; RDMAXPRT *xprt; if (!xdrs) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no context?", __func__); return (false); } xprt = x_xprt(xdrs); /* free old buffers (should do nothing) */ xdr_ioq_release(&cbc->workq.ioq_uv.uvqh); xdr_ioq_release(&cbc->holdq.ioq_uv.uvqh); xdr_rdma_callq(xprt); /* get new buffer */ (void) xdr_ioq_uv_fetch(&cbc->holdq, &xprt->outbufs.uvqh, "call buffer", 1, IOQ_FLAG_NONE); xdr_ioq_reset(&cbc->holdq, 0); return (true); } /** xdr_rdma_clnt_reply * * Client prepares for a reply * * potential output buffers are queued in workq. * * @param[IN] xdrs cm_data * * called by clnt_rdma_call() */ bool xdr_rdma_clnt_reply(XDR *xdrs, u_int32_t xid) { struct rpc_rdma_cbc *cbc = (struct rpc_rdma_cbc *)xdrs; RDMAXPRT *xprt; struct xdr_write_list *reply_array; struct xdr_ioq_uv *work_uv; struct poolq_entry *have; if (!xdrs) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no context?", __func__); return (false); } xprt = x_xprt(xdrs); work_uv = IOQ_(TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh)); rpcrdma_dump_msg(work_uv, "creply head", htonl(xid)); reply_array = (wl_t *)xdr_rdma_get_reply_array(work_uv->v.vio_head); if (reply_array->present == 0) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() No reply/read array, failing miserably " "till writes/inlines are handled", __func__); return (false); } else { uint32_t i; /* uint32_t l; */ uint32_t n = ntohl(reply_array->elements); for (i = 0; i < n; i++) { /* FIXME: xdr_rdma_getaddrbuf hangs instead of * failing if no match. add a zero timeout * when implemented */ have = xdr_ioq_uv_fetch(&cbc->holdq, &xprt->inbufs.uvqh, "creply body", 1, IOQ_FLAG_NONE); rpcrdma_dump_msg(IOQ_(have), "creply body", ntohl(xid)); /* length < size if the protocol works out... * FIXME: check anyway? */ /* l = ntohl(reply_array->entry[i].target.length); */ } } xdr_ioq_reset(&cbc->holdq, 0); return (true); } /** xdr_rdma_svc_recv * * Server assembles a call request * * concatenates any rdma Read buffers for processing, * but clones call rdma header in place for future use. * * @param[IN] cbc incoming request * call request is in workq * * called by svc_rdma_recv() */ bool xdr_rdma_svc_recv(struct rpc_rdma_cbc *cbc, u_int32_t xid) { RDMAXPRT *xprt; struct rdma_msg *rmsg; uint32_t k; uint32_t l; if (!cbc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no context?", __func__); return (false); } xprt = x_xprt(cbc->workq.xdrs); /* free old buffers (should do nothing) */ xdr_ioq_release(&cbc->holdq.ioq_uv.uvqh); xdr_rdma_callq(xprt); /* swap calling message from workq to holdq */ TAILQ_CONCAT(&cbc->holdq.ioq_uv.uvqh.qh, &cbc->workq.ioq_uv.uvqh.qh, q); cbc->holdq.ioq_uv.uvqh.qcount = cbc->workq.ioq_uv.uvqh.qcount; cbc->workq.ioq_uv.uvqh.qcount = 0; cbc->call_uv = IOQ_(TAILQ_FIRST(&cbc->holdq.ioq_uv.uvqh.qh)); (cbc->call_uv->u.uio_references)++; rmsg = m_(cbc->call_uv->v.vio_head); rpcrdma_dump_msg(cbc->call_uv, "call", rmsg->rdma_xid); /* locate NFS/RDMA (RFC-5666) chunk positions */ cbc->read_chunk = xdr_rdma_get_read_list(rmsg); cbc->write_chunk = (wl_t *)cbc->read_chunk; xdr_rdma_skip_read_list((uint32_t **)&cbc->write_chunk); cbc->reply_chunk = cbc->write_chunk; xdr_rdma_skip_write_list((uint32_t **)&cbc->reply_chunk); cbc->call_data = cbc->reply_chunk; xdr_rdma_skip_reply_array((uint32_t **)&cbc->call_data); /* skip past the header for the calling buffer */ xdr_ioq_reset(&cbc->holdq, ((uintptr_t)cbc->call_data - (uintptr_t)rmsg)); switch (ntohl(rmsg->rdma_type)) { case RDMA_MSG: return (true); case RDMA_NOMSG: break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() rdma_type %" PRIu32 "?", __func__, ntohl(rmsg->rdma_type)); return (false); } while (rl(cbc->read_chunk)->present != 0 && rl(cbc->read_chunk)->position == 0) { l = ntohl(rl(cbc->read_chunk)->target.length); k = xdr_rdma_chunk_fetch(&cbc->workq, &xprt->inbufs.uvqh, "call chunk", l, xprt->recvsize, xprt->xa->max_recv_sge, xdr_rdma_chunk_in); xdr_rdma_wait_read_cb(xprt, cbc, k, &rl(cbc->read_chunk)->target); rpcrdma_dump_msg(IOQ_(TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh)), "call chunk", rmsg->rdma_xid); /* concatenate any additional buffers after the calling message, * faking there is more call data in the calling buffer. */ TAILQ_CONCAT(&cbc->holdq.ioq_uv.uvqh.qh, &cbc->workq.ioq_uv.uvqh.qh, q); cbc->holdq.ioq_uv.uvqh.qcount += cbc->workq.ioq_uv.uvqh.qcount; cbc->workq.ioq_uv.uvqh.qcount = 0; cbc->read_chunk = (char *)cbc->read_chunk + sizeof(struct xdr_read_list); } return (true); } /** xdr_rdma_svc_reply * * Server prepares for a reply * * potential output buffers are queued in workq. * * @param[IN] cbc incoming request * call request is in holdq * * called by svc_rdma_reply() */ bool xdr_rdma_svc_reply(struct rpc_rdma_cbc *cbc, u_int32_t xid) { RDMAXPRT *xprt; struct xdr_write_list *reply_array; struct poolq_entry *have; if (!cbc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no context?", __func__); return (false); } xprt = x_xprt(cbc->workq.xdrs); /* free call buffers (head will be retained) */ xdr_ioq_release(&cbc->holdq.ioq_uv.uvqh); reply_array = (wl_t *)cbc->reply_chunk; if (reply_array->present == 0) { /* no reply array to write, replying inline and hope it works * (OK on RPC/RDMA Read) */ have = xdr_ioq_uv_fetch(&cbc->holdq, &xprt->outbufs.uvqh, "sreply buffer", 1, IOQ_FLAG_NONE); /* buffer is limited size */ IOQ_(have)->v.vio_head = IOQ_(have)->v.vio_tail = IOQ_(have)->v.vio_base; IOQ_(have)->v.vio_wrap = (char *)IOQ_(have)->v.vio_base + RFC5666_BUFFER_SIZE; /* make room at head for RDMA header */ xdr_ioq_reset(&cbc->holdq, (uintptr_t)cbc->call_data - (uintptr_t)cbc->write_chunk + offsetof(struct rdma_msg, rdma_body)); } else { uint32_t i; uint32_t l; uint32_t n = ntohl(reply_array->elements); if (!n) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() missing reply chunks", __func__); return (false); } /* fetch all reply chunks in advance to avoid deadlock * (there may be more than one) */ for (i = 0; i < n; i++) { l = ntohl(reply_array->entry[i].target.length); xdr_rdma_chunk_fetch(&cbc->holdq, &xprt->outbufs.uvqh, "sreply chunk", l, xprt->sendsize, xprt->xa->max_send_sge, xdr_rdma_chunk_out); } xdr_ioq_reset(&cbc->holdq, 0); } return (true); } /** xdr_rdma_clnt_flushout * * @param[IN] xdrs combined callback context * * @return true is message sent, false otherwise * * called by clnt_rdma_call() */ bool xdr_rdma_clnt_flushout(XDR *xdrs) { /* FIXME: decide how many buffers we use in argument!!!!!! */ #define num_chunks (xprt->xa->credits - 1) struct rpc_rdma_cbc *cbc = (struct rpc_rdma_cbc *)xdrs; RDMAXPRT *xprt; struct rpc_msg *msg; struct rdma_msg *rmsg; struct xdr_write_list *w_array; struct xdr_ioq_uv *head_uv; struct xdr_ioq_uv *work_uv; struct poolq_entry *have; int i = 0; if (!xdrs) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no context?", __func__); return (false); } xprt = x_xprt(cbc->workq.xdrs); work_uv = IOQ_(TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh)); msg = (struct rpc_msg *)(work_uv->v.vio_head); xdr_tail_update(cbc->workq.xdrs); switch(ntohl(msg->rm_direction)) { case CALL: /* good to go */ break; case REPLY: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() nothing to send on REPLY (%u)", __func__, ntohl(msg->rm_direction)); return (true); default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() bad rm_direction (%u)", __func__, ntohl(msg->rm_direction)); return (false); } cbc->workq.ioq_uv.uvq_fetch = xdr_ioq_uv_fetch_nothing; head_uv = IOQ_(xdr_ioq_uv_fetch(&cbc->workq, &xprt->outbufs.uvqh, "c_head buffer", 1, IOQ_FLAG_NONE)); (void)xdr_ioq_uv_fetch(&cbc->holdq, &xprt->inbufs.uvqh, "call buffers", num_chunks, IOQ_FLAG_NONE); rmsg = m_(head_uv->v.vio_head); rmsg->rdma_xid = msg->rm_xid; rmsg->rdma_vers = htonl(1); rmsg->rdma_credit = htonl(xprt->xa->credits); rmsg->rdma_type = htonl(RDMA_MSG); /* no read, write chunks. */ rmsg->rdma_body.rdma_msg.rdma_reads = 0; /* htonl(0); */ rmsg->rdma_body.rdma_msg.rdma_writes = 0; /* htonl(0); */ /* reply chunk */ w_array = (wl_t *)&rmsg->rdma_body.rdma_msg.rdma_reply; w_array->present = htonl(1); w_array->elements = htonl(num_chunks); TAILQ_FOREACH(have, &cbc->holdq.ioq_uv.uvqh.qh, q) { struct xdr_rdma_segment *w_seg = &w_array->entry[i++].target; uint32_t length = ioquv_length(IOQ_(have)); w_seg->handle = htonl(xprt->mr->rkey); w_seg->length = htonl(length); xdr_encode_hyper((uint32_t*)&w_seg->offset, (uintptr_t)IOQ_(have)->v.vio_head); } head_uv->v.vio_tail = head_uv->v.vio_head + xdr_rdma_header_length(rmsg); rpcrdma_dump_msg(head_uv, "clnthead", msg->rm_xid); rpcrdma_dump_msg(work_uv, "clntcall", msg->rm_xid); /* actual send, callback will take care of cleanup */ xdr_rdma_post_send_cb(xprt, cbc, 2); return (true); } /** xdr_rdma_svc_flushout * * @param[IN] cbc combined callback context * * called by svc_rdma_reply() */ bool xdr_rdma_svc_flushout(struct rpc_rdma_cbc *cbc) { RDMAXPRT *xprt; struct rpc_msg *msg; struct rdma_msg *rmsg; struct xdr_write_list *w_array; struct xdr_write_list *reply_array; struct xdr_ioq_uv *head_uv; struct xdr_ioq_uv *work_uv; if (!cbc) { __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() no context?", __func__); return (false); } xprt = x_xprt(cbc->workq.xdrs); /* swap reply body from holdq to workq */ TAILQ_CONCAT(&cbc->workq.ioq_uv.uvqh.qh, &cbc->holdq.ioq_uv.uvqh.qh, q); cbc->workq.ioq_uv.uvqh.qcount = cbc->holdq.ioq_uv.uvqh.qcount; cbc->holdq.ioq_uv.uvqh.qcount = 0; work_uv = IOQ_(TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh)); msg = (struct rpc_msg *)(work_uv->v.vio_head); /* work_uv->v.vio_tail has been set by xdr_tail_update() */ switch(ntohl(msg->rm_direction)) { case CALL: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() nothing to send on CALL (%u)", __func__, ntohl(msg->rm_direction)); return (true); case REPLY: /* good to go */ break; default: __warnx(TIRPC_DEBUG_FLAG_ERROR, "%s() bad rm_direction (%u)", __func__, ntohl(msg->rm_direction)); return (false); } /* usurp the holdq for the head, move to workq later */ head_uv = IOQ_(xdr_ioq_uv_fetch(&cbc->holdq, &xprt->outbufs.uvqh, "sreply head", 1, IOQ_FLAG_NONE)); /* entry was already added directly to the queue */ head_uv->v.vio_head = head_uv->v.vio_base; /* tail adjusted below */ head_uv->v.vio_wrap = (char *)head_uv->v.vio_base + xprt->sendsize; /* build the header that goes with the data */ rmsg = m_(head_uv->v.vio_head); rmsg->rdma_xid = msg->rm_xid; /* TODO: check it matches call_uv xid */ rmsg->rdma_vers = htonl(1); rmsg->rdma_credit = htonl(xprt->xa->credits); /* no read, write chunks. */ rmsg->rdma_body.rdma_msg.rdma_reads = 0; /* htonl(0); */ rmsg->rdma_body.rdma_msg.rdma_writes = 0; /* htonl(0); */ reply_array = (wl_t *)cbc->reply_chunk; if (reply_array->present == 0) { rmsg->rdma_type = htonl(RDMA_MSG); /* no reply chunk either */ rmsg->rdma_body.rdma_msg.rdma_reply = 0; /* htonl(0); */ head_uv->v.vio_tail = head_uv->v.vio_head + xdr_rdma_header_length(rmsg); rpcrdma_dump_msg(head_uv, "sreply head", msg->rm_xid); rpcrdma_dump_msg(work_uv, "sreply body", msg->rm_xid); } else { uint32_t i = 0; uint32_t n = ntohl(reply_array->elements); rmsg->rdma_type = htonl(RDMA_NOMSG); /* reply chunk */ w_array = (wl_t *)&rmsg->rdma_body.rdma_msg.rdma_reply; w_array->present = htonl(1); while (i < n) { struct xdr_rdma_segment *c_seg = &reply_array->entry[i].target; struct xdr_rdma_segment *w_seg = &w_array->entry[i++].target; uint32_t length = ntohl(c_seg->length); uint32_t k = length / xprt->sendsize; uint32_t m = length % xprt->sendsize; if (m) { /* need fractional buffer */ k++; } /* ensure never asking for more buffers than allowed */ if (k > xprt->xa->max_send_sge) { __warnx(TIRPC_DEBUG_FLAG_XDR, "%s() requested chunk %" PRIu32 " is too long (%" PRIu32 ">%" PRIu32 ")", __func__, length, k, xprt->xa->max_send_sge); k = xprt->xa->max_send_sge; } *w_seg = *c_seg; /* sometimes, back-to-back buffers could be sent * together. releases of unused buffers and * other events eventually scramble the buffers * enough that there's no gain in efficiency. */ xdr_rdma_wait_write_cb(xprt, cbc, k, w_seg); while (0 < k--) { struct poolq_entry *have = TAILQ_FIRST(&cbc->workq.ioq_uv.uvqh.qh); TAILQ_REMOVE(&cbc->workq.ioq_uv.uvqh.qh, have, q); (cbc->workq.ioq_uv.uvqh.qcount)--; rpcrdma_dump_msg(IOQ_(have), "sreply body", msg->rm_xid); xdr_ioq_uv_release(IOQ_(have)); } } w_array->elements = htonl(i); head_uv->v.vio_tail = head_uv->v.vio_head + xdr_rdma_header_length(rmsg); rpcrdma_dump_msg(head_uv, "sreply head", msg->rm_xid); } /* actual send, callback will take care of cleanup */ TAILQ_REMOVE(&cbc->holdq.ioq_uv.uvqh.qh, &head_uv->uvq, q); (cbc->holdq.ioq_uv.uvqh.qcount)--; (cbc->workq.ioq_uv.uvqh.qcount)++; TAILQ_INSERT_HEAD(&cbc->workq.ioq_uv.uvqh.qh, &head_uv->uvq, q); xdr_rdma_post_send_cb(xprt, cbc, cbc->workq.ioq_uv.uvqh.qcount); /* free the old inbuf we only kept for header */ xdr_ioq_uv_release(cbc->call_uv); return (true); } ntirpc-1.3.1/src/xdr_rec.c000066400000000000000000000502461261345040100153770ustar00rootroot00000000000000 /* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include #include /* * 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 #if !defined(_WIN32) #include #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include "rpc_com.h" static bool xdrrec_getlong(XDR *, long *); static bool xdrrec_putlong(XDR *, const long *); static bool xdrrec_getbytes(XDR *, char *, u_int); static bool xdrrec_putbytes(XDR *, const char *, u_int); static u_int xdrrec_getpos(XDR *); static bool xdrrec_setpos(XDR *, u_int); static int32_t *xdrrec_inline(XDR *, u_int); static void xdrrec_destroy(XDR *); static bool xdrrec_noop(void); typedef bool (*dummyfunc3) (XDR *, int, void *); typedef bool (*dummy_getbufs) (XDR *, xdr_uio *, u_int); typedef bool (*dummy_putbufs) (XDR *, xdr_uio *, u_int); static const struct xdr_ops xdrrec_ops = { xdrrec_getlong, xdrrec_putlong, xdrrec_getbytes, xdrrec_putbytes, xdrrec_getpos, xdrrec_setpos, xdrrec_inline, xdrrec_destroy, (dummyfunc3) xdrrec_noop, /* x_control */ (dummy_getbufs) xdrrec_noop, /* x_getbufs */ (dummy_putbufs) xdrrec_noop /* x_putbufs */ }; /* * 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 { XDR *xdrs; char *tcp_handle; /* * out-goung bits */ int (*writeit) (XDR *, void *, void *, 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 frag_sent; /* true if buffer sent in middle of record */ /* * in-coming bits */ int (*readit) (XDR *, void *, void *, 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 last_frag; u_int sendsize; u_int recvsize; bool nonblock; bool 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(u_int); static bool flush_out(RECSTREAM *, bool); static bool fill_input_buf(RECSTREAM *); static bool get_input_bytes(RECSTREAM *, char *, int); static bool set_input_fragment(RECSTREAM *); static bool skip_input_bytes(RECSTREAM *, long); static bool realloc_stream(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(XDR *xdrs, u_int sendsize, u_int recvsize, void *tcp_handle, /* like read, but pass it a tcp_handle, not sock */ int (*readit) (XDR *, void *, void *, int), /* like write, but pass it a tcp_handle, not sock */ int (*writeit) (XDR *, void *, void *, int)) { RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM)); if (rstrm == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDRREC, "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 = mem_alloc(rstrm->sendsize); if (rstrm->out_base == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDRREC, "xdrrec_create: out of memory"); mem_free(rstrm, sizeof(RECSTREAM)); return; } rstrm->recvsize = recvsize = fix_buf_size(recvsize); rstrm->in_base = mem_alloc(recvsize); if (rstrm->in_base == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDRREC, "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_lib[0] = NULL; xdrs->x_lib[1] = NULL; xdrs->x_public = NULL; xdrs->x_private = rstrm; rstrm->xdrs = xdrs; 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 routines defined below are the xdr ops which will go into the * xdr handle filled in by xdrrec_create. */ static bool xdrrec_getlong(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 >= sizeof(int32_t)) && ((PtrToUlong(rstrm->in_boundry) - PtrToUlong(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 xdrrec_putlong(XDR *xdrs, const long *lp) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); int32_t *dest_lp = ((int32_t *) (void *)(rstrm->out_finger)); rstrm->out_finger += sizeof(int32_t); if (rstrm->out_finger > 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 /* must manage buffers, fragments, and records */ xdrrec_getbytes(XDR *xdrs, char *addr, u_int len) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); int current; while (len > 0) { current = (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 xdrrec_putbytes(XDR *xdrs, const char *addr, u_int len) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); size_t current; while (len > 0) { current = (size_t) (PtrToUlong(rstrm->out_boundry) - PtrToUlong(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(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) xdrs->x_private; off_t pos; switch (xdrs->x_op) { case XDR_ENCODE: pos = rstrm->out_finger - rstrm->out_base - BYTES_PER_XDR_UNIT; break; case XDR_DECODE: pos = rstrm->in_boundry - rstrm->in_finger - BYTES_PER_XDR_UNIT; break; default: /* XXX annoys Coverity */ pos = (off_t) -1; break; } return ((u_int) pos); } static bool xdrrec_setpos(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(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 <= 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(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 xdrrec_skiprecord(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 function. * Returns true iff there is no more input in the buffer * after consuming the rest of the current record. */ bool xdrrec_eof(XDR *xdrs) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); while (rstrm->fbtbc > 0 || (!rstrm->last_frag)) { if (!skip_input_bytes(rstrm, rstrm->fbtbc)) return (true); rstrm->fbtbc = 0; if ((!rstrm->last_frag) && (!set_input_fragment(rstrm))) return (true); } if (rstrm->in_finger == rstrm->in_boundry) return (true); return (false); } /* * The client must tell the package when an end-of-record has occurred. * The second paramter 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 xdrrec_endofrecord(XDR *xdrs, bool sendnow) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); u_long len; /* fragment length */ if (sendnow || rstrm->frag_sent || (PtrToUlong(rstrm->out_finger) + sizeof(u_int32_t) >= PtrToUlong(rstrm->out_boundry))) { rstrm->frag_sent = false; return (flush_out(rstrm, true)); } len = PtrToUlong((rstrm->out_finger)) - PtrToUlong((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 __xdrrec_getrec(XDR *xdrs, enum xprt_stat *statp, bool expectdata) { RECSTREAM *rstrm = (RECSTREAM *) (xdrs->x_private); ssize_t n; int fraglen; if (!rstrm->in_haveheader) { n = rstrm->readit(xdrs, 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 < 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 (rstrm->in_reclen > rstrm->recvsize) realloc_stream(rstrm, rstrm->in_reclen); if (rstrm->in_header & LAST_FRAG) { rstrm->in_header &= ~LAST_FRAG; rstrm->last_frag = true; } } n = rstrm->readit(xdrs, 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 __xdrrec_setnonblock(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 flush_out(RECSTREAM *rstrm, bool eor) { u_int32_t eormask = (eor == true) ? LAST_FRAG : 0; u_int32_t len = (u_int32_t) (PtrToUlong(rstrm->out_finger) - PtrToUlong(rstrm->frag_header) - sizeof(u_int32_t)); *(rstrm->frag_header) = htonl(len | eormask); len = (u_int32_t) (PtrToUlong(rstrm->out_finger) - PtrToUlong(rstrm->out_base)); if ((*(rstrm->writeit)) (rstrm->xdrs, 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 /* knows nothing about records! Only about input buffers */ fill_input_buf(RECSTREAM *rstrm) { char *where; u_int32_t i; int len; if (rstrm->nonblock) return false; where = rstrm->in_base; i = (u_int32_t) (PtrToUlong(rstrm->in_boundry) % BYTES_PER_XDR_UNIT); where += i; len = (u_int32_t) (rstrm->in_size - i); len = (*(rstrm->readit)) (rstrm->xdrs, rstrm->tcp_handle, where, len); if (len == -1) return (false); rstrm->in_finger = where; where += len; rstrm->in_boundry = where; return (true); } static bool /* knows nothing about records! Only about input buffers */ get_input_bytes(RECSTREAM *rstrm, char *addr, int len) { size_t current; if (rstrm->nonblock) { if (len > (int)(rstrm->in_boundry - rstrm->in_finger)) return false; memcpy(addr, rstrm->in_finger, (size_t) len); rstrm->in_finger += len; return true; } while (len > 0) { current = (size_t) (PtrToUlong(rstrm->in_boundry) - PtrToUlong(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 /* next two bytes of the input stream are treated as a header */ set_input_fragment(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 /* consumes input bytes; knows nothing about records! */ skip_input_bytes(RECSTREAM *rstrm, long cnt) { u_int32_t current; while (cnt > 0) { current = (size_t) (PtrToUlong(rstrm->in_boundry) - PtrToUlong(rstrm->in_finger)); if (current == 0) { if (!fill_input_buf(rstrm)) return (false); continue; } current = (u_int32_t) ((cnt < current) ? cnt : current); rstrm->in_finger += current; cnt -= current; } return (true); } static u_int fix_buf_size(u_int s) { if (s < 100) s = 4000; return (RNDUP(s)); } /* * Reallocate the input buffer for a non-block stream. */ static bool realloc_stream(RECSTREAM *rstrm, int size) { ptrdiff_t diff; char *buf; if (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); } static bool xdrrec_noop(void) { return (false); } ntirpc-1.3.1/src/xdr_reference.c000066400000000000000000000076421261345040100165660ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * xdr_reference.c, Generic XDR routines impelmentation. * * Copyright (C) 1987, Sun Microsystems, Inc. * * These are the "non-trivial" xdr primitives used to serialize and de-serialize * "pointers". See xdr.h for more info on the interface to xdr. */ #include "namespace.h" #if !defined(_WIN32) #include #endif #include #include #include #include #include #include #if defined(__FreeBSD__) || defined(__NetBSD__) #include #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 xdr_reference(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 stat; if (loc == NULL) switch (xdrs->x_op) { case XDR_FREE: return (true); case XDR_DECODE: *pp = loc = (caddr_t) mem_alloc(size); if (loc == NULL) { __warnx(TIRPC_DEBUG_FLAG_XDR, "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 xdr_pointer(XDR *xdrs, char **objpp, u_int obj_size, xdrproc_t xdr_obj) { bool_t more_data; more_data = (*objpp != NULL); if (!inline_xdr_bool(xdrs, &more_data)) return (false); if (!more_data) { *objpp = NULL; return (true); } return (xdr_reference(xdrs, objpp, obj_size, xdr_obj)); } ntirpc-1.3.1/src/xdr_sizeof.c000066400000000000000000000103311261345040100161140ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ /* * xdr_sizeof.c * * Copyright 1990 Sun Microsystems, Inc. * * General purpose routine to see how much space something will use * when serialized using XDR. */ #include #include #include "namespace.h" #include #include #include #include #include #include "un-namespace.h" #include "rpc_com.h" /* ARGSUSED */ static bool x_putlong(XDR *xdrs, const long *longp) { xdrs->x_handy += BYTES_PER_XDR_UNIT; return (TRUE); } /* ARGSUSED */ static bool x_putbytes(XDR *xdrs, const char *bp, u_int len) { xdrs->x_handy += len; return (TRUE); } static u_int x_getpostn(XDR *xdrs) { return (xdrs->x_handy); } /* ARGSUSED */ static bool x_setpostn(XDR *xdrs, u_int pos) { /* This is not allowed */ return (FALSE); } static int32_t * x_inline(XDR *xdrs, u_int len) { if (len == 0) return (NULL); if (xdrs->x_op != XDR_ENCODE) return (NULL); if (len < PtrToUlong(xdrs->x_base)) { /* x_private was already allocated */ xdrs->x_handy += len; return ((int32_t *) xdrs->x_private); } else { /* Free the earlier space and allocate new area */ if (xdrs->x_private) __free(xdrs->x_private); xdrs->x_private = (caddr_t) mem_alloc(len); if (!xdrs->x_private) { xdrs->x_base = 0; return (NULL); } xdrs->x_base = (void *)(intptr_t) len; /* XXX */ xdrs->x_handy += len; return ((int32_t *) xdrs->x_private); } } static int harmless(void) { /* Always return FALSE/NULL, as the case may be */ return (0); } static void x_destroy(XDR *xdrs) { xdrs->x_handy = 0; xdrs->x_base = 0; if (xdrs->x_private) { __free(xdrs->x_private); xdrs->x_private = NULL; } return; } unsigned long xdr_sizeof(xdrproc_t func, void *data) { XDR x; struct xdr_ops ops; bool stat; /* to stop ANSI-C compiler from complaining */ typedef bool(*dummyfunc1) (XDR *, long *); typedef bool(*dummyfunc2) (XDR *, caddr_t, u_int); typedef bool(*dummyfunc3) (XDR *, const char *, u_int, u_int); typedef bool(*dummy_getbufs) (XDR *, xdr_uio *, u_int, u_int); typedef bool(*dummy_putbufs) (XDR *, xdr_uio *, u_int); ops.x_putlong = x_putlong; ops.x_putbytes = x_putbytes; ops.x_inline = x_inline; ops.x_getpostn = x_getpostn; ops.x_setpostn = x_setpostn; ops.x_destroy = x_destroy; /* the other harmless ones */ ops.x_getlong = (dummyfunc1) harmless; ops.x_getbytes = (dummyfunc2) harmless; ops.x_getbufs = (dummy_getbufs) harmless; ops.x_putbufs = (dummy_putbufs) harmless; x.x_op = XDR_ENCODE; x.x_ops = &ops; x.x_handy = 0; x.x_private = (caddr_t) NULL; x.x_base = (caddr_t) 0; stat = func(&x, data); if (x.x_private) __free(x.x_private); return (stat == TRUE ? (unsigned)x.x_handy : 0); } ntirpc-1.3.1/src/xdr_stdio.c000066400000000000000000000124771261345040100157540ustar00rootroot00000000000000/* * Copyright (c) 2009, Sun Microsystems, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * - Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * - Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * - Neither the name of Sun Microsystems, Inc. nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include #include /* * 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 #if !defined(_WIN32) #include #endif #include #include #include "un-namespace.h" static void xdrstdio_destroy(XDR *); static bool xdrstdio_getlong(XDR *, long *); static bool xdrstdio_putlong(XDR *, const long *); static bool xdrstdio_getbytes(XDR *, char *, u_int); static bool xdrstdio_putbytes(XDR *, const char *, u_int); static u_int xdrstdio_getpos(XDR *); static bool xdrstdio_setpos(XDR *, u_int); static int32_t *xdrstdio_inline(XDR *, u_int); static bool xdrstdio_noop(void); typedef bool (*dummyfunc3) (XDR *, int, void *); typedef bool (*dummy_getbufs) (XDR *, xdr_uio *, u_int); typedef bool (*dummy_putbufs) (XDR *, xdr_uio *, 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 */ (dummyfunc3) xdrstdio_noop, /* x_control */ (dummy_getbufs) xdrstdio_noop, /* x_getbufs */ (dummy_putbufs) xdrstdio_noop /* x_putbufs */ }; /* * Initialize a stdio xdr stream. * Sets the xdr stream handle xdrs for use on the stream file. * Operation flag is set to op. */ void xdrstdio_create(XDR *xdrs, FILE *file, enum xdr_op op) { xdrs->x_op = op; xdrs->x_ops = &xdrstdio_ops; xdrs->x_lib[0] = NULL; xdrs->x_lib[1] = NULL; xdrs->x_public = NULL; 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(XDR *xdrs) { (void)fflush((FILE *) xdrs->x_private); /* XXX: should we close the file ?? */ } static bool xdrstdio_getlong(XDR *xdrs, long *lp) { if (fread(lp, sizeof(int32_t), 1, (FILE *) xdrs->x_private) != 1) return (FALSE); *lp = (long)ntohl((u_int32_t) *lp); return (TRUE); } static bool xdrstdio_putlong(XDR *xdrs, const long *lp) { long mycopy = (long)htonl((u_int32_t) *lp); if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *) xdrs->x_private) != 1) return (FALSE); return (TRUE); } static bool xdrstdio_getbytes(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 xdrstdio_putbytes(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(XDR *xdrs) { return ((u_int) ftell((FILE *) xdrs->x_private)); } static bool xdrstdio_setpos(XDR *xdrs, u_int pos) { return ((fseek((FILE *) xdrs->x_private, (long)pos, 0) < 0) ? FALSE : TRUE); } /* ARGSUSED */ static int32_t * xdrstdio_inline(XDR *xdrs, u_int len) { /* * Must do some work to implement this: must insure * enough data in the underlying stdio buffer, * that the buffer is aligned so that we can indirect through a * long *, and stuff this pointer in xdrs->x_buf. Doing * a fread or fwrite to a scratch buffer would defeat * most of the gains to be had here and require storage * management on this buffer, so we don't do this. */ return (NULL); } static bool xdrstdio_noop(void) { return (FALSE); } ntirpc-1.3.1/tests/000077500000000000000000000000001261345040100141515ustar00rootroot00000000000000ntirpc-1.3.1/tests/.gitignore000066400000000000000000000000311261345040100161330ustar00rootroot00000000000000nfs4_testmsk nfs4_server ntirpc-1.3.1/tests/Makefile000066400000000000000000000011141261345040100156060ustar00rootroot00000000000000GANESHA_BUILD=/opt/GANESHA/build-nfs CFLAGS=-g -Wall -Werror -I../ntirpc LDFLAGS=-L$(GANESHA_BUILD)/libntirpc/src all: nfs4_testmsk nfs4_server nfs4_testmsk: nfs4_testmsk.c nfs4_xdr.o gcc $(CFLAGS) $(LDFLAGS) nfs4_xdr.o nfs4_testmsk.c -o nfs4_testmsk -lntirpc -lmooshika -lrt -lpthread -lgssapi_krb5 nfs4_server: nfs4_server.c nfs4_xdr.o gcc $(CFLAGS) $(LDFLAGS) nfs4_xdr.o nfs4_server.c -o nfs4_server -lntirpc -lmooshika -lrt -lpthread -lgssapi_krb5 #ignore CFLAGS for that one... nfs4_xdr.o: nfs4_xdr.c gcc -g -I../tirpc -c nfs4_xdr.c clean: rm -f *.o nfs4_{testmsk,server} ntirpc-1.3.1/tests/fsal_nfsv4_macros.h000066400000000000000000000631231261345040100177400ustar00rootroot00000000000000/* * vim:expandtab:shiftwidth=8:tabstop=8: */ /** * \file fsal_nfsv4_macros.h * \author $Author: deniel $ * \date 06/05/2007 * \version $Revision$ * \brief Usefull macros to manage NFSv4 call from FSAL_PROXY * * */ #ifndef _FSAL_NFSV4_MACROS_H #define _FSAL_NFSV4_MACROS_H #define MAXNAMLEN 256 typedef union { nfs_cookie4 data ; char pad[4]; } proxyfsal_cookie_t; typedef struct fsal_proxy_internal_fattr_readdir__ { fattr4_type type; fattr4_change change_time; fattr4_size size; fattr4_fsid fsid; fattr4_filehandle filehandle; fattr4_fileid fileid; fattr4_mode mode; fattr4_numlinks numlinks; fattr4_owner owner; /* Needs to points to a string */ fattr4_owner_group owner_group; /* Needs to points to a string */ fattr4_space_used space_used; fattr4_time_access time_access; fattr4_time_metadata time_metadata; fattr4_time_modify time_modify; fattr4_rawdev rawdev; char padowner[MAXNAMLEN]; char padgroup[MAXNAMLEN]; char padfh[NFS4_FHSIZE]; } fsal_proxy_internal_fattr_readdir_t; #define TIMEOUTRPC {2, 0} #define PRINT_HANDLE( tag, handle ) \ do { \ if(isFullDebug(COMPONENT_FSAL)) \ { \ char outstr[1024] ; \ snprintHandle(outstr, 1024, handle) ; \ LogFullDebug(COMPONENT_FSAL, "============> %s : handle=%s\n", tag, outstr ) ; \ } \ } while( 0 ) /* Free a compound */ #define COMPOUNDV4_ARG_FREE \ do {gsh_free(argcompound.argarray_val);} while( 0 ) /* OP specific macros */ #define COMPOUNDV4_ARG_ADD_OP_PUTROOTFH( argcompound ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_PUTROOTFH ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_OPEN_CONFIRM( argcompound, __openseqid, __other, __seqid ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_OPEN_CONFIRM ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen_confirm.seqid = __seqid ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen_confirm.open_stateid.seqid = __openseqid ; \ memcpy( argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen_confirm.open_stateid.other, __other, 12 ) ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_OPEN_NOCREATE( argcompound, __seqid, inclientid, inaccess, inname, __owner_val, __owner_len ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_OPEN ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.seqid = __seqid ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.share_access = OPEN4_SHARE_ACCESS_BOTH ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.share_deny = OPEN4_SHARE_DENY_NONE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.owner.clientid = inclientid ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.owner.owner.owner_len = __owner_len ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.owner.owner.owner_val = __owner_val ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.openhow.opentype = OPEN4_NOCREATE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.claim.claim = CLAIM_NULL ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.claim.open_claim4_u.file = inname ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_CLOSE( argcompound, __stateid ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_CLOSE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opclose.seqid = __stateid.seqid +1 ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opclose.open_stateid.seqid = __stateid.seqid ; \ memcpy( argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opclose.open_stateid.other, __stateid.other, 12 ) ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_GETATTR( argcompound, bitmap ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_GETATTR ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opgetattr.attr_request = bitmap ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_SETATTR( argcompound, inattr ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_SETATTR ; \ memset(&argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetattr.stateid,0,sizeof(stateid4)); \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetattr.obj_attributes = inattr ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_GETFH( argcompound ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_GETFH ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_PUTFH( argcompound, nfs4fh ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_PUTFH ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opputfh.object = nfs4fh ; \ argcompound.argarray.argarray_len += 1 ; \ } while( 0 ) #define COMPOUNDV4_ARG_ADD_OP_LOOKUP( argcompound, name ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_LOOKUP ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.oplookup.objname = name ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_LOOKUPP( argcompound ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_LOOKUPP ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_SETCLIENTID( argcompound, inclient, incallback ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_SETCLIENTID ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetclientid.client = inclient ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetclientid.callback = incallback ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetclientid.callback_ident = 0 ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_SETCLIENTID_CONFIRM( argcompound, inclientid, inverifier ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_SETCLIENTID_CONFIRM ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetclientid_confirm.clientid = inclientid ; \ strncpy( argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opsetclientid_confirm.setclientid_confirm, inverifier, NFS4_VERIFIER_SIZE ) ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_ACCESS( argcompound, inaccessflag ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_ACCESS ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opaccess.access = inaccessflag ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_READDIR( argcompound, incookie, innbentry, inverifier, inbitmap ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_READDIR ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.cookie = incookie ; \ memcpy( argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.cookieverf, inverifier, NFS4_VERIFIER_SIZE ) ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.dircount = innbentry*sizeof( entry4 ) ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.dircount = 2048 ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.maxcount = innbentry*sizeof( entry4 ) ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.maxcount = 4096 ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opreaddir.attr_request = inbitmap ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_OPEN_CREATE( argcompound, inname, inattrs, inclientid, __owner_val, __owner_len ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_OPEN ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.seqid = 0 ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.share_access = OPEN4_SHARE_ACCESS_BOTH ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.share_deny = OPEN4_SHARE_DENY_NONE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.owner.clientid = inclientid ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.owner.owner.owner_len = __owner_len ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.owner.owner.owner_val = __owner_val ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.openhow.opentype = OPEN4_CREATE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.openhow.openflag4_u.how.mode = GUARDED4 ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.openhow.openflag4_u.how.createhow4_u.createattrs = inattrs ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.claim.claim = CLAIM_NULL ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opopen.claim.open_claim4_u.file = inname ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_MKDIR( argcompound, inname, inattrs ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_CREATE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.objtype.type = NF4DIR ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.objname = inname ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.createattrs = inattrs ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_SYMLINK( argcompound, inname, incontent, inattrs ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_CREATE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.objtype.type = NF4LNK ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.objtype.createtype4_u.linkdata = incontent ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.objname = inname ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opcreate.createattrs = inattrs ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_LINK( argcompound, inname ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_LINK ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.oplink.newname = inname ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_REMOVE( argcompound, inname ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_REMOVE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opremove.target = inname ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_RENAME( argcompound, inoldname, innewname ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_RENAME ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.oprename.oldname = inoldname ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.oprename.newname = innewname ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_READLINK( argcompound ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_READLINK ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_SAVEFH( argcompound ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_SAVEFH ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_RESTOREFH( argcompound ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_RESTOREFH ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_READ( argcompound, instateid, inoffset, incount ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_READ ; \ memcpy( &argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opread.stateid, instateid, sizeof( stateid4 ) ) ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opread.offset = inoffset ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opread.count = incount ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_ARG_ADD_OP_WRITE( argcompound, instateid, inoffset, indatabuffval, indatabufflen ) \ do { \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].argop = OP_WRITE ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opwrite.stable= DATA_SYNC4 ; \ memcpy( &argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opwrite.stateid, instateid, sizeof( stateid4 ) ) ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opwrite.offset = inoffset ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opwrite.data.data_val = indatabuffval ; \ argcompound.argarray.argarray_val[argcompound.argarray.argarray_len].nfs_argop4_u.opwrite.data.data_len = indatabufflen ; \ argcompound.argarray.argarray_len += 1 ; \ } while ( 0 ) #define COMPOUNDV4_EXECUTE( pcontext, argcompound, rescompound, rc ) \ do { \ int __renew_rc = 0 ; \ rc = -1 ; \ do { \ if( __renew_rc == 0 ) \ { \ if( FSAL_proxy_change_user( pcontext ) == NULL ) break ; \ if( ( rc = clnt_call( pcontext->rpc_client, NFSPROC4_COMPOUND, \ (xdrproc_t)xdr_COMPOUND4args, (caddr_t)&argcompound, \ (xdrproc_t)xdr_COMPOUND4res, (caddr_t)&rescompound, \ timeout ) ) == RPC_SUCCESS ) \ break ; \ } \ LogEvent(COMPONENT_FSAL, "Reconnecting to the remote server.." ) ; \ pthread_mutex_lock( &pcontext->lock ) ; \ __renew_rc = fsal_internal_ClientReconnect( pcontext ) ; \ pthread_mutex_unlock( &pcontext->lock ) ; \ if (__renew_rc) { \ LogEvent(COMPONENT_FSAL, "Cannot reconnect, will sleep for %d seconds", \ pcontext->retry_sleeptime ) ; \ sleep( pcontext->retry_sleeptime ) ; \ } \ } while( 1 ) ; \ } while( 0 ) #define COMPOUNDV4_EXECUTE_SIMPLE( pcontext, argcompound, rescompound ) \ clnt_call( pcontext->rpc_client, NFSPROC4_COMPOUND, \ (xdrproc_t)xdr_COMPOUND4args, (caddr_t)&argcompound, \ (xdrproc_t)xdr_COMPOUND4res, (caddr_t)&rescompound, \ timeout ) #endif /* _FSAL_NFSV4_MACROS_H */ ntirpc-1.3.1/tests/nfs4.h000066400000000000000000001471021261345040100152010ustar00rootroot00000000000000/* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _NFS4_H_RPCGEN #define _NFS4_H_RPCGEN #include #ifdef __cplusplus extern "C" { #endif typedef int int32_t; typedef u_int uint32_t; typedef quad_t int64_t; typedef u_quad_t uint64_t; #define NFS4_FHSIZE 128 #define NFS4_VERIFIER_SIZE 8 #define NFS4_OPAQUE_LIMIT 1024 enum nfs_ftype4 { NF4REG = 1, NF4DIR = 2, NF4BLK = 3, NF4CHR = 4, NF4LNK = 5, NF4SOCK = 6, NF4FIFO = 7, NF4ATTRDIR = 8, NF4NAMEDATTR = 9, }; typedef enum nfs_ftype4 nfs_ftype4; enum nfsstat4 { NFS4_OK = 0, NFS4ERR_PERM = 1, NFS4ERR_NOENT = 2, NFS4ERR_IO = 5, NFS4ERR_NXIO = 6, NFS4ERR_ACCESS = 13, NFS4ERR_EXIST = 17, NFS4ERR_XDEV = 18, NFS4ERR_NOTDIR = 20, NFS4ERR_ISDIR = 21, NFS4ERR_INVAL = 22, NFS4ERR_FBIG = 27, NFS4ERR_NOSPC = 28, NFS4ERR_ROFS = 30, NFS4ERR_MLINK = 31, NFS4ERR_NAMETOOLONG = 63, NFS4ERR_NOTEMPTY = 66, NFS4ERR_DQUOT = 69, NFS4ERR_STALE = 70, NFS4ERR_BADHANDLE = 10001, NFS4ERR_BAD_COOKIE = 10003, NFS4ERR_NOTSUPP = 10004, NFS4ERR_TOOSMALL = 10005, NFS4ERR_SERVERFAULT = 10006, NFS4ERR_BADTYPE = 10007, NFS4ERR_DELAY = 10008, NFS4ERR_SAME = 10009, NFS4ERR_DENIED = 10010, NFS4ERR_EXPIRED = 10011, NFS4ERR_LOCKED = 10012, NFS4ERR_GRACE = 10013, NFS4ERR_FHEXPIRED = 10014, NFS4ERR_SHARE_DENIED = 10015, NFS4ERR_WRONGSEC = 10016, NFS4ERR_CLID_INUSE = 10017, NFS4ERR_RESOURCE = 10018, NFS4ERR_MOVED = 10019, NFS4ERR_NOFILEHANDLE = 10020, NFS4ERR_MINOR_VERS_MISMATCH = 10021, NFS4ERR_STALE_CLIENTID = 10022, NFS4ERR_STALE_STATEID = 10023, NFS4ERR_OLD_STATEID = 10024, NFS4ERR_BAD_STATEID = 10025, NFS4ERR_BAD_SEQID = 10026, NFS4ERR_NOT_SAME = 10027, NFS4ERR_LOCK_RANGE = 10028, NFS4ERR_SYMLINK = 10029, NFS4ERR_RESTOREFH = 10030, NFS4ERR_LEASE_MOVED = 10031, NFS4ERR_ATTRNOTSUPP = 10032, NFS4ERR_NO_GRACE = 10033, NFS4ERR_RECLAIM_BAD = 10034, NFS4ERR_RECLAIM_CONFLICT = 10035, NFS4ERR_BADXDR = 10036, NFS4ERR_LOCKS_HELD = 10037, NFS4ERR_OPENMODE = 10038, NFS4ERR_BADOWNER = 10039, NFS4ERR_BADCHAR = 10040, NFS4ERR_BADNAME = 10041, NFS4ERR_BAD_RANGE = 10042, NFS4ERR_LOCK_NOTSUPP = 10043, NFS4ERR_OP_ILLEGAL = 10044, NFS4ERR_DEADLOCK = 10045, NFS4ERR_FILE_OPEN = 10046, NFS4ERR_ADMIN_REVOKED = 10047, NFS4ERR_CB_PATH_DOWN = 10048, }; typedef enum nfsstat4 nfsstat4; typedef struct { u_int bitmap4_len; uint32_t *bitmap4_val; } bitmap4; typedef uint64_t offset4; typedef uint32_t count4; typedef uint64_t length4; typedef uint64_t clientid4; typedef uint32_t seqid4; typedef struct { u_int utf8string_len; char *utf8string_val; } utf8string; typedef utf8string utf8str_cis; typedef utf8string utf8str_cs; typedef utf8string utf8str_mixed; typedef utf8str_cs component4; typedef struct { u_int pathname4_len; component4 *pathname4_val; } pathname4; typedef uint64_t nfs_lockid4; typedef uint64_t nfs_cookie4; typedef utf8str_cs linktext4; typedef struct { u_int sec_oid4_len; char *sec_oid4_val; } sec_oid4; typedef uint32_t qop4; typedef uint32_t mode4; typedef uint64_t changeid4; typedef char verifier4[NFS4_VERIFIER_SIZE]; struct nfstime4 { int64_t seconds; uint32_t nseconds; }; typedef struct nfstime4 nfstime4; enum time_how4 { SET_TO_SERVER_TIME4 = 0, SET_TO_CLIENT_TIME4 = 1, }; typedef enum time_how4 time_how4; struct settime4 { time_how4 set_it; union { nfstime4 time; } settime4_u; }; typedef struct settime4 settime4; typedef struct { u_int nfs_fh4_len; char *nfs_fh4_val; } nfs_fh4; struct fsid4 { uint64_t major; uint64_t minor; }; typedef struct fsid4 fsid4; struct fs_location4 { struct { u_int server_len; utf8str_cis *server_val; } server; pathname4 rootpath; }; typedef struct fs_location4 fs_location4; struct fs_locations4 { pathname4 fs_root; struct { u_int locations_len; fs_location4 *locations_val; } locations; }; typedef struct fs_locations4 fs_locations4; #define ACL4_SUPPORT_ALLOW_ACL 0x00000001 #define ACL4_SUPPORT_DENY_ACL 0x00000002 #define ACL4_SUPPORT_AUDIT_ACL 0x00000004 #define ACL4_SUPPORT_ALARM_ACL 0x00000008 typedef uint32_t acetype4; #define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000 #define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001 #define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002 #define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003 typedef uint32_t aceflag4; #define ACE4_FILE_INHERIT_ACE 0x00000001 #define ACE4_DIRECTORY_INHERIT_ACE 0x00000002 #define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004 #define ACE4_INHERIT_ONLY_ACE 0x00000008 #define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010 #define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020 #define ACE4_IDENTIFIER_GROUP 0x00000040 typedef uint32_t acemask4; #define ACE4_READ_DATA 0x00000001 #define ACE4_LIST_DIRECTORY 0x00000001 #define ACE4_WRITE_DATA 0x00000002 #define ACE4_ADD_FILE 0x00000002 #define ACE4_APPEND_DATA 0x00000004 #define ACE4_ADD_SUBDIRECTORY 0x00000004 #define ACE4_READ_NAMED_ATTRS 0x00000008 #define ACE4_WRITE_NAMED_ATTRS 0x00000010 #define ACE4_EXECUTE 0x00000020 #define ACE4_DELETE_CHILD 0x00000040 #define ACE4_READ_ATTRIBUTES 0x00000080 #define ACE4_WRITE_ATTRIBUTES 0x00000100 #define ACE4_DELETE 0x00010000 #define ACE4_READ_ACL 0x00020000 #define ACE4_WRITE_ACL 0x00040000 #define ACE4_WRITE_OWNER 0x00080000 #define ACE4_SYNCHRONIZE 0x00100000 #define ACE4_GENERIC_READ 0x00120081 #define ACE4_GENERIC_WRITE 0x00160106 #define ACE4_GENERIC_EXECUTE 0x001200A0 struct nfsace4 { acetype4 type; aceflag4 flag; acemask4 access_mask; utf8str_mixed who; }; typedef struct nfsace4 nfsace4; #define MODE4_SUID 0x800 #define MODE4_SGID 0x400 #define MODE4_SVTX 0x200 #define MODE4_RUSR 0x100 #define MODE4_WUSR 0x080 #define MODE4_XUSR 0x040 #define MODE4_RGRP 0x020 #define MODE4_WGRP 0x010 #define MODE4_XGRP 0x008 #define MODE4_ROTH 0x004 #define MODE4_WOTH 0x002 #define MODE4_XOTH 0x001 struct specdata4 { uint32_t specdata1; uint32_t specdata2; }; typedef struct specdata4 specdata4; #define FH4_PERSISTENT 0x00000000 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001 #define FH4_VOLATILE_ANY 0x00000002 #define FH4_VOL_MIGRATION 0x00000004 #define FH4_VOL_RENAME 0x00000008 typedef bitmap4 fattr4_supported_attrs; typedef nfs_ftype4 fattr4_type; typedef uint32_t fattr4_fh_expire_type; typedef changeid4 fattr4_change; typedef uint64_t fattr4_size; typedef bool_t fattr4_link_support; typedef bool_t fattr4_symlink_support; typedef bool_t fattr4_named_attr; typedef fsid4 fattr4_fsid; typedef bool_t fattr4_unique_handles; typedef uint32_t fattr4_lease_time; typedef nfsstat4 fattr4_rdattr_error; typedef struct { u_int fattr4_acl_len; nfsace4 *fattr4_acl_val; } fattr4_acl; typedef uint32_t fattr4_aclsupport; typedef bool_t fattr4_archive; typedef bool_t fattr4_cansettime; typedef bool_t fattr4_case_insensitive; typedef bool_t fattr4_case_preserving; typedef bool_t fattr4_chown_restricted; typedef uint64_t fattr4_fileid; typedef uint64_t fattr4_files_avail; typedef nfs_fh4 fattr4_filehandle; typedef uint64_t fattr4_files_free; typedef uint64_t fattr4_files_total; typedef fs_locations4 fattr4_fs_locations; typedef bool_t fattr4_hidden; typedef bool_t fattr4_homogeneous; typedef uint64_t fattr4_maxfilesize; typedef uint32_t fattr4_maxlink; typedef uint32_t fattr4_maxname; typedef uint64_t fattr4_maxread; typedef uint64_t fattr4_maxwrite; typedef utf8str_cs fattr4_mimetype; typedef mode4 fattr4_mode; typedef uint64_t fattr4_mounted_on_fileid; typedef bool_t fattr4_no_trunc; typedef uint32_t fattr4_numlinks; typedef utf8str_mixed fattr4_owner; typedef utf8str_mixed fattr4_owner_group; typedef uint64_t fattr4_quota_avail_hard; typedef uint64_t fattr4_quota_avail_soft; typedef uint64_t fattr4_quota_used; typedef specdata4 fattr4_rawdev; typedef uint64_t fattr4_space_avail; typedef uint64_t fattr4_space_free; typedef uint64_t fattr4_space_total; typedef uint64_t fattr4_space_used; typedef bool_t fattr4_system; typedef nfstime4 fattr4_time_access; typedef settime4 fattr4_time_access_set; typedef nfstime4 fattr4_time_backup; typedef nfstime4 fattr4_time_create; typedef nfstime4 fattr4_time_delta; typedef nfstime4 fattr4_time_metadata; typedef nfstime4 fattr4_time_modify; typedef settime4 fattr4_time_modify_set; #define FATTR4_SUPPORTED_ATTRS 0 #define FATTR4_TYPE 1 #define FATTR4_FH_EXPIRE_TYPE 2 #define FATTR4_CHANGE 3 #define FATTR4_SIZE 4 #define FATTR4_LINK_SUPPORT 5 #define FATTR4_SYMLINK_SUPPORT 6 #define FATTR4_NAMED_ATTR 7 #define FATTR4_FSID 8 #define FATTR4_UNIQUE_HANDLES 9 #define FATTR4_LEASE_TIME 10 #define FATTR4_RDATTR_ERROR 11 #define FATTR4_FILEHANDLE 19 #define FATTR4_ACL 12 #define FATTR4_ACLSUPPORT 13 #define FATTR4_ARCHIVE 14 #define FATTR4_CANSETTIME 15 #define FATTR4_CASE_INSENSITIVE 16 #define FATTR4_CASE_PRESERVING 17 #define FATTR4_CHOWN_RESTRICTED 18 #define FATTR4_FILEID 20 #define FATTR4_FILES_AVAIL 21 #define FATTR4_FILES_FREE 22 #define FATTR4_FILES_TOTAL 23 #define FATTR4_FS_LOCATIONS 24 #define FATTR4_HIDDEN 25 #define FATTR4_HOMOGENEOUS 26 #define FATTR4_MAXFILESIZE 27 #define FATTR4_MAXLINK 28 #define FATTR4_MAXNAME 29 #define FATTR4_MAXREAD 30 #define FATTR4_MAXWRITE 31 #define FATTR4_MIMETYPE 32 #define FATTR4_MODE 33 #define FATTR4_NO_TRUNC 34 #define FATTR4_NUMLINKS 35 #define FATTR4_OWNER 36 #define FATTR4_OWNER_GROUP 37 #define FATTR4_QUOTA_AVAIL_HARD 38 #define FATTR4_QUOTA_AVAIL_SOFT 39 #define FATTR4_QUOTA_USED 40 #define FATTR4_RAWDEV 41 #define FATTR4_SPACE_AVAIL 42 #define FATTR4_SPACE_FREE 43 #define FATTR4_SPACE_TOTAL 44 #define FATTR4_SPACE_USED 45 #define FATTR4_SYSTEM 46 #define FATTR4_TIME_ACCESS 47 #define FATTR4_TIME_ACCESS_SET 48 #define FATTR4_TIME_BACKUP 49 #define FATTR4_TIME_CREATE 50 #define FATTR4_TIME_DELTA 51 #define FATTR4_TIME_METADATA 52 #define FATTR4_TIME_MODIFY 53 #define FATTR4_TIME_MODIFY_SET 54 #define FATTR4_MOUNTED_ON_FILEID 55 typedef struct { u_int attrlist4_len; char *attrlist4_val; } attrlist4; struct fattr4 { bitmap4 attrmask; attrlist4 attr_vals; }; typedef struct fattr4 fattr4; struct change_info4 { bool_t atomic; changeid4 before; changeid4 after; }; typedef struct change_info4 change_info4; struct clientaddr4 { char *r_netid; char *r_addr; }; typedef struct clientaddr4 clientaddr4; struct cb_client4 { uint32_t cb_program; clientaddr4 cb_location; }; typedef struct cb_client4 cb_client4; struct stateid4 { uint32_t seqid; char other[12]; }; typedef struct stateid4 stateid4; struct nfs_client_id4 { verifier4 verifier; struct { u_int id_len; char *id_val; } id; }; typedef struct nfs_client_id4 nfs_client_id4; struct open_owner4 { clientid4 clientid; struct { u_int owner_len; char *owner_val; } owner; }; typedef struct open_owner4 open_owner4; struct lock_owner4 { clientid4 clientid; struct { u_int owner_len; char *owner_val; } owner; }; typedef struct lock_owner4 lock_owner4; enum nfs_lock_type4 { READ_LT = 1, WRITE_LT = 2, READW_LT = 3, WRITEW_LT = 4, }; typedef enum nfs_lock_type4 nfs_lock_type4; #define ACCESS4_READ 0x00000001 #define ACCESS4_LOOKUP 0x00000002 #define ACCESS4_MODIFY 0x00000004 #define ACCESS4_EXTEND 0x00000008 #define ACCESS4_DELETE 0x00000010 #define ACCESS4_EXECUTE 0x00000020 struct ACCESS4args { uint32_t access; }; typedef struct ACCESS4args ACCESS4args; struct ACCESS4resok { uint32_t supported; uint32_t access; }; typedef struct ACCESS4resok ACCESS4resok; struct ACCESS4res { nfsstat4 status; union { ACCESS4resok resok4; } ACCESS4res_u; }; typedef struct ACCESS4res ACCESS4res; struct CLOSE4args { seqid4 seqid; stateid4 open_stateid; }; typedef struct CLOSE4args CLOSE4args; struct CLOSE4res { nfsstat4 status; union { stateid4 open_stateid; } CLOSE4res_u; }; typedef struct CLOSE4res CLOSE4res; struct COMMIT4args { offset4 offset; count4 count; }; typedef struct COMMIT4args COMMIT4args; struct COMMIT4resok { verifier4 writeverf; }; typedef struct COMMIT4resok COMMIT4resok; struct COMMIT4res { nfsstat4 status; union { COMMIT4resok resok4; } COMMIT4res_u; }; typedef struct COMMIT4res COMMIT4res; struct createtype4 { nfs_ftype4 type; union { linktext4 linkdata; specdata4 devdata; } createtype4_u; }; typedef struct createtype4 createtype4; struct CREATE4args { createtype4 objtype; component4 objname; fattr4 createattrs; }; typedef struct CREATE4args CREATE4args; struct CREATE4resok { change_info4 cinfo; bitmap4 attrset; }; typedef struct CREATE4resok CREATE4resok; struct CREATE4res { nfsstat4 status; union { CREATE4resok resok4; } CREATE4res_u; }; typedef struct CREATE4res CREATE4res; struct DELEGPURGE4args { clientid4 clientid; }; typedef struct DELEGPURGE4args DELEGPURGE4args; struct DELEGPURGE4res { nfsstat4 status; }; typedef struct DELEGPURGE4res DELEGPURGE4res; struct DELEGRETURN4args { stateid4 deleg_stateid; }; typedef struct DELEGRETURN4args DELEGRETURN4args; struct DELEGRETURN4res { nfsstat4 status; }; typedef struct DELEGRETURN4res DELEGRETURN4res; struct GETATTR4args { bitmap4 attr_request; }; typedef struct GETATTR4args GETATTR4args; struct GETATTR4resok { fattr4 obj_attributes; }; typedef struct GETATTR4resok GETATTR4resok; struct GETATTR4res { nfsstat4 status; union { GETATTR4resok resok4; } GETATTR4res_u; }; typedef struct GETATTR4res GETATTR4res; struct GETFH4resok { nfs_fh4 object; }; typedef struct GETFH4resok GETFH4resok; struct GETFH4res { nfsstat4 status; union { GETFH4resok resok4; } GETFH4res_u; }; typedef struct GETFH4res GETFH4res; struct LINK4args { component4 newname; }; typedef struct LINK4args LINK4args; struct LINK4resok { change_info4 cinfo; }; typedef struct LINK4resok LINK4resok; struct LINK4res { nfsstat4 status; union { LINK4resok resok4; } LINK4res_u; }; typedef struct LINK4res LINK4res; struct open_to_lock_owner4 { seqid4 open_seqid; stateid4 open_stateid; seqid4 lock_seqid; lock_owner4 lock_owner; }; typedef struct open_to_lock_owner4 open_to_lock_owner4; struct exist_lock_owner4 { stateid4 lock_stateid; seqid4 lock_seqid; }; typedef struct exist_lock_owner4 exist_lock_owner4; struct locker4 { bool_t new_lock_owner; union { open_to_lock_owner4 open_owner; exist_lock_owner4 lock_owner; } locker4_u; }; typedef struct locker4 locker4; struct LOCK4args { nfs_lock_type4 locktype; bool_t reclaim; offset4 offset; length4 length; locker4 locker; }; typedef struct LOCK4args LOCK4args; struct LOCK4denied { offset4 offset; length4 length; nfs_lock_type4 locktype; lock_owner4 owner; }; typedef struct LOCK4denied LOCK4denied; struct LOCK4resok { stateid4 lock_stateid; }; typedef struct LOCK4resok LOCK4resok; struct LOCK4res { nfsstat4 status; union { LOCK4resok resok4; LOCK4denied denied; } LOCK4res_u; }; typedef struct LOCK4res LOCK4res; struct LOCKT4args { nfs_lock_type4 locktype; offset4 offset; length4 length; lock_owner4 owner; }; typedef struct LOCKT4args LOCKT4args; struct LOCKT4res { nfsstat4 status; union { LOCK4denied denied; } LOCKT4res_u; }; typedef struct LOCKT4res LOCKT4res; struct LOCKU4args { nfs_lock_type4 locktype; seqid4 seqid; stateid4 lock_stateid; offset4 offset; length4 length; }; typedef struct LOCKU4args LOCKU4args; struct LOCKU4res { nfsstat4 status; union { stateid4 lock_stateid; } LOCKU4res_u; }; typedef struct LOCKU4res LOCKU4res; struct LOOKUP4args { component4 objname; }; typedef struct LOOKUP4args LOOKUP4args; struct LOOKUP4res { nfsstat4 status; }; typedef struct LOOKUP4res LOOKUP4res; struct LOOKUPP4res { nfsstat4 status; }; typedef struct LOOKUPP4res LOOKUPP4res; struct NVERIFY4args { fattr4 obj_attributes; }; typedef struct NVERIFY4args NVERIFY4args; struct NVERIFY4res { nfsstat4 status; }; typedef struct NVERIFY4res NVERIFY4res; enum createmode4 { UNCHECKED4 = 0, GUARDED4 = 1, EXCLUSIVE4 = 2, }; typedef enum createmode4 createmode4; struct createhow4 { createmode4 mode; union { fattr4 createattrs; verifier4 createverf; } createhow4_u; }; typedef struct createhow4 createhow4; enum opentype4 { OPEN4_NOCREATE = 0, OPEN4_CREATE = 1, }; typedef enum opentype4 opentype4; struct openflag4 { opentype4 opentype; union { createhow4 how; } openflag4_u; }; typedef struct openflag4 openflag4; enum limit_by4 { NFS_LIMIT_SIZE = 1, NFS_LIMIT_BLOCKS = 2, }; typedef enum limit_by4 limit_by4; struct nfs_modified_limit4 { uint32_t num_blocks; uint32_t bytes_per_block; }; typedef struct nfs_modified_limit4 nfs_modified_limit4; struct nfs_space_limit4 { limit_by4 limitby; union { uint64_t filesize; nfs_modified_limit4 mod_blocks; } nfs_space_limit4_u; }; typedef struct nfs_space_limit4 nfs_space_limit4; #define OPEN4_SHARE_ACCESS_READ 0x00000001 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003 #define OPEN4_SHARE_DENY_NONE 0x00000000 #define OPEN4_SHARE_DENY_READ 0x00000001 #define OPEN4_SHARE_DENY_WRITE 0x00000002 #define OPEN4_SHARE_DENY_BOTH 0x00000003 enum open_delegation_type4 { OPEN_DELEGATE_NONE = 0, OPEN_DELEGATE_READ = 1, OPEN_DELEGATE_WRITE = 2, }; typedef enum open_delegation_type4 open_delegation_type4; enum open_claim_type4 { CLAIM_NULL = 0, CLAIM_PREVIOUS = 1, CLAIM_DELEGATE_CUR = 2, CLAIM_DELEGATE_PREV = 3, }; typedef enum open_claim_type4 open_claim_type4; struct open_claim_delegate_cur4 { stateid4 delegate_stateid; component4 file; }; typedef struct open_claim_delegate_cur4 open_claim_delegate_cur4; struct open_claim4 { open_claim_type4 claim; union { component4 file; open_delegation_type4 delegate_type; open_claim_delegate_cur4 delegate_cur_info; component4 file_delegate_prev; } open_claim4_u; }; typedef struct open_claim4 open_claim4; struct OPEN4args { seqid4 seqid; uint32_t share_access; uint32_t share_deny; open_owner4 owner; openflag4 openhow; open_claim4 claim; }; typedef struct OPEN4args OPEN4args; struct open_read_delegation4 { stateid4 stateid; bool_t recall; nfsace4 permissions; }; typedef struct open_read_delegation4 open_read_delegation4; struct open_write_delegation4 { stateid4 stateid; bool_t recall; nfs_space_limit4 space_limit; nfsace4 permissions; }; typedef struct open_write_delegation4 open_write_delegation4; struct open_delegation4 { open_delegation_type4 delegation_type; union { open_read_delegation4 read; open_write_delegation4 write; } open_delegation4_u; }; typedef struct open_delegation4 open_delegation4; #define OPEN4_RESULT_CONFIRM 0x00000002 #define OPEN4_RESULT_LOCKTYPE_POSIX 0x00000004 struct OPEN4resok { stateid4 stateid; change_info4 cinfo; uint32_t rflags; bitmap4 attrset; open_delegation4 delegation; }; typedef struct OPEN4resok OPEN4resok; struct OPEN4res { nfsstat4 status; union { OPEN4resok resok4; } OPEN4res_u; }; typedef struct OPEN4res OPEN4res; struct OPENATTR4args { bool_t createdir; }; typedef struct OPENATTR4args OPENATTR4args; struct OPENATTR4res { nfsstat4 status; }; typedef struct OPENATTR4res OPENATTR4res; struct OPEN_CONFIRM4args { stateid4 open_stateid; seqid4 seqid; }; typedef struct OPEN_CONFIRM4args OPEN_CONFIRM4args; struct OPEN_CONFIRM4resok { stateid4 open_stateid; }; typedef struct OPEN_CONFIRM4resok OPEN_CONFIRM4resok; struct OPEN_CONFIRM4res { nfsstat4 status; union { OPEN_CONFIRM4resok resok4; } OPEN_CONFIRM4res_u; }; typedef struct OPEN_CONFIRM4res OPEN_CONFIRM4res; struct OPEN_DOWNGRADE4args { stateid4 open_stateid; seqid4 seqid; uint32_t share_access; uint32_t share_deny; }; typedef struct OPEN_DOWNGRADE4args OPEN_DOWNGRADE4args; struct OPEN_DOWNGRADE4resok { stateid4 open_stateid; }; typedef struct OPEN_DOWNGRADE4resok OPEN_DOWNGRADE4resok; struct OPEN_DOWNGRADE4res { nfsstat4 status; union { OPEN_DOWNGRADE4resok resok4; } OPEN_DOWNGRADE4res_u; }; typedef struct OPEN_DOWNGRADE4res OPEN_DOWNGRADE4res; struct PUTFH4args { nfs_fh4 object; }; typedef struct PUTFH4args PUTFH4args; struct PUTFH4res { nfsstat4 status; }; typedef struct PUTFH4res PUTFH4res; struct PUTPUBFH4res { nfsstat4 status; }; typedef struct PUTPUBFH4res PUTPUBFH4res; struct PUTROOTFH4res { nfsstat4 status; }; typedef struct PUTROOTFH4res PUTROOTFH4res; struct READ4args { stateid4 stateid; offset4 offset; count4 count; }; typedef struct READ4args READ4args; struct READ4resok { bool_t eof; struct { u_int data_len; char *data_val; } data; }; typedef struct READ4resok READ4resok; struct READ4res { nfsstat4 status; union { READ4resok resok4; } READ4res_u; }; typedef struct READ4res READ4res; struct READDIR4args { nfs_cookie4 cookie; verifier4 cookieverf; count4 dircount; count4 maxcount; bitmap4 attr_request; }; typedef struct READDIR4args READDIR4args; struct entry4 { nfs_cookie4 cookie; component4 name; fattr4 attrs; struct entry4 *nextentry; }; typedef struct entry4 entry4; struct dirlist4 { entry4 *entries; bool_t eof; }; typedef struct dirlist4 dirlist4; struct READDIR4resok { verifier4 cookieverf; dirlist4 reply; }; typedef struct READDIR4resok READDIR4resok; struct READDIR4res { nfsstat4 status; union { READDIR4resok resok4; } READDIR4res_u; }; typedef struct READDIR4res READDIR4res; struct READLINK4resok { linktext4 link; }; typedef struct READLINK4resok READLINK4resok; struct READLINK4res { nfsstat4 status; union { READLINK4resok resok4; } READLINK4res_u; }; typedef struct READLINK4res READLINK4res; struct REMOVE4args { component4 target; }; typedef struct REMOVE4args REMOVE4args; struct REMOVE4resok { change_info4 cinfo; }; typedef struct REMOVE4resok REMOVE4resok; struct REMOVE4res { nfsstat4 status; union { REMOVE4resok resok4; } REMOVE4res_u; }; typedef struct REMOVE4res REMOVE4res; struct RENAME4args { component4 oldname; component4 newname; }; typedef struct RENAME4args RENAME4args; struct RENAME4resok { change_info4 source_cinfo; change_info4 target_cinfo; }; typedef struct RENAME4resok RENAME4resok; struct RENAME4res { nfsstat4 status; union { RENAME4resok resok4; } RENAME4res_u; }; typedef struct RENAME4res RENAME4res; struct RENEW4args { clientid4 clientid; }; typedef struct RENEW4args RENEW4args; struct RENEW4res { nfsstat4 status; }; typedef struct RENEW4res RENEW4res; struct RESTOREFH4res { nfsstat4 status; }; typedef struct RESTOREFH4res RESTOREFH4res; struct SAVEFH4res { nfsstat4 status; }; typedef struct SAVEFH4res SAVEFH4res; struct SECINFO4args { component4 name; }; typedef struct SECINFO4args SECINFO4args; enum rpc_gss_svc_t { RPC_GSS_SVC_NONE = 1, RPC_GSS_SVC_INTEGRITY = 2, RPC_GSS_SVC_PRIVACY = 3, }; typedef enum rpc_gss_svc_t rpc_gss_svc_t; struct rpcsec_gss_info { sec_oid4 oid; qop4 qop; rpc_gss_svc_t service; }; typedef struct rpcsec_gss_info rpcsec_gss_info; struct secinfo4 { uint32_t flavor; union { rpcsec_gss_info flavor_info; } secinfo4_u; }; typedef struct secinfo4 secinfo4; typedef struct { u_int SECINFO4resok_len; secinfo4 *SECINFO4resok_val; } SECINFO4resok; struct SECINFO4res { nfsstat4 status; union { SECINFO4resok resok4; } SECINFO4res_u; }; typedef struct SECINFO4res SECINFO4res; struct SETATTR4args { stateid4 stateid; fattr4 obj_attributes; }; typedef struct SETATTR4args SETATTR4args; struct SETATTR4res { nfsstat4 status; bitmap4 attrsset; }; typedef struct SETATTR4res SETATTR4res; struct SETCLIENTID4args { nfs_client_id4 client; cb_client4 callback; uint32_t callback_ident; }; typedef struct SETCLIENTID4args SETCLIENTID4args; struct SETCLIENTID4resok { clientid4 clientid; verifier4 setclientid_confirm; }; typedef struct SETCLIENTID4resok SETCLIENTID4resok; struct SETCLIENTID4res { nfsstat4 status; union { SETCLIENTID4resok resok4; clientaddr4 client_using; } SETCLIENTID4res_u; }; typedef struct SETCLIENTID4res SETCLIENTID4res; struct SETCLIENTID_CONFIRM4args { clientid4 clientid; verifier4 setclientid_confirm; }; typedef struct SETCLIENTID_CONFIRM4args SETCLIENTID_CONFIRM4args; struct SETCLIENTID_CONFIRM4res { nfsstat4 status; }; typedef struct SETCLIENTID_CONFIRM4res SETCLIENTID_CONFIRM4res; struct VERIFY4args { fattr4 obj_attributes; }; typedef struct VERIFY4args VERIFY4args; struct VERIFY4res { nfsstat4 status; }; typedef struct VERIFY4res VERIFY4res; enum stable_how4 { UNSTABLE4 = 0, DATA_SYNC4 = 1, FILE_SYNC4 = 2, }; typedef enum stable_how4 stable_how4; struct WRITE4args { stateid4 stateid; offset4 offset; stable_how4 stable; struct { u_int data_len; char *data_val; } data; }; typedef struct WRITE4args WRITE4args; struct WRITE4resok { count4 count; stable_how4 committed; verifier4 writeverf; }; typedef struct WRITE4resok WRITE4resok; struct WRITE4res { nfsstat4 status; union { WRITE4resok resok4; } WRITE4res_u; }; typedef struct WRITE4res WRITE4res; struct RELEASE_LOCKOWNER4args { lock_owner4 lock_owner; }; typedef struct RELEASE_LOCKOWNER4args RELEASE_LOCKOWNER4args; struct RELEASE_LOCKOWNER4res { nfsstat4 status; }; typedef struct RELEASE_LOCKOWNER4res RELEASE_LOCKOWNER4res; struct ILLEGAL4res { nfsstat4 status; }; typedef struct ILLEGAL4res ILLEGAL4res; enum nfs_opnum4 { OP_ACCESS = 3, OP_CLOSE = 4, OP_COMMIT = 5, OP_CREATE = 6, OP_DELEGPURGE = 7, OP_DELEGRETURN = 8, OP_GETATTR = 9, OP_GETFH = 10, OP_LINK = 11, OP_LOCK = 12, OP_LOCKT = 13, OP_LOCKU = 14, OP_LOOKUP = 15, OP_LOOKUPP = 16, OP_NVERIFY = 17, OP_OPEN = 18, OP_OPENATTR = 19, OP_OPEN_CONFIRM = 20, OP_OPEN_DOWNGRADE = 21, OP_PUTFH = 22, OP_PUTPUBFH = 23, OP_PUTROOTFH = 24, OP_READ = 25, OP_READDIR = 26, OP_READLINK = 27, OP_REMOVE = 28, OP_RENAME = 29, OP_RENEW = 30, OP_RESTOREFH = 31, OP_SAVEFH = 32, OP_SECINFO = 33, OP_SETATTR = 34, OP_SETCLIENTID = 35, OP_SETCLIENTID_CONFIRM = 36, OP_VERIFY = 37, OP_WRITE = 38, OP_RELEASE_LOCKOWNER = 39, OP_ILLEGAL = 10044, }; typedef enum nfs_opnum4 nfs_opnum4; struct nfs_argop4 { nfs_opnum4 argop; union { ACCESS4args opaccess; CLOSE4args opclose; COMMIT4args opcommit; CREATE4args opcreate; DELEGPURGE4args opdelegpurge; DELEGRETURN4args opdelegreturn; GETATTR4args opgetattr; LINK4args oplink; LOCK4args oplock; LOCKT4args oplockt; LOCKU4args oplocku; LOOKUP4args oplookup; NVERIFY4args opnverify; OPEN4args opopen; OPENATTR4args opopenattr; OPEN_CONFIRM4args opopen_confirm; OPEN_DOWNGRADE4args opopen_downgrade; PUTFH4args opputfh; READ4args opread; READDIR4args opreaddir; REMOVE4args opremove; RENAME4args oprename; RENEW4args oprenew; SECINFO4args opsecinfo; SETATTR4args opsetattr; SETCLIENTID4args opsetclientid; SETCLIENTID_CONFIRM4args opsetclientid_confirm; VERIFY4args opverify; WRITE4args opwrite; RELEASE_LOCKOWNER4args oprelease_lockowner; } nfs_argop4_u; }; typedef struct nfs_argop4 nfs_argop4; struct nfs_resop4 { nfs_opnum4 resop; union { ACCESS4res opaccess; CLOSE4res opclose; COMMIT4res opcommit; CREATE4res opcreate; DELEGPURGE4res opdelegpurge; DELEGRETURN4res opdelegreturn; GETATTR4res opgetattr; GETFH4res opgetfh; LINK4res oplink; LOCK4res oplock; LOCKT4res oplockt; LOCKU4res oplocku; LOOKUP4res oplookup; LOOKUPP4res oplookupp; NVERIFY4res opnverify; OPEN4res opopen; OPENATTR4res opopenattr; OPEN_CONFIRM4res opopen_confirm; OPEN_DOWNGRADE4res opopen_downgrade; PUTFH4res opputfh; PUTPUBFH4res opputpubfh; PUTROOTFH4res opputrootfh; READ4res opread; READDIR4res opreaddir; READLINK4res opreadlink; REMOVE4res opremove; RENAME4res oprename; RENEW4res oprenew; RESTOREFH4res oprestorefh; SAVEFH4res opsavefh; SECINFO4res opsecinfo; SETATTR4res opsetattr; SETCLIENTID4res opsetclientid; SETCLIENTID_CONFIRM4res opsetclientid_confirm; VERIFY4res opverify; WRITE4res opwrite; RELEASE_LOCKOWNER4res oprelease_lockowner; ILLEGAL4res opillegal; } nfs_resop4_u; }; typedef struct nfs_resop4 nfs_resop4; struct COMPOUND4args { utf8str_cs tag; uint32_t minorversion; struct { u_int argarray_len; nfs_argop4 *argarray_val; } argarray; }; typedef struct COMPOUND4args COMPOUND4args; struct COMPOUND4res { nfsstat4 status; utf8str_cs tag; struct { u_int resarray_len; nfs_resop4 *resarray_val; } resarray; }; typedef struct COMPOUND4res COMPOUND4res; struct CB_GETATTR4args { nfs_fh4 fh; bitmap4 attr_request; }; typedef struct CB_GETATTR4args CB_GETATTR4args; struct CB_GETATTR4resok { fattr4 obj_attributes; }; typedef struct CB_GETATTR4resok CB_GETATTR4resok; struct CB_GETATTR4res { nfsstat4 status; union { CB_GETATTR4resok resok4; } CB_GETATTR4res_u; }; typedef struct CB_GETATTR4res CB_GETATTR4res; struct CB_RECALL4args { stateid4 stateid; bool_t truncate; nfs_fh4 fh; }; typedef struct CB_RECALL4args CB_RECALL4args; struct CB_RECALL4res { nfsstat4 status; }; typedef struct CB_RECALL4res CB_RECALL4res; struct CB_ILLEGAL4res { nfsstat4 status; }; typedef struct CB_ILLEGAL4res CB_ILLEGAL4res; enum nfs_cb_opnum4 { NFS4_OP_CB_GETATTR = 3, NFS4_OP_CB_RECALL = 4, NFS4_OP_CB_ILLEGAL = 10044, }; typedef enum nfs_cb_opnum4 nfs_cb_opnum4; struct nfs_cb_argop4 { u_int argop; union { CB_GETATTR4args opcbgetattr; CB_RECALL4args opcbrecall; } nfs_cb_argop4_u; }; typedef struct nfs_cb_argop4 nfs_cb_argop4; struct nfs_cb_resop4 { u_int resop; union { CB_GETATTR4res opcbgetattr; CB_RECALL4res opcbrecall; CB_ILLEGAL4res opcbillegal; } nfs_cb_resop4_u; }; typedef struct nfs_cb_resop4 nfs_cb_resop4; struct CB_COMPOUND4args { utf8str_cs tag; uint32_t minorversion; uint32_t callback_ident; struct { u_int argarray_len; nfs_cb_argop4 *argarray_val; } argarray; }; typedef struct CB_COMPOUND4args CB_COMPOUND4args; struct CB_COMPOUND4res { nfsstat4 status; utf8str_cs tag; struct { u_int resarray_len; nfs_cb_resop4 *resarray_val; } resarray; }; typedef struct CB_COMPOUND4res CB_COMPOUND4res; #define NFS4_PROGRAM 100003 #define NFS_V4 4 #if defined(__STDC__) || defined(__cplusplus) #define NFSPROC4_NULL 0 extern void * nfsproc4_null_4(void *, CLIENT *); extern void * nfsproc4_null_4_svc(void *, struct svc_req *); #define NFSPROC4_COMPOUND 1 extern COMPOUND4res * nfsproc4_compound_4(COMPOUND4args *, CLIENT *); extern COMPOUND4res * nfsproc4_compound_4_svc(COMPOUND4args *, struct svc_req *); extern int nfs4_program_4_freeresult (SVCXPRT *, xdrproc_t, caddr_t); #else /* K&R C */ #define NFSPROC4_NULL 0 extern void * nfsproc4_null_4(); extern void * nfsproc4_null_4_svc(); #define NFSPROC4_COMPOUND 1 extern COMPOUND4res * nfsproc4_compound_4(); extern COMPOUND4res * nfsproc4_compound_4_svc(); extern int nfs4_program_4_freeresult (); #endif /* K&R C */ #define NFS4_CALLBACK 0x40000000 #define NFS_CB 1 #if defined(__STDC__) || defined(__cplusplus) #define CB_NULL 0 extern void * cb_null_1(void *, CLIENT *); extern void * cb_null_1_svc(void *, struct svc_req *); #define CB_COMPOUND 1 extern CB_COMPOUND4res * cb_compound_1(CB_COMPOUND4args *, CLIENT *); extern CB_COMPOUND4res * cb_compound_1_svc(CB_COMPOUND4args *, struct svc_req *); extern int nfs4_callback_1_freeresult (SVCXPRT *, xdrproc_t, caddr_t); #else /* K&R C */ #define CB_NULL 0 extern void * cb_null_1(); extern void * cb_null_1_svc(); #define CB_COMPOUND 1 extern CB_COMPOUND4res * cb_compound_1(); extern CB_COMPOUND4res * cb_compound_1_svc(); extern int nfs4_callback_1_freeresult (); #endif /* K&R C */ /* the xdr functions */ #if defined(__STDC__) || defined(__cplusplus) extern bool_t xdr_nfs_ftype4 (XDR *, nfs_ftype4*); extern bool_t xdr_nfsstat4 (XDR *, nfsstat4*); extern bool_t xdr_bitmap4 (XDR *, bitmap4*); extern bool_t xdr_offset4 (XDR *, offset4*); extern bool_t xdr_count4 (XDR *, count4*); extern bool_t xdr_length4 (XDR *, length4*); extern bool_t xdr_clientid4 (XDR *, clientid4*); extern bool_t xdr_seqid4 (XDR *, seqid4*); extern bool_t xdr_utf8string (XDR *, utf8string*); extern bool_t xdr_utf8str_cis (XDR *, utf8str_cis*); extern bool_t xdr_utf8str_cs (XDR *, utf8str_cs*); extern bool_t xdr_utf8str_mixed (XDR *, utf8str_mixed*); extern bool_t xdr_component4 (XDR *, component4*); extern bool_t xdr_pathname4 (XDR *, pathname4*); extern bool_t xdr_nfs_lockid4 (XDR *, nfs_lockid4*); extern bool_t xdr_nfs_cookie4 (XDR *, nfs_cookie4*); extern bool_t xdr_linktext4 (XDR *, linktext4*); extern bool_t xdr_sec_oid4 (XDR *, sec_oid4*); extern bool_t xdr_qop4 (XDR *, qop4*); extern bool_t xdr_mode4 (XDR *, mode4*); extern bool_t xdr_changeid4 (XDR *, changeid4*); extern bool_t xdr_verifier4 (XDR *, verifier4); extern bool_t xdr_nfstime4 (XDR *, nfstime4*); extern bool_t xdr_time_how4 (XDR *, time_how4*); extern bool_t xdr_settime4 (XDR *, settime4*); extern bool_t xdr_nfs_fh4 (XDR *, nfs_fh4*); extern bool_t xdr_fsid4 (XDR *, fsid4*); extern bool_t xdr_fs_location4 (XDR *, fs_location4*); extern bool_t xdr_fs_locations4 (XDR *, fs_locations4*); extern bool_t xdr_acetype4 (XDR *, acetype4*); extern bool_t xdr_aceflag4 (XDR *, aceflag4*); extern bool_t xdr_acemask4 (XDR *, acemask4*); extern bool_t xdr_nfsace4 (XDR *, nfsace4*); extern bool_t xdr_specdata4 (XDR *, specdata4*); extern bool_t xdr_fattr4_supported_attrs (XDR *, fattr4_supported_attrs*); extern bool_t xdr_fattr4_type (XDR *, fattr4_type*); extern bool_t xdr_fattr4_fh_expire_type (XDR *, fattr4_fh_expire_type*); extern bool_t xdr_fattr4_change (XDR *, fattr4_change*); extern bool_t xdr_fattr4_size (XDR *, fattr4_size*); extern bool_t xdr_fattr4_link_support (XDR *, fattr4_link_support*); extern bool_t xdr_fattr4_symlink_support (XDR *, fattr4_symlink_support*); extern bool_t xdr_fattr4_named_attr (XDR *, fattr4_named_attr*); extern bool_t xdr_fattr4_fsid (XDR *, fattr4_fsid*); extern bool_t xdr_fattr4_unique_handles (XDR *, fattr4_unique_handles*); extern bool_t xdr_fattr4_lease_time (XDR *, fattr4_lease_time*); extern bool_t xdr_fattr4_rdattr_error (XDR *, fattr4_rdattr_error*); extern bool_t xdr_fattr4_acl (XDR *, fattr4_acl*); extern bool_t xdr_fattr4_aclsupport (XDR *, fattr4_aclsupport*); extern bool_t xdr_fattr4_archive (XDR *, fattr4_archive*); extern bool_t xdr_fattr4_cansettime (XDR *, fattr4_cansettime*); extern bool_t xdr_fattr4_case_insensitive (XDR *, fattr4_case_insensitive*); extern bool_t xdr_fattr4_case_preserving (XDR *, fattr4_case_preserving*); extern bool_t xdr_fattr4_chown_restricted (XDR *, fattr4_chown_restricted*); extern bool_t xdr_fattr4_fileid (XDR *, fattr4_fileid*); extern bool_t xdr_fattr4_files_avail (XDR *, fattr4_files_avail*); extern bool_t xdr_fattr4_filehandle (XDR *, fattr4_filehandle*); extern bool_t xdr_fattr4_files_free (XDR *, fattr4_files_free*); extern bool_t xdr_fattr4_files_total (XDR *, fattr4_files_total*); extern bool_t xdr_fattr4_fs_locations (XDR *, fattr4_fs_locations*); extern bool_t xdr_fattr4_hidden (XDR *, fattr4_hidden*); extern bool_t xdr_fattr4_homogeneous (XDR *, fattr4_homogeneous*); extern bool_t xdr_fattr4_maxfilesize (XDR *, fattr4_maxfilesize*); extern bool_t xdr_fattr4_maxlink (XDR *, fattr4_maxlink*); extern bool_t xdr_fattr4_maxname (XDR *, fattr4_maxname*); extern bool_t xdr_fattr4_maxread (XDR *, fattr4_maxread*); extern bool_t xdr_fattr4_maxwrite (XDR *, fattr4_maxwrite*); extern bool_t xdr_fattr4_mimetype (XDR *, fattr4_mimetype*); extern bool_t xdr_fattr4_mode (XDR *, fattr4_mode*); extern bool_t xdr_fattr4_mounted_on_fileid (XDR *, fattr4_mounted_on_fileid*); extern bool_t xdr_fattr4_no_trunc (XDR *, fattr4_no_trunc*); extern bool_t xdr_fattr4_numlinks (XDR *, fattr4_numlinks*); extern bool_t xdr_fattr4_owner (XDR *, fattr4_owner*); extern bool_t xdr_fattr4_owner_group (XDR *, fattr4_owner_group*); extern bool_t xdr_fattr4_quota_avail_hard (XDR *, fattr4_quota_avail_hard*); extern bool_t xdr_fattr4_quota_avail_soft (XDR *, fattr4_quota_avail_soft*); extern bool_t xdr_fattr4_quota_used (XDR *, fattr4_quota_used*); extern bool_t xdr_fattr4_rawdev (XDR *, fattr4_rawdev*); extern bool_t xdr_fattr4_space_avail (XDR *, fattr4_space_avail*); extern bool_t xdr_fattr4_space_free (XDR *, fattr4_space_free*); extern bool_t xdr_fattr4_space_total (XDR *, fattr4_space_total*); extern bool_t xdr_fattr4_space_used (XDR *, fattr4_space_used*); extern bool_t xdr_fattr4_system (XDR *, fattr4_system*); extern bool_t xdr_fattr4_time_access (XDR *, fattr4_time_access*); extern bool_t xdr_fattr4_time_access_set (XDR *, fattr4_time_access_set*); extern bool_t xdr_fattr4_time_backup (XDR *, fattr4_time_backup*); extern bool_t xdr_fattr4_time_create (XDR *, fattr4_time_create*); extern bool_t xdr_fattr4_time_delta (XDR *, fattr4_time_delta*); extern bool_t xdr_fattr4_time_metadata (XDR *, fattr4_time_metadata*); extern bool_t xdr_fattr4_time_modify (XDR *, fattr4_time_modify*); extern bool_t xdr_fattr4_time_modify_set (XDR *, fattr4_time_modify_set*); extern bool_t xdr_attrlist4 (XDR *, attrlist4*); extern bool_t xdr_fattr4 (XDR *, fattr4*); extern bool_t xdr_change_info4 (XDR *, change_info4*); extern bool_t xdr_clientaddr4 (XDR *, clientaddr4*); extern bool_t xdr_cb_client4 (XDR *, cb_client4*); extern bool_t xdr_stateid4 (XDR *, stateid4*); extern bool_t xdr_nfs_client_id4 (XDR *, nfs_client_id4*); extern bool_t xdr_open_owner4 (XDR *, open_owner4*); extern bool_t xdr_lock_owner4 (XDR *, lock_owner4*); extern bool_t xdr_nfs_lock_type4 (XDR *, nfs_lock_type4*); extern bool_t xdr_ACCESS4args (XDR *, ACCESS4args*); extern bool_t xdr_ACCESS4resok (XDR *, ACCESS4resok*); extern bool_t xdr_ACCESS4res (XDR *, ACCESS4res*); extern bool_t xdr_CLOSE4args (XDR *, CLOSE4args*); extern bool_t xdr_CLOSE4res (XDR *, CLOSE4res*); extern bool_t xdr_COMMIT4args (XDR *, COMMIT4args*); extern bool_t xdr_COMMIT4resok (XDR *, COMMIT4resok*); extern bool_t xdr_COMMIT4res (XDR *, COMMIT4res*); extern bool_t xdr_createtype4 (XDR *, createtype4*); extern bool_t xdr_CREATE4args (XDR *, CREATE4args*); extern bool_t xdr_CREATE4resok (XDR *, CREATE4resok*); extern bool_t xdr_CREATE4res (XDR *, CREATE4res*); extern bool_t xdr_DELEGPURGE4args (XDR *, DELEGPURGE4args*); extern bool_t xdr_DELEGPURGE4res (XDR *, DELEGPURGE4res*); extern bool_t xdr_DELEGRETURN4args (XDR *, DELEGRETURN4args*); extern bool_t xdr_DELEGRETURN4res (XDR *, DELEGRETURN4res*); extern bool_t xdr_GETATTR4args (XDR *, GETATTR4args*); extern bool_t xdr_GETATTR4resok (XDR *, GETATTR4resok*); extern bool_t xdr_GETATTR4res (XDR *, GETATTR4res*); extern bool_t xdr_GETFH4resok (XDR *, GETFH4resok*); extern bool_t xdr_GETFH4res (XDR *, GETFH4res*); extern bool_t xdr_LINK4args (XDR *, LINK4args*); extern bool_t xdr_LINK4resok (XDR *, LINK4resok*); extern bool_t xdr_LINK4res (XDR *, LINK4res*); extern bool_t xdr_open_to_lock_owner4 (XDR *, open_to_lock_owner4*); extern bool_t xdr_exist_lock_owner4 (XDR *, exist_lock_owner4*); extern bool_t xdr_locker4 (XDR *, locker4*); extern bool_t xdr_LOCK4args (XDR *, LOCK4args*); extern bool_t xdr_LOCK4denied (XDR *, LOCK4denied*); extern bool_t xdr_LOCK4resok (XDR *, LOCK4resok*); extern bool_t xdr_LOCK4res (XDR *, LOCK4res*); extern bool_t xdr_LOCKT4args (XDR *, LOCKT4args*); extern bool_t xdr_LOCKT4res (XDR *, LOCKT4res*); extern bool_t xdr_LOCKU4args (XDR *, LOCKU4args*); extern bool_t xdr_LOCKU4res (XDR *, LOCKU4res*); extern bool_t xdr_LOOKUP4args (XDR *, LOOKUP4args*); extern bool_t xdr_LOOKUP4res (XDR *, LOOKUP4res*); extern bool_t xdr_LOOKUPP4res (XDR *, LOOKUPP4res*); extern bool_t xdr_NVERIFY4args (XDR *, NVERIFY4args*); extern bool_t xdr_NVERIFY4res (XDR *, NVERIFY4res*); extern bool_t xdr_createmode4 (XDR *, createmode4*); extern bool_t xdr_createhow4 (XDR *, createhow4*); extern bool_t xdr_opentype4 (XDR *, opentype4*); extern bool_t xdr_openflag4 (XDR *, openflag4*); extern bool_t xdr_limit_by4 (XDR *, limit_by4*); extern bool_t xdr_nfs_modified_limit4 (XDR *, nfs_modified_limit4*); extern bool_t xdr_nfs_space_limit4 (XDR *, nfs_space_limit4*); extern bool_t xdr_open_delegation_type4 (XDR *, open_delegation_type4*); extern bool_t xdr_open_claim_type4 (XDR *, open_claim_type4*); extern bool_t xdr_open_claim_delegate_cur4 (XDR *, open_claim_delegate_cur4*); extern bool_t xdr_open_claim4 (XDR *, open_claim4*); extern bool_t xdr_OPEN4args (XDR *, OPEN4args*); extern bool_t xdr_open_read_delegation4 (XDR *, open_read_delegation4*); extern bool_t xdr_open_write_delegation4 (XDR *, open_write_delegation4*); extern bool_t xdr_open_delegation4 (XDR *, open_delegation4*); extern bool_t xdr_OPEN4resok (XDR *, OPEN4resok*); extern bool_t xdr_OPEN4res (XDR *, OPEN4res*); extern bool_t xdr_OPENATTR4args (XDR *, OPENATTR4args*); extern bool_t xdr_OPENATTR4res (XDR *, OPENATTR4res*); extern bool_t xdr_OPEN_CONFIRM4args (XDR *, OPEN_CONFIRM4args*); extern bool_t xdr_OPEN_CONFIRM4resok (XDR *, OPEN_CONFIRM4resok*); extern bool_t xdr_OPEN_CONFIRM4res (XDR *, OPEN_CONFIRM4res*); extern bool_t xdr_OPEN_DOWNGRADE4args (XDR *, OPEN_DOWNGRADE4args*); extern bool_t xdr_OPEN_DOWNGRADE4resok (XDR *, OPEN_DOWNGRADE4resok*); extern bool_t xdr_OPEN_DOWNGRADE4res (XDR *, OPEN_DOWNGRADE4res*); extern bool_t xdr_PUTFH4args (XDR *, PUTFH4args*); extern bool_t xdr_PUTFH4res (XDR *, PUTFH4res*); extern bool_t xdr_PUTPUBFH4res (XDR *, PUTPUBFH4res*); extern bool_t xdr_PUTROOTFH4res (XDR *, PUTROOTFH4res*); extern bool_t xdr_READ4args (XDR *, READ4args*); extern bool_t xdr_READ4resok (XDR *, READ4resok*); extern bool_t xdr_READ4res (XDR *, READ4res*); extern bool_t xdr_READDIR4args (XDR *, READDIR4args*); extern bool_t xdr_entry4 (XDR *, entry4*); extern bool_t xdr_dirlist4 (XDR *, dirlist4*); extern bool_t xdr_READDIR4resok (XDR *, READDIR4resok*); extern bool_t xdr_READDIR4res (XDR *, READDIR4res*); extern bool_t xdr_READLINK4resok (XDR *, READLINK4resok*); extern bool_t xdr_READLINK4res (XDR *, READLINK4res*); extern bool_t xdr_REMOVE4args (XDR *, REMOVE4args*); extern bool_t xdr_REMOVE4resok (XDR *, REMOVE4resok*); extern bool_t xdr_REMOVE4res (XDR *, REMOVE4res*); extern bool_t xdr_RENAME4args (XDR *, RENAME4args*); extern bool_t xdr_RENAME4resok (XDR *, RENAME4resok*); extern bool_t xdr_RENAME4res (XDR *, RENAME4res*); extern bool_t xdr_RENEW4args (XDR *, RENEW4args*); extern bool_t xdr_RENEW4res (XDR *, RENEW4res*); extern bool_t xdr_RESTOREFH4res (XDR *, RESTOREFH4res*); extern bool_t xdr_SAVEFH4res (XDR *, SAVEFH4res*); extern bool_t xdr_SECINFO4args (XDR *, SECINFO4args*); extern bool_t xdr_rpc_gss_svc_t (XDR *, rpc_gss_svc_t*); extern bool_t xdr_rpcsec_gss_info (XDR *, rpcsec_gss_info*); extern bool_t xdr_secinfo4 (XDR *, secinfo4*); extern bool_t xdr_SECINFO4resok (XDR *, SECINFO4resok*); extern bool_t xdr_SECINFO4res (XDR *, SECINFO4res*); extern bool_t xdr_SETATTR4args (XDR *, SETATTR4args*); extern bool_t xdr_SETATTR4res (XDR *, SETATTR4res*); extern bool_t xdr_SETCLIENTID4args (XDR *, SETCLIENTID4args*); extern bool_t xdr_SETCLIENTID4resok (XDR *, SETCLIENTID4resok*); extern bool_t xdr_SETCLIENTID4res (XDR *, SETCLIENTID4res*); extern bool_t xdr_SETCLIENTID_CONFIRM4args (XDR *, SETCLIENTID_CONFIRM4args*); extern bool_t xdr_SETCLIENTID_CONFIRM4res (XDR *, SETCLIENTID_CONFIRM4res*); extern bool_t xdr_VERIFY4args (XDR *, VERIFY4args*); extern bool_t xdr_VERIFY4res (XDR *, VERIFY4res*); extern bool_t xdr_stable_how4 (XDR *, stable_how4*); extern bool_t xdr_WRITE4args (XDR *, WRITE4args*); extern bool_t xdr_WRITE4resok (XDR *, WRITE4resok*); extern bool_t xdr_WRITE4res (XDR *, WRITE4res*); extern bool_t xdr_RELEASE_LOCKOWNER4args (XDR *, RELEASE_LOCKOWNER4args*); extern bool_t xdr_RELEASE_LOCKOWNER4res (XDR *, RELEASE_LOCKOWNER4res*); extern bool_t xdr_ILLEGAL4res (XDR *, ILLEGAL4res*); extern bool_t xdr_nfs_opnum4 (XDR *, nfs_opnum4*); extern bool_t xdr_nfs_argop4 (XDR *, nfs_argop4*); extern bool_t xdr_nfs_resop4 (XDR *, nfs_resop4*); extern bool_t xdr_COMPOUND4args (XDR *, COMPOUND4args*); extern bool_t xdr_COMPOUND4res (XDR *, COMPOUND4res*); extern bool_t xdr_CB_GETATTR4args (XDR *, CB_GETATTR4args*); extern bool_t xdr_CB_GETATTR4resok (XDR *, CB_GETATTR4resok*); extern bool_t xdr_CB_GETATTR4res (XDR *, CB_GETATTR4res*); extern bool_t xdr_CB_RECALL4args (XDR *, CB_RECALL4args*); extern bool_t xdr_CB_RECALL4res (XDR *, CB_RECALL4res*); extern bool_t xdr_CB_ILLEGAL4res (XDR *, CB_ILLEGAL4res*); extern bool_t xdr_nfs_cb_opnum4 (XDR *, nfs_cb_opnum4*); extern bool_t xdr_nfs_cb_argop4 (XDR *, nfs_cb_argop4*); extern bool_t xdr_nfs_cb_resop4 (XDR *, nfs_cb_resop4*); extern bool_t xdr_CB_COMPOUND4args (XDR *, CB_COMPOUND4args*); extern bool_t xdr_CB_COMPOUND4res (XDR *, CB_COMPOUND4res*); #else /* K&R C */ extern bool_t xdr_nfs_ftype4 (); extern bool_t xdr_nfsstat4 (); extern bool_t xdr_bitmap4 (); extern bool_t xdr_offset4 (); extern bool_t xdr_count4 (); extern bool_t xdr_length4 (); extern bool_t xdr_clientid4 (); extern bool_t xdr_seqid4 (); extern bool_t xdr_utf8string (); extern bool_t xdr_utf8str_cis (); extern bool_t xdr_utf8str_cs (); extern bool_t xdr_utf8str_mixed (); extern bool_t xdr_component4 (); extern bool_t xdr_pathname4 (); extern bool_t xdr_nfs_lockid4 (); extern bool_t xdr_nfs_cookie4 (); extern bool_t xdr_linktext4 (); extern bool_t xdr_sec_oid4 (); extern bool_t xdr_qop4 (); extern bool_t xdr_mode4 (); extern bool_t xdr_changeid4 (); extern bool_t xdr_verifier4 (); extern bool_t xdr_nfstime4 (); extern bool_t xdr_time_how4 (); extern bool_t xdr_settime4 (); extern bool_t xdr_nfs_fh4 (); extern bool_t xdr_fsid4 (); extern bool_t xdr_fs_location4 (); extern bool_t xdr_fs_locations4 (); extern bool_t xdr_acetype4 (); extern bool_t xdr_aceflag4 (); extern bool_t xdr_acemask4 (); extern bool_t xdr_nfsace4 (); extern bool_t xdr_specdata4 (); extern bool_t xdr_fattr4_supported_attrs (); extern bool_t xdr_fattr4_type (); extern bool_t xdr_fattr4_fh_expire_type (); extern bool_t xdr_fattr4_change (); extern bool_t xdr_fattr4_size (); extern bool_t xdr_fattr4_link_support (); extern bool_t xdr_fattr4_symlink_support (); extern bool_t xdr_fattr4_named_attr (); extern bool_t xdr_fattr4_fsid (); extern bool_t xdr_fattr4_unique_handles (); extern bool_t xdr_fattr4_lease_time (); extern bool_t xdr_fattr4_rdattr_error (); extern bool_t xdr_fattr4_acl (); extern bool_t xdr_fattr4_aclsupport (); extern bool_t xdr_fattr4_archive (); extern bool_t xdr_fattr4_cansettime (); extern bool_t xdr_fattr4_case_insensitive (); extern bool_t xdr_fattr4_case_preserving (); extern bool_t xdr_fattr4_chown_restricted (); extern bool_t xdr_fattr4_fileid (); extern bool_t xdr_fattr4_files_avail (); extern bool_t xdr_fattr4_filehandle (); extern bool_t xdr_fattr4_files_free (); extern bool_t xdr_fattr4_files_total (); extern bool_t xdr_fattr4_fs_locations (); extern bool_t xdr_fattr4_hidden (); extern bool_t xdr_fattr4_homogeneous (); extern bool_t xdr_fattr4_maxfilesize (); extern bool_t xdr_fattr4_maxlink (); extern bool_t xdr_fattr4_maxname (); extern bool_t xdr_fattr4_maxread (); extern bool_t xdr_fattr4_maxwrite (); extern bool_t xdr_fattr4_mimetype (); extern bool_t xdr_fattr4_mode (); extern bool_t xdr_fattr4_mounted_on_fileid (); extern bool_t xdr_fattr4_no_trunc (); extern bool_t xdr_fattr4_numlinks (); extern bool_t xdr_fattr4_owner (); extern bool_t xdr_fattr4_owner_group (); extern bool_t xdr_fattr4_quota_avail_hard (); extern bool_t xdr_fattr4_quota_avail_soft (); extern bool_t xdr_fattr4_quota_used (); extern bool_t xdr_fattr4_rawdev (); extern bool_t xdr_fattr4_space_avail (); extern bool_t xdr_fattr4_space_free (); extern bool_t xdr_fattr4_space_total (); extern bool_t xdr_fattr4_space_used (); extern bool_t xdr_fattr4_system (); extern bool_t xdr_fattr4_time_access (); extern bool_t xdr_fattr4_time_access_set (); extern bool_t xdr_fattr4_time_backup (); extern bool_t xdr_fattr4_time_create (); extern bool_t xdr_fattr4_time_delta (); extern bool_t xdr_fattr4_time_metadata (); extern bool_t xdr_fattr4_time_modify (); extern bool_t xdr_fattr4_time_modify_set (); extern bool_t xdr_attrlist4 (); extern bool_t xdr_fattr4 (); extern bool_t xdr_change_info4 (); extern bool_t xdr_clientaddr4 (); extern bool_t xdr_cb_client4 (); extern bool_t xdr_stateid4 (); extern bool_t xdr_nfs_client_id4 (); extern bool_t xdr_open_owner4 (); extern bool_t xdr_lock_owner4 (); extern bool_t xdr_nfs_lock_type4 (); extern bool_t xdr_ACCESS4args (); extern bool_t xdr_ACCESS4resok (); extern bool_t xdr_ACCESS4res (); extern bool_t xdr_CLOSE4args (); extern bool_t xdr_CLOSE4res (); extern bool_t xdr_COMMIT4args (); extern bool_t xdr_COMMIT4resok (); extern bool_t xdr_COMMIT4res (); extern bool_t xdr_createtype4 (); extern bool_t xdr_CREATE4args (); extern bool_t xdr_CREATE4resok (); extern bool_t xdr_CREATE4res (); extern bool_t xdr_DELEGPURGE4args (); extern bool_t xdr_DELEGPURGE4res (); extern bool_t xdr_DELEGRETURN4args (); extern bool_t xdr_DELEGRETURN4res (); extern bool_t xdr_GETATTR4args (); extern bool_t xdr_GETATTR4resok (); extern bool_t xdr_GETATTR4res (); extern bool_t xdr_GETFH4resok (); extern bool_t xdr_GETFH4res (); extern bool_t xdr_LINK4args (); extern bool_t xdr_LINK4resok (); extern bool_t xdr_LINK4res (); extern bool_t xdr_open_to_lock_owner4 (); extern bool_t xdr_exist_lock_owner4 (); extern bool_t xdr_locker4 (); extern bool_t xdr_LOCK4args (); extern bool_t xdr_LOCK4denied (); extern bool_t xdr_LOCK4resok (); extern bool_t xdr_LOCK4res (); extern bool_t xdr_LOCKT4args (); extern bool_t xdr_LOCKT4res (); extern bool_t xdr_LOCKU4args (); extern bool_t xdr_LOCKU4res (); extern bool_t xdr_LOOKUP4args (); extern bool_t xdr_LOOKUP4res (); extern bool_t xdr_LOOKUPP4res (); extern bool_t xdr_NVERIFY4args (); extern bool_t xdr_NVERIFY4res (); extern bool_t xdr_createmode4 (); extern bool_t xdr_createhow4 (); extern bool_t xdr_opentype4 (); extern bool_t xdr_openflag4 (); extern bool_t xdr_limit_by4 (); extern bool_t xdr_nfs_modified_limit4 (); extern bool_t xdr_nfs_space_limit4 (); extern bool_t xdr_open_delegation_type4 (); extern bool_t xdr_open_claim_type4 (); extern bool_t xdr_open_claim_delegate_cur4 (); extern bool_t xdr_open_claim4 (); extern bool_t xdr_OPEN4args (); extern bool_t xdr_open_read_delegation4 (); extern bool_t xdr_open_write_delegation4 (); extern bool_t xdr_open_delegation4 (); extern bool_t xdr_OPEN4resok (); extern bool_t xdr_OPEN4res (); extern bool_t xdr_OPENATTR4args (); extern bool_t xdr_OPENATTR4res (); extern bool_t xdr_OPEN_CONFIRM4args (); extern bool_t xdr_OPEN_CONFIRM4resok (); extern bool_t xdr_OPEN_CONFIRM4res (); extern bool_t xdr_OPEN_DOWNGRADE4args (); extern bool_t xdr_OPEN_DOWNGRADE4resok (); extern bool_t xdr_OPEN_DOWNGRADE4res (); extern bool_t xdr_PUTFH4args (); extern bool_t xdr_PUTFH4res (); extern bool_t xdr_PUTPUBFH4res (); extern bool_t xdr_PUTROOTFH4res (); extern bool_t xdr_READ4args (); extern bool_t xdr_READ4resok (); extern bool_t xdr_READ4res (); extern bool_t xdr_READDIR4args (); extern bool_t xdr_entry4 (); extern bool_t xdr_dirlist4 (); extern bool_t xdr_READDIR4resok (); extern bool_t xdr_READDIR4res (); extern bool_t xdr_READLINK4resok (); extern bool_t xdr_READLINK4res (); extern bool_t xdr_REMOVE4args (); extern bool_t xdr_REMOVE4resok (); extern bool_t xdr_REMOVE4res (); extern bool_t xdr_RENAME4args (); extern bool_t xdr_RENAME4resok (); extern bool_t xdr_RENAME4res (); extern bool_t xdr_RENEW4args (); extern bool_t xdr_RENEW4res (); extern bool_t xdr_RESTOREFH4res (); extern bool_t xdr_SAVEFH4res (); extern bool_t xdr_SECINFO4args (); extern bool_t xdr_rpc_gss_svc_t (); extern bool_t xdr_rpcsec_gss_info (); extern bool_t xdr_secinfo4 (); extern bool_t xdr_SECINFO4resok (); extern bool_t xdr_SECINFO4res (); extern bool_t xdr_SETATTR4args (); extern bool_t xdr_SETATTR4res (); extern bool_t xdr_SETCLIENTID4args (); extern bool_t xdr_SETCLIENTID4resok (); extern bool_t xdr_SETCLIENTID4res (); extern bool_t xdr_SETCLIENTID_CONFIRM4args (); extern bool_t xdr_SETCLIENTID_CONFIRM4res (); extern bool_t xdr_VERIFY4args (); extern bool_t xdr_VERIFY4res (); extern bool_t xdr_stable_how4 (); extern bool_t xdr_WRITE4args (); extern bool_t xdr_WRITE4resok (); extern bool_t xdr_WRITE4res (); extern bool_t xdr_RELEASE_LOCKOWNER4args (); extern bool_t xdr_RELEASE_LOCKOWNER4res (); extern bool_t xdr_ILLEGAL4res (); extern bool_t xdr_nfs_opnum4 (); extern bool_t xdr_nfs_argop4 (); extern bool_t xdr_nfs_resop4 (); extern bool_t xdr_COMPOUND4args (); extern bool_t xdr_COMPOUND4res (); extern bool_t xdr_CB_GETATTR4args (); extern bool_t xdr_CB_GETATTR4resok (); extern bool_t xdr_CB_GETATTR4res (); extern bool_t xdr_CB_RECALL4args (); extern bool_t xdr_CB_RECALL4res (); extern bool_t xdr_CB_ILLEGAL4res (); extern bool_t xdr_nfs_cb_opnum4 (); extern bool_t xdr_nfs_cb_argop4 (); extern bool_t xdr_nfs_cb_resop4 (); extern bool_t xdr_CB_COMPOUND4args (); extern bool_t xdr_CB_COMPOUND4res (); #endif /* K&R C */ #ifdef __cplusplus } #endif #endif /* !_NFS4_H_RPCGEN */ ntirpc-1.3.1/tests/nfs4_server.c000066400000000000000000000045411261345040100165610ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * Dominique Martinet * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 * * Everyone is permitted to copy and distribute verbatim or modified * copies of this license document, and changing it is allowed as long * as the name is changed. * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION * * 0. You just DO WHAT THE FUCK YOU WANT TO. */ #include #include #include #include #include #include #include #include #include #include "rpc/svc.h" #include "nfsv40.h" #include "nfs4.h" #include "fsal_nfsv4_macros.h" extern SVCXPRT *svc_msk_create(msk_trans_t*, u_int, void (*)(void*), void*); #define PROGNUM 100003 #define NFS_V4 4 #define SENDSIZE 32768 #define RECVSIZE 32768 #define CREDITS 20 inline void die(char* str, int i) { printf("%s: %s (%d)\n", str, strerror(i), i); exit(1); } int main() { int rc; SVCXPRT *rpc_svc; msk_trans_t *trans; msk_trans_attr_t attr; memset(&attr, 0, sizeof(msk_trans_attr_t)); attr.server = 10; attr.rq_depth = CREDITS; attr.sq_depth = CREDITS; attr.max_send_sge = 4; attr.port = "20049"; attr.node = "0.0.0.0"; attr.debug = 1; if (msk_init(&trans, &attr)) die("couldn't init trans", ENOMEM); msk_bind_server(trans); trans = msk_accept_one(trans); rpc_svc = svc_msk_create(trans, CREDITS, NULL, NULL); if (!rpc_svc) die("no rpc client", errno); struct rpc_msg rply; struct svc_req req; FILE *logfd = fopen("/tmp/nfsrdma_log", "w+"); memset(&req, 0, sizeof(req)); memset(&rply, 0, sizeof(rply)); rc = rpc_svc->xp_ops->xp_recv(rpc_svc, &req); printf("Got something (status %d)\n", rc); fwrite((char*)(&req.rq_msg), sizeof(req.rq_msg), sizeof(char), logfd); fwrite("\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11\x11", 0x10, sizeof(char), logfd); fflush(logfd); rply.rm_xid = req.rq_xid; rply.rm_direction=REPLY; rply.rm_reply.rp_stat = MSG_DENIED; rply.rm_flags = RPC_MSG_FLAG_NONE; rply.rjcted_rply.rj_stat = AUTH_ERROR; rply.rjcted_rply.rj_why = AUTH_FAILED; rpc_svc->xp_ops->xp_reply(rpc_svc, &req, &rply); msk_destroy_trans(&trans); return 0; } ntirpc-1.3.1/tests/nfs4_testmsk.c000066400000000000000000000147171261345040100167530ustar00rootroot00000000000000/* * Copyright (c) 2012-2014 CEA * Dominique Martinet * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * Version 2, December 2004 * * Everyone is permitted to copy and distribute verbatim or modified * copies of this license document, and changing it is allowed as long * as the name is changed. * * DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE * TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION * * 0. You just DO WHAT THE FUCK YOU WANT TO. */ #include #include #include #include #include #include #include #include #include #include "rpc/clnt.h" //#include "nfsv40.h" #include "nfs4.h" #include "fsal_nfsv4_macros.h" /* * Mooshika clnt create routine */ extern CLIENT *clnt_msk_create(msk_trans_t *, const rpcprog_t, const rpcvers_t, u_int); #define PROGNUM 100003 #define NFS_V4 4 #define SENDSIZE 32768 #define RECVSIZE 32768 #define CREDITS 20 inline void die(char* str, int i) { printf("%s: %s (%d)\n", str, strerror(i), i); exit(1); } void nfs4_list_to_bitmap4(bitmap4 * b, uint32_t plen, uint32_t * pval) { uint32_t i; int maxpos = -1; memset(b->bitmap4_val, 0, sizeof(uint32_t)*b->bitmap4_len); for(i = 0; i < plen; i++) { int intpos = pval[i] / 32; int bitpos = pval[i] % 32; if(intpos >= b->bitmap4_len) { printf("Mismatch between bitmap len and the list: " "got %d, need %d to accomodate attribute %d\n", b->bitmap4_len, intpos+1, pval[i]); continue; } b->bitmap4_val[intpos] |= (1U << bitpos); if(intpos > maxpos) maxpos = intpos; } b->bitmap4_len = maxpos + 1; } /* nfs4_list_to_bitmap4 */ void fsal_internal_proxy_create_fattr_readdir_bitmap(bitmap4 * pbitmap) { uint32_t tmpattrlist[20]; uint32_t attrlen = 0; pbitmap->bitmap4_len = 2; memset(pbitmap->bitmap4_val, 0, sizeof(uint32_t) * pbitmap->bitmap4_len); tmpattrlist[0] = FATTR4_TYPE; tmpattrlist[1] = FATTR4_CHANGE; tmpattrlist[2] = FATTR4_SIZE; tmpattrlist[3] = FATTR4_FSID; tmpattrlist[4] = FATTR4_FILEHANDLE; tmpattrlist[5] = FATTR4_FILEID; tmpattrlist[6] = FATTR4_MODE; tmpattrlist[7] = FATTR4_NUMLINKS; tmpattrlist[8] = FATTR4_OWNER; tmpattrlist[9] = FATTR4_OWNER_GROUP; tmpattrlist[10] = FATTR4_SPACE_USED; tmpattrlist[11] = FATTR4_TIME_ACCESS; tmpattrlist[12] = FATTR4_TIME_METADATA; tmpattrlist[13] = FATTR4_TIME_MODIFY; tmpattrlist[14] = FATTR4_RAWDEV; attrlen = 15; nfs4_list_to_bitmap4(pbitmap, attrlen, tmpattrlist); } /* fsal_internal_proxy_create_fattr_readdir_bitmap */ void fsal_internal_proxy_setup_readdir_fattr(fsal_proxy_internal_fattr_readdir_t * pfattr) { /* Just do the correct connection */ pfattr->owner.utf8string_val = pfattr->padowner; pfattr->owner_group.utf8string_val = pfattr->padgroup; pfattr->filehandle.nfs_fh4_val = pfattr->padfh; } int main() { int rc; CLIENT *rpc_client; msk_trans_t *trans; msk_trans_attr_t attr; memset(&attr, 0, sizeof(msk_trans_attr_t)); attr.server = 0; attr.rq_depth = CREDITS; attr.sq_depth = CREDITS; attr.max_send_sge = 4; attr.port = "20049"; attr.node = "127.0.0.1"; attr.debug = 1; if (msk_init(&trans, &attr)) die("couldn't init trans", ENOMEM); rpc_client = clnt_msk_create(trans, PROGNUM, NFS_V4, CREDITS); if (!rpc_client) die("no rpc client", errno); AUTH *auth = authunix_ncreate_default(); struct timeval timeout = TIMEOUTRPC; #if 0 rc = clnt_call(rpc_client, auth, NFSPROC4_NULL, (xdrproc_t) xdr_void, (caddr_t) NULL, (xdrproc_t) xdr_void, (caddr_t) NULL, timeout); if (rc != RPC_SUCCESS) printf("procnull went wrong (%d): %s", rc, clnt_sperrno(rc)); else printf("procnull success!\n"); #endif // 0 COMPOUND4args argnfs4; COMPOUND4res resnfs4; #define NB_OP_ALLOC 2 nfs_argop4 argoparray[NB_OP_ALLOC]; nfs_resop4 resoparray[NB_OP_ALLOC]; memset(argoparray, 0, sizeof(nfs_argop4)*NB_OP_ALLOC); memset(resoparray, 0, sizeof(nfs_resop4)*NB_OP_ALLOC); /* Setup results structures */ argnfs4.argarray.argarray_val = argoparray; resnfs4.resarray.resarray_val = resoparray; argnfs4.minorversion = 0; argnfs4.argarray.argarray_len = 0; /* argnfs4.tag.utf8string_val = "GANESHA NFSv4 Proxy: Lookup Root" ; */ argnfs4.tag.utf8string_val = NULL; argnfs4.tag.utf8string_len = 0; int nbreaddir = 256; proxyfsal_cookie_t start_position; start_position.data = 0; bitmap4 bitmap; uint32_t bitmap_val[2]; bitmap.bitmap4_len = 2; bitmap.bitmap4_val = bitmap_val; fsal_internal_proxy_create_fattr_readdir_bitmap(&bitmap); verifier4 verifier; memset(verifier, 0, sizeof(verifier)); #define IDX_OP_PUTROOTFH 0 #define IDX_OP_READDIR 1 COMPOUNDV4_ARG_ADD_OP_PUTROOTFH(argnfs4); COMPOUNDV4_ARG_ADD_OP_READDIR(argnfs4, start_position.data, nbreaddir, verifier, bitmap); struct proxy_entry4 { entry4 e4; char name[MAXNAMLEN]; fsal_proxy_internal_fattr_readdir_t attr; uint32_t bitmap[2]; } *pxy_e4; pxy_e4 = calloc(nbreaddir, sizeof(*pxy_e4)); if (!pxy_e4) die("calloc failed", ENOMEM); memset(pxy_e4, 0, sizeof(*pxy_e4)*nbreaddir); int i; for (i=0; ie4; rc = clnt_call(rpc_client, auth, NFSPROC4_COMPOUND, (xdrproc_t) xdr_COMPOUND4args, (caddr_t) &argnfs4, (xdrproc_t) xdr_COMPOUND4res, (caddr_t) &resnfs4, timeout); if (rc != RPC_SUCCESS) printf("compound went wrong (%d): %s\n", rc, clnt_sperrno(rc)); else printf("compound: got status : %x\n", resnfs4.resarray.resarray_val[IDX_OP_PUTROOTFH].nfs_resop4_u.opputrootfh.status); // use %s? msk_destroy_trans(&trans); return 0; } ntirpc-1.3.1/tests/nfs4_xdr.c000066400000000000000000001626521261345040100160600ustar00rootroot00000000000000/* * Please do not edit this file. * It was generated using rpcgen. */ #include "nfs4.h" bool_t xdr_nfs_ftype4 (XDR *xdrs, nfs_ftype4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_nfsstat4 (XDR *xdrs, nfsstat4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_bitmap4 (XDR *xdrs, bitmap4 *objp) { register int32_t *buf; if (!xdr_array (xdrs, (char **)&objp->bitmap4_val, (u_int *) &objp->bitmap4_len, ~0, sizeof (uint32_t), (xdrproc_t) xdr_uint32_t)) return FALSE; return TRUE; } bool_t xdr_offset4 (XDR *xdrs, offset4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_count4 (XDR *xdrs, count4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_length4 (XDR *xdrs, length4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_clientid4 (XDR *xdrs, clientid4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_seqid4 (XDR *xdrs, seqid4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_utf8string (XDR *xdrs, utf8string *objp) { register int32_t *buf; if (!xdr_bytes (xdrs, (char **)&objp->utf8string_val, (u_int *) &objp->utf8string_len, ~0)) return FALSE; return TRUE; } bool_t xdr_utf8str_cis (XDR *xdrs, utf8str_cis *objp) { register int32_t *buf; if (!xdr_utf8string (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_utf8str_cs (XDR *xdrs, utf8str_cs *objp) { register int32_t *buf; if (!xdr_utf8string (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_utf8str_mixed (XDR *xdrs, utf8str_mixed *objp) { register int32_t *buf; if (!xdr_utf8string (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_component4 (XDR *xdrs, component4 *objp) { register int32_t *buf; if (!xdr_utf8str_cs (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_pathname4 (XDR *xdrs, pathname4 *objp) { register int32_t *buf; if (!xdr_array (xdrs, (char **)&objp->pathname4_val, (u_int *) &objp->pathname4_len, ~0, sizeof (component4), (xdrproc_t) xdr_component4)) return FALSE; return TRUE; } bool_t xdr_nfs_lockid4 (XDR *xdrs, nfs_lockid4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_nfs_cookie4 (XDR *xdrs, nfs_cookie4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_linktext4 (XDR *xdrs, linktext4 *objp) { register int32_t *buf; if (!xdr_utf8str_cs (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_sec_oid4 (XDR *xdrs, sec_oid4 *objp) { register int32_t *buf; if (!xdr_bytes (xdrs, (char **)&objp->sec_oid4_val, (u_int *) &objp->sec_oid4_len, ~0)) return FALSE; return TRUE; } bool_t xdr_qop4 (XDR *xdrs, qop4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_mode4 (XDR *xdrs, mode4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_changeid4 (XDR *xdrs, changeid4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_verifier4 (XDR *xdrs, verifier4 objp) { register int32_t *buf; if (!xdr_opaque (xdrs, objp, NFS4_VERIFIER_SIZE)) return FALSE; return TRUE; } bool_t xdr_nfstime4 (XDR *xdrs, nfstime4 *objp) { register int32_t *buf; if (!xdr_int64_t (xdrs, &objp->seconds)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->nseconds)) return FALSE; return TRUE; } bool_t xdr_time_how4 (XDR *xdrs, time_how4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_settime4 (XDR *xdrs, settime4 *objp) { register int32_t *buf; if (!xdr_time_how4 (xdrs, &objp->set_it)) return FALSE; switch (objp->set_it) { case SET_TO_CLIENT_TIME4: if (!xdr_nfstime4 (xdrs, &objp->settime4_u.time)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_nfs_fh4 (XDR *xdrs, nfs_fh4 *objp) { register int32_t *buf; if (!xdr_bytes (xdrs, (char **)&objp->nfs_fh4_val, (u_int *) &objp->nfs_fh4_len, NFS4_FHSIZE)) return FALSE; return TRUE; } bool_t xdr_fsid4 (XDR *xdrs, fsid4 *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, &objp->major)) return FALSE; if (!xdr_uint64_t (xdrs, &objp->minor)) return FALSE; return TRUE; } bool_t xdr_fs_location4 (XDR *xdrs, fs_location4 *objp) { register int32_t *buf; if (!xdr_array (xdrs, (char **)&objp->server.server_val, (u_int *) &objp->server.server_len, ~0, sizeof (utf8str_cis), (xdrproc_t) xdr_utf8str_cis)) return FALSE; if (!xdr_pathname4 (xdrs, &objp->rootpath)) return FALSE; return TRUE; } bool_t xdr_fs_locations4 (XDR *xdrs, fs_locations4 *objp) { register int32_t *buf; if (!xdr_pathname4 (xdrs, &objp->fs_root)) return FALSE; if (!xdr_array (xdrs, (char **)&objp->locations.locations_val, (u_int *) &objp->locations.locations_len, ~0, sizeof (fs_location4), (xdrproc_t) xdr_fs_location4)) return FALSE; return TRUE; } bool_t xdr_acetype4 (XDR *xdrs, acetype4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_aceflag4 (XDR *xdrs, aceflag4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_acemask4 (XDR *xdrs, acemask4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_nfsace4 (XDR *xdrs, nfsace4 *objp) { register int32_t *buf; if (!xdr_acetype4 (xdrs, &objp->type)) return FALSE; if (!xdr_aceflag4 (xdrs, &objp->flag)) return FALSE; if (!xdr_acemask4 (xdrs, &objp->access_mask)) return FALSE; if (!xdr_utf8str_mixed (xdrs, &objp->who)) return FALSE; return TRUE; } bool_t xdr_specdata4 (XDR *xdrs, specdata4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, &objp->specdata1)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->specdata2)) return FALSE; return TRUE; } bool_t xdr_fattr4_supported_attrs (XDR *xdrs, fattr4_supported_attrs *objp) { register int32_t *buf; if (!xdr_bitmap4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_type (XDR *xdrs, fattr4_type *objp) { register int32_t *buf; if (!xdr_nfs_ftype4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_fh_expire_type (XDR *xdrs, fattr4_fh_expire_type *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_change (XDR *xdrs, fattr4_change *objp) { register int32_t *buf; if (!xdr_changeid4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_size (XDR *xdrs, fattr4_size *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_link_support (XDR *xdrs, fattr4_link_support *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_symlink_support (XDR *xdrs, fattr4_symlink_support *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_named_attr (XDR *xdrs, fattr4_named_attr *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_fsid (XDR *xdrs, fattr4_fsid *objp) { register int32_t *buf; if (!xdr_fsid4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_unique_handles (XDR *xdrs, fattr4_unique_handles *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_lease_time (XDR *xdrs, fattr4_lease_time *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_rdattr_error (XDR *xdrs, fattr4_rdattr_error *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_acl (XDR *xdrs, fattr4_acl *objp) { register int32_t *buf; if (!xdr_array (xdrs, (char **)&objp->fattr4_acl_val, (u_int *) &objp->fattr4_acl_len, ~0, sizeof (nfsace4), (xdrproc_t) xdr_nfsace4)) return FALSE; return TRUE; } bool_t xdr_fattr4_aclsupport (XDR *xdrs, fattr4_aclsupport *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_archive (XDR *xdrs, fattr4_archive *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_cansettime (XDR *xdrs, fattr4_cansettime *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_case_insensitive (XDR *xdrs, fattr4_case_insensitive *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_case_preserving (XDR *xdrs, fattr4_case_preserving *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_chown_restricted (XDR *xdrs, fattr4_chown_restricted *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_fileid (XDR *xdrs, fattr4_fileid *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_files_avail (XDR *xdrs, fattr4_files_avail *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_filehandle (XDR *xdrs, fattr4_filehandle *objp) { register int32_t *buf; if (!xdr_nfs_fh4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_files_free (XDR *xdrs, fattr4_files_free *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_files_total (XDR *xdrs, fattr4_files_total *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_fs_locations (XDR *xdrs, fattr4_fs_locations *objp) { register int32_t *buf; if (!xdr_fs_locations4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_hidden (XDR *xdrs, fattr4_hidden *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_homogeneous (XDR *xdrs, fattr4_homogeneous *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_maxfilesize (XDR *xdrs, fattr4_maxfilesize *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_maxlink (XDR *xdrs, fattr4_maxlink *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_maxname (XDR *xdrs, fattr4_maxname *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_maxread (XDR *xdrs, fattr4_maxread *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_maxwrite (XDR *xdrs, fattr4_maxwrite *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_mimetype (XDR *xdrs, fattr4_mimetype *objp) { register int32_t *buf; if (!xdr_utf8str_cs (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_mode (XDR *xdrs, fattr4_mode *objp) { register int32_t *buf; if (!xdr_mode4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_mounted_on_fileid (XDR *xdrs, fattr4_mounted_on_fileid *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_no_trunc (XDR *xdrs, fattr4_no_trunc *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_numlinks (XDR *xdrs, fattr4_numlinks *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_owner (XDR *xdrs, fattr4_owner *objp) { register int32_t *buf; if (!xdr_utf8str_mixed (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_owner_group (XDR *xdrs, fattr4_owner_group *objp) { register int32_t *buf; if (!xdr_utf8str_mixed (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_quota_avail_hard (XDR *xdrs, fattr4_quota_avail_hard *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_quota_avail_soft (XDR *xdrs, fattr4_quota_avail_soft *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_quota_used (XDR *xdrs, fattr4_quota_used *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_rawdev (XDR *xdrs, fattr4_rawdev *objp) { register int32_t *buf; if (!xdr_specdata4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_space_avail (XDR *xdrs, fattr4_space_avail *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_space_free (XDR *xdrs, fattr4_space_free *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_space_total (XDR *xdrs, fattr4_space_total *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_space_used (XDR *xdrs, fattr4_space_used *objp) { register int32_t *buf; if (!xdr_uint64_t (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_system (XDR *xdrs, fattr4_system *objp) { register int32_t *buf; if (!xdr_bool (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_access (XDR *xdrs, fattr4_time_access *objp) { register int32_t *buf; if (!xdr_nfstime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_access_set (XDR *xdrs, fattr4_time_access_set *objp) { register int32_t *buf; if (!xdr_settime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_backup (XDR *xdrs, fattr4_time_backup *objp) { register int32_t *buf; if (!xdr_nfstime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_create (XDR *xdrs, fattr4_time_create *objp) { register int32_t *buf; if (!xdr_nfstime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_delta (XDR *xdrs, fattr4_time_delta *objp) { register int32_t *buf; if (!xdr_nfstime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_metadata (XDR *xdrs, fattr4_time_metadata *objp) { register int32_t *buf; if (!xdr_nfstime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_modify (XDR *xdrs, fattr4_time_modify *objp) { register int32_t *buf; if (!xdr_nfstime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_fattr4_time_modify_set (XDR *xdrs, fattr4_time_modify_set *objp) { register int32_t *buf; if (!xdr_settime4 (xdrs, objp)) return FALSE; return TRUE; } bool_t xdr_attrlist4 (XDR *xdrs, attrlist4 *objp) { register int32_t *buf; if (!xdr_bytes (xdrs, (char **)&objp->attrlist4_val, (u_int *) &objp->attrlist4_len, ~0)) return FALSE; return TRUE; } bool_t xdr_fattr4 (XDR *xdrs, fattr4 *objp) { register int32_t *buf; if (!xdr_bitmap4 (xdrs, &objp->attrmask)) return FALSE; if (!xdr_attrlist4 (xdrs, &objp->attr_vals)) return FALSE; return TRUE; } bool_t xdr_change_info4 (XDR *xdrs, change_info4 *objp) { register int32_t *buf; if (!xdr_bool (xdrs, &objp->atomic)) return FALSE; if (!xdr_changeid4 (xdrs, &objp->before)) return FALSE; if (!xdr_changeid4 (xdrs, &objp->after)) return FALSE; return TRUE; } bool_t xdr_clientaddr4 (XDR *xdrs, clientaddr4 *objp) { register int32_t *buf; if (!xdr_string (xdrs, &objp->r_netid, ~0)) return FALSE; if (!xdr_string (xdrs, &objp->r_addr, ~0)) return FALSE; return TRUE; } bool_t xdr_cb_client4 (XDR *xdrs, cb_client4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, &objp->cb_program)) return FALSE; if (!xdr_clientaddr4 (xdrs, &objp->cb_location)) return FALSE; return TRUE; } bool_t xdr_stateid4 (XDR *xdrs, stateid4 *objp) { register int32_t *buf; int i; if (!xdr_uint32_t (xdrs, &objp->seqid)) return FALSE; if (!xdr_opaque (xdrs, objp->other, 12)) return FALSE; return TRUE; } bool_t xdr_nfs_client_id4 (XDR *xdrs, nfs_client_id4 *objp) { register int32_t *buf; if (!xdr_verifier4 (xdrs, objp->verifier)) return FALSE; if (!xdr_bytes (xdrs, (char **)&objp->id.id_val, (u_int *) &objp->id.id_len, NFS4_OPAQUE_LIMIT)) return FALSE; return TRUE; } bool_t xdr_open_owner4 (XDR *xdrs, open_owner4 *objp) { register int32_t *buf; if (!xdr_clientid4 (xdrs, &objp->clientid)) return FALSE; if (!xdr_bytes (xdrs, (char **)&objp->owner.owner_val, (u_int *) &objp->owner.owner_len, NFS4_OPAQUE_LIMIT)) return FALSE; return TRUE; } bool_t xdr_lock_owner4 (XDR *xdrs, lock_owner4 *objp) { register int32_t *buf; if (!xdr_clientid4 (xdrs, &objp->clientid)) return FALSE; if (!xdr_bytes (xdrs, (char **)&objp->owner.owner_val, (u_int *) &objp->owner.owner_len, NFS4_OPAQUE_LIMIT)) return FALSE; return TRUE; } bool_t xdr_nfs_lock_type4 (XDR *xdrs, nfs_lock_type4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_ACCESS4args (XDR *xdrs, ACCESS4args *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, &objp->access)) return FALSE; return TRUE; } bool_t xdr_ACCESS4resok (XDR *xdrs, ACCESS4resok *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, &objp->supported)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->access)) return FALSE; return TRUE; } bool_t xdr_ACCESS4res (XDR *xdrs, ACCESS4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_ACCESS4resok (xdrs, &objp->ACCESS4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_CLOSE4args (XDR *xdrs, CLOSE4args *objp) { register int32_t *buf; if (!xdr_seqid4 (xdrs, &objp->seqid)) return FALSE; if (!xdr_stateid4 (xdrs, &objp->open_stateid)) return FALSE; return TRUE; } bool_t xdr_CLOSE4res (XDR *xdrs, CLOSE4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_stateid4 (xdrs, &objp->CLOSE4res_u.open_stateid)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_COMMIT4args (XDR *xdrs, COMMIT4args *objp) { register int32_t *buf; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_count4 (xdrs, &objp->count)) return FALSE; return TRUE; } bool_t xdr_COMMIT4resok (XDR *xdrs, COMMIT4resok *objp) { register int32_t *buf; if (!xdr_verifier4 (xdrs, objp->writeverf)) return FALSE; return TRUE; } bool_t xdr_COMMIT4res (XDR *xdrs, COMMIT4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_COMMIT4resok (xdrs, &objp->COMMIT4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_createtype4 (XDR *xdrs, createtype4 *objp) { register int32_t *buf; if (!xdr_nfs_ftype4 (xdrs, &objp->type)) return FALSE; switch (objp->type) { case NF4LNK: if (!xdr_linktext4 (xdrs, &objp->createtype4_u.linkdata)) return FALSE; break; case NF4BLK: case NF4CHR: if (!xdr_specdata4 (xdrs, &objp->createtype4_u.devdata)) return FALSE; break; case NF4SOCK: case NF4FIFO: case NF4DIR: break; default: break; } return TRUE; } bool_t xdr_CREATE4args (XDR *xdrs, CREATE4args *objp) { register int32_t *buf; if (!xdr_createtype4 (xdrs, &objp->objtype)) return FALSE; if (!xdr_component4 (xdrs, &objp->objname)) return FALSE; if (!xdr_fattr4 (xdrs, &objp->createattrs)) return FALSE; return TRUE; } bool_t xdr_CREATE4resok (XDR *xdrs, CREATE4resok *objp) { register int32_t *buf; if (!xdr_change_info4 (xdrs, &objp->cinfo)) return FALSE; if (!xdr_bitmap4 (xdrs, &objp->attrset)) return FALSE; return TRUE; } bool_t xdr_CREATE4res (XDR *xdrs, CREATE4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_CREATE4resok (xdrs, &objp->CREATE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_DELEGPURGE4args (XDR *xdrs, DELEGPURGE4args *objp) { register int32_t *buf; if (!xdr_clientid4 (xdrs, &objp->clientid)) return FALSE; return TRUE; } bool_t xdr_DELEGPURGE4res (XDR *xdrs, DELEGPURGE4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_DELEGRETURN4args (XDR *xdrs, DELEGRETURN4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->deleg_stateid)) return FALSE; return TRUE; } bool_t xdr_DELEGRETURN4res (XDR *xdrs, DELEGRETURN4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_GETATTR4args (XDR *xdrs, GETATTR4args *objp) { register int32_t *buf; if (!xdr_bitmap4 (xdrs, &objp->attr_request)) return FALSE; return TRUE; } bool_t xdr_GETATTR4resok (XDR *xdrs, GETATTR4resok *objp) { register int32_t *buf; if (!xdr_fattr4 (xdrs, &objp->obj_attributes)) return FALSE; return TRUE; } bool_t xdr_GETATTR4res (XDR *xdrs, GETATTR4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_GETATTR4resok (xdrs, &objp->GETATTR4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_GETFH4resok (XDR *xdrs, GETFH4resok *objp) { register int32_t *buf; if (!xdr_nfs_fh4 (xdrs, &objp->object)) return FALSE; return TRUE; } bool_t xdr_GETFH4res (XDR *xdrs, GETFH4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_GETFH4resok (xdrs, &objp->GETFH4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_LINK4args (XDR *xdrs, LINK4args *objp) { register int32_t *buf; if (!xdr_component4 (xdrs, &objp->newname)) return FALSE; return TRUE; } bool_t xdr_LINK4resok (XDR *xdrs, LINK4resok *objp) { register int32_t *buf; if (!xdr_change_info4 (xdrs, &objp->cinfo)) return FALSE; return TRUE; } bool_t xdr_LINK4res (XDR *xdrs, LINK4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_LINK4resok (xdrs, &objp->LINK4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_open_to_lock_owner4 (XDR *xdrs, open_to_lock_owner4 *objp) { register int32_t *buf; if (!xdr_seqid4 (xdrs, &objp->open_seqid)) return FALSE; if (!xdr_stateid4 (xdrs, &objp->open_stateid)) return FALSE; if (!xdr_seqid4 (xdrs, &objp->lock_seqid)) return FALSE; if (!xdr_lock_owner4 (xdrs, &objp->lock_owner)) return FALSE; return TRUE; } bool_t xdr_exist_lock_owner4 (XDR *xdrs, exist_lock_owner4 *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->lock_stateid)) return FALSE; if (!xdr_seqid4 (xdrs, &objp->lock_seqid)) return FALSE; return TRUE; } bool_t xdr_locker4 (XDR *xdrs, locker4 *objp) { register int32_t *buf; if (!xdr_bool (xdrs, &objp->new_lock_owner)) return FALSE; switch (objp->new_lock_owner) { case TRUE: if (!xdr_open_to_lock_owner4 (xdrs, &objp->locker4_u.open_owner)) return FALSE; break; case FALSE: if (!xdr_exist_lock_owner4 (xdrs, &objp->locker4_u.lock_owner)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_LOCK4args (XDR *xdrs, LOCK4args *objp) { register int32_t *buf; if (!xdr_nfs_lock_type4 (xdrs, &objp->locktype)) return FALSE; if (!xdr_bool (xdrs, &objp->reclaim)) return FALSE; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_length4 (xdrs, &objp->length)) return FALSE; if (!xdr_locker4 (xdrs, &objp->locker)) return FALSE; return TRUE; } bool_t xdr_LOCK4denied (XDR *xdrs, LOCK4denied *objp) { register int32_t *buf; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_length4 (xdrs, &objp->length)) return FALSE; if (!xdr_nfs_lock_type4 (xdrs, &objp->locktype)) return FALSE; if (!xdr_lock_owner4 (xdrs, &objp->owner)) return FALSE; return TRUE; } bool_t xdr_LOCK4resok (XDR *xdrs, LOCK4resok *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->lock_stateid)) return FALSE; return TRUE; } bool_t xdr_LOCK4res (XDR *xdrs, LOCK4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_LOCK4resok (xdrs, &objp->LOCK4res_u.resok4)) return FALSE; break; case NFS4ERR_DENIED: if (!xdr_LOCK4denied (xdrs, &objp->LOCK4res_u.denied)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_LOCKT4args (XDR *xdrs, LOCKT4args *objp) { register int32_t *buf; if (!xdr_nfs_lock_type4 (xdrs, &objp->locktype)) return FALSE; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_length4 (xdrs, &objp->length)) return FALSE; if (!xdr_lock_owner4 (xdrs, &objp->owner)) return FALSE; return TRUE; } bool_t xdr_LOCKT4res (XDR *xdrs, LOCKT4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4ERR_DENIED: if (!xdr_LOCK4denied (xdrs, &objp->LOCKT4res_u.denied)) return FALSE; break; case NFS4_OK: break; default: break; } return TRUE; } bool_t xdr_LOCKU4args (XDR *xdrs, LOCKU4args *objp) { register int32_t *buf; if (!xdr_nfs_lock_type4 (xdrs, &objp->locktype)) return FALSE; if (!xdr_seqid4 (xdrs, &objp->seqid)) return FALSE; if (!xdr_stateid4 (xdrs, &objp->lock_stateid)) return FALSE; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_length4 (xdrs, &objp->length)) return FALSE; return TRUE; } bool_t xdr_LOCKU4res (XDR *xdrs, LOCKU4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_stateid4 (xdrs, &objp->LOCKU4res_u.lock_stateid)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_LOOKUP4args (XDR *xdrs, LOOKUP4args *objp) { register int32_t *buf; if (!xdr_component4 (xdrs, &objp->objname)) return FALSE; return TRUE; } bool_t xdr_LOOKUP4res (XDR *xdrs, LOOKUP4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_LOOKUPP4res (XDR *xdrs, LOOKUPP4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_NVERIFY4args (XDR *xdrs, NVERIFY4args *objp) { register int32_t *buf; if (!xdr_fattr4 (xdrs, &objp->obj_attributes)) return FALSE; return TRUE; } bool_t xdr_NVERIFY4res (XDR *xdrs, NVERIFY4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_createmode4 (XDR *xdrs, createmode4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_createhow4 (XDR *xdrs, createhow4 *objp) { register int32_t *buf; if (!xdr_createmode4 (xdrs, &objp->mode)) return FALSE; switch (objp->mode) { case UNCHECKED4: case GUARDED4: if (!xdr_fattr4 (xdrs, &objp->createhow4_u.createattrs)) return FALSE; break; case EXCLUSIVE4: if (!xdr_verifier4 (xdrs, objp->createhow4_u.createverf)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_opentype4 (XDR *xdrs, opentype4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_openflag4 (XDR *xdrs, openflag4 *objp) { register int32_t *buf; if (!xdr_opentype4 (xdrs, &objp->opentype)) return FALSE; switch (objp->opentype) { case OPEN4_CREATE: if (!xdr_createhow4 (xdrs, &objp->openflag4_u.how)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_limit_by4 (XDR *xdrs, limit_by4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_nfs_modified_limit4 (XDR *xdrs, nfs_modified_limit4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, &objp->num_blocks)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->bytes_per_block)) return FALSE; return TRUE; } bool_t xdr_nfs_space_limit4 (XDR *xdrs, nfs_space_limit4 *objp) { register int32_t *buf; if (!xdr_limit_by4 (xdrs, &objp->limitby)) return FALSE; switch (objp->limitby) { case NFS_LIMIT_SIZE: if (!xdr_uint64_t (xdrs, &objp->nfs_space_limit4_u.filesize)) return FALSE; break; case NFS_LIMIT_BLOCKS: if (!xdr_nfs_modified_limit4 (xdrs, &objp->nfs_space_limit4_u.mod_blocks)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_open_delegation_type4 (XDR *xdrs, open_delegation_type4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_open_claim_type4 (XDR *xdrs, open_claim_type4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_open_claim_delegate_cur4 (XDR *xdrs, open_claim_delegate_cur4 *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->delegate_stateid)) return FALSE; if (!xdr_component4 (xdrs, &objp->file)) return FALSE; return TRUE; } bool_t xdr_open_claim4 (XDR *xdrs, open_claim4 *objp) { register int32_t *buf; if (!xdr_open_claim_type4 (xdrs, &objp->claim)) return FALSE; switch (objp->claim) { case CLAIM_NULL: if (!xdr_component4 (xdrs, &objp->open_claim4_u.file)) return FALSE; break; case CLAIM_PREVIOUS: if (!xdr_open_delegation_type4 (xdrs, &objp->open_claim4_u.delegate_type)) return FALSE; break; case CLAIM_DELEGATE_CUR: if (!xdr_open_claim_delegate_cur4 (xdrs, &objp->open_claim4_u.delegate_cur_info)) return FALSE; break; case CLAIM_DELEGATE_PREV: if (!xdr_component4 (xdrs, &objp->open_claim4_u.file_delegate_prev)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_OPEN4args (XDR *xdrs, OPEN4args *objp) { register int32_t *buf; if (!xdr_seqid4 (xdrs, &objp->seqid)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->share_access)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->share_deny)) return FALSE; if (!xdr_open_owner4 (xdrs, &objp->owner)) return FALSE; if (!xdr_openflag4 (xdrs, &objp->openhow)) return FALSE; if (!xdr_open_claim4 (xdrs, &objp->claim)) return FALSE; return TRUE; } bool_t xdr_open_read_delegation4 (XDR *xdrs, open_read_delegation4 *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_bool (xdrs, &objp->recall)) return FALSE; if (!xdr_nfsace4 (xdrs, &objp->permissions)) return FALSE; return TRUE; } bool_t xdr_open_write_delegation4 (XDR *xdrs, open_write_delegation4 *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_bool (xdrs, &objp->recall)) return FALSE; if (!xdr_nfs_space_limit4 (xdrs, &objp->space_limit)) return FALSE; if (!xdr_nfsace4 (xdrs, &objp->permissions)) return FALSE; return TRUE; } bool_t xdr_open_delegation4 (XDR *xdrs, open_delegation4 *objp) { register int32_t *buf; if (!xdr_open_delegation_type4 (xdrs, &objp->delegation_type)) return FALSE; switch (objp->delegation_type) { case OPEN_DELEGATE_NONE: break; case OPEN_DELEGATE_READ: if (!xdr_open_read_delegation4 (xdrs, &objp->open_delegation4_u.read)) return FALSE; break; case OPEN_DELEGATE_WRITE: if (!xdr_open_write_delegation4 (xdrs, &objp->open_delegation4_u.write)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_OPEN4resok (XDR *xdrs, OPEN4resok *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_change_info4 (xdrs, &objp->cinfo)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->rflags)) return FALSE; if (!xdr_bitmap4 (xdrs, &objp->attrset)) return FALSE; if (!xdr_open_delegation4 (xdrs, &objp->delegation)) return FALSE; return TRUE; } bool_t xdr_OPEN4res (XDR *xdrs, OPEN4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_OPEN4resok (xdrs, &objp->OPEN4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_OPENATTR4args (XDR *xdrs, OPENATTR4args *objp) { register int32_t *buf; if (!xdr_bool (xdrs, &objp->createdir)) return FALSE; return TRUE; } bool_t xdr_OPENATTR4res (XDR *xdrs, OPENATTR4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_OPEN_CONFIRM4args (XDR *xdrs, OPEN_CONFIRM4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->open_stateid)) return FALSE; if (!xdr_seqid4 (xdrs, &objp->seqid)) return FALSE; return TRUE; } bool_t xdr_OPEN_CONFIRM4resok (XDR *xdrs, OPEN_CONFIRM4resok *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->open_stateid)) return FALSE; return TRUE; } bool_t xdr_OPEN_CONFIRM4res (XDR *xdrs, OPEN_CONFIRM4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_OPEN_CONFIRM4resok (xdrs, &objp->OPEN_CONFIRM4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_OPEN_DOWNGRADE4args (XDR *xdrs, OPEN_DOWNGRADE4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->open_stateid)) return FALSE; if (!xdr_seqid4 (xdrs, &objp->seqid)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->share_access)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->share_deny)) return FALSE; return TRUE; } bool_t xdr_OPEN_DOWNGRADE4resok (XDR *xdrs, OPEN_DOWNGRADE4resok *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->open_stateid)) return FALSE; return TRUE; } bool_t xdr_OPEN_DOWNGRADE4res (XDR *xdrs, OPEN_DOWNGRADE4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_OPEN_DOWNGRADE4resok (xdrs, &objp->OPEN_DOWNGRADE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_PUTFH4args (XDR *xdrs, PUTFH4args *objp) { register int32_t *buf; if (!xdr_nfs_fh4 (xdrs, &objp->object)) return FALSE; return TRUE; } bool_t xdr_PUTFH4res (XDR *xdrs, PUTFH4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_PUTPUBFH4res (XDR *xdrs, PUTPUBFH4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_PUTROOTFH4res (XDR *xdrs, PUTROOTFH4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_READ4args (XDR *xdrs, READ4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_count4 (xdrs, &objp->count)) return FALSE; return TRUE; } bool_t xdr_READ4resok (XDR *xdrs, READ4resok *objp) { register int32_t *buf; if (!xdr_bool (xdrs, &objp->eof)) return FALSE; if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } bool_t xdr_READ4res (XDR *xdrs, READ4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_READ4resok (xdrs, &objp->READ4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_READDIR4args (XDR *xdrs, READDIR4args *objp) { register int32_t *buf; if (!xdr_nfs_cookie4 (xdrs, &objp->cookie)) return FALSE; if (!xdr_verifier4 (xdrs, objp->cookieverf)) return FALSE; if (!xdr_count4 (xdrs, &objp->dircount)) return FALSE; if (!xdr_count4 (xdrs, &objp->maxcount)) return FALSE; if (!xdr_bitmap4 (xdrs, &objp->attr_request)) return FALSE; return TRUE; } bool_t xdr_entry4 (XDR *xdrs, entry4 *objp) { register int32_t *buf; if (!xdr_nfs_cookie4 (xdrs, &objp->cookie)) return FALSE; if (!xdr_component4 (xdrs, &objp->name)) return FALSE; if (!xdr_fattr4 (xdrs, &objp->attrs)) return FALSE; if (!xdr_pointer (xdrs, (char **)&objp->nextentry, sizeof (entry4), (xdrproc_t) xdr_entry4)) return FALSE; return TRUE; } bool_t xdr_dirlist4 (XDR *xdrs, dirlist4 *objp) { register int32_t *buf; if (!xdr_pointer (xdrs, (char **)&objp->entries, sizeof (entry4), (xdrproc_t) xdr_entry4)) return FALSE; if (!xdr_bool (xdrs, &objp->eof)) return FALSE; return TRUE; } bool_t xdr_READDIR4resok (XDR *xdrs, READDIR4resok *objp) { register int32_t *buf; if (!xdr_verifier4 (xdrs, objp->cookieverf)) return FALSE; if (!xdr_dirlist4 (xdrs, &objp->reply)) return FALSE; return TRUE; } bool_t xdr_READDIR4res (XDR *xdrs, READDIR4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_READDIR4resok (xdrs, &objp->READDIR4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_READLINK4resok (XDR *xdrs, READLINK4resok *objp) { register int32_t *buf; if (!xdr_linktext4 (xdrs, &objp->link)) return FALSE; return TRUE; } bool_t xdr_READLINK4res (XDR *xdrs, READLINK4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_READLINK4resok (xdrs, &objp->READLINK4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_REMOVE4args (XDR *xdrs, REMOVE4args *objp) { register int32_t *buf; if (!xdr_component4 (xdrs, &objp->target)) return FALSE; return TRUE; } bool_t xdr_REMOVE4resok (XDR *xdrs, REMOVE4resok *objp) { register int32_t *buf; if (!xdr_change_info4 (xdrs, &objp->cinfo)) return FALSE; return TRUE; } bool_t xdr_REMOVE4res (XDR *xdrs, REMOVE4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_REMOVE4resok (xdrs, &objp->REMOVE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_RENAME4args (XDR *xdrs, RENAME4args *objp) { register int32_t *buf; if (!xdr_component4 (xdrs, &objp->oldname)) return FALSE; if (!xdr_component4 (xdrs, &objp->newname)) return FALSE; return TRUE; } bool_t xdr_RENAME4resok (XDR *xdrs, RENAME4resok *objp) { register int32_t *buf; if (!xdr_change_info4 (xdrs, &objp->source_cinfo)) return FALSE; if (!xdr_change_info4 (xdrs, &objp->target_cinfo)) return FALSE; return TRUE; } bool_t xdr_RENAME4res (XDR *xdrs, RENAME4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_RENAME4resok (xdrs, &objp->RENAME4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_RENEW4args (XDR *xdrs, RENEW4args *objp) { register int32_t *buf; if (!xdr_clientid4 (xdrs, &objp->clientid)) return FALSE; return TRUE; } bool_t xdr_RENEW4res (XDR *xdrs, RENEW4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_RESTOREFH4res (XDR *xdrs, RESTOREFH4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_SAVEFH4res (XDR *xdrs, SAVEFH4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_SECINFO4args (XDR *xdrs, SECINFO4args *objp) { register int32_t *buf; if (!xdr_component4 (xdrs, &objp->name)) return FALSE; return TRUE; } bool_t xdr_rpc_gss_svc_t (XDR *xdrs, rpc_gss_svc_t *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_rpcsec_gss_info (XDR *xdrs, rpcsec_gss_info *objp) { register int32_t *buf; if (!xdr_sec_oid4 (xdrs, &objp->oid)) return FALSE; if (!xdr_qop4 (xdrs, &objp->qop)) return FALSE; if (!xdr_rpc_gss_svc_t (xdrs, &objp->service)) return FALSE; return TRUE; } bool_t xdr_secinfo4 (XDR *xdrs, secinfo4 *objp) { register int32_t *buf; if (!xdr_uint32_t (xdrs, &objp->flavor)) return FALSE; return TRUE; } bool_t xdr_SECINFO4resok (XDR *xdrs, SECINFO4resok *objp) { register int32_t *buf; if (!xdr_array (xdrs, (char **)&objp->SECINFO4resok_val, (u_int *) &objp->SECINFO4resok_len, ~0, sizeof (secinfo4), (xdrproc_t) xdr_secinfo4)) return FALSE; return TRUE; } bool_t xdr_SECINFO4res (XDR *xdrs, SECINFO4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_SECINFO4resok (xdrs, &objp->SECINFO4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_SETATTR4args (XDR *xdrs, SETATTR4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_fattr4 (xdrs, &objp->obj_attributes)) return FALSE; return TRUE; } bool_t xdr_SETATTR4res (XDR *xdrs, SETATTR4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; if (!xdr_bitmap4 (xdrs, &objp->attrsset)) return FALSE; return TRUE; } bool_t xdr_SETCLIENTID4args (XDR *xdrs, SETCLIENTID4args *objp) { register int32_t *buf; if (!xdr_nfs_client_id4 (xdrs, &objp->client)) return FALSE; if (!xdr_cb_client4 (xdrs, &objp->callback)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->callback_ident)) return FALSE; return TRUE; } bool_t xdr_SETCLIENTID4resok (XDR *xdrs, SETCLIENTID4resok *objp) { register int32_t *buf; if (!xdr_clientid4 (xdrs, &objp->clientid)) return FALSE; if (!xdr_verifier4 (xdrs, objp->setclientid_confirm)) return FALSE; return TRUE; } bool_t xdr_SETCLIENTID4res (XDR *xdrs, SETCLIENTID4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_SETCLIENTID4resok (xdrs, &objp->SETCLIENTID4res_u.resok4)) return FALSE; break; case NFS4ERR_CLID_INUSE: if (!xdr_clientaddr4 (xdrs, &objp->SETCLIENTID4res_u.client_using)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_SETCLIENTID_CONFIRM4args (XDR *xdrs, SETCLIENTID_CONFIRM4args *objp) { register int32_t *buf; if (!xdr_clientid4 (xdrs, &objp->clientid)) return FALSE; if (!xdr_verifier4 (xdrs, objp->setclientid_confirm)) return FALSE; return TRUE; } bool_t xdr_SETCLIENTID_CONFIRM4res (XDR *xdrs, SETCLIENTID_CONFIRM4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_VERIFY4args (XDR *xdrs, VERIFY4args *objp) { register int32_t *buf; if (!xdr_fattr4 (xdrs, &objp->obj_attributes)) return FALSE; return TRUE; } bool_t xdr_VERIFY4res (XDR *xdrs, VERIFY4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_stable_how4 (XDR *xdrs, stable_how4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_WRITE4args (XDR *xdrs, WRITE4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_offset4 (xdrs, &objp->offset)) return FALSE; if (!xdr_stable_how4 (xdrs, &objp->stable)) return FALSE; if (!xdr_bytes (xdrs, (char **)&objp->data.data_val, (u_int *) &objp->data.data_len, ~0)) return FALSE; return TRUE; } bool_t xdr_WRITE4resok (XDR *xdrs, WRITE4resok *objp) { register int32_t *buf; if (!xdr_count4 (xdrs, &objp->count)) return FALSE; if (!xdr_stable_how4 (xdrs, &objp->committed)) return FALSE; if (!xdr_verifier4 (xdrs, objp->writeverf)) return FALSE; return TRUE; } bool_t xdr_WRITE4res (XDR *xdrs, WRITE4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_WRITE4resok (xdrs, &objp->WRITE4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_RELEASE_LOCKOWNER4args (XDR *xdrs, RELEASE_LOCKOWNER4args *objp) { register int32_t *buf; if (!xdr_lock_owner4 (xdrs, &objp->lock_owner)) return FALSE; return TRUE; } bool_t xdr_RELEASE_LOCKOWNER4res (XDR *xdrs, RELEASE_LOCKOWNER4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_ILLEGAL4res (XDR *xdrs, ILLEGAL4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_nfs_opnum4 (XDR *xdrs, nfs_opnum4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_nfs_argop4 (XDR *xdrs, nfs_argop4 *objp) { register int32_t *buf; if (!xdr_nfs_opnum4 (xdrs, &objp->argop)) return FALSE; switch (objp->argop) { case OP_ACCESS: if (!xdr_ACCESS4args (xdrs, &objp->nfs_argop4_u.opaccess)) return FALSE; break; case OP_CLOSE: if (!xdr_CLOSE4args (xdrs, &objp->nfs_argop4_u.opclose)) return FALSE; break; case OP_COMMIT: if (!xdr_COMMIT4args (xdrs, &objp->nfs_argop4_u.opcommit)) return FALSE; break; case OP_CREATE: if (!xdr_CREATE4args (xdrs, &objp->nfs_argop4_u.opcreate)) return FALSE; break; case OP_DELEGPURGE: if (!xdr_DELEGPURGE4args (xdrs, &objp->nfs_argop4_u.opdelegpurge)) return FALSE; break; case OP_DELEGRETURN: if (!xdr_DELEGRETURN4args (xdrs, &objp->nfs_argop4_u.opdelegreturn)) return FALSE; break; case OP_GETATTR: if (!xdr_GETATTR4args (xdrs, &objp->nfs_argop4_u.opgetattr)) return FALSE; break; case OP_GETFH: break; case OP_LINK: if (!xdr_LINK4args (xdrs, &objp->nfs_argop4_u.oplink)) return FALSE; break; case OP_LOCK: if (!xdr_LOCK4args (xdrs, &objp->nfs_argop4_u.oplock)) return FALSE; break; case OP_LOCKT: if (!xdr_LOCKT4args (xdrs, &objp->nfs_argop4_u.oplockt)) return FALSE; break; case OP_LOCKU: if (!xdr_LOCKU4args (xdrs, &objp->nfs_argop4_u.oplocku)) return FALSE; break; case OP_LOOKUP: if (!xdr_LOOKUP4args (xdrs, &objp->nfs_argop4_u.oplookup)) return FALSE; break; case OP_LOOKUPP: break; case OP_NVERIFY: if (!xdr_NVERIFY4args (xdrs, &objp->nfs_argop4_u.opnverify)) return FALSE; break; case OP_OPEN: if (!xdr_OPEN4args (xdrs, &objp->nfs_argop4_u.opopen)) return FALSE; break; case OP_OPENATTR: if (!xdr_OPENATTR4args (xdrs, &objp->nfs_argop4_u.opopenattr)) return FALSE; break; case OP_OPEN_CONFIRM: if (!xdr_OPEN_CONFIRM4args (xdrs, &objp->nfs_argop4_u.opopen_confirm)) return FALSE; break; case OP_OPEN_DOWNGRADE: if (!xdr_OPEN_DOWNGRADE4args (xdrs, &objp->nfs_argop4_u.opopen_downgrade)) return FALSE; break; case OP_PUTFH: if (!xdr_PUTFH4args (xdrs, &objp->nfs_argop4_u.opputfh)) return FALSE; break; case OP_PUTPUBFH: break; case OP_PUTROOTFH: break; case OP_READ: if (!xdr_READ4args (xdrs, &objp->nfs_argop4_u.opread)) return FALSE; break; case OP_READDIR: if (!xdr_READDIR4args (xdrs, &objp->nfs_argop4_u.opreaddir)) return FALSE; break; case OP_READLINK: break; case OP_REMOVE: if (!xdr_REMOVE4args (xdrs, &objp->nfs_argop4_u.opremove)) return FALSE; break; case OP_RENAME: if (!xdr_RENAME4args (xdrs, &objp->nfs_argop4_u.oprename)) return FALSE; break; case OP_RENEW: if (!xdr_RENEW4args (xdrs, &objp->nfs_argop4_u.oprenew)) return FALSE; break; case OP_RESTOREFH: break; case OP_SAVEFH: break; case OP_SECINFO: if (!xdr_SECINFO4args (xdrs, &objp->nfs_argop4_u.opsecinfo)) return FALSE; break; case OP_SETATTR: if (!xdr_SETATTR4args (xdrs, &objp->nfs_argop4_u.opsetattr)) return FALSE; break; case OP_SETCLIENTID: if (!xdr_SETCLIENTID4args (xdrs, &objp->nfs_argop4_u.opsetclientid)) return FALSE; break; case OP_SETCLIENTID_CONFIRM: if (!xdr_SETCLIENTID_CONFIRM4args (xdrs, &objp->nfs_argop4_u.opsetclientid_confirm)) return FALSE; break; case OP_VERIFY: if (!xdr_VERIFY4args (xdrs, &objp->nfs_argop4_u.opverify)) return FALSE; break; case OP_WRITE: if (!xdr_WRITE4args (xdrs, &objp->nfs_argop4_u.opwrite)) return FALSE; break; case OP_RELEASE_LOCKOWNER: if (!xdr_RELEASE_LOCKOWNER4args (xdrs, &objp->nfs_argop4_u.oprelease_lockowner)) return FALSE; break; case OP_ILLEGAL: break; default: return FALSE; } return TRUE; } bool_t xdr_nfs_resop4 (XDR *xdrs, nfs_resop4 *objp) { register int32_t *buf; if (!xdr_nfs_opnum4 (xdrs, &objp->resop)) return FALSE; switch (objp->resop) { case OP_ACCESS: if (!xdr_ACCESS4res (xdrs, &objp->nfs_resop4_u.opaccess)) return FALSE; break; case OP_CLOSE: if (!xdr_CLOSE4res (xdrs, &objp->nfs_resop4_u.opclose)) return FALSE; break; case OP_COMMIT: if (!xdr_COMMIT4res (xdrs, &objp->nfs_resop4_u.opcommit)) return FALSE; break; case OP_CREATE: if (!xdr_CREATE4res (xdrs, &objp->nfs_resop4_u.opcreate)) return FALSE; break; case OP_DELEGPURGE: if (!xdr_DELEGPURGE4res (xdrs, &objp->nfs_resop4_u.opdelegpurge)) return FALSE; break; case OP_DELEGRETURN: if (!xdr_DELEGRETURN4res (xdrs, &objp->nfs_resop4_u.opdelegreturn)) return FALSE; break; case OP_GETATTR: if (!xdr_GETATTR4res (xdrs, &objp->nfs_resop4_u.opgetattr)) return FALSE; break; case OP_GETFH: if (!xdr_GETFH4res (xdrs, &objp->nfs_resop4_u.opgetfh)) return FALSE; break; case OP_LINK: if (!xdr_LINK4res (xdrs, &objp->nfs_resop4_u.oplink)) return FALSE; break; case OP_LOCK: if (!xdr_LOCK4res (xdrs, &objp->nfs_resop4_u.oplock)) return FALSE; break; case OP_LOCKT: if (!xdr_LOCKT4res (xdrs, &objp->nfs_resop4_u.oplockt)) return FALSE; break; case OP_LOCKU: if (!xdr_LOCKU4res (xdrs, &objp->nfs_resop4_u.oplocku)) return FALSE; break; case OP_LOOKUP: if (!xdr_LOOKUP4res (xdrs, &objp->nfs_resop4_u.oplookup)) return FALSE; break; case OP_LOOKUPP: if (!xdr_LOOKUPP4res (xdrs, &objp->nfs_resop4_u.oplookupp)) return FALSE; break; case OP_NVERIFY: if (!xdr_NVERIFY4res (xdrs, &objp->nfs_resop4_u.opnverify)) return FALSE; break; case OP_OPEN: if (!xdr_OPEN4res (xdrs, &objp->nfs_resop4_u.opopen)) return FALSE; break; case OP_OPENATTR: if (!xdr_OPENATTR4res (xdrs, &objp->nfs_resop4_u.opopenattr)) return FALSE; break; case OP_OPEN_CONFIRM: if (!xdr_OPEN_CONFIRM4res (xdrs, &objp->nfs_resop4_u.opopen_confirm)) return FALSE; break; case OP_OPEN_DOWNGRADE: if (!xdr_OPEN_DOWNGRADE4res (xdrs, &objp->nfs_resop4_u.opopen_downgrade)) return FALSE; break; case OP_PUTFH: if (!xdr_PUTFH4res (xdrs, &objp->nfs_resop4_u.opputfh)) return FALSE; break; case OP_PUTPUBFH: if (!xdr_PUTPUBFH4res (xdrs, &objp->nfs_resop4_u.opputpubfh)) return FALSE; break; case OP_PUTROOTFH: if (!xdr_PUTROOTFH4res (xdrs, &objp->nfs_resop4_u.opputrootfh)) return FALSE; break; case OP_READ: if (!xdr_READ4res (xdrs, &objp->nfs_resop4_u.opread)) return FALSE; break; case OP_READDIR: if (!xdr_READDIR4res (xdrs, &objp->nfs_resop4_u.opreaddir)) return FALSE; break; case OP_READLINK: if (!xdr_READLINK4res (xdrs, &objp->nfs_resop4_u.opreadlink)) return FALSE; break; case OP_REMOVE: if (!xdr_REMOVE4res (xdrs, &objp->nfs_resop4_u.opremove)) return FALSE; break; case OP_RENAME: if (!xdr_RENAME4res (xdrs, &objp->nfs_resop4_u.oprename)) return FALSE; break; case OP_RENEW: if (!xdr_RENEW4res (xdrs, &objp->nfs_resop4_u.oprenew)) return FALSE; break; case OP_RESTOREFH: if (!xdr_RESTOREFH4res (xdrs, &objp->nfs_resop4_u.oprestorefh)) return FALSE; break; case OP_SAVEFH: if (!xdr_SAVEFH4res (xdrs, &objp->nfs_resop4_u.opsavefh)) return FALSE; break; case OP_SECINFO: if (!xdr_SECINFO4res (xdrs, &objp->nfs_resop4_u.opsecinfo)) return FALSE; break; case OP_SETATTR: if (!xdr_SETATTR4res (xdrs, &objp->nfs_resop4_u.opsetattr)) return FALSE; break; case OP_SETCLIENTID: if (!xdr_SETCLIENTID4res (xdrs, &objp->nfs_resop4_u.opsetclientid)) return FALSE; break; case OP_SETCLIENTID_CONFIRM: if (!xdr_SETCLIENTID_CONFIRM4res (xdrs, &objp->nfs_resop4_u.opsetclientid_confirm)) return FALSE; break; case OP_VERIFY: if (!xdr_VERIFY4res (xdrs, &objp->nfs_resop4_u.opverify)) return FALSE; break; case OP_WRITE: if (!xdr_WRITE4res (xdrs, &objp->nfs_resop4_u.opwrite)) return FALSE; break; case OP_RELEASE_LOCKOWNER: if (!xdr_RELEASE_LOCKOWNER4res (xdrs, &objp->nfs_resop4_u.oprelease_lockowner)) return FALSE; break; case OP_ILLEGAL: if (!xdr_ILLEGAL4res (xdrs, &objp->nfs_resop4_u.opillegal)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_COMPOUND4args (XDR *xdrs, COMPOUND4args *objp) { register int32_t *buf; if (!xdr_utf8str_cs (xdrs, &objp->tag)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->minorversion)) return FALSE; if (!xdr_array (xdrs, (char **)&objp->argarray.argarray_val, (u_int *) &objp->argarray.argarray_len, ~0, sizeof (nfs_argop4), (xdrproc_t) xdr_nfs_argop4)) return FALSE; return TRUE; } bool_t xdr_COMPOUND4res (XDR *xdrs, COMPOUND4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; if (!xdr_utf8str_cs (xdrs, &objp->tag)) return FALSE; if (!xdr_array (xdrs, (char **)&objp->resarray.resarray_val, (u_int *) &objp->resarray.resarray_len, ~0, sizeof (nfs_resop4), (xdrproc_t) xdr_nfs_resop4)) return FALSE; return TRUE; } bool_t xdr_CB_GETATTR4args (XDR *xdrs, CB_GETATTR4args *objp) { register int32_t *buf; if (!xdr_nfs_fh4 (xdrs, &objp->fh)) return FALSE; if (!xdr_bitmap4 (xdrs, &objp->attr_request)) return FALSE; return TRUE; } bool_t xdr_CB_GETATTR4resok (XDR *xdrs, CB_GETATTR4resok *objp) { register int32_t *buf; if (!xdr_fattr4 (xdrs, &objp->obj_attributes)) return FALSE; return TRUE; } bool_t xdr_CB_GETATTR4res (XDR *xdrs, CB_GETATTR4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; switch (objp->status) { case NFS4_OK: if (!xdr_CB_GETATTR4resok (xdrs, &objp->CB_GETATTR4res_u.resok4)) return FALSE; break; default: break; } return TRUE; } bool_t xdr_CB_RECALL4args (XDR *xdrs, CB_RECALL4args *objp) { register int32_t *buf; if (!xdr_stateid4 (xdrs, &objp->stateid)) return FALSE; if (!xdr_bool (xdrs, &objp->truncate)) return FALSE; if (!xdr_nfs_fh4 (xdrs, &objp->fh)) return FALSE; return TRUE; } bool_t xdr_CB_RECALL4res (XDR *xdrs, CB_RECALL4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_CB_ILLEGAL4res (XDR *xdrs, CB_ILLEGAL4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; return TRUE; } bool_t xdr_nfs_cb_opnum4 (XDR *xdrs, nfs_cb_opnum4 *objp) { register int32_t *buf; if (!xdr_enum (xdrs, (enum_t *) objp)) return FALSE; return TRUE; } bool_t xdr_nfs_cb_argop4 (XDR *xdrs, nfs_cb_argop4 *objp) { register int32_t *buf; if (!xdr_u_int (xdrs, &objp->argop)) return FALSE; switch (objp->argop) { case NFS4_OP_CB_GETATTR: if (!xdr_CB_GETATTR4args (xdrs, &objp->nfs_cb_argop4_u.opcbgetattr)) return FALSE; break; case NFS4_OP_CB_RECALL: if (!xdr_CB_RECALL4args (xdrs, &objp->nfs_cb_argop4_u.opcbrecall)) return FALSE; break; case NFS4_OP_CB_ILLEGAL: break; default: return FALSE; } return TRUE; } bool_t xdr_nfs_cb_resop4 (XDR *xdrs, nfs_cb_resop4 *objp) { register int32_t *buf; if (!xdr_u_int (xdrs, &objp->resop)) return FALSE; switch (objp->resop) { case NFS4_OP_CB_GETATTR: if (!xdr_CB_GETATTR4res (xdrs, &objp->nfs_cb_resop4_u.opcbgetattr)) return FALSE; break; case NFS4_OP_CB_RECALL: if (!xdr_CB_RECALL4res (xdrs, &objp->nfs_cb_resop4_u.opcbrecall)) return FALSE; break; case NFS4_OP_CB_ILLEGAL: if (!xdr_CB_ILLEGAL4res (xdrs, &objp->nfs_cb_resop4_u.opcbillegal)) return FALSE; break; default: return FALSE; } return TRUE; } bool_t xdr_CB_COMPOUND4args (XDR *xdrs, CB_COMPOUND4args *objp) { register int32_t *buf; if (!xdr_utf8str_cs (xdrs, &objp->tag)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->minorversion)) return FALSE; if (!xdr_uint32_t (xdrs, &objp->callback_ident)) return FALSE; if (!xdr_array (xdrs, (char **)&objp->argarray.argarray_val, (u_int *) &objp->argarray.argarray_len, ~0, sizeof (nfs_cb_argop4), (xdrproc_t) xdr_nfs_cb_argop4)) return FALSE; return TRUE; } bool_t xdr_CB_COMPOUND4res (XDR *xdrs, CB_COMPOUND4res *objp) { register int32_t *buf; if (!xdr_nfsstat4 (xdrs, &objp->status)) return FALSE; if (!xdr_utf8str_cs (xdrs, &objp->tag)) return FALSE; if (!xdr_array (xdrs, (char **)&objp->resarray.resarray_val, (u_int *) &objp->resarray.resarray_len, ~0, sizeof (nfs_cb_resop4), (xdrproc_t) xdr_nfs_cb_resop4)) return FALSE; return TRUE; } ntirpc-1.3.1/tests/nfsv40.h000066400000000000000000001142321261345040100154450ustar00rootroot00000000000000/* * Please do not edit this file. * It was generated using rpcgen. */ #ifndef _NFS4_H_RPCGEN #define _NFS4_H_RPCGEN #ifndef _USE_SWIG #endif #ifdef _SOLARIS #include "solaris_port.h" #endif /* _SOLARIS */ #define NFS4_FHSIZE 128 #define NFS4_VERIFIER_SIZE 8 #define NFS4_OPAQUE_LIMIT 1024 enum nfs_ftype4 { NF4REG = 1, NF4DIR = 2, NF4BLK = 3, NF4CHR = 4, NF4LNK = 5, NF4SOCK = 6, NF4FIFO = 7, NF4ATTRDIR = 8, NF4NAMEDATTR = 9 }; typedef enum nfs_ftype4 nfs_ftype4; enum nfsstat4 { NFS4_OK = 0, NFS4ERR_PERM = 1, NFS4ERR_NOENT = 2, NFS4ERR_IO = 5, NFS4ERR_NXIO = 6, NFS4ERR_ACCESS = 13, NFS4ERR_EXIST = 17, NFS4ERR_XDEV = 18, NFS4ERR_NOTDIR = 20, NFS4ERR_ISDIR = 21, NFS4ERR_INVAL = 22, NFS4ERR_FBIG = 27, NFS4ERR_NOSPC = 28, NFS4ERR_ROFS = 30, NFS4ERR_MLINK = 31, NFS4ERR_NAMETOOLONG = 63, NFS4ERR_NOTEMPTY = 66, NFS4ERR_DQUOT = 69, NFS4ERR_STALE = 70, NFS4ERR_BADHANDLE = 10001, NFS4ERR_BAD_COOKIE = 10003, NFS4ERR_NOTSUPP = 10004, NFS4ERR_TOOSMALL = 10005, NFS4ERR_SERVERFAULT = 10006, NFS4ERR_BADTYPE = 10007, NFS4ERR_DELAY = 10008, NFS4ERR_SAME = 10009, NFS4ERR_DENIED = 10010, NFS4ERR_EXPIRED = 10011, NFS4ERR_LOCKED = 10012, NFS4ERR_GRACE = 10013, NFS4ERR_FHEXPIRED = 10014, NFS4ERR_SHARE_DENIED = 10015, NFS4ERR_WRONGSEC = 10016, NFS4ERR_CLID_INUSE = 10017, NFS4ERR_RESOURCE = 10018, NFS4ERR_MOVED = 10019, NFS4ERR_NOFILEHANDLE = 10020, NFS4ERR_MINOR_VERS_MISMATCH = 10021, NFS4ERR_STALE_CLIENTID = 10022, NFS4ERR_STALE_STATEID = 10023, NFS4ERR_OLD_STATEID = 10024, NFS4ERR_BAD_STATEID = 10025, NFS4ERR_BAD_SEQID = 10026, NFS4ERR_NOT_SAME = 10027, NFS4ERR_LOCK_RANGE = 10028, NFS4ERR_SYMLINK = 10029, NFS4ERR_RESTOREFH = 10030, NFS4ERR_LEASE_MOVED = 10031, NFS4ERR_ATTRNOTSUPP = 10032, NFS4ERR_NO_GRACE = 10033, NFS4ERR_RECLAIM_BAD = 10034, NFS4ERR_RECLAIM_CONFLICT = 10035, NFS4ERR_BADXDR = 10036, NFS4ERR_LOCKS_HELD = 10037, NFS4ERR_OPENMODE = 10038, NFS4ERR_BADOWNER = 10039, NFS4ERR_BADCHAR = 10040, NFS4ERR_BADNAME = 10041, NFS4ERR_BAD_RANGE = 10042, NFS4ERR_LOCK_NOTSUPP = 10043, NFS4ERR_OP_ILLEGAL = 10044, NFS4ERR_DEADLOCK = 10045, NFS4ERR_FILE_OPEN = 10046, NFS4ERR_ADMIN_REVOKED = 10047, NFS4ERR_CB_PATH_DOWN = 10048 }; typedef enum nfsstat4 nfsstat4; typedef struct { u_int bitmap4_len; uint32_t *bitmap4_val; } bitmap4; typedef uint64_t offset4; typedef uint32_t count4; typedef uint64_t length4; typedef uint64_t clientid4; typedef uint32_t seqid4; typedef struct { u_int utf8string_len; char *utf8string_val; } utf8string; typedef utf8string utf8str_cis; typedef utf8string utf8str_cs; typedef utf8string utf8str_mixed; typedef utf8str_cs component4; typedef struct { u_int pathname4_len; component4 *pathname4_val; } pathname4; typedef uint64_t nfs_lockid4; typedef uint64_t nfs_cookie4; typedef utf8str_cs linktext4; typedef struct { u_int sec_oid4_len; char *sec_oid4_val; } sec_oid4; typedef uint32_t qop4; typedef uint32_t mode4; typedef uint64_t changeid4; typedef char verifier4[NFS4_VERIFIER_SIZE]; struct nfstime4 { int64_t seconds; uint32_t nseconds; }; typedef struct nfstime4 nfstime4; enum time_how4 { SET_TO_SERVER_TIME4 = 0, SET_TO_CLIENT_TIME4 = 1 }; typedef enum time_how4 time_how4; struct settime4 { time_how4 set_it; union { nfstime4 time; } settime4_u; }; typedef struct settime4 settime4; typedef struct { u_int nfs_fh4_len; char *nfs_fh4_val; } nfs_fh4; struct fsid4 { uint64_t major; uint64_t minor; }; typedef struct fsid4 fsid4; struct fs_location4 { struct { u_int server_len; utf8str_cis *server_val; } server; pathname4 rootpath; }; typedef struct fs_location4 fs_location4; struct fs_locations4 { pathname4 fs_root; struct { u_int locations_len; fs_location4 *locations_val; } locations; }; typedef struct fs_locations4 fs_locations4; #define ACL4_SUPPORT_ALLOW_ACL 0x00000001 #define ACL4_SUPPORT_DENY_ACL 0x00000002 #define ACL4_SUPPORT_AUDIT_ACL 0x00000004 #define ACL4_SUPPORT_ALARM_ACL 0x00000008 typedef uint32_t acetype4; #define ACE4_ACCESS_ALLOWED_ACE_TYPE 0x00000000 #define ACE4_ACCESS_DENIED_ACE_TYPE 0x00000001 #define ACE4_SYSTEM_AUDIT_ACE_TYPE 0x00000002 #define ACE4_SYSTEM_ALARM_ACE_TYPE 0x00000003 typedef uint32_t aceflag4; #define ACE4_FILE_INHERIT_ACE 0x00000001 #define ACE4_DIRECTORY_INHERIT_ACE 0x00000002 #define ACE4_NO_PROPAGATE_INHERIT_ACE 0x00000004 #define ACE4_INHERIT_ONLY_ACE 0x00000008 #define ACE4_SUCCESSFUL_ACCESS_ACE_FLAG 0x00000010 #define ACE4_FAILED_ACCESS_ACE_FLAG 0x00000020 #define ACE4_IDENTIFIER_GROUP 0x00000040 typedef uint32_t acemask4; #define ACE4_READ_DATA 0x00000001 #define ACE4_LIST_DIRECTORY 0x00000001 #define ACE4_WRITE_DATA 0x00000002 #define ACE4_ADD_FILE 0x00000002 #define ACE4_APPEND_DATA 0x00000004 #define ACE4_ADD_SUBDIRECTORY 0x00000004 #define ACE4_READ_NAMED_ATTRS 0x00000008 #define ACE4_WRITE_NAMED_ATTRS 0x00000010 #define ACE4_EXECUTE 0x00000020 #define ACE4_DELETE_CHILD 0x00000040 #define ACE4_READ_ATTRIBUTES 0x00000080 #define ACE4_WRITE_ATTRIBUTES 0x00000100 #define ACE4_DELETE 0x00010000 #define ACE4_READ_ACL 0x00020000 #define ACE4_WRITE_ACL 0x00040000 #define ACE4_WRITE_OWNER 0x00080000 #define ACE4_SYNCHRONIZE 0x00100000 #define ACE4_GENERIC_READ 0x00120081 #define ACE4_GENERIC_WRITE 0x00160106 #define ACE4_GENERIC_EXECUTE 0x001200A0 struct nfsace4 { acetype4 type; aceflag4 flag; acemask4 access_mask; utf8str_mixed who; }; typedef struct nfsace4 nfsace4; #define MODE4_SUID 0x800 #define MODE4_SGID 0x400 #define MODE4_SVTX 0x200 #define MODE4_RUSR 0x100 #define MODE4_WUSR 0x080 #define MODE4_XUSR 0x040 #define MODE4_RGRP 0x020 #define MODE4_WGRP 0x010 #define MODE4_XGRP 0x008 #define MODE4_ROTH 0x004 #define MODE4_WOTH 0x002 #define MODE4_XOTH 0x001 struct specdata4 { uint32_t specdata1; uint32_t specdata2; }; typedef struct specdata4 specdata4; #define FH4_PERSISTENT 0x00000000 #define FH4_NOEXPIRE_WITH_OPEN 0x00000001 #define FH4_VOLATILE_ANY 0x00000002 #define FH4_VOL_MIGRATION 0x00000004 #define FH4_VOL_RENAME 0x00000008 typedef bitmap4 fattr4_supported_attrs; typedef nfs_ftype4 fattr4_type; typedef uint32_t fattr4_fh_expire_type; typedef changeid4 fattr4_change; typedef uint64_t fattr4_size; typedef bool_t fattr4_link_support; typedef bool_t fattr4_symlink_support; typedef bool_t fattr4_named_attr; typedef fsid4 fattr4_fsid; typedef bool_t fattr4_unique_handles; typedef uint32_t fattr4_lease_time; typedef nfsstat4 fattr4_rdattr_error; typedef struct { u_int fattr4_acl_len; nfsace4 *fattr4_acl_val; } fattr4_acl; typedef uint32_t fattr4_aclsupport; typedef bool_t fattr4_archive; typedef bool_t fattr4_cansettime; typedef bool_t fattr4_case_insensitive; typedef bool_t fattr4_case_preserving; typedef bool_t fattr4_chown_restricted; typedef uint64_t fattr4_fileid; typedef uint64_t fattr4_files_avail; typedef nfs_fh4 fattr4_filehandle; typedef uint64_t fattr4_files_free; typedef uint64_t fattr4_files_total; typedef fs_locations4 fattr4_fs_locations; typedef bool_t fattr4_hidden; typedef bool_t fattr4_homogeneous; typedef uint64_t fattr4_maxfilesize; typedef uint32_t fattr4_maxlink; typedef uint32_t fattr4_maxname; typedef uint64_t fattr4_maxread; typedef uint64_t fattr4_maxwrite; typedef utf8str_cs fattr4_mimetype; typedef mode4 fattr4_mode; typedef uint64_t fattr4_mounted_on_fileid; typedef bool_t fattr4_no_trunc; typedef uint32_t fattr4_numlinks; typedef utf8str_mixed fattr4_owner; typedef utf8str_mixed fattr4_owner_group; typedef uint64_t fattr4_quota_avail_hard; typedef uint64_t fattr4_quota_avail_soft; typedef uint64_t fattr4_quota_used; typedef specdata4 fattr4_rawdev; typedef uint64_t fattr4_space_avail; typedef uint64_t fattr4_space_free; typedef uint64_t fattr4_space_total; typedef uint64_t fattr4_space_used; typedef bool_t fattr4_system; typedef nfstime4 fattr4_time_access; typedef settime4 fattr4_time_access_set; typedef nfstime4 fattr4_time_backup; typedef nfstime4 fattr4_time_create; typedef nfstime4 fattr4_time_delta; typedef nfstime4 fattr4_time_metadata; typedef nfstime4 fattr4_time_modify; typedef settime4 fattr4_time_modify_set; #define FATTR4_SUPPORTED_ATTRS 0 #define FATTR4_TYPE 1 #define FATTR4_FH_EXPIRE_TYPE 2 #define FATTR4_CHANGE 3 #define FATTR4_SIZE 4 #define FATTR4_LINK_SUPPORT 5 #define FATTR4_SYMLINK_SUPPORT 6 #define FATTR4_NAMED_ATTR 7 #define FATTR4_FSID 8 #define FATTR4_UNIQUE_HANDLES 9 #define FATTR4_LEASE_TIME 10 #define FATTR4_RDATTR_ERROR 11 #define FATTR4_FILEHANDLE 19 #define FATTR4_ACL 12 #define FATTR4_ACLSUPPORT 13 #define FATTR4_ARCHIVE 14 #define FATTR4_CANSETTIME 15 #define FATTR4_CASE_INSENSITIVE 16 #define FATTR4_CASE_PRESERVING 17 #define FATTR4_CHOWN_RESTRICTED 18 #define FATTR4_FILEID 20 #define FATTR4_FILES_AVAIL 21 #define FATTR4_FILES_FREE 22 #define FATTR4_FILES_TOTAL 23 #define FATTR4_FS_LOCATIONS 24 #define FATTR4_HIDDEN 25 #define FATTR4_HOMOGENEOUS 26 #define FATTR4_MAXFILESIZE 27 #define FATTR4_MAXLINK 28 #define FATTR4_MAXNAME 29 #define FATTR4_MAXREAD 30 #define FATTR4_MAXWRITE 31 #define FATTR4_MIMETYPE 32 #define FATTR4_MODE 33 #define FATTR4_NO_TRUNC 34 #define FATTR4_NUMLINKS 35 #define FATTR4_OWNER 36 #define FATTR4_OWNER_GROUP 37 #define FATTR4_QUOTA_AVAIL_HARD 38 #define FATTR4_QUOTA_AVAIL_SOFT 39 #define FATTR4_QUOTA_USED 40 #define FATTR4_RAWDEV 41 #define FATTR4_SPACE_AVAIL 42 #define FATTR4_SPACE_FREE 43 #define FATTR4_SPACE_TOTAL 44 #define FATTR4_SPACE_USED 45 #define FATTR4_SYSTEM 46 #define FATTR4_TIME_ACCESS 47 #define FATTR4_TIME_ACCESS_SET 48 #define FATTR4_TIME_BACKUP 49 #define FATTR4_TIME_CREATE 50 #define FATTR4_TIME_DELTA 51 #define FATTR4_TIME_METADATA 52 #define FATTR4_TIME_MODIFY 53 #define FATTR4_TIME_MODIFY_SET 54 #define FATTR4_MOUNTED_ON_FILEID 55 typedef struct { u_int attrlist4_len; char *attrlist4_val; } attrlist4; struct fattr4 { bitmap4 attrmask; attrlist4 attr_vals; }; typedef struct fattr4 fattr4; struct change_info4 { bool_t atomic; changeid4 before; changeid4 after; }; typedef struct change_info4 change_info4; struct clientaddr4 { char *r_netid; char *r_addr; }; typedef struct clientaddr4 clientaddr4; struct cb_client4 { uint32_t cb_program; clientaddr4 cb_location; }; typedef struct cb_client4 cb_client4; struct stateid4 { uint32_t seqid; char other[12]; }; typedef struct stateid4 stateid4; struct nfs_client_id4 { verifier4 verifier; struct { u_int id_len; char *id_val; } id; }; typedef struct nfs_client_id4 nfs_client_id4; struct open_owner4 { clientid4 clientid; struct { u_int owner_len; char *owner_val; } owner; }; typedef struct open_owner4 open_owner4; struct lock_owner4 { clientid4 clientid; struct { u_int owner_len; char *owner_val; } owner; }; typedef struct lock_owner4 lock_owner4; enum nfs_lock_type4 { READ_LT = 1, WRITE_LT = 2, READW_LT = 3, WRITEW_LT = 4 }; typedef enum nfs_lock_type4 nfs_lock_type4; #define ACCESS4_READ 0x00000001 #define ACCESS4_LOOKUP 0x00000002 #define ACCESS4_MODIFY 0x00000004 #define ACCESS4_EXTEND 0x00000008 #define ACCESS4_DELETE 0x00000010 #define ACCESS4_EXECUTE 0x00000020 struct ACCESS4args { uint32_t access; }; typedef struct ACCESS4args ACCESS4args; struct ACCESS4resok { uint32_t supported; uint32_t access; }; typedef struct ACCESS4resok ACCESS4resok; struct ACCESS4res { nfsstat4 status; union { ACCESS4resok resok4; } ACCESS4res_u; }; typedef struct ACCESS4res ACCESS4res; struct CLOSE4args { seqid4 seqid; stateid4 open_stateid; }; typedef struct CLOSE4args CLOSE4args; struct CLOSE4res { nfsstat4 status; union { stateid4 open_stateid; } CLOSE4res_u; }; typedef struct CLOSE4res CLOSE4res; struct COMMIT4args { offset4 offset; count4 count; }; typedef struct COMMIT4args COMMIT4args; struct COMMIT4resok { verifier4 writeverf; }; typedef struct COMMIT4resok COMMIT4resok; struct COMMIT4res { nfsstat4 status; union { COMMIT4resok resok4; } COMMIT4res_u; }; typedef struct COMMIT4res COMMIT4res; struct createtype4 { nfs_ftype4 type; union { linktext4 linkdata; specdata4 devdata; } createtype4_u; }; typedef struct createtype4 createtype4; struct CREATE4args { createtype4 objtype; component4 objname; fattr4 createattrs; }; typedef struct CREATE4args CREATE4args; struct CREATE4resok { change_info4 cinfo; bitmap4 attrset; }; typedef struct CREATE4resok CREATE4resok; struct CREATE4res { nfsstat4 status; union { CREATE4resok resok4; } CREATE4res_u; }; typedef struct CREATE4res CREATE4res; struct DELEGPURGE4args { clientid4 clientid; }; typedef struct DELEGPURGE4args DELEGPURGE4args; struct DELEGPURGE4res { nfsstat4 status; }; typedef struct DELEGPURGE4res DELEGPURGE4res; struct DELEGRETURN4args { stateid4 deleg_stateid; }; typedef struct DELEGRETURN4args DELEGRETURN4args; struct DELEGRETURN4res { nfsstat4 status; }; typedef struct DELEGRETURN4res DELEGRETURN4res; struct GETATTR4args { bitmap4 attr_request; }; typedef struct GETATTR4args GETATTR4args; struct GETATTR4resok { fattr4 obj_attributes; }; typedef struct GETATTR4resok GETATTR4resok; struct GETATTR4res { nfsstat4 status; union { GETATTR4resok resok4; } GETATTR4res_u; }; typedef struct GETATTR4res GETATTR4res; struct GETFH4resok { nfs_fh4 object; }; typedef struct GETFH4resok GETFH4resok; struct GETFH4res { nfsstat4 status; union { GETFH4resok resok4; } GETFH4res_u; }; typedef struct GETFH4res GETFH4res; struct LINK4args { component4 newname; }; typedef struct LINK4args LINK4args; struct LINK4resok { change_info4 cinfo; }; typedef struct LINK4resok LINK4resok; struct LINK4res { nfsstat4 status; union { LINK4resok resok4; } LINK4res_u; }; typedef struct LINK4res LINK4res; struct open_to_lock_owner4 { seqid4 open_seqid; stateid4 open_stateid; seqid4 lock_seqid; lock_owner4 lock_owner; }; typedef struct open_to_lock_owner4 open_to_lock_owner4; struct exist_lock_owner4 { stateid4 lock_stateid; seqid4 lock_seqid; }; typedef struct exist_lock_owner4 exist_lock_owner4; struct locker4 { bool_t new_lock_owner; union { open_to_lock_owner4 open_owner; exist_lock_owner4 lock_owner; } locker4_u; }; typedef struct locker4 locker4; struct LOCK4args { nfs_lock_type4 locktype; bool_t reclaim; offset4 offset; length4 length; locker4 locker; }; typedef struct LOCK4args LOCK4args; struct LOCK4denied { offset4 offset; length4 length; nfs_lock_type4 locktype; lock_owner4 owner; }; typedef struct LOCK4denied LOCK4denied; struct LOCK4resok { stateid4 lock_stateid; }; typedef struct LOCK4resok LOCK4resok; struct LOCK4res { nfsstat4 status; union { LOCK4resok resok4; LOCK4denied denied; } LOCK4res_u; }; typedef struct LOCK4res LOCK4res; struct LOCKT4args { nfs_lock_type4 locktype; offset4 offset; length4 length; lock_owner4 owner; }; typedef struct LOCKT4args LOCKT4args; struct LOCKT4res { nfsstat4 status; union { LOCK4denied denied; } LOCKT4res_u; }; typedef struct LOCKT4res LOCKT4res; struct LOCKU4args { nfs_lock_type4 locktype; seqid4 seqid; stateid4 lock_stateid; offset4 offset; length4 length; }; typedef struct LOCKU4args LOCKU4args; struct LOCKU4res { nfsstat4 status; union { stateid4 lock_stateid; } LOCKU4res_u; }; typedef struct LOCKU4res LOCKU4res; struct LOOKUP4args { component4 objname; }; typedef struct LOOKUP4args LOOKUP4args; struct LOOKUP4res { nfsstat4 status; }; typedef struct LOOKUP4res LOOKUP4res; struct LOOKUPP4res { nfsstat4 status; }; typedef struct LOOKUPP4res LOOKUPP4res; struct NVERIFY4args { fattr4 obj_attributes; }; typedef struct NVERIFY4args NVERIFY4args; struct NVERIFY4res { nfsstat4 status; }; typedef struct NVERIFY4res NVERIFY4res; enum createmode4 { UNCHECKED4 = 0, GUARDED4 = 1, EXCLUSIVE4 = 2 }; typedef enum createmode4 createmode4; struct createhow4 { createmode4 mode; union { fattr4 createattrs; verifier4 createverf; } createhow4_u; }; typedef struct createhow4 createhow4; enum opentype4 { OPEN4_NOCREATE = 0, OPEN4_CREATE = 1 }; typedef enum opentype4 opentype4; struct openflag4 { opentype4 opentype; union { createhow4 how; } openflag4_u; }; typedef struct openflag4 openflag4; enum limit_by4 { NFS_LIMIT_SIZE = 1, NFS_LIMIT_BLOCKS = 2 }; typedef enum limit_by4 limit_by4; struct nfs_modified_limit4 { uint32_t num_blocks; uint32_t bytes_per_block; }; typedef struct nfs_modified_limit4 nfs_modified_limit4; struct nfs_space_limit4 { limit_by4 limitby; union { uint64_t filesize; nfs_modified_limit4 mod_blocks; } nfs_space_limit4_u; }; typedef struct nfs_space_limit4 nfs_space_limit4; #define OPEN4_SHARE_ACCESS_READ 0x00000001 #define OPEN4_SHARE_ACCESS_WRITE 0x00000002 #define OPEN4_SHARE_ACCESS_BOTH 0x00000003 #define OPEN4_SHARE_DENY_NONE 0x00000000 #define OPEN4_SHARE_DENY_READ 0x00000001 #define OPEN4_SHARE_DENY_WRITE 0x00000002 #define OPEN4_SHARE_DENY_BOTH 0x00000003 enum open_delegation_type4 { OPEN_DELEGATE_NONE = 0, OPEN_DELEGATE_READ = 1, OPEN_DELEGATE_WRITE = 2 }; typedef enum open_delegation_type4 open_delegation_type4; enum open_claim_type4 { CLAIM_NULL = 0, CLAIM_PREVIOUS = 1, CLAIM_DELEGATE_CUR = 2, CLAIM_DELEGATE_PREV = 3 }; typedef enum open_claim_type4 open_claim_type4; struct open_claim_delegate_cur4 { stateid4 delegate_stateid; component4 file; }; typedef struct open_claim_delegate_cur4 open_claim_delegate_cur4; struct open_claim4 { open_claim_type4 claim; union { component4 file; open_delegation_type4 delegate_type; open_claim_delegate_cur4 delegate_cur_info; component4 file_delegate_prev; } open_claim4_u; }; typedef struct open_claim4 open_claim4; struct OPEN4args { seqid4 seqid; uint32_t share_access; uint32_t share_deny; open_owner4 owner; openflag4 openhow; open_claim4 claim; }; typedef struct OPEN4args OPEN4args; struct open_read_delegation4 { stateid4 stateid; bool_t recall; nfsace4 permissions; }; typedef struct open_read_delegation4 open_read_delegation4; struct open_write_delegation4 { stateid4 stateid; bool_t recall; nfs_space_limit4 space_limit; nfsace4 permissions; }; typedef struct open_write_delegation4 open_write_delegation4; struct open_delegation4 { open_delegation_type4 delegation_type; union { open_read_delegation4 read; open_write_delegation4 write; } open_delegation4_u; }; typedef struct open_delegation4 open_delegation4; #define OPEN4_RESULT_CONFIRM 0x00000002 #define OPEN4_RESULT_LOCKTYPE_POSIX 0x00000004 struct OPEN4resok { stateid4 stateid; change_info4 cinfo; uint32_t rflags; bitmap4 attrset; open_delegation4 delegation; }; typedef struct OPEN4resok OPEN4resok; struct OPEN4res { nfsstat4 status; union { OPEN4resok resok4; } OPEN4res_u; }; typedef struct OPEN4res OPEN4res; struct OPENATTR4args { bool_t createdir; }; typedef struct OPENATTR4args OPENATTR4args; struct OPENATTR4res { nfsstat4 status; }; typedef struct OPENATTR4res OPENATTR4res; struct OPEN_CONFIRM4args { stateid4 open_stateid; seqid4 seqid; }; typedef struct OPEN_CONFIRM4args OPEN_CONFIRM4args; struct OPEN_CONFIRM4resok { stateid4 open_stateid; }; typedef struct OPEN_CONFIRM4resok OPEN_CONFIRM4resok; struct OPEN_CONFIRM4res { nfsstat4 status; union { OPEN_CONFIRM4resok resok4; } OPEN_CONFIRM4res_u; }; typedef struct OPEN_CONFIRM4res OPEN_CONFIRM4res; struct OPEN_DOWNGRADE4args { stateid4 open_stateid; seqid4 seqid; uint32_t share_access; uint32_t share_deny; }; typedef struct OPEN_DOWNGRADE4args OPEN_DOWNGRADE4args; struct OPEN_DOWNGRADE4resok { stateid4 open_stateid; }; typedef struct OPEN_DOWNGRADE4resok OPEN_DOWNGRADE4resok; struct OPEN_DOWNGRADE4res { nfsstat4 status; union { OPEN_DOWNGRADE4resok resok4; } OPEN_DOWNGRADE4res_u; }; typedef struct OPEN_DOWNGRADE4res OPEN_DOWNGRADE4res; struct PUTFH4args { nfs_fh4 object; }; typedef struct PUTFH4args PUTFH4args; struct PUTFH4res { nfsstat4 status; }; typedef struct PUTFH4res PUTFH4res; struct PUTPUBFH4res { nfsstat4 status; }; typedef struct PUTPUBFH4res PUTPUBFH4res; struct PUTROOTFH4res { nfsstat4 status; }; typedef struct PUTROOTFH4res PUTROOTFH4res; struct READ4args { stateid4 stateid; offset4 offset; count4 count; }; typedef struct READ4args READ4args; struct READ4resok { bool_t eof; struct { u_int data_len; char *data_val; } data; }; typedef struct READ4resok READ4resok; struct READ4res { nfsstat4 status; union { READ4resok resok4; } READ4res_u; }; typedef struct READ4res READ4res; struct READDIR4args { nfs_cookie4 cookie; verifier4 cookieverf; count4 dircount; count4 maxcount; bitmap4 attr_request; }; typedef struct READDIR4args READDIR4args; struct entry4 { nfs_cookie4 cookie; component4 name; fattr4 attrs; struct entry4 *nextentry; }; typedef struct entry4 entry4; struct dirlist4 { entry4 *entries; bool_t eof; }; typedef struct dirlist4 dirlist4; struct READDIR4resok { verifier4 cookieverf; dirlist4 reply; }; typedef struct READDIR4resok READDIR4resok; struct READDIR4res { nfsstat4 status; union { READDIR4resok resok4; } READDIR4res_u; }; typedef struct READDIR4res READDIR4res; struct READLINK4resok { linktext4 link; }; typedef struct READLINK4resok READLINK4resok; struct READLINK4res { nfsstat4 status; union { READLINK4resok resok4; } READLINK4res_u; }; typedef struct READLINK4res READLINK4res; struct REMOVE4args { component4 target; }; typedef struct REMOVE4args REMOVE4args; struct REMOVE4resok { change_info4 cinfo; }; typedef struct REMOVE4resok REMOVE4resok; struct REMOVE4res { nfsstat4 status; union { REMOVE4resok resok4; } REMOVE4res_u; }; typedef struct REMOVE4res REMOVE4res; struct RENAME4args { component4 oldname; component4 newname; }; typedef struct RENAME4args RENAME4args; struct RENAME4resok { change_info4 source_cinfo; change_info4 target_cinfo; }; typedef struct RENAME4resok RENAME4resok; struct RENAME4res { nfsstat4 status; union { RENAME4resok resok4; } RENAME4res_u; }; typedef struct RENAME4res RENAME4res; struct RENEW4args { clientid4 clientid; }; typedef struct RENEW4args RENEW4args; struct RENEW4res { nfsstat4 status; }; typedef struct RENEW4res RENEW4res; struct RESTOREFH4res { nfsstat4 status; }; typedef struct RESTOREFH4res RESTOREFH4res; struct SAVEFH4res { nfsstat4 status; }; typedef struct SAVEFH4res SAVEFH4res; struct SECINFO4args { component4 name; }; typedef struct SECINFO4args SECINFO4args; struct SETATTR4args { stateid4 stateid; fattr4 obj_attributes; }; typedef struct SETATTR4args SETATTR4args; struct SETATTR4res { nfsstat4 status; bitmap4 attrsset; }; typedef struct SETATTR4res SETATTR4res; struct SETCLIENTID4args { nfs_client_id4 client; cb_client4 callback; uint32_t callback_ident; }; typedef struct SETCLIENTID4args SETCLIENTID4args; struct SETCLIENTID4resok { clientid4 clientid; verifier4 setclientid_confirm; }; typedef struct SETCLIENTID4resok SETCLIENTID4resok; struct SETCLIENTID4res { nfsstat4 status; union { SETCLIENTID4resok resok4; clientaddr4 client_using; } SETCLIENTID4res_u; }; typedef struct SETCLIENTID4res SETCLIENTID4res; struct SETCLIENTID_CONFIRM4args { clientid4 clientid; verifier4 setclientid_confirm; }; typedef struct SETCLIENTID_CONFIRM4args SETCLIENTID_CONFIRM4args; struct SETCLIENTID_CONFIRM4res { nfsstat4 status; }; typedef struct SETCLIENTID_CONFIRM4res SETCLIENTID_CONFIRM4res; struct VERIFY4args { fattr4 obj_attributes; }; typedef struct VERIFY4args VERIFY4args; struct VERIFY4res { nfsstat4 status; }; typedef struct VERIFY4res VERIFY4res; enum stable_how4 { UNSTABLE4 = 0, DATA_SYNC4 = 1, FILE_SYNC4 = 2 }; typedef enum stable_how4 stable_how4; struct WRITE4args { stateid4 stateid; offset4 offset; stable_how4 stable; struct { u_int data_len; char *data_val; } data; }; typedef struct WRITE4args WRITE4args; struct WRITE4resok { count4 count; stable_how4 committed; verifier4 writeverf; }; typedef struct WRITE4resok WRITE4resok; struct WRITE4res { nfsstat4 status; union { WRITE4resok resok4; } WRITE4res_u; }; typedef struct WRITE4res WRITE4res; struct RELEASE_LOCKOWNER4args { lock_owner4 lock_owner; }; typedef struct RELEASE_LOCKOWNER4args RELEASE_LOCKOWNER4args; struct RELEASE_LOCKOWNER4res { nfsstat4 status; }; typedef struct RELEASE_LOCKOWNER4res RELEASE_LOCKOWNER4res; struct ILLEGAL4res { nfsstat4 status; }; typedef struct ILLEGAL4res ILLEGAL4res; enum nfs_opnum4 { NFS4_OP_ACCESS = 3, NFS4_OP_CLOSE = 4, NFS4_OP_COMMIT = 5, NFS4_OP_CREATE = 6, NFS4_OP_DELEGPURGE = 7, NFS4_OP_DELEGRETURN = 8, NFS4_OP_GETATTR = 9, NFS4_OP_GETFH = 10, NFS4_OP_LINK = 11, NFS4_OP_LOCK = 12, NFS4_OP_LOCKT = 13, NFS4_OP_LOCKU = 14, NFS4_OP_LOOKUP = 15, NFS4_OP_LOOKUPP = 16, NFS4_OP_NVERIFY = 17, NFS4_OP_OPEN = 18, NFS4_OP_OPENATTR = 19, NFS4_OP_OPEN_CONFIRM = 20, NFS4_OP_OPEN_DOWNGRADE = 21, NFS4_OP_PUTFH = 22, NFS4_OP_PUTPUBFH = 23, NFS4_OP_PUTROOTFH = 24, NFS4_OP_READ = 25, NFS4_OP_READDIR = 26, NFS4_OP_READLINK = 27, NFS4_OP_REMOVE = 28, NFS4_OP_RENAME = 29, NFS4_OP_RENEW = 30, NFS4_OP_RESTOREFH = 31, NFS4_OP_SAVEFH = 32, NFS4_OP_SECINFO = 33, NFS4_OP_SETATTR = 34, NFS4_OP_SETCLIENTID = 35, NFS4_OP_SETCLIENTID_CONFIRM = 36, NFS4_OP_VERIFY = 37, NFS4_OP_WRITE = 38, NFS4_OP_RELEASE_LOCKOWNER = 39, NFS4_OP_ILLEGAL = 10044 }; typedef enum nfs_opnum4 nfs_opnum4; struct nfs_argop4 { nfs_opnum4 argop; union { ACCESS4args opaccess; CLOSE4args opclose; COMMIT4args opcommit; CREATE4args opcreate; DELEGPURGE4args opdelegpurge; DELEGRETURN4args opdelegreturn; GETATTR4args opgetattr; LINK4args oplink; LOCK4args oplock; LOCKT4args oplockt; LOCKU4args oplocku; LOOKUP4args oplookup; NVERIFY4args opnverify; OPEN4args opopen; OPENATTR4args opopenattr; OPEN_CONFIRM4args opopen_confirm; OPEN_DOWNGRADE4args opopen_downgrade; PUTFH4args opputfh; READ4args opread; READDIR4args opreaddir; REMOVE4args opremove; RENAME4args oprename; RENEW4args oprenew; SECINFO4args opsecinfo; SETATTR4args opsetattr; SETCLIENTID4args opsetclientid; SETCLIENTID_CONFIRM4args opsetclientid_confirm; VERIFY4args opverify; WRITE4args opwrite; RELEASE_LOCKOWNER4args oprelease_lockowner; char padding[1024]; /** @todo: BUGAZOMEU: why do we need this ?? */ } nfs_argop4_u; }; typedef struct nfs_argop4 nfs_argop4; struct nfs_resop4 { nfs_opnum4 resop; union { ACCESS4res opaccess; CLOSE4res opclose; COMMIT4res opcommit; CREATE4res opcreate; DELEGPURGE4res opdelegpurge; DELEGRETURN4res opdelegreturn; GETATTR4res opgetattr; GETFH4res opgetfh; LINK4res oplink; LOCK4res oplock; LOCKT4res oplockt; LOCKU4res oplocku; LOOKUP4res oplookup; LOOKUPP4res oplookupp; NVERIFY4res opnverify; OPEN4res opopen; OPENATTR4res opopenattr; OPEN_CONFIRM4res opopen_confirm; OPEN_DOWNGRADE4res opopen_downgrade; PUTFH4res opputfh; PUTPUBFH4res opputpubfh; PUTROOTFH4res opputrootfh; READ4res opread; READDIR4res opreaddir; READLINK4res opreadlink; REMOVE4res opremove; RENAME4res oprename; RENEW4res oprenew; RESTOREFH4res oprestorefh; SAVEFH4res opsavefh; SETATTR4res opsetattr; SETCLIENTID4res opsetclientid; SETCLIENTID_CONFIRM4res opsetclientid_confirm; VERIFY4res opverify; WRITE4res opwrite; RELEASE_LOCKOWNER4res oprelease_lockowner; ILLEGAL4res opillegal; } nfs_resop4_u; }; typedef struct nfs_resop4 nfs_resop4; struct COMPOUND4args { utf8str_cs tag; uint32_t minorversion; struct { u_int argarray_len; nfs_argop4 *argarray_val; } argarray; }; typedef struct COMPOUND4args COMPOUND4args; struct COMPOUND4res { nfsstat4 status; utf8str_cs tag; struct { u_int resarray_len; nfs_resop4 *resarray_val; } resarray; }; typedef struct COMPOUND4res COMPOUND4res; struct CB_GETATTR4args { nfs_fh4 fh; bitmap4 attr_request; }; typedef struct CB_GETATTR4args CB_GETATTR4args; struct CB_GETATTR4resok { fattr4 obj_attributes; }; typedef struct CB_GETATTR4resok CB_GETATTR4resok; struct CB_GETATTR4res { nfsstat4 status; union { CB_GETATTR4resok resok4; } CB_GETATTR4res_u; }; typedef struct CB_GETATTR4res CB_GETATTR4res; struct CB_RECALL4args { stateid4 stateid; bool_t truncate; nfs_fh4 fh; }; typedef struct CB_RECALL4args CB_RECALL4args; struct CB_RECALL4res { nfsstat4 status; }; typedef struct CB_RECALL4res CB_RECALL4res; struct CB_ILLEGAL4res { nfsstat4 status; }; typedef struct CB_ILLEGAL4res CB_ILLEGAL4res; enum nfs_cb_opnum4 { NFS4_OP_CB_GETATTR = 3, NFS4_OP_CB_RECALL = 4, NFS4_OP_CB_ILLEGAL = 10044 }; typedef enum nfs_cb_opnum4 nfs_cb_opnum4; struct nfs_cb_argop4 { u_int argop; union { CB_GETATTR4args opcbgetattr; CB_RECALL4args opcbrecall; } nfs_cb_argop4_u; }; typedef struct nfs_cb_argop4 nfs_cb_argop4; struct nfs_cb_resop4 { u_int resop; union { CB_GETATTR4res opcbgetattr; CB_RECALL4res opcbrecall; CB_ILLEGAL4res opcbillegal; } nfs_cb_resop4_u; }; typedef struct nfs_cb_resop4 nfs_cb_resop4; struct CB_COMPOUND4args { utf8str_cs tag; uint32_t minorversion; uint32_t callback_ident; struct { u_int argarray_len; nfs_cb_argop4 *argarray_val; } argarray; }; typedef struct CB_COMPOUND4args CB_COMPOUND4args; struct CB_COMPOUND4res { nfsstat4 status; utf8str_cs tag; struct { u_int resarray_len; nfs_cb_resop4 *resarray_val; } resarray; }; typedef struct CB_COMPOUND4res CB_COMPOUND4res; #define NFS4_PROGRAM 100003 #define NFS_V4 4 #define NFSPROC4_NULL 0 #define NFSPROC4_COMPOUND 1 #define NFS4_CALLBACK 0x40000000 #define NFS_CB 1 #define CB_NULL 0 #define CB_COMPOUND 1 #ifndef _USE_SWIG /* the xdr functions */ extern bool_t xdr_nfs_ftype4(); extern bool_t xdr_nfsstat4(); extern bool_t xdr_bitmap4(); extern bool_t xdr_offset4(); extern bool_t xdr_count4(); extern bool_t xdr_length4(); extern bool_t xdr_clientid4(); extern bool_t xdr_seqid4(); extern bool_t xdr_utf8string(); extern bool_t xdr_utf8str_cis(); extern bool_t xdr_utf8str_cs(); extern bool_t xdr_utf8str_mixed(); extern bool_t xdr_component4(); extern bool_t xdr_pathname4(); extern bool_t xdr_nfs_lockid4(); extern bool_t xdr_nfs_cookie4(); extern bool_t xdr_linktext4(); extern bool_t xdr_sec_oid4(); extern bool_t xdr_qop4(); extern bool_t xdr_mode4(); extern bool_t xdr_changeid4(); extern bool_t xdr_verifier4(); extern bool_t xdr_nfstime4(); extern bool_t xdr_time_how4(); extern bool_t xdr_settime4(); extern bool_t xdr_nfs_fh4(); extern bool_t xdr_fsid4(); extern bool_t xdr_fs_location4(); extern bool_t xdr_fs_locations4(); extern bool_t xdr_acetype4(); extern bool_t xdr_aceflag4(); extern bool_t xdr_acemask4(); extern bool_t xdr_nfsace4(); extern bool_t xdr_specdata4(); extern bool_t xdr_fattr4_supported_attrs(); extern bool_t xdr_fattr4_type(); extern bool_t xdr_fattr4_fh_expire_type(); extern bool_t xdr_fattr4_change(); extern bool_t xdr_fattr4_size(); extern bool_t xdr_fattr4_link_support(); extern bool_t xdr_fattr4_symlink_support(); extern bool_t xdr_fattr4_named_attr(); extern bool_t xdr_fattr4_fsid(); extern bool_t xdr_fattr4_unique_handles(); extern bool_t xdr_fattr4_lease_time(); extern bool_t xdr_fattr4_rdattr_error(); extern bool_t xdr_fattr4_acl(); extern bool_t xdr_fattr4_aclsupport(); extern bool_t xdr_fattr4_archive(); extern bool_t xdr_fattr4_cansettime(); extern bool_t xdr_fattr4_case_insensitive(); extern bool_t xdr_fattr4_case_preserving(); extern bool_t xdr_fattr4_chown_restricted(); extern bool_t xdr_fattr4_fileid(); extern bool_t xdr_fattr4_files_avail(); extern bool_t xdr_fattr4_filehandle(); extern bool_t xdr_fattr4_files_free(); extern bool_t xdr_fattr4_files_total(); extern bool_t xdr_fattr4_fs_locations(); extern bool_t xdr_fattr4_hidden(); extern bool_t xdr_fattr4_homogeneous(); extern bool_t xdr_fattr4_maxfilesize(); extern bool_t xdr_fattr4_maxlink(); extern bool_t xdr_fattr4_maxname(); extern bool_t xdr_fattr4_maxread(); extern bool_t xdr_fattr4_maxwrite(); extern bool_t xdr_fattr4_mimetype(); extern bool_t xdr_fattr4_mode(); extern bool_t xdr_fattr4_mounted_on_fileid(); extern bool_t xdr_fattr4_no_trunc(); extern bool_t xdr_fattr4_numlinks(); extern bool_t xdr_fattr4_owner(); extern bool_t xdr_fattr4_owner_group(); extern bool_t xdr_fattr4_quota_avail_hard(); extern bool_t xdr_fattr4_quota_avail_soft(); extern bool_t xdr_fattr4_quota_used(); extern bool_t xdr_fattr4_rawdev(); extern bool_t xdr_fattr4_space_avail(); extern bool_t xdr_fattr4_space_free(); extern bool_t xdr_fattr4_space_total(); extern bool_t xdr_fattr4_space_used(); extern bool_t xdr_fattr4_system(); extern bool_t xdr_fattr4_time_access(); extern bool_t xdr_fattr4_time_access_set(); extern bool_t xdr_fattr4_time_backup(); extern bool_t xdr_fattr4_time_create(); extern bool_t xdr_fattr4_time_delta(); extern bool_t xdr_fattr4_time_metadata(); extern bool_t xdr_fattr4_time_modify(); extern bool_t xdr_fattr4_time_modify_set(); extern bool_t xdr_attrlist4(); extern bool_t xdr_fattr4(); extern bool_t xdr_change_info4(); extern bool_t xdr_clientaddr4(); extern bool_t xdr_cb_client4(); extern bool_t xdr_stateid4(); extern bool_t xdr_nfs_client_id4(); extern bool_t xdr_open_owner4(); extern bool_t xdr_lock_owner4(); extern bool_t xdr_nfs_lock_type4(); extern bool_t xdr_ACCESS4args(); extern bool_t xdr_ACCESS4resok(); extern bool_t xdr_ACCESS4res(); extern bool_t xdr_CLOSE4args(); extern bool_t xdr_CLOSE4res(); extern bool_t xdr_COMMIT4args(); extern bool_t xdr_COMMIT4resok(); extern bool_t xdr_COMMIT4res(); extern bool_t xdr_createtype4(); extern bool_t xdr_CREATE4args(); extern bool_t xdr_CREATE4resok(); extern bool_t xdr_CREATE4res(); extern bool_t xdr_DELEGPURGE4args(); extern bool_t xdr_DELEGPURGE4res(); extern bool_t xdr_DELEGRETURN4args(); extern bool_t xdr_DELEGRETURN4res(); extern bool_t xdr_GETATTR4args(); extern bool_t xdr_GETATTR4resok(); extern bool_t xdr_GETATTR4res(); extern bool_t xdr_GETFH4resok(); extern bool_t xdr_GETFH4res(); extern bool_t xdr_LINK4args(); extern bool_t xdr_LINK4resok(); extern bool_t xdr_LINK4res(); extern bool_t xdr_open_to_lock_owner4(); extern bool_t xdr_exist_lock_owner4(); extern bool_t xdr_locker4(); extern bool_t xdr_LOCK4args(); extern bool_t xdr_LOCK4denied(); extern bool_t xdr_LOCK4resok(); extern bool_t xdr_LOCK4res(); extern bool_t xdr_LOCKT4args(); extern bool_t xdr_LOCKT4res(); extern bool_t xdr_LOCKU4args(); extern bool_t xdr_LOCKU4res(); extern bool_t xdr_LOOKUP4args(); extern bool_t xdr_LOOKUP4res(); extern bool_t xdr_LOOKUPP4res(); extern bool_t xdr_NVERIFY4args(); extern bool_t xdr_NVERIFY4res(); extern bool_t xdr_createmode4(); extern bool_t xdr_createhow4(); extern bool_t xdr_opentype4(); extern bool_t xdr_openflag4(); extern bool_t xdr_limit_by4(); extern bool_t xdr_nfs_modified_limit4(); extern bool_t xdr_nfs_space_limit4(); extern bool_t xdr_open_delegation_type4(); extern bool_t xdr_open_claim_type4(); extern bool_t xdr_open_claim_delegate_cur4(); extern bool_t xdr_open_claim4(); extern bool_t xdr_OPEN4args(); extern bool_t xdr_open_read_delegation4(); extern bool_t xdr_open_write_delegation4(); extern bool_t xdr_open_delegation4(); extern bool_t xdr_OPEN4resok(); extern bool_t xdr_OPEN4res(); extern bool_t xdr_OPENATTR4args(); extern bool_t xdr_OPENATTR4res(); extern bool_t xdr_OPEN_CONFIRM4args(); extern bool_t xdr_OPEN_CONFIRM4resok(); extern bool_t xdr_OPEN_CONFIRM4res(); extern bool_t xdr_OPEN_DOWNGRADE4args(); extern bool_t xdr_OPEN_DOWNGRADE4resok(); extern bool_t xdr_OPEN_DOWNGRADE4res(); extern bool_t xdr_PUTFH4args(); extern bool_t xdr_PUTFH4res(); extern bool_t xdr_PUTPUBFH4res(); extern bool_t xdr_PUTROOTFH4res(); extern bool_t xdr_READ4args(); extern bool_t xdr_READ4resok(); extern bool_t xdr_READ4res(); extern bool_t xdr_READDIR4args(); extern bool_t xdr_entry4(); extern bool_t xdr_dirlist4(); extern bool_t xdr_READDIR4resok(); extern bool_t xdr_READDIR4res(); extern bool_t xdr_READLINK4resok(); extern bool_t xdr_READLINK4res(); extern bool_t xdr_REMOVE4args(); extern bool_t xdr_REMOVE4resok(); extern bool_t xdr_REMOVE4res(); extern bool_t xdr_RENAME4args(); extern bool_t xdr_RENAME4resok(); extern bool_t xdr_RENAME4res(); extern bool_t xdr_RENEW4args(); extern bool_t xdr_RENEW4res(); extern bool_t xdr_RESTOREFH4res(); extern bool_t xdr_SAVEFH4res(); extern bool_t xdr_SECINFO4args(); extern bool_t xdr_rpc_gss_svc_t(); extern bool_t xdr_rpcsec_gss_info(); extern bool_t xdr_secinfo4(); extern bool_t xdr_SECINFO4resok(); extern bool_t xdr_SECINFO4res(); extern bool_t xdr_SETATTR4args(); extern bool_t xdr_SETATTR4res(); extern bool_t xdr_SETCLIENTID4args(); extern bool_t xdr_SETCLIENTID4resok(); extern bool_t xdr_SETCLIENTID4res(); extern bool_t xdr_SETCLIENTID_CONFIRM4args(); extern bool_t xdr_SETCLIENTID_CONFIRM4res(); extern bool_t xdr_VERIFY4args(); extern bool_t xdr_VERIFY4res(); extern bool_t xdr_stable_how4(); extern bool_t xdr_WRITE4args(); extern bool_t xdr_WRITE4resok(); extern bool_t xdr_WRITE4res(); extern bool_t xdr_RELEASE_LOCKOWNER4args(); extern bool_t xdr_RELEASE_LOCKOWNER4res(); extern bool_t xdr_ILLEGAL4res(); extern bool_t xdr_nfs_opnum4(); extern bool_t xdr_nfs_argop4(); extern bool_t xdr_nfs_resop4(); extern bool_t xdr_COMPOUND4args(); extern bool_t xdr_COMPOUND4res(); extern bool_t xdr_CB_GETATTR4args(); extern bool_t xdr_CB_GETATTR4resok(); extern bool_t xdr_CB_GETATTR4res(); extern bool_t xdr_CB_RECALL4args(); extern bool_t xdr_CB_RECALL4res(); extern bool_t xdr_CB_ILLEGAL4res(); extern bool_t xdr_nfs_cb_opnum4(); extern bool_t xdr_nfs_cb_argop4(); extern bool_t xdr_nfs_cb_resop4(); extern bool_t xdr_CB_COMPOUND4args(); extern bool_t xdr_CB_COMPOUND4res(); #endif /* SWIG */ enum rpc_gss_svc_t { RPC_GSS_SVC_NONE = 1, RPC_GSS_SVC_INTEGRITY = 2, RPC_GSS_SVC_PRIVACY = 3, }; typedef enum rpc_gss_svc_t rpc_gss_svc_t; struct rpcsec_gss_info { sec_oid4 oid; qop4 qop; rpc_gss_svc_t service; }; typedef struct rpcsec_gss_info rpcsec_gss_info; struct secinfo4 { uint32_t flavor; union { rpcsec_gss_info flavor_info; } secinfo4_u; }; typedef struct secinfo4 secinfo4; typedef struct { u_int SECINFO4resok_len; secinfo4 *SECINFO4resok_val; } SECINFO4resok; struct SECINFO4res { nfsstat4 status; union { SECINFO4resok resok4; } SECINFO4res_u; }; typedef struct SECINFO4res SECINFO4res; #endif /* !_NFS4_H_RPCGEN */ ntirpc-1.3.1/version-h.in.cmake000066400000000000000000000007551261345040100163370ustar00rootroot00000000000000/* version.h file expanded by Cmake for build */ #ifndef VERSION_H #define VERSION_H #define NTIRPC_VERSION_MAJOR @NTIRPC_MAJOR_VERSION@ #define NTIRPC_VERSION_MINOR @NTIRPC_MINOR_VERSION@ #define NTIRPC_PATCH_LEVEL @NTIRPC_PATCH_LEVEL@ #define NTIRPC_VERSION "@NTIRPC_MAJOR_VERSION@.@NTIRPC_MINOR_VERSION@.@NTIRPC_PATCH_LEVEL@" #define NTIRPC_VERSION_COMMENT "@VERSION_COMMENT@" #define _GIT_HEAD_COMMIT "@_GIT_HEAD_COMMIT@" #define _GIT_DESCRIBE "@_GIT_DESCRIBE@" #endif /* VERSION_H */