X-Git-Url: https://git.decadent.org.uk/gitweb/?p=nfs-utils.git;a=blobdiff_plain;f=utils%2Fexportfs%2Fexportfs.c;h=12e8bf112dd414259ffec3d749497125c5c469b2;hp=8496d825cd28bd3a1932535e6b847086e3d9fb68;hb=140468c2968472e871b972e400f58ad659458a2d;hpb=26fd34002585e6a5aa09204b0b01d836fa83dcf3 diff --git a/utils/exportfs/exportfs.c b/utils/exportfs/exportfs.c index 8496d82..12e8bf1 100644 --- a/utils/exportfs/exportfs.c +++ b/utils/exportfs/exportfs.c @@ -25,7 +25,9 @@ #include #include #include +#include +#include "sockaddr.h" #include "misc.h" #include "nfslib.h" #include "exportfs.h" @@ -40,6 +42,7 @@ static void error(nfs_export *exp, int err); static void usage(const char *progname); static void validate_export(nfs_export *exp); static int matchhostname(const char *hostname1, const char *hostname2); +static void export_d_read(const char *dname); int main(int argc, char **argv) @@ -126,8 +129,10 @@ main(int argc, char **argv) return 0; } } - if (f_export && ! f_ignore) + if (f_export && ! f_ignore) { export_read(_PATH_EXPORTS); + export_d_read(_PATH_EXPORTS_D); + } if (f_export) { if (f_all) export_all(f_verbose); @@ -245,7 +250,7 @@ static void exportfs(char *arg, char *options, int verbose) { struct exportent *eep; - nfs_export *exp; + nfs_export *exp = NULL; struct addrinfo *ai = NULL; char *path; char *hname = arg; @@ -443,24 +448,34 @@ is_hostname(const char *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) +/* + * Take care to perform an explicit reverse lookup on presentation + * addresses. Otherwise we don't get a real canonical name or a + * complete list of addresses. + */ +static struct addrinfo * +address_list(const char *hostname) { - if (sa1->sa_family == sa2->sa_family) - switch (sa1->sa_family) { - case AF_INET: - return compare_sockaddrs4(sa1, sa2); - } + struct addrinfo *ai; + char *cname; + + ai = host_pton(hostname); + if (ai != NULL) { + /* @hostname was a presentation address */ + cname = host_canonname(ai->ai_addr); + freeaddrinfo(ai); + if (cname != NULL) + goto out; + } + /* @hostname was a hostname or had no reverse mapping */ + cname = strdup(hostname); + if (cname == NULL) + return NULL; - return false; +out: + ai = host_addrinfo(cname); + free(cname); + return ai; } static int @@ -479,10 +494,10 @@ matchhostname(const char *hostname1, const char *hostname2) if (!is_hostname(hostname1) || !is_hostname(hostname2)) return 0; - results1 = host_addrinfo(hostname1); + results1 = address_list(hostname1); if (results1 == NULL) goto out; - results2 = host_addrinfo(hostname2); + results2 = address_list(hostname2); if (results2 == NULL) goto out; @@ -493,7 +508,7 @@ matchhostname(const char *hostname1, const char *hostname2) 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)) { + if (nfs_compare_sockaddr(ai1->ai_addr, ai2->ai_addr)) { result = 1; break; } @@ -504,6 +519,59 @@ out: return result; } +/* Based on mnt_table_parse_dir() in + util-linux-ng/shlibs/mount/src/tab_parse.c */ +static void +export_d_read(const char *dname) +{ + int n = 0, i; + struct dirent **namelist = NULL; + + + n = scandir(dname, &namelist, NULL, versionsort); + if (n < 0) + xlog(L_NOTICE, "scandir %s: %s\n", dname, strerror(errno)); + else if (n == 0) + return; + + for (i = 0; i < n; i++) { + struct dirent *d = namelist[i]; + size_t namesz; + char fname[PATH_MAX + 1]; + int fname_len; + + + if (d->d_type != DT_UNKNOWN + && d->d_type != DT_REG + && d->d_type != DT_LNK) + continue; + if (*d->d_name == '.') + continue; + +#define _EXT_EXPORT_SIZ (sizeof(_EXT_EXPORT) - 1) + namesz = strlen(d->d_name); + if (!namesz + || namesz < _EXT_EXPORT_SIZ + 1 + || strcmp(d->d_name + (namesz - _EXT_EXPORT_SIZ), + _EXT_EXPORT)) + continue; + + fname_len = snprintf(fname, PATH_MAX +1, "%s/%s", dname, d->d_name); + if (fname_len > PATH_MAX) { + xlog(L_WARNING, "Too long file name: %s in %s\n", d->d_name, dname); + continue; + } + + export_read(fname); + } + + for (i = 0; i < n; i++) + free(namelist[i]); + free(namelist); + + return; +} + static char dumpopt(char c, char *fmt, ...) {