X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fexportfs%2Fexportfs.c;fp=utils%2Fexportfs%2Fexportfs.c;h=edc1625a8b76ce6648624cdbfe565d1d2faf6b8a;hp=0070b544d654400f9dbafa1127423e55609c5ea0;hb=21015ace7d0a356b24a57540ccfeb41d941e78ed;hpb=22d6566d473f71e241c791a02435d414648c99e8 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, ...)