forked from pool/libtirpc
5d2253d2db
OBS-URL: https://build.opensuse.org/package/show/Base:System/libtirpc?expand=0&rev=52b49edbc74959ad491aa81833a0bd24
121 lines
3.5 KiB
Diff
121 lines
3.5 KiB
Diff
commit 30feadb3ae5a8d001aabc44f8ddad44298ec61a2
|
|
Author: Olaf Kirch <okir@suse.de>
|
|
Date: Mon Aug 23 14:36:13 2010 +0200
|
|
|
|
pmap_set/unset: allow compat functions to work with old-style portmap
|
|
|
|
This change fixes a bug when running applications compiled against
|
|
libtirpc on a host with old-style portmap. Without this change, the
|
|
pmap_set/pmap_unset compatibility functions will actually be mapped
|
|
to a RPCB_SET/UNSET call. If the server does not support anything more
|
|
recent than PMAP, the operations will fail completely.
|
|
|
|
This fix makes pmap_set/unset try the old portmapper functions
|
|
first, and if those fail, try to fall back to the new rpcbind
|
|
interface.
|
|
|
|
Signed-off-by: Olaf Kirch <okir@suse.de>
|
|
|
|
diff --git a/src/pmap_clnt.c b/src/pmap_clnt.c
|
|
index 1d5d153..24cf94a 100644
|
|
--- a/src/pmap_clnt.c
|
|
+++ b/src/pmap_clnt.c
|
|
@@ -58,6 +58,10 @@ pmap_set(u_long program, u_long version, int protocol, int port)
|
|
struct netconfig *nconf;
|
|
char buf[32];
|
|
|
|
+#ifdef PORTMAP
|
|
+ if (__pmap_set(program, version, protocol, port))
|
|
+ return (TRUE);
|
|
+#endif
|
|
if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
|
|
return (FALSE);
|
|
}
|
|
@@ -89,6 +93,11 @@ pmap_unset(u_long program, u_long version)
|
|
bool_t udp_rslt = FALSE;
|
|
bool_t tcp_rslt = FALSE;
|
|
|
|
+#ifdef PORTMAP
|
|
+ if (__pmap_set(program, version, IPPROTO_UDP, 0)
|
|
+ && __pmap_set(program, version, IPPROTO_TCP, 0))
|
|
+ return (TRUE);
|
|
+#endif
|
|
nconf = __rpc_getconfip("udp");
|
|
if (nconf != NULL) {
|
|
udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
|
|
diff --git a/src/rpc_com.h b/src/rpc_com.h
|
|
index 38c2cfe..0a20a01 100644
|
|
--- a/src/rpc_com.h
|
|
+++ b/src/rpc_com.h
|
|
@@ -86,6 +86,9 @@ bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t);
|
|
void __xprt_unregister_unlocked(SVCXPRT *);
|
|
void __xprt_set_raddr(SVCXPRT *, const struct sockaddr_storage *);
|
|
|
|
+#ifdef PORTMAP
|
|
+bool_t __pmap_set(rpcprog_t, rpcvers_t, int protocol, int port);
|
|
+#endif
|
|
|
|
SVCXPRT **__svc_xports;
|
|
int __svc_maxrec;
|
|
diff --git a/src/rpcb_clnt.c b/src/rpcb_clnt.c
|
|
index 531c619..9562646 100644
|
|
--- a/src/rpcb_clnt.c
|
|
+++ b/src/rpcb_clnt.c
|
|
@@ -476,6 +476,55 @@ getpmaphandle(nconf, hostname, tgtaddr)
|
|
#define IN4_LOCALHOST_STRING "127.0.0.1"
|
|
#define IN6_LOCALHOST_STRING "::1"
|
|
|
|
+#ifdef PORTMAP
|
|
+/*
|
|
+ * Perform a PMAP_SET or PMAP_UNSET call to the
|
|
+ * local rpcbind/portmap service.
|
|
+ */
|
|
+bool_t
|
|
+__pmap_set(program, version, protocol, port)
|
|
+ rpcprog_t program;
|
|
+ rpcvers_t version;
|
|
+ int protocol;
|
|
+ int port;
|
|
+{
|
|
+ CLIENT *client;
|
|
+ rpcproc_t pmapproc;
|
|
+ struct pmap pmapparms;
|
|
+ bool_t rslt = FALSE;
|
|
+ enum clnt_stat clnt_st;
|
|
+
|
|
+ /* Arguments should already have been checked by caller */
|
|
+
|
|
+ pmapproc = port? PMAPPROC_SET : PMAPPROC_UNSET;
|
|
+ pmapparms.pm_prog = program;
|
|
+ pmapparms.pm_vers = version;
|
|
+ pmapparms.pm_prot = protocol;
|
|
+ pmapparms.pm_port = port;
|
|
+
|
|
+ client = getpmaphandle(NULL, IN4_LOCALHOST_STRING, NULL);
|
|
+ if (client == NULL)
|
|
+ return (FALSE);
|
|
+
|
|
+ clnt_st = CLNT_CALL(client, pmapproc,
|
|
+ (xdrproc_t) xdr_pmap, (caddr_t)(void *) &pmapparms,
|
|
+ (xdrproc_t) xdr_bool, (caddr_t)(void *) &rslt,
|
|
+ tottimeout);
|
|
+
|
|
+ if (clnt_st == RPC_SUCCESS)
|
|
+ return rslt;
|
|
+
|
|
+ if (clnt_st != RPC_PROGVERSMISMATCH &&
|
|
+ clnt_st != RPC_PROGUNAVAIL) {
|
|
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
|
|
+ clnt_geterr(client, &rpc_createerr.cf_error);
|
|
+ return (FALSE);
|
|
+ }
|
|
+
|
|
+ return (TRUE);
|
|
+}
|
|
+#endif
|
|
+
|
|
/*
|
|
* This routine will return a client handle that is connected to the local
|
|
* rpcbind. Returns NULL on error and free's everything.
|
|
|