From: Chuck Lever Date: Tue, 22 Jun 2010 17:06:40 +0000 (-0400) Subject: libexport.a: Replace matchhostname() X-Git-Tag: nfs-utils-1-2-3-rc4~2 X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=commitdiff_plain;h=21015ace7d0a356b24a57540ccfeb41d941e78ed 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 Signed-off-by: Steve Dickson --- 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 0070b54..edc1625 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -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, ...)