[-]
[+]
|
Changed |
_service:tar_git:rpcbind.spec
|
|
[-]
[+]
|
Changed |
_service
^
|
@@ -2,7 +2,7 @@
<service name="tar_git">
<param name="url">https://github.com/sailfishos-chum/rpcbind</param>
<param name="branch"></param>
- <param name="revision"></param>
+ <param name="revision">1.2.6</param>
<param name="token"/>
<param name="debian">N</param>
<param name="dumb">N</param>
|
|
Deleted |
_service:tar_git:rpcbind-1.2.6+master.20220120131204.51beab6.tar.bz2/rpcbind-1.2.6.tar.bz2
^
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/.gitmodules
^
|
@@ -0,0 +1,3 @@
+[submodule "upstream"]
+ path = upstream
+ url = git://git.linux-nfs.org/projects/steved/rpcbind.git
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream
^
|
+(directory)
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/.gitignore
^
|
@@ -0,0 +1,30 @@
+INSTALL
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache/
+compile
+config.guess
+config.h
+config.h.in
+config.log
+config.status
+config.sub
+configure
+depcomp
+install-sh
+libtool
+ltmain.sh
+missing
+src/config.h
+src/stamp-h2
+stamp-h1
+# file generated during compilation
+.deps
+.dirstamp
+*.o
+rpcbind
+rpcinfo
+# cscope database files
+cscope.*
+systemd/rpcbind.service
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/AUTHORS
^
|
@@ -0,0 +1,2 @@
+Gilles Quillard <gilles.quillard@bull.net>
+Vincent ROQUETA <vincent.roqueta@ext.bull.net>
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/COPYING
^
|
@@ -0,0 +1,24 @@
+/*
+ * 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.
+ */
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/ChangeLog
^
|
@@ -0,0 +1,247 @@
+2008-11-19 Steve Dickson <steved@redhat.com>
+ * Version 0.1.7 released.
+
+commit bdc14d4d867a26010466138ecb37336b1f489dcb
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date: Tue Oct 28 10:15:22 2008 -0400
+
+ rpcbind: Squelch make warnings
+
+ Change order of AC_PROG_LIBTOOL macro invocation in configure.in to
+ eliminate autotool warning:
+
+ Remember to add `AC_PROG_LIBTOOL' to `configure.in'.
+
+ Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 3d33ad8d37ea2f955a8b06beedade424bc22efbc
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date: Tue Oct 28 10:12:20 2008 -0400
+
+ rpcbind: Squelch make warnings
+
+ Eliminate make warnings when building rpcbind and rpcinfo:
+
+ make[3]: Circular security.o <- security.o dependency dropped.
+ make[3]: Circular util.o <- security.o dependency dropped.
+ make[3]: Circular util.o <- util.o dependency dropped.
+ make[3]: Circular util.o <- check_bound.o dependency dropped.
+ make[3]: Circular pmap_svc.o <- security.o dependency dropped.
+ make[3]: Circular pmap_svc.o <- util.o dependency dropped.
+ make[3]: Circular pmap_svc.o <- check_bound.o dependency dropped.
+ make[3]: Circular pmap_svc.o <- pmap_svc.o dependency dropped.
+
+ and so on.
+
+ Apparently src/Makefile.am needs either a list of source files or a
+ list of object files, but not both.
+
+ Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 1ee34cfa8cf3ce56f43690eba44215aafb1835a5
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date: Tue Oct 28 10:10:23 2008 -0400
+
+ rpcbind: Squelch a compiler warning
+
+ Remove a needless pointer-to-integer conversion. getnameinfo(3) wants
+ a size value greater than or equal to offsetof(struct sockaddr_un,
+ sun_path). Since pointers can be different sizes depending on the
+ hardware platform, let's make this a simple constant instead.
+
+ This eliminates the compiler warning:
+
+ rpcinfo.c: In function sa_len
+ rpcinfo.c:666: warning: cast from pointer to integer of different size
+
+ when building on x86-64.
+
+ Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 98ca016d5a2fb7a7da9e2332e3c59b123b820477
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date: Tue Oct 28 10:07:58 2008 -0400
+
+ rpcbind: Squelch a compiler warning
+
+ Include <nss.h> to get a forward declaration of __nss_configure_lookup().
+ This eliminates the compiler warning:
+
+ rpcbind.c: In function main
+ rpcbind.c:163: warning: implicit declaration of function
+ _nss_configure_lookup
+
+ Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 9266c745930cd052713e83c7ecb0917c17f33505
+Author: Chuck Lever <chuck.lever@oracle.com>
+Date: Tue Oct 28 10:02:42 2008 -0400
+
+ rpcbind: Squelch a compiler warning
+
+ Remove unused variable in read_struct(). This eliminates
+ the compiler warning:
+
+ warmstart.c: In function read_struct
+ warmstart.c:106: warning: unused variable sbuf
+
+ Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 0b847172bb5413d200da01618402897d493f40b1
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 30 14:49:21 2008 -0400
+
+ Properly identify local root user over ipv4/v6
+
+ When an application registers a service through an inet transport,
+ rpcbind will always treat the owner as "unknown". This allows random
+ users to unregister such services, and replace them with their own -
+ man-in-the-middle attacks for services like ypserv are trivial.
+
+ This patch changes pmapproc_change to check whether the call originated
+ from a priviliged local port, and if that is the case, it identifies the
+ caller as "superuser".
+
+ This mimics the way the current Linux portmap behaves.
+
+ Signed-off-by: Olaf Kirch <okir@suse.de>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 49e8a7c963c27ca3face271200b103a5efc50b05
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 30 14:44:05 2008 -0400
+
+ Fix debug output in is_loopback
+
+ The security check in is_loopback wants to print the source
+ port number, assuming that the remote address is always a
+ sockaddr_in - which is silly. Move the printf into the
+ address family specific switch statement.
+
+ Signed-off-by: Olaf Kirch <okir@suse.de>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 62a20676c31a1887f8151a5b0ca42932205c4f4b
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 30 14:43:13 2008 -0400
+
+ Fix debug output in pmap_set/unset
+
+ The debugging code in pmapproc_change prints the contents of
+ the "struct pmap" argument before decoding it, which results
+ in random garbage being displayed.
+
+ Signed-off-by: Olaf Kirch <okir@suse.de>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 3d9f63a9c308b305dfca745dafae63d8f96b313c
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 30 14:41:35 2008 -0400
+
+ Fix for warm start
+
+ If you use rpcbind with the warm start functionality, it will load *all*
+ registrations from the warm start files, including those for rpcbind
+ and portmap. This is wrong, as that information may be stale - a user
+ may specifically edit the netconfig file and restart rpcbind to change
+ the transports it supports. In this case we want the registrations
+ to match the status quo, rather than the status before the restart.
+
+ This patch changes read_warmstart() to merge the existing rpcb/pmap
+ lists, which contain only the rpcbind/portmap entries, with the saved
+ start lists, but ignoring any rpcbind/portmap entries present in the
+ warm start files.
+
+ Signed-off-by: Olaf Kirch <okir@suse.de>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 1d92cd58eb471765eba08ec819f7b5ae1d5e96ab
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 30 12:01:24 2008 -0400
+
+ Support portmap on AF_LOCAL, too
+
+ This patch makes sure we support portmap (aka rpcbind v2) on ipv4 _and_
+ af_local. That allows rpcbind to identify the owner of a socket much
+ better than by relying on privileged ports to tell root from non-root
+ users.
+
+ Signed-off-by: Olaf Kirch <okir@suse.de>
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 566f261ff6bae2842e2e64aaf70d2e31acc1efe7
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 16 10:23:48 2008 -0400
+
+ Simplify port live check in pmap_svc.c
+
+ There's some hack in pmap_getport that will cause a service
+ to be unregistered from the portmap list if we find the port
+ is no longer in use. Apart from being a gross hack, it is
+ also a rather inefficient hack. Since we now restrict pmap
+ emulation to IPv4, we know the address is always 0.0.0.0,
+ so no need to mess with uaddr strings.
+
+ (The bind_check code is a huge messy no-op anyway, since
+ all ports are added with bind_check = FALSE).
+
+ Signed-off-by: okir@suse.de
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 1a94b830a6b5a248faa6fa0e4b7818d9394f6369
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 16 10:15:39 2008 -0400
+
+ Change how we decide on the netids to use for portmap
+
+ The current code will try to use either udp or udp6, and either tcp or
+ tcp6 for its portmap emulation code. Enabling eg both tcp6 and tcp in
+ the netconfig file will cause error messages, and cause rpcbind to not
+ register itself on the second transport (tcp).
+
+ This is not what we want.
+
+ I believe portmap emulation should only be enabled over IPv4.
+ There's no point in enabling it over IPv6.
+
+ Signed-off-by: okir@suse.de
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 3e4c74ab527375f37b6633f528e7eab0c363967b
+Author: Olaf Kirch <okir@suse.de>
+Date: Tue Sep 16 10:08:35 2008 -0400
+
+ Introduce helpers for ipprot/netid mapping
+
+ There's a couple of places in the portmap emulation code
+ where we translate between ip protocol numbers and netids.
+ Encapsulate these in two helper functions:
+
+ extern char *pmap_ipprot2netid(int);
+ extern int pmap_netid2ipprot(const char *);
+
+ Signed-off-by: okir@suse.de
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+commit 3942a3b4dcd451a2c41ad95a45f3f1462cb3f133
+Author: Steve Dickson <steved@redhat.com>
+Date: Tue Sep 16 10:01:18 2008 -0400
+
+ Removed files that are generated from the automake process
+
+ Signed-off-by: Steve Dickson <steved@redhat.com>
+
+2008-07-09 Steve Dickson <steved@redhat.com>
+ * See the git://git.infradead.org/~steved/rpcbind.git GIT tree
+ for the latest Changelog entries
+
+2004-10-13 Antoine Fraticelli <antoine.fraticelli@bull.net>
+
+ * Version 0.1 released.
+
+081104 Fixed bug (bad services call)
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/INSTALL
^
|
@@ -0,0 +1,365 @@
+Installation 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 `<wchar.h>' 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.
+
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/Makefile.am
^
|
@@ -0,0 +1,67 @@
+AUTOMAKE_OPTIONS = subdir-objects
+
+AM_CPPFLAGS = \
+ -DCHECK_LOCAL \
+ -DPORTMAP \
+ -DFACILITY=LOG_MAIL \
+ -DSEVERITY=LOG_INFO \
+ -DINET6 \
+ -DRPCBIND_STATEDIR="\"$(statedir)\"" \
+ -DRPCBIND_USER="\"$(rpcuser)\"" \
+ -DNSS_MODULES="\"$(nss_modules)\"" \
+ -D_GNU_SOURCE \
+ $(TIRPC_CFLAGS)
+
+if DEBUG
+AM_CPPFLAGS += -DRPCBIND_DEBUG -DDEBUG_RMTCALL
+AM_CPPFLAGS += -DND_DEBUG -DBIND_DEBUG
+endif
+
+if LIBSETDEBUG
+AM_CPPFLAGS += -DLIB_SET_DEBUG
+endif
+
+if WARMSTART
+AM_CPPFLAGS += -DWARMSTART
+endif
+
+if LIBWRAP
+AM_CPPFLAGS += -DLIBWRAP
+endif
+
+if RMTCALLS
+AM_CPPFLAGS += -DRMTCALLS
+endif
+
+bin_PROGRAMS = rpcinfo
+sbin_PROGRAMS = rpcbind
+
+rpcbind_SOURCES = \
+ src/check_bound.c \
+ src/pmap_svc.c \
+ src/rpcb_stat.c \
+ src/rpcb_svc.c \
+ src/rpcb_svc_4.c \
+ src/rpcb_svc_com.c \
+ src/rpcbind.c \
+ src/rpcbind.h \
+ src/security.c \
+ src/util.c \
+ src/warmstart.c \
+ src/xlog.c
+rpcbind_LDADD = $(TIRPC_LIBS)
+
+if SYSTEMD
+AM_CPPFLAGS += $(SYSTEMD_CFLAGS) -DSYSTEMD
+
+rpcbind_LDADD += $(SYSTEMD_LIBS)
+
+systemdsystemunit_DATA = \
+ systemd/rpcbind.service \
+ systemd/rpcbind.socket
+endif
+
+rpcinfo_SOURCES = src/rpcinfo.c
+rpcinfo_LDADD = $(TIRPC_LIBS)
+
+dist_man8_MANS = man/rpcbind.8 man/rpcinfo.8
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/NEWS
^
|
@@ -0,0 +1,4 @@
+New in 0.1:
+* Portage from FreeBSD 5.2.1
+* Use autoconf/automake
+
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/README
^
|
@@ -0,0 +1,5 @@
+This release was a native source release from Sun.
+It has been ported from FreeBSD 5.2.1 to GNU/Linux in 2004.
+
+Please send bug reports to: libtirpc-devel@lists.sourceforge.net
+or linux-nfs@vger.kernel.org
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/autogen.sh
^
|
@@ -0,0 +1,42 @@
+#!/bin/sh -e
+
+echo -n cleaning up .
+
+# Clean up the generated crud
+(
+ for FILE in compile config.guess config.sub depcomp install-sh ltmain.sh missing mkinstalldirs; do
+ if test -f $FILE; then
+ rm -f $FILE
+ fi
+ echo -n .
+ done
+)
+
+for FILE in aclocal.m4 configure config.h.in; do
+ if test -f $FILE; then
+ rm -f $FILE
+ fi
+ echo -n .
+done
+
+for DIR in autom4te.cache; do
+ if test -d $DIR; then
+ rm -rf $DIR
+ fi
+ echo -n .
+done
+
+find . -type f -name 'Makefile.in' -print0 | xargs -r0 rm -f --
+find . -type f -name 'Makefile' -print0 | xargs -r0 rm -f --
+
+echo ' done'
+
+if test x"${1}" = x"clean"; then
+ exit
+fi
+
+aclocal
+#libtoolize --force --copy
+#autoheader
+automake --add-missing --copy --gnu # -Wall
+autoconf # -Wall
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/configure.ac
^
|
@@ -0,0 +1,73 @@
+AC_INIT(rpcbind, 1.2.6)
+
+AM_INIT_AUTOMAKE
+AC_CONFIG_SRCDIR([src/rpcbind.c])
+AC_PREFIX_DEFAULT(/usr)
+AC_PROG_CC
+
+AC_ARG_ENABLE([libwrap],
+ AS_HELP_STRING([--enable-libwrap], [Enables host name checking through tcpd @<:@default=no@:>@]))
+AM_CONDITIONAL(LIBWRAP, test x$enable_libwrap = xyes)
+
+AC_ARG_ENABLE([debug],
+ AS_HELP_STRING([--enable-debug], [Turns on rpcbind debugging @<:@default=no@:>@]))
+AM_CONDITIONAL(DEBUG, test x$enable_debug = xyes)
+if test x"$enable_debug" = xyes; then
+ AC_CHECK_LIB([tirpc], [libtirpc_set_debug], [lib_setdebug=yes])
+fi
+AM_CONDITIONAL(LIBSETDEBUG, test x$lib_setdebug = xyes)
+
+AC_ARG_ENABLE([warmstarts],
+ AS_HELP_STRING([--enable-warmstarts], [Enables Warm Starts @<:@default=no@:>@]))
+AM_CONDITIONAL(WARMSTART, test x$enable_warmstarts = xyes)
+
+AC_ARG_ENABLE([rmtcalls],
+ AS_HELP_STRING([--enable-rmtcalls], [Enables Remote Calls @<:@default=no@:>@]))
+AM_CONDITIONAL(RMTCALLS, test x$enable_rmtcalls = xyes)
+
+AC_ARG_WITH([statedir],
+ AS_HELP_STRING([--with-statedir=ARG], [use ARG as state dir @<:@default=/var/run/rpcbind@:>@])
+ ,, [with_statedir=/var/run/rpcbind])
+AC_SUBST([statedir], [$with_statedir])
+
+AC_ARG_WITH([rpcuser],
+ AS_HELP_STRING([--with-rpcuser=ARG], [use ARG for RPC @<:@default=root@:>@])
+ ,, [with_rpcuser=root])
+AC_SUBST([rpcuser], [$with_rpcuser])
+
+AC_ARG_WITH([nss_modules],
+ AS_HELP_STRING([--with-nss-modules=NSS_MODULES]
+ , [Sets the nss module search list to the given space-delimited string.
+ For example --with-nss-modules="files altfiles" @<:@default=files@:>@])
+ ,, [with_nss_modules=files])
+AC_SUBST([nss_modules], [$with_nss_modules])
+
+PKG_CHECK_MODULES([TIRPC], [libtirpc])
+
+PKG_PROG_PKG_CONFIG
+AC_ARG_WITH([systemdsystemunitdir],
+ AS_HELP_STRING([--with-systemdsystemunitdir=DIR], [Directory for systemd service files]),
+ [], [with_systemdsystemunitdir=$($PKG_CONFIG --variable=systemdsystemunitdir systemd)])
+ if test "x$with_systemdsystemunitdir" != xno; then
+ AC_SUBST([systemdsystemunitdir], [$with_systemdsystemunitdir])
+ PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [],
+ [PKG_CHECK_MODULES([SYSTEMD], [libsystemd-daemon], [],
+ AC_MSG_ERROR([libsystemd support requested but found]))])
+ fi
+AM_CONDITIONAL(SYSTEMD, [test -n "$with_systemdsystemunitdir" -a "x$with_systemdsystemunitdir" != xno ])
+
+AS_IF([test x$enable_libwrap = xyes], [
+ AC_CHECK_LIB([wrap], [hosts_access], ,
+ AC_MSG_ERROR([libwrap support requested but unable to find libwrap]))
+])
+
+AC_SEARCH_LIBS([pthread_create], [pthread])
+
+AC_CHECK_HEADERS([nss.h])
+
+# make sbindir available for substitution in config file
+# 2 "evals" needed to expand variable names
+AC_SUBST([_sbindir])
+AC_CONFIG_COMMANDS_PRE([eval eval _sbindir=$sbindir])
+
+AC_OUTPUT([Makefile systemd/rpcbind.service])
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/man/rpcbind-fr.8
^
|
@@ -0,0 +1,145 @@
+.\" @(#)rpcbind.1m 1.19 92/09/14 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" Copyright 1991 Sun Microsystems, Inc.
+.\" $FreeBSD: src/usr.sbin/rpcbind/rpcbind.8,v 1.5 2002/11/27 15:33:47 ru Exp $
+.\" Linux:
+
+.TH "RPCBIND" "8" "13 aout 2004" "rpcbind" ""
+
+
+.Dd September 14, 1992
+.Dt RPCBIND 8
+.Os
+.Sh NAME
+.Nm rpcbind
+.Nd correspondance entre les adresses universelles et les numéros de programme RPC
+.Sh SYNOPSIS
+.Nm
+.Op Fl adhils
+.Sh DESCRIPTION
+.Nm
+est un utilitaire qui convertit les numéros de programme
+.Tn RPC
+en adresses universelles
+Il doit etre executé sur l'hote pour pouvoir effectuer des
+appels de procedure à distance sur un serveur sur cette machine.
+.Nm
+doit être démarré avant que les serveurs RPC ne soient invoqués.
+.Pp
+Quand un service
+.Tn RPC
+est démarré,
+il indique à
+.Nm
+l'adresse à laquelle il écoute,
+et le numéro de programme
+.Tn RPC il est préparé à servir.
+Quand un client veux effectuer un appel
+.Tn RPC
+à un numéro de programme donné,
+il contacte d'abord
+.Nm
+sur la machine serveur pour déterminer
+l'adresse
+.Tn RPC
+à laquelle la requête doit être envoyée.
+.Pp
+.Nm
+doit être démarré avant tout autre service RPC
+Normalement, standard
+.Tn RPC
+servers are started by port monitors, so
+.Nm
+must be started before port monitors are invoked.
+.Pp
+Quand
+.Nm
+demarre, il vérifie que certains appels
+pour la translation nom->adres fonctionnent de manière correcte
+Si ceux-ci échouent, les bases de données de configuration reseau
+peuvent être corrompues
+Si les services
+.Tn RPC
+ne peuvent pas fonctionner correctement dans cette situation,
+.Nm
+rapporte la condition et se termine
+.Pp
+.Nm
+ne peut être lancé qu'en super-utilisateur
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl a
+En mode debug
+.Pq Fl d ,
+abandonne sur les erreurs.
+.It Fl d
+S'éxécute en mode debuggage. Empèche
+.Nm
+de s'éxécuter comme démon
+Dans ce mode,
+.Nm
+ne va pas forker au démarrage, va afficher des information additionnelles
+durant les différentes opérations, et va abandonner sur certaines erreurs
+si l'option
+.Fl a
+est aussi spécifiée.
+.It Fl h
+Specifie une adresse IP spécifique à lier pour les requetes UDP
+Specify specific IP addresses to bind to for UDP requests.
+Cette option peut être spécifiée plusieurs fois et est typiquement nécessaire dans
+le cas d'une éxécution sur un hôte à plusieurs interfaces réseau.
+Si aucune option
+.Fl h
+n'est spécifiée,
+.Nm
+va lier sur
+.Dv INADDR_ANY ,
+ce qui peut entrainer des problemes sur un hote a plusieurs interfaces réseau
+à cause du fait que
+which could lead to problems on a multi-homed host due to
+.Nm
+retourne un paquet UDP depuis une adresse IP différente de celle avec laquelle on lui avait envoyé la requête
+Notons que quand on spécifie une adresse IP avec l'option
+.Fl h ,
+.Nm
+va automatiquement ajouter à la liste l'adresse
+.Li 127.0.0.1
+et si IPv6 est activé, l'adresse
+.Li ::1
+.It Fl i
+Mode
+.Dq Insecure
+(non sécurisé)
+Autorise les appels à SET et UNSET depuis n'importe quel host
+Dans le cas normal,
+.Nm
+accepte ces requêtes seulement depuis l'interface loopback, et ce
+pour des raisons de sécurité
+Ce changement peut être rendu nécessaire pour les programmes qui auraient
+été compilé avec d'anciennes versions de la librairie rpc, et qui n'effectueraient pas
+ces requêtes en utilisant l'interface loopback
+.It Fl l
+Turn on libwrap connection logging.
+.It Fl s
+.Nm
+change le demon utilisateur le plus souvent possible
+Cela oblige
+.Nm
+à utiliser des ports non privilégiés pour les connexions sortantes, pour
+empêcher les clients non privilégié d'utiliser
+.Nm
+pour se connecter aux services depuis un port privilégié
+.El
+.Sh NOTES
+Tout les serveurs RPC doivent être redémarrés si
+.Nm
+est redémarré.
+.Sh SEE ALSO
+.Xr rpcbind 3 ,
+.Xr rpcinfo 8
+.Sh FILES
+.Bl -tag -width /var/run/rpcbind.sock -compact
+.It Pa /var/run/rpcbind.sock
+.Sh TRADUCTION
+Aurelien CHARBON (Sept 2003)
+.El
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/man/rpcbind.8
^
|
@@ -0,0 +1,161 @@
+.\" @(#)rpcbind.1m 1.19 92/09/14 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" Copyright 1991 Sun Microsystems, Inc.
+.\" $FreeBSD: src/usr.sbin/rpcbind/rpcbind.8,v 1.5 2002/11/27 15:33:47 ru Exp $
+
+.Dd September 14, 1992
+.Dt RPCBIND 8
+.Os
+.Sh NAME
+.Nm rpcbind
+.Nd universal addresses to RPC program number mapper
+.Sh SYNOPSIS
+.Nm
+.Op Fl adhiLls
+.Sh DESCRIPTION
+The
+.Nm
+utility is a server that converts
+.Tn RPC
+program numbers into
+universal addresses.
+It must be running on the host to be able to make
+.Tn RPC
+calls
+on a server on that machine.
+.Pp
+When an
+.Tn RPC
+service is started,
+it tells
+.Nm
+the address at which it is listening,
+and the
+.Tn RPC
+program numbers it is prepared to serve.
+When a client wishes to make an
+.Tn RPC
+call to a given program number,
+it first contacts
+.Nm
+on the server machine to determine
+the address where
+.Tn RPC
+requests should be sent.
+.Pp
+The
+.Nm
+utility should be started before any other RPC service.
+Normally, standard
+.Tn RPC
+servers are started by port monitors, so
+.Nm
+must be started before port monitors are invoked.
+.Pp
+When
+.Nm
+is started, it checks that certain name-to-address
+translation-calls function correctly.
+If they fail, the network configuration databases may be corrupt.
+Since
+.Tn RPC
+services cannot function correctly in this situation,
+.Nm
+reports the condition and terminates.
+.Pp
+The
+.Nm
+utility can only be started by the super-user.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl a
+When debugging
+.Pq Fl d ,
+do an abort on errors.
+.It Fl d
+Run in debug mode.
+In this mode,
+.Nm
+will log additional information during operation,
+and will abort on certain errors if
+.Fl a
+is also specified.
+With this option, the name-to-address translation consistency
+checks are shown in detail.
+.It Fl f
+Do not fork and become a background process.
+.It Fl h
+Specify specific IP addresses to bind to for UDP requests.
+This option may be specified multiple times and can be used to
+restrict the interfaces rpcbind will respond to.
+When specifying IP addresses with
+.Fl h ,
+.Nm
+will automatically add
+.Li 127.0.0.1
+and if IPv6 is enabled,
+.Li ::1
+to the list.
+If no
+.Fl h
+option is specified,
+.Nm
+will bind to
+.Dv INADDR_ANY ,
+which could lead to problems on a multi-homed host due to
+.Nm
+returning a UDP packet from a different IP address than it was
+sent to.
+Note that when
+.Nm
+is controlled via systemd's socket activation,
+the
+.Fl h
+option is ignored. In this case, you need to edit
+the
+.Nm ListenStream
+and
+.Nm ListenDgram
+definitions in
+.Nm /usr/lib/systemd/system/rpcbind.socket
+instead.
+.It Fl i
+.Dq Insecure
+mode.
+Allow calls to SET and UNSET from any host.
+Normally
+.Nm
+accepts these requests only from the loopback interface for security reasons.
+This change is necessary for programs that were compiled with earlier
+versions of the rpc library and do not make those requests using the
+loopback interface.
+.It Fl l
+Turn on libwrap connection logging.
+.It Fl s
+Cause
+.Nm
+to change to the user daemon as soon as possible.
+This causes
+.Nm
+to use non-privileged ports for outgoing connections, preventing non-privileged
+clients from using
+.Nm
+to connect to services from a privileged port.
+.It Fl w
+Cause
+.Nm
+to do a "warm start" by read a state file when
+.Nm
+starts up. The state file is created when
+.Nm
+terminates.
+.El
+.Sh NOTES
+All RPC servers must be restarted if
+.Nm
+is restarted.
+.Sh SEE ALSO
+.Xr rpcinfo 8
+.Sh LINUX PORT
+.Bl Aurelien Charbon <aurelien.charbon@bull.net>
+.El
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/man/rpcinfo.8
^
|
@@ -0,0 +1,354 @@
+.\" @(#)rpcinfo.1m 1.23 93/03/29 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" Copyright 1991 Sun Microsystems, Inc.
+.\" $NetBSD: rpcinfo.8,v 1.11 2001/12/08 19:12:46 wiz Exp $
+.Dd August 18, 1992
+.Dt RPCINFO 8
+.Sh NAME
+.Nm rpcinfo
+.Nd report RPC information
+.Sh SYNOPSIS
+.Nm "rpcinfo"
+.Op Fl m Li \&| Fl s
+.Op Ar host
+.Nm "rpcinfo"
+.Fl p Op Ar host
+.Nm "rpcinfo"
+.Fl T Ar transport
+.Ar host Ar prognum
+.Op Ar versnum
+.Nm "rpcinfo"
+.Fl l
+.Op Fl T Ar transport
+.Ar host Ar prognum Ar versnum
+.Nm "rpcinfo"
+.Op Fl n Ar portnum
+.Fl u
+.Ar host Ar prognum
+.Op Ar versnum
+.Nm "rpcinfo"
+.Op Fl n Ar portnum
+.Op Fl t
+.Ar host Ar prognum
+.Op Ar versnum
+.Nm "rpcinfo"
+.Fl a Ar serv_address
+.Fl T Ar transport
+.Ar prognum
+.Op Ar versnum
+.Nm "rpcinfo"
+.Fl b
+.Op Fl T Ar transport
+.Ar prognum Ar versnum
+.Nm "rpcinfo"
+.Fl d
+.Op Fl T Ar transport
+.Ar prognum Ar versnum
+.Sh DESCRIPTION
+.Nm
+makes an RPC call to an RPC
+server and reports what it finds.
+.Pp
+In the first synopsis,
+.Nm
+lists all the registered RPC services with
+.Nm rpcbind
+on
+.Ar host .
+If
+.Ar host
+is not specified, the local host is the default.
+If
+.Fl s
+is used, the information is displayed in a concise format.
+.Pp
+In the second synopsis,
+.Nm
+lists all the RPC services registered with
+.Nm rpcbind ,
+version 2.
+Also note that the format of the information
+is different in the first and the second synopsis.
+This is because the second synopsis is an older protocol used to
+collect the information displayed (version 2 of the
+.Nm rpcbind
+protocol).
+.Pp
+The third synopsis makes an RPC call to procedure 0
+of
+.Ar prognum
+and
+.Ar versnum
+on the specified
+.Ar host
+and reports whether a response was received.
+.Ar transport
+is the transport which has to be used for contacting the
+given service.
+The remote address of the service is obtained by
+making a call to the remote
+.Nm rpcbind .
+.Pp
+The
+.Ar prognum
+argument is a number that represents an RPC program number.
+If a
+.Ar versnum
+is specified,
+.Nm
+attempts to call that version of the specified
+.Ar prognum .
+Otherwise,
+.Nm
+attempts to find all the registered version
+numbers for the specified
+.Ar prognum
+by calling version 0,
+which is presumed not to exist;
+if it does exist,
+.Nm
+attempts to obtain this information by calling
+an extremely high version number instead,
+and attempts to call each registered version.
+Note:
+the version number is required for
+.Fl b
+and
+.Fl d
+options.
+.Sh OPTIONS
+.Bl -tag -width indent
+.It Fl T Ar transport
+Specify the transport on which the service is required.
+If this option is not specified,
+.Nm
+uses the transport specified in the
+.Ev NETPATH
+environment variable, or if that is unset or null, the transport
+in the
+.Xr netconfig 5
+database is used.
+This is a generic option,
+and can be used in conjunction with other options as
+shown in the SYNOPSIS.
+.Pp
+.It Fl a Ar serv_address
+Use
+.Ar serv_address
+as the (universal) address for the service on
+.Ar transport
+to ping procedure 0
+of the specified
+.Ar prognum
+and report whether a response was received.
+The
+.Fl T
+option is required with the
+.Fl a
+option.
+.Pp
+If
+.Ar versnum
+is not specified,
+.Nm
+tries to ping all
+available version numbers for that program number.
+This option avoids calls to remote
+.Nm rpcbind
+to find the address of the service.
+The
+.Ar serv_address
+is specified in universal address format of the given transport.
+.Pp
+.It Fl b
+Make an RPC broadcast to procedure 0
+of the specified
+.Ar prognum
+and
+.Ar versnum
+and report all hosts that respond.
+If
+.Ar transport
+is specified, it broadcasts its request only on the
+specified transport.
+If broadcasting is not supported by any
+transport,
+an error message is printed.
+Use of broadcasting should be limited because of the potential for adverse
+effect on other systems.
+.Pp
+.It Fl d
+Delete registration for the RPC service of the specified
+.Ar prognum
+and
+.Ar versnum .
+If
+.Ar transport
+is specified,
+unregister the service on only that transport,
+otherwise unregister the service on all
+the transports on which it was registered.
+Only the owner of a service can delete a registration, except the
+super-user who can delete any service.
+.Pp
+.It Fl l
+Display a list of entries with a given
+.Ar prognum
+and
+.Ar versnum
+on the specified
+.Ar host .
+Entries are returned for all transports
+in the same protocol family as that used to contact the remote
+.Nm rpcbind .
+.Pp
+.It Fl m
+Display a table of statistics of
+.Nm rpcbind
+operations on the given
+.Ar host .
+The table shows statistics for each version of
+.Nm rpcbind
+(versions 2, 3 and 4), giving the number of times each procedure was
+requested and successfully serviced, the number and type of remote call
+requests that were made, and information about RPC address lookups that were
+handled. This is useful for monitoring RPC activities on
+.Ar host .
+.Pp
+.It Fl n Ar portnum
+Use
+.Ar portnum
+as the port number for the
+.Fl t
+and
+.Fl u
+options instead of the port number given by
+.Nm rpcbind .
+Use of this option avoids a call to the remote
+.Nm rpcbind
+to find out the address of the service. This option is made
+obsolete by the
+.Fl a
+option.
+.Pp
+.It Fl p
+Probe
+.Nm rpcbind
+on
+.Ar host
+using version 2 of the
+.Nm rpcbind
+protocol,
+and display a list of all registered RPC programs.
+If
+.Ar host
+is not specified, it defaults to the local host.
+Note: Version 2 of the
+.Nm rpcbind
+protocol was previously known as the portmapper protocol.
+.Pp
+.It Fl s
+Display a concise list of all registered RPC programs on
+.Ar host .
+If
+.Ar host
+is not specified, it defaults to the local host.
+.Pp
+.It Fl t
+Make an RPC call to procedure 0 of
+.Ar prognum
+on the specified
+.Ar host
+using TCP,
+and report whether a response was received. This option is made
+obsolete by the
+.Fl T
+option as shown in the third synopsis.
+.Pp
+.It Fl u
+Make an RPC call to procedure 0 of
+.Ar prognum
+on the specified
+.Ar host
+using UDP,
+and report whether a response was received. This option is made
+obsolete by the
+.Fl T
+option as shown in the third synopsis.
+.El
+.Sh EXAMPLES
+To show all of the RPC services registered on the local machine use:
+.Pp
+.Bd -literal
+ example% rpcinfo
+.Ed
+.Pp
+To show all of the RPC
+services registered with
+.Nm rpcbind
+on the machine named
+.Nm klaxon
+use:
+.Pp
+.Bd -literal
+ example% rpcinfo klaxon
+.Ed
+.Pp
+The information displayed by the above commands can be quite lengthy.
+Use the
+.Fl s
+option to display a more concise list:
+.Pp
+.Bd -literal
+ example$ rpcinfo -s klaxon
+.Ed
+.Bl -column "program" "w,x,y,z" "local,tcp,udp,tcp6,udp6" "nlockmgr" "super-user"
+.It program Ta version(s) Ta netid(s) Ta service Ta owner
+.It 100000 Ta 2,3,4 Ta local,tcp,udp,tcp6,udp6 Ta rpcbind Ta super-user
+.It 100008 Ta 1 Ta udp,tcp,udp6,tcp6 Ta walld Ta super-user
+.It 100002 Ta 2,1 Ta udp,udp6 Ta rusersd Ta super-user
+.It 100001 Ta 2,3,4 Ta udp,udp6 Ta rstatd Ta super-user
+.It 100012 Ta 1 Ta udp,tcp Ta sprayd Ta super-user
+.It 100007 Ta 3 Ta udp,tcp Ta ypbind Ta super-user
+.El
+.Pp
+To show whether the RPC
+service with program number
+.Ar prognum
+and version
+.Ar versnum
+is registered on the machine named
+.Nm klaxon
+for the transport TCP
+use:
+.Pp
+.Bd -literal
+ example% rpcinfo -T tcp klaxon prognum versnum
+.Ed
+.Pp
+To show all RPC
+services registered with version 2 of the
+.Nm rpcbind
+protocol on the local machine use:
+.Bd -literal
+ example% rpcinfo -p
+.Ed
+.Pp
+To delete the registration for version
+1 of the
+.Nm walld
+(program number 100008 )
+service for all transports use:
+.Bd -literal
+ example# rpcinfo -d 100008 1
+.Ed
+.Pp
+or
+.Bd -literal
+ example# rpcinfo -d walld 1
+.Ed
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr netconfig 5 ,
+.Xr rpc 5 ,
+.Xr rpcbind 8
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/check_bound.c
^
|
@@ -0,0 +1,230 @@
+/* $NetBSD: check_bound.c,v 1.2 2000/06/22 08:09:26 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/check_bound.c,v 1.4 2002/10/07 02:56:59 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.
+ */
+
+/* #ident "@(#)check_bound.c 1.15 93/07/05 SMI" */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)check_bound.c 1.11 89/04/21 Copyr 1989 Sun Micro";
+#endif
+#endif
+
+/*
+ * check_bound.c
+ * Checks to see whether the program is still bound to the
+ * claimed address and returns the univeral merged address
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <netconfig.h>
+#include <syslog.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include "rpcbind.h"
+
+struct fdlist {
+ int fd;
+ struct netconfig *nconf;
+ struct fdlist *next;
+ int check_binding;
+};
+
+static struct fdlist *fdhead; /* Link list of the check fd's */
+static struct fdlist *fdtail;
+static char *nullstring = "";
+
+static bool_t check_bound(struct fdlist *, char *uaddr);
+
+/*
+ * Returns 1 if the given address is bound for the given addr & transport
+ * For all error cases, we assume that the address is bound
+ * Returns 0 for success.
+ */
+static bool_t
+check_bound(struct fdlist *fdl, char *uaddr)
+{
+ int fd;
+ struct netbuf *na;
+ int ans;
+
+ if (fdl->check_binding == FALSE)
+ return (TRUE);
+
+ na = uaddr2taddr(fdl->nconf, uaddr);
+ if (!na)
+ return (TRUE); /* punt, should never happen */
+
+ fd = __rpc_nconf2fd(fdl->nconf);
+ if (fd < 0) {
+ free(na->buf);
+ free(na);
+ return (TRUE);
+ }
+
+ ans = bind(fd, (struct sockaddr *)na->buf, na->len);
+
+ close(fd);
+ free(na->buf);
+ free(na);
+
+ return (ans == 0 ? FALSE : TRUE);
+}
+
+int
+add_bndlist(struct netconfig *nconf, struct netbuf *baddr /*__unused*/)
+{
+ struct fdlist *fdl;
+ struct netconfig *newnconf;
+
+ newnconf = getnetconfigent(nconf->nc_netid);
+ if (newnconf == NULL)
+ return (-1);
+ fdl = malloc(sizeof (struct fdlist));
+ if (fdl == NULL) {
+ freenetconfigent(newnconf);
+ syslog(LOG_ERR, "no memory!");
+ return (-1);
+ }
+ fdl->nconf = newnconf;
+ fdl->next = NULL;
+ if (fdhead == NULL) {
+ fdhead = fdl;
+ fdtail = fdl;
+ } else {
+ fdtail->next = fdl;
+ fdtail = fdl;
+ }
+ /* XXX no bound checking for now */
+ fdl->check_binding = FALSE;
+
+ return 0;
+}
+
+bool_t
+is_bound(char *netid, char *uaddr)
+{
+ struct fdlist *fdl;
+
+ for (fdl = fdhead; fdl; fdl = fdl->next)
+ if (strcmp(fdl->nconf->nc_netid, netid) == 0)
+ break;
+ if (fdl == NULL)
+ return (TRUE);
+ return (check_bound(fdl, uaddr));
+}
+
+/*
+ * Returns NULL if there was some system error.
+ * Returns "" if the address was not bound, i.e the server crashed.
+ * Returns the merged address otherwise.
+ */
+char *
+mergeaddr(SVCXPRT *xprt, char *netid, char *uaddr, char *saddr)
+{
+ struct fdlist *fdl;
+ char *c_uaddr, *s_uaddr, *m_uaddr, *allocated_uaddr = NULL;
+
+ for (fdl = fdhead; fdl; fdl = fdl->next)
+ if (strcmp(fdl->nconf->nc_netid, netid) == 0)
+ break;
+ if (fdl == NULL)
+ return (NULL);
+ if (check_bound(fdl, uaddr) == FALSE)
+ /* that server died */
+ return (nullstring);
+ /*
+ * If saddr is not NULL, the remote client may have included the
+ * address by which it contacted us. Use that for the "client" uaddr,
+ * otherwise use the info from the SVCXPRT.
+ */
+ if (saddr != NULL) {
+ c_uaddr = saddr;
+ } else {
+ c_uaddr = taddr2uaddr(fdl->nconf, svc_getrpccaller(xprt));
+ if (c_uaddr == NULL) {
+ syslog(LOG_ERR, "taddr2uaddr failed for %s",
+ fdl->nconf->nc_netid);
+ return (NULL);
+ }
+ allocated_uaddr = c_uaddr;
+ }
+
+#ifdef ND_DEBUG
+ if (debugging) {
+ if (saddr == NULL) {
+ fprintf(stderr, "mergeaddr: client uaddr = %s\n",
+ c_uaddr);
+ } else {
+ fprintf(stderr, "mergeaddr: contact uaddr = %s\n",
+ c_uaddr);
+ }
+ }
+#endif
+ s_uaddr = uaddr;
+ /*
+ * This is all we should need for IP 4 and 6
+ */
+ m_uaddr = addrmerge(svc_getrpccaller(xprt), s_uaddr, c_uaddr, netid);
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "mergeaddr: uaddr = %s, merged uaddr = %s\n",
+ uaddr, m_uaddr);
+#endif
+ if (allocated_uaddr != NULL)
+ free(allocated_uaddr);
+ return (m_uaddr);
+}
+
+/*
+ * Returns a netconf structure from its internal list. This
+ * structure should not be freed.
+ */
+struct netconfig *
+rpcbind_get_conf(char *netid)
+{
+ struct fdlist *fdl;
+
+ for (fdl = fdhead; fdl; fdl = fdl->next)
+ if (strcmp(fdl->nconf->nc_netid, netid) == 0)
+ break;
+ if (fdl == NULL)
+ return (NULL);
+ return (fdl->nconf);
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/pmap_svc.c
^
|
@@ -0,0 +1,425 @@
+/* $NetBSD: pmap_svc.c,v 1.2 2000/10/20 11:49:40 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/pmap_svc.c,v 1.4 2002/10/07 02:56:59 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) 1984 - 1991 by Sun Microsystems, Inc.
+ */
+
+/* #ident "@(#)pmap_svc.c 1.14 93/07/05 SMI" */
+
+#if 0
+#ifndef lint
+static char sccsid[] = "@(#)pmap_svc.c 1.23 89/04/05 Copyr 1984 Sun Micro";
+#endif
+#endif
+
+/*
+ * pmap_svc.c
+ * The server procedure for the version 2 portmaper.
+ * All the portmapper related interface from the portmap side.
+ */
+
+#ifdef PORTMAP
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/rpcb_prot.h>
+#ifdef RPCBIND_DEBUG
+#include <syslog.h>
+#include <stdlib.h>
+#endif
+#include "rpcbind.h"
+#include "xlog.h"
+#include <rpc/svc_soc.h> /* svc_getcaller routine definition */
+static struct pmaplist *find_service_pmap(rpcprog_t, rpcvers_t,
+ rpcprot_t);
+static bool_t pmapproc_change(struct svc_req *, SVCXPRT *, u_long);
+static bool_t pmapproc_getport(struct svc_req *, SVCXPRT *);
+static bool_t pmapproc_dump(struct svc_req *, SVCXPRT *);
+
+/*
+ * Called for all the version 2 inquiries.
+ */
+void
+pmap_service(struct svc_req *rqstp, SVCXPRT *xprt)
+{
+ rpcbs_procinfo(RPCBVERS_2_STAT, rqstp->rq_proc);
+ switch (rqstp->rq_proc) {
+ case PMAPPROC_NULL:
+ /*
+ * Null proc call
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "PMAPPROC_NULL\n");
+#endif
+ check_access(xprt, rqstp->rq_proc, 0, PMAPVERS);
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_void, NULL)) &&
+ debugging) {
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ break;
+
+ case PMAPPROC_SET:
+ /*
+ * Set a program, version to port mapping
+ */
+ pmapproc_change(rqstp, xprt, rqstp->rq_proc);
+ break;
+
+ case PMAPPROC_UNSET:
+ /*
+ * Remove a program, version to port mapping.
+ */
+ pmapproc_change(rqstp, xprt, rqstp->rq_proc);
+ break;
+
+ case PMAPPROC_GETPORT:
+ /*
+ * Lookup the mapping for a program, version and return its
+ * port number.
+ */
+ pmapproc_getport(rqstp, xprt);
+ break;
+
+ case PMAPPROC_DUMP:
+ /*
+ * Return the current set of mapped program, version
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "PMAPPROC_DUMP\n");
+#endif
+ pmapproc_dump(rqstp, xprt);
+ break;
+
+ case PMAPPROC_CALLIT:
+ /*
+ * Calls a procedure on the local machine. If the requested
+ * procedure is not registered this procedure does not return
+ * error information!!
+ * This procedure is only supported on rpc/udp and calls via
+ * rpc/udp. It passes null authentication parameters.
+ */
+ rpcbproc_callit_com(rqstp, xprt, PMAPPROC_CALLIT, PMAPVERS);
+ break;
+
+ default:
+ svcerr_noproc(xprt);
+ break;
+ }
+}
+
+/*
+ * returns the item with the given program, version number. If that version
+ * number is not found, it returns the item with that program number, so that
+ * the port number is now returned to the caller. The caller when makes a
+ * call to this program, version number, the call will fail and it will
+ * return with PROGVERS_MISMATCH. The user can then determine the highest
+ * and the lowest version number for this program using clnt_geterr() and
+ * use those program version numbers.
+ */
+static struct pmaplist *
+find_service_pmap(rpcprog_t prog, rpcvers_t vers, rpcprot_t prot)
+{
+ register struct pmaplist *hit = NULL;
+ register struct pmaplist *pml;
+
+ for (pml = list_pml; pml != NULL; pml = pml->pml_next) {
+ if ((pml->pml_map.pm_prog != prog) ||
+ (pml->pml_map.pm_prot != prot))
+ continue;
+ hit = pml;
+ if (pml->pml_map.pm_vers == vers)
+ break;
+ }
+ return (hit);
+}
+
+static bool_t
+pmapproc_change(struct svc_req *rqstp /*__unused*/, SVCXPRT *xprt, unsigned long op)
+{
+ struct pmap reg;
+ RPCB rpcbreg;
+ long ans;
+ uid_t uid;
+ char uidbuf[32];
+ int rc = TRUE;
+
+ /*
+ * Can't use getpwnam here. We might end up calling ourselves
+ * and looping.
+ */
+ if (__rpc_get_local_uid(xprt, &uid) < 0) {
+ rpcbreg.r_owner = "unknown";
+ if (is_localroot(svc_getrpccaller(xprt)))
+ rpcbreg.r_owner = "superuser";
+ } else if (uid == 0)
+ rpcbreg.r_owner = "superuser";
+ else {
+ /* r_owner will be strdup-ed later */
+ snprintf(uidbuf, sizeof uidbuf, "%d", uid);
+ rpcbreg.r_owner = uidbuf;
+ }
+
+ if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) {
+ svcerr_decode(xprt);
+ rc = FALSE;
+ goto done;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "%s request for (%lu, %lu) : ",
+ op == PMAPPROC_SET ? "PMAP_SET" : "PMAP_UNSET",
+ reg.pm_prog, reg.pm_vers);
+#endif
+
+ if (!check_access(xprt, op, reg.pm_prog, PMAPVERS)) {
+ svcerr_weakauth(xprt);
+ rc = (FALSE);
+ goto done;
+ }
+
+ rpcbreg.r_prog = reg.pm_prog;
+ rpcbreg.r_vers = reg.pm_vers;
+
+ if (op == PMAPPROC_SET) {
+ char buf[32];
+
+ rpcbreg.r_netid = pmap_ipprot2netid(reg.pm_prot);
+ if (rpcbreg.r_netid == NULL) {
+ ans = FALSE;
+ goto done_change;
+ }
+ if (!memcmp(rpcbreg.r_netid, "udp6", 4) ||
+ !memcmp(rpcbreg.r_netid, "tcp6", 4)) {
+ snprintf(buf, sizeof buf, "::.%d.%d",
+ (int)((reg.pm_port >> 8) & 0xff),
+ (int)(reg.pm_port & 0xff));
+ } else {
+ snprintf(buf, sizeof buf, "0.0.0.0.%d.%d",
+ (int)((reg.pm_port >> 8) & 0xff),
+ (int)(reg.pm_port & 0xff));
+ }
+ rpcbreg.r_addr = buf;
+ ans = map_set(&rpcbreg, rpcbreg.r_owner);
+ } else if (op == PMAPPROC_UNSET) {
+ bool_t ans1, ans2;
+ rpcbreg.r_addr = NULL;
+ rpcbreg.r_netid = tcptrans;
+ ans1 = map_unset(&rpcbreg, rpcbreg.r_owner);
+ rpcbreg.r_netid = udptrans;
+ ans2 = map_unset(&rpcbreg, rpcbreg.r_owner);
+ ans = ans1 || ans2;
+ } else {
+ ans = FALSE;
+ }
+done_change:
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t) &ans)) &&
+ debugging) {
+ xlog(L_ERROR, "portmap: svc_sendreply failed!\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "%s\n", ans == TRUE ? "succeeded" : "failed");
+#endif
+ if (op == PMAPPROC_SET)
+ rpcbs_set(RPCBVERS_2_STAT, ans);
+ else
+ rpcbs_unset(RPCBVERS_2_STAT, ans);
+done:
+ if (!svc_freeargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) {
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#endif
+ }
+ return (rc);
+}
+
+/* ARGSUSED */
+static bool_t
+pmapproc_getport(struct svc_req *rqstp /*__unused*/, SVCXPRT *xprt)
+{
+ struct pmap reg;
+ long lport;
+ int port = 0;
+ struct pmaplist *fnd;
+#ifdef RPCBIND_DEBUG
+ char *uaddr;
+#endif
+ int rc = TRUE;
+
+ if (!svc_getargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) {
+ svcerr_decode(xprt);
+ rc = FALSE;
+ goto done;
+ }
+
+ if (!check_access(xprt, PMAPPROC_GETPORT, reg.pm_prog, PMAPVERS)) {
+ svcerr_weakauth(xprt);
+ rc = FALSE;
+ goto done;
+ }
+
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ uaddr = taddr2uaddr(rpcbind_get_conf(xprt->xp_netid),
+ svc_getrpccaller(xprt));
+ xlog(LOG_DEBUG, "PMAP_GETPORT req for (%lu, %lu, %s) from %s :",
+ reg.pm_prog, reg.pm_vers,
+ pmap_ipprot2netid(reg.pm_prot)?: "<invalid>",
+ uaddr);
+ free(uaddr);
+ }
+#endif
+ fnd = find_service_pmap(reg.pm_prog, reg.pm_vers, reg.pm_prot);
+ if (fnd) {
+ char serveuaddr[32];
+ char *netid;
+
+ netid = pmap_ipprot2netid(reg.pm_prot);
+ if (netid != NULL) {
+ snprintf(serveuaddr, sizeof serveuaddr,
+ "0.0.0.0.%ld.%ld",
+ (fnd->pml_map.pm_port >> 8) & 0xff,
+ (fnd->pml_map.pm_port) & 0xff);
+
+ if (is_bound(netid, serveuaddr)) {
+ port = fnd->pml_map.pm_port;
+ } else { /* this service is dead; delete it */
+ delete_prog(reg.pm_prog);
+ }
+ }
+ }
+
+ lport = port;
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_long, (caddr_t)&lport)) &&
+ debugging) {
+ xlog(L_ERROR, "portmap: svc_sendreply failed!\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "port = %d\n", port);
+#endif
+ rpcbs_getaddr(RPCBVERS_2_STAT, reg.pm_prog, reg.pm_vers,
+ pmap_ipprot2netid(reg.pm_prot) ?: "<unknown>",
+ port ? udptrans : "");
+
+done:
+ if (!svc_freeargs(xprt, (xdrproc_t) xdr_pmap, (char *)®)) {
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#endif
+ }
+ return (rc);
+}
+
+/* ARGSUSED */
+static bool_t
+pmapproc_dump(struct svc_req *rqstp /*__unused*/, SVCXPRT *xprt)
+{
+ int rc = TRUE;
+
+ if (!svc_getargs(xprt, (xdrproc_t)xdr_void, NULL)) {
+ svcerr_decode(xprt);
+ rc = FALSE;
+ goto done;
+ }
+
+ if (!check_access(xprt, PMAPPROC_DUMP, 0, PMAPVERS)) {
+ svcerr_weakauth(xprt);
+ rc = FALSE;
+ goto done;
+ }
+
+ if ((!svc_sendreply(xprt, (xdrproc_t) xdr_pmaplist_ptr,
+ (caddr_t)&list_pml)) && debugging) {
+ xlog(L_ERROR, "portmap: svc_sendreply failed!\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+
+done:
+ if (!svc_freeargs(xprt, (xdrproc_t) xdr_void, (char *)NULL)) {
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+#endif
+ }
+ return (rc);
+}
+
+int pmap_netid2ipprot(const char *netid)
+{
+ if (!netid)
+ return 0;
+ if (strcmp(netid, tcptrans) == 0)
+ return IPPROTO_TCP;
+ if (strcmp(netid, udptrans) == 0)
+ return IPPROTO_UDP;
+ return 0;
+}
+
+char *pmap_ipprot2netid(unsigned long proto)
+{
+ if (proto == IPPROTO_UDP)
+ return udptrans;
+ if (proto == IPPROTO_TCP)
+ return tcptrans;
+ return NULL;
+}
+
+#endif /* PORTMAP */
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcb_stat.c
^
|
@@ -0,0 +1,205 @@
+/*
+ * $NetBSD: rpcb_stat.c,v 1.2 2000/07/04 20:27:40 matt Exp $
+ * $FreeBSD: src/usr.sbin/rpcbind/rpcb_stat.c,v 1.4 2003/10/29 09:29:23 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.
+ */
+/* #pragma ident "@(#)rpcb_stat.c 1.7 94/04/25 SMI" */
+
+/*
+ * rpcb_stat.c
+ * Allows for gathering of statistics
+ *
+ * Copyright (c) 1990 by Sun Microsystems, Inc.
+ */
+
+#include <stdio.h>
+#include <netconfig.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <sys/stat.h>
+#ifdef PORTMAP
+#include <rpc/pmap_prot.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+#include "rpcbind.h"
+
+static rpcb_stat_byvers inf;
+
+void
+rpcbs_init()
+{
+
+}
+
+void
+rpcbs_procinfo(rpcvers_t rtype, rpcproc_t proc)
+{
+ switch (rtype + 2) {
+#ifdef PORTMAP
+ case PMAPVERS: /* version 2 */
+ if (proc > rpcb_highproc_2)
+ return;
+ break;
+#endif
+ case RPCBVERS: /* version 3 */
+ if (proc > rpcb_highproc_3)
+ return;
+ break;
+ case RPCBVERS4: /* version 4 */
+ if (proc > rpcb_highproc_4)
+ return;
+ break;
+ default: return;
+ }
+ inf[rtype].info[proc]++;
+ return;
+}
+
+void
+rpcbs_set(rpcvers_t rtype, bool_t success)
+{
+ if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
+ return;
+ inf[rtype].setinfo++;
+ return;
+}
+
+void
+rpcbs_unset(rpcvers_t rtype, bool_t success)
+{
+ if ((rtype >= RPCBVERS_STAT) || (success == FALSE))
+ return;
+ inf[rtype].unsetinfo++;
+ return;
+}
+
+void
+rpcbs_getaddr(rpcvers_t rtype, rpcprog_t prog, rpcvers_t vers, char *netid,
+ char *uaddr)
+{
+ rpcbs_addrlist *al;
+ struct netconfig *nconf;
+
+ if (rtype >= RPCBVERS_STAT)
+ return;
+ for (al = inf[rtype].addrinfo; al; al = al->next) {
+
+ if(al->netid == NULL)
+ return;
+ if ((al->prog == prog) && (al->vers == vers) &&
+ (strcmp(al->netid, netid) == 0)) {
+ if ((uaddr == NULL) || (uaddr[0] == 0))
+ al->failure++;
+ else
+ al->success++;
+ return;
+ }
+ }
+ nconf = rpcbind_get_conf(netid);
+ if (nconf == NULL) {
+ return;
+ }
+ al = (rpcbs_addrlist *) malloc(sizeof (rpcbs_addrlist));
+ if (al == NULL) {
+ return;
+ }
+ al->prog = prog;
+ al->vers = vers;
+ al->netid = nconf->nc_netid;
+ if ((uaddr == NULL) || (uaddr[0] == 0)) {
+ al->failure = 1;
+ al->success = 0;
+ } else {
+ al->failure = 0;
+ al->success = 1;
+ }
+ al->next = inf[rtype].addrinfo;
+ inf[rtype].addrinfo = al;
+}
+
+void
+rpcbs_rmtcall(rpcvers_t rtype, rpcproc_t rpcbproc, rpcprog_t prog,
+ rpcvers_t vers, rpcproc_t proc, char *netid, rpcblist_ptr rbl)
+{
+ rpcbs_rmtcalllist *rl;
+ struct netconfig *nconf;
+
+ if (rtype >= RPCBVERS_STAT)
+ return;
+ for (rl = inf[rtype].rmtinfo; rl; rl = rl->next) {
+
+ if(rl->netid == NULL)
+ return;
+
+ if ((rl->prog == prog) && (rl->vers == vers) &&
+ (rl->proc == proc) &&
+ (strcmp(rl->netid, netid) == 0)) {
+ if ((rbl == NULL) ||
+ (rbl->rpcb_map.r_vers != vers))
+ rl->failure++;
+ else
+ rl->success++;
+ if (rpcbproc == RPCBPROC_INDIRECT)
+ rl->indirect++;
+ return;
+ }
+ }
+ nconf = rpcbind_get_conf(netid);
+ if (nconf == NULL) {
+ return;
+ }
+ rl = (rpcbs_rmtcalllist *) malloc(sizeof (rpcbs_rmtcalllist));
+ if (rl == NULL) {
+ return;
+ }
+ rl->prog = prog;
+ rl->vers = vers;
+ rl->proc = proc;
+ rl->netid = nconf->nc_netid;
+ if ((rbl == NULL) ||
+ (rbl->rpcb_map.r_vers != vers)) {
+ rl->failure = 1;
+ rl->success = 0;
+ } else {
+ rl->failure = 0;
+ rl->success = 1;
+ }
+ rl->indirect = 1;
+ rl->next = inf[rtype].rmtinfo;
+ inf[rtype].rmtinfo = rl;
+ return;
+}
+
+void *
+rpcbproc_getstat(void *arg /*__unused*/, struct svc_req *req /*__unused*/,
+ SVCXPRT *xprt /*__unused*/, rpcvers_t versnum /*__unused*/)
+{
+ return (void *)&inf;
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcb_svc.c
^
|
@@ -0,0 +1,240 @@
+/* $NetBSD: rpcb_svc.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc.c,v 1.2 2002/10/07 02:56:59 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.
+ */
+
+/* #ident "@(#)rpcb_svc.c 1.16 93/07/05 SMI" */
+
+/*
+ * rpcb_svc.c
+ * The server procedure for the version 3 rpcbind (TLI).
+ *
+ * It maintains a separate list of all the registered services with the
+ * version 3 of rpcbind.
+ */
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <netconfig.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "rpcbind.h"
+#include "xlog.h"
+
+static void *rpcbproc_getaddr_3_local(void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t);
+static void *rpcbproc_dump_3_local(void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t);
+
+/*
+ * Called by svc_getreqset. There is a separate server handle for
+ * every transport that it waits on.
+ */
+void
+rpcb_service_3(struct svc_req *rqstp, SVCXPRT *transp)
+{
+ union {
+ RPCB rpcbproc_set_3_arg;
+ RPCB rpcbproc_unset_3_arg;
+ RPCB rpcbproc_getaddr_3_local_arg;
+ struct rpcb_rmtcallargs rpcbproc_callit_3_arg;
+ char *rpcbproc_uaddr2taddr_3_arg;
+ struct netbuf rpcbproc_taddr2uaddr_3_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+ rpcprog_t setprog = 0;
+
+ rpcbs_procinfo(RPCBVERS_3_STAT, rqstp->rq_proc);
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ /*
+ * Null proc call
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_NULL");
+#endif
+ /* This call just logs, no actual checks */
+ check_access(transp, rqstp->rq_proc, 0, RPCBVERS);
+ (void) svc_sendreply(transp, (xdrproc_t)xdr_void, (char *)NULL);
+ return;
+
+ case RPCBPROC_SET:
+ xdr_argument = (xdrproc_t )xdr_rpcb;
+ xdr_result = (xdrproc_t )xdr_bool;
+ local = rpcbproc_set_com;
+ break;
+
+ case RPCBPROC_UNSET:
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_bool;
+ local = rpcbproc_unset_com;
+ break;
+
+ case RPCBPROC_GETADDR:
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_getaddr_3_local;
+ break;
+
+ case RPCBPROC_DUMP:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_DUMP");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
+ local = rpcbproc_dump_3_local;
+ break;
+
+ case RPCBPROC_CALLIT:
+ rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS);
+ return;
+
+ case RPCBPROC_GETTIME:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_GETTIME");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_u_long;
+ local = rpcbproc_gettime_com;
+ break;
+
+ case RPCBPROC_UADDR2TADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_UADDR2TADDR");
+#endif
+ xdr_argument = (xdrproc_t)xdr_wrapstring;
+ xdr_result = (xdrproc_t)xdr_netbuf;
+ local = rpcbproc_uaddr2taddr_com;
+ break;
+
+ case RPCBPROC_TADDR2UADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_TADDR2UADDR");
+#endif
+ xdr_argument = (xdrproc_t)xdr_netbuf;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_taddr2uaddr_com;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ (void) memset((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
+ (char *) &argument)) {
+ svcerr_decode(transp);
+ if (debugging)
+ (void) xlog(LOG_DEBUG, "rpcbind: could not decode");
+ goto done;
+ }
+
+ if (rqstp->rq_proc == RPCBPROC_SET
+ || rqstp->rq_proc == RPCBPROC_UNSET
+ || rqstp->rq_proc == RPCBPROC_GETADDR)
+ setprog = argument.rpcbproc_set_3_arg.r_prog;
+
+ if (!check_access(transp, rqstp->rq_proc, setprog, RPCBVERS)) {
+ svcerr_weakauth(transp);
+ goto done;
+ }
+ result = (*local)(&argument, rqstp, transp, RPCBVERS);
+ if (result != NULL && !svc_sendreply(transp, (xdrproc_t)xdr_result,
+ result)) {
+ svcerr_systemerr(transp);
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "rpcbind: svc_sendreply");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+done:
+ if (!svc_freeargs(transp, (xdrproc_t)xdr_argument, (char *)
+ &argument)) {
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "unable to free arguments");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+}
+
+/*
+ * Lookup the mapping for a program, version and return its
+ * address. Assuming that the caller wants the address of the
+ * server running on the transport on which the request came.
+ *
+ * We also try to resolve the universal address in terms of
+ * address of the caller.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getaddr_3_local(void *arg, struct svc_req *rqstp /*__unused*/,
+ SVCXPRT *transp /*__unused*/, rpcvers_t versnum /*__unused*/)
+{
+ RPCB *regp = (RPCB *)arg;
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ char *uaddr;
+
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
+ svc_getrpccaller(transp));
+ xlog(LOG_DEBUG, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, uaddr);
+ free(uaddr);
+ }
+#endif
+ return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS,
+ RPCB_ALLVERS));
+}
+
+/* ARGSUSED */
+static void *
+rpcbproc_dump_3_local(void *arg /*__unused*/, struct svc_req *rqstpc /*__unused*/,
+ SVCXPRT *transp /*__unused*/, rpcvers_t versnum /*__unused*/)
+{
+ return ((void *)&list_rbl);
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcb_svc_4.c
^
|
@@ -0,0 +1,460 @@
+/*
+ * $NetBSD: rpcb_svc_4.c,v 1.1 2000/06/02 23:15:41 fvdl Exp $
+ * $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc_4.c,v 1.4 2002/10/07 02:56:59 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.
+ */
+
+/* #ident "@(#)rpcb_svc_4.c 1.8 93/07/05 SMI" */
+
+/*
+ * rpcb_svc_4.c
+ * The server procedure for the version 4 rpcbind.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <netconfig.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include "rpcbind.h"
+#include "xlog.h"
+
+static void *rpcbproc_getaddr_4_local(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+static void *rpcbproc_getversaddr_4_local(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+static void *rpcbproc_getaddrlist_4_local(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+static void free_rpcb_entry_list(rpcb_entry_list_ptr *);
+static void *rpcbproc_dump_4_local(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+
+/*
+ * Called by svc_getreqset. There is a separate server handle for
+ * every transport that it waits on.
+ */
+void
+rpcb_service_4(struct svc_req *rqstp, SVCXPRT *transp)
+{
+ union {
+ rpcb rpcbproc_set_4_arg;
+ rpcb rpcbproc_unset_4_arg;
+ rpcb rpcbproc_getaddr_4_local_arg;
+ char *rpcbproc_uaddr2taddr_4_arg;
+ struct netbuf rpcbproc_taddr2uaddr_4_arg;
+ } argument;
+ char *result;
+ xdrproc_t xdr_argument, xdr_result;
+ void *(*local)(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+ rpcprog_t setprog = 0;
+
+ rpcbs_procinfo(RPCBVERS_4_STAT, rqstp->rq_proc);
+
+ switch (rqstp->rq_proc) {
+ case NULLPROC:
+ /*
+ * Null proc call
+ */
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_NULL\n");
+#endif
+ check_access(transp, rqstp->rq_proc, 0, RPCBVERS4);
+ (void) svc_sendreply(transp, (xdrproc_t) xdr_void,
+ (char *)NULL);
+ return;
+
+ case RPCBPROC_SET:
+ /*
+ * Check to see whether the message came from
+ * loopback transports (for security reasons)
+ */
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_bool;
+ local = rpcbproc_set_com;
+ break;
+
+ case RPCBPROC_UNSET:
+ /*
+ * Check to see whether the message came from
+ * loopback transports (for security reasons)
+ */
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_bool;
+ local = rpcbproc_unset_com;
+ break;
+
+ case RPCBPROC_GETADDR:
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_getaddr_4_local;
+ break;
+
+ case RPCBPROC_GETVERSADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_GETVERSADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_getversaddr_4_local;
+ break;
+
+ case RPCBPROC_DUMP:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_DUMP\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_rpcblist_ptr;
+ local = rpcbproc_dump_4_local;
+ break;
+
+ case RPCBPROC_INDIRECT:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_INDIRECT\n");
+#endif
+ rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
+ return;
+
+/* case RPCBPROC_CALLIT: */
+ case RPCBPROC_BCAST:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_BCAST\n");
+#endif
+ rpcbproc_callit_com(rqstp, transp, rqstp->rq_proc, RPCBVERS4);
+ return;
+
+ case RPCBPROC_GETTIME:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_GETTIME\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_u_long;
+ local = rpcbproc_gettime_com;
+ break;
+
+ case RPCBPROC_UADDR2TADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_UADDR2TADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_wrapstring;
+ xdr_result = (xdrproc_t)xdr_netbuf;
+ local = rpcbproc_uaddr2taddr_com;
+ break;
+
+ case RPCBPROC_TADDR2UADDR:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_TADDR2UADDR\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_netbuf;
+ xdr_result = (xdrproc_t)xdr_wrapstring;
+ local = rpcbproc_taddr2uaddr_com;
+ break;
+
+ case RPCBPROC_GETADDRLIST:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_GETADDRLIST\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_rpcb;
+ xdr_result = (xdrproc_t)xdr_rpcb_entry_list_ptr;
+ local = rpcbproc_getaddrlist_4_local;
+ break;
+
+ case RPCBPROC_GETSTAT:
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCBPROC_GETSTAT\n");
+#endif
+ xdr_argument = (xdrproc_t)xdr_void;
+ xdr_result = (xdrproc_t)xdr_rpcb_stat_byvers;
+ local = rpcbproc_getstat;
+ break;
+
+ default:
+ svcerr_noproc(transp);
+ return;
+ }
+ memset((char *)&argument, 0, sizeof (argument));
+ if (!svc_getargs(transp, (xdrproc_t) xdr_argument,
+ (char *)&argument)) {
+ svcerr_decode(transp);
+ if (debugging)
+ (void) xlog(LOG_DEBUG, "rpcbind: could not decode\n");
+ goto done;
+ }
+
+ if (rqstp->rq_proc == RPCBPROC_SET
+ || rqstp->rq_proc == RPCBPROC_UNSET
+ || rqstp->rq_proc == RPCBPROC_GETADDR)
+ setprog = argument.rpcbproc_set_4_arg.r_prog;
+
+ if (!check_access(transp, rqstp->rq_proc, setprog, RPCBVERS4)) {
+ svcerr_weakauth(transp);
+ goto done;
+ }
+ result = (*local)(&argument, rqstp, transp, RPCBVERS4);
+ if (result != NULL && !svc_sendreply(transp, (xdrproc_t) xdr_result,
+ result)) {
+ svcerr_systemerr(transp);
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "rpcbind: svc_sendreply\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+done:
+ if (!svc_freeargs(transp, (xdrproc_t) xdr_argument,
+ (char *)&argument)) {
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+ return;
+}
+
+/*
+ * Lookup the mapping for a program, version and return its
+ * address. Assuming that the caller wants the address of the
+ * server running on the transport on which the request came.
+ * Even if a service with a different version number is available,
+ * it will return that address. The client should check with an
+ * clnt_call to verify whether the service is the one that is desired.
+ * We also try to resolve the universal address in terms of
+ * address of the caller.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t rpcbversnum /*__unused*/)
+{
+ RPCB *regp = (RPCB *)arg;
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ char *uaddr;
+
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
+ svc_getrpccaller(transp));
+ xlog(LOG_DEBUG, "RPCB_GETADDR req for (%lu, %lu, %s) from %s: ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, uaddr);
+ free(uaddr);
+ }
+#endif
+ return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
+ RPCB_ALLVERS));
+}
+
+/*
+ * Lookup the mapping for a program, version and return its
+ * address. Assuming that the caller wants the address of the
+ * server running on the transport on which the request came.
+ *
+ * We also try to resolve the universal address in terms of
+ * address of the caller.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getversaddr_4_local(void *arg, struct svc_req *rqstp, SVCXPRT *transp,
+ rpcvers_t versnum /*__unused*/)
+{
+ RPCB *regp = (RPCB *)arg;
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ char *uaddr;
+
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid),
+ svc_getrpccaller(transp));
+ xlog(LOG_DEBUG, "RPCB_GETVERSADDR rqst for (%lu, %lu, %s)"
+ " from %s : ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, uaddr);
+ free(uaddr);
+ }
+#endif
+ return (rpcbproc_getaddr_com(regp, rqstp, transp, RPCBVERS4,
+ RPCB_ONEVERS));
+}
+
+/*
+ * Lookup the mapping for a program, version and return the
+ * addresses for all transports in the current transport family.
+ * We return a merged address.
+ */
+/* ARGSUSED */
+static void *
+rpcbproc_getaddrlist_4_local(void *arg, struct svc_req *rqstp /*__unused*/,
+ SVCXPRT *transp, rpcvers_t versnum /*__unused*/)
+{
+ RPCB *regp = (RPCB *)arg;
+ static rpcb_entry_list_ptr rlist;
+ register rpcblist_ptr rbl;
+ rpcb_entry_list_ptr rp, tail;
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcb_entry *a;
+ struct netconfig *nconf;
+ struct netconfig *reg_nconf;
+ char *saddr, *maddr = NULL;
+
+ free_rpcb_entry_list(&rlist);
+ tail = NULL;
+ prog = regp->r_prog;
+ vers = regp->r_vers;
+ reg_nconf = rpcbind_get_conf(transp->xp_netid);
+ if (reg_nconf == NULL)
+ return (NULL);
+ if (*(regp->r_addr) != '\0') {
+ saddr = regp->r_addr;
+ } else {
+ saddr = NULL;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ xlog(LOG_DEBUG, "r_addr: %s r_netid: %s nc_protofmly: %s\n",
+ regp->r_addr, regp->r_netid, reg_nconf->nc_protofmly);
+ }
+#endif
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog == prog) &&
+ (rbl->rpcb_map.r_vers == vers)) {
+ nconf = rpcbind_get_conf(rbl->rpcb_map.r_netid);
+ if (nconf == NULL)
+ goto fail;
+ if (strcmp(nconf->nc_protofmly, reg_nconf->nc_protofmly)
+ != 0) {
+ continue; /* not same proto family */
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "\tmerge with: %s\n",
+ rbl->rpcb_map.r_addr);
+#endif
+ if ((maddr = mergeaddr(transp, rbl->rpcb_map.r_netid,
+ rbl->rpcb_map.r_addr, saddr)) == NULL) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, " FAILED\n");
+#endif
+ continue;
+ } else if (!maddr[0]) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, " SUCCEEDED, but port died - maddr: nullstring\n");
+#endif
+ /* The server died. Unset this combination */
+ delete_prog(regp->r_prog);
+ continue;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, " SUCCEEDED maddr: %s\n", maddr);
+#endif
+ /*
+ * Add it to rlist.
+ */
+ rp = malloc(sizeof (rpcb_entry_list));
+ if (rp == NULL)
+ goto fail;
+ a = &rp->rpcb_entry_map;
+ a->r_maddr = maddr;
+ a->r_nc_netid = nconf->nc_netid;
+ a->r_nc_semantics = nconf->nc_semantics;
+ a->r_nc_protofmly = nconf->nc_protofmly;
+ a->r_nc_proto = nconf->nc_proto;
+ rp->rpcb_entry_next = NULL;
+ if (rlist == NULL) {
+ rlist = rp;
+ tail = rp;
+ } else {
+ tail->rpcb_entry_next = rp;
+ tail = rp;
+ }
+ rp = NULL;
+ }
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ for (rp = rlist; rp; rp = rp->rpcb_entry_next) {
+ xlog(LOG_DEBUG, "\t%s %s\n", rp->rpcb_entry_map.r_maddr,
+ rp->rpcb_entry_map.r_nc_proto);
+ }
+ }
+#endif
+ /*
+ * XXX: getaddrlist info is also being stuffed into getaddr.
+ * Perhaps wrong, but better than it not getting counted at all.
+ */
+ rpcbs_getaddr(RPCBVERS4 - 2, prog, vers, transp->xp_netid, maddr);
+ return (void *)&rlist;
+
+fail: free_rpcb_entry_list(&rlist);
+ return (NULL);
+}
+
+/*
+ * Free only the allocated structure, rest is all a pointer to some
+ * other data somewhere else.
+ */
+static void
+free_rpcb_entry_list(rpcb_entry_list_ptr *rlistp)
+{
+ register rpcb_entry_list_ptr rbl, tmp;
+
+ for (rbl = *rlistp; rbl != NULL; ) {
+ tmp = rbl;
+ rbl = rbl->rpcb_entry_next;
+ free((char *)tmp->rpcb_entry_map.r_maddr);
+ free((char *)tmp);
+ }
+ *rlistp = NULL;
+}
+
+/* ARGSUSED */
+static void *
+rpcbproc_dump_4_local(void *arg /*__unused*/, struct svc_req *req /*__unused*/,
+ SVCXPRT *xprt /*__unused*/, rpcvers_t versnum /*__unused*/)
+{
+ return ((void *)&list_rbl);
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcb_svc_com.c
^
|
@@ -0,0 +1,1444 @@
+/* $NetBSD: rpcb_svc_com.c,v 1.9 2002/11/08 00:16:39 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/rpcb_svc_com.c,v 1.11 2003/10/29 09:30:37 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.
+ */
+
+/* #ident "@(#)rpcb_svc_com.c 1.18 94/05/02 SMI" */
+
+/*
+ * rpcb_svc_com.c
+ * The commom server procedure for the rpcbind.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <poll.h>
+#include <bits/poll.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/svc_dg.h>
+#include <netconfig.h>
+#include <errno.h>
+#include <syslog.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <time.h>
+#ifdef PORTMAP
+#include <netinet/in.h>
+#include <rpc/pmap_prot.h>
+#endif /* PORTMAP */
+#include <string.h>
+#include <stdlib.h>
+
+#include "rpcbind.h"
+#include "xlog.h"
+
+#define RPC_BUF_MAX 65536 /* can be raised if required */
+
+
+# define POLLRDNORM 0x040 /* Normal data may be read. */
+# define POLLRDBAND 0x080 /* Priority data may be read. */
+
+
+
+static char *nullstring = "";
+static int rpcb_rmtcalls;
+
+struct rmtcallfd_list {
+ int fd;
+ SVCXPRT *xprt;
+ char *netid;
+ struct rmtcallfd_list *next;
+};
+
+#define NFORWARD 64
+#define MAXTIME_OFF 300 /* 5 minutes */
+
+struct finfo {
+ int flag;
+#define FINFO_ACTIVE 0x1
+ u_int32_t caller_xid;
+ struct netbuf *caller_addr;
+ u_int32_t forward_xid;
+ int forward_fd;
+ char *uaddr;
+ rpcproc_t reply_type;
+ rpcvers_t versnum;
+ time_t time;
+};
+static struct finfo FINFO[NFORWARD];
+
+
+static bool_t xdr_encap_parms(XDR *, struct encap_parms *);
+static bool_t xdr_rmtcall_args(XDR *, struct r_rmtcall_args *);
+static bool_t xdr_rmtcall_result(XDR *, struct r_rmtcall_args *);
+static bool_t xdr_opaque_parms(XDR *, struct r_rmtcall_args *);
+static int find_rmtcallfd_by_netid(char *);
+static SVCXPRT *find_rmtcallxprt_by_fd(int);
+static int forward_register(u_int32_t, struct netbuf *, int, char *,
+ rpcproc_t, rpcvers_t, u_int32_t *);
+static struct finfo *forward_find(u_int32_t);
+static int free_slot_by_xid(u_int32_t);
+static int free_slot_by_index(int);
+static int netbufcmp(struct netbuf *, struct netbuf *);
+static struct netbuf *netbufdup(struct netbuf *);
+static void netbuffree(struct netbuf *);
+static int check_rmtcalls(struct pollfd *, int);
+static void xprt_set_caller(SVCXPRT *, struct finfo *);
+static void send_svcsyserr(SVCXPRT *, struct finfo *);
+static void handle_reply(int, SVCXPRT *);
+static void find_versions(rpcprog_t, char *, rpcvers_t *, rpcvers_t *);
+static rpcblist_ptr find_service(rpcprog_t, rpcvers_t, char *);
+static char *getowner(SVCXPRT *, char *, size_t);
+static int add_pmaplist(RPCB *);
+static int del_pmaplist(RPCB *);
+
+/*
+ * Set a mapping of program, version, netid
+ */
+/* ARGSUSED */
+void *
+rpcbproc_set_com(void *arg, struct svc_req *rqstp /*__unused*/, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ RPCB *regp = (RPCB *)arg;
+ static bool_t ans;
+ char owner[64];
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCB_SET request for (%lu, %lu, %s, %s) : ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid, regp->r_addr);
+#endif
+ ans = map_set(regp, getowner(transp, owner, sizeof owner));
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCB_SET: %s", ans == TRUE ? "succeeded" : "failed");
+#endif
+ /* XXX: should have used some defined constant here */
+ rpcbs_set(rpcbversnum - 2, ans);
+ return (void *)&ans;
+}
+
+bool_t
+map_set(RPCB *regp, char *owner)
+{
+ RPCB reg, *a;
+ rpcblist_ptr rbl, fnd;
+
+ reg = *regp;
+ /*
+ * check to see if already used
+ * find_service returns a hit even if
+ * the versions don't match, so check for it
+ */
+ fnd = find_service(reg.r_prog, reg.r_vers, reg.r_netid);
+ if (fnd && (fnd->rpcb_map.r_vers == reg.r_vers)) {
+ if (!strcmp(fnd->rpcb_map.r_addr, reg.r_addr))
+ /*
+ * if these match then it is already
+ * registered so just say "OK".
+ */
+ return (TRUE);
+ else
+ return (FALSE);
+ }
+ /*
+ * add to the end of the list
+ */
+ rbl = malloc(sizeof (RPCBLIST));
+ if (rbl == NULL)
+ return (FALSE);
+ a = &(rbl->rpcb_map);
+ a->r_prog = reg.r_prog;
+ a->r_vers = reg.r_vers;
+ a->r_netid = strdup(reg.r_netid);
+ a->r_addr = strdup(reg.r_addr);
+ a->r_owner = strdup(owner);
+ if (!a->r_addr || !a->r_netid || !a->r_owner) {
+ if (a->r_netid)
+ free(a->r_netid);
+ if (a->r_addr)
+ free(a->r_addr);
+ if (a->r_owner)
+ free(a->r_owner);
+ free(rbl);
+ return (FALSE);
+ }
+ rbl->rpcb_next = (rpcblist_ptr)NULL;
+ if (list_rbl == NULL) {
+ list_rbl = rbl;
+ } else {
+ for (fnd = list_rbl; fnd->rpcb_next;
+ fnd = fnd->rpcb_next)
+ ;
+ fnd->rpcb_next = rbl;
+ }
+#ifdef PORTMAP
+ (void) add_pmaplist(regp);
+#endif
+ return (TRUE);
+}
+
+/*
+ * Unset a mapping of program, version, netid
+ */
+/* ARGSUSED */
+void *
+rpcbproc_unset_com(void *arg, struct svc_req *rqstp /*__unused*/, SVCXPRT *transp,
+ rpcvers_t rpcbversnum)
+{
+ RPCB *regp = (RPCB *)arg;
+ static bool_t ans;
+ char owner[64];
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCB_UNSET request for (%lu, %lu, %s) : ",
+ (unsigned long)regp->r_prog, (unsigned long)regp->r_vers,
+ regp->r_netid);
+#endif
+
+ ans = map_unset(regp, getowner(transp, owner, sizeof owner));
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "RPCB_UNSET: %s", ans == TRUE ? "succeeded" : "failed");
+#endif
+ /* XXX: should have used some defined constant here */
+ rpcbs_unset(rpcbversnum - 2, ans);
+ return (void *)&ans;
+}
+
+bool_t
+map_unset(RPCB *regp, char *owner)
+{
+ int ans = 0;
+ rpcblist_ptr rbl, prev, tmp;
+
+ if (owner == NULL)
+ return (0);
+
+ for (prev = NULL, rbl = list_rbl; rbl; /* cstyle */) {
+ if ((rbl->rpcb_map.r_prog != regp->r_prog) ||
+ (rbl->rpcb_map.r_vers != regp->r_vers) ||
+ (regp->r_netid[0] && strcasecmp(regp->r_netid,
+ rbl->rpcb_map.r_netid))) {
+ /* both rbl & prev move forwards */
+ prev = rbl;
+ rbl = rbl->rpcb_next;
+ continue;
+ }
+ /*
+ * Check whether appropriate uid. Unset only
+ * if superuser or the owner itself.
+ */
+#ifdef RPCBIND_DEBUG
+ xlog(LOG_DEBUG,"Suppression RPC_UNSET(map_unset) ");
+ xlog(LOG_DEBUG,"rbl->rpcb_map.r_owner=%s ",rbl->rpcb_map.r_owner);
+ xlog(LOG_DEBUG,"owner=%s ",owner);
+#endif
+ if (strcmp(owner, "superuser") &&
+ strcmp(rbl->rpcb_map.r_owner, owner))
+ return (0);
+ /* found it; rbl moves forward, prev stays */
+ ans = 1;
+ tmp = rbl;
+ rbl = rbl->rpcb_next;
+ if (prev == NULL)
+ list_rbl = rbl;
+ else
+ prev->rpcb_next = rbl;
+ free(tmp->rpcb_map.r_addr);
+ free(tmp->rpcb_map.r_netid);
+ free(tmp->rpcb_map.r_owner);
+ free(tmp);
+ }
+#ifdef PORTMAP
+ if (ans)
+ (void) del_pmaplist(regp);
+#endif
+ /*
+ * We return 1 either when the entry was not there or it
+ * was able to unset it. It can come to this point only if
+ * atleast one of the conditions is true.
+ */
+ return (1);
+}
+
+void
+delete_prog(unsigned int prog)
+{
+ RPCB reg;
+ register rpcblist_ptr rbl;
+
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog != prog))
+ continue;
+ if (is_bound(rbl->rpcb_map.r_netid, rbl->rpcb_map.r_addr))
+ continue;
+ reg.r_prog = rbl->rpcb_map.r_prog;
+ reg.r_vers = rbl->rpcb_map.r_vers;
+ reg.r_netid = strdup(rbl->rpcb_map.r_netid);
+ (void) map_unset(®, "superuser");
+ free(reg.r_netid);
+ }
+}
+
+void *
+rpcbproc_getaddr_com(RPCB *regp, struct svc_req *rqstp /*__unused*/,
+ SVCXPRT *transp, rpcvers_t rpcbversnum, rpcvers_t verstype)
+{
+ static char *uaddr;
+ char *saddr = NULL;
+ rpcblist_ptr fnd;
+
+ if (uaddr != NULL && uaddr != nullstring) {
+ free(uaddr);
+ uaddr = NULL;
+ }
+ fnd = find_service(regp->r_prog, regp->r_vers, transp->xp_netid);
+ if (fnd && ((verstype == RPCB_ALLVERS) ||
+ (regp->r_vers == fnd->rpcb_map.r_vers))) {
+ if (*(regp->r_addr) != '\0') { /* may contain a hint about */
+ saddr = regp->r_addr; /* the interface that we */
+ } /* should use */
+ if (!(uaddr = mergeaddr(transp, transp->xp_netid,
+ fnd->rpcb_map.r_addr, saddr))) {
+ /* Try whatever we have */
+ uaddr = strdup(fnd->rpcb_map.r_addr);
+ } else if (!uaddr[0]) {
+ /*
+ * The server died. Unset all versions of this prog.
+ */
+ delete_prog(regp->r_prog);
+ uaddr = nullstring;
+ }
+ } else {
+ uaddr = nullstring;
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "getaddr: %s", uaddr);
+#endif
+ /* XXX: should have used some defined constant here */
+ rpcbs_getaddr(rpcbversnum - 2, regp->r_prog, regp->r_vers,
+ transp->xp_netid, uaddr);
+ return (void *)&uaddr;
+}
+
+/* ARGSUSED */
+void *
+rpcbproc_gettime_com(void *arg /*__unused*/, struct svc_req *rqstp /*__unused*/,
+ SVCXPRT *transp /*__unused*/, rpcvers_t rpcbversnum /*__unused*/)
+{
+ static time_t curtime;
+
+ (void) time(&curtime);
+ return (void *)&curtime;
+}
+
+/*
+ * Convert uaddr to taddr. Should be used only by
+ * local servers/clients. (kernel level stuff only)
+ */
+/* ARGSUSED */
+void *
+rpcbproc_uaddr2taddr_com(void *arg, struct svc_req *rqstp /*__unused*/,
+ SVCXPRT *transp, rpcvers_t rpcbversnum /*__unused*/)
+{
+ char **uaddrp = (char **)arg;
+ struct netconfig *nconf;
+ static struct netbuf nbuf;
+ static struct netbuf *taddr;
+
+ if (taddr) {
+ free(taddr->buf);
+ free(taddr);
+ taddr = NULL;
+ }
+ if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
+ ((taddr = uaddr2taddr(nconf, *uaddrp)) == NULL)) {
+ (void) memset((char *)&nbuf, 0, sizeof (struct netbuf));
+ return (void *)&nbuf;
+ }
+ return (void *)taddr;
+}
+
+/*
+ * Convert taddr to uaddr. Should be used only by
+ * local servers/clients. (kernel level stuff only)
+ */
+/* ARGSUSED */
+void *
+rpcbproc_taddr2uaddr_com(void *arg, struct svc_req *rqstp /*__unused*/,
+ SVCXPRT *transp, rpcvers_t rpcbversnum /*__unused*/)
+{
+ struct netbuf *taddr = (struct netbuf *)arg;
+ static char *uaddr;
+ struct netconfig *nconf;
+
+#ifdef CHEW_FDS
+ int fd;
+
+ if ((fd = open("/dev/null", O_RDONLY)) == -1) {
+ uaddr = (char *)strerror(errno);
+ return (&uaddr);
+ }
+#endif /* CHEW_FDS */
+ if (uaddr != NULL && uaddr != nullstring) {
+ free(uaddr);
+ uaddr = NULL;
+ }
+ if (((nconf = rpcbind_get_conf(transp->xp_netid)) == NULL) ||
+ ((uaddr = taddr2uaddr(nconf, taddr)) == NULL)) {
+ uaddr = nullstring;
+ }
+ return (void *)&uaddr;
+}
+
+
+static bool_t
+xdr_encap_parms(XDR *xdrs, struct encap_parms *epp)
+{
+ return (xdr_bytes(xdrs, &(epp->args), (u_int *) &(epp->arglen), ~0));
+}
+
+/*
+ * XDR remote call arguments. It ignores the address part.
+ * written for XDR_DECODE direction only
+ */
+static bool_t
+xdr_rmtcall_args(XDR *xdrs, struct r_rmtcall_args *cap)
+{
+ /* does not get the address or the arguments */
+ if (xdr_u_int32_t(xdrs, &(cap->rmt_prog)) &&
+ xdr_u_int32_t(xdrs, &(cap->rmt_vers)) &&
+ xdr_u_int32_t(xdrs, &(cap->rmt_proc))) {
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR remote call results along with the address. Ignore
+ * program number, version number and proc number.
+ * Written for XDR_ENCODE direction only.
+ */
+static bool_t
+xdr_rmtcall_result(XDR *xdrs, struct r_rmtcall_args *cap)
+{
+ bool_t result;
+
+#ifdef PORTMAP
+ if (cap->rmt_localvers == PMAPVERS) {
+ int h1, h2, h3, h4, p1, p2;
+ u_long port;
+
+ /* interpret the universal address for TCP/IP */
+ if (sscanf(cap->rmt_uaddr, "%d.%d.%d.%d.%d.%d",
+ &h1, &h2, &h3, &h4, &p1, &p2) != 6)
+ return (FALSE);
+ port = ((p1 & 0xff) << 8) + (p2 & 0xff);
+ result = xdr_u_long(xdrs, &port);
+ } else
+#endif
+ if ((cap->rmt_localvers == RPCBVERS) ||
+ (cap->rmt_localvers == RPCBVERS4)) {
+ result = xdr_wrapstring(xdrs, &(cap->rmt_uaddr));
+ } else {
+ return (FALSE);
+ }
+ if (result == TRUE)
+ return (xdr_encap_parms(xdrs, &(cap->rmt_args)));
+ return (FALSE);
+}
+
+/*
+ * only worries about the struct encap_parms part of struct r_rmtcall_args.
+ * The arglen must already be set!!
+ */
+static bool_t
+xdr_opaque_parms(XDR *xdrs, struct r_rmtcall_args *cap)
+{
+ return (xdr_opaque(xdrs, cap->rmt_args.args, cap->rmt_args.arglen));
+}
+
+static struct rmtcallfd_list *rmthead;
+static struct rmtcallfd_list *rmttail;
+
+int
+create_rmtcall_fd(struct netconfig *nconf)
+{
+ int fd;
+ struct rmtcallfd_list *rmt;
+ SVCXPRT *xprt;
+
+ if ((fd = __rpc_nconf2fd(nconf)) == -1) {
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "create_rmtcall_fd: couldn't open \"%s\" (errno %d)\n",
+ nconf->nc_device, errno);
+ return (-1);
+ }
+ xprt = svc_tli_create(fd, 0, (struct t_bind *) 0, 0, 0);
+ if (xprt == NULL) {
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "create_rmtcall_fd: svc_tli_create failed\n");
+ return (-1);
+ }
+ rmt = malloc(sizeof (struct rmtcallfd_list));
+ if (rmt == NULL) {
+ syslog(LOG_ERR, "create_rmtcall_fd: no memory!");
+ return (-1);
+ }
+ rmt->xprt = xprt;
+ rmt->netid = strdup(nconf->nc_netid);
+ xprt->xp_netid = rmt->netid;
+ rmt->fd = fd;
+ rmt->next = NULL;
+ if (rmthead == NULL) {
+ rmthead = rmt;
+ rmttail = rmt;
+ } else {
+ rmttail->next = rmt;
+ rmttail = rmt;
+ }
+ return (fd);
+}
+
+static int
+find_rmtcallfd_by_netid(char *netid)
+{
+ struct rmtcallfd_list *rmt;
+
+ for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
+ if (strcmp(netid, rmt->netid) == 0) {
+ return (rmt->fd);
+ }
+ }
+ return (-1);
+}
+
+static SVCXPRT *
+find_rmtcallxprt_by_fd(int fd)
+{
+ struct rmtcallfd_list *rmt;
+
+ for (rmt = rmthead; rmt != NULL; rmt = rmt->next) {
+ if (fd == rmt->fd) {
+ return (rmt->xprt);
+ }
+ }
+ return (NULL);
+}
+
+
+/*
+ * Call a remote procedure service. This procedure is very quiet when things
+ * go wrong. The proc is written to support broadcast rpc. In the broadcast
+ * case, a machine should shut-up instead of complain, lest the requestor be
+ * overrun with complaints at the expense of not hearing a valid reply.
+ * When receiving a request and verifying that the service exists, we
+ *
+ * receive the request
+ *
+ * open a new TLI endpoint on the same transport on which we received
+ * the original request
+ *
+ * remember the original request's XID (which requires knowing the format
+ * of the svc_dg_data structure)
+ *
+ * forward the request, with a new XID, to the requested service,
+ * remembering the XID used to send this request (for later use in
+ * reassociating the answer with the original request), the requestor's
+ * address, the file descriptor on which the forwarded request is
+ * made and the service's address.
+ *
+ * mark the file descriptor on which we anticipate receiving a reply from
+ * the service and one to select for in our private svc_run procedure
+ *
+ * At some time in the future, a reply will be received from the service to
+ * which we forwarded the request. At that time, we detect that the socket
+ * used was for forwarding (by looking through the finfo structures to see
+ * whether the fd corresponds to one of those) and call handle_reply() to
+ *
+ * receive the reply
+ *
+ * bundle the reply, along with the service's universal address
+ *
+ * create a SVCXPRT structure and use a version of svc_sendreply
+ * that allows us to specify the reply XID and destination, send the reply
+ * to the original requestor.
+ */
+
+void
+rpcbproc_callit_com(struct svc_req *rqstp, SVCXPRT *transp,
+ rpcproc_t reply_type, rpcvers_t versnum)
+{
+ register rpcblist_ptr rbl;
+ struct netconfig *nconf;
+ struct netbuf *caller;
+ struct r_rmtcall_args a;
+ char outbuf[RPC_BUF_MAX];
+ struct netbuf *na = (struct netbuf *) NULL;
+ struct rpc_msg call_msg;
+ int outlen;
+ u_int sendsz;
+ XDR outxdr;
+ AUTH *auth;
+ int fd = -1;
+ char *uaddr, *m_uaddr = NULL, *local_uaddr = NULL;
+ u_int32_t *xidp;
+ struct __rpc_sockinfo si;
+ struct sockaddr *localsa;
+ struct netbuf tbuf;
+ int size = 0;
+ if (!__rpc_fd2sockinfo(transp->xp_fd, &si)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ return;
+ }
+ if (si.si_socktype != SOCK_DGRAM)
+ return; /* Only datagram type accepted */
+ sendsz = UDPMSGSIZE;
+
+ call_msg.rm_xid = 0; /* For error checking purposes */
+ memset(&a, 0, sizeof(a)); /* Zero out the input buffer */
+ if (!svc_getargs(transp, (xdrproc_t) xdr_rmtcall_args, (char *) &a)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_decode(transp);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: svc_getargs failed\n");
+ goto error;
+ }
+
+ if (!check_callit(transp, &a, versnum)) {
+ svcerr_weakauth(transp);
+ goto error;
+ }
+
+ caller = svc_getrpccaller(transp);
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ uaddr = taddr2uaddr(rpcbind_get_conf(transp->xp_netid), caller);
+ xlog(LOG_DEBUG, "%s %s req for (%lu, %lu, %lu, %s) from %s : ",
+ versnum == PMAPVERS ? "pmap_rmtcall" :
+ versnum == RPCBVERS ? "rpcb_rmtcall" :
+ versnum == RPCBVERS4 ? "rpcb_indirect" : "unknown",
+ reply_type == RPCBPROC_INDIRECT ? "indirect" : "callit",
+ (unsigned long)a.rmt_prog, (unsigned long)a.rmt_vers,
+ (unsigned long)a.rmt_proc, transp->xp_netid,
+ uaddr ? uaddr : "unknown");
+ if (uaddr)
+ free(uaddr);
+ }
+#endif
+
+ rbl = find_service(a.rmt_prog, a.rmt_vers, transp->xp_netid);
+
+ rpcbs_rmtcall(versnum - 2, reply_type, a.rmt_prog, a.rmt_vers,
+ a.rmt_proc, transp->xp_netid, rbl);
+ if (rbl == (rpcblist_ptr)NULL) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "prog %lu vers %lu: not found\n",
+ a.rmt_prog, a.rmt_vers);
+#endif
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_noprog(transp);
+ goto error;
+ }
+ if (rbl->rpcb_map.r_vers != a.rmt_vers) {
+ if (reply_type == RPCBPROC_INDIRECT) {
+ rpcvers_t vers_low, vers_high;
+
+ find_versions(a.rmt_prog, transp->xp_netid,
+ &vers_low, &vers_high);
+ svcerr_progvers(transp, vers_low, vers_high);
+ }
+ goto error;
+ }
+
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "found at uaddr %s\n", rbl->rpcb_map.r_addr);
+#endif
+ /*
+ * Check whether this entry is valid and a server is present
+ * Mergeaddr() returns NULL if no such entry is present, and
+ * returns "" if the entry was present but the server is not
+ * present (i.e., it crashed).
+ */
+ if (reply_type == RPCBPROC_INDIRECT) {
+ uaddr = mergeaddr(transp, transp->xp_netid,
+ rbl->rpcb_map.r_addr, NULL);
+ if (uaddr == NULL || uaddr[0] == '\0') {
+ svcerr_noprog(transp);
+ if (uaddr != NULL)
+ free(uaddr);
+ goto error;
+ }
+ free(uaddr);
+ }
+ nconf = rpcbind_get_conf(transp->xp_netid);
+ if (nconf == (struct netconfig *)NULL) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: rpcbind_get_conf failed\n");
+ goto error;
+ }
+ localsa = local_sa(((struct sockaddr *)caller->buf)->sa_family);
+ if (localsa == NULL) {
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: no local address\n");
+ goto error;
+ }
+
+ switch(localsa->sa_family){
+ case AF_INET:
+ size = sizeof(struct sockaddr_in);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ }
+ tbuf.len = tbuf.maxlen = size;
+ tbuf.buf = localsa;
+ local_uaddr =
+ addrmerge(&tbuf, rbl->rpcb_map.r_addr, NULL, nconf->nc_netid);
+ m_uaddr = addrmerge(caller, rbl->rpcb_map.r_addr, NULL,
+ nconf->nc_netid);
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, "merged uaddr %s\n", m_uaddr);
+#endif
+ if ((fd = find_rmtcallfd_by_netid(nconf->nc_netid)) == -1) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ goto error;
+ }
+ xidp = __rpcb_get_dg_xidp(transp);
+ switch (forward_register(*xidp, caller, fd, m_uaddr, reply_type,
+ versnum, &call_msg.rm_xid)) {
+ case 1:
+ /* Success; forward_register() will free m_uaddr for us. */
+ m_uaddr = NULL;
+ break;
+ case 0:
+ /*
+ * A duplicate request for the slow server. Let's not
+ * beat on it any more.
+ */
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: duplicate request\n");
+ goto error;
+ case -1:
+ /* forward_register failed. Perhaps no memory. */
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: forward_register failed\n");
+ goto error;
+ }
+
+#ifdef DEBUG_RMTCALL
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: original XID %x, new XID %x\n",
+ *xidp, call_msg.rm_xid);
+#endif
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = a.rmt_prog;
+ call_msg.rm_call.cb_vers = a.rmt_vers;
+
+ memset(outbuf, '\0', sendsz); /* Zero out the output buffer */
+ xdrmem_create(&outxdr, outbuf, sendsz, XDR_ENCODE);
+
+ if (!xdr_callhdr(&outxdr, &call_msg)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: xdr_callhdr failed\n");
+ goto error;
+ }
+ if (!xdr_u_int32_t(&outxdr, &(a.rmt_proc))) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: xdr_u_long failed\n");
+ goto error;
+ }
+
+ if (rqstp->rq_cred.oa_flavor == AUTH_NULL) {
+ auth = authnone_create();
+ } else if (rqstp->rq_cred.oa_flavor == AUTH_SYS) {
+ struct authunix_parms *au;
+
+ au = (struct authunix_parms *)rqstp->rq_clntcred;
+ auth = authunix_create(au->aup_machname,
+ au->aup_uid, au->aup_gid,
+ au->aup_len, au->aup_gids);
+ if (auth == NULL) /* fall back */
+ auth = authnone_create();
+ } else {
+ /* we do not support any other authentication scheme */
+ if (debugging)
+ xlog(LOG_DEBUG,
+"rpcbproc_callit_com: oa_flavor != AUTH_NONE and oa_flavor != AUTH_SYS\n");
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_weakauth(transp); /* XXX too strong.. */
+ goto error;
+ }
+ if (auth == NULL) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: authwhatever_create returned NULL\n");
+ goto error;
+ }
+ if (!AUTH_MARSHALL(auth, &outxdr)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ AUTH_DESTROY(auth);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: AUTH_MARSHALL failed\n");
+ goto error;
+ }
+ AUTH_DESTROY(auth);
+ if (!xdr_opaque_parms(&outxdr, &a)) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: xdr_opaque_parms failed\n");
+ goto error;
+ }
+ outlen = (int) XDR_GETPOS(&outxdr);
+
+ na = uaddr2taddr(nconf, local_uaddr);
+ if (!na) {
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ goto error;
+ }
+
+ if (sendto(fd, outbuf, outlen, 0, (struct sockaddr *)na->buf, na->len)
+ != outlen) {
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "rpcbproc_callit_com: sendto failed: errno %d\n", errno);
+ if (reply_type == RPCBPROC_INDIRECT)
+ svcerr_systemerr(transp);
+ goto error;
+ }
+ goto out;
+
+error:
+ if (call_msg.rm_xid != 0)
+ (void) free_slot_by_xid(call_msg.rm_xid);
+out:
+ if (!svc_freeargs(transp, (xdrproc_t) xdr_rmtcall_args, (char *) &a)) {
+ if (debugging) {
+ (void) xlog(LOG_DEBUG, "unable to free arguments\n");
+ if (doabort) {
+ rpcbind_abort();
+ }
+ }
+ }
+ if (local_uaddr)
+ free(local_uaddr);
+ if (na) {
+ free(na->buf);
+ free(na);
+ }
+ if (m_uaddr != NULL)
+ free(m_uaddr);
+}
+
+/*
+ * Makes an entry into the FIFO for the given request.
+ * Returns 1 on success, 0 if this is a duplicate request, or -1 on error.
+ * *callxidp is set to the xid of the call.
+ */
+static int
+forward_register(u_int32_t caller_xid, struct netbuf *caller_addr,
+ int forward_fd, char *uaddr, rpcproc_t reply_type,
+ rpcvers_t versnum, u_int32_t *callxidp)
+{
+ int i;
+ int j = 0;
+ time_t min_time, time_now;
+ static u_int32_t lastxid;
+ int entry = -1;
+
+ min_time = FINFO[0].time;
+ time_now = time((time_t *)0);
+ /* initialization */
+ if (lastxid == 0)
+ lastxid = time_now * NFORWARD;
+
+ /*
+ * Check if it is a duplicate entry. Then,
+ * try to find an empty slot. If not available, then
+ * use the slot with the earliest time.
+ */
+ for (i = 0; i < NFORWARD; i++) {
+ if (FINFO[i].flag & FINFO_ACTIVE) {
+ if ((FINFO[i].caller_xid == caller_xid) &&
+ (FINFO[i].reply_type == reply_type) &&
+ (FINFO[i].versnum == versnum) &&
+ (!netbufcmp(FINFO[i].caller_addr,
+ caller_addr))) {
+ FINFO[i].time = time((time_t *)0);
+ return (0); /* Duplicate entry */
+ } else {
+ /* Should we wait any longer */
+ if ((time_now - FINFO[i].time) > MAXTIME_OFF)
+ (void) free_slot_by_index(i);
+ }
+ }
+ if (entry == -1) {
+ if ((FINFO[i].flag & FINFO_ACTIVE) == 0) {
+ entry = i;
+ } else if (FINFO[i].time < min_time) {
+ j = i;
+ min_time = FINFO[i].time;
+ }
+ }
+ }
+ if (entry != -1) {
+ /* use this empty slot */
+ j = entry;
+ } else {
+ (void) free_slot_by_index(j);
+ }
+ if ((FINFO[j].caller_addr = netbufdup(caller_addr)) == NULL) {
+ return (-1);
+ }
+ rpcb_rmtcalls++; /* no of pending calls */
+ FINFO[j].flag = FINFO_ACTIVE;
+ FINFO[j].reply_type = reply_type;
+ FINFO[j].versnum = versnum;
+ FINFO[j].time = time_now;
+ FINFO[j].caller_xid = caller_xid;
+ FINFO[j].forward_fd = forward_fd;
+ /*
+ * Though uaddr is not allocated here, it will still be freed
+ * from free_slot_*().
+ */
+ FINFO[j].uaddr = uaddr;
+ lastxid = lastxid + NFORWARD;
+ /* Don't allow a zero xid below. */
+ if ((u_int32_t)(lastxid + NFORWARD) <= NFORWARD)
+ lastxid = NFORWARD;
+ FINFO[j].forward_xid = lastxid + j; /* encode slot */
+ *callxidp = FINFO[j].forward_xid; /* forward on this xid */
+ return (1);
+}
+
+static struct finfo *
+forward_find(u_int32_t reply_xid)
+{
+ int i;
+
+ i = reply_xid % (u_int32_t)NFORWARD;
+ if ((FINFO[i].flag & FINFO_ACTIVE) &&
+ (FINFO[i].forward_xid == reply_xid)) {
+ return (&FINFO[i]);
+ }
+ return (NULL);
+}
+
+static int
+free_slot_by_xid(u_int32_t xid)
+{
+ int entry;
+
+ entry = xid % (u_int32_t)NFORWARD;
+ return (free_slot_by_index(entry));
+}
+
+static int
+free_slot_by_index(int index)
+{
+ struct finfo *fi;
+
+ fi = &FINFO[index];
+ if (fi->flag & FINFO_ACTIVE) {
+ netbuffree(fi->caller_addr);
+ free(fi->uaddr);
+ fi->flag &= ~FINFO_ACTIVE;
+ rpcb_rmtcalls--;
+ return (1);
+ }
+ return (0);
+}
+
+static int
+netbufcmp(struct netbuf *n1, struct netbuf *n2)
+{
+ return ((n1->len != n2->len) || memcmp(n1->buf, n2->buf, n1->len));
+}
+
+static struct netbuf *
+netbufdup(struct netbuf *ap)
+{
+ struct netbuf *np;
+
+ if ((np = malloc(sizeof(struct netbuf))) == NULL)
+ return (NULL);
+ if ((np->buf = malloc(ap->len)) == NULL) {
+ free(np);
+ return (NULL);
+ }
+ np->maxlen = np->len = ap->len;
+ memcpy(np->buf, ap->buf, ap->len);
+ return (np);
+}
+
+static void
+netbuffree(struct netbuf *ap)
+{
+ free(ap->buf);
+ free(ap);
+}
+
+
+void
+my_svc_run()
+{
+ int poll_ret, check_ret;
+
+ for (;;) {
+ struct pollfd my_pollfd[svc_max_pollfd];
+ int i;
+
+ if (svc_max_pollfd == 0 && svc_pollfd == NULL)
+ return;
+
+
+ for (i = 0; i < svc_max_pollfd; ++i)
+ {
+ my_pollfd[i].fd = svc_pollfd[i].fd;
+ my_pollfd[i].events = svc_pollfd[i].events;
+ my_pollfd[i].revents = 0;
+ }
+
+ switch (poll_ret = poll(my_pollfd, svc_max_pollfd, 30 * 1000)) {
+ case -1:
+ /*
+ * We ignore all errors, continuing with the assumption
+ * that it was set by the signal handlers (or any
+ * other outside event) and not caused by poll().
+ */
+ case 0:
+ continue;
+ default:
+ /*
+ * If we found as many replies on callback fds
+ * as the number of descriptors selectable which
+ * poll() returned, there can be no more so we
+ * don't call svc_getreq_poll. Otherwise, there
+ * must be another so we must call svc_getreq_poll.
+ */
+ if ((check_ret = check_rmtcalls(my_pollfd, svc_max_pollfd)) ==
+ poll_ret)
+ continue;
+ svc_getreq_poll(my_pollfd, poll_ret-check_ret);
+ }
+ }
+}
+
+static int
+check_rmtcalls(struct pollfd *pfds, int nfds)
+{
+ int j, ncallbacks_found = 0, rmtcalls_pending;
+ SVCXPRT *xprt;
+
+ if (rpcb_rmtcalls == 0)
+ return (0);
+
+ rmtcalls_pending = rpcb_rmtcalls;
+ for (j = 0; j < nfds; j++) {
+ if ((xprt = find_rmtcallxprt_by_fd(pfds[j].fd)) != NULL) {
+ if (pfds[j].revents) {
+ ncallbacks_found++;
+#ifdef DEBUG_RMTCALL
+ if (debugging)
+ xlog(LOG_DEBUG,
+"my_svc_run: polled on forwarding fd %d, netid %s - calling handle_reply\n",
+ pfds[j].fd, xprt->xp_netid);
+#endif
+ handle_reply(pfds[j].fd, xprt);
+ pfds[j].revents = 0;
+ if (ncallbacks_found >= rmtcalls_pending) {
+ break;
+ }
+ }
+ }
+ }
+ return (ncallbacks_found);
+}
+
+/*
+ * This is really a helper function defined in libtirpc,
+ * but unfortunately, it hasn't been exported yet.
+ */
+static 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_alloc(len);
+ if (nb->buf == NULL)
+ return NULL;
+
+ nb->maxlen = nb->len = len;
+ }
+ memcpy(nb->buf, ptr, len);
+ return nb;
+}
+
+static void
+xprt_set_caller(SVCXPRT *xprt, struct finfo *fi)
+{
+ const struct netbuf *caller = fi->caller_addr;
+ u_int32_t *xidp;
+
+ __rpc_set_netbuf(svc_getrpccaller(xprt), caller->buf, caller->len);
+ xidp = __rpcb_get_dg_xidp(xprt);
+ *xidp = fi->caller_xid;
+}
+
+/*
+ * Call svcerr_systemerr() only if RPCBVERS4
+ */
+static void
+send_svcsyserr(SVCXPRT *xprt, struct finfo *fi)
+{
+ if (fi->reply_type == RPCBPROC_INDIRECT) {
+ xprt_set_caller(xprt, fi);
+ svcerr_systemerr(xprt);
+ }
+ return;
+}
+
+extern SVCAUTH svc_auth_none;
+
+static void
+handle_reply(int fd, SVCXPRT *xprt)
+{
+ XDR reply_xdrs;
+ struct rpc_msg reply_msg;
+ struct rpc_err reply_error;
+ char *buffer;
+ struct finfo *fi;
+ int inlen, pos, len;
+ struct r_rmtcall_args a;
+ struct sockaddr_storage ss;
+ socklen_t fromlen;
+
+ buffer = malloc(RPC_BUF_MAX);
+ if (buffer == NULL)
+ goto done;
+
+ do {
+ fromlen = sizeof(ss);
+ inlen = recvfrom(fd, buffer, RPC_BUF_MAX, 0,
+ (struct sockaddr *)&ss, &fromlen);
+ } while (inlen < 0 && errno == EINTR);
+ if (inlen < 0) {
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "handle_reply: recvfrom returned %d, errno %d\n", inlen, errno);
+ goto done;
+ }
+
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = 0;
+ reply_msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+
+ xdrmem_create(&reply_xdrs, buffer, (u_int)inlen, XDR_DECODE);
+ if (!xdr_replymsg(&reply_xdrs, &reply_msg)) {
+ if (debugging)
+ (void) xlog(LOG_DEBUG,
+ "handle_reply: xdr_replymsg failed\n");
+ goto done;
+ }
+ fi = forward_find(reply_msg.rm_xid);
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ xlog(LOG_DEBUG, "handle_reply: reply xid: %d fi addr: %p\n",
+ reply_msg.rm_xid, fi);
+ }
+#endif
+ if (fi == NULL) {
+ goto done;
+ }
+ _seterr_reply(&reply_msg, &reply_error);
+ if (reply_error.re_status != RPC_SUCCESS) {
+ if (debugging)
+ (void) xlog(LOG_DEBUG, "handle_reply: %s\n",
+ clnt_sperrno(reply_error.re_status));
+ send_svcsyserr(xprt, fi);
+ goto done;
+ }
+ pos = XDR_GETPOS(&reply_xdrs);
+ len = inlen - pos;
+ a.rmt_args.args = &buffer[pos];
+ a.rmt_args.arglen = len;
+ a.rmt_uaddr = fi->uaddr;
+ a.rmt_localvers = fi->versnum;
+
+ xprt_set_caller(xprt, fi);
+#if defined(SVC_XP_AUTH)
+ SVC_XP_AUTH(xprt) = svc_auth_none;
+#else
+ xprt->xp_auth = &svc_auth_none;
+#endif
+ svc_sendreply(xprt, (xdrproc_t) xdr_rmtcall_result, (char *) &a);
+#if !defined(SVC_XP_AUTH)
+ SVCAUTH_DESTROY(xprt->xp_auth);
+ xprt->xp_auth = NULL;
+#endif
+
+done:
+ if (buffer)
+ free(buffer);
+
+ if (reply_msg.rm_xid == 0) {
+#ifdef SVC_RUN_DEBUG
+ if (debugging) {
+ xlog(LOG_DEBUG, "handle_reply: NULL xid on exit!\n");
+ }
+#endif
+ } else
+ (void) free_slot_by_xid(reply_msg.rm_xid);
+ return;
+}
+
+static void
+find_versions(rpcprog_t prog, char *netid, rpcvers_t *lowvp, rpcvers_t *highvp)
+{
+ register rpcblist_ptr rbl;
+ unsigned int lowv = 0;
+ unsigned int highv = 0;
+
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog != prog) ||
+ ((rbl->rpcb_map.r_netid != NULL) &&
+ (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
+ continue;
+ if (lowv == 0) {
+ highv = rbl->rpcb_map.r_vers;
+ lowv = highv;
+ } else if (rbl->rpcb_map.r_vers < lowv) {
+ lowv = rbl->rpcb_map.r_vers;
+ } else if (rbl->rpcb_map.r_vers > highv) {
+ highv = rbl->rpcb_map.r_vers;
+ }
+ }
+ *lowvp = lowv;
+ *highvp = highv;
+ return;
+}
+
+/*
+ * returns the item with the given program, version number and netid.
+ * If that version number is not found, it returns the item with that
+ * program number, so that address is now returned to the caller. The
+ * caller when makes a call to this program, version number, the call
+ * will fail and it will return with PROGVERS_MISMATCH. The user can
+ * then determine the highest and the lowest version number for this
+ * program using clnt_geterr() and use those program version numbers.
+ *
+ * Returns the RPCBLIST for the given prog, vers and netid
+ */
+static rpcblist_ptr
+find_service(rpcprog_t prog, rpcvers_t vers, char *netid)
+{
+ register rpcblist_ptr hit = NULL;
+ register rpcblist_ptr rbl;
+
+ for (rbl = list_rbl; rbl != NULL; rbl = rbl->rpcb_next) {
+ if ((rbl->rpcb_map.r_prog != prog) ||
+ ((rbl->rpcb_map.r_netid != NULL) &&
+ (strcasecmp(rbl->rpcb_map.r_netid, netid) != 0)))
+ continue;
+ hit = rbl;
+ if (rbl->rpcb_map.r_vers == vers)
+ break;
+ }
+ return (hit);
+}
+
+/*
+ * Copies the name associated with the uid of the caller and returns
+ * a pointer to it. Similar to getwd().
+ */
+static char *
+getowner(SVCXPRT *transp, char *owner, size_t ownersize)
+{
+ uid_t uid;
+
+ if (__rpc_get_local_uid(transp, &uid) < 0) {
+ if (is_localroot(svc_getrpccaller(transp)))
+ snprintf(owner, ownersize, "superuser");
+ else
+ snprintf(owner, ownersize, "unknown");
+ } else if (uid == 0)
+ snprintf(owner, ownersize, "superuser");
+ else
+ snprintf(owner, ownersize, "%d", uid);
+
+ return owner;
+}
+
+#ifdef PORTMAP
+/*
+ * Extract port from universal TCP/UDP address
+ */
+int
+uaddr2port(char *uaddr, u_long *p_port)
+{
+ char *pt1, *pt2;
+ int rc = -1;
+
+ if ((pt1 = strrchr(uaddr, '.')) != NULL) {
+ *pt1++ = 0;
+ if ((pt2 = strrchr(uaddr, '.')) != NULL) {
+ *pt2++ = 0;
+ *p_port = atoi(pt2) * 256 + atoi(pt1);
+ rc = 0;
+ *--pt2 = '.';
+ }
+ *--pt1 = '.';
+ }
+ return rc;
+}
+
+/*
+ * Add this to the pmap list only if it is UDP or TCP.
+ */
+static int
+add_pmaplist(RPCB *arg)
+{
+ struct pmap pmap;
+ struct pmaplist *pml;
+
+ pmap.pm_prot = pmap_netid2ipprot(arg->r_netid);
+ if (!pmap.pm_prot)
+ /* Not an IP protocol */
+ return (0);
+
+ /* interpret the universal address for TCP/IP */
+ if (uaddr2port(arg->r_addr, &pmap.pm_port) == -1)
+ return (0);
+ pmap.pm_prog = arg->r_prog;
+ pmap.pm_vers = arg->r_vers;
+ /*
+ * add to END of list
+ */
+ pml = malloc(sizeof (struct pmaplist));
+ if (pml == NULL) {
+ (void) syslog(LOG_ERR, "rpcbind: no memory!\n");
+ return (1);
+ }
+ pml->pml_map = pmap;
+ pml->pml_next = NULL;
+ if (list_pml == NULL) {
+ list_pml = pml;
+ } else {
+ struct pmaplist *fnd;
+
+ /* Attach to the end of the list */
+ for (fnd = list_pml; fnd->pml_next; fnd = fnd->pml_next)
+ ;
+ fnd->pml_next = pml;
+ }
+ return (0);
+}
+
+/*
+ * Delete this from the pmap list only if it is UDP or TCP.
+ */
+static int
+del_pmaplist(RPCB *arg)
+{
+ struct pmaplist *pml;
+ struct pmaplist *prevpml, *fnd;
+ unsigned long prot;
+
+ if (arg->r_netid[0] == 0) {
+ prot = 0; /* Remove all occurrences */
+ } else
+ if ((prot = pmap_netid2ipprot(arg->r_netid)) == 0) {
+ /* Not an IP protocol */
+ return (0);
+ }
+ for (prevpml = NULL, pml = list_pml; pml; /* cstyle */) {
+ if ((pml->pml_map.pm_prog != arg->r_prog) ||
+ (pml->pml_map.pm_vers != arg->r_vers) ||
+ (prot && (pml->pml_map.pm_prot != prot))) {
+ /* both pml & prevpml move forwards */
+ prevpml = pml;
+ pml = pml->pml_next;
+ continue;
+ }
+ /* found it; pml moves forward, prevpml stays */
+ fnd = pml;
+ pml = pml->pml_next;
+ if (prevpml == NULL)
+ list_pml = pml;
+ else
+ prevpml->pml_next = pml;
+ free(fnd);
+ }
+ return (0);
+}
+#endif /* PORTMAP */
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcbind.c
^
|
@@ -0,0 +1,948 @@
+/* $NetBSD: rpcbind.c,v 1.3 2002/11/08 00:16:40 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/rpcbind.c,v 1.12 2003/10/29 09:31:41 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) 1984 - 1991 by Sun Microsystems, Inc.
+ */
+
+
+
+/*
+ * rpcbind.c
+ * Implements the program, version to address mapping for rpc.
+ *
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/resource.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <sys/file.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef PORTMAP
+#include <netinet/in.h>
+#endif
+#include <arpa/inet.h>
+#ifdef SYSTEMD
+#include <systemd/sd-daemon.h>
+#endif
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <grp.h>
+#include <syslog.h>
+#include <err.h>
+#include <pwd.h>
+#include <string.h>
+#include <errno.h>
+#ifdef HAVE_NSS_H
+#include <nss.h>
+#else
+static inline void __nss_configure_lookup(const char *db, const char *s) {}
+#endif
+#include "rpcbind.h"
+#include "xlog.h"
+
+/*#define RPCBIND_DEBUG*/
+
+/* Global variables */
+
+int debugging = 0; /* Tell me what's going on */
+int doabort = 0; /* When debugging, do an abort on errors */
+int dofork = 1; /* fork? */
+int createdsocket = 0; /* Did I create the socket or systemd did it for me? */
+
+rpcblist_ptr list_rbl; /* A list of version 3/4 rpcbind services */
+
+#ifdef RPCBIND_USER
+char *rpcbinduser = RPCBIND_USER;
+#else
+char *rpcbinduser = NULL;
+#endif
+
+#ifdef NSS_MODULES
+char *nss_modules = NSS_MODULES;
+#else
+char *nss_modules = "files";
+#endif
+
+/* who to suid to if -s is given */
+#define RUN_AS "daemon"
+
+#define RPCBINDDLOCK "/var/run/rpcbind.lock"
+
+int runasdaemon = 0;
+int insecure = 0;
+int oldstyle_local = 0;
+int verboselog = 0;
+
+char **hosts = NULL;
+int nhosts = 0;
+int on = 1;
+int rpcbindlockfd;
+
+#ifdef LIB_SET_DEBUG
+void libtirpc_set_debug(char *name, int level, int use_stderr);
+#endif
+#ifdef WARMSTART
+/* Local Variable */
+static int warmstart = 0; /* Grab an old copy of registrations. */
+#endif
+
+#ifdef PORTMAP
+struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
+char *udptrans; /* Name of UDP transport */
+char *tcptrans; /* Name of TCP transport */
+char *udp_uaddr; /* Universal UDP address */
+char *tcp_uaddr; /* Universal TCP address */
+#endif
+static char servname[] = "rpcbind";
+static char superuser[] = "superuser";
+
+int main(int, char *[]);
+
+static int init_transport(struct netconfig *);
+static void rbllist_add(rpcprog_t, rpcvers_t, struct netconfig *,
+ struct netbuf *);
+static void terminate(int);
+static void parseargs(int, char *[]);
+
+int
+main(int argc, char *argv[])
+{
+ struct netconfig *nconf;
+ void *nc_handle; /* Net config handle */
+ struct rlimit rl;
+ int maxrec = RPC_MAXDATASIZE;
+
+ parseargs(argc, argv);
+
+ /* Check that another rpcbind isn't already running. */
+ if ((rpcbindlockfd = (open(RPCBINDDLOCK,
+ O_RDONLY|O_CREAT, 0444))) == -1)
+ err(1, "%s", RPCBINDDLOCK);
+
+ if(flock(rpcbindlockfd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK)
+ errx(1, "another rpcbind is already running. Aborting");
+
+ getrlimit(RLIMIT_NOFILE, &rl);
+ if (rl.rlim_cur < 128) {
+ if (rl.rlim_max <= 128)
+ rl.rlim_cur = rl.rlim_max;
+ else
+ rl.rlim_cur = 128;
+ setrlimit(RLIMIT_NOFILE, &rl);
+ }
+
+ if (geteuid()) { /* This command allowed only to root */
+ fprintf(stderr, "Sorry. You are not superuser\n");
+ exit(1);
+ }
+
+ /*
+ * Make sure we use the local service file
+ * for service lookkups
+ */
+ __nss_configure_lookup("services", nss_modules);
+
+ nc_handle = setnetconfig(); /* open netconfig file */
+ if (nc_handle == NULL) {
+ syslog(LOG_ERR, "could not read /etc/netconfig");
+ exit(1);
+ }
+
+ nconf = getnetconfigent("local");
+ if (nconf == NULL)
+ nconf = getnetconfigent("unix");
+ if (nconf == NULL) {
+ syslog(LOG_ERR, "%s: can't find local transport\n", argv[0]);
+ exit(1);
+ }
+ xlog_open("rpcbind");
+ if (dofork) {
+ xlog_syslog(TRUE);
+ xlog_stderr(FALSE);
+ } else {
+ xlog_syslog(FALSE);
+ xlog_stderr(TRUE);
+ }
+ if (debugging) {
+ xlog_config(D_ALL, 1);
+#ifdef LIB_SET_DEBUG
+ libtirpc_set_debug("rpcbind", debugging, (dofork == 0));
+#endif
+ }
+ rpc_control(RPC_SVC_CONNMAXREC_SET, &maxrec);
+
+ init_transport(nconf);
+
+ while ((nconf = getnetconfig(nc_handle))) {
+ if (nconf->nc_flag & NC_VISIBLE)
+ init_transport(nconf);
+ }
+ endnetconfig(nc_handle);
+
+#ifdef PORTMAP
+ if (!udptrans)
+ udptrans = "";
+ if (!tcptrans)
+ tcptrans = "";
+#endif
+
+ /* catch the usual termination signals for graceful exit */
+ (void) signal(SIGCHLD, reap);
+ (void) signal(SIGINT, terminate);
+ (void) signal(SIGTERM, terminate);
+ (void) signal(SIGQUIT, terminate);
+ /* ignore others that could get sent */
+ (void) signal(SIGPIPE, SIG_IGN);
+ (void) signal(SIGHUP, SIG_IGN);
+ (void) signal(SIGUSR1, SIG_IGN);
+ (void) signal(SIGUSR2, SIG_IGN);
+
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ xlog(LOG_DEBUG, "debugging enabled.");
+ if (doabort)
+ xlog(LOG_DEBUG, "Will abort on errors!\n");
+ }
+#endif
+ if (dofork) {
+ if (daemon(0, 0))
+ err(1, "fork failed");
+ }
+
+ if (runasdaemon || rpcbinduser) {
+ struct passwd *p;
+ char *id = runasdaemon ? RUN_AS : rpcbinduser;
+
+ /*
+ * Make sure we use the local password file
+ * for these lookups.
+ */
+ __nss_configure_lookup("passwd", nss_modules);
+
+ if((p = getpwnam(id)) == NULL) {
+ syslog(LOG_ERR, "cannot get uid of '%s': %m", id);
+ exit(1);
+ }
+#ifdef WARMSTART
+ if (warmstart) {
+ mkdir_warmstart(p->pw_uid);
+ }
+#endif
+ if (setgid(p->pw_gid) == -1) {
+ syslog(LOG_ERR, "setgid to '%s' (%d) failed: %m", id, p->pw_gid);
+ exit(1);
+ }
+ if (setgroups(0, NULL) == -1) {
+ syslog(LOG_ERR, "dropping supplemental groups failed: %m");
+ exit(1);
+ }
+ if (setuid(p->pw_uid) == -1) {
+ syslog(LOG_ERR, "setuid to '%s' (%d) failed: %m", id, p->pw_uid);
+ exit(1);
+ }
+ }
+
+#ifdef WARMSTART
+ if (warmstart) {
+ read_warmstart();
+ }
+#endif
+
+ network_init();
+
+#ifdef SYSTEMD
+ /* Try to notify system of successful startup, regardless of whether we
+ * used systemd socket activation or not. When started from the command
+ * line, this should not hurt either.
+ */
+ sd_notify(0, "READY=1");
+#endif
+ my_svc_run();
+ syslog(LOG_ERR, "svc_run returned unexpectedly");
+ rpcbind_abort();
+ /* NOTREACHED */
+
+ return 0;
+}
+
+/*
+ * Normally systemd will open sockets in dual ipv4/ipv6 mode.
+ * That won't work with netconfig and we'll only match
+ * the ipv6 socket. Convert it to IPV6_V6ONLY and issue
+ * a warning for the user to fix their systemd config.
+ */
+static int
+handle_ipv6_socket(int fd)
+{
+ int opt;
+ socklen_t len = sizeof(opt);
+
+ if (getsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &opt, &len)) {
+ syslog(LOG_ERR, "failed to get ipv6 socket opts: %m");
+ return -1;
+ }
+
+ if (opt) /* socket is already in V6ONLY mode */
+ return 0;
+
+ syslog(LOG_ERR, "systemd has passed an IPv4/IPv6 dual-mode socket.");
+ syslog(LOG_ERR, "Please fix your systemd config by specifying IPv4 and IPv6 sockets separately and using BindIPv6Only=ipv6-only.");
+ return -1;
+}
+
+/*
+ * Adds the entry into the rpcbind database.
+ * If PORTMAP, then for UDP and TCP, it adds the entries for version 2 also
+ * Returns 0 if succeeds, else fails
+ */
+static int
+init_transport(struct netconfig *nconf)
+{
+ int fd = -1;
+ struct t_bind taddr;
+ struct addrinfo hints, *res = NULL;
+ struct __rpc_sockinfo si;
+ SVCXPRT *my_xprt = NULL;
+ int status; /* bound checking ? */
+ int aicode;
+ int addrlen = 0;
+ int nhostsbak;
+ int checkbind;
+ int on = 1;
+ struct sockaddr *sa = NULL;
+ u_int32_t host_addr[4]; /* IPv4 or IPv6 */
+ struct sockaddr_un sun;
+ mode_t oldmask;
+ int n;
+ res = NULL;
+
+ if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ return (1); /* not my type */
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ int i;
+ char **s;
+
+ (void) xlog(LOG_DEBUG, "%s: %ld lookup routines :\n",
+ nconf->nc_netid, nconf->nc_nlookups);
+ for (i = 0, s = nconf->nc_lookups; i < nconf->nc_nlookups;
+ i++, s++)
+ xlog(LOG_DEBUG, "[%d] - %s\n", i, *s);
+ }
+#endif
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ syslog(LOG_ERR, "cannot get information for %s",
+ nconf->nc_netid);
+ return (1);
+ }
+
+#ifdef SYSTEMD
+ n = sd_listen_fds(0);
+ if (n < 0) {
+ syslog(LOG_ERR, "failed to acquire systemd sockets: %s", strerror(-n));
+ return 1;
+ }
+
+ /* Try to find if one of the systemd sockets we were given match
+ * our netconfig structure. */
+
+ for (fd = SD_LISTEN_FDS_START; fd < SD_LISTEN_FDS_START + n; fd++) {
+ struct __rpc_sockinfo si_other;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_un un;
+ struct sockaddr_in in4;
+ struct sockaddr_in6 in6;
+ struct sockaddr_storage storage;
+ } sa;
+ socklen_t addrlen = sizeof(sa);
+
+ if (!__rpc_fd2sockinfo(fd, &si_other)) {
+ syslog(LOG_ERR, "cannot get information for fd %i", fd);
+ return 1;
+ }
+
+ if (si.si_af != si_other.si_af ||
+ si.si_socktype != si_other.si_socktype ||
+ si.si_proto != si_other.si_proto)
+ continue;
+
+ if (getsockname(fd, &sa.sa, &addrlen) < 0) {
+ syslog(LOG_ERR, "failed to query socket name: %s",
+ strerror(errno));
+ goto error;
+ }
+
+ if (sa.sa.sa_family == AF_INET6 && handle_ipv6_socket(fd))
+ goto error;
+
+ /* Copy the address */
+ taddr.addr.maxlen = taddr.addr.len = addrlen;
+ taddr.addr.buf = malloc(addrlen);
+ if (taddr.addr.buf == NULL) {
+ syslog(LOG_ERR,
+ "cannot allocate memory for %s address",
+ nconf->nc_netid);
+ goto error;
+ }
+ memcpy(taddr.addr.buf, &sa, addrlen);
+
+ my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
+ RPC_MAXDATASIZE, RPC_MAXDATASIZE);
+ if (my_xprt == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "%s: could not create service",
+ nconf->nc_netid);
+ goto error;
+ }
+ }
+
+ /*
+ * If none of the systemd sockets matched, we set up the socket in
+ * the normal way:
+ */
+#endif
+ if (my_xprt != NULL)
+ goto got_socket;
+
+ if ((strcmp(nconf->nc_netid, "local") == 0) ||
+ (strcmp(nconf->nc_netid, "unix") == 0)) {
+ memset(&sun, 0, sizeof sun);
+ sun.sun_family = AF_LOCAL;
+ unlink(_PATH_RPCBINDSOCK);
+ createdsocket = 1; /* We are now in the process of creating the unix socket */
+ strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
+ addrlen = SUN_LEN(&sun);
+ sa = (struct sockaddr *)&sun;
+ } else {
+ /* Get rpcbind's address on this transport */
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = si.si_af;
+ hints.ai_socktype = si.si_socktype;
+ hints.ai_protocol = si.si_proto;
+ }
+ if (nconf->nc_semantics == NC_TPI_CLTS) {
+ /*
+ * If no hosts were specified, just bind to INADDR_ANY. Otherwise
+ * make sure 127.0.0.1 is added to the list.
+ */
+ nhostsbak = nhosts;
+ nhostsbak++;
+ hosts = realloc(hosts, nhostsbak * sizeof(char *));
+ if (nhostsbak == 1)
+ hosts[0] = "*";
+ else {
+ if (hints.ai_family == AF_INET) {
+ hosts[nhostsbak - 1] = "127.0.0.1";
+ } else if (hints.ai_family == AF_INET6) {
+ hosts[nhostsbak - 1] = "::1";
+ } else
+ return 1;
+ }
+
+ /*
+ * Bind to specific IPs if asked to
+ */
+ checkbind = 0;
+ while (nhostsbak > 0) {
+ --nhostsbak;
+ /*
+ * XXX - using RPC library internal functions.
+ */
+ if ((fd = __rpc_nconf2fd(nconf)) < 0) {
+ syslog(LOG_ERR, "cannot create socket for %s",
+ nconf->nc_netid);
+ return (1);
+ }
+
+ hints.ai_flags &= ~AI_NUMERICHOST;
+ switch (hints.ai_family) {
+ case AF_INET:
+ if (inet_pton(AF_INET, hosts[nhostsbak],
+ host_addr) == 1) {
+ hints.ai_flags |= AI_NUMERICHOST;
+ } else {
+ /*
+ * Skip if we have an AF_INET6 address.
+ */
+ if (inet_pton(AF_INET6,
+ hosts[nhostsbak], host_addr) == 1)
+ continue;
+ }
+ break;
+ case AF_INET6:
+ if (inet_pton(AF_INET6, hosts[nhostsbak],
+ host_addr) == 1) {
+ hints.ai_flags |= AI_NUMERICHOST;
+ } else {
+ /*
+ * Skip if we have an AF_INET address.
+ */
+ if (inet_pton(AF_INET, hosts[nhostsbak],
+ host_addr) == 1)
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+
+ /*
+ * If no hosts were specified, just bind to INADDR_ANY
+ */
+ if (strcmp("*", hosts[nhostsbak]) == 0)
+ hosts[nhostsbak] = NULL;
+
+ if ((aicode = getaddrinfo(hosts[nhostsbak],
+ servname, &hints, &res)) != 0) {
+ if ((aicode = getaddrinfo(hosts[nhostsbak],
+ "portmapper", &hints, &res)) != 0) {
+ syslog(LOG_ERR,
+ "cannot get local address for %s: %s",
+ nconf->nc_netid, gai_strerror(aicode));
+ continue;
+ }
+ }
+ addrlen = res->ai_addrlen;
+ sa = (struct sockaddr *)res->ai_addr;
+ oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
+ if (bind(fd, sa, addrlen) != 0) {
+ syslog(LOG_ERR, "cannot bind %s on %s: %m",
+ (hosts[nhostsbak] == NULL) ? "*" :
+ hosts[nhostsbak], nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ continue;
+ } else
+ checkbind++;
+ (void) umask(oldmask);
+
+ /* Copy the address */
+ taddr.addr.maxlen = taddr.addr.len = addrlen;
+ taddr.addr.buf = malloc(addrlen);
+ if (taddr.addr.buf == NULL) {
+ syslog(LOG_ERR,
+ "cannot allocate memory for %s address",
+ nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ return 1;
+ }
+ memcpy(taddr.addr.buf, sa, addrlen);
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ /*
+ * for debugging print out our universal
+ * address
+ */
+ char *uaddr;
+ struct netbuf nb;
+ int sa_size = 0;
+
+ nb.buf = sa;
+ switch( sa->sa_family){
+ case AF_INET:
+ sa_size = sizeof (struct sockaddr_in);
+ break;
+ case AF_INET6:
+ sa_size = sizeof (struct sockaddr_in6);
+ break;
+ }
+ nb.len = nb.maxlen = sa_size;
+ uaddr = taddr2uaddr(nconf, &nb);
+ (void) xlog(LOG_DEBUG,
+ "rpcbind : my address is %s\n", uaddr);
+ (void) free(uaddr);
+ }
+#endif
+ my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr,
+ RPC_MAXDATASIZE, RPC_MAXDATASIZE);
+ if (my_xprt == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "%s: could not create service",
+ nconf->nc_netid);
+ goto error;
+ }
+ }
+ if (!checkbind)
+ return 1;
+ } else { /* NC_TPI_COTS */
+ if ((fd = __rpc_nconf2fd(nconf)) < 0) {
+ syslog(LOG_ERR, "cannot create socket for %s",
+ nconf->nc_netid);
+ return (1);
+ }
+
+ if ((strcmp(nconf->nc_netid, "local") != 0) &&
+ (strcmp(nconf->nc_netid, "unix") != 0)) {
+ if ((aicode = getaddrinfo(NULL, servname, &hints, &res))!= 0) {
+ if ((aicode = getaddrinfo(NULL, "portmapper", &hints, &res))!= 0) {
+ printf("cannot get local address for %s: %s", nconf->nc_netid, gai_strerror(aicode));
+ syslog(LOG_ERR,
+ "cannot get local address for %s: %s",
+ nconf->nc_netid, gai_strerror(aicode));
+ return 1;
+ }
+ }
+ addrlen = res->ai_addrlen;
+ sa = (struct sockaddr *)res->ai_addr;
+ }
+ oldmask = umask(S_IXUSR|S_IXGRP|S_IXOTH);
+ __rpc_fd2sockinfo(fd, &si);
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on,
+ sizeof(on)) != 0) {
+ syslog(LOG_ERR, "cannot set SO_REUSEADDR on %s",
+ nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ return 1;
+ }
+ if (bind(fd, sa, addrlen) < 0) {
+ syslog(LOG_ERR, "cannot bind %s: %m", nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ return 1;
+ }
+ (void) umask(oldmask);
+
+ /* Copy the address */
+ taddr.addr.len = taddr.addr.maxlen = addrlen;
+ taddr.addr.buf = malloc(addrlen);
+ if (taddr.addr.buf == NULL) {
+ syslog(LOG_ERR, "cannot allocate memory for %s address",
+ nconf->nc_netid);
+ if (res != NULL)
+ freeaddrinfo(res);
+ return 1;
+ }
+ memcpy(taddr.addr.buf, sa, addrlen);
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ /* for debugging print out our universal address */
+ char *uaddr;
+ struct netbuf nb;
+ int sa_size2 = 0;
+
+ nb.buf = sa;
+ switch( sa->sa_family){
+ case AF_INET:
+ sa_size2 = sizeof (struct sockaddr_in);
+ break;
+ case AF_INET6:
+ sa_size2 = sizeof (struct sockaddr_in6);
+ break;
+ }
+ nb.len = nb.maxlen = sa_size2;
+ uaddr = taddr2uaddr(nconf, &nb);
+ (void) xlog(LOG_DEBUG, "rpcbind : my address is %s\n",
+ uaddr);
+ (void) free(uaddr);
+ }
+#endif
+
+ listen(fd, SOMAXCONN);
+
+ my_xprt = (SVCXPRT *)svc_tli_create(fd, nconf, &taddr, RPC_MAXDATASIZE, RPC_MAXDATASIZE);
+ if (my_xprt == (SVCXPRT *)NULL) {
+ syslog(LOG_ERR, "%s: could not create service",
+ nconf->nc_netid);
+ goto error;
+ }
+ }
+got_socket:
+
+#ifdef PORTMAP
+ /*
+ * Register both the versions for tcp/ip, udp/ip.
+ */
+ if (si.si_af == AF_INET &&
+ (si.si_proto == IPPROTO_TCP || si.si_proto == IPPROTO_UDP)) {
+ struct pmaplist *pml;
+
+ pml = malloc(sizeof (struct pmaplist));
+ if (pml == NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+ pml->pml_map.pm_prog = PMAPPROG;
+ pml->pml_map.pm_vers = PMAPVERS;
+ pml->pml_map.pm_port = PMAPPORT;
+ pml->pml_map.pm_prot = si.si_proto;
+
+ switch (si.si_proto) {
+ case IPPROTO_TCP:
+ tcptrans = strdup(nconf->nc_netid);
+ break;
+ case IPPROTO_UDP:
+ udptrans = strdup(nconf->nc_netid);
+ break;
+ }
+ pml->pml_next = list_pml;
+ list_pml = pml;
+
+ /* Add version 3 information */
+ pml = malloc(sizeof (struct pmaplist));
+ if (pml == NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+ pml->pml_map = list_pml->pml_map;
+ pml->pml_map.pm_vers = RPCBVERS;
+ pml->pml_next = list_pml;
+ list_pml = pml;
+
+ /* Add version 4 information */
+ pml = malloc (sizeof (struct pmaplist));
+ if (pml == NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+ pml->pml_map = list_pml->pml_map;
+ pml->pml_map.pm_vers = RPCBVERS4;
+ pml->pml_next = list_pml;
+ list_pml = pml;
+
+ /* Also add version 2 stuff to rpcbind list */
+ rbllist_add(PMAPPROG, PMAPVERS, nconf, &taddr.addr);
+ }
+
+ /* We need to support portmap over IPv4. It makes sense to
+ * support it over AF_LOCAL as well, because that allows
+ * rpcbind to identify the owner of a socket much better
+ * than by relying on privileged ports to tell root from
+ * non-root users. */
+ if (si.si_af == AF_INET || si.si_af == AF_LOCAL) {
+ if (!svc_register(my_xprt, PMAPPROG, PMAPVERS, pmap_service, 0)) {
+ syslog(LOG_ERR, "could not register on %s",
+ nconf->nc_netid);
+ goto error;
+ }
+ }
+#endif
+
+ /* version 3 registration */
+ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS, rpcb_service_3, NULL)) {
+ syslog(LOG_ERR, "could not register %s version 3",
+ nconf->nc_netid);
+ goto error;
+ }
+ rbllist_add(RPCBPROG, RPCBVERS, nconf, &taddr.addr);
+
+ /* version 4 registration */
+ if (!svc_reg(my_xprt, RPCBPROG, RPCBVERS4, rpcb_service_4, NULL)) {
+ syslog(LOG_ERR, "could not register %s version 4",
+ nconf->nc_netid);
+ goto error;
+ }
+ rbllist_add(RPCBPROG, RPCBVERS4, nconf, &taddr.addr);
+
+ /* decide if bound checking works for this transport */
+ status = add_bndlist(nconf, &taddr.addr);
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ if (status < 0) {
+ xlog(LOG_DEBUG, "Error in finding bind status for %s\n",
+ nconf->nc_netid);
+ } else if (status == 0) {
+ xlog(LOG_DEBUG, "check binding for %s\n",
+ nconf->nc_netid);
+ } else if (status > 0) {
+ xlog(LOG_DEBUG, "No check binding for %s\n",
+ nconf->nc_netid);
+ }
+ }
+#endif
+
+
+#ifdef RMTCALLS
+ /*
+ * rmtcall only supported on CLTS transports for now.
+ */
+ if (nconf->nc_semantics == NC_TPI_CLTS) {
+ status = create_rmtcall_fd(nconf);
+#ifdef RPCBIND_DEBUG
+ if (debugging) {
+ if (status < 0) {
+ xlog(LOG_DEBUG,
+ "Could not create rmtcall fd for %s\n",
+ nconf->nc_netid);
+ } else {
+ xlog(LOG_DEBUG, "rmtcall fd for %s is %d\n",
+ nconf->nc_netid, status);
+ }
+ }
+#endif
+ }
+#endif
+
+ if (res != NULL)
+ freeaddrinfo(res);
+ return (0);
+error:
+ if (res != NULL)
+ freeaddrinfo(res);
+ close(fd);
+ return (1);
+}
+
+static void
+rbllist_add(rpcprog_t prog, rpcvers_t vers, struct netconfig *nconf,
+ struct netbuf *addr)
+{
+ rpcblist_ptr rbl;
+
+ rbl = malloc(sizeof (rpcblist));
+ if (rbl == NULL) {
+ syslog(LOG_ERR, "no memory!");
+ exit(1);
+ }
+#ifdef RPCBIND_DEBUG
+ if (debugging){
+ xlog(LOG_DEBUG,"FUNCTION rbllist_add");
+ xlog(LOG_DEBUG,"Add the prog %lu vers %lu to the rpcbind list",
+ (ulong)prog, (ulong)vers);
+ }
+#endif
+ rbl->rpcb_map.r_prog = prog;
+ rbl->rpcb_map.r_vers = vers;
+ rbl->rpcb_map.r_netid = strdup(nconf->nc_netid);
+ rbl->rpcb_map.r_addr = taddr2uaddr(nconf, addr);
+ rbl->rpcb_map.r_owner = strdup(superuser);
+ rbl->rpcb_next = list_rbl; /* Attach to global list */
+ list_rbl = rbl;
+}
+
+/*
+ * Catch the signal and die
+ */
+static void
+terminate(int dummy /*__unused*/)
+{
+ close(rpcbindlockfd);
+ if(createdsocket)
+ unlink(_PATH_RPCBINDSOCK);
+ unlink(RPCBINDDLOCK);
+#ifdef WARMSTART
+ write_warmstart(); /* Dump yourself */
+#endif
+ exit(0); /* exit gracefully */
+}
+
+void
+rpcbind_abort()
+{
+#ifdef WARMSTART
+ write_warmstart(); /* Dump yourself */
+#endif
+ abort();
+}
+
+/* get command line options */
+static void
+parseargs(int argc, char *argv[])
+{
+ int c;
+ oldstyle_local = 1;
+ while ((c = getopt(argc, argv, "adh:ilswf")) != -1) {
+ switch (c) {
+ case 'a':
+ doabort = 1; /* when debugging, do an abort on */
+ break; /* errors; for rpcbind developers */
+ /* only! */
+ case 'd':
+ debugging++;
+ break;
+ case 'h':
+ ++nhosts;
+ hosts = realloc(hosts, nhosts * sizeof(char *));
+ if (hosts == NULL)
+ errx(1, "Out of memory");
+ hosts[nhosts - 1] = strdup(optarg);
+ if (hosts[nhosts - 1] == NULL)
+ errx(1, "Out of memory");
+ break;
+ case 'i':
+ insecure = 1;
+ break;
+ case 'l':
+ verboselog = 1;
+ break;
+ case 's':
+ runasdaemon = 1;
+ break;
+ case 'f':
+ dofork = 0;
+ break;
+#ifdef WARMSTART
+ case 'w':
+ warmstart = 1;
+ break;
+#endif
+ default: /* error */
+ fprintf(stderr, "usage: rpcbind [-adhilswf]\n");
+ exit (1);
+ }
+ }
+ if (doabort && !debugging) {
+ fprintf(stderr,
+ "-a (abort) specified without -d (debugging) -- ignored.\n");
+ doabort = 0;
+ }
+}
+
+void
+reap(int dummy /*__unused*/)
+{
+ int save_errno = errno;
+
+ while (wait3(NULL, WNOHANG, NULL) > 0)
+ ;
+ errno = save_errno;
+}
+
+void
+toggle_verboselog(int dummy /*__unused*/)
+{
+ verboselog = !verboselog;
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcbind.h
^
|
@@ -0,0 +1,145 @@
+/* $NetBSD: rpcbind.h,v 1.1 2000/06/03 00:47:21 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/rpcbind.h,v 1.2 2002/10/07 02:56:59 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.
+ */
+
+/* #ident "@(#)rpcbind.h 1.4 90/04/12 SMI" */
+
+/*
+ * rpcbind.h
+ * The common header declarations
+ */
+
+#ifndef rpcbind_h
+#define rpcbind_h
+
+#ifdef PORTMAP
+#include <rpc/pmap_prot.h>
+#endif
+#include <rpc/rpcb_prot.h>
+
+/*
+ * Stuff for the rmtcall service
+ */
+struct encap_parms {
+ u_int32_t arglen;
+ char *args;
+};
+
+struct r_rmtcall_args {
+ u_int32_t rmt_prog;
+ u_int32_t rmt_vers;
+ u_int32_t rmt_proc;
+ int rmt_localvers; /* whether to send port # or uaddr */
+ char *rmt_uaddr;
+ struct encap_parms rmt_args;
+};
+
+extern int debugging;
+extern int doabort;
+extern int verboselog;
+extern int insecure;
+extern int oldstyle_local;
+extern rpcblist_ptr list_rbl; /* A list of version 3 & 4 rpcbind services */
+
+#ifdef PORTMAP
+extern struct pmaplist *list_pml; /* A list of version 2 rpcbind services */
+extern char *udptrans; /* Name of UDP transport */
+extern char *tcptrans; /* Name of TCP transport */
+extern char *pmap_ipprot2netid(unsigned long);
+extern int pmap_netid2ipprot(const char *);
+#endif
+
+int add_bndlist(struct netconfig *, struct netbuf *);
+bool_t is_bound(char *, char *);
+char *mergeaddr(SVCXPRT *, char *, char *, char *);
+struct netconfig *rpcbind_get_conf(char *);
+
+void rpcbs_init(void);
+void rpcbs_procinfo(rpcvers_t, rpcproc_t);
+void rpcbs_set(rpcvers_t, bool_t);
+void rpcbs_unset(rpcvers_t, bool_t);
+void rpcbs_getaddr(rpcvers_t, rpcprog_t, rpcvers_t, char *, char *);
+void rpcbs_rmtcall(rpcvers_t, rpcproc_t, rpcprog_t, rpcvers_t, rpcproc_t,
+ char *, rpcblist_ptr);
+void *rpcbproc_getstat(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+
+void rpcb_service_3(struct svc_req *, SVCXPRT *);
+void rpcb_service_4(struct svc_req *, SVCXPRT *);
+
+/* Common functions shared between versions */
+void *rpcbproc_set_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+void *rpcbproc_unset_com(void *, struct svc_req *, SVCXPRT *, rpcvers_t);
+bool_t map_set(RPCB *, char *);
+bool_t map_unset(RPCB *, char *);
+void delete_prog(unsigned int);
+void *rpcbproc_getaddr_com(RPCB *, struct svc_req *, SVCXPRT *, rpcvers_t,
+ rpcvers_t);
+void *rpcbproc_gettime_com(void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t);
+void *rpcbproc_uaddr2taddr_com(void *, struct svc_req *,
+ SVCXPRT *, rpcvers_t);
+void *rpcbproc_taddr2uaddr_com(void *, struct svc_req *, SVCXPRT *,
+ rpcvers_t);
+int create_rmtcall_fd(struct netconfig *);
+void rpcbproc_callit_com(struct svc_req *, SVCXPRT *, rpcvers_t,
+ rpcvers_t);
+void my_svc_run(void);
+
+void rpcbind_abort(void);
+void reap(int);
+void toggle_verboselog(int);
+
+int check_access(SVCXPRT *, rpcproc_t, rpcprog_t, unsigned int);
+int check_callit(SVCXPRT *, struct r_rmtcall_args *, int);
+void logit(int, struct sockaddr *, rpcproc_t, rpcprog_t, const char *);
+int is_loopback(struct netbuf *);
+int is_localroot(struct netbuf *);
+
+#ifdef PORTMAP
+extern void pmap_service(struct svc_req *, SVCXPRT *);
+#endif
+
+void mkdir_warmstart(int uid);
+void write_warmstart(void);
+void read_warmstart(void);
+
+char *addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr, char *netid);
+void network_init(void);
+struct sockaddr *local_sa(int);
+
+/* For different getaddr semantics */
+#define RPCB_ALLVERS 0
+#define RPCB_ONEVERS 1
+
+#endif /* rpcbind_h */
+
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/rpcinfo.c
^
|
@@ -0,0 +1,1958 @@
+/*
+ * 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.
+ */
+/*
+ * rpcinfo: ping a particular rpc program
+ * or dump the the registered programs on the remote machine.
+ */
+
+/*
+ * We are for now defining PORTMAP here. It doesnt even compile
+ * unless it is defined.
+ */
+#ifndef PORTMAP
+#define PORTMAP
+#endif
+
+/*
+ * If PORTMAP is defined, rpcinfo will talk to both portmapper and
+ * rpcbind programs; else it talks only to rpcbind. In the latter case
+ * all the portmapper specific options such as -u, -t, -p become void.
+ */
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/rpcent.h>
+#include <rpc/nettype.h>
+#include <rpc/rpc_com.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <ctype.h>
+
+#ifdef PORTMAP /* Support for version 2 portmapper */
+#include <netinet/in.h>
+#include <netdb.h>
+#include <arpa/inet.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#endif
+
+#define max(a,b) ((a) > (b) ? (a) : (b))
+
+#define MIN_VERS ((u_long)0)
+#define MAX_VERS ((u_long)4294967295UL)
+#define UNKNOWN "unknown"
+
+/*
+ * Functions to be performed.
+ */
+#define NONE 0 /* no function */
+#define PMAPDUMP 1 /* dump portmapper registrations */
+#define TCPPING 2 /* ping TCP service */
+#define UDPPING 3 /* ping UDP service */
+#define BROADCAST 4 /* ping broadcast service */
+#define DELETES 5 /* delete registration for the service */
+#define ADDRPING 6 /* pings at the given address */
+#define PROGPING 7 /* pings a program on a given host */
+#define RPCBDUMP 8 /* dump rpcbind registrations */
+#define RPCBDUMP_SHORT 9 /* dump rpcbind registrations - short version */
+#define RPCBADDRLIST 10 /* dump addr list about one prog */
+#define RPCBGETSTAT 11 /* Get statistics */
+
+struct netidlist
+{
+ char *netid;
+ struct netidlist *next;
+};
+
+struct verslist
+{
+ int vers;
+ struct verslist *next;
+};
+
+struct rpcbdump_short
+{
+ u_long prog;
+ struct verslist *vlist;
+ struct netidlist *nlist;
+ struct rpcbdump_short *next;
+ char *owner;
+};
+
+
+#ifdef PORTMAP
+static void ip_ping (u_short, char *, int, char **);
+static void pmapdump (int, char **);
+static CLIENT *ip_getclient(const char *hostname, rpcprog_t prognum, rpcvers_t versnum, const char *proto);
+#endif
+
+static bool_t reply_proc (void *, struct netbuf *, struct netconfig *);
+static void brdcst (int, char **);
+static void addrping (char *, char *, int, char **);
+static void progping (char *, int, char **);
+static CLIENT *clnt_addr_create (char *, struct netconfig *, u_long, u_long);
+static CLIENT *clnt_rpcbind_create (char *, int, struct netbuf **);
+static CLIENT *getclnthandle (char *, struct netconfig *, u_long,
+ struct netbuf **);
+static int pstatus (CLIENT *, u_long, u_long);
+static void rpcbdump (int, char *, int, char **);
+static void rpcbgetstat (int, char **);
+static void rpcbaddrlist (char *, int, char **);
+static void deletereg (char *, int, char **);
+static void print_rmtcallstat (int, rpcb_stat *);
+static void print_getaddrstat (int, rpcb_stat *);
+static void usage (void);
+static u_long getprognum (char *);
+static u_long getvers (char *);
+static char *spaces (int);
+static bool_t add_version (struct rpcbdump_short *, u_long);
+static bool_t add_netid (struct rpcbdump_short *, char *);
+
+int main (int argc, char **argv);
+
+int
+main (int argc, char **argv)
+{
+ register int c;
+ int errflg;
+ int function;
+ char *netid = NULL;
+ char *address = NULL;
+#ifdef PORTMAP
+ char *strptr;
+ u_short portnum = 0;
+#endif
+
+ function = NONE;
+ errflg = 0;
+#ifdef PORTMAP
+ while ((c = getopt (argc, argv, "a:bdlmn:pstT:u")) != -1)
+#else
+ while ((c = getopt (argc, argv, "a:bdlmn:sT:")) != -1)
+#endif
+ {
+ switch (c)
+ {
+#ifdef PORTMAP
+ case 'p':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = PMAPDUMP;
+ break;
+
+ case 't':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = TCPPING;
+ break;
+
+ case 'u':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = UDPPING;
+ break;
+
+ case 'n':
+ portnum = (u_short) strtol (optarg, &strptr, 10);
+ if (strptr == optarg || *strptr != '\0')
+ {
+ fprintf (stderr, "rpcinfo: %s is illegal port number\n",
+ optarg);
+ exit (1);
+ }
+ break;
+#endif
+
+ case 'a':
+ address = optarg;
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = ADDRPING;
+ break;
+
+ case 'b':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = BROADCAST;
+ break;
+
+ case 'd':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = DELETES;
+ break;
+
+ case 'l':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBADDRLIST;
+ break;
+
+ case 'm':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBGETSTAT;
+ break;
+
+ case 's':
+ if (function != NONE)
+ errflg = 1;
+ else
+ function = RPCBDUMP_SHORT;
+ break;
+
+ case 'T':
+ netid = optarg;
+ break;
+ case '?':
+ errflg = 1;
+ break;
+ }
+ }
+
+ if (errflg || ((function == ADDRPING) && !netid))
+ {
+ usage ();
+ return 1;
+ }
+
+ if (function == NONE)
+ {
+ if (argc - optind > 1)
+ function = PROGPING;
+ else
+ function = RPCBDUMP;
+ }
+
+ switch (function)
+ {
+#ifdef PORTMAP
+ case PMAPDUMP:
+ if (portnum != 0)
+ {
+ usage ();
+ return 1;
+ }
+ pmapdump (argc - optind, argv + optind);
+ break;
+
+ case UDPPING:
+ ip_ping (portnum, "udp", argc - optind, argv + optind);
+ break;
+
+ case TCPPING:
+ ip_ping (portnum, "tcp", argc - optind, argv + optind);
+ break;
+#endif
+ case BROADCAST:
+ brdcst (argc - optind, argv + optind);
+ break;
+ case DELETES:
+ deletereg (netid, argc - optind, argv + optind);
+ break;
+ case ADDRPING:
+ addrping (address, netid, argc - optind, argv + optind);
+ break;
+ case PROGPING:
+ progping (netid, argc - optind, argv + optind);
+ break;
+ case RPCBDUMP:
+ case RPCBDUMP_SHORT:
+ rpcbdump (function, netid, argc - optind, argv + optind);
+ break;
+ case RPCBGETSTAT:
+ rpcbgetstat (argc - optind, argv + optind);
+ break;
+ case RPCBADDRLIST:
+ rpcbaddrlist (netid, argc - optind, argv + optind);
+ break;
+ }
+ return (0);
+}
+
+static CLIENT *
+local_rpcb (rpcprog_t prog, rpcvers_t vers)
+{
+#if 0
+ void *localhandle;
+ struct netconfig *nconf;
+ CLIENT *clnt;
+
+ localhandle = setnetconfig();
+ while ((nconf = getnetconfig(localhandle)) != NULL) {
+ if (nconf->nc_protofmly != NULL &&
+ strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+ break;
+ }
+ if (nconf == NULL) {
+ warnx("getnetconfig: %s", nc_sperror());
+ return (NULL);
+ }
+
+ clnt = clnt_tp_create (/* "localhost"*/ NULL, prog, vers, nconf);
+ endnetconfig(localhandle);
+ return clnt;
+#else
+ struct netbuf nbuf;
+ struct sockaddr_un sun;
+ int sock;
+
+ memset (&sun, 0, sizeof sun);
+ sock = socket (AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ return NULL;
+
+ 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;
+
+ return clnt_vc_create (sock, &nbuf, prog, vers, 0, 0);
+#endif
+}
+
+#ifdef PORTMAP
+static enum clnt_stat
+ip_ping_one(client, vers)
+ CLIENT *client;
+ u_int32_t vers;
+{
+ struct timeval to = { .tv_sec = 10, .tv_usec = 0 };
+
+ (void) CLNT_CONTROL (client, CLSET_VERS, &vers);
+ return CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void, (char *) NULL,
+ to);
+}
+
+/*
+ * If portnum is 0, then go and get the address from portmapper, which happens
+ * transparently through clnt*_create(); If version number is not given, it
+ * tries to find out the version number by making a call to version 0 and if
+ * that fails, it obtains the high order and the low order version number. If
+ * version 0 calls succeeds, it tries for MAXVERS call and repeats the same.
+ */
+static void
+ip_ping (portnum, proto, argc, argv)
+ u_short portnum;
+ char *proto;
+ int argc;
+ char **argv;
+{
+ CLIENT *client;
+ enum clnt_stat rpc_stat;
+ const char *hostname;
+ u_long prognum, vers, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+
+ if (argc < 2 || argc > 3)
+ {
+ usage ();
+ exit (1);
+ }
+
+ hostname = argv[0];
+ prognum = getprognum (argv[1]);
+ if (argc == 2)
+ { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ vers = MIN_VERS;
+ }
+ else
+ {
+ vers = getvers (argv[2]);
+ }
+
+ client = ip_getclient(hostname, prognum, vers, proto);
+
+ rpc_stat = ip_ping_one(client, vers);
+ if (argc != 2)
+ {
+ /* Version number was known */
+ if (pstatus (client, prognum, vers) < 0)
+ exit (1);
+ (void) CLNT_DESTROY (client);
+ return;
+ }
+
+ /* Version number not known */
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ rpc_stat = ip_ping_one(client, MAX_VERS);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ }
+ else
+ {
+ (void) pstatus (client, prognum, MAX_VERS);
+ exit (1);
+ }
+ }
+ else
+ {
+ (void) pstatus (client, prognum, (u_long) 0);
+ exit (1);
+ }
+ for (vers = minvers; vers <= maxvers; vers++)
+ {
+ rpc_stat = ip_ping_one(client, vers);
+ if (pstatus (client, prognum, vers) < 0)
+ failure = 1;
+ }
+ if (failure)
+ exit (1);
+ (void) CLNT_DESTROY (client);
+ return;
+}
+
+/*
+ * Dump all the portmapper registerations
+ */
+static void
+pmapdump (argc, argv)
+ int argc;
+ char **argv;
+{
+ struct pmaplist *head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ enum clnt_stat clnt_st;
+ struct rpc_err err;
+ char *host = NULL;
+
+ if (argc > 1)
+ {
+ usage ();
+ exit (1);
+ }
+ if (argc == 1)
+ {
+ host = argv[0];
+
+ /* This is a little bit more complicated than it should be.
+ * ip_getclient will do an rpcb_getaddr call to identify the
+ * port of the portmapper - but it works, and it's easier than
+ * creating a copy of ip_getclient that avoids the getaddr call.
+ */
+ client = ip_getclient(host, PMAPPROG, PMAPVERS, "tcp");
+ }
+ else
+ client = local_rpcb (PMAPPROG, PMAPVERS);
+
+ if (client == NULL)
+ {
+ if (rpc_createerr.cf_stat == RPC_TLIERROR)
+ {
+ /*
+ * "Misc. TLI error" is not too helpful. Most likely
+ * the connection to the remote server timed out, so
+ * this error is at least less perplexing.
+ */
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ rpc_createerr.cf_error.re_status = RPC_FAILED;
+ }
+ clnt_pcreateerror ("rpcinfo: can't contact portmapper");
+ exit (1);
+ }
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+
+ clnt_st = CLNT_CALL (client, PMAPPROC_DUMP, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_pmaplist_ptr, (char *) &head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) || (clnt_st == RPC_PROGUNAVAIL))
+ {
+ CLNT_GETERR (client, &err);
+ if (err.re_vers.low > PMAPVERS)
+ fprintf (stderr,
+ "%s does not support portmapper. Try rpcinfo %s instead\n",
+ host, host);
+ exit (1);
+ }
+ clnt_perror (client, "rpcinfo: can't contact portmapper");
+ exit (1);
+ }
+ if (head == NULL)
+ {
+ printf ("No remote programs registered.\n");
+ }
+ else
+ {
+ printf (" program vers proto port service\n");
+ for (; head != NULL; head = head->pml_next)
+ {
+ printf ("%10ld%5ld", head->pml_map.pm_prog, head->pml_map.pm_vers);
+ if (head->pml_map.pm_prot == IPPROTO_UDP)
+ printf ("%6s", "udp");
+ else if (head->pml_map.pm_prot == IPPROTO_TCP)
+ printf ("%6s", "tcp");
+ else
+ printf ("%6ld", head->pml_map.pm_prot);
+ printf ("%7ld", head->pml_map.pm_port);
+ rpc = getrpcbynumber (head->pml_map.pm_prog);
+ if (rpc)
+ printf (" %s\n", rpc->r_name);
+ else
+ printf ("\n");
+ }
+ }
+}
+
+/*
+ * Try to obtain the address of a given host/program/version, using the
+ * specified protocol (one of udp or tcp).
+ * This loops over all netconfig entries (according to the order given by
+ * netpath and the config file), and tries to resolve the hostname, and obtain
+ * the address using rpcb_getaddr.
+ */
+CLIENT *
+ip_getclient(hostname, prognum, versnum, proto)
+ const char *hostname;
+ rpcprog_t prognum;
+ rpcvers_t versnum;
+ const char *proto;
+{
+ void *handle;
+ enum clnt_stat saved_stat = RPC_SUCCESS;
+ struct netconfig *nconf, *result = NULL;
+ struct netbuf bind_address;
+ struct sockaddr_storage __sa;
+ CLIENT *client;
+
+ memset(&bind_address, 0, sizeof(bind_address));
+ bind_address.maxlen = sizeof(__sa);
+ bind_address.buf = &__sa;
+
+ handle = setnetconfig();
+ while ((nconf = getnetconfig(handle)) != NULL)
+ {
+ if (!strcmp(nconf->nc_proto, proto)) {
+ if (rpcb_getaddr(prognum, versnum, nconf, &bind_address, hostname))
+ {
+ result = getnetconfigent(nconf->nc_netid);
+ endnetconfig(handle);
+ break;
+ }
+
+ if (rpc_createerr.cf_stat != RPC_UNKNOWNHOST)
+ {
+ clnt_pcreateerror (hostname);
+ exit (1);
+ }
+
+ saved_stat = rpc_createerr.cf_stat;
+ }
+ }
+
+ if (result == NULL)
+ {
+ if (saved_stat != RPC_SUCCESS)
+ {
+ rpc_createerr.cf_stat = saved_stat;
+ clnt_pcreateerror (hostname);
+ }
+ else
+ fprintf (stderr, "Cannot find suitable transport for protocol %s\n", proto);
+
+ exit (1);
+ }
+
+ client = clnt_tli_create(RPC_ANYFD, result, &bind_address, prognum, versnum, 0, 0);
+ if (client == NULL)
+ {
+ clnt_pcreateerror(hostname);
+ exit (1);
+ }
+
+ freenetconfigent(result);
+ return client;
+}
+#endif /* PORTMAP */
+
+static int
+sa_len(struct sockaddr *sa)
+{
+ socklen_t salen;
+
+ switch (sa->sa_family)
+ {
+ case AF_LOCAL:
+ salen = sizeof (struct sockaddr_un);
+ break;
+ case AF_INET:
+ salen = sizeof (struct sockaddr_in);
+ break;
+ case AF_INET6:
+ salen = sizeof (struct sockaddr_in6);
+ break;
+ default:
+ salen = 0;
+ break;
+ }
+ return salen;
+}
+
+/*
+ * reply_proc collects replies from the broadcast.
+ * to get a unique list of responses the output of rpcinfo should
+ * be piped through sort(1) and then uniq(1).
+ */
+
+ /*ARGSUSED*/ static bool_t
+reply_proc (res, who, nconf)
+ void *res; /* Nothing comes back */
+ struct netbuf *who; /* Who sent us the reply */
+ struct netconfig *nconf; /* On which transport the reply came */
+{
+ char *uaddr;
+ char hostbuf[NI_MAXHOST];
+ char *hostname;
+ struct sockaddr *sa = (struct sockaddr *) who->buf;
+
+ if (getnameinfo (sa, sa_len (sa), hostbuf, NI_MAXHOST, NULL, 0, 0))
+ {
+ hostname = UNKNOWN;
+ }
+ else
+ {
+ hostname = hostbuf;
+ }
+ if (!(uaddr = taddr2uaddr (nconf, who)))
+ {
+ printf ("%s\t%s\n", UNKNOWN, hostname);
+ } else {
+ printf ("%s\t%s\n", uaddr, hostname);
+ free ((char *) uaddr);
+ }
+ return (FALSE);
+}
+
+static void
+brdcst (argc, argv)
+ int argc;
+ char **argv;
+{
+ enum clnt_stat rpc_stat;
+ u_long prognum, vers;
+
+ if (argc != 2)
+ {
+ usage ();
+ exit (1);
+ }
+ prognum = getprognum (argv[0]);
+ vers = getvers (argv[1]);
+ rpc_stat = rpc_broadcast (prognum, vers, NULLPROC,
+ (xdrproc_t) xdr_void, (char *) NULL,
+ (xdrproc_t) xdr_void, (char *) NULL,
+ (resultproc_t) reply_proc, NULL);
+ if ((rpc_stat != RPC_SUCCESS) && (rpc_stat != RPC_TIMEDOUT))
+ {
+ fprintf (stderr, "rpcinfo: broadcast failed: %s\n",
+ clnt_sperrno (rpc_stat));
+ exit (1);
+ }
+ exit (0);
+}
+
+static bool_t
+add_version (rs, vers)
+ struct rpcbdump_short *rs;
+ u_long vers;
+{
+ struct verslist *vl;
+
+ for (vl = rs->vlist; vl; vl = vl->next)
+ if (vl->vers == vers)
+ break;
+ if (vl)
+ return (TRUE);
+ vl = (struct verslist *) malloc (sizeof (struct verslist));
+ if (vl == NULL)
+ return (FALSE);
+ vl->vers = vers;
+ vl->next = rs->vlist;
+ rs->vlist = vl;
+ return (TRUE);
+}
+
+static bool_t
+add_netid (rs, netid)
+ struct rpcbdump_short *rs;
+ char *netid;
+{
+ struct netidlist *nl;
+
+ for (nl = rs->nlist; nl; nl = nl->next)
+ if (strcmp (nl->netid, netid) == 0)
+ break;
+ if (nl)
+ return (TRUE);
+ nl = (struct netidlist *) malloc (sizeof (struct netidlist));
+ if (nl == NULL)
+ return (FALSE);
+ nl->netid = netid;
+ nl->next = rs->nlist;
+ rs->nlist = nl;
+ return (TRUE);
+}
+
+static void
+rpcbdump (dumptype, netid, argc, argv)
+ int dumptype;
+ char *netid;
+ int argc;
+ char **argv;
+{
+ rpcblist_ptr head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ char *host;
+ struct netidlist *nl;
+ struct verslist *vl;
+ struct rpcbdump_short *rs, *rs_tail = NULL;
+ char buf[256];
+ enum clnt_stat clnt_st;
+ struct rpc_err err;
+ struct rpcbdump_short *rs_head = NULL;
+
+ if (argc > 1)
+ {
+ usage ();
+ exit (1);
+ }
+ if (argc == 1)
+ {
+ host = argv[0];
+ if (netid == NULL)
+ {
+ client = clnt_rpcbind_create (host, RPCBVERS, NULL);
+ }
+ else
+ {
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent (netid);
+ if (nconf == NULL)
+ {
+ nc_perror ("rpcinfo: invalid transport");
+ exit (1);
+ }
+ client = getclnthandle (host, nconf, RPCBVERS, NULL);
+ if (nconf)
+ (void) freenetconfigent (nconf);
+ }
+ }
+ else
+ client = local_rpcb (PMAPPROG, RPCBVERS);
+
+ if (client == (CLIENT *) NULL)
+ {
+ clnt_pcreateerror ("rpcinfo: can't contact rpcbind");
+ exit (1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ clnt_st = CLNT_CALL (client, RPCBPROC_DUMP, (xdrproc_t) xdr_void,
+ NULL, (xdrproc_t) xdr_rpcblist_ptr, (char *) &head,
+ minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) || (clnt_st == RPC_PROGUNAVAIL))
+ {
+ int vers;
+
+ CLNT_GETERR (client, &err);
+ if (err.re_vers.low == RPCBVERS4)
+ {
+ vers = RPCBVERS4;
+ clnt_control (client, CLSET_VERS, (char *) &vers);
+ clnt_st = CLNT_CALL (client, RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_rpcblist_ptr,
+ (char *) &head, minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ goto failed;
+ }
+ else
+ {
+ if (err.re_vers.high == PMAPVERS)
+ {
+ int high, low;
+ struct pmaplist *pmaphead = NULL;
+ rpcblist_ptr list, prev = NULL;
+
+ vers = PMAPVERS;
+ clnt_control (client, CLSET_VERS, (char *) &vers);
+ clnt_st = CLNT_CALL (client, PMAPPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_pmaplist_ptr,
+ (char *) &pmaphead, minutetimeout);
+ if (clnt_st != RPC_SUCCESS)
+ goto failed;
+ /*
+ * convert to rpcblist_ptr format
+ */
+ for (head = NULL; pmaphead != NULL;
+ pmaphead = pmaphead->pml_next)
+ {
+ list = (rpcblist *) malloc (sizeof (rpcblist));
+ if (list == NULL)
+ goto error;
+ if (head == NULL)
+ head = list;
+ else
+ prev->rpcb_next = (rpcblist_ptr) list;
+
+ list->rpcb_next = NULL;
+ list->rpcb_map.r_prog = pmaphead->pml_map.pm_prog;
+ list->rpcb_map.r_vers = pmaphead->pml_map.pm_vers;
+ if (pmaphead->pml_map.pm_prot == IPPROTO_UDP)
+ list->rpcb_map.r_netid = "udp";
+ else if (pmaphead->pml_map.pm_prot == IPPROTO_TCP)
+ list->rpcb_map.r_netid = "tcp";
+ else
+ {
+#define MAXLONG_AS_STRING "2147483648"
+ list->rpcb_map.r_netid =
+ malloc (strlen (MAXLONG_AS_STRING) + 1);
+ if (list->rpcb_map.r_netid == NULL)
+ goto error;
+ sprintf (list->rpcb_map.r_netid, "%6ld",
+ pmaphead->pml_map.pm_prot);
+ }
+ list->rpcb_map.r_owner = UNKNOWN;
+ low = pmaphead->pml_map.pm_port & 0xff;
+ high = (pmaphead->pml_map.pm_port >> 8) & 0xff;
+ list->rpcb_map.r_addr = strdup ("0.0.0.0.XXX.XXX");
+ sprintf (&list->rpcb_map.r_addr[8], "%d.%d", high, low);
+ prev = list;
+ }
+ }
+ }
+ }
+ else
+ { /* any other error */
+ failed:
+ clnt_perror (client, "rpcinfo: can't contact rpcbind: ");
+ exit (1);
+ }
+ }
+ if (head == NULL)
+ {
+ printf ("No remote programs registered.\n");
+ }
+ else if (dumptype == RPCBDUMP)
+ {
+ printf
+ (" program version netid address service owner\n");
+ for (; head != NULL; head = head->rpcb_next)
+ {
+ printf ("%10u%5u ",
+ head->rpcb_map.r_prog, head->rpcb_map.r_vers);
+ printf ("%-9s ", head->rpcb_map.r_netid);
+ printf ("%-22s", head->rpcb_map.r_addr);
+ rpc = getrpcbynumber (head->rpcb_map.r_prog);
+ if (rpc)
+ printf (" %-10s", rpc->r_name);
+ else
+ printf (" %-10s", "-");
+ printf (" %s\n", head->rpcb_map.r_owner);
+ }
+ }
+ else if (dumptype == RPCBDUMP_SHORT)
+ {
+ for (; head != NULL; head = head->rpcb_next)
+ {
+ for (rs = rs_head; rs; rs = rs->next)
+ if (head->rpcb_map.r_prog == rs->prog)
+ break;
+ if (rs == NULL)
+ {
+ rs = (struct rpcbdump_short *)
+ malloc (sizeof (struct rpcbdump_short));
+ if (rs == NULL)
+ goto error;
+ rs->next = NULL;
+ if (rs_head == NULL)
+ {
+ rs_head = rs;
+ rs_tail = rs;
+ }
+ else
+ {
+ rs_tail->next = rs;
+ rs_tail = rs;
+ }
+ rs->prog = head->rpcb_map.r_prog;
+ rs->owner = head->rpcb_map.r_owner;
+ rs->nlist = NULL;
+ rs->vlist = NULL;
+ }
+ if (add_version (rs, head->rpcb_map.r_vers) == FALSE)
+ goto error;
+ if (add_netid (rs, head->rpcb_map.r_netid) == FALSE)
+ goto error;
+ }
+ printf
+ (" program version(s) netid(s) service owner\n");
+ for (rs = rs_head; rs; rs = rs->next)
+ {
+ size_t netidmax = sizeof(buf) - 1;
+ char *p = buf;
+
+ printf ("%10ld ", rs->prog);
+ for (vl = rs->vlist; vl; vl = vl->next)
+ {
+ sprintf (p, "%d", vl->vers);
+ p = p + strlen (p);
+ if (vl->next)
+ sprintf (p++, ",");
+ }
+ printf ("%-10s", buf);
+ buf[0] = '\0';
+
+ for (nl = rs->nlist; nl; nl = nl->next)
+ {
+ strncat (buf, nl->netid, netidmax);
+ if (strlen (nl->netid) < netidmax)
+ netidmax -= strlen(nl->netid);
+ else
+ break;
+
+ if (nl->next && netidmax > 1)
+ {
+ strncat (buf, ",", netidmax);
+ netidmax --;
+ }
+ }
+
+ printf ("%-32s", buf);
+ rpc = getrpcbynumber (rs->prog);
+ if (rpc)
+ printf (" %-11s", rpc->r_name);
+ else
+ printf (" %-11s", "-");
+ printf (" %s\n", rs->owner);
+ }
+ }
+ clnt_destroy (client);
+ return;
+error:fprintf (stderr, "rpcinfo: no memory\n");
+ return;
+}
+
+static char nullstring[] = "\000";
+
+static void
+rpcbaddrlist (netid, argc, argv)
+ char *netid;
+ int argc;
+ char **argv;
+{
+ rpcb_entry_list_ptr head = NULL;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ struct rpcent *rpc;
+ char *host;
+ RPCB parms;
+ struct netbuf *targaddr;
+
+ if (argc != 3)
+ {
+ usage ();
+ exit (1);
+ }
+ host = argv[0];
+ if (netid == NULL)
+ {
+ client = clnt_rpcbind_create (host, RPCBVERS4, &targaddr);
+ }
+ else
+ {
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent (netid);
+ if (nconf == NULL)
+ {
+ nc_perror ("rpcinfo: invalid transport");
+ exit (1);
+ }
+ client = getclnthandle (host, nconf, RPCBVERS4, &targaddr);
+ if (nconf)
+ (void) freenetconfigent (nconf);
+ }
+ if (client == (CLIENT *) NULL)
+ {
+ clnt_pcreateerror ("rpcinfo: can't contact rpcbind");
+ exit (1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+
+ parms.r_prog = getprognum (argv[1]);
+ parms.r_vers = getvers (argv[2]);
+ parms.r_netid = client->cl_netid;
+ if (targaddr == NULL)
+ {
+ parms.r_addr = nullstring; /* for XDRing */
+ }
+ else
+ {
+ /*
+ * We also send the remote system the address we
+ * used to contact it in case it can help it
+ * connect back with us
+ */
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent (client->cl_netid);
+ if (nconf != NULL)
+ {
+ parms.r_addr = taddr2uaddr (nconf, targaddr);
+ if (parms.r_addr == NULL)
+ parms.r_addr = nullstring;
+ freenetconfigent (nconf);
+ }
+ else
+ {
+ parms.r_addr = nullstring; /* for XDRing */
+ }
+ free (targaddr->buf);
+ free (targaddr);
+ }
+ parms.r_owner = nullstring;
+
+ if (CLNT_CALL (client, RPCBPROC_GETADDRLIST, (xdrproc_t) xdr_rpcb,
+ (char *) &parms, (xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *) &head, minutetimeout) != RPC_SUCCESS)
+ {
+ clnt_perror (client, "rpcinfo: can't contact rpcbind: ");
+ exit (1);
+ }
+ if (head == NULL)
+ {
+ printf ("No remote programs registered.\n");
+ }
+ else
+ {
+ printf
+ (" program vers tp_family/name/class address\t\t service\n");
+ for (; head != NULL; head = head->rpcb_entry_next)
+ {
+ rpcb_entry *re;
+ char buf[128];
+
+ re = &head->rpcb_entry_map;
+ printf ("%10u%3u ", parms.r_prog, parms.r_vers);
+ sprintf (buf, "%s/%s/%s ",
+ re->r_nc_protofmly, re->r_nc_proto,
+ re->r_nc_semantics == NC_TPI_CLTS ? "clts" :
+ re->r_nc_semantics == NC_TPI_COTS ? "cots" : "cots_ord");
+ printf ("%-24s", buf);
+ printf ("%-24s", re->r_maddr);
+ rpc = getrpcbynumber (parms.r_prog);
+ if (rpc)
+ printf (" %-13s", rpc->r_name);
+ else
+ printf (" %-13s", "-");
+ printf ("\n");
+ }
+ }
+ clnt_destroy (client);
+ return;
+}
+
+/*
+ * monitor rpcbind
+ */
+static void
+rpcbgetstat (argc, argv)
+ int argc;
+ char **argv;
+{
+ rpcb_stat_byvers inf;
+ struct timeval minutetimeout;
+ register CLIENT *client;
+ char *host;
+ int i, j;
+ rpcbs_addrlist *pa;
+ rpcbs_rmtcalllist *pr;
+ int cnt, flen;
+#define MAXFIELD 64
+ char fieldbuf[MAXFIELD];
+#define MAXLINE 256
+ char linebuf[MAXLINE];
+ char *cp, *lp;
+ char *pmaphdr[] = {
+ "NULL", "SET", "UNSET", "GETPORT",
+ "DUMP", "CALLIT"
+ };
+ char *rpcb3hdr[] = {
+ "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
+ "U2T", "T2U"
+ };
+ char *rpcb4hdr[] = {
+ "NULL", "SET", "UNSET", "GETADDR", "DUMP", "CALLIT", "TIME",
+ "U2T", "T2U", "VERADDR", "INDRECT", "GETLIST", "GETSTAT"
+ };
+
+#define TABSTOP 8
+
+ if (argc >= 1)
+ {
+ host = argv[0];
+ client = clnt_rpcbind_create (host, RPCBVERS4, NULL);
+ }
+ else
+ client = local_rpcb (PMAPPROG, RPCBVERS4);
+ if (client == (CLIENT *) NULL)
+ {
+ clnt_pcreateerror ("rpcinfo: can't contact rpcbind");
+ exit (1);
+ }
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ memset ((char *) &inf, 0, sizeof (rpcb_stat_byvers));
+ if (CLNT_CALL (client, RPCBPROC_GETSTAT, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_rpcb_stat_byvers, (char *) &inf,
+ minutetimeout) != RPC_SUCCESS)
+ {
+ clnt_perror (client, "rpcinfo: can't contact rpcbind: ");
+ exit (1);
+ }
+ printf ("PORTMAP (version 2) statistics\n");
+ lp = linebuf;
+ for (i = 0; i <= rpcb_highproc_2; i++)
+ {
+ fieldbuf[0] = '\0';
+ switch (i)
+ {
+ case PMAPPROC_SET:
+ sprintf (fieldbuf, "%d/", inf[RPCBVERS_2_STAT].setinfo);
+ break;
+ case PMAPPROC_UNSET:
+ sprintf (fieldbuf, "%d/", inf[RPCBVERS_2_STAT].unsetinfo);
+ break;
+ case PMAPPROC_GETPORT:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_2_STAT].addrinfo; pa; pa = pa->next)
+ cnt += pa->success;
+ sprintf (fieldbuf, "%d/", cnt);
+ break;
+ case PMAPPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_2_STAT].rmtinfo; pr; pr = pr->next)
+ cnt += pr->success;
+ sprintf (fieldbuf, "%d/", cnt);
+ break;
+ default:
+ break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen (fieldbuf);
+ sprintf (cp, "%d", inf[RPCBVERS_2_STAT].info[i]);
+ flen = strlen (fieldbuf);
+ printf ("%s%s", pmaphdr[i],
+ spaces ((TABSTOP * (1 + flen / TABSTOP))
+ - strlen (pmaphdr[i])));
+ sprintf (lp, "%s%s", fieldbuf,
+ spaces (cnt = ((TABSTOP * (1 + flen / TABSTOP)) - flen)));
+ lp += (flen + cnt);
+ }
+ printf ("\n%s\n\n", linebuf);
+
+ if (inf[RPCBVERS_2_STAT].info[PMAPPROC_CALLIT])
+ {
+ printf ("PMAP_RMTCALL call statistics\n");
+ print_rmtcallstat (RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
+ printf ("\n");
+ }
+
+ if (inf[RPCBVERS_2_STAT].info[PMAPPROC_GETPORT])
+ {
+ printf ("PMAP_GETPORT call statistics\n");
+ print_getaddrstat (RPCBVERS_2_STAT, &inf[RPCBVERS_2_STAT]);
+ printf ("\n");
+ }
+
+ printf ("RPCBIND (version 3) statistics\n");
+ lp = linebuf;
+ for (i = 0; i <= rpcb_highproc_3; i++)
+ {
+ fieldbuf[0] = '\0';
+ switch (i)
+ {
+ case RPCBPROC_SET:
+ sprintf (fieldbuf, "%d/", inf[RPCBVERS_3_STAT].setinfo);
+ break;
+ case RPCBPROC_UNSET:
+ sprintf (fieldbuf, "%d/", inf[RPCBVERS_3_STAT].unsetinfo);
+ break;
+ case RPCBPROC_GETADDR:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_3_STAT].addrinfo; pa; pa = pa->next)
+ cnt += pa->success;
+ sprintf (fieldbuf, "%d/", cnt);
+ break;
+ case RPCBPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_3_STAT].rmtinfo; pr; pr = pr->next)
+ cnt += pr->success;
+ sprintf (fieldbuf, "%d/", cnt);
+ break;
+ default:
+ break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen (fieldbuf);
+ sprintf (cp, "%d", inf[RPCBVERS_3_STAT].info[i]);
+ flen = strlen (fieldbuf);
+ printf ("%s%s", rpcb3hdr[i],
+ spaces ((TABSTOP * (1 + flen / TABSTOP))
+ - strlen (rpcb3hdr[i])));
+ sprintf (lp, "%s%s", fieldbuf,
+ spaces (cnt = ((TABSTOP * (1 + flen / TABSTOP)) - flen)));
+ lp += (flen + cnt);
+ }
+ printf ("\n%s\n\n", linebuf);
+
+ if (inf[RPCBVERS_3_STAT].info[RPCBPROC_CALLIT])
+ {
+ printf ("RPCB_RMTCALL (version 3) call statistics\n");
+ print_rmtcallstat (RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
+ printf ("\n");
+ }
+
+ if (inf[RPCBVERS_3_STAT].info[RPCBPROC_GETADDR])
+ {
+ printf ("RPCB_GETADDR (version 3) call statistics\n");
+ print_getaddrstat (RPCBVERS_3_STAT, &inf[RPCBVERS_3_STAT]);
+ printf ("\n");
+ }
+
+ printf ("RPCBIND (version 4) statistics\n");
+
+ for (j = 0; j <= 9; j += 9)
+ { /* Just two iterations for printing */
+ lp = linebuf;
+ for (i = j; i <= max (8, rpcb_highproc_4 - 9 + j); i++)
+ {
+ fieldbuf[0] = '\0';
+ switch (i)
+ {
+ case RPCBPROC_SET:
+ sprintf (fieldbuf, "%d/", inf[RPCBVERS_4_STAT].setinfo);
+ break;
+ case RPCBPROC_UNSET:
+ sprintf (fieldbuf, "%d/", inf[RPCBVERS_4_STAT].unsetinfo);
+ break;
+ case RPCBPROC_GETADDR:
+ cnt = 0;
+ for (pa = inf[RPCBVERS_4_STAT].addrinfo; pa; pa = pa->next)
+ cnt += pa->success;
+ sprintf (fieldbuf, "%d/", cnt);
+ break;
+ case RPCBPROC_CALLIT:
+ cnt = 0;
+ for (pr = inf[RPCBVERS_4_STAT].rmtinfo; pr; pr = pr->next)
+ cnt += pr->success;
+ sprintf (fieldbuf, "%d/", cnt);
+ break;
+ default:
+ break; /* For the remaining ones */
+ }
+ cp = &fieldbuf[0] + strlen (fieldbuf);
+ /*
+ * XXX: We also add RPCBPROC_GETADDRLIST queries to
+ * RPCB_GETADDR because rpcbind includes the
+ * RPCB_GETADDRLIST successes in RPCB_GETADDR.
+ */
+ if (i != RPCBPROC_GETADDR)
+ sprintf (cp, "%d", inf[RPCBVERS_4_STAT].info[i]);
+ else
+ sprintf (cp, "%d", inf[RPCBVERS_4_STAT].info[i] +
+ inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDRLIST]);
+ flen = strlen (fieldbuf);
+ printf ("%s%s", rpcb4hdr[i],
+ spaces ((TABSTOP * (1 + flen / TABSTOP))
+ - strlen (rpcb4hdr[i])));
+ sprintf (lp, "%s%s", fieldbuf,
+ spaces (cnt = ((TABSTOP * (1 + flen / TABSTOP)) - flen)));
+ lp += (flen + cnt);
+ }
+ printf ("\n%s\n", linebuf);
+ }
+
+ if (inf[RPCBVERS_4_STAT].info[RPCBPROC_CALLIT] ||
+ inf[RPCBVERS_4_STAT].info[RPCBPROC_INDIRECT])
+ {
+ printf ("\n");
+ printf ("RPCB_RMTCALL (version 4) call statistics\n");
+ print_rmtcallstat (RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
+ }
+
+ if (inf[RPCBVERS_4_STAT].info[RPCBPROC_GETADDR])
+ {
+ printf ("\n");
+ printf ("RPCB_GETADDR (version 4) call statistics\n");
+ print_getaddrstat (RPCBVERS_4_STAT, &inf[RPCBVERS_4_STAT]);
+ }
+ clnt_destroy (client);
+}
+
+/*
+ * Delete registeration for this (prog, vers, netid)
+ */
+static void
+deletereg (netid, argc, argv)
+ char *netid;
+ int argc;
+ char **argv;
+{
+ struct netconfig *nconf = NULL;
+
+ if (argc != 2)
+ {
+ usage ();
+ exit (1);
+ }
+ if (netid)
+ {
+ nconf = getnetconfigent (netid);
+ if (nconf == NULL)
+ {
+ fprintf (stderr, "rpcinfo: netid %s not supported\n", netid);
+ exit (1);
+ }
+ }
+ if ((rpcb_unset (getprognum (argv[0]), getvers (argv[1]), nconf)) == 0)
+ {
+ fprintf (stderr,
+ "rpcinfo: Could not delete registration for prog %s version %s\n",
+ argv[0], argv[1]);
+ exit (1);
+ }
+}
+
+/*
+ * Create and return a handle for the given nconf.
+ * Exit if cannot create handle.
+ */
+static CLIENT *
+clnt_addr_create (address, nconf, prog, vers)
+ char *address;
+ struct netconfig *nconf;
+ u_long prog;
+ u_long vers;
+{
+ CLIENT *client;
+ static struct netbuf *nbuf;
+ static int fd = RPC_ANYFD;
+
+ if (fd == RPC_ANYFD)
+ {
+ if ((fd = __rpc_nconf2fd (nconf)) == -1)
+ {
+ rpc_createerr.cf_stat = RPC_TLIERROR;
+ clnt_pcreateerror ("rpcinfo");
+ exit (1);
+ }
+ /* Convert the uaddr to taddr */
+ nbuf = uaddr2taddr (nconf, address);
+ if (nbuf == NULL)
+ {
+ errx (1, "rpcinfo: no address for client handle");
+ exit (1);
+ }
+ }
+ client = clnt_tli_create (fd, nconf, nbuf, prog, vers, 0, 0);
+ if (client == (CLIENT *) NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ exit (1);
+ }
+ return (client);
+}
+
+/*
+ * If the version number is given, ping that (prog, vers); else try to find
+ * the version numbers supported for that prog and ping all the versions.
+ * Remote rpcbind is not contacted for this service. The requests are
+ * sent directly to the services themselves.
+ */
+static void
+addrping (address, netid, argc, argv)
+ char *address;
+ char *netid;
+ int argc;
+ char **argv;
+{
+ CLIENT *client;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ u_int32_t prognum, versnum, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+ struct netconfig *nconf;
+ int fd;
+
+ if (argc < 1 || argc > 2 || (netid == NULL))
+ {
+ usage ();
+ exit (1);
+ }
+ nconf = getnetconfigent (netid);
+ if (nconf == (struct netconfig *) NULL)
+ {
+ fprintf (stderr, "rpcinfo: Could not find %s\n", netid);
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ prognum = getprognum (argv[0]);
+ if (argc == 1)
+ { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ versnum = MIN_VERS;
+ }
+ else
+ {
+ versnum = getvers (argv[1]);
+ }
+ client = clnt_addr_create (address, nconf, prognum, versnum);
+ rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void,
+ (char *) NULL, to);
+ if (argc == 2)
+ {
+ /* Version number was known */
+ if (pstatus (client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY (client);
+ if (failure)
+ exit (1);
+ return;
+ }
+ /* Version number not known */
+ (void) CLNT_CONTROL (client, CLSET_FD_NCLOSE, (char *) NULL);
+ (void) CLNT_CONTROL (client, CLGET_FD, (char *) &fd);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ (void) CLNT_DESTROY (client);
+ client = clnt_addr_create (address, nconf, prognum, MAX_VERS);
+ rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void,
+ (char *) NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ }
+ else
+ {
+ (void) pstatus (client, prognum, MAX_VERS);
+ exit (1);
+ }
+ }
+ else
+ {
+ (void) pstatus (client, prognum, (u_long) 0);
+ exit (1);
+ }
+ (void) CLNT_DESTROY (client);
+ for (versnum = minvers; versnum <= maxvers; versnum++)
+ {
+ client = clnt_addr_create (address, nconf, prognum, versnum);
+ rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void,
+ (char *) NULL, to);
+ if (pstatus (client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY (client);
+ }
+ (void) close (fd);
+ if (failure)
+ exit (1);
+ return;
+}
+
+/*
+ * If the version number is given, ping that (prog, vers); else try to find
+ * the version numbers supported for that prog and ping all the versions.
+ * Remote rpcbind is *contacted* for this service. The requests are
+ * then sent directly to the services themselves.
+ */
+static void
+progping (netid, argc, argv)
+ char *netid;
+ int argc;
+ char **argv;
+{
+ CLIENT *client;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ u_int32_t prognum, versnum, minvers, maxvers;
+ struct rpc_err rpcerr;
+ int failure = 0;
+ struct netconfig *nconf;
+
+ if (argc < 2 || argc > 3 || (netid == NULL))
+ {
+ usage ();
+ exit (1);
+ }
+ prognum = getprognum (argv[1]);
+ if (argc == 2)
+ { /* Version number not known */
+ /*
+ * A call to version 0 should fail with a program/version
+ * mismatch, and give us the range of versions supported.
+ */
+ versnum = MIN_VERS;
+ }
+ else
+ {
+ versnum = getvers (argv[2]);
+ }
+ if (netid)
+ {
+ nconf = getnetconfigent (netid);
+ if (nconf == (struct netconfig *) NULL)
+ {
+ fprintf (stderr, "rpcinfo: Could not find %s\n", netid);
+ exit (1);
+ }
+ client = clnt_tp_create (argv[0], prognum, versnum, nconf);
+ }
+ else
+ {
+ client = clnt_create (argv[0], prognum, versnum, "NETPATH");
+ }
+ if (client == (CLIENT *) NULL)
+ {
+ clnt_pcreateerror ("rpcinfo");
+ exit (1);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void,
+ (char *) NULL, to);
+ if (argc == 3)
+ {
+ /* Version number was known */
+ if (pstatus (client, prognum, versnum) < 0)
+ failure = 1;
+ (void) CLNT_DESTROY (client);
+ if (failure)
+ exit (1);
+ return;
+ }
+ /* Version number not known */
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * Oh dear, it DOES support version 0.
+ * Let's try version MAX_VERS.
+ */
+ versnum = MAX_VERS;
+ (void) CLNT_CONTROL (client, CLSET_VERS, (char *) &versnum);
+ rpc_stat = CLNT_CALL (client, NULLPROC,
+ (xdrproc_t) xdr_void, (char *) NULL,
+ (xdrproc_t) xdr_void, (char *) NULL, to);
+ if (rpc_stat == RPC_PROGVERSMISMATCH)
+ {
+ clnt_geterr (client, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ }
+ else if (rpc_stat == RPC_SUCCESS)
+ {
+ /*
+ * It also supports version MAX_VERS.
+ * Looks like we have a wise guy.
+ * OK, we give them information on all
+ * 4 billion versions they support...
+ */
+ minvers = 0;
+ maxvers = MAX_VERS;
+ }
+ else
+ {
+ (void) pstatus (client, prognum, MAX_VERS);
+ exit (1);
+ }
+ }
+ else
+ {
+ (void) pstatus (client, prognum, (u_long) 0);
+ exit (1);
+ }
+ for (versnum = minvers; versnum <= maxvers; versnum++)
+ {
+ (void) CLNT_CONTROL (client, CLSET_VERS, (char *) &versnum);
+ rpc_stat = CLNT_CALL (client, NULLPROC, (xdrproc_t) xdr_void,
+ (char *) NULL, (xdrproc_t) xdr_void,
+ (char *) NULL, to);
+ if (pstatus (client, prognum, versnum) < 0)
+ failure = 1;
+ }
+ (void) CLNT_DESTROY (client);
+ if (failure)
+ exit (1);
+ return;
+}
+
+static void
+usage ()
+{
+ fprintf (stderr, "Usage: rpcinfo [-m | -s] [host]\n");
+#ifdef PORTMAP
+ fprintf (stderr, " rpcinfo -p [host]\n");
+#endif
+ fprintf (stderr, " rpcinfo -T netid host prognum [versnum]\n");
+ fprintf (stderr, " rpcinfo -l host prognum versnum\n");
+#ifdef PORTMAP
+ fprintf (stderr,
+ " rpcinfo [-n portnum] -u | -t host prognum [versnum]\n");
+#endif
+ fprintf (stderr,
+ " rpcinfo -a serv_address -T netid prognum [version]\n");
+ fprintf (stderr, " rpcinfo -b prognum versnum\n");
+ fprintf (stderr, " rpcinfo -d [-T netid] prognum versnum\n");
+}
+
+static u_long
+getprognum (arg)
+ char *arg;
+{
+ char *strptr;
+ register struct rpcent *rpc;
+ register u_long prognum;
+ char *tptr = arg;
+
+ while (*tptr && isdigit (*tptr++));
+ if (*tptr || isalpha (*(tptr - 1)))
+ {
+ rpc = getrpcbyname (arg);
+ if (rpc == NULL)
+ {
+ fprintf (stderr, "rpcinfo: %s is unknown service\n", arg);
+ exit (1);
+ }
+ prognum = rpc->r_number;
+ }
+ else
+ {
+ prognum = strtol (arg, &strptr, 10);
+ if (strptr == arg || *strptr != '\0')
+ {
+ fprintf (stderr, "rpcinfo: %s is illegal program number\n", arg);
+ exit (1);
+ }
+ }
+ return (prognum);
+}
+
+static u_long
+getvers (arg)
+ char *arg;
+{
+ char *strptr;
+ register u_long vers;
+
+ vers = (int) strtol (arg, &strptr, 10);
+ if (strptr == arg || *strptr != '\0')
+ {
+ fprintf (stderr, "rpcinfo: %s is illegal version number\n", arg);
+ exit (1);
+ }
+ return (vers);
+}
+
+/*
+ * This routine should take a pointer to an "rpc_err" structure, rather than
+ * a pointer to a CLIENT structure, but "clnt_perror" takes a pointer to
+ * a CLIENT structure rather than a pointer to an "rpc_err" structure.
+ * As such, we have to keep the CLIENT structure around in order to print
+ * a good error message.
+ */
+static int
+pstatus (client, prog, vers)
+ register CLIENT *client;
+ u_long prog;
+ u_long vers;
+{
+ struct rpc_err rpcerr;
+
+ clnt_geterr (client, &rpcerr);
+ if (rpcerr.re_status != RPC_SUCCESS)
+ {
+ clnt_perror (client, "rpcinfo");
+ printf ("program %lu version %lu is not available\n", prog, vers);
+ return (-1);
+ }
+ else
+ {
+ printf ("program %lu version %lu ready and waiting\n", prog, vers);
+ return (0);
+ }
+}
+
+static CLIENT *
+clnt_rpcbind_create (host, rpcbversnum, targaddr)
+ char *host;
+ int rpcbversnum;
+ struct netbuf **targaddr;
+{
+ static char *tlist[3] = {
+ "circuit_n", "circuit_v", "datagram_v"
+ };
+ int i;
+ struct netconfig *nconf;
+ CLIENT *clnt = NULL;
+ void *handle;
+
+ rpc_createerr.cf_stat = RPC_SUCCESS;
+ for (i = 0; i < 3; i++)
+ {
+ if ((handle = __rpc_setconf (tlist[i])) == NULL)
+ continue;
+ while (clnt == (CLIENT *) NULL)
+ {
+ if ((nconf = __rpc_getconf (handle)) == NULL)
+ {
+ if (rpc_createerr.cf_stat == RPC_SUCCESS)
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ break;
+ }
+ clnt = getclnthandle (host, nconf, rpcbversnum, targaddr);
+ }
+ if (clnt)
+ break;
+ __rpc_endconf (handle);
+ }
+ return (clnt);
+}
+
+static CLIENT *
+getclnthandle (host, nconf, rpcbversnum, targaddr)
+ char *host;
+ struct netconfig *nconf;
+ u_long rpcbversnum;
+ struct netbuf **targaddr;
+{
+ struct netbuf addr;
+ struct addrinfo hints, *res;
+ CLIENT *client = NULL;
+
+ /* Get the address of the rpcbind */
+ memset (&hints, 0, sizeof hints);
+ if ((getaddrinfo (host, "rpcbind", &hints, &res) != 0) &&
+ (getaddrinfo (host, "portmapper",&hints, &res) != 0))
+ {
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ return (NULL);
+ }
+ addr.len = addr.maxlen = res->ai_addrlen;
+ addr.buf = res->ai_addr;
+ client = clnt_tli_create (RPC_ANYFD, nconf, &addr, RPCBPROG,
+ rpcbversnum, 0, 0);
+ if (client)
+ {
+ if (targaddr != NULL)
+ {
+ *targaddr = (struct netbuf *) malloc (sizeof (struct netbuf));
+ if (*targaddr != NULL)
+ {
+ (*targaddr)->maxlen = addr.maxlen;
+ (*targaddr)->len = addr.len;
+ (*targaddr)->buf = (char *) malloc (addr.len);
+ if ((*targaddr)->buf != NULL)
+ {
+ memcpy ((*targaddr)->buf, addr.buf, addr.len);
+ }
+ }
+ }
+ }
+ else
+ {
+ if (rpc_createerr.cf_stat == RPC_TLIERROR)
+ {
+ /*
+ * Assume that the other system is dead; this is a
+ * better error to display to the user.
+ */
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ rpc_createerr.cf_error.re_status = RPC_FAILED;
+ }
+ }
+ freeaddrinfo (res);
+ return (client);
+}
+
+static void
+print_rmtcallstat (rtype, infp)
+ int rtype;
+ rpcb_stat *infp;
+{
+ register rpcbs_rmtcalllist_ptr pr;
+ struct rpcent *rpc;
+
+ if (rtype == RPCBVERS_4_STAT)
+ printf ("prog\t\tvers\tproc\tnetid\tindirect success failure\n");
+ else
+ printf ("prog\t\tvers\tproc\tnetid\tsuccess\tfailure\n");
+ for (pr = infp->rmtinfo; pr; pr = pr->next)
+ {
+ rpc = getrpcbynumber (pr->prog);
+ if (rpc)
+ printf ("%-16s", rpc->r_name);
+ else
+ printf ("%-16d", pr->prog);
+ printf ("%d\t%d\t%s\t", pr->vers, pr->proc, pr->netid);
+ if (rtype == RPCBVERS_4_STAT)
+ printf ("%d\t ", pr->indirect);
+ printf ("%d\t%d\n", pr->success, pr->failure);
+ }
+}
+
+static void
+print_getaddrstat (rtype, infp)
+ int rtype;
+ rpcb_stat *infp;
+{
+ rpcbs_addrlist_ptr al;
+ register struct rpcent *rpc;
+
+ printf ("prog\t\tvers\tnetid\t success\tfailure\n");
+ for (al = infp->addrinfo; al; al = al->next)
+ {
+ rpc = getrpcbynumber (al->prog);
+ if (rpc)
+ printf ("%-16s", rpc->r_name);
+ else
+ printf ("%-16d", al->prog);
+ printf ("%d\t%s\t %-12d\t%d\n",
+ al->vers, al->netid, al->success, al->failure);
+ }
+}
+
+static char *
+spaces (howmany)
+ int howmany;
+{
+ static char space_array[] = /* 64 spaces */
+ " ";
+
+ if (howmany <= 0 || howmany > sizeof (space_array))
+ {
+ return ("");
+ }
+ return (&space_array[sizeof (space_array) - howmany - 1]);
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/security.c
^
|
@@ -0,0 +1,353 @@
+/* $NetBSD: security.c,v 1.5 2000/06/08 09:01:05 fvdl Exp $ */
+/* $FreeBSD: src/usr.sbin/rpcbind/security.c,v 1.6 2002/12/16 22:24:26 mbr Exp $ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/pmap_prot.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <netdb.h>
+
+#include "xlog.h"
+
+/*
+ * XXX for special case checks in check_callit.
+ */
+#define MOUNTPROC_MNT 1
+#define MOUNTPROC_UMNT 3
+#define NFS_PROGRAM 100003
+#define YPPROG 100004
+#define MOUNTPROG 100005
+#define YPBINDPROG 100007
+#define YPPASSWDPROG 100009
+#define RQUOTAPROG 100011
+
+#define YPBINDPROC_SETDOM 2
+#define YPPROC_MATCH 3
+#define YPPROC_FIRST 4
+#define YPPROC_NEXT 5
+#define YPPROC_ALL 8
+
+#include "rpcbind.h"
+
+#ifdef LIBWRAP
+# include <tcpd.h>
+#ifndef LIBWRAP_ALLOW_FACILITY
+# define LIBWRAP_ALLOW_FACILITY LOG_AUTH
+#endif
+#ifndef LIBWRAP_ALLOW_SEVERITY
+# define LIBWRAP_ALLOW_SEVERITY LOG_INFO
+#endif
+#ifndef LIBWRAP_DENY_FACILITY
+# define LIBWRAP_DENY_FACILITY LOG_AUTH
+#endif
+#ifndef LIBWRAP_DENY_SEVERITY
+# define LIBWRAP_DENY_SEVERITY LOG_WARNING
+#endif
+int allow_severity = LIBWRAP_ALLOW_FACILITY|LIBWRAP_ALLOW_SEVERITY;
+int deny_severity = LIBWRAP_DENY_FACILITY|LIBWRAP_DENY_SEVERITY;
+#endif
+
+#ifndef PORTMAP_LOG_FACILITY
+# define PORTMAP_LOG_FACILITY LOG_AUTH
+#endif
+#ifndef PORTMAP_LOG_SEVERITY
+# define PORTMAP_LOG_SEVERITY LOG_INFO
+#endif
+#ifdef __linux__
+ #define IPV6PORT_RESERVED IPPORT_RESERVED
+#endif
+
+int log_severity = PORTMAP_LOG_FACILITY|PORTMAP_LOG_SEVERITY;
+
+extern int verboselog;
+
+int
+check_access(SVCXPRT *xprt, rpcproc_t proc, rpcprog_t prog, unsigned int rpcbvers)
+{
+ struct netbuf *caller = svc_getrpccaller(xprt);
+ struct sockaddr *addr = (struct sockaddr *)caller->buf;
+#ifdef LIBWRAP
+ struct request_info req;
+#endif
+
+ /*
+ * The older PMAP_* equivalents have the same numbers, so
+ * they are accounted for here as well.
+ */
+ switch (proc) {
+ case RPCBPROC_SET:
+ case RPCBPROC_UNSET:
+ if (!insecure && !is_loopback(caller)) {
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG, " declined (non-loopback sender) \n");
+#endif
+ if (verboselog)
+ logit(log_severity, addr, proc, prog,
+ " declined (non-loopback sender)");
+ return 0;
+ }
+ break;
+ case RPCBPROC_GETADDR:
+ case RPCBPROC_CALLIT:
+ case RPCBPROC_INDIRECT:
+ case RPCBPROC_DUMP:
+ case RPCBPROC_GETTIME:
+ case RPCBPROC_UADDR2TADDR:
+ case RPCBPROC_TADDR2UADDR:
+ case RPCBPROC_GETVERSADDR:
+ case RPCBPROC_GETADDRLIST:
+ case RPCBPROC_GETSTAT:
+ default:
+ break;
+ }
+
+#ifdef LIBWRAP
+ if (addr->sa_family == AF_LOCAL)
+ return 1;
+ request_init(&req, RQ_DAEMON, "rpcbind", RQ_CLIENT_SIN, addr, 0);
+ sock_methods(&req);
+ if(!hosts_access(&req)) {
+
+ logit(deny_severity, addr, proc, prog, ": request from unauthorized host");
+ return 0;
+ }
+#endif
+ if (verboselog)
+ logit(log_severity, addr, proc, prog, "");
+ return 1;
+}
+
+int
+is_loopback(struct netbuf *nbuf)
+{
+ struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ if (!oldstyle_local)
+ return 0;
+ sin = (struct sockaddr_in *)addr;
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "Checking caller's address (port = %d)\n",
+ ntohs(sin->sin_port));
+#endif
+ return (sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK));
+#ifdef INET6
+ case AF_INET6:
+ if (!oldstyle_local)
+ return 0;
+ sin6 = (struct sockaddr_in6 *)addr;
+#ifdef RPCBIND_DEBUG
+ if (debugging)
+ xlog(LOG_DEBUG,
+ "Checking caller's address (port = %d)\n",
+ ntohs(sin6->sin6_port));
+#endif
+ return (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) ||
+ (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&
+ sin6->sin6_addr.s6_addr32[3] == htonl(INADDR_LOOPBACK)));
+#endif
+ case AF_LOCAL:
+ return 1;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * For IPv4/v6, this is exactly the same as is_loopback for now.
+ * The difference is that this returns false for other transports.
+ */
+int
+is_localroot(struct netbuf *nbuf)
+{
+ struct sockaddr *addr = (struct sockaddr *)nbuf->buf;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+
+ switch (addr->sa_family) {
+ case AF_INET:
+ if (!oldstyle_local)
+ return 0;
+ sin = (struct sockaddr_in *)addr;
+ return ((sin->sin_addr.s_addr == htonl(INADDR_LOOPBACK)) &&
+ (ntohs(sin->sin_port) < IPPORT_RESERVED));
+#ifdef INET6
+ case AF_INET6:
+ if (!oldstyle_local)
+ return 0;
+ sin6 = (struct sockaddr_in6 *)addr;
+ return ((IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr) ||
+ (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) &&
+ sin6->sin6_addr.s6_addr32[3] == htonl(INADDR_LOOPBACK))) &&
+ (ntohs(sin6->sin6_port) < IPV6PORT_RESERVED));
+#endif
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+
+/* logit - report events of interest via the syslog daemon */
+void
+logit(int severity, struct sockaddr *addr, rpcproc_t procnum, rpcprog_t prognum,
+ const char *text){
+
+ int size = 0;
+ const char *procname;
+ char procbuf[32];
+ char *progname;
+ char progbuf[32];
+ char fromname[NI_MAXHOST];
+ struct rpcent *rpc;
+ static const char *procmap[] = {
+ /* RPCBPROC_NULL */ "null",
+ /* RPCBPROC_SET */ "set",
+ /* RPCBPROC_UNSET */ "unset",
+ /* RPCBPROC_GETADDR */ "getport/addr",
+ /* RPCBPROC_DUMP */ "dump",
+ /* RPCBPROC_CALLIT */ "callit",
+ /* RPCBPROC_GETTIME */ "gettime",
+ /* RPCBPROC_UADDR2TADDR */ "uaddr2taddr",
+ /* RPCBPROC_TADDR2UADDR */ "taddr2uaddr",
+ /* RPCBPROC_GETVERSADDR */ "getversaddr",
+ /* RPCBPROC_INDIRECT */ "indirect",
+ /* RPCBPROC_GETADDRLIST */ "getaddrlist",
+ /* RPCBPROC_GETSTAT */ "getstat"
+ };
+
+ /*
+ * Fork off a process or the portmap daemon might hang while
+ * getrpcbynumber() or syslog() does its thing.
+ */
+
+ if (fork() == 0) {
+
+ /* Try to map program number to name. */
+
+ if (prognum == 0) {
+ progname = "";
+ } else if ((rpc = getrpcbynumber((int) prognum))) {
+ progname = rpc->r_name;
+ } else {
+ snprintf(progname = progbuf, sizeof(progbuf), "%u",
+ (unsigned)prognum);
+ }
+
+ /* Try to map procedure number to name. */
+
+ if (procnum >= (sizeof procmap / sizeof (char *))) {
+ snprintf(procbuf, sizeof procbuf, "%u",
+ (unsigned)procnum);
+ procname = procbuf;
+ } else
+ procname = procmap[procnum];
+
+ /* Write syslog record. */
+
+ if (addr->sa_family == AF_LOCAL)
+ strcpy(fromname, "local");
+ else {
+ switch(addr->sa_family){
+
+ case AF_INET:
+ size=sizeof(struct sockaddr_in);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ size=sizeof(struct sockaddr_in6);
+ break;
+#endif
+ }
+ getnameinfo(addr,size , fromname, sizeof fromname, NULL, 0, NI_NUMERICHOST);
+ }
+ syslog(severity, "connect from %s to %s(%s)%s",
+ fromname, procname, progname, text);
+ _exit(0);
+ }
+}
+
+int
+check_callit(SVCXPRT *xprt, struct r_rmtcall_args *args, int versnum /*__unused*/)
+{
+ struct sockaddr *sa = (struct sockaddr *)svc_getrpccaller(xprt)->buf;
+
+ /*
+ * Always allow calling NULLPROC
+ */
+ if (args->rmt_proc == 0)
+ return 1;
+
+ /*
+ * XXX - this special casing sucks.
+ */
+ switch (args->rmt_prog) {
+ case RPCBPROG:
+ /*
+ * Allow indirect calls to ourselves in insecure mode.
+ * The is_loopback checks aren't useful then anyway.
+ */
+ if (!insecure)
+ goto deny;
+ break;
+ case MOUNTPROG:
+ if (args->rmt_proc != MOUNTPROC_MNT &&
+ args->rmt_proc != MOUNTPROC_UMNT)
+ break;
+ goto deny;
+ case YPBINDPROG:
+ if (args->rmt_proc != YPBINDPROC_SETDOM)
+ break;
+ /* FALLTHROUGH */
+ case YPPASSWDPROG:
+ case NFS_PROGRAM:
+ case RQUOTAPROG:
+ goto deny;
+ case YPPROG:
+ switch (args->rmt_proc) {
+ case YPPROC_ALL:
+ case YPPROC_MATCH:
+ case YPPROC_FIRST:
+ case YPPROC_NEXT:
+ goto deny;
+ default:
+ break;
+ }
+ default:
+ break;
+ }
+
+ return 1;
+deny:
+#ifdef LIBWRAP
+ logit(deny_severity, sa, args->rmt_proc, args->rmt_prog,
+ ": indirect call not allowed");
+#else
+ logit(LOG_AUTH|LOG_WARNING, sa, args->rmt_proc, args->rmt_prog,
+ ": indirect call not allowed");
+#endif
+ return 0;
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/util.c
^
|
@@ -0,0 +1,401 @@
+/*
+ * $NetBSD: util.c,v 1.4 2000/08/03 00:04:30 fvdl Exp $
+ * $FreeBSD: src/usr.sbin/rpcbind/util.c,v 1.5 2002/10/07 02:56:59 alfred Exp $
+ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Frank van der Linden.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation 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 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.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <ifaddrs.h>
+#include <poll.h>
+#include <rpc/rpc.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <netconfig.h>
+#include <stdio.h>
+#include <arpa/inet.h>
+
+#include "rpcbind.h"
+
+#define SA2SIN(sa) ((struct sockaddr_in *)(sa))
+#define SA2SINADDR(sa) (SA2SIN(sa)->sin_addr)
+#ifdef INET6
+#define SA2SIN6(sa) ((struct sockaddr_in6 *)(sa))
+#define SA2SIN6ADDR(sa) (SA2SIN6(sa)->sin6_addr)
+#endif
+
+static struct sockaddr_in *local_in4;
+#ifdef INET6
+static struct sockaddr_in6 *local_in6;
+#endif
+
+static int bitmaskcmp(void *, void *, void *, int);
+
+/*
+ * For all bits set in "mask", compare the corresponding bits in
+ * "dst" and "src", and see if they match. Returns 0 if the addresses
+ * match.
+ */
+static int
+bitmaskcmp(void *dst, void *src, void *mask, int bytelen)
+{
+ int i;
+ u_int8_t *p1 = dst, *p2 = src, *netmask = mask;
+
+ for (i = 0; i < bytelen; i++)
+ if ((p1[i] & netmask[i]) != (p2[i] & netmask[i]))
+ return (1);
+ return (0);
+}
+
+/*
+ * Find a server address that can be used by `caller' to contact
+ * the local service specified by `serv_uaddr'. If `clnt_uaddr' is
+ * non-NULL, it is used instead of `caller' as a hint suggesting
+ * the best address (e.g. the `r_addr' field of an rpc, which
+ * contains the rpcbind server address that the caller used).
+ *
+ * Returns the best server address as a malloc'd "universal address"
+ * string which should be freed by the caller. On error, returns NULL.
+ */
+char *
+addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
+ char *netid)
+{
+ struct ifaddrs *ifap, *ifp = NULL, *bestif, *exactif;
+ struct netbuf *serv_nbp = NULL, *hint_nbp = NULL, tbuf;
+ struct sockaddr *caller_sa, *hint_sa, *ifsa, *ifmasksa, *serv_sa;
+ struct sockaddr_storage ss;
+ struct netconfig *nconf;
+ char *caller_uaddr = NULL, *hint_uaddr = NULL;
+ char *ret = NULL;
+ int size = 0;
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "addrmerge(caller, %s, %s, %s\n", serv_uaddr,
+ clnt_uaddr == NULL ? "NULL" : clnt_uaddr, netid);
+#endif
+ caller_sa = caller->buf;
+ if ((nconf = rpcbind_get_conf(netid)) == NULL)
+ goto freeit;
+ if ((caller_uaddr = taddr2uaddr(nconf, caller)) == NULL)
+ goto freeit;
+
+ /*
+ * Use `clnt_uaddr' as the hint if non-NULL, but ignore it if its
+ * address family is different from that of the caller.
+ */
+ hint_sa = NULL;
+ if (clnt_uaddr != NULL) {
+ hint_uaddr = clnt_uaddr;
+ if ((hint_nbp = uaddr2taddr(nconf, clnt_uaddr)) == NULL)
+ goto freeit;
+ hint_sa = hint_nbp->buf;
+ }
+ if (hint_sa == NULL || hint_sa->sa_family != caller_sa->sa_family) {
+ hint_uaddr = caller_uaddr;
+ hint_sa = caller->buf;
+ }
+
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "addrmerge: hint %s\n", hint_uaddr);
+#endif
+ /* Local caller, just return the server address. */
+ if (strncmp(caller_uaddr, "0.0.0.0.", 8) == 0 ||
+ strncmp(caller_uaddr, "::.", 3) == 0 || caller_uaddr[0] == '/') {
+ ret = strdup(serv_uaddr);
+ goto freeit;
+ }
+
+ if (getifaddrs(&ifp) < 0)
+ goto freeit;
+
+ /*
+ * Loop through all interfaces. For each interface, see if the
+ * network portion of its address is equal to that of the client.
+ * If so, we have found the interface that we want to use.
+ */
+ bestif = NULL; /* first interface UP with same network & family */
+ exactif = NULL; /* the interface requested by the client */
+ u_int8_t maskAllAddrBits[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; /* 16 bytes for IPv6 */
+ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+ ifsa = ifap->ifa_addr;
+ ifmasksa = ifap->ifa_netmask;
+
+ if (ifsa == NULL || ifsa->sa_family != hint_sa->sa_family ||
+ !(ifap->ifa_flags & IFF_UP))
+ continue;
+
+ switch (hint_sa->sa_family) {
+ case AF_INET:
+ /*
+ * If the hint address matches this interface
+ * address/netmask, then we're done.
+ */
+ if (!bitmaskcmp(&SA2SINADDR(ifsa),
+ &SA2SINADDR(hint_sa), &SA2SINADDR(ifmasksa),
+ sizeof(struct in_addr))) {
+ if(!bestif) /* for compatibility with previous code */
+ bestif = ifap;
+ /* Is this an exact match? */
+ if (!bitmaskcmp(&SA2SINADDR(ifsa),
+ &SA2SINADDR(hint_sa), maskAllAddrBits,
+ sizeof(struct in_addr))) {
+ exactif = ifap;
+ goto found;
+ }
+ /* else go-on looking for an exact match */
+ }
+ break;
+#ifdef INET6
+ case AF_INET6:
+ /*
+ * For v6 link local addresses, if the caller is on
+ * a link-local address then use the scope id to see
+ * which one.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(ifsa)) &&
+ IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(caller_sa)) &&
+ IN6_IS_ADDR_LINKLOCAL(&SA2SIN6ADDR(hint_sa))) {
+ if (SA2SIN6(ifsa)->sin6_scope_id ==
+ SA2SIN6(caller_sa)->sin6_scope_id) {
+ bestif = ifap;
+ goto found;
+ }
+ } else if (!bitmaskcmp(&SA2SIN6ADDR(ifsa),
+ &SA2SIN6ADDR(hint_sa), &SA2SIN6ADDR(ifmasksa),
+ sizeof(struct in6_addr))) {
+ if(!bestif) /* for compatibility with previous code */
+ bestif = ifap;
+ /* Is this an exact match? */
+ if (!bitmaskcmp(&SA2SIN6ADDR(ifsa),
+ &SA2SIN6ADDR(hint_sa), maskAllAddrBits,
+ sizeof(struct in6_addr))) {
+ exactif = ifap;
+ goto found;
+ }
+ /* else go-on looking for an exact match */
+ }
+ break;
+#endif
+ default:
+ continue;
+ }
+
+ /*
+ * Remember the first possibly useful interface, preferring
+ * "normal" to point-to-point and loopback ones.
+ */
+ if (bestif == NULL ||
+ (!(ifap->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT)) &&
+ (bestif->ifa_flags & (IFF_LOOPBACK | IFF_POINTOPOINT))))
+ bestif = ifap;
+ }
+
+ if (bestif == NULL)
+ goto freeit;
+
+found:
+ if(exactif)
+ bestif = exactif;
+ /*
+ * Construct the new address using the the address from
+ * `bestif', and the port number from `serv_uaddr'.
+ */
+ serv_nbp = uaddr2taddr(nconf, serv_uaddr);
+ if (serv_nbp == NULL)
+ goto freeit;
+ serv_sa = serv_nbp->buf;
+
+ switch(bestif->ifa_addr->sa_family){
+ case AF_INET:
+ size = sizeof(struct sockaddr_in);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ size = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ }
+ memcpy(&ss, bestif->ifa_addr, size);
+
+ switch (ss.ss_family) {
+ case AF_INET:
+ SA2SIN(&ss)->sin_port = SA2SIN(serv_sa)->sin_port;
+ tbuf.len = sizeof(struct sockaddr_in);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ SA2SIN6(&ss)->sin6_port = SA2SIN6(serv_sa)->sin6_port;
+ tbuf.len = sizeof(struct sockaddr_in6);
+ break;
+#endif
+ }
+ tbuf.maxlen = sizeof(ss);
+ tbuf.buf = &ss;
+ ret = taddr2uaddr(nconf, &tbuf);
+
+freeit:
+ if (caller_uaddr != NULL)
+ free(caller_uaddr);
+ if (hint_nbp != NULL) {
+ free(hint_nbp->buf);
+ free(hint_nbp);
+ }
+ if (serv_nbp != NULL) {
+ free(serv_nbp->buf);
+ free(serv_nbp);
+ }
+ if (ifp != NULL)
+ freeifaddrs(ifp);
+
+#ifdef ND_DEBUG
+ if (debugging)
+ fprintf(stderr, "addrmerge: returning %s\n", ret);
+#endif
+ return ret;
+}
+
+void
+network_init()
+{
+#ifdef INET6
+ struct ifaddrs *ifap, *ifp;
+ struct ipv6_mreq mreq6;
+ unsigned int ifindex;
+ int s;
+#endif
+ int ecode;
+ struct addrinfo hints, *res = NULL;
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = AF_INET;
+ if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
+ if (debugging)
+ fprintf(stderr, "can't get local ip4 address: %s\n",
+ gai_strerror(ecode));
+ } else {
+ local_in4 = (struct sockaddr_in *)malloc(sizeof *local_in4);
+ if (local_in4 == NULL) {
+ if (debugging)
+ fprintf(stderr, "can't alloc local ip4 addr\n");
+ }
+ memcpy(local_in4, res->ai_addr, sizeof *local_in4);
+ }
+
+#ifdef INET6
+ hints.ai_family = AF_INET6;
+ if ((ecode = getaddrinfo(NULL, "sunrpc", &hints, &res))) {
+ if (debugging)
+ fprintf(stderr, "can't get local ip6 address: %s\n",
+ gai_strerror(ecode));
+ } else {
+ local_in6 = (struct sockaddr_in6 *)malloc(sizeof *local_in6);
+ if (local_in6 == NULL) {
+ if (debugging)
+ fprintf(stderr, "can't alloc local ip6 addr\n");
+ }
+ memcpy(local_in6, res->ai_addr, sizeof *local_in6);
+ }
+
+ /*
+ * Now join the RPC ipv6 multicast group on all interfaces.
+ */
+ if (getifaddrs(&ifp) < 0) {
+ freeaddrinfo (res);
+ return;
+ }
+ mreq6.ipv6mr_interface = 0;
+ inet_pton(AF_INET6, RPCB_MULTICAST_ADDR, &mreq6.ipv6mr_multiaddr);
+
+ s = socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP);
+ if (s < 0) {
+ if (debugging)
+ fprintf(stderr, "socket(AF_INET6) failed: %s\n", strerror(errno));
+ freeaddrinfo (res);
+ return;
+ }
+
+ /*
+ * Loop through all interfaces. For each IPv6 multicast-capable
+ * interface, join the RPC multicast group on that interface.
+ */
+ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+ if (!ifap->ifa_addr ||
+ ifap->ifa_addr->sa_family != AF_INET6 ||
+ !(ifap->ifa_flags & IFF_MULTICAST))
+ continue;
+ ifindex = if_nametoindex(ifap->ifa_name);
+ if (ifindex == mreq6.ipv6mr_interface)
+ /*
+ * Already did this one.
+ */
+ continue;
+ mreq6.ipv6mr_interface = ifindex;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
+ sizeof mreq6) < 0)
+ if (debugging)
+ perror("setsockopt v6 multicast");
+ }
+ close(s);
+#endif
+ freeaddrinfo (res);
+}
+
+struct sockaddr *
+local_sa(int af)
+{
+ switch (af) {
+ case AF_INET:
+ return (struct sockaddr *)local_in4;
+#ifdef INET6
+ case AF_INET6:
+ return (struct sockaddr *)local_in6;
+#endif
+ default:
+ return NULL;
+ }
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/warmstart.c
^
|
@@ -0,0 +1,240 @@
+/*
+ * 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.
+ */
+/*
+ * warmstart.c
+ * Allows for gathering of registrations from an earlier dumped file.
+ *
+ * Copyright (c) 1990 by Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/xdr.h>
+#ifdef PORTMAP
+#include <netinet/in.h>
+#include <rpc/pmap_prot.h>
+#endif
+#include <syslog.h>
+#include <unistd.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include "rpcbind.h"
+
+/* These files keep the pmap_list and rpcb_list in XDR format */
+#define RPCBFILE RPCBIND_STATEDIR "/rpcbind.xdr"
+#ifdef PORTMAP
+#define PMAPFILE RPCBIND_STATEDIR "/portmap.xdr"
+#endif
+
+#ifndef O_DIRECTORY
+#define O_DIRECTORY 0
+#endif
+#ifndef O_NOFOLLOW
+#define O_NOFOLLOW 0
+#endif
+
+static bool_t write_struct(char *, xdrproc_t, void *);
+static bool_t read_struct(char *, xdrproc_t, void *);
+
+static bool_t
+write_struct(char *filename, xdrproc_t structproc, void *list)
+{
+ FILE *fp;
+ XDR xdrs;
+ mode_t omask;
+
+ omask = umask(077);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ int i;
+
+ for (i = 0; i < 10; i++)
+ close(i);
+ fp = fopen(filename, "w");
+ if (fp == NULL) {
+ syslog(LOG_ERR,
+ "cannot open file = %s for writing", filename);
+ syslog(LOG_ERR, "cannot save any registration");
+ return (FALSE);
+ }
+ }
+ (void) umask(omask);
+ xdrstdio_create(&xdrs, fp, XDR_ENCODE);
+
+ if (structproc(&xdrs, list) == FALSE) {
+ syslog(LOG_ERR, "xdr_%s: failed", filename);
+ fclose(fp);
+ return (FALSE);
+ }
+ XDR_DESTROY(&xdrs);
+ fclose(fp);
+ return (TRUE);
+}
+
+static bool_t
+read_struct(char *filename, xdrproc_t structproc, void *list)
+{
+ FILE *fp;
+ XDR xdrs;
+
+ if (debugging)
+ fprintf(stderr, "rpcbind: using '%s' startup file\n", filename);
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ if (errno != ENOENT)
+ syslog(LOG_ERR,
+ "Cannot open '%s' file for reading, errno %d (%s)",
+ filename, errno, strerror(errno));
+ goto error;
+ }
+
+ xdrstdio_create(&xdrs, fp, XDR_DECODE);
+ if (structproc(&xdrs, list) == FALSE) {
+ fprintf(stderr, "rpcbind: xdr_%s: failed\n", filename);
+ fclose(fp);
+ goto error;
+ }
+ XDR_DESTROY(&xdrs);
+
+ fclose(fp);
+ if (unlink(filename) < 0) {
+ syslog(LOG_ERR, "Cannot unlink '%s', errno %d (%s)",
+ filename, errno, strerror(errno));
+ }
+ return (TRUE);
+
+error:
+ if (errno != ENOENT && unlink(filename) < 0) {
+ syslog(LOG_ERR, "Cannot unlink '%s', errno %d (%s)",
+ filename, errno, strerror(errno));
+ }
+ if (debugging)
+ fprintf(stderr, "rpcbind: will start from scratch\n");
+ return (FALSE);
+}
+
+void
+mkdir_warmstart(int uid)
+{
+ /* Already exists? */
+ if (access(RPCBIND_STATEDIR, X_OK) == 0)
+ return;
+
+ if (mkdir(RPCBIND_STATEDIR, 0770) == 0) {
+ int fd = open(RPCBIND_STATEDIR, O_RDONLY | O_DIRECTORY | O_NOFOLLOW);
+ if (fd >= 0) {
+ if (fchown(fd, uid, -1) < 0) {
+ syslog(LOG_ERR,
+ "mkdir_warmstart: open failed '%s', errno %d (%s)",
+ RPCBIND_STATEDIR, errno, strerror(errno));
+ }
+ close(fd);
+ } else
+ syslog(LOG_ERR, "mkdir_warmstart: open failed '%s', errno %d (%s)",
+ RPCBIND_STATEDIR, errno, strerror(errno));
+ } else
+ syslog(LOG_ERR, "mkdir_warmstart: mkdir failed '%s', errno %d (%s)",
+ RPCBIND_STATEDIR, errno, strerror(errno));
+}
+
+void
+write_warmstart()
+{
+ (void) mkdir(RPCBIND_STATEDIR, 0770);
+ (void) write_struct(RPCBFILE, (xdrproc_t)xdr_rpcblist_ptr, &list_rbl);
+#ifdef PORTMAP
+ (void) write_struct(PMAPFILE, (xdrproc_t)xdr_pmaplist_ptr, &list_pml);
+#endif
+
+}
+
+void
+read_warmstart()
+{
+ rpcblist_ptr tmp_rpcbl = NULL;
+#ifdef PORTMAP
+ struct pmaplist *tmp_pmapl = NULL;
+#endif
+ int rc;
+
+ rc = read_struct(RPCBFILE, (xdrproc_t)xdr_rpcblist_ptr, &tmp_rpcbl);
+ if (rc == TRUE) {
+ rpcblist *pos, **tail;
+
+ /* The current rpcblist contains only the registrations
+ * for rpcbind and portmap. We keep those, since the
+ * info from the warm start file may be stale if the
+ * netconfig file was changed in the meantime.
+ * From the warm start file, we weed out any rpcbind info.
+ */
+ for (tail = &list_rbl; *tail; tail = &(*tail)->rpcb_next)
+ ;
+ while ((pos = tmp_rpcbl) != NULL) {
+ tmp_rpcbl = pos->rpcb_next;
+ if (pos->rpcb_map.r_prog != RPCBPROG) {
+ *tail = pos;
+ tail = &pos->rpcb_next;
+ } else {
+ free(pos);
+ }
+ }
+ *tail = NULL;
+ }
+#ifdef PORTMAP
+ rc = read_struct(PMAPFILE, (xdrproc_t)xdr_pmaplist_ptr, &tmp_pmapl);
+ if (rc == TRUE) {
+ struct pmaplist *pos, **tail;
+
+ /* The current pmaplist contains only the registrations
+ * for rpcbind and portmap. We keep those, since the
+ * info from the warm start file may be stale if the
+ * netconfig file was changed in the meantime.
+ * From the warm start file, we weed out any rpcbind info.
+ */
+ for (tail = &list_pml; *tail; tail = &(*tail)->pml_next)
+ ;
+ while ((pos = tmp_pmapl) != NULL) {
+ tmp_pmapl = pos->pml_next;
+ if (pos->pml_map.pm_prog != PMAPPROG) {
+ *tail = pos;
+ tail = &pos->pml_next;
+ } else {
+ free(pos);
+ }
+ }
+ *tail = NULL;
+ }
+#endif
+
+ return;
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/xlog.c
^
|
@@ -0,0 +1,234 @@
+/*
+ * support/nfs/xlog.c
+ *
+ * This module handles the logging of requests.
+ *
+ * TODO: Merge the two "XXX_log() calls.
+ *
+ * Authors: Donald J. Becker, <becker@super.org>
+ * Rick Sladkey, <jrs@world.std.com>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Olaf Kirch, <okir@monad.swb.de>
+ *
+ * This software maybe be used for any purpose provided
+ * the above copyright notice is retained. It is supplied
+ * as is, with no warranty expressed or implied.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <unistd.h>
+#include <signal.h>
+#include <time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <syslog.h>
+#include <errno.h>
+#include "xlog.h"
+
+#undef VERBOSE_PRINTF
+
+static int log_stderr = 1;
+static int log_syslog = 1;
+static int logging = 0; /* enable/disable DEBUG logs */
+static int logmask = 0; /* What will be logged */
+static char log_name[256]; /* name of this program */
+static int log_pid = -1; /* PID of this program */
+
+int export_errno = 0;
+
+static void xlog_toggle(int sig);
+static struct xlog_debugfac debugnames[] = {
+ { "general", D_GENERAL, },
+ { "call", D_CALL, },
+ { "auth", D_AUTH, },
+ { "parse", D_PARSE, },
+ { "all", D_ALL, },
+ { NULL, 0, },
+};
+
+void
+xlog_open(char *progname)
+{
+ openlog(progname, LOG_PID, LOG_DAEMON);
+
+ strncpy(log_name, progname, sizeof (log_name) - 1);
+ log_name [sizeof (log_name) - 1] = '\0';
+ log_pid = getpid();
+
+ signal(SIGUSR1, xlog_toggle);
+ signal(SIGUSR2, xlog_toggle);
+}
+
+void
+xlog_stderr(int on)
+{
+ log_stderr = on;
+}
+
+void
+xlog_syslog(int on)
+{
+ log_syslog = on;
+}
+
+static void
+xlog_toggle(int sig)
+{
+ unsigned int tmp, i;
+
+ if (sig == SIGUSR1) {
+ if ((logmask & D_ALL) && !logging) {
+ xlog(D_GENERAL, "turned on logging");
+ logging = 1;
+ return;
+ }
+ tmp = ~logmask;
+ logmask |= ((logmask & D_ALL) << 1) | D_GENERAL;
+ for (i = -1, tmp &= logmask; tmp; tmp >>= 1, i++)
+ if (tmp & 1)
+ xlog(D_GENERAL,
+ "turned on logging level %d", i);
+ } else {
+ xlog(D_GENERAL, "turned off logging");
+ logging = 0;
+ }
+ signal(sig, xlog_toggle);
+}
+
+void
+xlog_config(int fac, int on)
+{
+ if (on)
+ logmask |= fac;
+ else
+ logmask &= ~fac;
+ if (on)
+ logging = 1;
+}
+
+void
+xlog_sconfig(char *kind, int on)
+{
+ struct xlog_debugfac *tbl = debugnames;
+
+ while (tbl->df_name != NULL && strcasecmp(tbl->df_name, kind))
+ tbl++;
+ if (!tbl->df_name) {
+ xlog (L_WARNING, "Invalid debug facility: %s\n", kind);
+ return;
+ }
+ xlog_config(tbl->df_fac, on);
+}
+
+int
+xlog_enabled(int fac)
+{
+ return (logging && (fac & logmask));
+}
+
+
+/* Write something to the system logfile and/or stderr */
+void
+xlog_backend(int kind, const char *fmt, va_list args)
+{
+ va_list args2;
+
+ if (!(kind & (L_ALL)) && !(logging && (kind & logmask)))
+ return;
+
+ if (log_stderr)
+ va_copy(args2, args);
+
+ if (log_syslog) {
+ switch (kind) {
+ case L_FATAL:
+ vsyslog(LOG_ERR, fmt, args);
+ break;
+ case L_ERROR:
+ vsyslog(LOG_ERR, fmt, args);
+ break;
+ case L_WARNING:
+ vsyslog(LOG_WARNING, fmt, args);
+ break;
+ case L_NOTICE:
+ vsyslog(LOG_NOTICE, fmt, args);
+ break;
+ default:
+ if (!log_stderr)
+ vsyslog(LOG_INFO, fmt, args);
+ break;
+ }
+ }
+
+ if (log_stderr) {
+#ifdef VERBOSE_PRINTF
+ time_t now;
+ struct tm *tm;
+
+ time(&now);
+ tm = localtime(&now);
+ fprintf(stderr, "%s[%d] %04d-%02d-%02d %02d:%02d:%02d ",
+ log_name, log_pid,
+ tm->tm_year+1900, tm->tm_mon + 1, tm->tm_mday,
+ tm->tm_hour, tm->tm_min, tm->tm_sec);
+#else
+ fprintf(stderr, "%s: ", log_name);
+#endif
+ vfprintf(stderr, fmt, args2);
+ fprintf(stderr, "\n");
+ va_end(args2);
+ }
+
+ if (kind == L_FATAL)
+ exit(1);
+}
+
+void
+xlog(int kind, const char* fmt, ...)
+{
+ va_list args;
+
+ if (kind & (L_ERROR|D_GENERAL))
+ export_errno = 1;
+
+ va_start(args, fmt);
+ xlog_backend(kind, fmt, args);
+ va_end(args);
+}
+
+void
+xlog_warn(const char* fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ xlog_backend(L_WARNING, fmt, args);
+ va_end(args);
+}
+
+
+void
+xlog_err(const char* fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ xlog_backend(L_FATAL, fmt, args);
+ va_end(args);
+}
+
+void
+xlog_errno(int err, const char *fmt, ...)
+{
+ va_list args;
+
+ errno = err;
+ va_start(args, fmt);
+ xlog_backend(L_FATAL, fmt, args);
+ va_end(args);
+}
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/src/xlog.h
^
|
@@ -0,0 +1,52 @@
+/*
+ * xlog Logging functionality
+ *
+ * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de>
+ */
+
+#ifndef XLOG_H
+#define XLOG_H
+
+#include <stdarg.h>
+
+/* These are logged always. L_FATAL also does exit(1) */
+#define L_FATAL 0x0100
+#define L_ERROR 0x0200
+#define L_WARNING 0x0400
+#define L_NOTICE 0x0800
+#define L_ALL 0xFF00
+
+/* These are logged if enabled with xlog_[s]config */
+/* NB: code does not expect ORing together D_ and L_ */
+#define D_GENERAL 0x0001 /* general debug info */
+#define D_CALL 0x0002
+#define D_AUTH 0x0004
+#define D_FAC3 0x0008
+#define D_FAC4 0x0010
+#define D_FAC5 0x0020
+#define D_PARSE 0x0040
+#define D_FAC7 0x0080
+#define D_ALL 0x00FF
+
+/* This can be used to define symbolic log names that can be passed to
+ * xlog_config.
+ */
+struct xlog_debugfac {
+ char *df_name;
+ int df_fac;
+};
+
+extern int export_errno;
+void xlog_open(char *progname);
+void xlog_stderr(int on);
+void xlog_syslog(int on);
+void xlog_config(int fac, int on);
+void xlog_sconfig(char *, int on);
+int xlog_enabled(int fac);
+void xlog(int fac, const char *fmt, ...);
+void xlog_warn(const char *fmt, ...);
+void xlog_err(const char *fmt, ...);
+void xlog_errno(int err, const char *fmt, ...);
+void xlog_backend(int fac, const char *fmt, va_list args);
+
+#endif /* XLOG_H */
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/systemd/rpcbind.service.in
^
|
@@ -0,0 +1,18 @@
+[Unit]
+Description=RPC Bind
+Documentation=man:rpcbind(8)
+DefaultDependencies=no
+RequiresMountsFor=@statedir@
+
+# Make sure we use the IP addresses listed for
+# rpcbind.socket, no matter how this unit is started.
+Requires=rpcbind.socket
+Wants=rpcbind.target
+
+[Service]
+Type=notify
+# distro can provide a drop-in adding EnvironmentFile=-/??? if needed.
+ExecStart=@_sbindir@/rpcbind $RPCBIND_OPTIONS -w -f
+
+[Install]
+WantedBy=multi-user.target
|
[-]
[+]
|
Added |
_service:tar_git:rpcbind-1.2.6.tar.bz2/upstream/systemd/rpcbind.socket
^
|
@@ -0,0 +1,18 @@
+[Unit]
+Description=RPCbind Server Activation Socket
+DefaultDependencies=no
+Wants=rpcbind.target
+Before=rpcbind.target
+
+[Socket]
+ListenStream=/run/rpcbind.sock
+
+# RPC netconfig can't handle ipv6/ipv4 dual sockets
+BindIPv6Only=ipv6-only
+ListenStream=0.0.0.0:111
+ListenDatagram=0.0.0.0:111
+ListenStream=[::]:111
+ListenDatagram=[::]:111
+
+[Install]
+WantedBy=sockets.target
|
[-]
[+]
|
Changed |
_service:tar_git:rpcbind.yaml
^
|
@@ -6,17 +6,21 @@
Sources:
- '%{name}-%{version}.tar.bz2'
URL: https://sourceforge.net/project/rpcbind/
+SCM: git://git.linux-nfs.org/projects/steved/rpcbind.git
Description: |
%{summary}.
%if "%{?vendor}" == "chum"
- PackagerName: nephros
Categories:
- Network
- System
+ Custom:
+ PackagingRepo: https://github.com/sailfishos-chum/rpcbind
%endif
-
+SetupOptions: -q -n %{name}-%{version}/upstream
PkgBR:
+ - autoconf
+ - automake
- systemd
PkgConfigBR:
- libtirpc
@@ -24,7 +28,6 @@
Files:
- '%{_bindir}/*'
- '%{_sbindir}/*'
- - '%{_mandir}/*/*'
- '%{_unitdir}/*'
SubPackages:
- Name: doc
|