summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSteve Dickson <steved@redhat.com>2019-09-05 10:06:18 -0400
committerSteve Dickson <steved@redhat.com>2019-09-05 10:06:18 -0400
commitb5937e1414e1600d788fd1d689b4f64a09422d03 (patch)
treeeefe9e31768008bd1d9c47609ced2298c5b10a4f
parent0bc1c0ae7ce61a7ac8a8e9a9b2086268f011abf0 (diff)
downloadrpcbind-b5937e1414e1600d788fd1d689b4f64a09422d03.tar.gz
rpcbind: look for an exact match of the ip address for a requested service first
the rpcbind program returns the first IP address that matches the hint IP, i.e.: The first interface found that is UP and on the same network as the hint IP address (bestmatch). That could be wrong if there are multiple ips in the same subnet for the same interface configured. For instance output of ip addr: ~> ip addr inet 10.xxx.xx.133/22 brd 10.xxx.xx.255 scope global mgmt <------first ip-address which matches the hint inet 10.xxx.xx.147/22 scope global eth0 <----actual ip-address where nfs server is configured inet 10.xxx.xx.160/22 scope global secondary eth0 ~> rpc mount export: RPC: Timed out rpc mount export: RPC: Timed out For multiple IP adresses in the same subnet, it should try to find an exact match first and only if that fails return the best match. Signed-off-by: Thomas Blume <thomas.blume@suse.com> Signed-off-by: Steve Dickson <steved@redhat.com>
-rw-r--r--src/util.c34
1 files changed, 28 insertions, 6 deletions
diff --git a/src/util.c b/src/util.c
index 74b0284..bf2d024 100644
--- a/src/util.c
+++ b/src/util.c
@@ -103,7 +103,7 @@ char *
addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
char *netid)
{
- struct ifaddrs *ifap, *ifp = NULL, *bestif;
+ 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;
@@ -157,7 +157,10 @@ addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
* 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;
+ 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;
@@ -175,8 +178,16 @@ addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
if (!bitmaskcmp(&SA2SINADDR(ifsa),
&SA2SINADDR(hint_sa), &SA2SINADDR(ifmasksa),
sizeof(struct in_addr))) {
- bestif = ifap;
- goto found;
+ 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
@@ -197,8 +208,16 @@ addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
} else if (!bitmaskcmp(&SA2SIN6ADDR(ifsa),
&SA2SIN6ADDR(hint_sa), &SA2SIN6ADDR(ifmasksa),
sizeof(struct in6_addr))) {
- bestif = ifap;
- goto found;
+ 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
@@ -215,10 +234,13 @@ addrmerge(struct netbuf *caller, char *serv_uaddr, char *clnt_uaddr,
(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'.