Introduce rpcbind client utility functions
authorChuck Lever <chuck.lever@oracle.com>
Mon, 17 Nov 2008 21:13:48 +0000 (16:13 -0500)
committerSteve Dickson <steved@redhat.com>
Mon, 17 Nov 2008 21:13:48 +0000 (16:13 -0500)
It turns out that at least the mount command and the showmount command
need to query a server's rpcbind daemon.  They need to query over
AF_INET6 as well as AF_INET.

libtirpc provides an rpcbind query capability with the rpcb_getaddr(3)
interface, but it takes a hostname and netconfig entry rather than a
sockaddr and a protocol type, and always uses a lengthy timeout.  The
former is important to the mount command because it sometimes must
operate using a specific port and IP address rather than depending on
rpcbind and DNS to convert a [hostname, RPC program, netconfig] tuple
to a [socket address, port number, transport protocol] tuple.

The rpcb_getaddr(3) API also always uses a privileged port (at least
for setuid root executables like mount.nfs), which is not required for
an rpcbind query.  This can exhaust the local system's reserved port
space quickly.

This patch provides a reserved-port-friendly AF_INET6-capable rpcbind
query C API that can be shared among commands and tools in nfs-utils,
and allows a query to a specified socket address and port rather than
a hostname.

In addition to an rpcbind query interface, this patch also provides a
facility to ping the remote RPC service to ensure that it is operating
as advertised by rpcbind.  It's useful to combine an RPC ping with an
rpcbind query because in many cases, components of nfs-utils already
ping an RPC service immediately after receiving a successful GETPORT
result.

There are also a handful of utility routines provided, such as a
functions that can map between [sockaddr, port] and a universal
address.

I've made an attempt to make these new functions build and operate on
systems that do not have libtirpc.

Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
support/include/nfsrpc.h
support/nfs/Makefile.am

index e129a72..1529d44 100644 (file)
@@ -67,4 +67,75 @@ extern CLIENT                *nfs_get_rpcclient(const struct sockaddr *,
                                const rpcprog_t, const rpcvers_t,
                                struct timeval *);
 
+/*
+ * Convert a socket address to a universal address
+ */
+extern char            *nfs_sockaddr2universal(const struct sockaddr *,
+                               const socklen_t);
+
+/*
+ * Extract port number from a universal address
+ */
+extern int             nfs_universal2port(const char *);
+
+/*
+ * Generic function that maps an RPC service tuple to an IP port
+ * number of the service on a remote post, and sends a NULL
+ * request to determine if the service is responding to requests
+ */
+extern int             nfs_getport_ping(struct sockaddr *sap,
+                               const socklen_t salen,
+                               const rpcprog_t program,
+                               const rpcvers_t version,
+                               const unsigned short protocol);
+
+/*
+ * Generic function that maps an RPC service tuple to an IP port
+ * number of the service on a remote host
+ */
+extern unsigned short  nfs_getport(const struct sockaddr *,
+                               const socklen_t, const rpcprog_t,
+                               const rpcvers_t, const unsigned short);
+
+/*
+ * Generic function that maps an RPC service tuple to an IP port
+ * number of the service on the local host
+ */
+extern unsigned short  nfs_getlocalport(const rpcprot_t,
+                               const rpcvers_t, const unsigned short);
+
+/*
+ * Function to invoke an rpcbind v3/v4 GETADDR request
+ */
+extern unsigned short  nfs_rpcb_getaddr(const struct sockaddr *,
+                               const socklen_t,
+                               const unsigned short,
+                               const struct sockaddr *,
+                               const socklen_t,
+                               const rpcprog_t,
+                               const rpcvers_t,
+                               const unsigned short,
+                               const struct timeval *);
+
+/*
+ * Function to invoke a portmap GETPORT request
+ */
+extern unsigned long   nfs_pmap_getport(const struct sockaddr_in *,
+                               const unsigned short,
+                               const unsigned long,
+                               const unsigned long,
+                               const unsigned long,
+                               const struct timeval *);
+
+/*
+ * Contact a remote RPC service to discover whether it is responding
+ * to requests.
+ */
+extern int             nfs_rpc_ping(const struct sockaddr *sap,
+                               const socklen_t salen,
+                               const rpcprog_t program,
+                               const rpcvers_t version,
+                               const unsigned short protocol,
+                               const struct timeval *timeout);
+
 #endif /* __NFS_UTILS_NFSRPC_H */
index d6d71d9..86f52a1 100644 (file)
@@ -3,7 +3,7 @@
 noinst_LIBRARIES = libnfs.a
 libnfs_a_SOURCES = exports.c rmtab.c xio.c rpcmisc.c rpcdispatch.c \
                   xlog.c xcommon.c wildmat.c nfssvc.c nfsclient.c \
-                  nfsexport.c getfh.c nfsctl.c rpc_socket.c \
+                  nfsexport.c getfh.c nfsctl.c rpc_socket.c getport.c \
                   svc_socket.c cacheio.c closeall.c nfs_mntent.c
 
 MAINTAINERCLEANFILES = Makefile.in