diff options
author | neilbrown <neilbrown> | 2003-03-26 03:05:39 +0000 |
---|---|---|
committer | neilbrown <neilbrown> | 2003-03-26 03:05:39 +0000 |
commit | 16be8c20d6fe1a997d90ecb229aee6a5f092b73d (patch) | |
tree | 72625879992ba430479dd80550918facef1dfb1c /support/export | |
parent | cec295bf37b784ed6ae5674ce34b9c75d89ea0a1 (diff) | |
download | nfs-utils-neilb-devel.tar.gz |
Work towards support new cache in 2.5nfs-utils-1-1-0-pre11neilb-devel
Diffstat (limited to 'support/export')
-rw-r--r-- | support/export/client.c | 98 | ||||
-rw-r--r-- | support/export/hostname.c | 51 | ||||
-rw-r--r-- | support/export/xtab.c | 47 |
3 files changed, 195 insertions, 1 deletions
diff --git a/support/export/client.c b/support/export/client.c index 6d5d306..3db21ae 100644 --- a/support/export/client.c +++ b/support/export/client.c @@ -230,6 +230,104 @@ client_find(struct hostent *hp) } /* + * Find client name given an IP address + * This is found by gathering all known names that match that IP address, + * sorting them and joining them with '+' + * + */ +static char *add_name(char *old, char *add); + +char * +client_compose(struct in_addr addr) +{ + struct hostent *he = NULL; + char *name = NULL; + int i; + + if (clientlist[MCL_WILDCARD] || clientlist[MCL_NETGROUP]) + he = get_reliable_hostbyaddr((const char*)&addr, sizeof(addr), AF_INET); + if (he == NULL) + he = get_hostent((const char*)&addr, sizeof(addr), AF_INET); + + for (i = 0 ; i < MCL_MAXTYPES; i++) { + nfs_client *clp; + for (clp = clientlist[i]; clp ; clp = clp->m_next) { + if (!client_check(clp, he)) + continue; + name = add_name(name, clp->m_hostname); + } + } + return name; +} + +int +client_member(char *client, char *name) +{ + /* check if "client" (a ',' separated list of names) + * contains 'name' as a member + */ + int l = strlen(name); + while (*client) { + if (strncmp(client, name, l) == 0 && + (client[l] == ',' || client[l] == '\0')) + return 1; + client = strchr(client, ','); + if (client == NULL) + return 0; + client++; + } + return 0; +} + + +int +name_cmp(char *a, char *b) +{ + /* compare strings a and b, but only upto ',' in a */ + while (*a && *b && *a != ',' && *a == *b) + a++, b++; + if (!*b && (!*a || !a == ',') ) + return 0; + if (!*b) return 1; + if (!*a || *a == ',') return -1; + return *a - *b; +} + +static char * +add_name(char *old, char *add) +{ + int len = strlen(add)+2; + char *new; + char *cp; + if (old) len += strlen(old); + + new = malloc(len); + if (!new) { + free(old); + return NULL; + } + cp = old; + while (cp && *cp && name_cmp(cp, add) < 0) { + /* step cp forward over a name */ + char *e = strchr(cp, ','); + if (e) + cp = e+1; + else + cp = cp + strlen(cp); + } + strncpy(new, old, cp-old); + new[cp-old] = 0; + if (cp != old && !*cp) + strcat(new, ","); + strcat(new, add); + if (cp && *cp) { + strcat(new, ","); + strcat(new, cp); + } + return new; +} + +/* * Match a host (given its hostent record) to a client record. This * is usually called from mountd. */ diff --git a/support/export/hostname.c b/support/export/hostname.c index 299fe99..0378f35 100644 --- a/support/export/hostname.c +++ b/support/export/hostname.c @@ -16,6 +16,7 @@ #include <netinet/in.h> #include <arpa/inet.h> #include <stdlib.h> +#include <xlog.h> #ifdef TEST #define xmalloc malloc #else @@ -216,6 +217,56 @@ matchhostname (const char *h1, const char *h2) return status; } + +/* Map IP to hostname, and then map back to addr to make sure it is a + * reliable hostname + */ +struct hostent * +get_reliable_hostbyaddr(const char *addr, int len, int type) +{ + struct hostent *hp; + + char **sp; + struct hostent *forward = NULL; + char *tmpname; + + hp = gethostbyaddr(addr, len , type); + if (!hp) + return hp; + + /* must make sure the hostent is authorative. */ + + hp = hostent_dup (hp); + tmpname = xstrdup((hp)->h_name); + if (tmpname) { + forward = gethostbyname(tmpname); + free(tmpname); + } + if (forward) { + /* now make sure the "addr" is in the list */ + for (sp = forward->h_addr_list ; *sp ; sp++) { + if (memcmp(*sp, addr, forward->h_length)==0) + break; + } + + if (!*sp) { + /* it was a FAKE */ + xlog(L_WARNING, "Fake hostname %s for %s - forward lookup doesn't match reverse", + forward->h_name, inet_ntoa(*(struct in_addr*)addr)); + return NULL; + } + free (hp); + hp = hostent_dup (forward); + } + else { + /* never heard of it. misconfigured DNS? */ + xlog(L_WARNING, "Fake hostname %s for %s - forward lookup doesn't exist", + forward->h_name, inet_ntoa(*(struct in_addr*)addr)); + return NULL; + } + return hp; +} + #ifdef TEST void print_host (struct hostent *hp) diff --git a/support/export/xtab.c b/support/export/xtab.c index 3ef3661..d9265a2 100644 --- a/support/export/xtab.c +++ b/support/export/xtab.c @@ -18,6 +18,8 @@ #include "xio.h" #include "xlog.h" +static void cond_rename(char *newfile, char *oldfile); + static int xtab_read(char *xtab, int is_export) { @@ -104,7 +106,7 @@ xtab_write(char *xtab, char *xtabtmp, int is_export) } endexportent(); - rename(xtabtmp, xtab); + cond_rename(xtabtmp, xtab); xfunlock(lockid); @@ -142,3 +144,46 @@ xtab_append(nfs_export *exp) exp->m_xtabent = 1; } +/* + * rename newfile onto oldfile unless + * they are identical + */ +static void cond_rename(char *newfile, char *oldfile) +{ + int nfd, ofd; + char nbuf[4096], obuf[4096]; + int ncnt, ocnt; + + nfd = open(newfile, 0); + if (nfd < 0) + return; + ofd = open(oldfile, 0); + if (ofd < 0) { + close(nfd); + rename(newfile, oldfile); + return; + } + + do { + ncnt = read(nfd, nbuf, sizeof(nbuf)); + if (ncnt < 0) + break; + ocnt = read(ofd, obuf, sizeof(obuf)); + if (ocnt < 0) + break; + if (ncnt != ocnt) + break; + if (ncnt == 0) { + close(nfd); + close(ofd); + unlink(newfile); + return; + } + } while (memcmp(obuf, nbuf, ncnt) == 0); + + /* some mis-match */ + close(nfd); + close(ofd); + rename(newfile, oldfile); + return; +} |