diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2010-06-22 13:06:40 -0400 |
---|---|---|
committer | Steve Dickson <steved@redhat.com> | 2010-06-22 16:04:53 -0400 |
commit | 21015ace7d0a356b24a57540ccfeb41d941e78ed (patch) | |
tree | 1735653057e844649f03706b35112d029cafdac7 /utils/exportfs/exportfs.c | |
parent | 22d6566d473f71e241c791a02435d414648c99e8 (diff) | |
download | nfs-utils-21015ace7d0a356b24a57540ccfeb41d941e78ed.tar.gz nfs-utils-21015ace7d0a356b24a57540ccfeb41d941e78ed.tar.xz nfs-utils-21015ace7d0a356b24a57540ccfeb41d941e78ed.zip |
libexport.a: Replace matchhostname()
So that exportfs can eventually support IPv6 addresses, copy statd's
getaddrinfo(3)-based matchhostname to exportfs, with adjustments for
dealing with export wildcards and netgroups. Until exportfs has full
IPv6 support, however, we want to ensure that IPv6 addresses continue
to remain blocked in the address comparison code used by exportfs. At
a later point we'll replace much of this with the generic functions
in sockaddr.h.
Since it contains special logic for handling wildcard and netgroups,
this function is specialized for exportfs, and does not belong in
one of the shared libraries.
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
Signed-off-by: Steve Dickson <steved@redhat.com>
Diffstat (limited to 'utils/exportfs/exportfs.c')
-rw-r--r-- | utils/exportfs/exportfs.c | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 0070b54..edc1625 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -15,6 +15,7 @@ #include <sys/vfs.h> #include <sys/stat.h> #include <unistd.h> +#include <stdbool.h> #include <stdlib.h> #include <string.h> #include <stdarg.h> @@ -36,6 +37,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) @@ -421,6 +423,82 @@ validate_export(nfs_export *exp) } } +static _Bool +is_hostname(const char *sp) +{ + if (*sp == '\0' || *sp == '@') + return false; + + for (; *sp != '\0'; sp++) { + if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/') + return false; + if (*sp == '\\' && sp[1] != '\0') + sp++; + } + + return true; +} + +static _Bool +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 _Bool +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 false; +} + +static int +matchhostname(const char *hostname1, const char *hostname2) +{ + struct addrinfo *results1 = NULL, *results2 = NULL; + struct addrinfo *ai1, *ai2; + int result = 0; + + if (strcasecmp(hostname1, hostname2) == 0) + return 1; + + /* + * Don't pass export wildcards or netgroup names to DNS + */ + if (!is_hostname(hostname1) || !is_hostname(hostname2)) + return 0; + + results1 = host_addrinfo(hostname1); + if (results1 == NULL) + goto out; + results2 = host_addrinfo(hostname2); + if (results2 == NULL) + goto out; + + if (strcasecmp(results1->ai_canonname, results2->ai_canonname) == 0) { + result = 1; + goto out; + } + + for (ai1 = results1; ai1 != NULL; ai1 = ai1->ai_next) + for (ai2 = results2; ai2 != NULL; ai2 = ai2->ai_next) + if (compare_sockaddrs(ai1->ai_addr, ai2->ai_addr)) { + result = 1; + break; + } + +out: + freeaddrinfo(results1); + freeaddrinfo(results2); + return result; +} static char dumpopt(char c, char *fmt, ...) |