mount.nfs: prefer IPv4 addresses over IPv6 We're poised to enable IPv6 in nfs-utils in distros. There is a potential problem however. glibc seems to prefer IPv6 addrs. If someone has a working IPv4 server today that has an IPv6 address, then clients may start trying to mount over that address. If the server doesn't support NFS serving over IPv6 (and virtually no linux servers currently do), then the mount will start failing. Avoid this problem by making the mount.nfs code prefer IPv4 addresses when they are available. Signed-off-by: Jeff Layton Acked-by: NeilBrown --- utils/mount/network.c | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) --- nfs-utils-1.2.3.orig/utils/mount/network.c +++ nfs-utils-1.2.3/utils/mount/network.c @@ -206,7 +206,7 @@ static const unsigned int *nfs_default_p int nfs_lookup(const char *hostname, const sa_family_t family, struct sockaddr *sap, socklen_t *salen) { - struct addrinfo *gai_results; + struct addrinfo *gai_results, *gai_pref; struct addrinfo gai_hint = { #ifdef HAVE_DECL_AI_ADDRCONFIG .ai_flags = AI_ADDRCONFIG, @@ -232,12 +232,29 @@ int nfs_lookup(const char *hostname, con return ret; } - switch (gai_results->ai_addr->sa_family) { + /* + * It will probably be quite a while before we have enough IPv6 + * capable servers to be able to prefer using IPv6. For now, we + * only use IPv6 when there is no IPv4 address available in the + * results. + */ + gai_pref = gai_results; + while (gai_pref) { + if (gai_pref->ai_addr->sa_family == AF_INET) + break; + gai_pref = gai_pref->ai_next; + } + + /* no IPv4 addr found, just use first on the list */ + if (gai_pref == NULL) + gai_pref = gai_results; + + switch (gai_pref->ai_addr->sa_family) { case AF_INET: case AF_INET6: - if (len >= gai_results->ai_addrlen) { - *salen = gai_results->ai_addrlen; - memcpy(sap, gai_results->ai_addr, *salen); + if (len >= gai_pref->ai_addrlen) { + *salen = gai_pref->ai_addrlen; + memcpy(sap, gai_pref->ai_addr, *salen); ret = 1; } break;