From 265f2708bdc6030250c13d46d70ed689c140c34e Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 6 Jan 2009 12:03:26 -0500 Subject: mount: revert recent fix for build problems on old systems Revert the patch that added local definitions of AI_ADDRCONFIG and friends to utils/mount/network.c. While old header versions don't have those flags, even older versions of getaddrinfo(3) don't support those flags at all. The result is this error: mount.nfs: DNS resolution failed for 10.10.10.10: Bad value for ai_flags Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- utils/mount/network.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/utils/mount/network.c b/utils/mount/network.c index 6a9a41a..afa47a4 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -50,24 +50,6 @@ #include "nfsrpc.h" #include "network.h" -/* - * Earlier versions of glibc's /usr/include/netdb.h exclude these - * definitions because it was thought they were not part of a stable - * POSIX standard. However, they are defined by RFC 2553 and 3493 - * and in POSIX 1003.1-2001, so these definitions were added in later - * versions of netdb.h. - */ -#ifndef AI_V4MAPPED -#define AI_V4MAPPED 0x0008 /* IPv4-mapped addresses are acceptable. */ -#endif /* AI_V4MAPPED */ -#ifndef AI_ALL -#define AI_ALL 0x0010 /* Return both IPv4 and IPv6 addresses. */ -#endif /* AI_ALL */ -#ifndef AI_ADDRCONFIG -#define AI_ADDRCONFIG 0x0020 /* Use configuration of this host to choose \ - returned address type. */ -#endif /* AI_ADDRCONFIG */ - #define PMAP_TIMEOUT (10) #define CONNECT_TIMEOUT (20) #define MOUNT_TIMEOUT (30) -- cgit From 632650fa1a0b358f9d8d617cfd115a334c4b9b66 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 6 Jan 2009 12:07:04 -0500 Subject: mount command: use gethostbyname(3) when building on old systems Glibc's getaddrinfo(3) implementation was added over time. Some old versions support AI_ADDRCONFIG, but don't define it in header files. Some older versions don't support AI_ADDRCONFIG at all. Let's add specific checks to configure.ac to see that the local getaddrinfo(3) implementation is complete. If it isn't, we will make available a resolver that uses gethostbyname(3) and disable IPv6 entirely. This patch should apply to 1.1.4 as well as the current nfs-utils repo. The next patch has a fix for the getaddrinfo(3) call added since 1.1.4 in support/nfs/getport.c. Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- configure.ac | 8 ++++++++ utils/mount/network.c | 56 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/configure.ac b/configure.ac index 48d76d7..1b83296 100644 --- a/configure.ac +++ b/configure.ac @@ -246,6 +246,11 @@ if test "$enable_gss" = yes; then fi +AC_CHECK_DECL([AI_ADDRCONFIG], + AC_DEFINE([HAVE_DECL_AI_ADDRCONFIG], 1, + [Define this to 1 if AI_ADDRCONFIG macro is defined]), , + [ #include ] ) + if test "$enable_ipv6" = yes; then AC_CHECK_FUNC(inet_ntop, , , AC_MSG_ERROR(Function 'inet_ntop' not found.)) @@ -255,6 +260,9 @@ if test "$enable_ipv6" = yes; then AC_MSG_ERROR([libtirpc needed for IPv6 support])) AC_CHECK_HEADERS(tirpc/netconfig.h, , AC_MSG_ERROR([libtirpc-devel needed for IPv6 support])) + AC_CHECK_DECL([AI_ADDRCONFIG], , + AC_MSG_ERROR([full getaddrinfo(3) implementation needed for IPv6 support]), + [ #include ] ) fi dnl ************************************************************* diff --git a/utils/mount/network.c b/utils/mount/network.c index afa47a4..a82c338 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -157,6 +157,7 @@ static void nfs_set_port(struct sockaddr *sap, const unsigned short port) } } +#ifdef HAVE_DECL_AI_ADDRCONFIG /** * nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address * @hostname: pointer to C string containing DNS hostname to resolve @@ -210,6 +211,61 @@ int nfs_name_to_address(const char *hostname, freeaddrinfo(gai_results); return ret; } +#else /* HAVE_DECL_AI_ADDRCONFIG */ +/** + * nfs_name_to_address - resolve hostname to an IPv4 socket address + * @hostname: pointer to C string containing DNS hostname to resolve + * @af_hint: hint to restrict resolution to one address family + * @sap: pointer to buffer to fill with socket address + * @len: IN: size of buffer to fill; OUT: size of socket address + * + * Returns 1 and places a socket address at @sap if successful; + * otherwise zero. + * + * Some older getaddrinfo(3) implementations don't support + * AI_ADDRCONFIG or AI_V4MAPPED properly. For those cases, a DNS + * resolver based on the traditional gethostbyname(3) is provided. + */ +int nfs_name_to_address(const char *hostname, + const sa_family_t af_hint, + struct sockaddr *sap, socklen_t *salen) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sap; + socklen_t len = *salen; + struct hostent *hp; + + *salen = 0; + + if (af_hint != AF_INET) { + nfs_error(_("%s: address family not supported by DNS resolver\n"), + progname, hostname); + return 0; + } + + sin->sin_family = AF_INET; + if (inet_aton(hostname, &sin->sin_addr)) { + *salen = sizeof(*sin); + return 1; + } + + hp = gethostbyname(hostname); + if (hp == NULL) { + nfs_error(_("%s: DNS resolution failed for %s: %s"), + progname, hostname, hstrerror(h_errno)); + return 0; + } + + if (hp->h_length > len) { + nfs_error(_("%s: DNS resolution results too long for buffer\n"), + progname); + return 0; + } + + memcpy(&sin->sin_addr, hp->h_addr, hp->h_length); + *salen = hp->h_length; + return 1; +} +#endif /* HAVE_DECL_AI_ADDRCONFIG */ /** * nfs_gethostbyname - resolve a hostname to an IPv4 address -- cgit From e9dbcba18defacbee9b5a48ddea9f6d3449b34e9 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 6 Jan 2009 12:08:33 -0500 Subject: mount: getport: don't use getaddrinfo(3) on old systems Older glibc versions have a getaddrinfo(3) that doesn't support AI_ADDRCONFIG. Detect that case and build something else for getport.c that will work adequately on those systems. Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- support/nfs/getport.c | 69 +++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 59 insertions(+), 10 deletions(-) diff --git a/support/nfs/getport.c b/support/nfs/getport.c index 25dca6c..47824a2 100644 --- a/support/nfs/getport.c +++ b/support/nfs/getport.c @@ -73,6 +73,60 @@ static const char *nfs_gp_rpcb_pgmtbl[] = { NULL, }; +#ifdef HAVE_DECL_AI_ADDRCONFIG +/* + * getaddrinfo(3) generates a usable loopback address based on how the + * local network interfaces are configured. RFC 3484 requires that the + * results are sorted so that the first result has the best likelihood + * of working, so we try just that first result. + * + * Returns TRUE on success. + */ +static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen) +{ + struct addrinfo *gai_results; + struct addrinfo gai_hint = { + .ai_flags = AI_ADDRCONFIG, + }; + socklen_t len = *salen; + int ret = 0; + + if (getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results)) + return 0; + + switch (gai_results->ai_addr->sa_family) { + case AF_INET: + case AF_INET6: + if (len >= gai_results->ai_addrlen) { + memcpy(sap, gai_results->ai_addr, + gai_results->ai_addrlen); + *salen = gai_results->ai_addrlen; + ret = 1; + } + } + + freeaddrinfo(gai_results); + return ret; +} +#else +/* + * Old versions of getaddrinfo(3) don't support AI_ADDRCONFIG, so we + * have a fallback for building on legacy systems. + */ +static int nfs_gp_loopback_address(struct sockaddr *sap, socklen_t *salen) +{ + struct sockaddr_in *sin = (struct sockaddr_in *)sap; + + memset(sin, 0, sizeof(*sin)); + + sin->sin_family = AF_INET; + sin->sin_addr.s_addr = htonl(INADDR_LOOPBACK); + *salen = sizeof(*sin); + + return 1; +} +#endif + /* * Discover the port number that should be used to contact an * rpcbind service. This will detect if the port has a local @@ -780,12 +834,10 @@ unsigned short nfs_getlocalport(const rpcprot_t program, const rpcvers_t version, const unsigned short protocol) { - struct addrinfo *gai_results; - struct addrinfo gai_hint = { - .ai_flags = AI_ADDRCONFIG, - }; + struct sockaddr_storage address; + struct sockaddr *lb_addr = (struct sockaddr *)&address; + socklen_t lb_len = sizeof(lb_addr); unsigned short port = 0; - int error; #ifdef NFS_GP_LOCAL const struct sockaddr_un sun = { @@ -811,12 +863,9 @@ unsigned short nfs_getlocalport(const rpcprot_t program, #endif /* NFS_GP_LOCAL */ if (port == 0) { - error = getaddrinfo(NULL, "sunrpc", &gai_hint, &gai_results); - if (error == 0) { - port = nfs_getport(gai_results->ai_addr, - gai_results->ai_addrlen, + if (nfs_gp_loopback_address(lb_addr, &lb_len)) { + port = nfs_getport(lb_addr, lb_len, program, version, protocol); - freeaddrinfo(gai_results); } else rpc_createerr.cf_stat = RPC_UNKNOWNADDR; } -- cgit From 18e84356811587a9cc405c4c6e18ca5573940e35 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 6 Jan 2009 12:12:55 -0500 Subject: mount command: Random clean up Fix some documenting comments and an error message in configure.ac. Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- configure.ac | 2 +- utils/mount/network.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 1b83296..48061e4 100644 --- a/configure.ac +++ b/configure.ac @@ -259,7 +259,7 @@ if test "$enable_ipv6" = yes; then AC_CHECK_LIB(tirpc, clnt_tli_create, , AC_MSG_ERROR([libtirpc needed for IPv6 support])) AC_CHECK_HEADERS(tirpc/netconfig.h, , - AC_MSG_ERROR([libtirpc-devel needed for IPv6 support])) + AC_MSG_ERROR([libtirpc headers needed for IPv6 support])) AC_CHECK_DECL([AI_ADDRCONFIG], , AC_MSG_ERROR([full getaddrinfo(3) implementation needed for IPv6 support]), [ #include ] ) diff --git a/utils/mount/network.c b/utils/mount/network.c index a82c338..d262e94 100644 --- a/utils/mount/network.c +++ b/utils/mount/network.c @@ -161,6 +161,7 @@ static void nfs_set_port(struct sockaddr *sap, const unsigned short port) /** * nfs_name_to_address - resolve hostname to an IPv4 or IPv6 socket address * @hostname: pointer to C string containing DNS hostname to resolve + * @af_hint: hint to restrict resolution to one address family * @sap: pointer to buffer to fill with socket address * @len: IN: size of buffer to fill; OUT: size of socket address * @@ -270,7 +271,7 @@ int nfs_name_to_address(const char *hostname, /** * nfs_gethostbyname - resolve a hostname to an IPv4 address * @hostname: pointer to a C string containing a DNS hostname - * @saddr: returns an IPv4 address + * @sin: returns an IPv4 address * * Returns 1 if successful, otherwise zero. */ -- cgit From 8b4b71895e95e55e9fa924c2cc159311eb329ee5 Mon Sep 17 00:00:00 2001 From: Chuck Lever Date: Tue, 6 Jan 2009 12:35:15 -0500 Subject: configure: use "--disable-uuid" instead of "--without-uuid" Reported by Kevin Coffman and Jonathan Andrews. Apparently --without-uuid doesn't work with some older versions of autoconf, so correct the help text to document the option that actually does the trick. Signed-off-by: Chuck Lever Signed-off-by: Steve Dickson --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 48061e4..7140f48 100644 --- a/configure.ac +++ b/configure.ac @@ -109,7 +109,7 @@ AC_ARG_WITH(rpcgen, AC_SUBST(RPCGEN_PATH) AM_CONDITIONAL(CONFIG_RPCGEN, [test "$RPCGEN_PATH" == ""]) AC_ARG_ENABLE(uuid, - [AC_HELP_STRING([--without-uuid], [Exclude uuid support and so avoid possibly buggy libblkid])], + [AC_HELP_STRING([--disable-uuid], [Exclude uuid support to avoid buggy libblkid])], if test "$enableval" = "yes" ; then choose_blkid=yes; else choose_blkid=no; fi, choose_blkid=default) AC_ARG_ENABLE(mount, -- cgit