Some IPv6 enhancements for nfs-utils
Subsystems (2)
cover Some IPv6 enhancements for nfs-utils
Hi Chuck et al,
I've been playing with IPv6 server support and offer these patches which get us a little bit closer.
I realise that you may already have similar patches queued in which case feel free to ignore these.
With these plus a couple of #defines of IPV6_SUPPORTED I can export with NFSv4 over IPv6 quite successfully.
NeilBrown
---
Neil Brown (3):
Make buffers large enough for IPv6 addresses Give hostname.c more support for IPv6 Allow check_fqdn to compare IPv6 addresses
support/export/client.c | 23 +---------------------- support/export/hostname.c | 28 +++++++++++++++++++--------- utils/mountd/cache.c | 6 +++--- utils/mountd/rmtab.c | 2 +- 4 files changed, 24 insertions(+), 35 deletions(-)
Signature · 1 line
Signature
PATCH 1/3 Make buffers large enough for IPv6 addresses
Each of these buffers is use to hold the presentation format for an address which could be either IPv4 or IPv6, so make the buffers large enough for either.
--- support/export/hostname.c | 2 +- utils/mountd/cache.c | 6 +++--- utils/mountd/rmtab.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-)
support/export/hostname.c +1 -1
@@ -299,7 +299,7 @@ struct addrinfo * host_numeric_addrinfo(const struct sockaddr *sap) {socklen_t salen =sockaddr_size (sap); -char buf[INET_ADDRSTRLEN ]; +char buf[INET6_ADDRSTRLEN ];struct addrinfo *ai;int error;
utils/mountd/cache.c +3 -3
@@ -75,7 +75,7 @@ void auth_unix_ip(FILE *f)*/ char *cp;char class[20 ]; -char ipaddr[20 ]; +char ipaddr[INET6_ADDRSTRLEN ];char *client =NULL ;struct addrinfo *tmp =NULL ;struct addrinfo *ai =NULL ;
@@ -90,7 +90,7 @@ void auth_unix_ip(FILE *f) strcmp(class, "nfsd") != 0)return ; -if (qword_get (&cp, ipaddr,20 ) <=0 ) +if (qword_get (&cp, ipaddr,sizeof (ipaddr)) <=0 )return ; tmp =host_pton (ipaddr);
@@ -920,7 +920,7 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path)int cache_export (nfs_export *exp,char *path) { -char buf[INET_ADDRSTRLEN ]; +char buf[INET6_ADDRSTRLEN ];int err;FILE *f;
utils/mountd/rmtab.c +1 -1
@@ -143,7 +143,7 @@ mountlist_del_all(struct sockaddr_in *sin)return ; hostname =host_canonname ((struct sockaddr *)sin);if (hostname ==NULL ) { -char buf[INET_ADDRSTRLEN ]; +char buf[INET6_ADDRSTRLEN ];xlog (L_ERROR ,"can't get hostname of %s" ,host_ntop ((struct sockaddr *)sin, buf,sizeof (buf))); goto out_unlock;
Re: [PATCH 1/3] Make buffers large enough for IPv6 addresses
Quoted 62 lines · Neil Brown
Each of these buffers is use to hold the presentation format for an address which could be either IPv4 or IPv6, so make the buffers large enough for either.
Signed-off-by NeilBrown <[email protected]>--- support/export/hostname.c | 2 +- utils/mountd/cache.c | 6 +++--- utils/mountd/rmtab.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-)support/export/hostname.c +1
-1@@ -299,7 +299,7 @@ struct addrinfo * host_numeric_addrinfo(const struct sockaddr *sap) {socklen_t salen =sockaddr_size (sap); -char buf[INET_ADDRSTRLEN ]; +char buf[INET6_ADDRSTRLEN ];struct addrinfo *ai;int error;utils/mountd/cache.c +3
-3@@ -75,7 +75,7 @@ void auth_unix_ip(FILE *f)*/ char *cp;char class[20 ]; -char ipaddr[20 ]; +char ipaddr[INET6_ADDRSTRLEN ];char *client =NULL ;struct addrinfo *tmp =NULL ;struct addrinfo *ai =NULL ;@@ -90,7 +90,7 @@ void auth_unix_ip(FILE *f) strcmp(class, "nfsd") != 0)return ; -if (qword_get (&cp, ipaddr,20 ) <=0 ) +if (qword_get (&cp, ipaddr,sizeof (ipaddr)) <=0 )return ; tmp =host_pton (ipaddr);@@ -920,7 +920,7 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path)int cache_export (nfs_export *exp,char *path) { -char buf[INET_ADDRSTRLEN ]; +char buf[INET6_ADDRSTRLEN ];int err;FILE *f;utils/mountd/rmtab.c +0
-0
utils/mountd/rmtab.c mountlist_del_all(struct sockaddr_in *sin) · line 149
Quoted 8 lines
utils/mountd/rmtab.c +1
-1@@ -143,7 +143,7 @@ mountlist_del_all(struct sockaddr_in *sin)return ; hostname =host_canonname ((struct sockaddr *)sin);if (hostname ==NULL ) { -char buf[INET_ADDRSTRLEN ]; +char buf[INET6_ADDRSTRLEN ];xlog (L_ERROR ,"can't get hostname of %s" ,host_ntop ((struct sockaddr *)sin, buf,sizeof (buf))); goto out_unlock;
These size changes already exist due to commit d901e32
steved.
PATCH 2/3 Give hostname.c more support for IPv6
In reply to Neil BrownAllow host_pton, host_addrinfo, and all functions that use sockaddr_size to work correctly with IPv6 addresses.
This means host_addrinfo can now return IPv6 addresses, but I think all code is ready for that.
--- support/export/hostname.c | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-)
support/export/hostname.c +18 -8
@@ -38,9 +38,11 @@static socklen_t sockaddr_size (const struct sockaddr *sap) { -if (sap->sa_family !=AF_INET ) -return 0 ; -return (socklen_t )sizeof (struct sockaddr_in ); +if (sap->sa_family ==AF_INET ) +return (socklen_t )sizeof (struct sockaddr_in ); +if (sap->sa_family ==AF_INET6 ) +return (socklen_t )sizeof (struct sockaddr_in6 ); +return 0 ; }#endif /* HAVE_GETNAMEINFO */
@@ -126,10 +128,12 @@ host_pton(const char *paddr)* addresses that end with a blank. * * inet_pton(3) is much stricter. Use it to be certain we -* have a real AF_INET presentation address, before invoking -* getaddrinfo(3) to generate the full addrinfo list. +* have a real AF_INET or AF_INET6 presentation address, +* before invoking getaddrinfo(3) to generate the full +* addrinfo list. */ -if (inet_pton (AF_INET , paddr, &sin.sin_addr) ==0 ) +if (inet_pton (AF_INET , paddr, &sin.sin_addr) ==0 && +inet_pton (AF_INET6 , paddr, &sin.sin_addr) ==0 )return NULL ; error =getaddrinfo (paddr,NULL , &hint, &ai);
@@ -168,7 +172,7 @@ host_addrinfo(const char *hostname) {struct addrinfo *ai =NULL ;struct addrinfo hint = { - .ai_family =AF_INET , + .ai_family =AF_UNSPEC ,/* don't return duplicates */ .ai_protocol = (int )IPPROTO_UDP , .ai_flags =AI_ADDRCONFIG |AI_CANONNAME ,
@@ -178,7 +182,13 @@ host_addrinfo(const char *hostname) error =getaddrinfo (hostname,NULL , &hint, &ai);switch (error) {case 0 : -return ai; +if (ai->ai_family ==AF_INET || + ai->ai_family ==AF_INET6 ) +return ai; +freeaddrinfo (ai); +xlog (D_GENERAL ,"%s: resolved to neither IPv4 nor IPv6 address." , + hostname); +break ;case EAI_SYSTEM :xlog (D_GENERAL ,"%s: failed to resolve %s: (%d) %m" , __func__, hostname, errno);
Re: [PATCH 2/3] Give hostname.c more support for IPv6
Neil Brown wrote:
+ if (inet_pton(AF_INET, paddr, &sin.sin_addr) == 0 &&
+ inet_pton(AF_INET6, paddr, &sin.sin_addr) == 0)
return NULL;
Having converted a few apps myself, I wish there were an equivalent to inet_pton that instead of taking an AF argument, would return the AF that it found. Then you could do the above in a single call.
Re: [PATCH 2/3] Give hostname.c more support for IPv6
In reply to Neil BrownQuoted 19 lines · Neil Brown
Allow
host_pton,host_addrinfo, and all functions that usesockaddr_sizeto work correctly with IPv6 addresses.This means
host_addrinfocan now return IPv6 addresses, but I think all code is ready for that.Signed-off-by NeilBrown <[email protected]>--- support/export/hostname.c | 26 ++++++++++++++++++-------- 1 files changed, 18 insertions(+), 8 deletions(-)support/export/hostname.c +0
-0@@ -38,9 +38,11 @@static socklen_t sockaddr_size (const struct sockaddr *sap) {
support/export/hostname.c line 47
Quoted 10 lines
support/export/hostname.c +5
-3-if (sap->sa_family !=AF_INET ) -return 0 ; - return (socklen_t)sizeof(struct sockaddr_in); +if (sap->sa_family ==AF_INET ) +return (socklen_t )sizeof (struct sockaddr_in ); +if (sap->sa_family ==AF_INET6 ) +return (socklen_t )sizeof (struct sockaddr_in6 ); + return 0; }#endif /* HAVE_GETNAMEINFO */
This routine was eliminated with commit 63afb9
Quoted 5 lines
support/export/hostname.c +0
-0@@ -126,10 +128,12 @@ host_pton(const char *paddr)* addresses that end with a blank. * * inet_pton(3) is much stricter. Use it to be certain we
support/export/hostname.c host_pton(const char *paddr) · line 137
Quoted 10 lines
support/export/hostname.c +5
-3-* have a real AF_INET presentation address, before invoking -* getaddrinfo(3) to generate the full addrinfo list. +* have a real AF_INET or AF_INET6 presentation address, +* before invoking getaddrinfo(3) to generate the full +* addrinfo list. */ -if (inet_pton (AF_INET , paddr, &sin.sin_addr) ==0 ) +if (inet_pton (AF_INET , paddr, &sin.sin_addr) ==0 && +inet_pton (AF_INET6 , paddr, &sin.sin_addr) ==0 )return NULL ;
This error case is already handled in the current version of of host_pton, but I must say, the above approved is much clear than the existing code... but I'm going to leave things as-is..
Quoted 13 lines
support/export/hostname.c +1
-1error =getaddrinfo (paddr,NULL , &hint, &ai);@@ -168,7 +172,7 @@ host_addrinfo(const char *hostname) {struct addrinfo *ai =NULL ;struct addrinfo hint = { - .ai_family =AF_INET , + .ai_family =AF_UNSPEC ,/* don't return duplicates */ .ai_protocol = (int )IPPROTO_UDP , .ai_flags =AI_ADDRCONFIG |AI_CANONNAME ,@@ -178,7 +182,13 @@ host_addrinfo(const char *hostname) error =getaddrinfo (hostname,NULL , &hint, &ai);
support/export/hostname.c host_addrinfo(const char *hostname) · line 191
Quoted 10 lines
support/export/hostname.c +7
-1switch (error) {case 0 : -return ai; +if (ai->ai_family ==AF_INET || + ai->ai_family ==AF_INET6 ) +return ai; +freeaddrinfo (ai); +xlog (D_GENERAL ,"%s: resolved to neither IPv4 nor IPv6 address." , + hostname); +break ;
I think I'm going to try and blend this in with Chuck's recent patches since I do like the idea of logging unsupported address families...
steved.
Quoted 5 lines
support/export/hostname.c +0
-0case EAI_SYSTEM :xlog (D_GENERAL ,"%s: failed to resolve %s: (%d) %m" , __func__, hostname, errno);
PATCH 3/3 Allow check_fqdn to compare IPv6 addresses
In reply to Neil BrownSimply use nfs_compare_sockaddr in place of addrs_match
--- support/export/client.c | 23 +---------------------- 1 files changed, 1 insertions(+), 22 deletions(-)
support/export/client.c +1 -22
@@ -372,27 +372,6 @@ add_name(char *old, const char *add)return new; } -static _Bool -addrs_match4 (const struct sockaddr *sa1,const struct sockaddr *sa2) -{ -const struct sockaddr_in *si1 = (const struct sockaddr_in *)sa1; -const struct sockaddr_in *si2 = (const struct sockaddr_in *)sa2; - -return si1->sin_addr.s_addr == si2->sin_addr.s_addr; -} - -static _Bool -addrs_match (const struct sockaddr *sa1,const struct sockaddr *sa2) -{ -if (sa1->sa_family == sa2->sa_family) -switch (sa1->sa_family) { -case AF_INET : -return addrs_match4 (sa1, sa2); - } - -return false; -} -/* * Check each address listed in @ai against each address * stored in @clp. Return 1 if a match is found, otherwise
@@ -405,7 +384,7 @@ check_fqdn(const nfs_client *clp, const struct addrinfo *ai)for (; ai; ai = ai->ai_next)for (i =0 ; i < clp->m_naddr; i++) -if (addrs_match (ai->ai_addr,get_addrlist (clp, i))) +if (nfs_compare_sockaddr (ai->ai_addr,get_addrlist (clp, i)))return 1 ;return 0 ;
Re: [PATCH 3/3] Allow check_fqdn to compare IPv6 addresses
Quoted 42 lines · Neil Brown
Simply use
nfs_compare_sockaddrin place ofaddrs_matchSigned-off-by NeilBrown <[email protected]>--- support/export/client.c | 23 +---------------------- 1 files changed, 1 insertions(+), 22 deletions(-)support/export/client.c +0
-21@@ -372,27 +372,6 @@ add_name(char *old, const char *add)return new; } -static _Bool -addrs_match4 (const struct sockaddr *sa1,const struct sockaddr *sa2) -{ -const struct sockaddr_in *si1 = (const struct sockaddr_in *)sa1; -const struct sockaddr_in *si2 = (const struct sockaddr_in *)sa2; - -return si1->sin_addr.s_addr == si2->sin_addr.s_addr; -} - -static _Bool -addrs_match (const struct sockaddr *sa1,const struct sockaddr *sa2) -{ -if (sa1->sa_family == sa2->sa_family) -switch (sa1->sa_family) { -case AF_INET : -return addrs_match4 (sa1, sa2); - } - -return false; -} -/* * Check each address listed in @ai against each address * stored in @clp. Return 1 if a match is found, otherwise
support/export/client.c check_fqdn(const nfs_client *clp, const struct addrinfo *ai) · line 390
Quoted 8 lines
support/export/client.c +1
-1@@ -405,7 +384,7 @@ check_fqdn(const nfs_client *clp, const struct addrinfo *ai)for (; ai; ai = ai->ai_next)for (i =0 ; i < clp->m_naddr; i++) -if (addrs_match (ai->ai_addr,get_addrlist (clp, i))) +if (nfs_compare_sockaddr (ai->ai_addr,get_addrlist (clp, i)))return 1 ;return 0 ;
This change already exists due to commit 60abb9
steved.
Hi Neil-
Quoted 5 lines · Neil Brown
Hi Chuck et al,
I've been playing with IPv6 server support and offer these patches which get us a little bit closer.
I realise that you may already have similar patches queued in which case feel free to ignore these.
The full series of patches giving mountd IPv6 support is in my git repo on linux-nfs.org. See:
http://git.linux-nfs.org/?p=cel/nfs-utils.git;a=summary
This is what we have queued up. We're taking a resting stop for the next nfs-utils release since the pre-requisite patches touched so many parts of mountd, and we'd like to give them some soak time.
If SuSE requires NFS server-side IPv6 support, would it be possible for you to try out my series? It looks like you touched all the important bases in your patch set.
Quoted 13 lines
With these plus a couple of #defines of
IPV6_SUPPORTEDI can export with NFSv4 over IPv6 quite successfully.NeilBrown
---
Neil Brown (3):
Make buffers large enough for IPv6 addresses
Givehostname.cmore support for IPv6
Allowcheck_fqdnto compare IPv6 addresses
Quoted 9 lines
support/export/client.c | 23 +---------------------- support/export/hostname.c | 28 +++++++++++++++++++--------- utils/mountd/cache.c | 6 +++--- utils/mountd/rmtab.c | 2 +- 4 files changed, 24 insertions(+), 35 deletions(-)Signature · 1 line
Signature
--
Chuck Lever
chuck[dot]lever[at]oracle[dot]com