diff options
author | Steve Dickson <steved@redhat.com> | 2019-09-05 10:06:18 -0400 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2019-09-05 10:06:18 -0400 |
commit | b5937e1414e1600d788fd1d689b4f64a09422d03 (patch) | |
tree | eefe9e31768008bd1d9c47609ced2298c5b10a4f | |
parent | 0bc1c0ae7ce61a7ac8a8e9a9b2086268f011abf0 (diff) | |
download | rpcbind-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.c | 34 |
1 files changed, 28 insertions, 6 deletions
@@ -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'. |