X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fexportfs%2Fexportfs.c;h=93bad32241fae7d5d0c4f7276e75f3290da5ffdf;hp=50f1e34e92eb3e93ecb4b2dc8e60819adf80c00a;hb=6d7babe6afae068e8a1054f785785d374788f5ee;hpb=3ca5879be32c4c11750e12230ff588195fff0738 diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 50f1e34..93bad32 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -12,20 +12,23 @@ #include #endif +#include +#include #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); @@ -36,6 +39,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) @@ -232,7 +236,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; @@ -245,21 +249,14 @@ 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 != NULL) { + exp = export_find(ai, path); + hname = ai->ai_canonname; + } + } else exp = export_lookup(hname, path, 0); - } if (!exp) { if (!(eep = mkexportent(hname, path, options)) || @@ -278,7 +275,7 @@ exportfs(char *arg, char *options, int verbose) validate_export(exp); out: - if (hp) free (hp); + freeaddrinfo(ai); } static void @@ -428,6 +425,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, ...)