forked from pool/libtirpc
c3b2cb84b1
- Update to upstream 0.2.5 release - Add symbol versioning to fix symbol conflicts (001-symbol-versions-v2.patch), but disable until commited upstream - Adjust libtirpc-clnt_broadcast_fix.patch and rename to 002-clnt_broadcast_fix.patch - Adjust libtirpc-rpc_broadcast_misformed_replies.patch and rename to 003-rpc_broadcast_misformed_replies.patch - Rename libtirpc-getpmaphandle.patch to 004-getpmaphandle.patch - Adjust libtirpc-bindresvport_blacklist.patch and rename to 000-bindresvport_blacklist.patch - Drop libtirpc-pmap-setunset.patch, not needed anymore - Apply libtirpc-new-path-rpcbindsock.patch only on openSUSE 13.1 and later OBS-URL: https://build.opensuse.org/request/show/265252 OBS-URL: https://build.opensuse.org/package/show/Base:System/libtirpc?expand=0&rev=41
72 lines
2.1 KiB
Diff
72 lines
2.1 KiB
Diff
Author: Olaf Kirch <okir@suse.de>
|
|
Date: Thu Nov 13 10:24:39 2008 +0100
|
|
|
|
rpc_broadcast: handle misformed rpcbind replies
|
|
|
|
Some rpcbind implementations seem to return IPv6 uaddrs
|
|
in response to an IPv4 broadcast (which is probably due
|
|
to their using a single v6 socket to handle both v6 and
|
|
v4 requests).
|
|
|
|
We can either discard these replies, or fix them up silently.
|
|
Here's a patch that implements the latter.
|
|
|
|
Signed-off-by: Olaf Kirch <okir@suse.de>
|
|
|
|
--- a/src/clnt_bcast.c
|
|
+++ b/src/clnt_bcast.c
|
|
@@ -222,6 +222,39 @@
|
|
return 0;
|
|
}
|
|
|
|
+/*
|
|
+ * Some rpcbind implementations use an IPv6 socket to serve both
|
|
+ * IPv4 and IPv6 messages, but neglect to check for the caller's
|
|
+ * address family when sending broadcast replies. These rpcbind
|
|
+ * implementations return an IPv6 address in reply to an IPv4
|
|
+ * broadcast. We can either ignore them, or try to patch them up.
|
|
+ */
|
|
+static struct netbuf *
|
|
+__ipv6v4_fixup(struct sockaddr_storage *ss, const char *uaddr)
|
|
+{
|
|
+ struct sockaddr_in sin;
|
|
+ struct netbuf *np;
|
|
+
|
|
+ /* ss is the remote rpcbind server's address */
|
|
+ if (ss->ss_family != AF_INET)
|
|
+ return NULL;
|
|
+ memcpy(&sin, ss, sizeof(sin));
|
|
+
|
|
+ np = __rpc_uaddr2taddr_af(AF_INET6, uaddr);
|
|
+ if (np == NULL)
|
|
+ return NULL;
|
|
+
|
|
+ /* Overwrite the port with that of the service we
|
|
+ * wanted to talk to. */
|
|
+ sin.sin_port = ((struct sockaddr_in6 *) np)->sin6_port;
|
|
+
|
|
+ /* We know netbuf holds a sockaddr_in6, so it can easily
|
|
+ * hold a sockaddr_in as well. */
|
|
+ memcpy(np->buf, &sin, sizeof(sin));
|
|
+ np->len = sizeof(sin);
|
|
+
|
|
+ return np;
|
|
+}
|
|
|
|
enum clnt_stat
|
|
rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
|
|
@@ -588,6 +621,13 @@
|
|
LIBTIRPC_DEBUG(3, ("rpc_broadcast_exp: uaddr %s\n", uaddrp));
|
|
np = uaddr2taddr(
|
|
fdlist[i].nconf, uaddrp);
|
|
+ /* Some misguided rpcbind implemenations
|
|
+ * seem to return an IPv6 uaddr in IPv4
|
|
+ * responses. */
|
|
+ if (np == NULL)
|
|
+ np = __ipv6v4_fixup(
|
|
+ &fdlist[i].raddr,
|
|
+ uaddrp);
|
|
if (np != NULL) {
|
|
done = (*eachresult)(resultsp,
|
|
np, fdlist[i].nconf);
|