summaryrefslogtreecommitdiff
path: root/support/export
diff options
context:
space:
mode:
authorneilbrown <neilbrown>2003-03-26 03:05:39 +0000
committerneilbrown <neilbrown>2003-03-26 03:05:39 +0000
commit16be8c20d6fe1a997d90ecb229aee6a5f092b73d (patch)
tree72625879992ba430479dd80550918facef1dfb1c /support/export
parentcec295bf37b784ed6ae5674ce34b9c75d89ea0a1 (diff)
downloadnfs-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.c98
-rw-r--r--support/export/hostname.c51
-rw-r--r--support/export/xtab.c47
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;
+}