From b528396f6d6f4b0a677fdcf1fcc29eb0d2add7d4 Mon Sep 17 00:00:00 2001 From: Jeff Layton Date: Dec 04 2009 19:35:54 +0000 Subject: Remove server-side bits since they're not quite baked yet --- diff --git a/nfs-utils-1.2.1-cel-ipv6.patch b/nfs-utils-1.2.1-cel-ipv6.patch index 4b252a5..2130d33 100644 --- a/nfs-utils-1.2.1-cel-ipv6.patch +++ b/nfs-utils-1.2.1-cel-ipv6.patch @@ -10385,7433 +10385,3 @@ index 84d4122..d64fd8e 100644 return 0; } -------------------------------------------------------------------------------- -libexport-a-remove-dead-code -------------------------------------------------------------------------------- -libexport.a: Remove dead code - -From: Chuck Lever - -Clean up: I can't find any call sites for client_find() or -client_match(). - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 22 ---------------------- - support/include/exportfs.h | 2 -- - 2 files changed, 0 insertions(+), 24 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 5fcf355..2af07da 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -211,28 +211,6 @@ client_freeall(void) - } - } - --nfs_client * --client_find(struct hostent *hp) --{ -- nfs_client *clp; -- int i; -- -- for (i = 0; i < MCL_MAXTYPES; i++) { -- for (clp = clientlist[i]; clp; clp = clp->m_next) { -- if (!client_check(clp, hp)) -- continue; --#ifdef notdef -- if (clp->m_type == MCL_FQDN) -- return clp; -- return client_dup(clp, hp); --#else -- return clp; --#endif -- } -- } -- return NULL; --} -- - struct hostent * - client_resolve(struct in_addr addr) - { -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 1ad41e2..ef96a02 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -80,12 +80,10 @@ extern exp_hash_table exportlist[MCL_MAXTYPES]; - extern nfs_client * clientlist[MCL_MAXTYPES]; - - nfs_client * client_lookup(char *hname, int canonical); --nfs_client * client_find(struct hostent *); - void client_add(nfs_client *); - nfs_client * client_dup(nfs_client *, struct hostent *); - int client_gettype(char *hname); - int client_check(nfs_client *, struct hostent *); --int client_match(nfs_client *, char *hname); - void client_release(nfs_client *); - void client_freeall(void); - char * client_compose(struct hostent *he); -------------------------------------------------------------------------------- -libexport-a-eliminate-nfs_clie -------------------------------------------------------------------------------- -libexport.a: Eliminate nfs_client.m_count field - -From: Chuck Lever - -Since nfs_client records are not garbage collected, there doesn't seem -to be any real need to maintain a reference count for each record. - -In addition to removing nominally dead code, this commit gets rid of a -site where a mountd or exportfs process can exit suddenly due to a -software bug. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 9 --------- - support/export/export.c | 3 --- - support/include/exportfs.h | 2 -- - 3 files changed, 0 insertions(+), 14 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 2af07da..b08dda2 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -135,7 +135,6 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) - clp->m_hostname = xstrdup(hname); - - clp->m_exported = 0; -- clp->m_count = 0; - - if (clp->m_type == MCL_SUBNETWORK) { - char *cp = strchr(clp->m_hostname, '/'); -@@ -188,14 +187,6 @@ client_add(nfs_client *clp) - } - - void --client_release(nfs_client *clp) --{ -- if (clp->m_count <= 0) -- xlog(L_FATAL, "client_free: m_count <= 0!"); -- clp->m_count--; --} -- --void - client_freeall(void) - { - nfs_client *clp, **head; -diff --git a/support/export/export.c b/support/export/export.c -index e5e6cb0..f5846d0 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -95,7 +95,6 @@ export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep) - exp->m_changed = 0; - exp->m_warned = 0; - exp->m_client = clp; -- clp->m_count++; - } - - /* -@@ -115,7 +114,6 @@ export_dup(nfs_export *exp, struct hostent *hp) - if (exp->m_export.e_hostname) - new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname); - clp = client_dup(exp->m_client, hp); -- clp->m_count++; - new->m_client = clp; - new->m_mayexport = exp->m_mayexport; - new->m_exported = 0; -@@ -266,7 +264,6 @@ export_freeall(void) - for (i = 0; i < MCL_MAXTYPES; i++) { - for (exp = exportlist[i].p_head; exp; exp = nxt) { - nxt = exp->m_next; -- client_release(exp->m_client); - if (exp->m_export.e_squids) - xfree(exp->m_export.e_squids); - if (exp->m_export.e_sqgids) -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index ef96a02..6dec3d6 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -48,7 +48,6 @@ typedef struct mclient { - int m_naddr; - struct in_addr m_addrlist[NFSCLNT_ADDRMAX]; - int m_exported; /* exported to nfsd */ -- int m_count; - } nfs_client; - - typedef struct mexport { -@@ -84,7 +83,6 @@ void client_add(nfs_client *); - nfs_client * client_dup(nfs_client *, struct hostent *); - int client_gettype(char *hname); - int client_check(nfs_client *, struct hostent *); --void client_release(nfs_client *); - void client_freeall(void); - char * client_compose(struct hostent *he); - struct hostent * client_resolve(struct in_addr addr); -------------------------------------------------------------------------------- -libexport-a-clean-up-client_co -------------------------------------------------------------------------------- -libexport.a: Clean up client_compose() and client_member() - -From: Chuck Lever - -Clean up: Replace outdated comments, and fix some function -declarations. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 32 +++++++++++++++++++++----------- - 1 files changed, 21 insertions(+), 11 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index b08dda2..179471f 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -28,6 +28,8 @@ - #if !defined(__GLIBC__) || __GLIBC__ < 2 - extern int innetgr(char *netgr, char *host, char *, char *); - #endif -+ -+static char *add_name(char *old, char *add); - static void client_init(nfs_client *clp, const char *hname, - struct hostent *hp); - static int client_checkaddr(nfs_client *clp, struct in_addr addr); -@@ -215,14 +217,18 @@ client_resolve(struct in_addr addr) - return he; - } - --/* -- * Find client name given an IP address -- * This is found by gathering all known names that match that IP address, -- * sorting them and joining them with '+' -+/** -+ * client_compose - Make a list of cached hostnames that match an IP address -+ * @he: pointer to hostent containing IP address information to match -+ * -+ * Gather all known client hostnames that match the IP address, and sort -+ * the result into a comma-separated list. - * -+ * Returns a '\0'-terminated ASCII string containing a comma-separated -+ * sorted list of client hostnames, or NULL if no client records matched -+ * the IP address or memory could not be allocated. Caller must free the -+ * returned string with free(3). - */ --static char *add_name(char *old, char *add); -- - char * - client_compose(struct hostent *he) - { -@@ -240,12 +246,17 @@ client_compose(struct hostent *he) - return name; - } - -+/** -+ * client_member - check if @name is contained in the list @client -+ * @client: '\0'-terminated ASCII string containing -+ * comma-separated list of hostnames -+ * @name: '\0'-terminated ASCII string containing hostname to look for -+ * -+ * Returns 1 if @name was found in @client, otherwise zero is returned. -+ */ - int - client_member(char *client, char *name) - { -- /* check if "client" (a ',' separated list of names) -- * contains 'name' as a member -- */ - int l = strlen(name); - while (*client) { - if (strncmp(client, name, l) == 0 && -@@ -259,8 +270,7 @@ client_member(char *client, char *name) - return 0; - } - -- --int -+static int - name_cmp(char *a, char *b) - { - /* compare strings a and b, but only upto ',' in a */ -------------------------------------------------------------------------------- -libexport-a-factor-fqdn-checki -------------------------------------------------------------------------------- -libexport.a: Factor FQDN checking out of check_client() - -From: Chuck Lever - -Clean up: Factor the MCL_FQDN case out of check_client() and -client_checkaddr(). This will make it easier to add IPv6 support -eventually. - -The logic in the new helper function will get a little more tangled -once IPv6 support is introduced. Each slot in the clp address list -eventually may contain an address from either address family. - -Note that the switch statement in client_checkaddr() is redundant, -since clp->cl_mtype is loop invariant. This change makes FQDN client -checking more efficient, at the cost of a few extra lines of code. - -This commit should not change code behavior in any way. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 29 +++++++++++++++++++++++------ - 1 files changed, 23 insertions(+), 6 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 179471f..292066d 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -319,6 +319,28 @@ add_name(char *old, char *add) - } - - /* -+ * Check each address listed in @hp against each address -+ * stored in @clp. Return 1 if a match is found, otherwise -+ * zero. -+ */ -+static int -+check_fqdn(const nfs_client *clp, const struct hostent *hp) -+{ -+ struct in_addr addr; -+ char **ap; -+ int i; -+ -+ for (ap = hp->h_addr_list; *ap; ap++) { -+ addr = *(struct in_addr *)*ap; -+ -+ for (i = 0; i < clp->m_naddr; i++) -+ if (clp->m_addrlist[i].s_addr == addr.s_addr) -+ return 1; -+ } -+ return 0; -+} -+ -+/* - * Match a host (given its hostent record) to a client record. This - * is usually called from mountd. - */ -@@ -331,6 +353,7 @@ client_check(nfs_client *clp, struct hostent *hp) - - switch (clp->m_type) { - case MCL_FQDN: -+ return check_fqdn(clp, hp); - case MCL_SUBNETWORK: - for (ap = hp->h_addr_list; *ap; ap++) { - if (client_checkaddr(clp, *(struct in_addr *) *ap)) -@@ -404,12 +427,6 @@ client_checkaddr(nfs_client *clp, struct in_addr addr) - int i; - - switch (clp->m_type) { -- case MCL_FQDN: -- for (i = 0; i < clp->m_naddr; i++) { -- if (clp->m_addrlist[i].s_addr == addr.s_addr) -- return 1; -- } -- return 0; - case MCL_SUBNETWORK: - return !((clp->m_addrlist[0].s_addr ^ addr.s_addr) - & clp->m_addrlist[1].s_addr); -------------------------------------------------------------------------------- -libexport-a-factor-subnetwork- -------------------------------------------------------------------------------- -libexport.a: Factor SUBNETWORK checking out of check_client() - -From: Chuck Lever - -Clean up: Factor the MCL_SUBNETWORK case out of check_client() and -client_checkaddr(). This will make it easier to add IPv6 support -eventually. - -The logic in the new helper function will get a little more tangled -once IPv6 support is introduced. Each slot in the clp address list -eventually may contain an address from either address family. - -Note that the switch statement in client_checkaddr() is redundant, -since clp->cl_mtype is loop invariant. This change makes SUBNETWORK -client checking more efficient, at the cost of a few extra lines of -code. - -This commit should not change code behavior in any way. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 32 ++++++++++++++++++++++---------- - 1 files changed, 22 insertions(+), 10 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 292066d..1e9e870 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -341,6 +341,27 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp) - } - - /* -+ * Check each address listed in @hp against the subnetwork or -+ * host address stored in @clp. Return 1 if an address in @hp -+ * matches the host address stored in @clp, otherwise zero. -+ */ -+static int -+check_subnetwork(const nfs_client *clp, const struct hostent *hp) -+{ -+ struct in_addr addr; -+ char **ap; -+ -+ for (ap = hp->h_addr_list; *ap; ap++) { -+ addr = *(struct in_addr *)*ap; -+ -+ if (!((clp->m_addrlist[0].s_addr ^ addr.s_addr) & -+ clp->m_addrlist[1].s_addr)) -+ return 1; -+ } -+ return 0; -+} -+ -+/* - * Match a host (given its hostent record) to a client record. This - * is usually called from mountd. - */ -@@ -355,11 +376,7 @@ client_check(nfs_client *clp, struct hostent *hp) - case MCL_FQDN: - return check_fqdn(clp, hp); - case MCL_SUBNETWORK: -- for (ap = hp->h_addr_list; *ap; ap++) { -- if (client_checkaddr(clp, *(struct in_addr *) *ap)) -- return 1; -- } -- return 0; -+ return check_subnetwork(clp, hp); - case MCL_WILDCARD: - if (wildmat(hname, cname)) - return 1; -@@ -426,11 +443,6 @@ client_checkaddr(nfs_client *clp, struct in_addr addr) - { - int i; - -- switch (clp->m_type) { -- case MCL_SUBNETWORK: -- return !((clp->m_addrlist[0].s_addr ^ addr.s_addr) -- & clp->m_addrlist[1].s_addr); -- } - return 0; - } - -------------------------------------------------------------------------------- -libexport-a-remove-unused-func -------------------------------------------------------------------------------- -libexport.a: Remove unused function client_checkaddr() - -From: Chuck Lever - -Clean up. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 9 --------- - 1 files changed, 0 insertions(+), 9 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 1e9e870..11441ed 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -32,7 +32,6 @@ extern int innetgr(char *netgr, char *host, char *, char *); - static char *add_name(char *old, char *add); - static void client_init(nfs_client *clp, const char *hname, - struct hostent *hp); --static int client_checkaddr(nfs_client *clp, struct in_addr addr); - - nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; - -@@ -438,14 +437,6 @@ client_check(nfs_client *clp, struct hostent *hp) - return 0; - } - --static int --client_checkaddr(nfs_client *clp, struct in_addr addr) --{ -- int i; -- -- return 0; --} -- - int - client_gettype(char *ident) - { -------------------------------------------------------------------------------- -libexport-a-refactor-netgroup- -------------------------------------------------------------------------------- -libexport.a: Refactor netgroup checking in client_check() - -From: Chuck Lever - -Clean up: refactor netgroup logic out of client_check() to make it -easier to introduce IPv6 support. - - + Use preferred style of keeping #ifdef out of the middle of - function definitions. Squelch compiler warnings for "#ifndef - HAVE_INNETGR" by using __attribute__((unused)). - - + Use preferred style of not using curly braces around switch cases. - - + Match style used for check_{fqdn,subnetwork}. - - + Clarify comment documenting use of h_aliases - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 95 +++++++++++++++++++++++++++-------------------- - 1 files changed, 55 insertions(+), 40 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 11441ed..a573767 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -361,6 +361,60 @@ check_subnetwork(const nfs_client *clp, const struct hostent *hp) - } - - /* -+ * Check if @hp's hostname or aliases fall in a given netgroup. -+ * Return 1 if @hp represents a host in the netgroup, otherwise zero. -+ */ -+#ifdef HAVE_INNETGR -+static int -+check_netgroup(const char *cname, const struct hostent *hp) -+{ -+ const char *netgroup = cname + 1; -+ char *hname = hp->h_name; -+ struct hostent *nhp = NULL; -+ struct sockaddr_in addr; -+ int match, i; -+ char *dot; -+ -+ /* First, try to match the hostname without -+ * splitting off the domain */ -+ if (innetgr(netgroup, hname, NULL, NULL)) -+ return 1; -+ -+ /* Try matching aliases of this host listed in /etc/hosts or nis[+] */ -+ for (i = 0; hp->h_aliases[i]; i++) { -+ if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL)) -+ return 1; -+ } -+ -+ /* If hname is ip address convert to FQDN */ -+ if (inet_aton(hname, &addr.sin_addr) && -+ (nhp = gethostbyaddr((const char *)&(addr.sin_addr), -+ sizeof(addr.sin_addr), AF_INET))) { -+ hname = nhp->h_name; -+ if (innetgr(netgroup, hname, NULL, NULL)) -+ return 1; -+ } -+ -+ /* Okay, strip off the domain (if we have one) */ -+ if ((dot = strchr(hname, '.')) == NULL) -+ return 0; -+ -+ *dot = '\0'; -+ match = innetgr(netgroup, hname, NULL, NULL); -+ *dot = '.'; -+ -+ return match; -+} -+#else /* !HAVE_INNETGR */ -+static int -+check_netgroup(__attribute__((unused)) const char *cname, -+ __attribute__((unused)) const struct hostent *hp) -+{ -+ return 0; -+} -+#endif /* !HAVE_INNETGR */ -+ -+/* - * Match a host (given its hostent record) to a client record. This - * is usually called from mountd. - */ -@@ -386,46 +440,7 @@ client_check(nfs_client *clp, struct hostent *hp) - } - return 0; - case MCL_NETGROUP: --#ifdef HAVE_INNETGR -- { -- char *dot; -- int match, i; -- struct hostent *nhp = NULL; -- struct sockaddr_in addr; -- -- /* First, try to match the hostname without -- * splitting off the domain */ -- if (innetgr(cname+1, hname, NULL, NULL)) -- return 1; -- -- /* try the aliases as well */ -- for (i = 0; hp->h_aliases[i]; i++) { -- if (innetgr(cname+1, hp->h_aliases[i], NULL, NULL)) -- return 1; -- } -- -- /* If hname is ip address convert to FQDN */ -- if (inet_aton(hname, &addr.sin_addr) && -- (nhp = gethostbyaddr((const char *)&(addr.sin_addr), -- sizeof(addr.sin_addr), AF_INET))) { -- hname = (char *)nhp->h_name; -- if (innetgr(cname+1, hname, NULL, NULL)) -- return 1; -- } -- -- /* Okay, strip off the domain (if we have one) */ -- if ((dot = strchr(hname, '.')) == NULL) -- return 0; -- -- *dot = '\0'; -- match = innetgr(cname+1, hname, NULL, NULL); -- *dot = '.'; -- -- return match; -- } --#else -- return 0; --#endif -+ return check_netgroup(clp->m_hostname, hp); - case MCL_ANONYMOUS: - return 1; - case MCL_GSS: -------------------------------------------------------------------------------- -libexport-a-refactor-wildcard- -------------------------------------------------------------------------------- -libexport.a: Refactor wildcard checking in client_check() - -From: Chuck Lever - -Clean up: refactor wildcard logic out of client_check() to make it -easier to introduce IPv6 support. - -Match the style used for client_check_{fqdn,subnetwork,netgroup}. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 35 +++++++++++++++++++++++------------ - 1 files changed, 23 insertions(+), 12 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index a573767..2ebab82 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -361,6 +361,28 @@ check_subnetwork(const nfs_client *clp, const struct hostent *hp) - } - - /* -+ * Check if a wildcard nfs_client record matches the canonical name -+ * or the aliases of a host. Return 1 if a match is found, otherwise -+ * zero. -+ */ -+static int -+check_wildcard(char *cname, const struct hostent *hp) -+{ -+ char *hname = hp->h_name; -+ char **ap; -+ -+ if (wildmat(hname, cname)) -+ return 1; -+ -+ /* Try matching aliases of this host listed in /etc/hosts or nis[+] */ -+ for (ap = hp->h_aliases; *ap; ap++) -+ if (wildmat(*ap, cname)) -+ return 1; -+ -+ return 0; -+} -+ -+/* - * Check if @hp's hostname or aliases fall in a given netgroup. - * Return 1 if @hp represents a host in the netgroup, otherwise zero. - */ -@@ -421,24 +443,13 @@ check_netgroup(__attribute__((unused)) const char *cname, - int - client_check(nfs_client *clp, struct hostent *hp) - { -- char *hname = (char *) hp->h_name; -- char *cname = clp->m_hostname; -- char **ap; -- - switch (clp->m_type) { - case MCL_FQDN: - return check_fqdn(clp, hp); - case MCL_SUBNETWORK: - return check_subnetwork(clp, hp); - case MCL_WILDCARD: -- if (wildmat(hname, cname)) -- return 1; -- else { -- for (ap = hp->h_aliases; *ap; ap++) -- if (wildmat(*ap, cname)) -- return 1; -- } -- return 0; -+ return check_wildcard(clp->m_hostname, hp); - case MCL_NETGROUP: - return check_netgroup(clp->m_hostname, hp); - case MCL_ANONYMOUS: -------------------------------------------------------------------------------- -libexport-a-replace-xlog-l_fat -------------------------------------------------------------------------------- -libexport.a: replace xlog(L_FATAL) in client_check() - -From: Chuck Lever - -Clean up: Prevent the process from exiting in client_check(). Report -bad m_type values, but return 0. - -This removes another site where a mountd or exportfs process can exit -sideways. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 13 +++++++++---- - 1 files changed, 9 insertions(+), 4 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 2ebab82..adc502e 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -436,9 +436,13 @@ check_netgroup(__attribute__((unused)) const char *cname, - } - #endif /* !HAVE_INNETGR */ - --/* -- * Match a host (given its hostent record) to a client record. This -- * is usually called from mountd. -+/** -+ * client_check - check if IP address information matches a cached nfs_client -+ * @clp: pointer to a cached nfs_client record -+ * @hp: pointer to hostent containing host IP information -+ * -+ * Returns 1 if the address information matches the cached nfs_client, -+ * otherwise zero. - */ - int - client_check(nfs_client *clp, struct hostent *hp) -@@ -457,7 +461,8 @@ client_check(nfs_client *clp, struct hostent *hp) - case MCL_GSS: - return 0; - default: -- xlog(L_FATAL, "internal: bad client type %d", clp->m_type); -+ xlog(D_GENERAL, "%s: unrecognized client type: %d", -+ __func__, clp->m_type); - } - - return 0; -------------------------------------------------------------------------------- -libexport-a-add-client_resolve -------------------------------------------------------------------------------- -libexport.a: Add client_resolve_addr() - -From: Chuck Lever - -Clean up: Introduce a new function in libexport.a that combines -client_resolve() and converting a presentation address to a sockaddr. - -This combination appears in several places in libexport.a, each of -which will need to be expanded to support IPv6. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 27 +++++++++++++++++++++++++++ - support/include/exportfs.h | 2 ++ - utils/mountd/cache.c | 21 ++++++--------------- - 3 files changed, 35 insertions(+), 15 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index adc502e..cc64b3d 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -203,6 +203,13 @@ client_freeall(void) - } - } - -+/** -+ * client_resolve - look up an IPv4 address -+ * @addr: IPv4 address to resolve -+ * -+ * Returns a dynamically allocated hostent structure, or NULL if -+ * some problem occurred. Caller must free the result with free(3). -+ */ - struct hostent * - client_resolve(struct in_addr addr) - { -@@ -217,6 +224,26 @@ client_resolve(struct in_addr addr) - } - - /** -+ * client_resolve_paddr - resolve a presentation address -+ * @address: '\0'-terminated ASCII string containing an IP presentation address -+ * @result: OUT: pointer to result -+ * -+ * Returns 1 and sets @result if @paddr is a valid IP presentation address; -+ * otherwise 0 is returned. Caller must free @result with free(3). -+ */ -+int -+client_resolve_paddr(const char *address, struct hostent **result) -+{ -+ struct in_addr addr; -+ -+ if (!inet_aton(address, &addr)) -+ return 0; -+ -+ *result = client_resolve(addr); -+ return 1; -+} -+ -+/** - * client_compose - Make a list of cached hostnames that match an IP address - * @he: pointer to hostent containing IP address information to match - * -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 6dec3d6..fa6b47b 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -86,6 +86,8 @@ int client_check(nfs_client *, struct hostent *); - void client_freeall(void); - char * client_compose(struct hostent *he); - struct hostent * client_resolve(struct in_addr addr); -+int client_resolve_paddr(const char *address, -+ struct hostent **result); - int client_member(char *client, char *name); - - int export_read(char *fname); -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index 0af1daa..92cc87f 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -66,7 +66,6 @@ void auth_unix_ip(FILE *f) - char class[20]; - char ipaddr[20]; - char *client = NULL; -- struct in_addr addr; - struct hostent *he = NULL; - if (readline(fileno(f), &lbuf, &lbuflen) != 1) - return; -@@ -82,14 +81,12 @@ void auth_unix_ip(FILE *f) - if (qword_get(&cp, ipaddr, 20) <= 0) - return; - -- if (inet_aton(ipaddr, &addr)==0) -- return; -- - auth_reload(); - - /* addr is a valid, interesting address, find the domain name... */ - if (!use_ipaddr) { -- he = client_resolve(addr); -+ if (!client_resolve_paddr(ipaddr, &he)) -+ return; - client = client_compose(he); - } - -@@ -468,11 +465,8 @@ void nfsd_fh(FILE *f) - break; - } - if (use_ipaddr) { -- if (he == NULL) { -- if (!inet_aton(dom, &addr)) -- goto out; -- he = client_resolve(addr); -- } -+ if (!he && !client_resolve_paddr(dom, &he)) -+ goto out; - if (!client_check(exp->m_client, he)) - continue; - } -@@ -690,11 +684,8 @@ void nfsd_export(FILE *f) - continue; - } - if (use_ipaddr) { -- if (he == NULL) { -- if (!inet_aton(dom, &addr)) -- goto out; -- he = client_resolve(addr); -- } -+ if (!he && !client_resolve_paddr(dom, &he)) -+ goto out; - if (!client_check(exp->m_client, he)) - continue; - } -------------------------------------------------------------------------------- -libexport-a-reduce-code-duplic -------------------------------------------------------------------------------- -libexport.a: Reduce code duplication in client_init() - -From: Chuck Lever - -Clean up: Most cases in client_init() set clp->m_naddr to zero. Move -it to the common part of the function, and simplify the logic. This -will make IPv6 support here more straightforward. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 9 +++++---- - 1 files changed, 5 insertions(+), 4 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index cc64b3d..594f459 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -136,6 +136,7 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) - clp->m_hostname = xstrdup(hname); - - clp->m_exported = 0; -+ clp->m_naddr = 0; - - if (clp->m_type == MCL_SUBNETWORK) { - char *cp = strchr(clp->m_hostname, '/'); -@@ -159,10 +160,10 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) - } - } - *cp = '/'; -- clp->m_naddr = 0; -- } else if (!hp) { -- clp->m_naddr = 0; -- } else { -+ return; -+ } -+ -+ if (hp) { - char **ap = hp->h_addr_list; - int i; - -------------------------------------------------------------------------------- -libexport-a-add-helper-for-pop -------------------------------------------------------------------------------- -libexport.a: Add helper for populating m_addrlist[] - -From: Chuck Lever - -Clean up: Move common code that populates an nfs_client record's -m_addrlist to a helper function. This eliminates a little code -duplication, and makes it simpler to add IPv6 support later. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 35 ++++++++++++++++++----------------- - 1 files changed, 18 insertions(+), 17 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 594f459..6b76e83 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -36,6 +36,21 @@ static void client_init(nfs_client *clp, const char *hname, - nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; - - -+static void -+init_addrlist(nfs_client *clp, const struct hostent *hp) -+{ -+ char **ap; -+ int i; -+ -+ if (!hp) -+ return; -+ -+ ap = hp->h_addr_list; -+ for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) -+ clp->m_addrlist[i] = *(struct in_addr *)*ap; -+ clp->m_naddr = i; -+} -+ - /* if canonical is set, then we *know* this is already a canonical name - * so hostname lookup is avoided. - * This is used when reading /proc/fs/nfs/exports -@@ -96,14 +111,8 @@ client_lookup(char *hname, int canonical) - client_add(clp); - } - -- if (htype == MCL_FQDN && clp->m_naddr == 0 && hp != NULL) { -- char **ap = hp->h_addr_list; -- int i; -- -- for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) -- clp->m_addrlist[i] = *(struct in_addr *)*ap; -- clp->m_naddr = i; -- } -+ if (htype == MCL_FQDN && clp->m_naddr == 0) -+ init_addrlist(clp, hp); - - if (hp) - free (hp); -@@ -163,15 +172,7 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) - return; - } - -- if (hp) { -- char **ap = hp->h_addr_list; -- int i; -- -- for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) { -- clp->m_addrlist[i] = *(struct in_addr *)*ap; -- } -- clp->m_naddr = i; -- } -+ init_addrlist(clp, hp); - } - - void -------------------------------------------------------------------------------- -libexport-a-fix-whitespace-dam -------------------------------------------------------------------------------- -libexport.a: Fix whitespace damage in support/export/export.c - -From: Chuck Lever - -Clean up whitespace damage introduced by commit 4cacc965. - -Signed-off-by: Chuck Lever ---- - - support/export/export.c | 11 ++++++----- - 1 files changed, 6 insertions(+), 5 deletions(-) - - -diff --git a/support/export/export.c b/support/export/export.c -index f5846d0..f03d7d1 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -124,6 +124,7 @@ export_dup(nfs_export *exp, struct hostent *hp) - - return new; - } -+ - /* - * Add export entry to hash table - */ -@@ -275,11 +276,11 @@ export_freeall(void) - xfree(exp->m_export.e_hostname); - xfree(exp); - } -- for(j = 0; j < HASH_TABLE_SIZE; j++) { -- exportlist[i].entries[j].p_first = NULL; -- exportlist[i].entries[j].p_last = NULL; -- } -- exportlist[i].p_head = NULL; -+ for (j = 0; j < HASH_TABLE_SIZE; j++) { -+ exportlist[i].entries[j].p_first = NULL; -+ exportlist[i].entries[j].p_last = NULL; -+ } -+ exportlist[i].p_head = NULL; - } - client_freeall(); - } -------------------------------------------------------------------------------- -libexport-a-e_fslocdata-should -------------------------------------------------------------------------------- -libexport.a: e_fslocdata should be freed with free(3) - -From: Chuck Lever - -Clean up: Since e_fslocdata is allocated with strdup(3), and not -xstrdup(), it should be freed with free(3), and not xfree(). - -Signed-off-by: Chuck Lever ---- - - support/export/export.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - - -diff --git a/support/export/export.c b/support/export/export.c -index f03d7d1..46045ae 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -272,7 +272,7 @@ export_freeall(void) - if (exp->m_export.e_mountpoint) - free(exp->m_export.e_mountpoint); - if (exp->m_export.e_fslocdata) -- xfree(exp->m_export.e_fslocdata); -+ free(exp->m_export.e_fslocdata); - xfree(exp->m_export.e_hostname); - xfree(exp); - } -------------------------------------------------------------------------------- -libexport-a-add-export_free -------------------------------------------------------------------------------- -libexport.a: Add export_free() - -From: Chuck Lever - -Clean up: Introduce a helper to free nfs_export records. - -Signed-off-by: Chuck Lever ---- - - support/export/export.c | 14 ++++++++++++-- - 1 files changed, 12 insertions(+), 2 deletions(-) - - -diff --git a/support/export/export.c b/support/export/export.c -index 46045ae..aae1995 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -28,6 +28,13 @@ static int export_check(nfs_export *, struct hostent *, char *); - static nfs_export * - export_allowed_internal(struct hostent *hp, char *path); - -+static void -+export_free(nfs_export *exp) -+{ -+ xfree(exp->m_export.e_hostname); -+ xfree(exp); -+} -+ - int - export_read(char *fname) - { -@@ -256,6 +263,10 @@ export_check(nfs_export *exp, struct hostent *hp, char *path) - return client_check(exp->m_client, hp); - } - -+/** -+ * export_freeall - deallocate all nfs_export records -+ * -+ */ - void - export_freeall(void) - { -@@ -273,8 +284,7 @@ export_freeall(void) - free(exp->m_export.e_mountpoint); - if (exp->m_export.e_fslocdata) - free(exp->m_export.e_fslocdata); -- xfree(exp->m_export.e_hostname); -- xfree(exp); -+ export_free(exp); - } - for (j = 0; j < HASH_TABLE_SIZE; j++) { - exportlist[i].entries[j].p_first = NULL; -------------------------------------------------------------------------------- -libexport-a-export_find-should -------------------------------------------------------------------------------- -libexport.a: export_find() should handle address parsing errors - -From: Chuck Lever - -Either a failed memory allocation or an address mask parsing error can -cause client_init(), and therefore client_dup(), to make our process -exit suddenly. - -Since export_find() can return NULL in some cases, it can handle NULL -returns from its subroutines if an address parsing error occurs, or if -memory is exhausted. Allow for client_dup() to return NULL instead of -exiting sideways. - -Signed-off-by: Chuck Lever ---- - - support/export/export.c | 19 +++++++++++++++---- - 1 files changed, 15 insertions(+), 4 deletions(-) - - -diff --git a/support/export/export.c b/support/export/export.c -index aae1995..b64933c 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -104,10 +104,17 @@ export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep) - exp->m_client = clp; - } - --/* -- * Duplicate exports data. The in-core export struct retains the -- * original hostname from /etc/exports, while the in-core client struct -- * gets the newly found FQDN. -+/** -+ * export_dup - Duplicate an export record -+ * @exp: pointer to export record to duplicate -+ * @hp: pointer to host info to plant in the new client record -+ * -+ * The in-core export struct retains the original hostname from -+ * /etc/exports, while the in-core client struct gets the newly -+ * found FQDN. -+ * -+ * Returns a freshly instantiated export record, or NULL if -+ * a problem occurred. - */ - nfs_export * - export_dup(nfs_export *exp, struct hostent *hp) -@@ -121,6 +128,10 @@ export_dup(nfs_export *exp, struct hostent *hp) - if (exp->m_export.e_hostname) - new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname); - clp = client_dup(exp->m_client, hp); -+ if (!clp) { -+ export_free(new); -+ return NULL; -+ } - new->m_client = clp; - new->m_mayexport = exp->m_mayexport; - new->m_exported = 0; -------------------------------------------------------------------------------- -libexport-a-add-client_free -------------------------------------------------------------------------------- -libexport.a: Add client_free() - -From: Chuck Lever - -Clean up: Introduce a helper to free nfs_client records. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 10 ++++++++-- - 1 files changed, 8 insertions(+), 2 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 6b76e83..bfe5c9e 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -51,6 +51,13 @@ init_addrlist(nfs_client *clp, const struct hostent *hp) - clp->m_naddr = i; - } - -+static void -+client_free(nfs_client *clp) -+{ -+ xfree(clp->m_hostname); -+ xfree(clp); -+} -+ - /* if canonical is set, then we *know* this is already a canonical name - * so hostname lookup is avoided. - * This is used when reading /proc/fs/nfs/exports -@@ -199,8 +206,7 @@ client_freeall(void) - head = clientlist + i; - while (*head) { - *head = (clp = *head)->m_next; -- xfree(clp->m_hostname); -- xfree(clp); -+ client_free(clp); - } - } - } -------------------------------------------------------------------------------- -libexport-a-allow-client_init- -------------------------------------------------------------------------------- -libexport.a: Allow client_init() to fail instead of exit - -From: Chuck Lever - -client_init()'s current callers can now deal correctly with a failure. -Get rid of code that can cause our process to exit in client_init(), -if address mask parsing or memory allocation fails. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 24 +++++++++++++++++------- - 1 files changed, 17 insertions(+), 7 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index bfe5c9e..36561b8 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -30,7 +30,7 @@ extern int innetgr(char *netgr, char *host, char *, char *); - #endif - - static char *add_name(char *old, char *add); --static void client_init(nfs_client *clp, const char *hname, -+static int client_init(nfs_client *clp, const char *hname, - struct hostent *hp); - - nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; -@@ -114,13 +114,18 @@ client_lookup(char *hname, int canonical) - clp = (nfs_client *) xmalloc(sizeof(*clp)); - memset(clp, 0, sizeof(*clp)); - clp->m_type = htype; -- client_init(clp, hname, NULL); -+ if (!client_init(clp, hname, NULL)) { -+ client_free(clp); -+ clp = NULL; -+ goto out; -+ } - client_add(clp); - } - - if (htype == MCL_FQDN && clp->m_naddr == 0) - init_addrlist(clp, hp); - -+out: - if (hp) - free (hp); - -@@ -137,12 +142,15 @@ client_dup(nfs_client *clp, struct hostent *hp) - new->m_type = MCL_FQDN; - new->m_hostname = NULL; - -- client_init(new, (char *) hp->h_name, hp); -+ if (!client_init(new, hp->h_name, hp)) { -+ client_free(new); -+ return NULL; -+ } - client_add(new); - return new; - } - --static void -+static int - client_init(nfs_client *clp, const char *hname, struct hostent *hp) - { - xfree(clp->m_hostname); -@@ -171,15 +179,17 @@ client_init(nfs_client *clp, const char *hname, struct hostent *hp) - htonl ((uint32_t) ~0 << (32 - netmask)); - } - else { -- xlog(L_FATAL, "invalid netmask `%s' for %s", -- cp + 1, clp->m_hostname); -+ xlog(L_ERROR, "invalid netmask `%s' for %s", -+ cp + 1, clp->m_hostname); -+ return 0; - } - } - *cp = '/'; -- return; -+ return 1; - } - - init_addrlist(clp, hp); -+ return 1; - } - - void -------------------------------------------------------------------------------- -libexport-a-allow-m_hostname-a -------------------------------------------------------------------------------- -libexport.a: Allow m_hostname allocation to fail instead of exit - -From: Chuck Lever - -Replace xstrdup() with strdup(3) in client_init, to prevent the -process from exiting if the memory allocation fails. - -Since I am replacing xstrdup(), I also took the opportunity to -simplify the m_hostname allocation logic. Every caller passes a NULL -m_hostname field, so there is no need for the extra free(3) at the top -of the function. In addition, every caller passes an appropriate -hostname string in @hname, so there's no need to decide based on the -value of @hp which string to copy. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 11 ++++------- - 1 files changed, 4 insertions(+), 7 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 36561b8..56854f2 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -54,7 +54,7 @@ init_addrlist(nfs_client *clp, const struct hostent *hp) - static void - client_free(nfs_client *clp) - { -- xfree(clp->m_hostname); -+ free(clp->m_hostname); - xfree(clp); - } - -@@ -140,7 +140,6 @@ client_dup(nfs_client *clp, struct hostent *hp) - new = (nfs_client *) xmalloc(sizeof(*new)); - memcpy(new, clp, sizeof(*new)); - new->m_type = MCL_FQDN; -- new->m_hostname = NULL; - - if (!client_init(new, hp->h_name, hp)) { - client_free(new); -@@ -153,11 +152,9 @@ client_dup(nfs_client *clp, struct hostent *hp) - static int - client_init(nfs_client *clp, const char *hname, struct hostent *hp) - { -- xfree(clp->m_hostname); -- if (hp) -- clp->m_hostname = xstrdup(hp->h_name); -- else -- clp->m_hostname = xstrdup(hname); -+ clp->m_hostname = strdup(hname); -+ if (!clp->m_hostname) -+ return 0; - - clp->m_exported = 0; - clp->m_naddr = 0; -------------------------------------------------------------------------------- -libexport-a-allow-malloc-3-fai -------------------------------------------------------------------------------- -libexport.a: Allow malloc(3) failures in client_lookup() and friends - -From: Chuck Lever - -Use malloc(3) instead of xmalloc() in client_lookup() and -client_dup(), ensuring that a failed memory allocation here doesn't -cause our process to exit suddenly. - -Allocation of nfs_client records and the m_hostname string are now -consistently handled with malloc(3), calloc(3), strdup(3), and -free(3). - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 13 ++++++++----- - 1 files changed, 8 insertions(+), 5 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 56854f2..fb0deac 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -17,7 +17,7 @@ - #include - #include - #include --#include "xmalloc.h" -+ - #include "misc.h" - #include "nfslib.h" - #include "exportfs.h" -@@ -55,7 +55,7 @@ static void - client_free(nfs_client *clp) - { - free(clp->m_hostname); -- xfree(clp); -+ free(clp); - } - - /* if canonical is set, then we *know* this is already a canonical name -@@ -111,8 +111,9 @@ client_lookup(char *hname, int canonical) - } - - if (!clp) { -- clp = (nfs_client *) xmalloc(sizeof(*clp)); -- memset(clp, 0, sizeof(*clp)); -+ clp = calloc(1, sizeof(*clp)); -+ if (!clp) -+ goto out; - clp->m_type = htype; - if (!client_init(clp, hname, NULL)) { - client_free(clp); -@@ -137,7 +138,9 @@ client_dup(nfs_client *clp, struct hostent *hp) - { - nfs_client *new; - -- new = (nfs_client *) xmalloc(sizeof(*new)); -+ new = (nfs_client *)malloc(sizeof(*new)); -+ if (!new) -+ return NULL; - memcpy(new, clp, sizeof(*new)); - new->m_type = MCL_FQDN; - -------------------------------------------------------------------------------- -libexport-a-refactor-client_in -------------------------------------------------------------------------------- -libexport.a: Refactor client_init() - -From: Chuck Lever - -Clean up: Move subnet hostname parsing logic out of client_init() to -make it simpler to introduce IPv6 support. - -Make client_init() a helper, since it's already static. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 97 +++++++++++++++++++++++++++-------------------- - 1 files changed, 55 insertions(+), 42 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index fb0deac..725730e 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -30,8 +30,6 @@ extern int innetgr(char *netgr, char *host, char *, char *); - #endif - - static char *add_name(char *old, char *add); --static int client_init(nfs_client *clp, const char *hname, -- struct hostent *hp); - - nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; - -@@ -58,6 +56,61 @@ client_free(nfs_client *clp) - free(clp); - } - -+static int -+init_netmask(nfs_client *clp, const char *slash) -+{ -+ if (strchr(slash + 1, '.')) { -+ clp->m_addrlist[1].s_addr = inet_addr(slash + 1); -+ } else { -+ int prefixlen = atoi(slash + 1); -+ if (0 < prefixlen && prefixlen <= 32) -+ clp->m_addrlist[1].s_addr = -+ htonl((uint32_t)~0 << (32 - prefixlen)); -+ else -+ goto out_badprefix; -+ } -+ -+ return 1; -+ -+out_badprefix: -+ xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname); -+ return 0; -+} -+ -+static int -+init_subnetwork(nfs_client *clp) -+{ -+ static char slash32[] = "/32"; -+ char *cp; -+ -+ cp = strchr(clp->m_hostname, '/'); -+ if (!cp) -+ cp = slash32; -+ -+ *cp = '\0'; -+ clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname); -+ *cp = '/'; -+ -+ return init_netmask(clp, cp); -+} -+ -+static int -+client_init(nfs_client *clp, const char *hname, const struct hostent *hp) -+{ -+ clp->m_hostname = strdup(hname); -+ if (!clp->m_hostname) -+ return 0; -+ -+ clp->m_exported = 0; -+ clp->m_naddr = 0; -+ -+ if (clp->m_type == MCL_SUBNETWORK) -+ return init_subnetwork(clp); -+ -+ init_addrlist(clp, hp); -+ return 1; -+} -+ - /* if canonical is set, then we *know* this is already a canonical name - * so hostname lookup is avoided. - * This is used when reading /proc/fs/nfs/exports -@@ -152,46 +205,6 @@ client_dup(nfs_client *clp, struct hostent *hp) - return new; - } - --static int --client_init(nfs_client *clp, const char *hname, struct hostent *hp) --{ -- clp->m_hostname = strdup(hname); -- if (!clp->m_hostname) -- return 0; -- -- clp->m_exported = 0; -- clp->m_naddr = 0; -- -- if (clp->m_type == MCL_SUBNETWORK) { -- char *cp = strchr(clp->m_hostname, '/'); -- static char slash32[] = "/32"; -- -- if(!cp) cp = slash32; -- *cp = '\0'; -- clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname); -- if (strchr(cp + 1, '.')) { -- clp->m_addrlist[1].s_addr = inet_addr(cp+1); -- } -- else { -- int netmask = atoi(cp + 1); -- if (0 < netmask && netmask <= 32) { -- clp->m_addrlist[1].s_addr = -- htonl ((uint32_t) ~0 << (32 - netmask)); -- } -- else { -- xlog(L_ERROR, "invalid netmask `%s' for %s", -- cp + 1, clp->m_hostname); -- return 0; -- } -- } -- *cp = '/'; -- return 1; -- } -- -- init_addrlist(clp, hp); -- return 1; --} -- - void - client_add(nfs_client *clp) - { -------------------------------------------------------------------------------- -libexport-a-clean-up-client_ad -------------------------------------------------------------------------------- -libexport.a: Clean up client_add() - -From: Chuck Lever - -Clean up: client_add()'s current callers never set unknown m_type -values, so the m_type check is unnecessary. Remove another site where -client_lookup() or client_dup() could exit sideways. - -All of client_add()'s callers are in the same source file where it is -defined, so make it a static helper function. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 26 ++++++++++++-------------- - support/include/exportfs.h | 1 - - 2 files changed, 12 insertions(+), 15 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 725730e..3c80b5b 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -111,6 +111,18 @@ client_init(nfs_client *clp, const char *hname, const struct hostent *hp) - return 1; - } - -+static void -+client_add(nfs_client *clp) -+{ -+ nfs_client **cpp; -+ -+ cpp = &clientlist[clp->m_type]; -+ while (*cpp) -+ cpp = &((*cpp)->m_next); -+ clp->m_next = NULL; -+ *cpp = clp; -+} -+ - /* if canonical is set, then we *know* this is already a canonical name - * so hostname lookup is avoided. - * This is used when reading /proc/fs/nfs/exports -@@ -206,20 +218,6 @@ client_dup(nfs_client *clp, struct hostent *hp) - } - - void --client_add(nfs_client *clp) --{ -- nfs_client **cpp; -- -- if (clp->m_type < 0 || clp->m_type >= MCL_MAXTYPES) -- xlog(L_FATAL, "unknown client type in client_add"); -- cpp = clientlist + clp->m_type; -- while (*cpp) -- cpp = &((*cpp)->m_next); -- clp->m_next = NULL; -- *cpp = clp; --} -- --void - client_freeall(void) - { - nfs_client *clp, **head; -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index fa6b47b..36b7935 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -79,7 +79,6 @@ extern exp_hash_table exportlist[MCL_MAXTYPES]; - extern nfs_client * clientlist[MCL_MAXTYPES]; - - nfs_client * client_lookup(char *hname, int canonical); --void client_add(nfs_client *); - nfs_client * client_dup(nfs_client *, struct hostent *); - int client_gettype(char *hname); - int client_check(nfs_client *, struct hostent *); -------------------------------------------------------------------------------- -mountd-exportfs-make-m_addrlis -------------------------------------------------------------------------------- -mountd/exportfs: Make m_addrlist field a sockaddr_storage - -From: Chuck Lever - -To store non-AF_INET addresses in the nfs_client structure, we need to -use sockaddr_storage (or at least sockaddr_in6) instead of in_addr for -the m_addrlist field. Add a few helper functions to handle type -casting and array indexing for us. - -We could treat the nfs_client address list as if all the addresses -in the list were the same family. This might work for MCL_SUBNETWORK -type nfs_clients. However, during the transition to IPv6, most hosts -will have at least one IPv4 and one IPv6 address. For MCL_FQDN, I -think we need to have the ability to store addresses from both -families in one nfs_client. - -Additionally, IPv6 scope IDs are not part of struct sin6_addr. To -support link-local IPv6 addresses, the scope ID must be stored. - -Thus, each slot in the address list needs to be a full socket address. - -A "struct sockaddr_storage" is 130 bytes. This increases the size of -the nfs_client data structure significantly. We could use -sockaddr_in6 instead, if size matters. My girlfriend tells me it -doesn't. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 38 +++++++++++++++++++++++++++++--------- - support/export/nfsctl.c | 17 +++++++++++++---- - support/include/exportfs.h | 40 +++++++++++++++++++++++++++++++++++++++- - utils/mountd/auth.c | 2 +- - utils/mountd/cache.c | 3 ++- - 5 files changed, 84 insertions(+), 16 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 3c80b5b..f47f972 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -37,6 +37,9 @@ nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; - static void - init_addrlist(nfs_client *clp, const struct hostent *hp) - { -+ struct sockaddr_in sin = { -+ .sin_family = AF_INET, -+ }; - char **ap; - int i; - -@@ -44,8 +47,10 @@ init_addrlist(nfs_client *clp, const struct hostent *hp) - return; - - ap = hp->h_addr_list; -- for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) -- clp->m_addrlist[i] = *(struct in_addr *)*ap; -+ for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) { -+ sin.sin_addr = *(struct in_addr *)*ap; -+ set_addrlist_in(clp, i, &sin); -+ } - clp->m_naddr = i; - } - -@@ -59,17 +64,22 @@ client_free(nfs_client *clp) - static int - init_netmask(nfs_client *clp, const char *slash) - { -+ struct sockaddr_in sin = { -+ .sin_family = AF_INET, -+ }; -+ - if (strchr(slash + 1, '.')) { -- clp->m_addrlist[1].s_addr = inet_addr(slash + 1); -+ sin.sin_addr.s_addr = inet_addr(slash + 1); - } else { - int prefixlen = atoi(slash + 1); - if (0 < prefixlen && prefixlen <= 32) -- clp->m_addrlist[1].s_addr = -+ sin.sin_addr.s_addr = - htonl((uint32_t)~0 << (32 - prefixlen)); - else - goto out_badprefix; - } - -+ set_addrlist_in(clp, 1, &sin); - return 1; - - out_badprefix: -@@ -80,6 +90,9 @@ out_badprefix: - static int - init_subnetwork(nfs_client *clp) - { -+ struct sockaddr_in sin = { -+ .sin_family = AF_INET, -+ }; - static char slash32[] = "/32"; - char *cp; - -@@ -88,7 +101,8 @@ init_subnetwork(nfs_client *clp) - cp = slash32; - - *cp = '\0'; -- clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname); -+ sin.sin_addr.s_addr = inet_addr(clp->m_hostname); -+ set_addrlist_in(clp, 0, &sin); - *cp = '/'; - - return init_netmask(clp, cp); -@@ -381,6 +395,7 @@ add_name(char *old, char *add) - static int - check_fqdn(const nfs_client *clp, const struct hostent *hp) - { -+ struct sockaddr_in *sin; - struct in_addr addr; - char **ap; - int i; -@@ -388,9 +403,11 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp) - for (ap = hp->h_addr_list; *ap; ap++) { - addr = *(struct in_addr *)*ap; - -- for (i = 0; i < clp->m_naddr; i++) -- if (clp->m_addrlist[i].s_addr == addr.s_addr) -+ for (i = 0; i < clp->m_naddr; i++) { -+ sin = get_addrlist_in(clp, i); -+ if (sin->sin_addr.s_addr == addr.s_addr) - return 1; -+ } - } - return 0; - } -@@ -403,14 +420,17 @@ check_fqdn(const nfs_client *clp, const struct hostent *hp) - static int - check_subnetwork(const nfs_client *clp, const struct hostent *hp) - { -+ struct sockaddr_in *address, *mask; - struct in_addr addr; - char **ap; - - for (ap = hp->h_addr_list; *ap; ap++) { -+ address = get_addrlist_in(clp, 0); -+ mask = get_addrlist_in(clp, 1); - addr = *(struct in_addr *)*ap; - -- if (!((clp->m_addrlist[0].s_addr ^ addr.s_addr) & -- clp->m_addrlist[1].s_addr)) -+ if (!((address->sin_addr.s_addr ^ addr.s_addr) & -+ mask->sin_addr.s_addr)) - return 1; - } - return 0; -diff --git a/support/export/nfsctl.c b/support/export/nfsctl.c -index e2877b9..ae357c7 100644 ---- a/support/export/nfsctl.c -+++ b/support/export/nfsctl.c -@@ -66,7 +66,7 @@ str_tolower(char *s) - static int - cltsetup(struct nfsctl_client *cltarg, nfs_client *clp) - { -- int i; -+ int i, j; - - if (clp->m_type != MCL_FQDN) { - xlog(L_ERROR, "internal: can't export non-FQDN host"); -@@ -76,10 +76,19 @@ cltsetup(struct nfsctl_client *cltarg, nfs_client *clp) - strncpy(cltarg->cl_ident, clp->m_hostname, - sizeof (cltarg->cl_ident) - 1); - str_tolower(cltarg->cl_ident); -- cltarg->cl_naddr = clp->m_naddr; -- for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++) -- cltarg->cl_addrlist[i] = clp->m_addrlist[i]; - -+ j = 0; -+ for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++) { -+ struct sockaddr_in *sin = get_addrlist_in(clp, i); -+ if (sin->sin_family == AF_INET) -+ cltarg->cl_addrlist[j++] = sin->sin_addr; -+ } -+ if (j == 0) { -+ xlog(L_ERROR, "internal: no supported addresses in nfs_client"); -+ return 0; -+ } -+ -+ cltarg->cl_naddr = j; - return 1; - } - -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 36b7935..1b3c942 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -46,10 +46,48 @@ typedef struct mclient { - char * m_hostname; - int m_type; - int m_naddr; -- struct in_addr m_addrlist[NFSCLNT_ADDRMAX]; -+ struct sockaddr_storage m_addrlist[NFSCLNT_ADDRMAX]; - int m_exported; /* exported to nfsd */ - } nfs_client; - -+static inline struct sockaddr * -+get_addrlist(const nfs_client *clp, const int i) -+{ -+ return (struct sockaddr *)&clp->m_addrlist[i]; -+} -+ -+static inline struct sockaddr_in * -+get_addrlist_in(const nfs_client *clp, const int i) -+{ -+ return (struct sockaddr_in *)get_addrlist(clp, i); -+} -+ -+static inline struct sockaddr_in6 * -+get_addrlist_in6(const nfs_client *clp, const int i) -+{ -+ return (struct sockaddr_in6 *)get_addrlist(clp, i); -+} -+ -+static inline void -+set_addrlist(nfs_client *clp, const int i, -+ const struct sockaddr *sap, const socklen_t salen) -+{ -+ if (salen <= sizeof(clp->m_addrlist[i])) -+ memcpy(&clp->m_addrlist[i], sap, salen); -+} -+ -+static inline void -+set_addrlist_in(nfs_client *clp, const int i, const struct sockaddr_in *sin) -+{ -+ set_addrlist(clp, i, (const struct sockaddr *)sin, sizeof(*sin)); -+} -+ -+static inline void -+set_addrlist_in6(nfs_client *clp, const int i, const struct sockaddr_in6 *sin6) -+{ -+ set_addrlist(clp, i, (const struct sockaddr *)sin6, sizeof(*sin6)); -+} -+ - typedef struct mexport { - struct mexport * m_next; - struct mclient * m_client; -diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c -index 388dbb3..db7f109 100644 ---- a/utils/mountd/auth.c -+++ b/utils/mountd/auth.c -@@ -141,7 +141,7 @@ auth_authenticate_internal(char *what, struct sockaddr_in *caller, - if (my_client.m_hostname == NULL) - return NULL; - my_client.m_naddr = 1; -- my_client.m_addrlist[0] = caller->sin_addr; -+ set_addrlist_in(&my_client, 0, caller); - my_exp.m_client = &my_client; - - exp = NULL; -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index 92cc87f..e54c4c6 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -864,6 +864,7 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path) - - int cache_export(nfs_export *exp, char *path) - { -+ struct sockaddr_in *sin = get_addrlist_in(exp->m_client, 0); - int err; - FILE *f; - -@@ -872,7 +873,7 @@ int cache_export(nfs_export *exp, char *path) - return -1; - - qword_print(f, "nfsd"); -- qword_print(f, inet_ntoa(exp->m_client->m_addrlist[0])); -+ qword_print(f, inet_ntoa(sin->sin_addr)); - qword_printint(f, time(0)+30*60); - qword_print(f, exp->m_client->m_hostname); - err = qword_eol(f); -------------------------------------------------------------------------------- -libexport-a-add-helpers-to-man -------------------------------------------------------------------------------- -libexport.a: Add helpers to manage DNS lookups - -From: Chuck Lever - -Introduce DNS query helpers based on getaddrinfo(3) and -getnameinfo(3). These will be used to replace the existing -hostent-based helpers. - -Put some of these new helpers to immediate use, where convenient. - -I've added forward declarations for these new functions in exportfs.h -since they are part of libexport.a, rather than misc.h, where the -hostent-based forward declarations are currently. - -Signed-off-by: Chuck Lever ---- - - support/export/hostname.c | 284 ++++++++++++++++++++++++++++++++++++++++++++ - support/include/exportfs.h | 7 + - utils/exportfs/exportfs.c | 11 +- - utils/mountd/cache.c | 3 - utils/mountd/rmtab.c | 19 +-- - 5 files changed, 306 insertions(+), 18 deletions(-) - - -diff --git a/support/export/hostname.c b/support/export/hostname.c -index 8a23a89..3cd1131 100644 ---- a/support/export/hostname.c -+++ b/support/export/hostname.c -@@ -26,6 +26,13 @@ - #include "misc.h" - #endif - -+#include "exportfs.h" -+#include "compaddr.h" -+ -+#ifndef HAVE_DECL_AI_ADDRCONFIG -+#define AI_ADDRCONFIG 0 -+#endif -+ - #define ALIGNMENT sizeof (char *) - - static int -@@ -158,6 +165,283 @@ hostent_dup (struct hostent *hp) - return cp; - } - -+#ifdef HAVE_GETNAMEINFO -+static socklen_t -+sockaddr_size(const struct sockaddr *sap) -+{ -+ if (sap->sa_family != AF_INET) -+ return 0; -+ return sizeof(struct sockaddr_in); -+} -+#endif -+ -+/** -+ * host_ntop - generate presentation address given a sockaddr -+ * @sap: pointer to socket address -+ * -+ * Returns a pointer to a static character buffer containing -+ * a presentation address. -+ */ -+#ifdef HAVE_GETNAMEINFO -+char * -+host_ntop(const struct sockaddr *sap) -+{ -+ static char buf[NI_MAXHOST]; -+ socklen_t salen = sockaddr_size(sap); -+ -+ if (salen == 0) -+ return strncpy(buf, "unknown family", sizeof(buf)); -+ -+ if (!getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, -+ NI_NUMERICHOST)) -+ return buf; -+ -+ return strncpy(buf, "bad address", sizeof(buf)); -+} -+#else /* !HAVE_GETNAMEINFO */ -+char * -+host_ntop(const struct sockaddr *sap) -+{ -+ const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; -+ static char buf[INET_ADDRSTRLEN]; -+ -+ if (sap->sa_family != AF_INET) -+ return strncpy(buf, "unknown family", sizeof(buf)); -+ -+ if (inet_ntop(AF_INET, &sin->sin_addr.s_addr, buf, sizeof(buf))) -+ return buf; -+ -+ return strncpy(buf, "bad address", sizeof(buf)); -+} -+#endif /* !HAVE_GETNAMEINFO */ -+ -+/** -+ * host_pton - return addrinfo for a given presentation address -+ * @paddr: pointer to a '\0'-terminated ASCII string containing an -+ * IP presentation address -+ * -+ * Returns address info structure, or NULL if an error occurs. Caller -+ * must free the returned structure with freeaddrinfo(3). -+ */ -+struct addrinfo * -+host_pton(const char *paddr) -+{ -+ struct addrinfo *ai, hints = { -+ .ai_protocol = IPPROTO_UDP, /* don't return duplicates */ -+ .ai_flags = AI_NUMERICHOST, -+ }; -+ struct sockaddr_in sin; -+ int error; -+ -+ /* -+ * getaddrinfo(3) recognizes incomplete addresses like "10.4" -+ * as valid AF_INET addresses. It also accepts presentation -+ * 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. -+ */ -+ if (!inet_pton(AF_INET, paddr, &sin.sin_addr)) -+ return NULL; -+ -+ error = getaddrinfo(paddr, NULL, &hints, &ai); -+ if (error) { -+ xlog(D_GENERAL, "%s: failed to convert %s: %s", -+ __func__, paddr, gai_strerror(error)); -+ return NULL; -+ } -+ -+ return ai; -+} -+ -+/** -+ * host_addrinfo - return addrinfo for a given hostname -+ * @hostname: pointer to a '\0'-terminated ASCII string containing a hostname -+ * -+ * Returns address info structure with ai_canonname filled in, or NULL -+ * if no information is available for @hostname. Caller must free the -+ * returned structure with freeaddrinfo(3). -+ */ -+struct addrinfo * -+host_addrinfo(const char *hostname) -+{ -+ struct addrinfo hints = { -+ .ai_family = AF_INET, -+ .ai_protocol = IPPROTO_UDP, /* don't return duplicates */ -+ .ai_flags = AI_ADDRCONFIG | AI_CANONNAME, -+ }; -+ struct addrinfo *ai; -+ int error; -+ -+ error = getaddrinfo(hostname, NULL, &hints, &ai); -+ if (error) { -+ xlog(D_GENERAL, "%s: failed to resolve %s: %s", -+ __func__, hostname, gai_strerror(error)); -+ return NULL; -+ } -+ -+ return ai; -+} -+ -+/** -+ * host_canonname - return canonical hostname bound to an address -+ * @sap: pointer to socket address to look up -+ * -+ * Discover the canonical hostname associated with the given socket -+ * address. The host's reverse mapping is verified in the process. -+ * -+ * Returns a '\0'-terminated ASCII string containing a hostname, or -+ * NULL if no hostname can be found for @sap. Caller must free -+ * the string. -+ */ -+#ifdef HAVE_GETNAMEINFO -+char * -+host_canonname(const struct sockaddr *sap) -+{ -+ char buf[NI_MAXHOST]; -+ socklen_t salen = sockaddr_size(sap); -+ int error; -+ -+ if (salen == 0) { -+ xlog(D_GENERAL, "%s: unsupported address family %d", -+ __func__, sap->sa_family); -+ return NULL; -+ } -+ -+ error = getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, NI_NAMEREQD); -+ if (error) { -+ getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, -+ NI_NUMERICHOST); -+ xlog(D_GENERAL, "%s: failed to resolve %s: %s", -+ __func__, buf, gai_strerror(error)); -+ return NULL; -+ } -+ -+ return strdup(buf); -+} -+#else /* !HAVE_GETNAMEINFO */ -+char * -+host_canonname(const struct sockaddr *sap) -+{ -+ const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; -+ const struct in_addr *addr = &sin->sin_addr; -+ struct hostent *hp; -+ -+ if (sap->sa_family != AF_INET) -+ return NULL; -+ -+ hp = gethostbyaddr(addr, sizeof(addr), AF_INET); -+ if (!hp) -+ return NULL; -+ -+ return strdup(hp->h_name); -+} -+#endif /* !HAVE_GETNAMEINFO */ -+ -+/** -+ * host_reliable_addrinfo - return addrinfo for a given address -+ * @sap: pointer to socket address to look up -+ * -+ * Reverse and forward lookups are performed to ensure the address has -+ * proper forward and reverse mappings. -+ * -+ * Returns address info structure with ai_canonname filled in, or NULL -+ * if no information is available for @sap. Caller must free the returned -+ * structure with freeaddrinfo(3). -+ */ -+struct addrinfo * -+host_reliable_addrinfo(const struct sockaddr *sap) -+{ -+ struct addrinfo *ai; -+ char *hostname; -+ -+ hostname = host_canonname(sap); -+ if (!hostname) -+ return NULL; -+ -+ ai = host_addrinfo(hostname); -+ -+ free(hostname); -+ return ai; -+} -+ -+/** -+ * host_numeric_addrinfo - return addrinfo without doing DNS queries -+ * @sap: pointer to socket address -+ * -+ * Returns address info structure, or NULL if an error occurred. -+ * Caller must free the returned structure with freeaddrinfo(3). -+ */ -+#ifdef HAVE_GETNAMEINFO -+struct addrinfo * -+host_numeric_addrinfo(const struct sockaddr *sap) -+{ -+ char buf[NI_MAXHOST]; -+ struct addrinfo *ai; -+ socklen_t salen = sockaddr_size(sap); -+ int error; -+ -+ if (salen == 0) { -+ xlog(D_GENERAL, "%s: unsupported address family %d", -+ __func__, sap->sa_family); -+ return NULL; -+ } -+ -+ error = getnameinfo(sap, salen, buf, sizeof(buf), NULL, 0, -+ NI_NUMERICHOST); -+ if (error) { -+ xlog(D_GENERAL, "%s: getnameinfo(3) failed: %s", -+ __func__, gai_strerror(error)); -+ return NULL; -+ } -+ -+ ai = host_pton(buf); -+ -+ /* -+ * getaddrinfo(AI_NUMERICHOST) never fills in ai_canonname -+ */ -+ if (ai) { -+ ai->ai_canonname = strdup(buf); -+ if (!ai->ai_canonname) { -+ freeaddrinfo(ai); -+ ai = NULL; -+ } -+ } -+ -+ return ai; -+} -+#else /* !HAVE_GETNAMEINFO */ -+struct addrinfo * -+host_numeric_addrinfo(const struct sockaddr *sap) -+{ -+ const struct sockaddr_in *sin = (const struct sockaddr_in *)sap; -+ const struct in_addr *addr = &sin->sin_addr; -+ char buf[INET_ADDRSTRLEN]; -+ struct addrinfo *ai; -+ -+ if (sap->sa_family != AF_INET) -+ return NULL; -+ -+ if (!inet_ntop(AF_INET, (char *)addr, buf, sizeof(buf))) -+ return NULL; -+ -+ ai = host_pton(buf); -+ -+ /* -+ * getaddrinfo(AI_NUMERICHOST) never fills in ai_canonname -+ */ -+ if (ai) { -+ ai->ai_canonname = strdup(buf); -+ if (!ai->ai_canonname) { -+ freeaddrinfo(ai); -+ ai = NULL; -+ } -+ } -+ -+ return ai; -+} -+#endif /* !HAVE_GETNAMEINFO */ -+ - static int - is_hostname(const char *sp) - { -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 1b3c942..9a51398 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -145,6 +145,13 @@ int xtab_mount_write(void); - int xtab_export_write(void); - void xtab_append(nfs_export *); - -+char * host_ntop(const struct sockaddr *sap); -+struct addrinfo * host_pton(const char *paddr); -+struct addrinfo * host_addrinfo(const char *hostname); -+char * host_canonname(const struct sockaddr *sap); -+struct addrinfo * host_reliable_addrinfo(const struct sockaddr *sap); -+struct addrinfo * host_numeric_addrinfo(const struct sockaddr *sap); -+ - int rmtab_read(void); - - struct nfskey * key_lookup(char *hname); -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index 593a8eb..f1d1c01 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -286,7 +286,7 @@ static void - unexportfs(char *arg, int verbose) - { - nfs_export *exp; -- struct hostent *hp = NULL; -+ struct addrinfo *ai = NULL; - char *path; - char *hname = arg; - int htype; -@@ -301,10 +301,9 @@ unexportfs(char *arg, int verbose) - } - - if ((htype = client_gettype(hname)) == MCL_FQDN) { -- if ((hp = gethostbyname(hname)) != 0) { -- hp = hostent_dup (hp); -- hname = (char *) hp->h_name; -- } -+ ai = host_addrinfo(hname); -+ if (ai) -+ hname = ai->ai_canonname; - } - - for (exp = exportlist[htype].p_head; exp; exp = exp->m_next) { -@@ -340,7 +339,7 @@ unexportfs(char *arg, int verbose) - exp->m_mayexport = 0; - } - -- if (hp) free (hp); -+ freeaddrinfo(ai); - } - - static int can_test(void) -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index e54c4c6..a1191d2 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -864,7 +864,6 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path) - - int cache_export(nfs_export *exp, char *path) - { -- struct sockaddr_in *sin = get_addrlist_in(exp->m_client, 0); - int err; - FILE *f; - -@@ -873,7 +872,7 @@ int cache_export(nfs_export *exp, char *path) - return -1; - - qword_print(f, "nfsd"); -- qword_print(f, inet_ntoa(sin->sin_addr)); -+ qword_print(f, host_ntop(get_addrlist(exp->m_client, 0))); - qword_printint(f, time(0)+30*60); - qword_print(f, exp->m_client->m_hostname); - err = qword_eol(f); -diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c -index c371f8d..3b45d57 100644 ---- a/utils/mountd/rmtab.c -+++ b/utils/mountd/rmtab.c -@@ -132,8 +132,7 @@ mountlist_del(char *hname, const char *path) - void - mountlist_del_all(struct sockaddr_in *sin) - { -- struct in_addr addr = sin->sin_addr; -- struct hostent *hp; -+ char *hostname; - struct rmtabent *rep; - nfs_export *exp; - FILE *fp; -@@ -141,27 +140,27 @@ mountlist_del_all(struct sockaddr_in *sin) - - if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0) - return; -- if (!(hp = gethostbyaddr((char *)&addr, sizeof(addr), AF_INET))) { -- xlog(L_ERROR, "can't get hostname of %s", inet_ntoa(addr)); -+ hostname = host_canonname((struct sockaddr *)sin); -+ if (!hostname) { -+ xlog(L_ERROR, "can't get hostname of %s", -+ host_ntop((struct sockaddr *)sin)); - xfunlock(lockid); - return; - } -- else -- hp = hostent_dup (hp); - - if (!setrmtabent("r")) { - xfunlock(lockid); -- free (hp); -+ free(hostname); - return; - } - if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) { - endrmtabent(); - xfunlock(lockid); -- free (hp); -+ free(hostname); - return; - } - while ((rep = getrmtabent(1, NULL)) != NULL) { -- if (strcmp(rep->r_client, hp->h_name) == 0 && -+ if (strcmp(rep->r_client, hostname) == 0 && - (exp = auth_authenticate("umountall", sin, rep->r_path))) - continue; - fputrmtabent(fp, rep, NULL); -@@ -173,7 +172,7 @@ mountlist_del_all(struct sockaddr_in *sin) - endrmtabent(); /* close & unlink */ - fendrmtabent(fp); - xfunlock(lockid); -- free (hp); -+ free(hostname); - } - - mountlist -------------------------------------------------------------------------------- -mountd-replace-struct-hostent- -------------------------------------------------------------------------------- -mountd: Replace "struct hostent" with "struct addrinfo" - -From: Chuck Lever - -struct hostent can store either IPv4 or IPv6 addresses, but it can't -store both for the same host. Neither can hostent deal with parts of -socket addresses that are outside of the sin{,6}_addr field. - -Replace the use of "struct hostent" everywhere in libexport.a, mountd, -and exportfs with "struct addrinfo". This is a large change, but -there are so many strong dependencies on struct hostent that this -can't be broken into smaller pieces. - -This also means we can get rid of hostent_dup(), since the results of -getaddrinfo(3) are already dynamically allocated. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 256 ++++++++++++++++++++++++-------------------- - support/export/export.c | 46 ++++++-- - support/export/rmtab.c | 46 ++++---- - support/include/exportfs.h | 19 ++- - utils/exportfs/exportfs.c | 39 +++---- - utils/mountd/auth.c | 35 +++--- - utils/mountd/cache.c | 31 ++--- - utils/mountd/mountd.c | 24 ++-- - 8 files changed, 265 insertions(+), 231 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index f47f972..c299299 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -35,21 +35,19 @@ nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; - - - static void --init_addrlist(nfs_client *clp, const struct hostent *hp) -+init_addrlist(nfs_client *clp, const struct addrinfo *ai) - { -- struct sockaddr_in sin = { -- .sin_family = AF_INET, -- }; -- char **ap; - int i; - -- if (!hp) -+ if (!ai) - return; - -- ap = hp->h_addr_list; -- for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) { -- sin.sin_addr = *(struct in_addr *)*ap; -- set_addrlist_in(clp, i, &sin); -+ for (i = 0; i < NFSCLNT_ADDRMAX; i++) { -+ set_addrlist(clp, i, ai->ai_addr, ai->ai_addrlen); -+ -+ ai = ai->ai_next; -+ if (ai == NULL) -+ break; - } - clp->m_naddr = i; - } -@@ -109,7 +107,7 @@ init_subnetwork(nfs_client *clp) - } - - static int --client_init(nfs_client *clp, const char *hname, const struct hostent *hp) -+client_init(nfs_client *clp, const char *hname, const struct addrinfo *ai) - { - clp->m_hostname = strdup(hname); - if (!clp->m_hostname) -@@ -121,7 +119,7 @@ client_init(nfs_client *clp, const char *hname, const struct hostent *hp) - if (clp->m_type == MCL_SUBNETWORK) - return init_subnetwork(clp); - -- init_addrlist(clp, hp); -+ init_addrlist(clp, ai); - return 1; - } - -@@ -146,42 +144,21 @@ client_lookup(char *hname, int canonical) - { - nfs_client *clp = NULL; - int htype; -- struct hostent *hp = NULL; -+ struct addrinfo *ai = NULL; - - htype = client_gettype(hname); - - if (htype == MCL_FQDN && !canonical) { -- struct hostent *hp2; -- hp = gethostbyname(hname); -- if (hp == NULL || hp->h_addrtype != AF_INET) { -- xlog(L_ERROR, "%s has non-inet addr", hname); -- return NULL; -+ ai = host_addrinfo(hname); -+ if (!ai) { -+ xlog(L_ERROR, "Failed to resolve %s", hname); -+ goto out; - } -- /* make sure we have canonical name */ -- hp2 = hostent_dup(hp); -- hp = gethostbyaddr(hp2->h_addr, hp2->h_length, -- hp2->h_addrtype); -- if (hp) { -- hp = hostent_dup(hp); -- /* but now we might not have all addresses... */ -- if (hp2->h_addr_list[1]) { -- struct hostent *hp3 = -- gethostbyname(hp->h_name); -- if (hp3) { -- free(hp); -- hp = hostent_dup(hp3); -- } -- } -- free(hp2); -- } else -- hp = hp2; -- -- hname = (char *) hp->h_name; -+ hname = ai->ai_canonname; - -- for (clp = clientlist[htype]; clp; clp = clp->m_next) { -- if (client_check(clp, hp)) -+ for (clp = clientlist[htype]; clp; clp = clp->m_next) -+ if (client_check(clp, ai)) - break; -- } - } else { - for (clp = clientlist[htype]; clp; clp = clp->m_next) { - if (strcasecmp(hname, clp->m_hostname)==0) -@@ -203,17 +180,24 @@ client_lookup(char *hname, int canonical) - } - - if (htype == MCL_FQDN && clp->m_naddr == 0) -- init_addrlist(clp, hp); -+ init_addrlist(clp, ai); - - out: -- if (hp) -- free (hp); -- -+ freeaddrinfo(ai); - return clp; - } - -+/** -+ * client_dup - create a copy of an nfs_client -+ * @clp: pointer to nfs_client to copy -+ * @ai: pointer to addrinfo used to initialize the new client's addrlist -+ * -+ * Returns a dynamically allocated nfs_client if successful, or -+ * NULL if some problem occurs. Caller must free the returned -+ * nfs_client with free(3). -+ */ - nfs_client * --client_dup(nfs_client *clp, struct hostent *hp) -+client_dup(const nfs_client *clp, const struct addrinfo *ai) - { - nfs_client *new; - -@@ -223,7 +207,7 @@ client_dup(nfs_client *clp, struct hostent *hp) - memcpy(new, clp, sizeof(*new)); - new->m_type = MCL_FQDN; - -- if (!client_init(new, hp->h_name, hp)) { -+ if (!client_init(new, ai->ai_canonname, ai)) { - client_free(new); - return NULL; - } -@@ -247,23 +231,23 @@ client_freeall(void) - } - - /** -- * client_resolve - look up an IPv4 address -- * @addr: IPv4 address to resolve -+ * client_resolve - look up an IP address -+ * @sap: pointer to socket address to resolve - * -- * Returns a dynamically allocated hostent structure, or NULL if -- * some problem occurred. Caller must free the result with free(3). -+ * Returns an addrinfo structure, or NULL if some problem occurred. -+ * Caller must free the result with freeaddrinfo(3). - */ --struct hostent * --client_resolve(struct in_addr addr) -+struct addrinfo * -+client_resolve(const struct sockaddr *sap) - { -- struct hostent *he = NULL; -+ struct addrinfo *ai = NULL; - - if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP]) -- he = get_reliable_hostbyaddr((const char*)&addr, sizeof(addr), AF_INET); -- if (he == NULL) -- he = get_hostent((const char*)&addr, sizeof(addr), AF_INET); -+ ai = host_reliable_addrinfo(sap); -+ if (!ai) -+ ai = host_numeric_addrinfo(sap); - -- return he; -+ return ai; - } - - /** -@@ -275,20 +259,23 @@ client_resolve(struct in_addr addr) - * otherwise 0 is returned. Caller must free @result with free(3). - */ - int --client_resolve_paddr(const char *address, struct hostent **result) -+client_resolve_paddr(const char *address, struct addrinfo **result) - { -- struct in_addr addr; -+ struct addrinfo *ai; - -- if (!inet_aton(address, &addr)) -+ ai = host_pton(address); -+ if (!ai) - return 0; - -- *result = client_resolve(addr); -+ *result = client_resolve(ai->ai_addr); -+ -+ freeaddrinfo(ai); - return 1; - } - - /** - * client_compose - Make a list of cached hostnames that match an IP address -- * @he: pointer to hostent containing IP address information to match -+ * @ai: pointer to addrinfo containing IP address information to match - * - * Gather all known client hostnames that match the IP address, and sort - * the result into a comma-separated list. -@@ -299,7 +286,7 @@ client_resolve_paddr(const char *address, struct hostent **result) - * returned string with free(3). - */ - char * --client_compose(struct hostent *he) -+client_compose(const struct addrinfo *ai) - { - char *name = NULL; - int i; -@@ -307,7 +294,7 @@ client_compose(struct hostent *he) - for (i = 0 ; i < MCL_MAXTYPES; i++) { - nfs_client *clp; - for (clp = clientlist[i]; clp ; clp = clp->m_next) { -- if (!client_check(clp, he)) -+ if (!client_check(clp, ai)) - continue; - name = add_name(name, clp->m_hostname); - } -@@ -327,6 +314,7 @@ int - client_member(char *client, char *name) - { - int l = strlen(name); -+ - while (*client) { - if (strncmp(client, name, l) == 0 && - (client[l] == ',' || client[l] == '\0')) -@@ -387,52 +375,83 @@ add_name(char *old, char *add) - return new; - } - -+static int -+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 int -+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 0; -+} -+ - /* -- * Check each address listed in @hp against each address -+ * Check each address listed in @ai against each address - * stored in @clp. Return 1 if a match is found, otherwise - * zero. - */ - static int --check_fqdn(const nfs_client *clp, const struct hostent *hp) -+check_fqdn(const nfs_client *clp, const struct addrinfo *ai) - { -- struct sockaddr_in *sin; -- struct in_addr addr; -- char **ap; - int i; - -- for (ap = hp->h_addr_list; *ap; ap++) { -- addr = *(struct in_addr *)*ap; -- -- for (i = 0; i < clp->m_naddr; i++) { -- sin = get_addrlist_in(clp, i); -- if (sin->sin_addr.s_addr == addr.s_addr) -+ for (; ai; ai = ai->ai_next) -+ for (i = 0; i < clp->m_naddr; i++) -+ if (addrs_match(ai->ai_addr, get_addrlist(clp, i))) - return 1; -- } -+ -+ return 0; -+} -+ -+static int -+mask_match(const uint32_t a, const uint32_t b, const uint32_t m) -+{ -+ return !((a ^ b) & m); -+} -+ -+static int -+check_subnet_v4(const struct sockaddr_in *address, -+ const struct sockaddr_in *mask, const struct addrinfo *ai) -+{ -+ for (; ai; ai = ai->ai_next) { -+ struct sockaddr_in *sin = (struct sockaddr_in *)ai->ai_addr; -+ -+ if (sin->sin_family != AF_INET) -+ continue; -+ -+ if (mask_match(address->sin_addr.s_addr, -+ sin->sin_addr.s_addr, -+ mask->sin_addr.s_addr)) -+ return 1; - } - return 0; - } - - /* -- * Check each address listed in @hp against the subnetwork or -+ * Check each address listed in @ai against the subnetwork or - * host address stored in @clp. Return 1 if an address in @hp - * matches the host address stored in @clp, otherwise zero. - */ - static int --check_subnetwork(const nfs_client *clp, const struct hostent *hp) -+check_subnetwork(const nfs_client *clp, const struct addrinfo *ai) - { -- struct sockaddr_in *address, *mask; -- struct in_addr addr; -- char **ap; -- -- for (ap = hp->h_addr_list; *ap; ap++) { -- address = get_addrlist_in(clp, 0); -- mask = get_addrlist_in(clp, 1); -- addr = *(struct in_addr *)*ap; -- -- if (!((address->sin_addr.s_addr ^ addr.s_addr) & -- mask->sin_addr.s_addr)) -- return 1; -+ switch (get_addrlist(clp, 0)->sa_family) { -+ case AF_INET: -+ return check_subnet_v4(get_addrlist_in(clp, 0), -+ get_addrlist_in(clp, 1), ai); - } -+ - return 0; - } - -@@ -442,34 +461,35 @@ check_subnetwork(const nfs_client *clp, const struct hostent *hp) - * zero. - */ - static int --check_wildcard(char *cname, const struct hostent *hp) -+check_wildcard(char *cname, char *hname) - { -- char *hname = hp->h_name; -+ struct hostent *hp; - char **ap; - - if (wildmat(hname, cname)) - return 1; - - /* Try matching aliases of this host listed in /etc/hosts or nis[+] */ -- for (ap = hp->h_aliases; *ap; ap++) -- if (wildmat(*ap, cname)) -- return 1; -+ hp = gethostbyname(hname); -+ if (hp) -+ for (ap = hp->h_aliases; *ap; ap++) -+ if (wildmat(*ap, cname)) -+ return 1; - - return 0; - } - - /* -- * Check if @hp's hostname or aliases fall in a given netgroup. -- * Return 1 if @hp represents a host in the netgroup, otherwise zero. -+ * Check if @ai's hostname or aliases fall in a given netgroup. -+ * Return 1 if @ai represents a host in the netgroup, otherwise zero. - */ - #ifdef HAVE_INNETGR - static int --check_netgroup(const char *cname, const struct hostent *hp) -+check_netgroup(const char *cname, char *hname) - { - const char *netgroup = cname + 1; -- char *hname = hp->h_name; -- struct hostent *nhp = NULL; -- struct sockaddr_in addr; -+ struct addrinfo *ai = NULL; -+ struct hostent *hp; - int match, i; - char *dot; - -@@ -479,17 +499,17 @@ check_netgroup(const char *cname, const struct hostent *hp) - return 1; - - /* Try matching aliases of this host listed in /etc/hosts or nis[+] */ -- for (i = 0; hp->h_aliases[i]; i++) { -- if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL)) -- return 1; -- } -+ hp = gethostbyname(hname); -+ if (hp) -+ for (i = 0; hp->h_aliases[i]; i++) -+ if (innetgr(netgroup, hp->h_aliases[i], NULL, NULL)) -+ return 1; - - /* If hname is ip address convert to FQDN */ -- if (inet_aton(hname, &addr.sin_addr) && -- (nhp = gethostbyaddr((const char *)&(addr.sin_addr), -- sizeof(addr.sin_addr), AF_INET))) { -- hname = nhp->h_name; -- if (innetgr(netgroup, hname, NULL, NULL)) -+ ai = host_pton(hname); -+ if (ai) { -+ freeaddrinfo(ai); -+ if (innetgr(cname + 1, hname, NULL, NULL)) - return 1; - } - -@@ -506,7 +526,7 @@ check_netgroup(const char *cname, const struct hostent *hp) - #else /* !HAVE_INNETGR */ - static int - check_netgroup(__attribute__((unused)) const char *cname, -- __attribute__((unused)) const struct hostent *hp) -+ __attribute__((unused)) const char *hname) - { - return 0; - } -@@ -515,23 +535,23 @@ check_netgroup(__attribute__((unused)) const char *cname, - /** - * client_check - check if IP address information matches a cached nfs_client - * @clp: pointer to a cached nfs_client record -- * @hp: pointer to hostent containing host IP information -+ * @ai: pointer to addrinfo to compare it with - * - * Returns 1 if the address information matches the cached nfs_client, - * otherwise zero. - */ - int --client_check(nfs_client *clp, struct hostent *hp) -+client_check(const nfs_client *clp, const struct addrinfo *ai) - { - switch (clp->m_type) { - case MCL_FQDN: -- return check_fqdn(clp, hp); -+ return check_fqdn(clp, ai); - case MCL_SUBNETWORK: -- return check_subnetwork(clp, hp); -+ return check_subnetwork(clp, ai); - case MCL_WILDCARD: -- return check_wildcard(clp->m_hostname, hp); -+ return check_wildcard(clp->m_hostname, ai->ai_canonname); - case MCL_NETGROUP: -- return check_netgroup(clp->m_hostname, hp); -+ return check_netgroup(clp->m_hostname, ai->ai_canonname); - case MCL_ANONYMOUS: - return 1; - case MCL_GSS: -diff --git a/support/export/export.c b/support/export/export.c -index b64933c..fe99f4f 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -24,9 +24,11 @@ static int export_hash(char *); - - static void export_init(nfs_export *exp, nfs_client *clp, - struct exportent *nep); --static int export_check(nfs_export *, struct hostent *, char *); -+static int export_check(const nfs_export *exp, const struct addrinfo *ai, -+ const char *path); - static nfs_export * -- export_allowed_internal(struct hostent *hp, char *path); -+ export_allowed_internal(const struct addrinfo *ai, -+ const char *path); - - static void - export_free(nfs_export *exp) -@@ -116,8 +118,8 @@ export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep) - * Returns a freshly instantiated export record, or NULL if - * a problem occurred. - */ --nfs_export * --export_dup(nfs_export *exp, struct hostent *hp) -+static nfs_export * -+export_dup(nfs_export *exp, const struct addrinfo *ai) - { - nfs_export *new; - nfs_client *clp; -@@ -127,7 +129,7 @@ export_dup(nfs_export *exp, struct hostent *hp) - dupexportent(&new->m_export, &exp->m_export); - if (exp->m_export.e_hostname) - new->m_export.e_hostname = xstrdup(exp->m_export.e_hostname); -- clp = client_dup(exp->m_client, hp); -+ clp = client_dup(exp->m_client, ai); - if (!clp) { - export_free(new); - return NULL; -@@ -174,19 +176,27 @@ export_add(nfs_export *exp) - } - } - -+/** -+ * export_find - find or create a suitable nfs_export for @ai and @path -+ * @ai: pointer to addrinfo for client -+ * @path: '\0'-terminated ASCII string containing export path -+ * -+ * Returns a pointer to nfs_export data matching @ai and @path, -+ * or NULL if an error occurs. -+ */ - nfs_export * --export_find(struct hostent *hp, char *path) -+export_find(const struct addrinfo *ai, const char *path) - { - nfs_export *exp; - int i; - - for (i = 0; i < MCL_MAXTYPES; i++) { - for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { -- if (!export_check(exp, hp, path)) -+ if (!export_check(exp, ai, path)) - continue; - if (exp->m_client->m_type == MCL_FQDN) - return exp; -- return export_dup(exp, hp); -+ return export_dup(exp, ai); - } - } - -@@ -194,7 +204,7 @@ export_find(struct hostent *hp, char *path) - } - - static nfs_export * --export_allowed_internal (struct hostent *hp, char *path) -+export_allowed_internal(const struct addrinfo *ai, const char *path) - { - nfs_export *exp; - int i; -@@ -202,7 +212,7 @@ export_allowed_internal (struct hostent *hp, char *path) - for (i = 0; i < MCL_MAXTYPES; i++) { - for (exp = exportlist[i].p_head; exp; exp = exp->m_next) { - if (!exp->m_mayexport || -- !export_check(exp, hp, path)) -+ !export_check(exp, ai, path)) - continue; - return exp; - } -@@ -211,8 +221,16 @@ export_allowed_internal (struct hostent *hp, char *path) - return NULL; - } - -+/** -+ * export_allowed - determine if this export is allowed -+ * @ai: pointer to addrinfo for client -+ * @path: '\0'-terminated ASCII string containing export path -+ * -+ * Returns a pointer to nfs_export data matching @ai and @path, -+ * or NULL if the export is not allowed. -+ */ - nfs_export * --export_allowed(struct hostent *hp, char *path) -+export_allowed(const struct addrinfo *ai, const char *path) - { - nfs_export *exp; - char epath[MAXPATHLEN+1]; -@@ -225,7 +243,7 @@ export_allowed(struct hostent *hp, char *path) - - /* Try the longest matching exported pathname. */ - while (1) { -- exp = export_allowed_internal (hp, epath); -+ exp = export_allowed_internal(ai, epath); - if (exp) - return exp; - /* We have to treat the root, "/", specially. */ -@@ -266,12 +284,12 @@ export_lookup(char *hname, char *path, int canonical) - } - - static int --export_check(nfs_export *exp, struct hostent *hp, char *path) -+export_check(const nfs_export *exp, const struct addrinfo *ai, const char *path) - { - if (strcmp(path, exp->m_export.e_path)) - return 0; - -- return client_check(exp->m_client, hp); -+ return client_check(exp->m_client, ai); - } - - /** -diff --git a/support/export/rmtab.c b/support/export/rmtab.c -index b49e1aa..ff348bd 100644 ---- a/support/export/rmtab.c -+++ b/support/export/rmtab.c -@@ -27,31 +27,37 @@ rmtab_read(void) - - setrmtabent("r"); - while ((rep = getrmtabent(1, NULL)) != NULL) { -- struct hostent *hp = NULL; -- int htype; -+ int htype; - - htype = client_gettype(rep->r_client); -- if ((htype == MCL_FQDN || htype == MCL_SUBNETWORK) -- && (hp = gethostbyname (rep->r_client)) -- && (hp = hostent_dup (hp), -- exp = export_allowed (hp, rep->r_path))) { -- /* see if the entry already exists, otherwise this was an instantiated -- * wild card, and we must add it -- */ -- nfs_export *exp2 = export_lookup(rep->r_client, -+ if (htype == MCL_FQDN || htype == MCL_SUBNETWORK) { -+ struct addrinfo *ai; -+ -+ ai = host_addrinfo(rep->r_client); -+ if (ai) { -+ /* -+ * See if the entry already exists; otherwise, -+ * this was an instantiated wild card, and we -+ * must add it. -+ */ -+ exp = export_allowed(ai, rep->r_path); -+ if (exp) { -+ nfs_export *exp2 = export_lookup(rep->r_client, - exp->m_export.e_path, 0); -- if (!exp2) { -- struct exportent ee; -- dupexportent(&ee, &exp->m_export); -- ee.e_hostname = rep->r_client; -- exp2 = export_create(&ee, 0); -- exp2->m_changed = exp->m_changed; -+ if (!exp2) { -+ struct exportent ee; -+ dupexportent(&ee, &exp->m_export); -+ ee.e_hostname = rep->r_client; -+ exp2 = export_create(&ee, 0); -+ exp2->m_changed = exp->m_changed; -+ } -+ exp2->m_mayexport = 1; -+ } -+ freeaddrinfo(ai); - } -- free (hp); -- exp2->m_mayexport = 1; -- } else if (hp) /* export_allowed failed */ -- free(hp); -+ } - } -+ - if (errno == EINVAL) { - /* Something goes wrong. We need to fix the rmtab - file. */ -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 9a51398..60185dd 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -117,24 +117,27 @@ extern exp_hash_table exportlist[MCL_MAXTYPES]; - extern nfs_client * clientlist[MCL_MAXTYPES]; - - nfs_client * client_lookup(char *hname, int canonical); --nfs_client * client_dup(nfs_client *, struct hostent *); -+nfs_client * client_dup(const nfs_client *clp, -+ const struct addrinfo *ai); - int client_gettype(char *hname); --int client_check(nfs_client *, struct hostent *); -+int client_check(const nfs_client *clp, -+ const struct addrinfo *ai); - void client_freeall(void); --char * client_compose(struct hostent *he); --struct hostent * client_resolve(struct in_addr addr); -+char * client_compose(const struct addrinfo *ai); -+struct addrinfo * client_resolve(const struct sockaddr *sap); - int client_resolve_paddr(const char *address, -- struct hostent **result); -+ struct addrinfo **result); - int client_member(char *client, char *name); - - int export_read(char *fname); - void export_add(nfs_export *); - void export_reset(nfs_export *); - nfs_export * export_lookup(char *hname, char *path, int caconical); --nfs_export * export_find(struct hostent *, char *path); --nfs_export * export_allowed(struct hostent *, char *path); -+nfs_export * export_find(const struct addrinfo *ai, -+ const char *path); -+nfs_export * export_allowed(const struct addrinfo *ai, -+ const char *path); - nfs_export * export_create(struct exportent *, int canonical); --nfs_export * export_dup(nfs_export *, struct hostent *); - void export_freeall(void); - int export_export(nfs_export *); - int export_unexport(nfs_export *); -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index f1d1c01..1d3e403 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -231,7 +231,7 @@ exportfs(char *arg, char *options, int verbose) - { - struct exportent *eep; - nfs_export *exp; -- struct hostent *hp = NULL; -+ struct addrinfo *ai = NULL; - char *path; - char *hname = arg; - int htype; -@@ -244,32 +244,21 @@ exportfs(char *arg, char *options, int verbose) - return; - } - -- if ((htype = client_gettype(hname)) == MCL_FQDN && -- (hp = gethostbyname(hname)) != NULL) { -- struct hostent *hp2 = hostent_dup (hp); -- hp = gethostbyaddr(hp2->h_addr, hp2->h_length, -- hp2->h_addrtype); -- if (hp) { -- free(hp2); -- hp = hostent_dup(hp); -- } else -- hp = hp2; -- exp = export_find(hp, path); -- hname = hp->h_name; -- } else { -+ if ((htype = client_gettype(hname)) == MCL_FQDN) { -+ ai = host_addrinfo(hname); -+ if (ai) { -+ exp = export_find(ai, path); -+ hname = ai->ai_canonname; -+ } -+ } else - exp = export_lookup(hname, path, 0); -- } - - if (!exp) { - if (!(eep = mkexportent(hname, path, options)) || -- !(exp = export_create(eep, 0))) { -- if (hp) free (hp); -- return; -- } -- } else if (!updateexportent(&exp->m_export, options)) { -- if (hp) free (hp); -- return; -- } -+ !(exp = export_create(eep, 0))) -+ goto out; -+ } else if (!updateexportent(&exp->m_export, options)) -+ goto out; - - if (verbose) - printf("exporting %s:%s\n", exp->m_client->m_hostname, -@@ -279,7 +268,9 @@ exportfs(char *arg, char *options, int verbose) - exp->m_changed = 1; - exp->m_warned = 0; - validate_export(exp); -- if (hp) free (hp); -+ -+out: -+ freeaddrinfo(ai); - } - - static void -diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c -index db7f109..1eb78a3 100644 ---- a/utils/mountd/auth.c -+++ b/utils/mountd/auth.c -@@ -112,8 +112,8 @@ auth_reload() - } - - static nfs_export * --auth_authenticate_internal(char *what, struct sockaddr_in *caller, -- char *path, struct hostent *hp, -+auth_authenticate_internal(struct sockaddr_in *caller, -+ char *path, struct addrinfo *ai, - enum auth_error *error) - { - nfs_export *exp; -@@ -127,7 +127,7 @@ auth_authenticate_internal(char *what, struct sockaddr_in *caller, - my_client.m_hostname = - strdup(inet_ntoa(caller->sin_addr)); - } else { -- n = client_compose(hp); -+ n = client_compose(ai); - *error = unknown_host; - if (!n) - my_client.m_hostname = NULL; -@@ -151,7 +151,7 @@ auth_authenticate_internal(char *what, struct sockaddr_in *caller, - continue; - if (!use_ipaddr && !client_member(my_client.m_hostname, exp->m_client->m_hostname)) - continue; -- if (use_ipaddr && !client_check(exp->m_client, hp)) -+ if (use_ipaddr && !client_check(exp->m_client, ai)) - continue; - break; - } -@@ -163,7 +163,7 @@ auth_authenticate_internal(char *what, struct sockaddr_in *caller, - exp = &my_exp; - - } else { -- if (!(exp = export_find(hp, path))) { -+ if (!(exp = export_find(ai, path))) { - *error = no_entry; - return NULL; - } -@@ -188,7 +188,7 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path) - nfs_export *exp = NULL; - char epath[MAXPATHLEN+1]; - char *p = NULL; -- struct hostent *hp = NULL; -+ struct addrinfo *ai = NULL; - struct in_addr addr = caller->sin_addr; - enum auth_error error = bad_path; - -@@ -202,14 +202,14 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path) - epath[sizeof (epath) - 1] = '\0'; - auth_fixpath(epath); /* strip duplicate '/' etc */ - -- hp = client_resolve(caller->sin_addr); -- if (!hp) -+ ai = client_resolve((struct sockaddr *)caller); -+ if (!ai) - return exp; - - /* Try the longest matching exported pathname. */ - while (1) { -- exp = auth_authenticate_internal(what, caller, epath, -- hp, &error); -+ exp = auth_authenticate_internal(caller, epath, -+ ai, &error); - if (exp || (error != not_exported && error != no_entry)) - break; - /* We have to treat the root, "/", specially. */ -@@ -232,31 +232,30 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path) - - case no_entry: - xlog(L_WARNING, "refused %s request from %s for %s (%s): no export entry", -- what, hp->h_name, path, epath); -+ what, ai->ai_canonname, path, epath); - break; - - case not_exported: - xlog(L_WARNING, "refused %s request from %s for %s (%s): not exported", -- what, hp->h_name, path, epath); -+ what, ai->ai_canonname, path, epath); - break; - - case illegal_port: - xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d", -- what, hp->h_name, path, epath, ntohs(caller->sin_port)); -+ what, ai->ai_canonname, path, epath, ntohs(caller->sin_port)); - break; - - case success: - xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)", -- what, hp->h_name, ntohs(caller->sin_port), path, epath); -+ what, ai->ai_canonname, ntohs(caller->sin_port), path, epath); - break; - default: - xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d", -- what, hp->h_name, ntohs(caller->sin_port), path, epath, error); -+ what, ai->ai_canonname, ntohs(caller->sin_port), -+ path, epath, error); - } - -- if (hp) -- free (hp); -- -+ freeaddrinfo(ai); - return exp; - } - -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index a1191d2..cbe477d 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -66,7 +66,7 @@ void auth_unix_ip(FILE *f) - char class[20]; - char ipaddr[20]; - char *client = NULL; -- struct hostent *he = NULL; -+ struct addrinfo *ai = NULL; - if (readline(fileno(f), &lbuf, &lbuflen) != 1) - return; - -@@ -85,11 +85,12 @@ void auth_unix_ip(FILE *f) - - /* addr is a valid, interesting address, find the domain name... */ - if (!use_ipaddr) { -- if (!client_resolve_paddr(ipaddr, &he)) -+ if (!client_resolve_paddr(ipaddr, &ai)) - return; -- client = client_compose(he); -+ client = client_compose(ai); - } -- -+ freeaddrinfo(ai); -+ - qword_print(f, "nfsd"); - qword_print(f, ipaddr); - qword_printint(f, time(0)+30*60); -@@ -100,8 +101,7 @@ void auth_unix_ip(FILE *f) - qword_eol(f); - xlog(D_CALL, "auth_unix_ip: client %p '%s'", client, client?client: "DEFAULT"); - -- if (client) free(client); -- free(he); -+ free(client); - } - - void auth_unix_gid(FILE *f) -@@ -282,8 +282,7 @@ void nfsd_fh(FILE *f) - unsigned int fsidnum=0; - char fsid[32]; - struct exportent *found = NULL; -- struct hostent *he = NULL; -- struct in_addr addr; -+ struct addrinfo *ai = NULL; - char *found_path = NULL; - nfs_export *exp; - int i; -@@ -465,9 +464,9 @@ void nfsd_fh(FILE *f) - break; - } - if (use_ipaddr) { -- if (!he && !client_resolve_paddr(dom, &he)) -+ if (!ai && !client_resolve_paddr(dom, &ai)) - goto out; -- if (!client_check(exp->m_client, he)) -+ if (!client_check(exp->m_client, ai)) - continue; - } - /* It's a match !! */ -@@ -541,8 +540,7 @@ found: - out: - if (found_path) - free(found_path); -- if (he) -- free(he); -+ freeaddrinfo(ai); - free(dom); - xlog(D_CALL, "nfsd_fh: found %p path %s", found, found ? found->e_path : NULL); - return; -@@ -634,8 +632,7 @@ void nfsd_export(FILE *f) - char *dom, *path; - nfs_export *exp, *found = NULL; - int found_type = 0; -- struct in_addr addr; -- struct hostent *he = NULL; -+ struct addrinfo *ai = NULL; - struct exportent *v4root = NULL; - - -@@ -684,9 +681,9 @@ void nfsd_export(FILE *f) - continue; - } - if (use_ipaddr) { -- if (!he && !client_resolve_paddr(dom, &he)) -+ if (!ai && !client_resolve_paddr(dom, &ai)) - goto out; -- if (!client_check(exp->m_client, he)) -+ if (!client_check(exp->m_client, ai)) - continue; - } - if (!found) { -@@ -742,7 +739,7 @@ void nfsd_export(FILE *f) - - if (dom) free(dom); - if (path) free(path); -- if (he) free(he); -+ freeaddrinfo(ai); - } - - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index 888fd8c..4c0c503 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -565,21 +565,21 @@ get_exportlist(void) - } - - if (i != MCL_FQDN && e->ex_groups) { -- struct hostent *hp; -- - cp = &e->ex_groups; - while ((c = *cp) != NULL) { -- if (client_gettype (c->gr_name) == MCL_FQDN -- && (hp = gethostbyname(c->gr_name))) { -- hp = hostent_dup (hp); -- if (client_check(exp->m_client, hp)) { -- *cp = c->gr_next; -- xfree(c->gr_name); -- xfree(c); -- xfree (hp); -- continue; -+ if (client_gettype (c->gr_name) == MCL_FQDN) { -+ struct addrinfo *ai; -+ ai = host_addrinfo(c->gr_name); -+ if (ai) { -+ if (client_check(exp->m_client, ai)) { -+ *cp = c->gr_next; -+ xfree(c->gr_name); -+ xfree(c); -+ freeaddrinfo(ai); -+ continue; -+ } -+ freeaddrinfo(ai); - } -- xfree (hp); - } - cp = &(c->gr_next); - } -------------------------------------------------------------------------------- -libexport-a-make-export_read-r -------------------------------------------------------------------------------- -libexport.a: Make export_read() return void - -From: Chuck Lever - -Clean up: export_read()'s return value is always zero, and its only -caller never checks it. - -Signed-off-by: Chuck Lever ---- - - support/export/export.c | 9 ++++++--- - support/include/exportfs.h | 2 +- - 2 files changed, 7 insertions(+), 4 deletions(-) - - -diff --git a/support/export/export.c b/support/export/export.c -index fe99f4f..346af92 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -37,7 +37,12 @@ export_free(nfs_export *exp) - xfree(exp); - } - --int -+/** -+ * export_read - read entries from /etc/exports -+ * @fname: name of file to read from -+ * -+ */ -+void - export_read(char *fname) - { - struct exportent *eep; -@@ -65,8 +70,6 @@ export_read(char *fname) - } - } - endexportent(); -- -- return 0; - } - - /* -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 60185dd..7f1ea28 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -129,7 +129,7 @@ int client_resolve_paddr(const char *address, - struct addrinfo **result); - int client_member(char *client, char *name); - --int export_read(char *fname); -+void export_read(char *fname); - void export_add(nfs_export *); - void export_reset(nfs_export *); - nfs_export * export_lookup(char *hname, char *path, int caconical); -------------------------------------------------------------------------------- -libexport-a-make-export_add-st -------------------------------------------------------------------------------- -libexport.a: Make export_add() static - -From: Chuck Lever - -Clean up: export_add() is not called from outside of export.c, so make -it a static helper. - -Signed-off-by: Chuck Lever ---- - - support/export/export.c | 59 +++++++++++++++++++++----------------------- - support/include/exportfs.h | 1 - - 2 files changed, 28 insertions(+), 32 deletions(-) - - -diff --git a/support/export/export.c b/support/export/export.c -index 346af92..1f972ff 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -37,6 +37,34 @@ export_free(nfs_export *exp) - xfree(exp); - } - -+static void -+export_add(nfs_export *exp) -+{ -+ exp_hash_table *p_tbl; -+ exp_hash_entry *p_hen; -+ nfs_export *p_next; -+ -+ int type = exp->m_client->m_type; -+ int pos; -+ -+ pos = export_hash(exp->m_export.e_path); -+ p_tbl = &(exportlist[type]); /* pointer to hash table */ -+ p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */ -+ -+ if (!(p_hen->p_first)) { /* hash table entry is empty */ -+ p_hen->p_first = exp; -+ p_hen->p_last = exp; -+ -+ exp->m_next = p_tbl->p_head; -+ p_tbl->p_head = exp; -+ } else { /* hash table entry is NOT empty */ -+ p_next = p_hen->p_last->m_next; -+ p_hen->p_last->m_next = exp; -+ exp->m_next = p_next; -+ p_hen->p_last = exp; -+ } -+} -+ - /** - * export_read - read entries from /etc/exports - * @fname: name of file to read from -@@ -148,37 +176,6 @@ export_dup(nfs_export *exp, const struct addrinfo *ai) - return new; - } - --/* -- * Add export entry to hash table -- */ --void --export_add(nfs_export *exp) --{ -- exp_hash_table *p_tbl; -- exp_hash_entry *p_hen; -- nfs_export *p_next; -- -- int type = exp->m_client->m_type; -- int pos; -- -- pos = export_hash(exp->m_export.e_path); -- p_tbl = &(exportlist[type]); /* pointer to hash table */ -- p_hen = &(p_tbl->entries[pos]); /* pointer to hash table entry */ -- -- if (!(p_hen->p_first)) { /* hash table entry is empty */ -- p_hen->p_first = exp; -- p_hen->p_last = exp; -- -- exp->m_next = p_tbl->p_head; -- p_tbl->p_head = exp; -- } else { /* hash table entry is NOT empty */ -- p_next = p_hen->p_last->m_next; -- p_hen->p_last->m_next = exp; -- exp->m_next = p_next; -- p_hen->p_last = exp; -- } --} -- - /** - * export_find - find or create a suitable nfs_export for @ai and @path - * @ai: pointer to addrinfo for client -diff --git a/support/include/exportfs.h b/support/include/exportfs.h -index 7f1ea28..49ad866 100644 ---- a/support/include/exportfs.h -+++ b/support/include/exportfs.h -@@ -130,7 +130,6 @@ int client_resolve_paddr(const char *address, - int client_member(char *client, char *name); - - void export_read(char *fname); --void export_add(nfs_export *); - void export_reset(nfs_export *); - nfs_export * export_lookup(char *hname, char *path, int caconical); - nfs_export * export_find(const struct addrinfo *ai, -------------------------------------------------------------------------------- -libexport-a-add-a-few-addition -------------------------------------------------------------------------------- -libexport.a: Add a few additional documenting comments - -From: Chuck Lever - -Clean up. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 21 ++++++++++++++++++--- - support/export/export.c | 19 +++++++++++++++---- - 2 files changed, 33 insertions(+), 7 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index c299299..712b252 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -135,9 +135,13 @@ client_add(nfs_client *clp) - *cpp = clp; - } - --/* if canonical is set, then we *know* this is already a canonical name -- * so hostname lookup is avoided. -- * This is used when reading /proc/fs/nfs/exports -+/** -+ * client_lookup - look for @hname in our list of cached nfs_clients -+ * @hname: '\0'-terminated ASCII string containing hostname to look for -+ * @canonical: if set, @hname is known to be canonical DNS name -+ * -+ * Returns pointer to a matching or freshly created nfs_client. NULL -+ * is returned if some problem occurs. - */ - nfs_client * - client_lookup(char *hname, int canonical) -@@ -215,6 +219,10 @@ client_dup(const nfs_client *clp, const struct addrinfo *ai) - return new; - } - -+/** -+ * client_freeall - deallocate all nfs_client records -+ * -+ */ - void - client_freeall(void) - { -@@ -564,6 +572,13 @@ client_check(const nfs_client *clp, const struct addrinfo *ai) - return 0; - } - -+/** -+ * client_gettype - determine type of nfs_client given an identifier -+ * @ident: '\0'-terminated ASCII string containing a client identifier -+ * -+ * Returns the type of nfs_client record that would be used for -+ * this client. -+ */ - int - client_gettype(char *ident) - { -diff --git a/support/export/export.c b/support/export/export.c -index 1f972ff..7993997 100644 ---- a/support/export/export.c -+++ b/support/export/export.c -@@ -100,8 +100,13 @@ export_read(char *fname) - endexportent(); - } - --/* -- * Create an in-core export struct from an export entry. -+/** -+ * export_create - create an in-core nfs_export record from an export entry -+ * @xep: export entry to lookup -+ * @canonical: if set, e_hostname is known to be canonical DNS name -+ * -+ * Returns a freshly instantiated export record, or NULL if -+ * a problem occurred. - */ - nfs_export * - export_create(struct exportent *xep, int canonical) -@@ -256,8 +261,14 @@ export_allowed(const struct addrinfo *ai, const char *path) - return NULL; - } - --/* -- * Search hash table for export entry. -+/** -+ * export_lookup - search hash table for export entry -+ * @hname: '\0'-terminated ASCII string containing client hostname to look for -+ * @path: '\0'-terminated ASCII string containing export path to look for -+ * @canonical: if set, @hname is known to be canonical DNS name -+ * -+ * Returns a pointer to nfs_export record matching @hname and @path, -+ * or NULL if the export was not found. - */ - nfs_export * - export_lookup(char *hname, char *path, int canonical) -------------------------------------------------------------------------------- -libexport-a-replace-matchhostn -------------------------------------------------------------------------------- -libexport.a: Replace matchhostname() - -From: Chuck Lever - -So exportfs can eventually support IPv6 addresses, copy statd's -getaddrinfo(3)-based matchhostname to exportfs, with adjustments for -dealing with export wildcards and netgroups. For now, we want to -ensure that IPv6 addresses continue to remain blocked in the address -comparison code used by exportfs. - -Since it contains special logic for handling wildcard and netgroups, -this function is specialized for exportfs, and does not belong in -generic code. - -Signed-off-by: Chuck Lever ---- - - support/include/misc.h | 2 - - utils/exportfs/exportfs.c | 78 +++++++++++++++++++++++++++++++++++++++++++++ - 2 files changed, 78 insertions(+), 2 deletions(-) - - -diff --git a/support/include/misc.h b/support/include/misc.h -index 9a1b25d..e817bc5 100644 ---- a/support/include/misc.h -+++ b/support/include/misc.h -@@ -15,8 +15,6 @@ - int randomkey(unsigned char *keyout, int len); - int weakrandomkey(unsigned char *keyout, int len); - --int matchhostname(const char *h1, const char *h2); -- - struct hostent; - struct hostent *hostent_dup(struct hostent *hp); - struct hostent *get_hostent (const char *addr, int len, int type); -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index 1d3e403..fae8310 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -35,6 +35,7 @@ static void dump(int verbose); - static void error(nfs_export *exp, int err); - static void usage(void); - static void validate_export(nfs_export *exp); -+static int matchhostname(const char *hostname1, const char *hostname2); - - int - main(int argc, char **argv) -@@ -420,6 +421,83 @@ validate_export(nfs_export *exp) - } - } - -+static int -+is_hostname(const char *sp) -+{ -+ if (*sp == '\0' || *sp == '@') -+ return 0; -+ -+ for (; *sp; sp++) { -+ if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/') -+ return 0; -+ if (*sp == '\\' && sp[1]) -+ sp++; -+ } -+ -+ return 1; -+} -+ -+static int -+compare_sockaddrs4(const struct sockaddr *sa1, const struct sockaddr *sa2) -+{ -+ const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; -+ const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; -+ return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; -+} -+ -+static int -+compare_sockaddrs(const struct sockaddr *sa1, const struct sockaddr *sa2) -+{ -+ if (sa1->sa_family == sa2->sa_family) -+ switch (sa1->sa_family) { -+ case AF_INET: -+ return compare_sockaddrs4(sa1, sa2); -+ } -+ -+ return 0; -+} -+ -+static int -+matchhostname(const char *hostname1, const char *hostname2) -+{ -+ struct addrinfo *gai_results1 = NULL, *gai_results2 = NULL; -+ struct addrinfo *ai1, *ai2; -+ int result = 0; -+ -+ if (strcasecmp(hostname1, hostname2) == 0) -+ return 1; -+ -+ /* -+ * Don't pass wildcards or netgroup names to DNS -+ */ -+ if (!is_hostname(hostname1) || !is_hostname(hostname2)) -+ return 0; -+ -+ gai_results1 = host_addrinfo(hostname1); -+ if (gai_results1 == NULL) -+ goto out; -+ gai_results2 = host_addrinfo(hostname2); -+ if (gai_results2 == NULL) -+ goto out; -+ -+ if (strcasecmp(gai_results1->ai_canonname, -+ gai_results2->ai_canonname) == 0) { -+ result = 1; -+ goto out; -+ } -+ -+ for (ai1 = gai_results1; ai1; ai1 = ai1->ai_next) -+ for (ai2 = gai_results2; ai2; ai2 = ai2->ai_next) -+ if (compare_sockaddrs(ai1->ai_addr, ai2->ai_addr)) { -+ result = 1; -+ goto out; -+ } -+ -+out: -+ freeaddrinfo(gai_results2); -+ freeaddrinfo(gai_results1); -+ return result; -+} - - static char - dumpopt(char c, char *fmt, ...) -------------------------------------------------------------------------------- -libexport-a-remove-unused-host -------------------------------------------------------------------------------- -libexport.a: Remove unused hostent-based DNS helper functions - -From: Chuck Lever - -Clean up: Get rid of hostent-based DNS helper functions in -libexport.a that have been replaced by addrinfo-based DNS helpers. - -Signed-off-by: Chuck Lever ---- - - support/export/hostname.c | 320 ++------------------------------------------- - support/include/misc.h | 5 - - 2 files changed, 16 insertions(+), 309 deletions(-) - - -diff --git a/support/export/hostname.c b/support/export/hostname.c -index 3cd1131..8d3a2bc 100644 ---- a/support/export/hostname.c -+++ b/support/export/hostname.c -@@ -1,30 +1,30 @@ - /* -- * support/export/hostname.c -+ * Copyright 2009 Oracle. All rights reserved. - * -- * Functions for hostname. -+ * This file is part of nfs-utils. - * -+ * nfs-utils is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * nfs-utils is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with nfs-utils. If not, see . - */ - - #ifdef HAVE_CONFIG_H - #include - #endif - --/* --#define TEST --*/ -- - #include --#include --#include --#include - #include --#include --#ifdef TEST --#define xmalloc malloc --#else --#include "xmalloc.h" --#include "misc.h" --#endif -+#include -+#include - - #include "exportfs.h" - #include "compaddr.h" -@@ -33,138 +33,6 @@ - #define AI_ADDRCONFIG 0 - #endif - --#define ALIGNMENT sizeof (char *) -- --static int --align (int len, int al) --{ -- int i; -- i = len % al; -- if (i) -- len += al - i; -- return len; --} -- --struct hostent * --get_hostent (const char *addr, int len, int type) --{ -- struct hostent *cp; -- int len_ent; -- const char *name; -- int len_name; -- int num_aliases = 1; -- int len_aliases = sizeof (char *); -- int num_addr_list = 1; -- int len_addr_list = sizeof (char *); -- int pos; -- struct in_addr *ipv4; -- -- switch (type) -- { -- case AF_INET: -- ipv4 = (struct in_addr *) addr; -- name = inet_ntoa (*ipv4); -- break; -- -- default: -- return NULL; -- } -- -- len_ent = align (sizeof (*cp), ALIGNMENT); -- len_name = align (strlen (name) + 1, ALIGNMENT); -- -- num_addr_list++; -- len_addr_list += align (len, ALIGNMENT) + sizeof (char *); -- -- cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases -- + len_addr_list); -- -- cp->h_addrtype = type; -- cp->h_length = len; -- pos = len_ent; -- cp->h_name = (char *) &(((char *) cp) [pos]); -- strcpy (cp->h_name, name); -- -- pos += len_name; -- cp->h_aliases = (char **) &(((char *) cp) [pos]); -- pos += num_aliases * sizeof (char *); -- cp->h_aliases [0] = NULL; -- -- pos = len_ent + len_name + len_aliases; -- cp->h_addr_list = (char **) &(((char *) cp) [pos]); -- pos += num_addr_list * sizeof (char *); -- cp->h_addr_list [0] = (char *) &(((char *) cp) [pos]); -- memcpy (cp->h_addr_list [0], addr, cp->h_length); -- pos += align (cp->h_length, ALIGNMENT); -- cp->h_addr_list [1] = NULL; -- -- return cp; --} -- --struct hostent * --hostent_dup (struct hostent *hp) --{ -- int len_ent = align (sizeof (*hp), ALIGNMENT); -- int len_name = align (strlen (hp->h_name) + 1, ALIGNMENT); -- int num_aliases = 1; -- int len_aliases = sizeof (char *); -- int num_addr_list = 1; -- int len_addr_list = sizeof (char *); -- int pos, i; -- char **sp; -- struct hostent *cp; -- -- for (sp = hp->h_aliases; sp && *sp; sp++) -- { -- num_aliases++; -- len_aliases += align (strlen (*sp) + 1, ALIGNMENT) -- + sizeof (char *); -- } -- -- for (sp = hp->h_addr_list; *sp; sp++) -- { -- num_addr_list++; -- len_addr_list += align (hp->h_length, ALIGNMENT) -- + sizeof (char *); -- } -- -- cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases -- + len_addr_list); -- -- *cp = *hp; -- pos = len_ent; -- cp->h_name = (char *) &(((char *) cp) [pos]); -- strcpy (cp->h_name, hp->h_name); -- -- pos += len_name; -- cp->h_aliases = (char **) &(((char *) cp) [pos]); -- pos += num_aliases * sizeof (char *); -- for (sp = hp->h_aliases, i = 0; i < num_aliases; i++, sp++) -- if (sp && *sp) -- { -- cp->h_aliases [i] = (char *) &(((char *) cp) [pos]); -- strcpy (cp->h_aliases [i], *sp); -- pos += align (strlen (*sp) + 1, ALIGNMENT); -- } -- else -- cp->h_aliases [i] = NULL; -- -- pos = len_ent + len_name + len_aliases; -- cp->h_addr_list = (char **) &(((char *) cp) [pos]); -- pos += num_addr_list * sizeof (char *); -- for (sp = hp->h_addr_list, i = 0; i < num_addr_list; i++, sp++) -- if (*sp) -- { -- cp->h_addr_list [i] = (char *) &(((char *) cp) [pos]); -- memcpy (cp->h_addr_list [i], *sp, hp->h_length); -- pos += align (hp->h_length, ALIGNMENT); -- } -- else -- cp->h_addr_list [i] = *sp; -- -- return cp; --} -- - #ifdef HAVE_GETNAMEINFO - static socklen_t - sockaddr_size(const struct sockaddr *sap) -@@ -441,159 +309,3 @@ host_numeric_addrinfo(const struct sockaddr *sap) - return ai; - } - #endif /* !HAVE_GETNAMEINFO */ -- --static int --is_hostname(const char *sp) --{ -- if (*sp == '\0' || *sp == '@') -- return 0; -- -- for (; *sp; sp++) -- { -- if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/') -- return 0; -- if (*sp == '\\' && sp[1]) -- sp++; -- } -- -- return 1; --} -- --int --matchhostname (const char *h1, const char *h2) --{ -- struct hostent *hp1, *hp2; -- int status; -- -- if (strcasecmp (h1, h2) == 0) -- return 1; -- -- if (!is_hostname (h1) || !is_hostname (h2)) -- return 0; -- -- hp1 = gethostbyname (h1); -- if (hp1 == NULL) -- return 0; -- -- hp1 = hostent_dup (hp1); -- -- hp2 = gethostbyname (h2); -- if (hp2) -- { -- if (strcasecmp (hp1->h_name, hp2->h_name) == 0) -- status = 1; -- else -- { -- char **ap1, **ap2; -- -- status = 0; -- for (ap1 = hp1->h_addr_list; *ap1 && status == 0; ap1++) -- for (ap2 = hp2->h_addr_list; *ap2; ap2++) -- if (memcmp (*ap1, *ap2, sizeof (struct in_addr)) == 0) -- { -- status = 1; -- break; -- } -- } -- } -- else -- status = 0; -- -- free (hp1); -- return status; --} -- -- --/* Map IP to hostname, and then map back to addr to make sure it is a -- * reliable hostname -- */ --struct hostent * --get_reliable_hostbyaddr(const char *addr, int len, int type) --{ -- struct hostent *hp = NULL; -- -- struct hostent *reverse; -- struct hostent *forward; -- char **sp; -- -- reverse = gethostbyaddr (addr, len, type); -- if (!reverse) -- return NULL; -- -- /* must make sure the hostent is authorative. */ -- -- reverse = hostent_dup (reverse); -- forward = gethostbyname (reverse->h_name); -- -- if (forward) { -- /* now make sure the "addr" is in the list */ -- for (sp = forward->h_addr_list ; *sp ; sp++) { -- if (memcmp (*sp, addr, forward->h_length) == 0) -- break; -- } -- -- if (*sp) { -- /* it's valid */ -- hp = hostent_dup (forward); -- } -- else { -- /* it was a FAKE */ -- xlog (L_WARNING, "Fake hostname %s for %s - forward lookup doesn't match reverse", -- reverse->h_name, inet_ntoa(*(struct in_addr*)addr)); -- } -- } -- else { -- /* never heard of it. misconfigured DNS? */ -- xlog (L_WARNING, "Fake hostname %s for %s - forward lookup doesn't exist", -- reverse->h_name, inet_ntoa(*(struct in_addr*)addr)); -- } -- -- free (reverse); -- return hp; --} -- -- --#ifdef TEST --void --print_host (struct hostent *hp) --{ -- char **sp; -- -- if (hp) -- { -- printf ("official hostname: %s\n", hp->h_name); -- printf ("aliases:\n"); -- for (sp = hp->h_aliases; *sp; sp++) -- printf (" %s\n", *sp); -- printf ("IP addresses:\n"); -- for (sp = hp->h_addr_list; *sp; sp++) -- printf (" %s\n", inet_ntoa (*(struct in_addr *) *sp)); -- } -- else -- printf ("Not host information\n"); --} -- --int --main (int argc, char **argv) --{ -- struct hostent *hp = gethostbyname (argv [1]); -- struct hostent *cp; -- struct in_addr addr; -- -- print_host (hp); -- -- if (hp) -- { -- cp = hostent_dup (hp); -- print_host (cp); -- free (cp); -- } -- printf ("127.0.0.1 == %s: %d\n", argv [1], -- matchhostname ("127.0.0.1", argv [1])); -- addr.s_addr = inet_addr(argv [2]); -- printf ("%s\n", inet_ntoa (addr)); -- cp = get_hostent ((const char *)&addr, sizeof(addr), AF_INET); -- print_host (cp); -- return 0; --} --#endif -diff --git a/support/include/misc.h b/support/include/misc.h -index e817bc5..bc5ba23 100644 ---- a/support/include/misc.h -+++ b/support/include/misc.h -@@ -15,11 +15,6 @@ - int randomkey(unsigned char *keyout, int len); - int weakrandomkey(unsigned char *keyout, int len); - --struct hostent; --struct hostent *hostent_dup(struct hostent *hp); --struct hostent *get_hostent (const char *addr, int len, int type); --struct hostent *get_reliable_hostbyaddr(const char *addr, int len, int type); -- - extern int is_mountpoint(char *path); - - #endif /* MISC_H */ -------------------------------------------------------------------------------- -exportfs-exportfs-c-no-longer- -------------------------------------------------------------------------------- -exportfs: exportfs.c no longer needs #include "xmalloc.h" - -From: Chuck Lever - -No calls to xmalloc() or xstrdup() here. No need for the double -#include of xmalloc.h. - -Signed-off-by: Chuck Lever ---- - - utils/exportfs/exportfs.c | 6 ++++-- - 1 files changed, 4 insertions(+), 2 deletions(-) - - -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index fae8310..c62716e 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -12,19 +12,21 @@ - #include - #endif - -+#include -+#include - #include - #include - #include - #include - #include - #include -+#include - #include - #include --#include "xmalloc.h" -+ - #include "misc.h" - #include "nfslib.h" - #include "exportfs.h" --#include "xmalloc.h" - #include "xlog.h" - - static void export_all(int verbose); -------------------------------------------------------------------------------- -exportfs-use-xlog-for-error-re -------------------------------------------------------------------------------- -exportfs: Use xlog() for error reporting - -From: Chuck Lever - -Clean up: libexport.a uses xlog() exclusively for error reporting and -debugging messages. Enable xlog debugging messages in exportfs. Use -xlog instead of fprintf(stderr) for reporting errors in exportfs.c, to -be consistent with libexport.a and other components of nfs-utils. - -Signed-off-by: Chuck Lever ---- - - utils/exportfs/exportfs.c | 57 ++++++++++++++++++++++++--------------------- - 1 files changed, 30 insertions(+), 27 deletions(-) - - -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index c62716e..b76958d 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -35,7 +35,7 @@ static void unexportfs(char *arg, int verbose); - static void exports_update(int verbose); - static void dump(int verbose); - static void error(nfs_export *exp, int err); --static void usage(void); -+static void usage(const char *progname); - static void validate_export(nfs_export *exp); - static int matchhostname(const char *hostname1, const char *hostname2); - -@@ -43,6 +43,7 @@ int - main(int argc, char **argv) - { - char *options = NULL; -+ char *progname = NULL; - int f_export = 1; - int f_all = 0; - int f_verbose = 0; -@@ -52,7 +53,14 @@ main(int argc, char **argv) - int new_cache = 0; - int force_flush = 0; - -- xlog_open("exportfs"); -+ if ((progname = strrchr(argv[0], '/')) != NULL) -+ progname++; -+ else -+ progname = argv[0]; -+ -+ xlog_open(progname); -+ xlog_stderr(1); -+ xlog_syslog(0); - - export_errno = 0; - -@@ -76,26 +84,27 @@ main(int argc, char **argv) - break; - case 'v': - f_verbose = 1; -+ xlog_config(D_ALL, 1); - break; - case 'f': - force_flush = 1; - break; - default: -- usage(); -+ usage(progname); - break; - } - } - - if (optind != argc && f_all) { -- fprintf(stderr,"exportfs: extra arguments are not permitted with -a or -r.\n"); -+ xlog(L_ERROR, "extra arguments are not permitted with -a or -r"); - return 1; - } - if (f_ignore && (f_all || ! f_export)) { -- fprintf(stderr,"exportfs: -i not meaningful with -a, -r or -u.\n"); -+ xlog(L_ERROR, "-i not meaningful with -a, -r or -u"); - return 1; - } - if (f_reexport && ! f_export) { -- fprintf(stderr, "exportfs: -r and -u are incompatible.\n"); -+ xlog(L_ERROR, "-r and -u are incompatible"); - return 1; - } - new_cache = check_new_cache(); -@@ -104,8 +113,10 @@ main(int argc, char **argv) - if (new_cache) - cache_flush(1); - else { -- fprintf(stderr, "exportfs: -f: only available with new cache controls: mount /proc/fs/nfsd first\n"); -- exit(1); -+ xlog(L_ERROR, "-f is available only " -+ "with new cache controls. " -+ "Mount /proc/fs/nfsd first"); -+ return 1; - } - return 0; - } else { -@@ -243,7 +254,7 @@ exportfs(char *arg, char *options, int verbose) - *path++ = '\0'; - - if (!path || *path != '/') { -- fprintf(stderr, "Invalid exporting option: %s\n", arg); -+ xlog(L_ERROR, "Invalid exporting option: %s", arg); - return; - } - -@@ -289,8 +300,7 @@ unexportfs(char *arg, int verbose) - *path++ = '\0'; - - if (!path || *path != '/') { -- fprintf(stderr, "Invalid unexporting option: %s\n", -- arg); -+ xlog(L_ERROR, "Invalid unexporting option: %s", arg); - return; - } - -@@ -385,14 +395,12 @@ validate_export(nfs_export *exp) - int fs_has_fsid = 0; - - if (stat(path, &stb) < 0) { -- fprintf(stderr, "exportfs: Warning: %s does not exist\n", -- path); -+ xlog(L_ERROR, "Failed to stat %s: %m \n", path); - return; - } - if (!S_ISDIR(stb.st_mode) && !S_ISREG(stb.st_mode)) { -- fprintf(stderr, "exportfs: Warning: %s is neither " -- "a directory nor a file.\n" -- " remote access will fail\n", path); -+ xlog(L_ERROR, "%s is neither a directory nor a file. " -+ "Remote access will fail", path); - return; - } - if (!can_test()) -@@ -405,19 +413,14 @@ validate_export(nfs_export *exp) - if ((exp->m_export.e_flags & NFSEXP_FSID) || exp->m_export.e_uuid || - fs_has_fsid) { - if ( !test_export(path, 1)) { -- fprintf(stderr, "exportfs: Warning: %s does not " -- "support NFS export.\n", -- path); -+ xlog(L_ERROR, "%s does not support NFS export", path); - return; - } - } else if ( ! test_export(path, 0)) { - if (test_export(path, 1)) -- fprintf(stderr, "exportfs: Warning: %s requires fsid= " -- "for NFS export\n", path); -+ xlog(L_ERROR, "%s requires fsid= for NFS export", path); - else -- fprintf(stderr, "exportfs: Warning: %s does not " -- "support NFS export.\n", -- path); -+ xlog(L_ERROR, "%s does not support NFS export", path); - return; - - } -@@ -601,13 +604,13 @@ dump(int verbose) - static void - error(nfs_export *exp, int err) - { -- fprintf(stderr, "%s:%s: %s\n", exp->m_client->m_hostname, -+ xlog(L_ERROR, "%s:%s: %s\n", exp->m_client->m_hostname, - exp->m_export.e_path, strerror(err)); - } - - static void --usage(void) -+usage(const char *progname) - { -- fprintf(stderr, "usage: exportfs [-aruv] [host:/path]\n"); -+ fprintf(stderr, "usage: %s [-aruv] [host:/path]\n", progname); - exit(1); - } -------------------------------------------------------------------------------- -libexport-a-prepare-to-recogni -------------------------------------------------------------------------------- -libexport.a: Prepare to recognize IPv6 addresses in client_gettype() - -From: Chuck Lever - -The current open-coded parsing logic in client_gettype() will be hard -to modify to recognize IPv6 addresses. Use a more generic mechanism -for detecting IP presentation addresses. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 23 ++++++++++++++--------- - 1 files changed, 14 insertions(+), 9 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 712b252..5e481a8 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -582,7 +582,8 @@ client_check(const nfs_client *clp, const struct addrinfo *ai) - int - client_gettype(char *ident) - { -- char *sp; -+ struct addrinfo *ai; -+ char *sp; - - if (ident[0] == '\0' || strcmp(ident, "*")==0) - return MCL_ANONYMOUS; -@@ -602,12 +603,16 @@ client_gettype(char *ident) - if (*sp == '\\' && sp[1]) - sp++; - } -- /* check for N.N.N.N */ -- sp = ident; -- if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '.') return MCL_FQDN; -- sp++; if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '.') return MCL_FQDN; -- sp++; if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '.') return MCL_FQDN; -- sp++; if(!isdigit(*sp) || strtoul(sp, &sp, 10) > 255 || *sp != '\0') return MCL_FQDN; -- /* we lie here a bit. but technically N.N.N.N == N.N.N.N/32 :) */ -- return MCL_SUBNETWORK; -+ -+ /* -+ * Treat unadorned host addresses as MCL_SUBNETWORK. -+ * Everything else is MCL_FQDN. -+ */ -+ ai = host_pton(ident); -+ if (ai) { -+ freeaddrinfo(ai); -+ return MCL_SUBNETWORK; -+ } -+ -+ return MCL_FQDN; - } -------------------------------------------------------------------------------- -libexport-a-prepare-init_subne -------------------------------------------------------------------------------- -libexport.a: Prepare init_subnetwork() for IPv6 support - -From: Chuck Lever - -Retire the slash32 logic in inet_netmask() in favor of a more generic -netmask parser that can support IPv6 addresses. - -If an invalid IP address string is given to inet_addr(3), it returns -INADDR_NONE, which is actually a valid address (255.255.255.255). -We're none the wiser to the substitution until something breaks later. -This patch provides better sanity checking of the parsed address, now -that such an error can be reported to client_init()'s callers. - -We can also check the prefixlen value a little more carefully as well. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 77 ++++++++++++++++++++++++++++++++++------------- - 1 files changed, 56 insertions(+), 21 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 5e481a8..b42bcde 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -17,6 +17,7 @@ - #include - #include - #include -+#include - - #include "misc.h" - #include "nfslib.h" -@@ -60,25 +61,55 @@ client_free(nfs_client *clp) - } - - static int --init_netmask(nfs_client *clp, const char *slash) -+init_netmask(nfs_client *clp, const char *slash, const sa_family_t family) - { - struct sockaddr_in sin = { - .sin_family = AF_INET, - }; -+ unsigned long prefixlen; - -- if (strchr(slash + 1, '.')) { -- sin.sin_addr.s_addr = inet_addr(slash + 1); -+ /* No slash present; assume netmask is all ones */ -+ if (!slash) { -+ switch (family) { -+ case AF_INET: -+ prefixlen = 32; -+ break; -+ default: -+ goto out_badfamily; -+ } - } else { -- int prefixlen = atoi(slash + 1); -- if (0 < prefixlen && prefixlen <= 32) -- sin.sin_addr.s_addr = -- htonl((uint32_t)~0 << (32 - prefixlen)); -- else -+ char *endptr; -+ -+ /* A spelled out netmask address, perhaps? */ -+ if (strchr(slash + 1, '.')) { -+ if (!inet_pton(AF_INET, slash + 1, &sin.sin_addr.s_addr)) -+ goto out_badmask; -+ set_addrlist_in(clp, 1, &sin); -+ return 1; -+ } -+ -+ /* A prefixlen was given */ -+ prefixlen = strtoul(slash + 1, &endptr, 10); -+ if (*endptr != '\0' && prefixlen != ULONG_MAX && errno != ERANGE) - goto out_badprefix; - } - -- set_addrlist_in(clp, 1, &sin); -- return 1; -+ switch (family) { -+ case AF_INET: -+ if (prefixlen > 32) -+ goto out_badprefix; -+ sin.sin_addr.s_addr = htonl((uint32_t)~0 << (32 - prefixlen)); -+ set_addrlist_in(clp, 1, &sin); -+ return 1; -+ } -+ -+out_badfamily: -+ xlog(L_ERROR, "Unsupported address family for %s", clp->m_hostname); -+ return 0; -+ -+out_badmask: -+ xlog(L_ERROR, "Invalid netmask `%s' for %s", slash + 1, clp->m_hostname); -+ return 0; - - out_badprefix: - xlog(L_ERROR, "Invalid prefix `%s' for %s", slash + 1, clp->m_hostname); -@@ -88,22 +119,26 @@ out_badprefix: - static int - init_subnetwork(nfs_client *clp) - { -- struct sockaddr_in sin = { -- .sin_family = AF_INET, -- }; -- static char slash32[] = "/32"; -+ struct addrinfo *ai; -+ sa_family_t family; - char *cp; - - cp = strchr(clp->m_hostname, '/'); -- if (!cp) -- cp = slash32; - -- *cp = '\0'; -- sin.sin_addr.s_addr = inet_addr(clp->m_hostname); -- set_addrlist_in(clp, 0, &sin); -- *cp = '/'; -+ if (cp) -+ *cp = '\0'; -+ ai = host_pton(clp->m_hostname); -+ if (cp) -+ *cp = '/'; -+ if (!ai) { -+ xlog(L_ERROR, "Invalid IP address %s", clp->m_hostname); -+ return 0; -+ } -+ set_addrlist(clp, 0, ai->ai_addr, ai->ai_addrlen); -+ family = ai->ai_addr->sa_family; -+ freeaddrinfo(ai); - -- return init_netmask(clp, cp); -+ return init_netmask(clp, cp, family); - } - - static int -------------------------------------------------------------------------------- -libexport-a-ipv6-support-for-c -------------------------------------------------------------------------------- -libexport.a: IPv6 support for client_init_subnet() - -From: Chuck Lever - -To parse and store an IPv6 host or subnet address, -client_init_netmask() needs to handle 128 bit subnet masks. - -To keep things neat, only the flags that determine whether -getaddrinfo(3) can return IPV6 addresses are changed when -IPV6_SUPPORTED is enabled. If IPV6_SUPPORT is disabled, -IPv6 support here remains compiled in, but should never be -executed. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 32 ++++++++++++++++++++++++++++++++ - 1 files changed, 32 insertions(+), 0 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index b42bcde..01f9974 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -63,6 +63,12 @@ client_free(nfs_client *clp) - static int - init_netmask(nfs_client *clp, const char *slash, const sa_family_t family) - { -+#ifdef IPV6_SUPPORTED -+ int i; -+ struct sockaddr_in6 sin6 = { -+ .sin6_family = AF_INET6, -+ }; -+#endif - struct sockaddr_in sin = { - .sin_family = AF_INET, - }; -@@ -74,6 +80,11 @@ init_netmask(nfs_client *clp, const char *slash, const sa_family_t family) - case AF_INET: - prefixlen = 32; - break; -+#ifdef IPV6_SUPPORTED -+ case AF_INET6: -+ prefixlen = 128; -+ break; -+#endif - default: - goto out_badfamily; - } -@@ -87,6 +98,14 @@ init_netmask(nfs_client *clp, const char *slash, const sa_family_t family) - set_addrlist_in(clp, 1, &sin); - return 1; - } -+#ifdef IPV6_SUPPORTED -+ if (strchr(slash + 1, ':')) { -+ if (!inet_pton(AF_INET6, slash + 1, &sin6.sin6_addr)) -+ goto out_badmask; -+ set_addrlist_in6(clp, 1, &sin6); -+ return 1; -+ } -+#endif - - /* A prefixlen was given */ - prefixlen = strtoul(slash + 1, &endptr, 10); -@@ -101,6 +120,19 @@ init_netmask(nfs_client *clp, const char *slash, const sa_family_t family) - sin.sin_addr.s_addr = htonl((uint32_t)~0 << (32 - prefixlen)); - set_addrlist_in(clp, 1, &sin); - return 1; -+#ifdef IPV6_SUPPORTED -+ case AF_INET6: -+ if (prefixlen > 128) -+ goto out_badprefix; -+ for (i = 0; prefixlen > 32; i++) { -+ sin6.sin6_addr.s6_addr32[i] = 0xffffffff; -+ prefixlen -= 32; -+ } -+ sin6.sin6_addr.s6_addr32[i] = -+ htonl((uint32_t)~0 << (32 - prefixlen)); -+ set_addrlist_in6(clp, 1, &sin6); -+ return 1; -+#endif - } - - out_badfamily: -------------------------------------------------------------------------------- -libexport-a-ipv6-support-in-cl -------------------------------------------------------------------------------- -libexport.a: IPv6 support in client_check() - -From: Chuck Lever - -Introduce support for IPv6 in client_check()'s helpers. - -Signed-off-by: Chuck Lever ---- - - support/export/client.c | 64 +++++++++++++++++++++++++++++++---------------- - 1 files changed, 42 insertions(+), 22 deletions(-) - - -diff --git a/support/export/client.c b/support/export/client.c -index 01f9974..703f7d6 100644 ---- a/support/export/client.c -+++ b/support/export/client.c -@@ -22,6 +22,7 @@ - #include "misc.h" - #include "nfslib.h" - #include "exportfs.h" -+#include "compaddr.h" - - /* netgroup stuff never seems to be defined in any header file. Linux is - * not alone in this. -@@ -450,27 +451,6 @@ add_name(char *old, char *add) - return new; - } - --static int --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 int --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 0; --} -- - /* - * Check each address listed in @ai against each address - * stored in @clp. Return 1 if a match is found, otherwise -@@ -483,7 +463,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 (compare_sockaddr(ai->ai_addr, get_addrlist(clp, i))) - return 1; - - return 0; -@@ -513,6 +493,43 @@ check_subnet_v4(const struct sockaddr_in *address, - return 0; - } - -+#ifdef IPV6_SUPPORTED -+static int -+check_subnet_v6(const struct sockaddr_in6 *address, -+ const struct sockaddr_in6 *mask, const struct addrinfo *ai) -+{ -+ for (; ai; ai = ai->ai_next) { -+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)ai->ai_addr; -+ -+ if (sin6->sin6_family != AF_INET6) -+ continue; -+ -+ if (mask_match(address->sin6_addr.s6_addr32[0], -+ sin6->sin6_addr.s6_addr[0], -+ mask->sin6_addr.s6_addr32[0]) && -+ mask_match(address->sin6_addr.s6_addr32[1], -+ sin6->sin6_addr.s6_addr[1], -+ mask->sin6_addr.s6_addr32[1]) && -+ mask_match(address->sin6_addr.s6_addr32[2], -+ sin6->sin6_addr.s6_addr[2], -+ mask->sin6_addr.s6_addr32[2]) && -+ mask_match(address->sin6_addr.s6_addr32[3], -+ sin6->sin6_addr.s6_addr[3], -+ mask->sin6_addr.s6_addr32[3])) -+ return 1; -+ } -+ return 0; -+} -+#else /* !IPV6_SUPPORTED */ -+static int -+check_subnet_v6(__attribute__((unused)) const struct sockaddr_in6 *address, -+ __attribute__((unused)) const struct sockaddr_in6 *mask, -+ __attribute__((unused)) const struct addrinfo *ai) -+{ -+ return 0; -+} -+#endif /* !IPV6_SUPPORTED */ -+ - /* - * Check each address listed in @ai against the subnetwork or - * host address stored in @clp. Return 1 if an address in @hp -@@ -525,6 +542,9 @@ check_subnetwork(const nfs_client *clp, const struct addrinfo *ai) - case AF_INET: - return check_subnet_v4(get_addrlist_in(clp, 0), - get_addrlist_in(clp, 1), ai); -+ case AF_INET6: -+ return check_subnet_v6(get_addrlist_in6(clp, 0), -+ get_addrlist_in6(clp, 1), ai); - } - - return 0; -------------------------------------------------------------------------------- -libnfs-a-fix-api-for-getfh-fri -------------------------------------------------------------------------------- -libnfs.a: Fix API for getfh() & friends - -From: Chuck Lever - -POSIX requires that a "struct sockaddr" is the same size as a "struct -sockaddr_in". Therefore, "struct sockaddr" cannot contain an AF_INET6 -address. - -The nfsctl_arg struct uses a struct sockaddr to pass the client's IP -address to the kernel, meaning the legacy nfsctl() API can never -support IPv6. Fortunately for us, this legacy interface was replaced -by a text-based cache interface a few years back. We don't need to -support non-AF_INET addresses here. - -To document this, change the definitions of getfh() and friends to -take a struct sockaddr_in * instead of a struct sockaddr * . - -Since mountd will support IPv6 in the near future, check that the -family of incoming client addresses is AF_INET, in order to prevent -non-AF_INET addresses from being passed to the legacy nfsctl() -interface. - -Signed-off-by: Chuck Lever ---- - - support/include/nfslib.h | 9 ++++++--- - support/nfs/getfh.c | 48 ++++++++++++++++++++++++++++++++++++++++------ - utils/mountd/mountd.c | 7 +++---- - 3 files changed, 51 insertions(+), 13 deletions(-) - - -diff --git a/support/include/nfslib.h b/support/include/nfslib.h -index e4777dd..edd3b32 100644 ---- a/support/include/nfslib.h -+++ b/support/include/nfslib.h -@@ -135,9 +135,12 @@ int nfsaddclient(struct nfsctl_client *clp); - int nfsdelclient(struct nfsctl_client *clp); - int nfsexport(struct nfsctl_export *exp); - int nfsunexport(struct nfsctl_export *exp); --struct nfs_fh_len * getfh_old(struct sockaddr *addr, dev_t dev, ino_t ino); --struct nfs_fh_len * getfh(struct sockaddr *addr, const char *); --struct nfs_fh_len * getfh_size(struct sockaddr *addr, const char *, int size); -+ -+struct nfs_fh_len * getfh_old(const struct sockaddr_in *sin, -+ const dev_t dev, const ino_t ino); -+struct nfs_fh_len * getfh(const struct sockaddr_in *sin, const char *path); -+struct nfs_fh_len * getfh_size(const struct sockaddr_in *sin, -+ const char *path, int const size); - - void qword_print(FILE *f, char *str); - void qword_printhex(FILE *f, char *str, int slen); -diff --git a/support/nfs/getfh.c b/support/nfs/getfh.c -index 81266fd..f3023c5 100644 ---- a/support/nfs/getfh.c -+++ b/support/nfs/getfh.c -@@ -19,8 +19,17 @@ - #include - #include "nfslib.h" - -+/** -+ * getfh_old - ask the kernel for an NFSv2 file handle via nfsctl() -+ * @sin: pointer to the AF_INET address of a client -+ * @dev: device number of device where requested object resides -+ * @ino: inode number of requested object -+ * -+ * Returns a pointer to an NFSv2 file handle, or NULL if some error -+ * occurred. errno is set to reflect the specifics of the error. -+ */ - struct nfs_fh_len * --getfh_old (struct sockaddr *addr, dev_t dev, ino_t ino) -+getfh_old (const struct sockaddr_in *sin, const dev_t dev, const ino_t ino) - { - union nfsctl_res res; - struct nfsctl_arg arg; -@@ -30,7 +39,7 @@ getfh_old (struct sockaddr *addr, dev_t dev, ino_t ino) - arg.ca_getfh.gf_version = 2; /* obsolete */ - arg.ca_getfh.gf_dev = dev; - arg.ca_getfh.gf_ino = ino; -- memcpy(&arg.ca_getfh.gf_addr, addr, sizeof(struct sockaddr_in)); -+ memcpy(&arg.ca_getfh.gf_addr, sin, sizeof(*sin)); - - if (nfsctl(NFSCTL_GETFH, &arg, &res) < 0) - return NULL; -@@ -40,19 +49,32 @@ getfh_old (struct sockaddr *addr, dev_t dev, ino_t ino) - return &rfh; - } - -+/** -+ * getfh - ask the kernel for an NFSv2 file handle via nfsctl() -+ * @sin: pointer to the AF_INET address of a client -+ * @path: pointer to a '\0'-terminated ASCII string containing an pathname -+ * -+ * Returns a pointer to an NFSv2 file handle, or NULL if some error -+ * occurred. errno is set to reflect the specifics of the error. -+ */ - struct nfs_fh_len * --getfh(struct sockaddr *addr, const char *path) -+getfh(const struct sockaddr_in *sin, const char *path) - { - static union nfsctl_res res; - struct nfsctl_arg arg; - static struct nfs_fh_len rfh; - -+ if (sin->sin_family != AF_INET) { -+ errno = EAFNOSUPPORT; -+ return NULL; -+ } -+ - arg.ca_version = NFSCTL_VERSION; - arg.ca_getfd.gd_version = 2; /* obsolete */ - strncpy(arg.ca_getfd.gd_path, path, - sizeof(arg.ca_getfd.gd_path) - 1); - arg.ca_getfd.gd_path[sizeof (arg.ca_getfd.gd_path) - 1] = '\0'; -- memcpy(&arg.ca_getfd.gd_addr, addr, sizeof(struct sockaddr_in)); -+ memcpy(&arg.ca_getfd.gd_addr, sin, sizeof(*sin)); - - if (nfsctl(NFSCTL_GETFD, &arg, &res) < 0) - return NULL; -@@ -62,17 +84,31 @@ getfh(struct sockaddr *addr, const char *path) - return &rfh; - } - -+/** -+ * getfh_size - ask the kernel for a file handle via nfsctl() -+ * @sin: pointer to the AF_INET address of a client -+ * @path: pointer to a '\0'-terminated ASCII string containing an pathname -+ * @size: maximum size, in bytes, of the returned file handle -+ * -+ * Returns a pointer to an NFSv3 file handle, or NULL if some error -+ * occurred. errno is set to reflect the specifics of the error. -+ */ - struct nfs_fh_len * --getfh_size(struct sockaddr *addr, const char *path, int size) -+getfh_size(const struct sockaddr_in *sin, const char *path, const int size) - { - static union nfsctl_res res; - struct nfsctl_arg arg; - -+ if (sin->sin_family != AF_INET) { -+ errno = EAFNOSUPPORT; -+ return NULL; -+ } -+ - arg.ca_version = NFSCTL_VERSION; - strncpy(arg.ca_getfs.gd_path, path, - sizeof(arg.ca_getfs.gd_path) - 1); - arg.ca_getfs.gd_path[sizeof (arg.ca_getfs.gd_path) - 1] = '\0'; -- memcpy(&arg.ca_getfs.gd_addr, addr, sizeof(struct sockaddr_in)); -+ memcpy(&arg.ca_getfs.gd_addr, sin, sizeof(*sin)); - arg.ca_getfs.gd_maxlen = size; - - if (nfsctl(NFSCTL_GETFS, &arg, &res) < 0) -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index 4c0c503..4955fb0 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -482,14 +482,13 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, - xtab_append(exp); - - if (v3) -- fh = getfh_size ((struct sockaddr *) sin, p, 64); -+ fh = getfh_size(sin, p, 64); - if (!v3 || (fh == NULL && errno == EINVAL)) { - /* We first try the new nfs syscall. */ -- fh = getfh ((struct sockaddr *) sin, p); -+ fh = getfh(sin, p); - if (fh == NULL && errno == EINVAL) - /* Let's try the old one. */ -- fh = getfh_old ((struct sockaddr *) sin, -- stb.st_dev, stb.st_ino); -+ fh = getfh_old(sin, stb.st_dev, stb.st_ino); - } - if (fh == NULL && !did_export) { - exp->m_exported = 0; -------------------------------------------------------------------------------- -mountd-add-ipv6-support-in-aut -------------------------------------------------------------------------------- -mountd: add IPv6 support in auth_authenticate() - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/mountd/auth.c | 62 +++++++++++++++++++++++++++++-------------------- - utils/mountd/mountd.c | 6 ++--- - utils/mountd/mountd.h | 5 ++-- - utils/mountd/rmtab.c | 3 ++ - 4 files changed, 45 insertions(+), 31 deletions(-) - - -diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c -index 1eb78a3..d63b23a 100644 ---- a/utils/mountd/auth.c -+++ b/utils/mountd/auth.c -@@ -21,6 +21,7 @@ - #include "mountd.h" - #include "xmalloc.h" - #include "v4root.h" -+#include "nfsrpc.h" - - enum auth_error - { -@@ -112,9 +113,8 @@ auth_reload() - } - - static nfs_export * --auth_authenticate_internal(struct sockaddr_in *caller, -- char *path, struct addrinfo *ai, -- enum auth_error *error) -+auth_authenticate_internal(const struct sockaddr *caller, const char *path, -+ struct addrinfo *ai, enum auth_error *error) - { - nfs_export *exp; - -@@ -123,10 +123,9 @@ auth_authenticate_internal(struct sockaddr_in *caller, - /* return static nfs_export with details filled in */ - char *n; - free(my_client.m_hostname); -- if (use_ipaddr) { -- my_client.m_hostname = -- strdup(inet_ntoa(caller->sin_addr)); -- } else { -+ if (use_ipaddr) -+ my_client.m_hostname = strdup(host_ntop(caller)); -+ else { - n = client_compose(ai); - *error = unknown_host; - if (!n) -@@ -141,7 +140,21 @@ auth_authenticate_internal(struct sockaddr_in *caller, - if (my_client.m_hostname == NULL) - return NULL; - my_client.m_naddr = 1; -- set_addrlist_in(&my_client, 0, caller); -+ switch (caller->sa_family) { -+ case AF_INET: -+ set_addrlist_in(&my_client, 0, -+ (struct sockaddr_in *)caller); -+ break; -+#ifdef IPV6_SUPPORTED -+ case AF_INET6: -+ set_addrlist_in6(&my_client, 0, -+ (struct sockaddr_in6 *)caller); -+ break; -+#endif -+ default: -+ free(n); -+ return NULL; -+ } - my_exp.m_client = &my_client; - - exp = NULL; -@@ -173,7 +186,7 @@ auth_authenticate_internal(struct sockaddr_in *caller, - } - } - if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) && -- ntohs(caller->sin_port) >= IPPORT_RESERVED) { -+ nfs_get_port(caller) >= IPPORT_RESERVED) { - *error = illegal_port; - return NULL; - } -@@ -183,18 +196,18 @@ auth_authenticate_internal(struct sockaddr_in *caller, - } - - nfs_export * --auth_authenticate(char *what, struct sockaddr_in *caller, char *path) -+auth_authenticate(const char *what, const struct sockaddr *caller, -+ const char *path) - { - nfs_export *exp = NULL; - char epath[MAXPATHLEN+1]; - char *p = NULL; - struct addrinfo *ai = NULL; -- struct in_addr addr = caller->sin_addr; - enum auth_error error = bad_path; - -- if (path [0] != '/') { -- xlog(L_WARNING, "bad path in %s request from %s: \"%s\"", -- what, inet_ntoa(addr), path); -+ if (path[0] != '/') { -+ xlog(L_WARNING, "Bad path in %s request from %s: \"%s\"", -+ what, host_ntop(caller), path); - return exp; - } - -@@ -202,14 +215,13 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path) - epath[sizeof (epath) - 1] = '\0'; - auth_fixpath(epath); /* strip duplicate '/' etc */ - -- ai = client_resolve((struct sockaddr *)caller); -+ ai = client_resolve(caller); - if (!ai) - return exp; - - /* Try the longest matching exported pathname. */ - while (1) { -- exp = auth_authenticate_internal(caller, epath, -- ai, &error); -+ exp = auth_authenticate_internal(caller, epath, ai, &error); - if (exp || (error != not_exported && error != no_entry)) - break; - /* We have to treat the root, "/", specially. */ -@@ -222,12 +234,12 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path) - switch (error) { - case bad_path: - xlog(L_WARNING, "bad path in %s request from %s: \"%s\"", -- what, inet_ntoa(addr), path); -+ what, host_ntop(caller), path); - break; - - case unknown_host: - xlog(L_WARNING, "refused %s request from %s for %s (%s): unmatched host", -- what, inet_ntoa(addr), path, epath); -+ what, host_ntop(caller), path, epath); - break; - - case no_entry: -@@ -241,17 +253,17 @@ auth_authenticate(char *what, struct sockaddr_in *caller, char *path) - break; - - case illegal_port: -- xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %d", -- what, ai->ai_canonname, path, epath, ntohs(caller->sin_port)); -+ xlog(L_WARNING, "refused %s request from %s for %s (%s): illegal port %u", -+ what, ai->ai_canonname, path, epath, nfs_get_port(caller)); - break; - - case success: -- xlog(L_NOTICE, "authenticated %s request from %s:%d for %s (%s)", -- what, ai->ai_canonname, ntohs(caller->sin_port), path, epath); -+ xlog(L_NOTICE, "authenticated %s request from %s:%u for %s (%s)", -+ what, ai->ai_canonname, nfs_get_port(caller), path, epath); - break; - default: -- xlog(L_NOTICE, "%s request from %s:%d for %s (%s) gave %d", -- what, ai->ai_canonname, ntohs(caller->sin_port), -+ xlog(L_NOTICE, "%s request from %s:%u for %s (%s) gave %d", -+ what, ai->ai_canonname, nfs_get_port(caller), - path, epath, error); - } - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index 4955fb0..3d857f0 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -236,7 +236,7 @@ mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp) - p = rpath; - } - -- if (!(exp = auth_authenticate("unmount", sin, p))) { -+ if (!(exp = auth_authenticate("unmount", (struct sockaddr *)sin, p))) { - return 1; - } - -@@ -311,7 +311,7 @@ mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res) - } - - /* Now authenticate the intruder... */ -- exp = auth_authenticate("pathconf", sin, p); -+ exp = auth_authenticate("pathconf", (struct sockaddr *)sin, p); - if (!exp) { - return 1; - } else if (stat(p, &stb) < 0) { -@@ -413,7 +413,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, - } - - /* Now authenticate the intruder... */ -- exp = auth_authenticate("mount", sin, p); -+ exp = auth_authenticate("mount", (struct sockaddr *)sin, p); - if (!exp) { - *error = NFSERR_ACCES; - return NULL; -diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h -index 31bacb5..96e9bf1 100644 ---- a/utils/mountd/mountd.h -+++ b/utils/mountd/mountd.h -@@ -41,8 +41,9 @@ bool_t mount_mnt_3_svc(struct svc_req *, dirpath *, mountres3 *); - void mount_dispatch(struct svc_req *, SVCXPRT *); - void auth_init(char *export_file); - unsigned int auth_reload(void); --nfs_export * auth_authenticate(char *what, struct sockaddr_in *sin, -- char *path); -+nfs_export * auth_authenticate(const char *what, -+ const struct sockaddr *caller, -+ const char *path); - void auth_export(nfs_export *exp); - - void mountlist_add(char *host, const char *path); -diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c -index 3b45d57..a6d553f 100644 ---- a/utils/mountd/rmtab.c -+++ b/utils/mountd/rmtab.c -@@ -161,7 +161,8 @@ mountlist_del_all(struct sockaddr_in *sin) - } - while ((rep = getrmtabent(1, NULL)) != NULL) { - if (strcmp(rep->r_client, hostname) == 0 && -- (exp = auth_authenticate("umountall", sin, rep->r_path))) -+ (exp = auth_authenticate("umountall", -+ (struct sockaddr *)sin, rep->r_path))) - continue; - fputrmtabent(fp, rep, NULL); - } -------------------------------------------------------------------------------- -mountd-support-ipv6-in-mountd- -------------------------------------------------------------------------------- -mountd: Support IPv6 in mountd's svc routines - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/mountd/mountd.c | 35 ++++++++++++++++++----------------- - 1 files changed, 18 insertions(+), 17 deletions(-) - - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index 3d857f0..ba4fcb7 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -212,9 +212,9 @@ mount_mnt_1_svc(struct svc_req *rqstp, dirpath *path, fhstatus *res) - bool_t - mount_dump_1_svc(struct svc_req *rqstp, void *argp, mountlist *res) - { -- struct sockaddr_in *addr = nfs_getrpccaller_in(rqstp->rq_xprt); -+ struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - -- xlog(D_CALL, "dump request from %s.", inet_ntoa(addr->sin_addr)); -+ xlog(D_CALL, "dump request from %s.", host_ntop(sap)); - *res = mountlist_list(); - - return 1; -@@ -223,7 +223,7 @@ mount_dump_1_svc(struct svc_req *rqstp, void *argp, mountlist *res) - bool_t - mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp) - { -- struct sockaddr_in *sin = nfs_getrpccaller_in(rqstp->rq_xprt); -+ struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - nfs_export *exp; - char *p = *argp; - char rpath[MAXPATHLEN+1]; -@@ -236,11 +236,11 @@ mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp) - p = rpath; - } - -- if (!(exp = auth_authenticate("unmount", (struct sockaddr *)sin, p))) { -+ if (!(exp = auth_authenticate("unmount", sap, p))) { - return 1; - } - -- mountlist_del(inet_ntoa(sin->sin_addr), p); -+ mountlist_del(host_ntop(sap), p); - return 1; - } - -@@ -257,9 +257,9 @@ mount_umntall_1_svc(struct svc_req *rqstp, void *argp, void *resp) - bool_t - mount_export_1_svc(struct svc_req *rqstp, void *argp, exports *resp) - { -- struct sockaddr_in *addr = nfs_getrpccaller_in(rqstp->rq_xprt); -+ struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - -- xlog(D_CALL, "export request from %s.", inet_ntoa(addr->sin_addr)); -+ xlog(D_CALL, "export request from %s.", host_ntop(sap)); - *resp = get_exportlist(); - - return 1; -@@ -268,9 +268,9 @@ mount_export_1_svc(struct svc_req *rqstp, void *argp, exports *resp) - bool_t - mount_exportall_1_svc(struct svc_req *rqstp, void *argp, exports *resp) - { -- struct sockaddr_in *addr = nfs_getrpccaller_in(rqstp->rq_xprt); -+ struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - -- xlog(D_CALL, "exportall request from %s.", inet_ntoa(addr->sin_addr)); -+ xlog(D_CALL, "exportall request from %s.", host_ntop(sap)); - *resp = get_exportlist(); - - return 1; -@@ -290,7 +290,7 @@ mount_exportall_1_svc(struct svc_req *rqstp, void *argp, exports *resp) - bool_t - mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res) - { -- struct sockaddr_in *sin = nfs_getrpccaller_in(rqstp->rq_xprt); -+ struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - struct stat stb; - nfs_export *exp; - char rpath[MAXPATHLEN+1]; -@@ -311,7 +311,7 @@ mount_pathconf_2_svc(struct svc_req *rqstp, dirpath *path, ppathcnf *res) - } - - /* Now authenticate the intruder... */ -- exp = auth_authenticate("pathconf", (struct sockaddr *)sin, p); -+ exp = auth_authenticate("pathconf", sap, p); - if (!exp) { - return 1; - } else if (stat(p, &stb) < 0) { -@@ -393,7 +393,7 @@ static struct nfs_fh_len * - get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, - mountstat3 *error, int v3) - { -- struct sockaddr_in *sin = nfs_getrpccaller_in(rqstp->rq_xprt); -+ struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - struct stat stb, estb; - nfs_export *exp; - struct nfs_fh_len *fh; -@@ -413,7 +413,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, - } - - /* Now authenticate the intruder... */ -- exp = auth_authenticate("mount", (struct sockaddr *)sin, p); -+ exp = auth_authenticate("mount", sap, p); - if (!exp) { - *error = NFSERR_ACCES; - return NULL; -@@ -482,13 +482,14 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, - xtab_append(exp); - - if (v3) -- fh = getfh_size(sin, p, 64); -+ fh = getfh_size((struct sockaddr_in *)sap, p, 64); - if (!v3 || (fh == NULL && errno == EINVAL)) { - /* We first try the new nfs syscall. */ -- fh = getfh(sin, p); -+ fh = getfh((struct sockaddr_in *)sap, p); - if (fh == NULL && errno == EINVAL) - /* Let's try the old one. */ -- fh = getfh_old(sin, stb.st_dev, stb.st_ino); -+ fh = getfh_old((struct sockaddr_in *)sap, -+ stb.st_dev, stb.st_ino); - } - if (fh == NULL && !did_export) { - exp->m_exported = 0; -@@ -502,7 +503,7 @@ get_rootfh(struct svc_req *rqstp, dirpath *path, nfs_export **expret, - } - } - *error = NFS_OK; -- mountlist_add(inet_ntoa(sin->sin_addr), p); -+ mountlist_add(host_ntop(sap), p); - if (expret) - *expret = exp; - return fh; -------------------------------------------------------------------------------- -mountd-support-ipv6-in-mountli-0 -------------------------------------------------------------------------------- -mountd: support IPv6 in mountlist_del_all() - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/mountd/mountd.c | 2 +- - utils/mountd/mountd.h | 2 +- - utils/mountd/rmtab.c | 10 ++++------ - 3 files changed, 6 insertions(+), 8 deletions(-) - - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index ba4fcb7..cd3a024 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -250,7 +250,7 @@ mount_umntall_1_svc(struct svc_req *rqstp, void *argp, void *resp) - /* Reload /etc/xtab if necessary */ - auth_reload(); - -- mountlist_del_all(nfs_getrpccaller_in(rqstp->rq_xprt)); -+ mountlist_del_all(nfs_getrpccaller(rqstp->rq_xprt)); - return 1; - } - -diff --git a/utils/mountd/mountd.h b/utils/mountd/mountd.h -index 96e9bf1..0d31ca7 100644 ---- a/utils/mountd/mountd.h -+++ b/utils/mountd/mountd.h -@@ -48,7 +48,7 @@ void auth_export(nfs_export *exp); - - void mountlist_add(char *host, const char *path); - void mountlist_del(char *host, const char *path); --void mountlist_del_all(struct sockaddr_in *sin); -+void mountlist_del_all(const struct sockaddr *sap); - mountlist mountlist_list(void); - - -diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c -index a6d553f..b5d5bb7 100644 ---- a/utils/mountd/rmtab.c -+++ b/utils/mountd/rmtab.c -@@ -130,7 +130,7 @@ mountlist_del(char *hname, const char *path) - } - - void --mountlist_del_all(struct sockaddr_in *sin) -+mountlist_del_all(const struct sockaddr *sap) - { - char *hostname; - struct rmtabent *rep; -@@ -140,10 +140,9 @@ mountlist_del_all(struct sockaddr_in *sin) - - if ((lockid = xflock(_PATH_RMTABLCK, "w")) < 0) - return; -- hostname = host_canonname((struct sockaddr *)sin); -+ hostname = host_canonname(sap); - if (!hostname) { -- xlog(L_ERROR, "can't get hostname of %s", -- host_ntop((struct sockaddr *)sin)); -+ xlog(L_ERROR, "can't get hostname of %s", host_ntop(sap)); - xfunlock(lockid); - return; - } -@@ -161,8 +160,7 @@ mountlist_del_all(struct sockaddr_in *sin) - } - while ((rep = getrmtabent(1, NULL)) != NULL) { - if (strcmp(rep->r_client, hostname) == 0 && -- (exp = auth_authenticate("umountall", -- (struct sockaddr *)sin, rep->r_path))) -+ (exp = auth_authenticate("umountall", sap, rep->r_path))) - continue; - fputrmtabent(fp, rep, NULL); - } -------------------------------------------------------------------------------- -mountd-add-mountlist_freeall -------------------------------------------------------------------------------- -mountd: Add mountlist_freeall() - -From: Chuck Lever - -Clean up: introduce a helper for freeing all mountlist records. - -Signed-off-by: Chuck Lever ---- - - utils/mountd/rmtab.c | 19 +++++++++++++------ - 1 files changed, 13 insertions(+), 6 deletions(-) - - -diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c -index b5d5bb7..fd41dbf 100644 ---- a/utils/mountd/rmtab.c -+++ b/utils/mountd/rmtab.c -@@ -174,6 +174,18 @@ mountlist_del_all(const struct sockaddr *sap) - free(hostname); - } - -+static void -+mountlist_freeall(mountlist mlist) -+{ -+ while (mlist) { -+ mountlist m = mlist; -+ mlist = m->ml_next; -+ xfree(m->ml_hostname); -+ xfree(m->ml_directory); -+ xfree(m); -+ } -+} -+ - mountlist - mountlist_list(void) - { -@@ -193,12 +205,7 @@ mountlist_list(void) - return NULL; - } - if (stb.st_mtime != last_mtime) { -- while (mlist) { -- mlist = (m = mlist)->ml_next; -- xfree(m->ml_hostname); -- xfree(m->ml_directory); -- xfree(m); -- } -+ mountlist_freeall(mlist); - last_mtime = stb.st_mtime; - - setrmtabent("r"); -------------------------------------------------------------------------------- -mountd-handle-memory-exhaustio -------------------------------------------------------------------------------- -mountd: Handle memory exhaustion in mountlist_list() - -From: Chuck Lever - -I'm about to replace inet_aton(3)/gethostbyaddr(3) with -host_pton()/host_canonname(). Since host_canonname() returns a string -allocated with strdup(3) instead of xstrdup(), mountlist_list() will -now have to deal with memory exhaustion properly. - -Signed-off-by: Chuck Lever ---- - - utils/mountd/rmtab.c | 32 ++++++++++++++++++++++++-------- - 1 files changed, 24 insertions(+), 8 deletions(-) - - -diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c -index fd41dbf..f08d5fd 100644 ---- a/utils/mountd/rmtab.c -+++ b/utils/mountd/rmtab.c -@@ -16,7 +16,7 @@ - #include - #include - #include --#include "xmalloc.h" -+ - #include "misc.h" - #include "exportfs.h" - #include "xio.h" -@@ -180,9 +180,9 @@ mountlist_freeall(mountlist mlist) - while (mlist) { - mountlist m = mlist; - mlist = m->ml_next; -- xfree(m->ml_hostname); -- xfree(m->ml_directory); -- xfree(m); -+ free(m->ml_hostname); -+ free(m->ml_directory); -+ free(m); - } - } - -@@ -210,16 +210,32 @@ mountlist_list(void) - - setrmtabent("r"); - while ((rep = getrmtabent(1, NULL)) != NULL) { -- m = (mountlist) xmalloc(sizeof(*m)); -+ m = calloc(1, sizeof(*m)); -+ if (!m) { -+ mountlist_freeall(mlist); -+ mlist = NULL; -+ xlog(L_ERROR, "%s: memory allocation failed", -+ __func__); -+ break; -+ } - - if (reverse_resolve && - inet_aton((const char *) rep->r_client, &addr) && - (he = gethostbyaddr(&addr, sizeof(addr), AF_INET))) -- m->ml_hostname = xstrdup(he->h_name); -+ m->ml_hostname = strdup(he->h_name); - else -- m->ml_hostname = xstrdup(rep->r_client); -+ m->ml_hostname = strdup(rep->r_client); -+ -+ m->ml_directory = strdup(rep->r_path); -+ -+ if (!m->ml_hostname || !m->ml_directory) { -+ mountlist_freeall(mlist); -+ mlist = NULL; -+ xlog(L_ERROR, "%s: memory allocation failed", -+ __func__); -+ break; -+ } - -- m->ml_directory = xstrdup(rep->r_path); - m->ml_next = mlist; - mlist = m; - } -------------------------------------------------------------------------------- -mountd-support-ipv6-in-mountli -------------------------------------------------------------------------------- -mountd: Support IPv6 in mountlist_list() - -From: Chuck Lever - -Replace inet_aton(3) and gethostbyaddr(3) with calls to our shiny new -host_foo() DNS helpers. - -Signed-off-by: Chuck Lever ---- - - utils/mountd/rmtab.c | 16 +++++++++------- - 1 files changed, 9 insertions(+), 7 deletions(-) - - -diff --git a/utils/mountd/rmtab.c b/utils/mountd/rmtab.c -index f08d5fd..8e91ee4 100644 ---- a/utils/mountd/rmtab.c -+++ b/utils/mountd/rmtab.c -@@ -195,8 +195,6 @@ mountlist_list(void) - struct rmtabent *rep; - struct stat stb; - int lockid; -- struct in_addr addr; -- struct hostent *he; - - if ((lockid = xflock(_PATH_RMTABLCK, "r")) < 0) - return NULL; -@@ -219,11 +217,15 @@ mountlist_list(void) - break; - } - -- if (reverse_resolve && -- inet_aton((const char *) rep->r_client, &addr) && -- (he = gethostbyaddr(&addr, sizeof(addr), AF_INET))) -- m->ml_hostname = strdup(he->h_name); -- else -+ if (reverse_resolve) { -+ struct addrinfo *ai; -+ ai = host_pton(rep->r_client); -+ if (ai) { -+ m->ml_hostname = host_canonname(ai->ai_addr); -+ freeaddrinfo(ai); -+ } -+ } -+ if (!m->ml_hostname) - m->ml_hostname = strdup(rep->r_client); - - m->ml_directory = strdup(rep->r_path); -------------------------------------------------------------------------------- -exportfs-enable-ipv6-support-i -------------------------------------------------------------------------------- -exportfs: Enable IPv6 support in matchhostname() - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/exportfs/exportfs.c | 23 ++--------------------- - 1 files changed, 2 insertions(+), 21 deletions(-) - - -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index b76958d..5702864 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -28,6 +28,7 @@ - #include "nfslib.h" - #include "exportfs.h" - #include "xlog.h" -+#include "compaddr.h" - - static void export_all(int verbose); - static void exportfs(char *arg, char *options, int verbose); -@@ -443,26 +444,6 @@ is_hostname(const char *sp) - } - - static int --compare_sockaddrs4(const struct sockaddr *sa1, const struct sockaddr *sa2) --{ -- const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1; -- const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2; -- return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr; --} -- --static int --compare_sockaddrs(const struct sockaddr *sa1, const struct sockaddr *sa2) --{ -- if (sa1->sa_family == sa2->sa_family) -- switch (sa1->sa_family) { -- case AF_INET: -- return compare_sockaddrs4(sa1, sa2); -- } -- -- return 0; --} -- --static int - matchhostname(const char *hostname1, const char *hostname2) - { - struct addrinfo *gai_results1 = NULL, *gai_results2 = NULL; -@@ -493,7 +474,7 @@ matchhostname(const char *hostname1, const char *hostname2) - - for (ai1 = gai_results1; ai1; ai1 = ai1->ai_next) - for (ai2 = gai_results2; ai2; ai2 = ai2->ai_next) -- if (compare_sockaddrs(ai1->ai_addr, ai2->ai_addr)) { -+ if (compare_sockaddr(ai1->ai_addr, ai2->ai_addr)) { - result = 1; - goto out; - } -------------------------------------------------------------------------------- -mountd-handle-ipv6-addresses-i -------------------------------------------------------------------------------- -mountd: Handle IPv6 addresses in kernel auth_unix_ip upcalls - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/mountd/cache.c | 4 ++-- - 1 files changed, 2 insertions(+), 2 deletions(-) - - -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index cbe477d..255a67b 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -64,7 +64,7 @@ void auth_unix_ip(FILE *f) - */ - char *cp; - char class[20]; -- char ipaddr[20]; -+ char ipaddr[INET6_ADDRSTRLEN]; - char *client = NULL; - struct addrinfo *ai = NULL; - if (readline(fileno(f), &lbuf, &lbuflen) != 1) -@@ -78,7 +78,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; - - auth_reload(); -------------------------------------------------------------------------------- -libexport-a-enable-ipv6-suppor -------------------------------------------------------------------------------- -libexport.a: Enable IPv6 support in hostname.c - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - support/export/hostname.c | 30 +++++++++++++++--------------- - 1 files changed, 15 insertions(+), 15 deletions(-) - - -diff --git a/support/export/hostname.c b/support/export/hostname.c -index 8d3a2bc..c92b241 100644 ---- a/support/export/hostname.c -+++ b/support/export/hostname.c -@@ -33,16 +33,6 @@ - #define AI_ADDRCONFIG 0 - #endif - --#ifdef HAVE_GETNAMEINFO --static socklen_t --sockaddr_size(const struct sockaddr *sap) --{ -- if (sap->sa_family != AF_INET) -- return 0; -- return sizeof(struct sockaddr_in); --} --#endif -- - /** - * host_ntop - generate presentation address given a sockaddr - * @sap: pointer to socket address -@@ -55,7 +45,7 @@ char * - host_ntop(const struct sockaddr *sap) - { - static char buf[NI_MAXHOST]; -- socklen_t salen = sockaddr_size(sap); -+ socklen_t salen = sockaddr_length(sap); - - if (salen == 0) - return strncpy(buf, "unknown family", sizeof(buf)); -@@ -99,7 +89,7 @@ host_pton(const char *paddr) - .ai_flags = AI_NUMERICHOST, - }; - struct sockaddr_in sin; -- int error; -+ int error, inet4; - - /* - * getaddrinfo(3) recognizes incomplete addresses like "10.4" -@@ -109,8 +99,9 @@ host_pton(const char *paddr) - * inet_pton(3) is much stricter. Use it to be certain we - * have a real AF_INET presentation address. - */ -+ inet4 = 1; - if (!inet_pton(AF_INET, paddr, &sin.sin_addr)) -- return NULL; -+ inet4 = 0; - - error = getaddrinfo(paddr, NULL, &hints, &ai); - if (error) { -@@ -119,6 +110,11 @@ host_pton(const char *paddr) - return NULL; - } - -+ if (!inet4 && ai->ai_addr->sa_family == AF_INET) { -+ freeaddrinfo(ai); -+ return NULL; -+ } -+ - return ai; - } - -@@ -134,7 +130,11 @@ struct addrinfo * - host_addrinfo(const char *hostname) - { - struct addrinfo hints = { -+#ifdef IPV6_SUPPORTED -+ .ai_family = AF_UNSPEC, -+#else - .ai_family = AF_INET, -+#endif - .ai_protocol = IPPROTO_UDP, /* don't return duplicates */ - .ai_flags = AI_ADDRCONFIG | AI_CANONNAME, - }; -@@ -167,7 +167,7 @@ char * - host_canonname(const struct sockaddr *sap) - { - char buf[NI_MAXHOST]; -- socklen_t salen = sockaddr_size(sap); -+ socklen_t salen = sockaddr_length(sap); - int error; - - if (salen == 0) { -@@ -246,7 +246,7 @@ host_numeric_addrinfo(const struct sockaddr *sap) - { - char buf[NI_MAXHOST]; - struct addrinfo *ai; -- socklen_t salen = sockaddr_size(sap); -+ socklen_t salen = sockaddr_length(sap); - int error; - - if (salen == 0) { -------------------------------------------------------------------------------- -mountd-support-ti-rpc-mountd-l -------------------------------------------------------------------------------- -mountd: Support TI-RPC mountd listener - -From: Chuck Lever - -If TI-RPC is available, use it to create mountd's svc listener. If -not, use the old function, rpc_init(), to create mountd's listener. - -IPv6 can be supported if TI-RCP is available. In this case, -/etc/netconfig is searched to determine which transports to advertise. - -Signed-off-by: Chuck Lever ---- - - utils/mountd/mountd.c | 18 +++++++++--------- - 1 files changed, 9 insertions(+), 9 deletions(-) - - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index cd3a024..8ff64c7 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -81,11 +81,11 @@ static void - unregister_services (void) - { - if (nfs_version & 0x1) -- pmap_unset (MOUNTPROG, MOUNTVERS); -+ nfs_svc_unregister(MOUNTPROG, MOUNTVERS); - if (nfs_version & (0x1 << 1)) -- pmap_unset (MOUNTPROG, MOUNTVERS_POSIX); -+ nfs_svc_unregister(MOUNTPROG, MOUNTVERS_POSIX); - if (nfs_version & (0x1 << 2)) -- pmap_unset (MOUNTPROG, MOUNTVERS_NFSV3); -+ nfs_svc_unregister(MOUNTPROG, MOUNTVERS_NFSV3); - } - - static void -@@ -736,14 +736,14 @@ main(int argc, char **argv) - cache_open(); - - if (nfs_version & 0x1) -- rpc_init("mountd", MOUNTPROG, MOUNTVERS, -- mount_dispatch, port); -+ (void)nfs_svc_create("mountd", MOUNTPROG, MOUNTVERS, -+ mount_dispatch, port); - if (nfs_version & (0x1 << 1)) -- rpc_init("mountd", MOUNTPROG, MOUNTVERS_POSIX, -- mount_dispatch, port); -+ (void)nfs_svc_create("mountd", MOUNTPROG, MOUNTVERS_POSIX, -+ mount_dispatch, port); - if (nfs_version & (0x1 << 2)) -- rpc_init("mountd", MOUNTPROG, MOUNTVERS_NFSV3, -- mount_dispatch, port); -+ (void)nfs_svc_create("mountd", MOUNTPROG, MOUNTVERS_NFSV3, -+ mount_dispatch, port); - - sa.sa_handler = killer; - sigaction(SIGINT, &sa, NULL); -------------------------------------------------------------------------------- -mountd-fix-up-version-and-usag -------------------------------------------------------------------------------- -mountd: Fix up version and usage messages - -From: Chuck Lever - -Clean up: rpc.mountd is no longer known as kmountd. Use the program's -basename rather than the full pathname for the usage message. Display -a version message at start up similar to statd's. - -Signed-off-by: Chuck Lever ---- - - utils/mountd/mountd.c | 34 +++++++++++++++++++++------------- - 1 files changed, 21 insertions(+), 13 deletions(-) - - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index 8ff64c7..8694bd5 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -608,6 +608,7 @@ main(int argc, char **argv) - { - char *export_file = _PATH_EXPORTS; - char *state_dir = NFS_STATEDIR; -+ char *progname; - int foreground = 0; - int port = 0; - int descriptors = 0; -@@ -615,6 +616,12 @@ main(int argc, char **argv) - struct sigaction sa; - struct rlimit rlim; - -+ /* Set the basename */ -+ if ((progname = strrchr(argv[0], '/')) != NULL) -+ progname++; -+ else -+ progname = argv[0]; -+ - /* Parse the command line options and arguments. */ - opterr = 0; - while ((c = getopt_long(argc, argv, "o:nFd:f:p:P:hH:N:V:vrs:t:g", longopts, NULL)) != EOF) -@@ -626,8 +633,8 @@ main(int argc, char **argv) - descriptors = atoi(optarg); - if (descriptors <= 0) { - fprintf(stderr, "%s: bad descriptors: %s\n", -- argv [0], optarg); -- usage(argv [0], 1); -+ progname, optarg); -+ usage(progname, 1); - } - break; - case 'F': -@@ -643,15 +650,15 @@ main(int argc, char **argv) - ha_callout_prog = optarg; - break; - case 'h': -- usage(argv [0], 0); -+ usage(progname, 0); - break; - case 'P': /* XXX for nfs-server compatibility */ - case 'p': - port = atoi(optarg); - if (port <= 0 || port > 65535) { - fprintf(stderr, "%s: bad port number: %s\n", -- argv [0], optarg); -- usage(argv [0], 1); -+ progname, optarg); -+ usage(progname, 1); - } - break; - case 'N': -@@ -666,7 +673,7 @@ main(int argc, char **argv) - case 's': - if ((state_dir = xstrdup(optarg)) == NULL) { - fprintf(stderr, "%s: xstrdup(%s) failed!\n", -- argv[0], optarg); -+ progname, optarg); - exit(1); - } - break; -@@ -677,28 +684,28 @@ main(int argc, char **argv) - nfs_version |= 1 << (atoi (optarg) - 1); - break; - case 'v': -- printf("kmountd %s\n", VERSION); -+ printf("%s version " VERSION "\n", progname); - exit(0); - case 0: - break; - case '?': - default: -- usage(argv [0], 1); -+ usage(progname, 1); - } - - /* No more arguments allowed. */ - if (optind != argc || !(nfs_version & 0x7)) -- usage(argv [0], 1); -+ usage(progname, 1); - - if (chdir(state_dir)) { - fprintf(stderr, "%s: chdir(%s) failed: %s\n", -- argv [0], state_dir, strerror(errno)); -+ progname, state_dir, strerror(errno)); - exit(1); - } - - if (getrlimit (RLIMIT_NOFILE, &rlim) != 0) - fprintf(stderr, "%s: getrlimit (RLIMIT_NOFILE) failed: %s\n", -- argv [0], strerror(errno)); -+ progname, strerror(errno)); - else { - /* glibc sunrpc code dies if getdtablesize > FD_SETSIZE */ - if ((descriptors == 0 && rlim.rlim_cur > FD_SETSIZE) || -@@ -708,14 +715,15 @@ main(int argc, char **argv) - rlim.rlim_cur = descriptors; - if (setrlimit (RLIMIT_NOFILE, &rlim) != 0) { - fprintf(stderr, "%s: setrlimit (RLIMIT_NOFILE) failed: %s\n", -- argv [0], strerror(errno)); -+ progname, strerror(errno)); - exit(1); - } - } - } - /* Initialize logging. */ - if (!foreground) xlog_stderr(0); -- xlog_open("mountd"); -+ xlog_open(progname); -+ xlog(L_NOTICE, "Version " VERSION " starting"); - - sa.sa_handler = SIG_IGN; - sa.sa_flags = 0; -------------------------------------------------------------------------------- -mountd-auth-c-no-longer-needs- -------------------------------------------------------------------------------- -mountd: auth.c no longer needs #include xmalloc.h - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/mountd/auth.c | 4 +++- - 1 files changed, 3 insertions(+), 1 deletions(-) - - -diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c -index d63b23a..d2beb46 100644 ---- a/utils/mountd/auth.c -+++ b/utils/mountd/auth.c -@@ -10,16 +10,18 @@ - #include - #endif - -+#include - #include - #include - #include - #include - #include -+#include -+ - #include "misc.h" - #include "nfslib.h" - #include "exportfs.h" - #include "mountd.h" --#include "xmalloc.h" - #include "v4root.h" - #include "nfsrpc.h" - -------------------------------------------------------------------------------- -mountd-cache-c-no-longer-needs -------------------------------------------------------------------------------- -mountd: cache.c no longer needs #include xmalloc.h - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - utils/mountd/cache.c | 1 - - 1 files changed, 0 insertions(+), 1 deletions(-) - - -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index 255a67b..890a0fe 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -29,7 +29,6 @@ - #include "nfslib.h" - #include "exportfs.h" - #include "mountd.h" --#include "xmalloc.h" - #include "fsloc.h" - #include "pseudoflavors.h" - #include "v4root.h" -------------------------------------------------------------------------------- -libexport-a-rmtab-c-no-longer- -------------------------------------------------------------------------------- -libexport.a: rmtab.c no longer needs #include xmalloc.h - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - support/export/rmtab.c | 6 +++--- - 1 files changed, 3 insertions(+), 3 deletions(-) - - -diff --git a/support/export/rmtab.c b/support/export/rmtab.c -index ff348bd..15b6d06 100644 ---- a/support/export/rmtab.c -+++ b/support/export/rmtab.c -@@ -1,7 +1,7 @@ - /* -- * support/export/rmntab.c -+ * support/export/rmtab.c - * -- * Interface to the rmnt file. -+ * Interface to the rmtab file. - * - */ - -@@ -12,7 +12,7 @@ - #include - #include - #include --#include "xmalloc.h" -+ - #include "misc.h" - #include "nfslib.h" - #include "exportfs.h" -------------------------------------------------------------------------------- -libexport-a-xtab-c-no-longer-n -------------------------------------------------------------------------------- -libexport.a: xtab.c no longer needs #include xmalloc.h - -From: Chuck Lever - -Signed-off-by: Chuck Lever ---- - - support/export/xtab.c | 2 +- - 1 files changed, 1 insertions(+), 1 deletions(-) - - -diff --git a/support/export/xtab.c b/support/export/xtab.c -index 2a43193..e953071 100644 ---- a/support/export/xtab.c -+++ b/support/export/xtab.c -@@ -14,7 +14,7 @@ - #include - #include - #include --#include "xmalloc.h" -+ - #include "nfslib.h" - #include "exportfs.h" - #include "xio.h" -------------------------------------------------------------------------------- -mountd-squelch-unused-paramete -------------------------------------------------------------------------------- -mountd: Squelch unused parameter warnings in mountd.c - -From: Chuck Lever - -Clean up: Eliminate these compiler warnings: - -mountd.c: In function ‘mount_null_1_svc’: -mountd.c:195: warning: unused parameter ‘rqstp’ -mountd.c:195: warning: unused parameter ‘argp’ -mountd.c:195: warning: unused parameter ‘resp’ -mountd.c: In function ‘mount_dump_1_svc’: -mountd.c:213: warning: unused parameter ‘argp’ -mountd.c: In function ‘mount_umnt_1_svc’: -mountd.c:224: warning: unused parameter ‘resp’ -mountd.c: In function ‘mount_umntall_1_svc’: -mountd.c:248: warning: unused parameter ‘argp’ -mountd.c:248: warning: unused parameter ‘resp’ -mountd.c: In function ‘mount_export_1_svc’: -mountd.c:258: warning: unused parameter ‘argp’ -mountd.c: In function ‘mount_exportall_1_svc’: -mountd.c:269: warning: unused parameter ‘argp’ - -Signed-off-by: Chuck Lever ---- - - utils/mountd/mountd.c | 19 +++++++++++++------ - 1 files changed, 13 insertions(+), 6 deletions(-) - - -diff --git a/utils/mountd/mountd.c b/utils/mountd/mountd.c -index 8694bd5..d060286 100644 ---- a/utils/mountd/mountd.c -+++ b/utils/mountd/mountd.c -@@ -192,7 +192,9 @@ sig_hup (int sig) - } - - bool_t --mount_null_1_svc(struct svc_req *rqstp, void *argp, void *resp) -+mount_null_1_svc(__attribute__((unused)) struct svc_req *rqstp, -+ __attribute__((unused)) void *argp, -+ __attribute__((unused)) void *resp) - { - return 1; - } -@@ -210,7 +212,8 @@ mount_mnt_1_svc(struct svc_req *rqstp, dirpath *path, fhstatus *res) - } - - bool_t --mount_dump_1_svc(struct svc_req *rqstp, void *argp, mountlist *res) -+mount_dump_1_svc(struct svc_req *rqstp, __attribute__((unused)) void *argp, -+ mountlist *res) - { - struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - -@@ -221,7 +224,8 @@ mount_dump_1_svc(struct svc_req *rqstp, void *argp, mountlist *res) - } - - bool_t --mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp) -+mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, -+ __attribute__((unused)) void *resp) - { - struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - nfs_export *exp; -@@ -245,7 +249,8 @@ mount_umnt_1_svc(struct svc_req *rqstp, dirpath *argp, void *resp) - } - - bool_t --mount_umntall_1_svc(struct svc_req *rqstp, void *argp, void *resp) -+mount_umntall_1_svc(struct svc_req *rqstp, __attribute__((unused)) void *argp, -+ __attribute__((unused))void *resp) - { - /* Reload /etc/xtab if necessary */ - auth_reload(); -@@ -255,7 +260,8 @@ mount_umntall_1_svc(struct svc_req *rqstp, void *argp, void *resp) - } - - bool_t --mount_export_1_svc(struct svc_req *rqstp, void *argp, exports *resp) -+mount_export_1_svc(struct svc_req *rqstp, __attribute__((unused)) void *argp, -+ exports *resp) - { - struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - -@@ -266,7 +272,8 @@ mount_export_1_svc(struct svc_req *rqstp, void *argp, exports *resp) - } - - bool_t --mount_exportall_1_svc(struct svc_req *rqstp, void *argp, exports *resp) -+mount_exportall_1_svc(struct svc_req *rqstp, __attribute__((unused)) void *argp, -+ exports *resp) - { - struct sockaddr *sap = nfs_getrpccaller(rqstp->rq_xprt); - -------------------------------------------------------------------------------- -mountd-make-e_fsid-unsigned -------------------------------------------------------------------------------- -mountd: Make e_fsid unsigned - -From: Chuck Lever - -Eliminate this compiler warning: - -cache.c: In function ‘nfsd_fh’: -cache.c:441: warning: comparison between signed and unsigned integer -expressions - -Signed-off-by: Chuck Lever ---- - - support/include/nfslib.h | 3 ++- - support/nfs/cacheio.c | 5 +++++ - support/nfs/exports.c | 2 +- - utils/exportfs/exportfs.c | 2 +- - utils/mountd/cache.c | 2 +- - 5 files changed, 10 insertions(+), 4 deletions(-) - - -diff --git a/support/include/nfslib.h b/support/include/nfslib.h -index edd3b32..7965e42 100644 ---- a/support/include/nfslib.h -+++ b/support/include/nfslib.h -@@ -83,7 +83,7 @@ struct exportent { - int e_nsquids; - int * e_sqgids; - int e_nsqgids; -- int e_fsid; -+ unsigned int e_fsid; - char * e_mountpoint; - int e_fslocmethod; - char * e_fslocdata; -@@ -145,6 +145,7 @@ struct nfs_fh_len * getfh_size(const struct sockaddr_in *sin, - void qword_print(FILE *f, char *str); - void qword_printhex(FILE *f, char *str, int slen); - void qword_printint(FILE *f, int num); -+void qword_printuint(FILE *f, unsigned int num); - int qword_eol(FILE *f); - int readline(int fd, char **buf, int *lenp); - int qword_get(char **bpp, char *dest, int bufsize); -diff --git a/support/nfs/cacheio.c b/support/nfs/cacheio.c -index 6a6ed5a..7966005 100644 ---- a/support/nfs/cacheio.c -+++ b/support/nfs/cacheio.c -@@ -148,6 +148,11 @@ void qword_printint(FILE *f, int num) - fprintf(f, "%d ", num); - } - -+void qword_printuint(FILE *f, unsigned int num) -+{ -+ fprintf(f, "%u ", num); -+} -+ - int qword_eol(FILE *f) - { - int err; -diff --git a/support/nfs/exports.c b/support/nfs/exports.c -index 1aaebf4..5e7cc0c 100644 ---- a/support/nfs/exports.c -+++ b/support/nfs/exports.c -@@ -250,7 +250,7 @@ putexportent(struct exportent *ep) - fprintf(fp, "%sacl,", (ep->e_flags & NFSEXP_NOACL)? - "no_" : ""); - if (ep->e_flags & NFSEXP_FSID) { -- fprintf(fp, "fsid=%d,", ep->e_fsid); -+ fprintf(fp, "fsid=%u,", ep->e_fsid); - } - if (ep->e_uuid) - fprintf(fp, "fsid=%s,", ep->e_uuid); -diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c -index 5702864..0856079 100644 ---- a/utils/exportfs/exportfs.c -+++ b/utils/exportfs/exportfs.c -@@ -550,7 +550,7 @@ dump(int verbose) - if (ep->e_flags & NFSEXP_NOACL) - c = dumpopt(c, "no_acl"); - if (ep->e_flags & NFSEXP_FSID) -- c = dumpopt(c, "fsid=%d", ep->e_fsid); -+ c = dumpopt(c, "fsid=%u", ep->e_fsid); - if (ep->e_uuid) - c = dumpopt(c, "fsid=%s", ep->e_uuid); - if (ep->e_mountpoint) -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index 890a0fe..2f512f7 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -599,7 +599,7 @@ static int dump_to_cache(FILE *f, char *domain, char *path, struct exportent *ex - qword_printint(f, exp->e_flags & flag_mask); - qword_printint(f, exp->e_anonuid); - qword_printint(f, exp->e_anongid); -- qword_printint(f, exp->e_fsid); -+ qword_printuint(f, exp->e_fsid); - write_fsloc(f, exp, path); - write_secinfo(f, exp, flag_mask); - if (exp->e_uuid == NULL || different_fs) { -------------------------------------------------------------------------------- -mountd-squelch-compiler-warnin-0 -------------------------------------------------------------------------------- -mountd: Squelch compiler warnings in cache.c - -From: Chuck Lever - -Clean up: Eliminate these compiler warnings: - -cache.c: In function ‘nfsd_fh’: -cache.c:441: warning: comparison between signed and unsigned integer -expressions -cache.c: At top level: -cache.c:713: warning: missing initializer -cache.c:713: warning: (near initialization for ‘cachelist[0].f’) -cache.c:714: warning: missing initializer -cache.c:714: warning: (near initialization for ‘cachelist[1].f’) -cache.c:715: warning: missing initializer -cache.c:715: warning: (near initialization for ‘cachelist[2].f’) -cache.c:716: warning: missing initializer -cache.c:716: warning: (near initialization for ‘cachelist[3].f’) -cache.c:717: warning: missing initializer -cache.c:717: warning: (near initialization for ‘cachelist[4].f’) -cache.c: In function ‘cache_export_ent’: -cache.c:788: warning: comparison between signed and unsigned integer -expressions -cache.c:808: warning: comparison between signed and unsigned integer -expressions - -Signed-off-by: Chuck Lever ---- - - utils/mountd/cache.c | 26 +++++++++++++++++++------- - 1 files changed, 19 insertions(+), 7 deletions(-) - - -diff --git a/utils/mountd/cache.c b/utils/mountd/cache.c -index 2f512f7..9b71521 100644 ---- a/utils/mountd/cache.c -+++ b/utils/mountd/cache.c -@@ -747,11 +747,23 @@ struct { - void (*cache_handle)(FILE *f); - FILE *f; - } cachelist[] = { -- { "auth.unix.ip", auth_unix_ip}, -- { "auth.unix.gid", auth_unix_gid}, -- { "nfsd.export", nfsd_export}, -- { "nfsd.fh", nfsd_fh}, -- { NULL, NULL } -+ { -+ .cache_name = "auth.unix.ip", -+ .cache_handle = auth_unix_ip, -+ }, -+ { -+ .cache_name = "auth.unix.gid", -+ .cache_handle = auth_unix_gid, -+ }, -+ { -+ .cache_name = "nfsd.export", -+ .cache_handle = nfsd_export, -+ }, -+ { -+ .cache_name = "nfsd.fh", -+ .cache_handle = nfsd_fh, -+ }, -+ { NULL, NULL, NULL }, - }; - - extern int manage_gids; -@@ -821,8 +833,8 @@ int cache_export_ent(char *domain, struct exportent *exp, char *path) - * and export them with the same options - */ - struct stat stb; -- int l = strlen(exp->e_path); -- int dev; -+ size_t l = strlen(exp->e_path); -+ dev_t dev; - - if (strlen(path) <= l || path[l] != '/' || - strncmp(exp->e_path, path, l) != 0) -------------------------------------------------------------------------------- -mountd-squelch-compiler-warnin -------------------------------------------------------------------------------- -mountd: Squelch compiler warning in fsloc.c - -From: Chuck Lever - -Clean up: Eliminate this compiler warning: - -fsloc.c: In function ‘replicas_lookup’: -fsloc.c:149: warning: unused parameter ‘key’ - -I have a nagging sense that @key will be used at some point, so I'm -leaving it in. - -Signed-off-by: Chuck Lever ---- - - utils/mountd/fsloc.c | 3 ++- - 1 files changed, 2 insertions(+), 1 deletions(-) - - -diff --git a/utils/mountd/fsloc.c b/utils/mountd/fsloc.c -index 5b094b0..dcbe62a 100644 ---- a/utils/mountd/fsloc.c -+++ b/utils/mountd/fsloc.c -@@ -146,7 +146,8 @@ static struct servers *method_list(char *data) - } - - /* Returns appropriately filled struct servers, or NULL if had a problem */ --struct servers *replicas_lookup(int method, char *data, char *key) -+struct servers *replicas_lookup(int method, char *data, -+ __attribute__((unused)) char *key) - { - struct servers *sp=NULL; - switch(method) { -------------------------------------------------------------------------------- -mountd-update-mountd-exportfs- -------------------------------------------------------------------------------- -mountd: Update mountd/exportfs man pages to reflect IPv6 changes - -From: Chuck Lever - -Document IPv6 support in rpc.mountd and exportfs, and clarify existing -language in the man page. - -Clean up: Use bold consistently for program names, and italics -consistently for file names. Use "rpc.mountd" consistently as the -name of the mountd daemon. - -Signed-off-by: Chuck Lever ---- - - utils/exportfs/exportfs.man | 281 ++++++++++++++++++++++--------------------- - utils/exportfs/exports.man | 70 +++++++---- - utils/mountd/mountd.man | 240 ++++++++++++++++++++++++------------- - 3 files changed, 342 insertions(+), 249 deletions(-) - - -diff --git a/utils/exportfs/exportfs.man b/utils/exportfs/exportfs.man -index c7b230a..9839ba5 100644 ---- a/utils/exportfs/exportfs.man -+++ b/utils/exportfs/exportfs.man -@@ -1,11 +1,11 @@ -+.\"@(#)exportfs.8" - .\" --.\" exportfs(8) --.\" - .\" Copyright (C) 1995 Olaf Kirch - .\" Modifications 1999-2003 Neil Brown --.TH exportfs 8 "18 July 2003" -+.\" -+.TH exportfs 8 "31 December 2009" - .SH NAME --exportfs \- maintain list of NFS exported file systems -+exportfs \- maintain table of exported NFS file systems - .SH SYNOPSIS - .BI "/usr/sbin/exportfs [-avi] [-o " "options,.." "] [" "client:/path" " ..] - .br -@@ -18,65 +18,68 @@ exportfs \- maintain list of NFS exported file systems - .BI "/usr/sbin/exportfs -f" - .br - .SH DESCRIPTION -+An NFS server maintains a table of local physical file systems -+that are accessible to NFS clients. -+Each file system in this table is referred to as an -+.IR "exported file system" , -+or -+.IR export , -+for short. -+.PP - The - .B exportfs --command is used to maintain the current table of exported file systems for --NFS. This list is kept in a separate file named --.BR /var/lib/nfs/etab --which is read by --.B mountd --when a remote host requests access to mount a file tree, and parts of --the list which are active are kept in the kernel's export table. --.P --Normally this --.B etab --file is initialized with the list of all file systems named in --.B /etc/exports -+command maintains the current table of exports for the NFS server. -+The master export table is kept in a file named -+.IR /var/lib/nfs/etab . -+This file is read by -+.B rpc.mountd -+when a client sends an NFS MOUNT request. -+.PP -+Normally the master export table is initialized with the contents of -+.I /etc/exports - by invoking - .BR "exportfs -a" . --.P --However, administrators can choose to add and delete individual file systems --without modifying --.B /etc/exports --using --.BR exportfs . --.P -+However, a system administrator can choose to add or delete -+exports without modifying -+.I /etc/exports -+by using the -+.B exportfs -+command. -+.PP - .B exportfs --and it's partner program --.B mountd --work in one of two modes, a legacy mode which applies to 2.4 and -+and its partner program -+.B rpc.mountd -+work in one of two modes: a legacy mode which applies to 2.4 and - earlier versions of the Linux kernel, and a new mode which applies to --2.6 and later versions providing the -+2.6 and later versions, providing the - .B nfsd - virtual filesystem has been mounted at --.B /proc/fs/nfsd -+.I /proc/fs/nfsd - or --.BR /proc/fs/nfs . --If this filesystem is not mounted in 2.6, the legacy mode is used. --.P -+.IR /proc/fs/nfs . -+On 2.6 kernels, if this filesystem is not mounted, the legacy mode is used. -+.PP - In the new mode, - .B exportfs --does not give any information to the kernel but only provides it to --.B mountd -+does not give any information to the kernel, but provides it only to -+.B rpc.mountd - through the --.B /var/lib/nfs/etab -+.I /var/lib/nfs/etab - file. --.B mountd --will listen to requests from the kernel and will provide information --as needed. --.P -+.B rpc.mountd -+then manages kernel requests for information about exports, as needed. -+.PP - In the legacy mode, --any export requests which identify a specific host (rather than a --subnet or netgroup etc) are entered directly into the kernel's export --table as well as being written to --.BR /var/lib/nfs/etab . --Further, any mount points listed in --.B /var/lib/nfs/rmtab -+exports which identify a specific host, rather than a subnet or netgroup, -+are entered directly into the kernel's export table, -+as well as being written to -+.IR /var/lib/nfs/etab . -+Further, exports listed in -+.I /var/lib/nfs/rmtab - which match a non host-specific export request will cause an - appropriate export entry for the host given in --.B rmtab --to be entered --into the kernel's export table. -+.I rmtab -+to be added to the kernel's export table. - .SH OPTIONS - .TP - .B -a -@@ -84,163 +87,167 @@ Export or unexport all directories. - .TP - .BI "-o " options,... - Specify a list of export options in the same manner as in --.BR exports(5) . -+.BR exports (5). - .TP - .B -i - Ignore the --.B /etc/exports --file, so that only default options and options given on the command --line are used. -+.I /etc/exports -+file. Only default options and options given on the command line are used. - .TP - .B -r --Reexport all directories. It synchronizes /var/lib/nfs/etab --with /etc/exports. It removes entries in /var/lib/nfs/etab --which are deleted from /etc/exports, and remove any entries from the -+Reexport all directories, synchronizing -+.I /var/lib/nfs/etab -+with -+.IR /etc/exports . -+This option removes entries in -+.I /var/lib/nfs/etab -+which have been deleted from -+.I /etc/exports, and removes any entries from the - kernel export table which are no longer valid. - .TP - .B -u - Unexport one or more directories. - .TP - .B -f --In 'new' mode, flush everything out of the kernels export table. Any --clients that are active will get new entries added by --.B mountd --when they make their next request. -+If -+.I /proc/fs/nfsd -+or -+.I /proc/fs/nfs -+is mounted, flush everything out of the kernel's export table. -+Fresh entries for active clients are added to the kernel's export table by -+.B rpc.mountd -+when they make their next NFS mount request. - .TP - .B -v - Be verbose. When exporting or unexporting, show what's going on. When - displaying the current export list, also display the list of export - options. - .SH DISCUSSION --.\" -------------------- Exporting Directories -------------------- - .SS Exporting Directories --The first synopsis shows how to invoke the command when adding new --entries to the export table. When using -+The first synopsis shows how to invoke -+.B exportfs -+when adding new entries to the export table. When using - .BR "exportfs -a" , --all directories in --.B exports(5) -+all exports listed in -+.I /etc/exports - are added to --.B etab --and the resulting list is pushed into the kernel. --.P -+.IR /var/lib/nfs/etab . -+The kernel's export table is also updated as needed. -+.PP - The - .I host:/path --argument specifies the directory to export along with the host or hosts to --export it to. All formats described in -+argument specifies a local directory to export, -+along with the client or clients who are permitted to access it. -+See - .B exports(5) --are supported; to export a directory to the world, simply specify -+for a description of supported options and access list formats. -+To export a directory to the world, simply specify - .IR :/path . --.P -+.PP - The export options for a particular host/directory pair derive from --several sources. There is a set of default options which can be overridden by --entries in --.B /etc/exports --(unless the --.B -i --option is given). --In addition, the administrator may override any options from these sources --using the -+several sources. -+The default export options are -+.BR sync,ro,root_squash,wdelay . -+These can be overridden by entries in -+.IR /etc/exports . -+.PP -+A system administrator may override options from these sources using the - .B -o --argument which takes a comma-separated list of options in the same fashion -+command-line option on -+.BR exportfs . -+This option takes a comma-separated list of options in the same fashion - as one would specify them in --.BR exports(5) . --Thus, -+.IR /etc/exports . -+In this way - .B exportfs --can also be used to modify the export options of an already exported --directory. --.P --Modifications of the kernel export table used by --.B nfsd(8) --take place immediately after parsing the command line and updating the --.B etab --file. --.P --The default export options are --.BR sync,ro,root_squash,wdelay . --.\" -------------------- Unexporting Directories ------------------ -+can be used to modify the export options of an already exported directory. - .SS Unexporting Directories - The third synopsis shows how to unexported a currently exported directory. - When using - .BR "exportfs -ua" , - all entries listed in --.B etab -+.I /var/lib/nfs/etab - are removed from the kernel export tables, and the file is cleared. This - effectively shuts down all NFS activity. --.P --To remove an export to a host, specify a -+.PP -+To remove an export, specify a - .I host:/path - pair. This deletes the specified entry from --.B etab -+.I /var/lib/nfs/etab - and removes the corresponding kernel entry (if any). --To remove one or more exports to several hosts, use --.BR "exportfs -ua" . --.P --.\" -------------------- Dumping the Export Table ----------------- -+.PP - .SS Dumping the Export Table - Invoking - .B exportfs --without further options shows the current list of exported file systems. --When giving the -+without options shows the current list of exported file systems. -+Adding the - .B -v --option, the list of flags pertaining to each export are shown in addition. --.\" -------------------- EXAMPLES --------------------------------- -+option causes -+.B exportfs -+to display the export options for each export. - .SH EXAMPLES - The following adds all directories listed in --.B /etc/exports -+.I /etc/exports - to --.B /var/lib/nfs/etab -+.I /var/lib/nfs/etab - and pushes the resulting export entries into the kernel: --.P -+.PP - .nf - .B "# exportfs -a - .fi --.P -+.PP - To export the --.B /usr/tmp -+.I /usr/tmp - directory to host - .BR django , --allowing asynchronous writes, one would do this: --.P -+allowing insecure file locking requests from clients: -+.PP - .nf --.B "# exportfs -o async django:/usr/tmp -+.B "# exportfs -o insecure_locks django:/usr/tmp - .fi --.P -+.PP - To unexport the --.B /usr/tmp -+.I /usr/tmp - directory: --.P -+.PP - .nf - .B "# exportfs -u django:/usr/tmp - .fi --.P --To unexport all the directories listed in --.B /etc/exports: --.P -+.PP -+To unexport all exports listed in -+.IR /etc/exports : -+.PP - .nf - .B "# exportfs -au - .fi --.\" -------------------- DEPENDENCIES ----------------------------- --.SH DEPENDENCIES --Exporting to IP networks, DNS and NIS domains does not enable clients --from these groups to access NFS immediately; rather, these sorts of --exports are hints to --.B mountd(8) -+.SH USAGE NOTES -+Exporting to IP networks or DNS and NIS domains does not enable clients -+from these groups to access NFS immediately. -+Rather, these sorts of exports are hints to -+.BR rpc.mountd (8) - to grant any mount requests from these clients. --This is usually not a big problem, because any existing mounts are preserved --in --.B rmtab -+This is usually not a problem, because any existing mounts are preserved in -+.I rmtab - across reboots. --.P -+.PP - When unexporting a network or domain entry, any current exports to members - of this group will be checked against the remaining valid exports and - if they themselves are no longer valid they will be removed. --.P --.\" -------------------- SEE ALSO -------------------------------- -+.SH FILES -+.TP 2.5i -+.I /etc/exports -+input file listing exports, export options, and access control lists -+.TP 2.5i -+.I /var/lib/nfs/etab -+master table of exports -+.TP 2.5i -+.I /var/lib/nfs/rmtab -+table of clients accessing server's exports - .SH SEE ALSO --.BR exports(5) ", " mountd(8) --.\" -------------------- AUTHOR ---------------------------------- -+.BR exports (5), -+.BR rpc.mountd (8), -+.BR netgroup (5) - .SH AUTHORS --Olaf Kirch, -+Olaf Kirch - .br --Neil Brown, -- -+Neil Brown -diff --git a/utils/exportfs/exports.man b/utils/exportfs/exports.man -index ea28ca8..90d2cf2 100644 ---- a/utils/exportfs/exports.man -+++ b/utils/exportfs/exports.man -@@ -1,18 +1,22 @@ --.TH EXPORTS 5 "4 March 2005" "Linux" "Linux File Formats Manual" -+.\"@(#)exports.5" -+.\" -+.TH exports 5 "31 December 2009" - .SH NAME --exports \- NFS file systems being exported (for Kernel based NFS) --.SH SYNOPSIS --.B /etc/exports -+exports \- NFS server export table - .SH DESCRIPTION - The file - .I /etc/exports --serves as the access control list for file systems which may be --exported to NFS clients. It is used by --.IR exportfs (8) -+contains a table of local physical file systems on an NFS server -+that are accessible to NFS clients. -+The contents of the file are maintained by the server's system -+administrator. -+.PP -+Each file system in this table has a list of options and an -+access control list. -+The table is used by -+.BR exportfs (8) - to give information to --.IR mountd (8) --and to the kernel based NFS file server daemon --.IR nfsd (8). -+.BR mountd (8). - .PP - The file format is similar to the SunOS - .I exports -@@ -34,7 +38,9 @@ double quotes. You can also specify spaces or other unusual character in - the export name using a backslash followed by the character code as three - octal digits. - .PP --To apply changes to this file, run exportfs \-ra or restart the NFS server. -+To apply changes to this file, run -+.BR exportfs \-ra -+or restart the NFS server. - .PP - .SS Machine Name Formats - NFS clients may be specified in a number of ways: -@@ -61,9 +67,10 @@ simultaneously. This is done by specifying an IP address and netmask pair - as - .IR address/netmask - where the netmask can be specified in dotted-decimal format, or as a --contiguous mask length (for example, either `/255.255.252.0' or `/22' appended --to the network base address result in identical subnetworks with 10 bits of --host). Wildcard characters generally do not work on IP addresses, though they -+contiguous mask length. -+For example, either `/255.255.252.0' or `/22' appended -+to the network base IPv4 address results in identical subnetworks with 10 bits of -+host. Wildcard characters generally do not work on IP addresses, though they - may work by accident when reverse DNS lookups fail. - '''.TP - '''.B =public -@@ -106,7 +113,7 @@ preceding sec= option. The only options that are permitted to vary in - this way are ro, rw, no_root_squash, root_squash, and all_squash. - .PP - .SS General Options --.IR exportfs -+.BR exportfs - understands the following export options: - .TP - .IR secure "\*d -@@ -144,7 +151,8 @@ default. In all releases after 1.0.0, - is the default, and - .I async - must be explicitly requested if needed. --To help make system administrators aware of this change, 'exportfs' -+To help make system administrators aware of this change, -+.B exportfs - will issue a warning if neither - .I sync - nor -@@ -246,7 +254,7 @@ If you genuinely require subtree checking, you should explicitly put - that option in the - .B exports - file. If you put neither option, --.I exportfs -+.B exportfs - will warn you that the change is pending. - - .TP -@@ -272,7 +280,9 @@ or - .TP - .IR no_acl - On some specially patched kernels, and when exporting filesystems that --support ACLs, this option tells nfsd not to reveal ACLs to clients, so -+support ACLs, this option tells -+.B nfsd -+not to reveal ACLs to clients, so - they will see only a subset of actual permissions on the given file - system. This option is safe for filesystems used by NFSv2 clients and - old NFSv3 clients that perform access decisions locally. Current -@@ -381,7 +391,7 @@ of the filesystem must be handled elsewhere.) - - .SS User ID Mapping - .PP --.I nfsd -+.B nfsd - bases its access control to files on the server machine on the uid and - gid provided in each NFS RPC request. The normal behavior a user would - expect is that she can access her files on the server just as she would -@@ -399,11 +409,11 @@ and can be turned off with - .IR no_root_squash . - .PP - By default, --'''.I nfsd -+'''.B nfsd - '''tries to obtain the anonymous uid and gid by looking up user - '''.I nobody - '''in the password file at startup time. If it isn't found, a uid and gid --.I exportfs -+.B exportfs - chooses a uid and gid - of 65534 for squashed access. These values can also be overridden by - the -@@ -411,7 +421,7 @@ the - options. - '''.PP - '''In addition to this, --'''.I nfsd -+'''.B nfsd - '''lets you specify arbitrary uids and gids that should be mapped to user - '''nobody as well. - Finally, you can map all user requests to the -@@ -478,7 +488,7 @@ all three mounts with the `sync' option enabled. - '''access to the private directory. - '''.SH CAVEATS - '''Unlike other NFS server implementations, this --'''.I nfsd -+'''.B nfsd - '''allows you to export both a directory and a subdirectory thereof to - '''the same host, for instance - '''.IR /usr " and " /usr/X11R6 . -@@ -499,7 +509,15 @@ all three mounts with the `sync' option enabled. - .BR showmount (8). - '''.SH DIAGNOSTICS - '''An error parsing the file is reported using syslogd(8) as level NOTICE from --'''a DAEMON whenever nfsd(8) or mountd(8) is started up. Any unknown -+'''a DAEMON whenever -+'''.BR nfsd (8) -+'''or -+'''.BR mountd (8) -+'''is started up. Any unknown - '''host is reported at that time, but often not all hosts are not yet known --'''to named(8) at boot time, thus as hosts are found they are reported --'''with the same syslogd(8) parameters. -+'''to -+'''.BR named (8) -+'''at boot time, thus as hosts are found they are reported -+'''with the same -+'''.BR syslogd (8) -+'''parameters. -diff --git a/utils/mountd/mountd.man b/utils/mountd/mountd.man -index bfa06e0..f337590 100644 ---- a/utils/mountd/mountd.man -+++ b/utils/mountd/mountd.man -@@ -1,9 +1,9 @@ --.\" --.\" mountd(8) -+.\"@(#)rpc.mountd.8" - .\" - .\" Copyright (C) 1999 Olaf Kirch - .\" Modified by Paul Clements, 2004. --.TH rpc.mountd 8 "31 Aug 2004" -+.\" -+.TH rpc.mountd 8 "31 Dec 2009" - .SH NAME - rpc.mountd \- NFS mount daemon - .SH SYNOPSIS -@@ -11,48 +11,73 @@ rpc.mountd \- NFS mount daemon - .SH DESCRIPTION - The - .B rpc.mountd --program implements the NFS mount protocol. When receiving a MOUNT --request from an NFS client, it checks the request against the list of --currently exported file systems. If the client is permitted to mount --the file system, --.B rpc.mountd --obtains a file handle for requested directory and returns it to --the client. --.SS Exporting NFS File Systems --Making file systems available to NFS clients is called --.IR exporting . --.P --Usually, a file system and the hosts it should be made available to --are listed in the --.B /etc/exports --file, and invoking --.B exportfs -a --whenever the system is booted. The -+daemon implements the server side of the NFS MOUNT protocol, -+an NFS side protocol used by NFS version 2 [RFC1094] and NFS version 3 [RFC1813]. -+.PP -+An NFS server maintains a table of local physical file systems -+that are accessible to NFS clients. -+Each file system in this table is referred to as an -+.IR "exported file system" , -+or -+.IR export , -+for short. -+.PP -+Each file system in the export table has an access control list. -+.B rpc.mountd -+uses these access control lists to determine -+whether an NFS client is permitted to access a given file system. -+For details on how to manage your NFS server's export table, see the -+.BR exports (5) -+and - .BR exportfs (8) --command makes export information available to both the kernel NFS --server module and the --.B rpc.mountd --daemon. --.P --Alternatively, you can export individual directories temporarily --using --.BR exportfs 's --.IB host : /directory --syntax. -+man pages. -+.SS Mounting exported NFS File Systems -+The NFS MOUNT protocol has several procedures. -+The most important of these are -+MNT (mount an export) and -+UMNT (unmount an export). -+.PP -+A MNT request has two arguments: an explicit argument that -+contains the pathname of the root directory of the export to be mounted, -+and an implicit argument that is the sender's IP address. -+.PP -+When receiving a MNT request from an NFS client, -+.B rpc.mountd -+checks both the pathname and the sender's IP address against its export table. -+If the sender is permitted to access the requested export, -+.B rpc.mountd -+returns an NFS file handle for the export's root directory to the client. -+The client can then use the root file handle and NFS LOOKUP requests -+to navigate the directory structure of the export. - .SS The rmtab File --For every mount request received from an NFS client, --.B rpc.mountd --adds an entry to the --.B /var/lib/nfs/rmtab --file. When receiving an unmount request, that entry is removed. --.P --However, this file is mostly ornamental. One, the client can continue --to use the file handle even after calling --.B rpc.mountd 's --UMOUNT procedure. And two, if a client reboots without notifying --.B rpc.mountd , --a stale entry will remain in --.BR rmtab . -+The -+.B rpc.mountd -+daemon registers every successful MNT request by adding an entry to the -+.I /var/lib/nfs/rmtab -+file. -+When receivng a UMNT request from an NFS client, -+.B rpc.mountd -+simply removes the matching entry from -+.IR /var/lib/nfs/rmtab , -+as long as the access control list for that export allows that sender -+to access the export. -+.PP -+Clients can discover the list of file systems an NFS server is -+currently exporting, or the list of other clients that have mounted -+its exports, by using the -+.BR showmount (8) -+command. -+.BR showmount (8) -+uses other procedures in the NFS MOUNT protocol to report information -+about the server's exported file systems. -+.PP -+Note, however, that there is little to guarantee that the contents of -+.I /var/lib/nfs/rmtab -+are accurate. -+A client may continue accessing an export even after invoking UMNT. -+If the client reboots without sending a UMNT request, stale entries -+remain for that client in -+.IR /var/lib/nfs/rmtab . - .SH OPTIONS - .TP - .B \-d kind " or " \-\-debug kind -@@ -94,22 +119,25 @@ Don't advertise TCP for mount. - Ignored (compatibility with unfsd??). - .TP - .B \-p " or " \-\-port num --Force -+Specifies the port number used for RPC listener sockets. -+If this option is not specified, - .B rpc.mountd --to bind to the specified port num, instead of using the random port --number assigned by the portmapper. -+chooses a random ephemeral port for each listener socket. -+.IP -+This option can be used to fix the port value of -+.BR rpc.mountd 's -+listeners when NFS MOUNT requests must traverse a firewall -+between clients and servers. - .TP - .B \-H " or " \-\-ha-callout prog --Specify a high availability callout program, which will receive callouts --for all client mount and unmount requests. This allows --.B rpc.mountd --to be used in a High Availability NFS (HA-NFS) environment. This callout is not --needed (and should not be used) with 2.6 and later kernels (instead, --mount the nfsd filesystem on --.B /proc/fs/nfsd --). --The program will be called with 4 arguments. --The first will be -+Specify a high availability callout program. -+This program receives callouts for all MOUNT and UNMOUNT requests. -+This allows -+.B rpc.mountd -+to be used in a High Availability NFS (HA-NFS) environment. -+.IP -+The callout program is run with 4 arguments. -+The first is - .B mount - or - .B unmount -@@ -118,19 +146,30 @@ The second will be the name of the client performing the mount. - The third will be the path that the client is mounting. - The last is the number of concurrent mounts that we believe the client - has of that path. -+.IP -+This callout is not needed with 2.6 and later kernels. -+Instead, mount the nfsd filesystem on -+.IR /proc/fs/nfsd . - .TP - .BI "\-s," "" " \-\-state\-directory\-path " directory --specify a directory in which to place statd state information. -+Specify a directory in which to place statd state information. - If this option is not specified the default of --.BR /var/lib/nfs -+.I /var/lib/nfs - is used. - .TP - .BI "\-r," "" " \-\-reverse\-lookup" --mountd tracks IP addresses in the rmtab, and when a DUMP request is made (by --someone running showmount -a, for instance), it returns IP addresses instead --of hostnames by default. This option causes mountd to do a reverse --lookup on each IP address and return that hostname instead. Enabling this can --have a substantial negative effect on performance in some situations. -+.B rpc.mountd -+tracks IP addresses in the -+.I rmtab -+file. When a DUMP request is made (by -+someone running -+.BR "showmount -a" , -+for instance), it returns IP addresses instead -+of hostnames by default. This option causes -+.B rpc.mountd -+to perform a reverse lookup on each IP address and return that hostname instead. -+Enabling this can have a substantial negative effect on performance -+in some situations. - .TP - .BR "\-t N" " or " "\-\-num\-threads=N" - This option specifies the number of worker threads that rpc.mountd -@@ -162,41 +201,70 @@ If you use the - flag, then the list of group ids received from the client will be - replaced by a list of group ids determined by an appropriate lookup on - the server. Note that the 'primary' group id is not affected so a --.I newgroup -+.B newgroup - command on the client will still be effective. This function requires - a Linux Kernel with version at least 2.6.21. -- - .SH TCP_WRAPPERS SUPPORT --This -+You can protect your - .B rpc.mountd --version is protected by the -+listeners using the -+.B tcp_wrapper -+library or -+.BR iptables (8). -+.PP -+Note that the - .B tcp_wrapper --library. You have to give the clients access to --.B rpc.mountd --if they should be allowed to use it. To allow connects from clients of --the .bar.com domain you could use the following line in /etc/hosts.allow: -- --mountd: .bar.com -- --You have to use the daemon name -+library supports only IPv4 networking. -+.PP -+Add the hostnames of NFS peers that are allowed to access -+.B rpc.mountd -+to -+.IR /etc/hosts.allow . -+Use the daemon name - .B mountd --for the daemon name (even if the binary has a different name). --.B Note: --hostnames used in either access file will be ignored when -+even if the -+.B rpc.mountd -+binary has a different name. -+.PP -+Hostnames used in either access file will be ignored when - they can not be resolved into IP addresses. -- --For further information please have a look at the -+For further information see the - .BR tcpd (8) - and - .BR hosts_access (5) --manual pages. -+man pages. -+.SS IPv6 and TI-RPC support -+TI-RPC is a pre-requisite for supporting NFS on IPv6. -+If TI-RPC support is built into -+.BR rpc.mountd , -+it attempts to start listeners on network transports marked 'visible' in -+.IR /etc/netconfig . -+As long as at least one network transport listener starts successfully, -+.B rpc.mountd -+will operate. -+.SH FILES -+.TP 2.5i -+.I /etc/exports -+input file for -+.BR exportfs , -+listing exports, export options, and access control lists -+.TP 2.5i -+.I /var/lib/nfs/rmtab -+table of clients accessing server's exports - .SH SEE ALSO --.BR rpc.nfsd (8), - .BR exportfs (8), - .BR exports (5), --.BR rpc.rquotad (8). --.SH FILES --.BR /etc/exports , --.BR /var/lib/nfs/xtab . -+.BR showmount (8), -+.BR rpc.nfsd (8), -+.BR rpc.rquotad (8), -+.BR nfs (5), -+.BR tcpd (8), -+.BR hosts_access (5), -+.BR iptables (8), -+.BR netconfig (5) -+.sp -+RFC 1094 - "NFS: Network File System Protocol Specification" -+.br -+RFC 1813 - "NFS Version 3 Protocol Specification" - .SH AUTHOR - Olaf Kirch, H. J. Lu, G. Allan Morris III, and a host of others. -------------------------------------------------------------------------------- -nfsd-revert-commit-b2a3cd59 -------------------------------------------------------------------------------- -nfsd: Revert commit b2a3cd59 - -From: Chuck Lever - -Enable IPv6 support in rpc.nfsd again. - -Signed-off-by: Chuck Lever ---- - - utils/nfsd/nfsd.c | 9 --------- - utils/nfsd/nfssvc.c | 9 --------- - 2 files changed, 0 insertions(+), 18 deletions(-) - - -diff --git a/utils/nfsd/nfsd.c b/utils/nfsd/nfsd.c -index 1cda1e5..650c593 100644 ---- a/utils/nfsd/nfsd.c -+++ b/utils/nfsd/nfsd.c -@@ -27,15 +27,6 @@ - #include "nfssvc.h" - #include "xlog.h" - --/* -- * IPv6 support for nfsd was finished before some of the other daemons (mountd -- * and statd in particular). That could be a problem in the future if someone -- * were to boot a kernel that supports IPv6 serving with an older nfs-utils. For -- * now, hardcode the IPv6 switch into the off position until the other daemons -- * are functional. -- */ --#undef IPV6_SUPPORTED -- - static void usage(const char *); - - static struct option longopts[] = -diff --git a/utils/nfsd/nfssvc.c b/utils/nfsd/nfssvc.c -index b8028bb..119135e 100644 ---- a/utils/nfsd/nfssvc.c -+++ b/utils/nfsd/nfssvc.c -@@ -22,15 +22,6 @@ - #include "nfslib.h" - #include "xlog.h" - --/* -- * IPv6 support for nfsd was finished before some of the other daemons (mountd -- * and statd in particular). That could be a problem in the future if someone -- * were to boot a kernel that supports IPv6 serving with an older nfs-utils. For -- * now, hardcode the IPv6 switch into the off position until the other daemons -- * are functional. -- */ --#undef IPV6_SUPPORTED -- - #define NFSD_PORTS_FILE "/proc/fs/nfsd/portlist" - #define NFSD_VERS_FILE "/proc/fs/nfsd/versions" - #define NFSD_THREAD_FILE "/proc/fs/nfsd/threads" diff --git a/nfs-utils-1.2.1-relax-insecure-option.patch b/nfs-utils-1.2.1-relax-insecure-option.patch deleted file mode 100644 index a8206ba..0000000 --- a/nfs-utils-1.2.1-relax-insecure-option.patch +++ /dev/null @@ -1,34 +0,0 @@ -From fa42ac173d1d7e37a4052471dfc15520a09f102e Mon Sep 17 00:00:00 2001 -From: Robert Gordon -Date: Mon, 16 Nov 2009 13:25:02 -0500 -Subject: [PATCH] relax insecure option on mountd - -In nfs-utils 1.2.0, I noticed that the insecure option validates that -the client port is a -subset of IPPORT_RESERVED as opposed to just validating it is a valid -reserved port. The following proposed patch would correct that issue. - -Acked-by: Jeff Layton -Signed-off-by: Robert Gordon -Signed-off-by: Steve Dickson ---- - utils/mountd/auth.c | 3 +-- - 1 files changed, 1 insertions(+), 2 deletions(-) - -diff --git a/utils/mountd/auth.c b/utils/mountd/auth.c -index 575f207..5a7ff8c 100644 ---- a/utils/mountd/auth.c -+++ b/utils/mountd/auth.c -@@ -169,8 +169,7 @@ auth_authenticate_internal(char *what, struct sockaddr_in *caller, - } - } - if (!(exp->m_export.e_flags & NFSEXP_INSECURE_PORT) && -- (ntohs(caller->sin_port) < IPPORT_RESERVED/2 || -- ntohs(caller->sin_port) >= IPPORT_RESERVED)) { -+ ntohs(caller->sin_port) >= IPPORT_RESERVED) { - *error = illegal_port; - return NULL; - } --- -1.6.5.2 - diff --git a/nfs-utils.spec b/nfs-utils.spec index 3f11065..ec67b99 100644 --- a/nfs-utils.spec +++ b/nfs-utils.spec @@ -2,7 +2,7 @@ Summary: NFS utilities and supporting clients and daemons for the kernel NFS ser Name: nfs-utils URL: http://sourceforge.net/projects/nfs Version: 1.2.1 -Release: 3.ipv6.1%{?dist} +Release: 3.ipv6.2%{?dist} Epoch: 1 # group all 32bit related archs @@ -24,8 +24,7 @@ Patch02: nfs-utils-1.1.0-exp-subtree-warn-off.patch Patch200: nfs-utils-1.2.0-v4root-rel8.patch Patch201: nfs-utils-1.2.1-nfsd-bootfail.patch -Patch300: nfs-utils-1.2.1-relax-insecure-option.patch -Patch301: nfs-utils-1.2.1-cel-ipv6.patch +Patch300: nfs-utils-1.2.1-cel-ipv6.patch Group: System Environment/Daemons Provides: exportfs = %{epoch}:%{version}-%{release} @@ -81,7 +80,6 @@ This package also contains the mount.nfs and umount.nfs program. %patch201 -p1 %patch300 -p1 -%patch301 -p1 # Remove .orig files find . -name "*.orig" | xargs rm -f @@ -254,12 +252,9 @@ fi %attr(4755,root,root) /sbin/umount.nfs4 %changelog -* Thu Dec 3 2009 Jeff Layton 1.2.1-3.ipv6.1 +* Fri Dec 4 2009 Jeff Layton 1.2.1-3.ipv6.2 - remove patches to fix statd/sm-notify paths in old statd -- add patch to relax "insecure" export option (so that later patches apply - cleanly) -- add patches from Chuck Lever's tree to support IPv6 in statd, mountd and - exportfs +- add patches from Chuck Lever's tree to support IPv6 in statd and mount.nfs - enable IPv6 during configuration * Thu Nov 12 2009 Steve Dickson 1.2.1-3