diff options
author | hjl <hjl> | 1999-10-18 23:21:12 +0000 |
---|---|---|
committer | hjl <hjl> | 1999-10-18 23:21:12 +0000 |
commit | 8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9 (patch) | |
tree | 0904ef8554ed680fe3244fa618685e1fb7ea148b /support/export | |
download | nfs-utils-8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9.tar.gz nfs-utils-8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9.tar.xz nfs-utils-8b7ad01b14df1e7529b9ba8a1ea17df0d6004ef9.zip |
Initial revision
Diffstat (limited to 'support/export')
-rw-r--r-- | support/export/Makefile | 27 | ||||
-rw-r--r-- | support/export/client.c | 298 | ||||
-rw-r--r-- | support/export/export.c | 259 | ||||
-rw-r--r-- | support/export/hostname.c | 262 | ||||
-rw-r--r-- | support/export/keys.c | 72 | ||||
-rw-r--r-- | support/export/mount.x | 345 | ||||
-rw-r--r-- | support/export/nfsctl.c | 105 | ||||
-rw-r--r-- | support/export/rmtab.c | 79 | ||||
-rw-r--r-- | support/export/xtab.c | 133 |
9 files changed, 1580 insertions, 0 deletions
diff --git a/support/export/Makefile b/support/export/Makefile new file mode 100644 index 0000000..1243305 --- /dev/null +++ b/support/export/Makefile @@ -0,0 +1,27 @@ +# +# libexport.a +# Miscellaneous utility functions related to exporting and mounting +# of NFS volumes. +# + +LIBNAME = libexport.a +SRCS = $(RPCSRCS) client.c export.c hostname.c nfsctl.c rmtab.c \ + xtab.c +OBJS = $(SRCS:.c=.o) + +RPCSRCS = mount_clnt.c mount_xdr.c +RPCHDRS = mount.h + +include $(TOP)rules.mk + +$(RPCHDRS) $(RPCSRCS): mount.x + $(RM) $(RPCHDRS) $(RPCSRCS) + $(RPCGEN) -h -o mount.h $< + $(RPCGEN) -l -o mount_clnt.c $< + $(RPCGEN) -c -o mount_xdr.c $< + +clean distclean:: + $(RM) $(RPCHDRS) $(RPCSRCS) + +install:: + @: diff --git a/support/export/client.c b/support/export/client.c new file mode 100644 index 0000000..8c5200a --- /dev/null +++ b/support/export/client.c @@ -0,0 +1,298 @@ +/* + * support/export/client.c + * + * Maintain list of nfsd clients. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <sys/types.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdlib.h> +#include <string.h> +#include <netdb.h> +#include "xmalloc.h" +#include "misc.h" +#include "nfslib.h" +#include "exportfs.h" + +/* netgroup stuff never seems to be defined in any header file. Linux is + * not alone in this. + */ +#if !defined(__GLIBC__) || __GLIBC__ < 2 +extern int innetgr(char *netgr, char *host, char *, char *); +#endif +static void client_init(nfs_client *clp, const char *hname, + struct hostent *hp); +static int client_checkaddr(nfs_client *clp, struct in_addr addr); + +nfs_client *clientlist[MCL_MAXTYPES] = { NULL, }; + + +nfs_client * +client_lookup(char *hname) +{ + nfs_client *clp = NULL; + int htype; + struct hostent *hp = NULL; + + htype = client_gettype(hname); + + if (htype == MCL_FQDN) { + hp = gethostbyname(hname); + if (hp == NULL || hp->h_addrtype != AF_INET) { + xlog(L_ERROR, "%s has non-inet addr", hname); + return NULL; + } + hp = hostent_dup (hp); + hname = (char *) hp->h_name; + + for (clp = clientlist[htype]; clp; clp = clp->m_next) { + if (client_check(clp, hp)) + break; + } + } else { + for (clp = clientlist[htype]; clp; clp = clp->m_next) { + if (strcmp(hname, clp->m_hostname)==0) + break; + } + } + + if (!clp) { + clp = (nfs_client *) xmalloc(sizeof(*clp)); + memset(clp, 0, sizeof(*clp)); + clp->m_type = htype; + client_init(clp, hname, NULL); + client_add(clp); + } + + if (htype == MCL_FQDN && clp->m_naddr == 0 && hp != NULL) { + char **ap = hp->h_addr_list; + int i; + + for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) + clp->m_addrlist[i] = *(struct in_addr *)*ap; + clp->m_naddr = i; + } + + if (hp) + free (hp); + + return clp; +} + +nfs_client * +client_dup(nfs_client *clp, struct hostent *hp) +{ + nfs_client *new; + + new = (nfs_client *) xmalloc(sizeof(*new)); + memcpy(new, clp, sizeof(*new)); + new->m_type = MCL_FQDN; + + client_init(new, (char *) hp->h_name, hp); + client_add(new); + return new; +} + +static void +client_init(nfs_client *clp, const char *hname, struct hostent *hp) +{ + if (hp) { + strncpy(clp->m_hostname, hp->h_name, + sizeof (clp->m_hostname) - 1); + } else { + strncpy(clp->m_hostname, hname, + sizeof (clp->m_hostname) - 1); + } + clp->m_hostname[sizeof (clp->m_hostname) - 1] = '\0'; + + clp->m_exported = 0; + clp->m_count = 0; + + if (clp->m_type == MCL_SUBNETWORK) { + char *cp = strchr(clp->m_hostname, '/'); + + *cp = '\0'; + clp->m_addrlist[0].s_addr = inet_addr(clp->m_hostname); + clp->m_addrlist[1].s_addr = inet_addr(cp+1); + *cp = '/'; + clp->m_naddr = 0; + } else if (!hp) { + clp->m_naddr = 0; + } else { + char **ap = hp->h_addr_list; + int i; + + for (i = 0; *ap && i < NFSCLNT_ADDRMAX; i++, ap++) { + clp->m_addrlist[i] = *(struct in_addr *)*ap; + } + clp->m_naddr = i; + } +} + +void +client_add(nfs_client *clp) +{ + nfs_client **cpp; + + if (clp->m_type < 0 || clp->m_type >= MCL_MAXTYPES) + xlog(L_FATAL, "unknown client type in client_add"); + cpp = clientlist + clp->m_type; + while (*cpp) + cpp = &((*cpp)->m_next); + clp->m_next = NULL; + *cpp = clp; +} + +void +client_release(nfs_client *clp) +{ + if (clp->m_count <= 0) + xlog(L_FATAL, "client_free: m_count <= 0!"); + clp->m_count--; +} + +void +client_freeall(void) +{ + nfs_client *clp, **head; + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { + head = clientlist + i; + while (*head) { + *head = (clp = *head)->m_next; + xfree(clp); + } + } +} + +nfs_client * +client_find(struct hostent *hp) +{ + nfs_client *clp; + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (clp = clientlist[i]; clp; clp = clp->m_next) { + if (!client_check(clp, hp)) + continue; +#ifdef notdef + if (clp->m_type == MCL_FQDN) + return clp; + return client_dup(clp, hp); +#else + return clp; +#endif + } + } + return NULL; +} + +/* + * Match a host (given its hostent record) to a client record. This + * is usually called from mountd. + */ +int +client_check(nfs_client *clp, struct hostent *hp) +{ + char *hname = (char *) hp->h_name; + char *cname = clp->m_hostname; + char **ap; + + switch (clp->m_type) { + case MCL_FQDN: + case MCL_SUBNETWORK: + for (ap = hp->h_addr_list; *ap; ap++) { + if (client_checkaddr(clp, *(struct in_addr *) *ap)) + return 1; + } + return 0; + case MCL_WILDCARD: + if (wildmat(hname, cname)) + return 1; + else { + for (ap = hp->h_aliases; *ap; ap++) + if (wildmat(*ap, cname)) + return 1; + } + return 0; + case MCL_NETGROUP: +#ifdef HAVE_INNETGR + { + char *dot; + int match; + + /* First, try to match the hostname without + * splitting off the domain */ + if (innetgr(cname+1, hname, NULL, NULL)) + return 1; + + /* Okay, strip off the domain (if we have one) */ + if ((dot = strchr(hname, '.')) == NULL) + return 0; + + *dot = '\0'; + match = innetgr(cname+1, hname, NULL, dot + 1); + *dot = '.'; + + return match; + } +#else + return 0; +#endif + case MCL_ANONYMOUS: + return 1; + default: + xlog(L_FATAL, "internal: bad client type %d", clp->m_type); + } + + return 0; +} + +static int +client_checkaddr(nfs_client *clp, struct in_addr addr) +{ + int i; + + switch (clp->m_type) { + case MCL_FQDN: + for (i = 0; i < clp->m_naddr; i++) { + if (clp->m_addrlist[i].s_addr == addr.s_addr) + return 1; + } + return 0; + case MCL_SUBNETWORK: + return !((clp->m_addrlist[0].s_addr ^ addr.s_addr) + & clp->m_addrlist[1].s_addr); + } + return 0; +} + +int +client_gettype(char *ident) +{ + char *sp; + + if (ident[0] == '\0') + return MCL_ANONYMOUS; + if (ident[0] == '@') { +#ifndef HAVE_INNETGR + xlog(L_WARNING, "netgroup support not compiled in"); +#endif + return MCL_NETGROUP; + } + for (sp = ident; *sp; sp++) { + if (*sp == '*' || *sp == '?' || *sp == '[') + return MCL_WILDCARD; + if (*sp == '/') + return MCL_SUBNETWORK; + if (*sp == '\\' && sp[1]) + sp++; + } + return MCL_FQDN; +} diff --git a/support/export/export.c b/support/export/export.c new file mode 100644 index 0000000..09efaa8 --- /dev/null +++ b/support/export/export.c @@ -0,0 +1,259 @@ +/* + * support/export/export.c + * + * Maintain list of exported file systems. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <string.h> +#include <sys/types.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <stdlib.h> +#include "xmalloc.h" +#include "nfslib.h" +#include "exportfs.h" + +nfs_export *exportlist[MCL_MAXTYPES] = { NULL, }; + +static void export_init(nfs_export *exp, nfs_client *clp, + struct exportent *nep); +static int export_check(nfs_export *, struct hostent *, char *); +static nfs_export * + export_allowed_internal(struct hostent *hp, char *path); + +int +export_read(char *fname) +{ + struct exportent *eep; + nfs_export *exp; + + setexportent(fname, "r"); + while ((eep = getexportent()) != NULL) { + exp = export_lookup(eep->e_hostname, eep->e_path); + if (!exp) + export_create(eep); + else { + if (exp->m_export.e_flags != eep->e_flags) { + xlog(L_ERROR, "incompatible dupilcated export entries:"); + xlog(L_ERROR, "\t%s:%s (0x%x) [IGNORED]", eep->e_hostname, + eep->e_path, eep->e_flags); + xlog(L_ERROR, "\t%s:%s (0x%x)", exp->m_export.e_hostname, + exp->m_export.e_path, exp->m_export.e_flags); + } + else { + xlog(L_ERROR, "dupilcated export entries:"); + xlog(L_ERROR, "\t%s:%s", eep->e_hostname, eep->e_path); + xlog(L_ERROR, "\t%s:%s", exp->m_export.e_hostname, + exp->m_export.e_path); + } + } + } + endexportent(); + + return 0; +} + +/* + * Create an in-core export struct from an export entry. + */ +nfs_export * +export_create(struct exportent *xep) +{ + nfs_client *clp; + nfs_export *exp; + + if (!(clp = client_lookup(xep->e_hostname))) { + /* bad export entry; complaint already logged */ + return NULL; + } + exp = (nfs_export *) xmalloc(sizeof(*exp)); + export_init(exp, clp, xep); + export_add(exp); + + return exp; +} + +static void +export_init(nfs_export *exp, nfs_client *clp, struct exportent *nep) +{ + struct exportent *e = &exp->m_export; + + dupexportent(e, nep); + + exp->m_exported = 0; + exp->m_xtabent = 0; + exp->m_mayexport = 0; + exp->m_changed = 0; + exp->m_client = clp; + clp->m_count++; +} + +/* + * Duplicate exports data. The in-core export struct retains the + * original hostname from /etc/exports, while the in-core client struct + * gets the newly found FQDN. + */ +nfs_export * +export_dup(nfs_export *exp, struct hostent *hp) +{ + nfs_export *new; + nfs_client *clp; + + new = (nfs_export *) xmalloc(sizeof(*new)); + memcpy(new, exp, sizeof(*new)); + dupexportent(&new->m_export, &exp->m_export); + clp = client_dup(exp->m_client, hp); + clp->m_count++; + new->m_client = clp; + new->m_mayexport = exp->m_mayexport; + new->m_exported = 0; + new->m_xtabent = 0; + new->m_changed = 0; + export_add(new); + + return new; +} + +void +export_add(nfs_export *exp) +{ + nfs_export **epp; + int type = exp->m_client->m_type; + int slen = strlen(exp->m_export.e_path); + + if (type < 0 || type >= MCL_MAXTYPES) + xlog(L_FATAL, "unknown client type in export_add"); + + epp = exportlist + type; + while (*epp && slen < strlen((*epp)->m_export.e_path)) + epp = &((*epp)->m_next); + exp->m_next = *epp; + *epp = exp; +} + +nfs_export * +export_find(struct hostent *hp, char *path) +{ + nfs_export *exp; + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (exp = exportlist[i]; exp; exp = exp->m_next) { + if (!export_check(exp, hp, path)) + continue; + if (exp->m_client->m_type == MCL_FQDN) + return exp; + return export_dup(exp, hp); + } + } + + return NULL; +} + +static nfs_export * +export_allowed_internal (struct hostent *hp, char *path) +{ + nfs_export *exp; + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (exp = exportlist[i]; exp; exp = exp->m_next) { + if (!exp->m_mayexport || + !export_check(exp, hp, path)) + continue; + return exp; + } + } + + return NULL; +} + +struct exportent * +export_allowed(struct hostent *hp, char *path) +{ + static struct exportent ee; + nfs_export *exp; + char epath[MAXPATHLEN+1]; + char *p = NULL; + + if (path [0] != '/') return NULL; + + strncpy(epath, path, sizeof (epath) - 1); + epath[sizeof (epath) - 1] = '\0'; + + /* Try the longest matching exported pathname. */ + while (1) { + exp = export_allowed_internal (hp, epath); + if (exp) { + dupexportent(&ee, &exp->m_export); + return ⅇ + } + /* We have to treat the root, "/", specially. */ + if (p == &epath[1]) break; + p = strrchr(epath, '/'); + if (p == epath) p++; + *p = '\0'; + } + + return NULL; +} + +nfs_export * +export_lookup(char *hname, char *path) +{ + nfs_client *clp; + nfs_export *exp; + + if (!(clp = client_lookup(hname))) + return NULL; + for (exp = exportlist[clp->m_type]; exp; exp = exp->m_next) + if (exp->m_client == clp && !strcmp(exp->m_export.e_path, path)) + return exp; + return NULL; +} + +static int +export_check(nfs_export *exp, struct hostent *hp, char *path) +{ + if (strcmp(path, exp->m_export.e_path)) + return 0; + + return client_check(exp->m_client, hp); +} + +void +export_freeall(void) +{ + nfs_export *exp, *nxt; + int i; + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (exp = exportlist[i]; exp; exp = nxt) { + nxt = exp->m_next; + client_release(exp->m_client); + if (exp->m_export.e_squids) + xfree(exp->m_export.e_squids); + if (exp->m_export.e_sqgids) + xfree(exp->m_export.e_sqgids); + xfree(exp); + } + exportlist[i] = NULL; + } + client_freeall(); +} + +void +export_reset(nfs_export *exp) +{ + if (!exp) + return; + + /* Restore m_path. */ + strncpy(exp->m_export.m_path, exp->m_export.e_path, + sizeof (exp->m_export.m_path) - 1); + exp->m_export.m_path[sizeof (exp->m_export.m_path) - 1] = '\0'; +} diff --git a/support/export/hostname.c b/support/export/hostname.c new file mode 100644 index 0000000..a37d4de --- /dev/null +++ b/support/export/hostname.c @@ -0,0 +1,262 @@ +/* + * support/export/hostname.c + * + * Functions for hostname. + * + */ + +#include "config.h" + +/* +#define TEST +*/ + +#include <string.h> +#include <netdb.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <stdlib.h> +#ifdef TEST +#define xmalloc malloc +#else +#include "xmalloc.h" +#include "misc.h" +#endif + +#define ALIGNMENT sizeof (char *) + +static int +align (int len, int al) +{ + int i; + i = len % al; + if (i) + len += al - i; + return len; +} + +struct hostent * +get_hostent (const char *addr, int len, int type) +{ + struct hostent *cp; + int len_ent; + const char *name; + int len_name; + int num_aliases = 1; + int len_aliases = sizeof (char *); + int num_addr_list = 1; + int len_addr_list = sizeof (char *); + int pos; + struct in_addr *ipv4; + + switch (type) + { + case AF_INET: + ipv4 = (struct in_addr *) addr; + name = inet_ntoa (*ipv4); + break; + + default: + return NULL; + } + + len_ent = align (sizeof (*cp), ALIGNMENT); + len_name = align (strlen (name) + 1, ALIGNMENT); + + num_addr_list++; + len_addr_list += align (len, ALIGNMENT) + sizeof (char *); + + cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases + + len_addr_list); + + cp->h_addrtype = type; + cp->h_length = len; + pos = len_ent; + cp->h_name = (char *) &(((char *) cp) [pos]); + strcpy (cp->h_name, name); + + pos += len_name; + cp->h_aliases = (char **) &(((char *) cp) [pos]); + pos += num_aliases * sizeof (char *); + cp->h_aliases [0] = NULL; + + pos = len_ent + len_name + len_aliases; + cp->h_addr_list = (char **) &(((char *) cp) [pos]); + pos += num_addr_list * sizeof (char *); + cp->h_addr_list [0] = (char *) &(((char *) cp) [pos]); + memcpy (cp->h_addr_list [0], addr, cp->h_length); + pos += align (cp->h_length, ALIGNMENT); + cp->h_addr_list [1] = NULL; + + return cp; +} + +struct hostent * +hostent_dup (struct hostent *hp) +{ + int len_ent = align (sizeof (*hp), ALIGNMENT); + int len_name = align (strlen (hp->h_name) + 1, ALIGNMENT); + int num_aliases = 1; + int len_aliases = sizeof (char *); + int num_addr_list = 1; + int len_addr_list = sizeof (char *); + int pos, i; + char **sp; + struct hostent *cp; + + for (sp = hp->h_aliases; *sp; sp++) + { + num_aliases++; + len_aliases += align (strlen (*sp) + 1, ALIGNMENT) + + sizeof (char *); + } + + for (sp = hp->h_addr_list; *sp; sp++) + { + num_addr_list++; + len_addr_list += align (hp->h_length, ALIGNMENT) + + sizeof (char *); + } + + cp = (struct hostent *) xmalloc (len_ent + len_name + len_aliases + + len_addr_list); + + *cp = *hp; + pos = len_ent; + cp->h_name = (char *) &(((char *) cp) [pos]); + strcpy (cp->h_name, hp->h_name); + + pos += len_name; + cp->h_aliases = (char **) &(((char *) cp) [pos]); + pos += num_aliases * sizeof (char *); + for (sp = hp->h_aliases, i = 0; i < num_aliases; i++, sp++) + if (*sp) + { + cp->h_aliases [i] = (char *) &(((char *) cp) [pos]); + strcpy (cp->h_aliases [i], *sp); + pos += align (strlen (*sp) + 1, ALIGNMENT); + } + else + cp->h_aliases [i] = *sp; + + pos = len_ent + len_name + len_aliases; + cp->h_addr_list = (char **) &(((char *) cp) [pos]); + pos += num_addr_list * sizeof (char *); + for (sp = hp->h_addr_list, i = 0; i < num_addr_list; i++, sp++) + if (*sp) + { + cp->h_addr_list [i] = (char *) &(((char *) cp) [pos]); + memcpy (cp->h_addr_list [i], *sp, hp->h_length); + pos += align (hp->h_length, ALIGNMENT); + } + else + cp->h_addr_list [i] = *sp; + + return cp; +} + +static int +is_hostname(const char *sp) +{ + if (*sp == '\0' || *sp == '@') + return 0; + + for (; *sp; sp++) + { + if (*sp == '*' || *sp == '?' || *sp == '[' || *sp == '/') + return 0; + if (*sp == '\\' && sp[1]) + sp++; + } + + return 1; +} + +int +matchhostname (const char *h1, const char *h2) +{ + struct hostent *hp1, *hp2; + int status; + + if (strcasecmp (h1, h2) == 0) + return 1; + + if (!is_hostname (h1) || !is_hostname (h2)) + return 0; + + hp1 = gethostbyname (h1); + if (hp1 == NULL) + return 0; + + hp1 = hostent_dup (hp1); + + hp2 = gethostbyname (h2); + if (hp2) + { + if (strcasecmp (hp1->h_name, hp2->h_name) == 0) + status = 1; + else + { + char **ap1, **ap2; + + status = 0; + for (ap1 = hp1->h_addr_list; *ap1 && status == 0; ap1++) + for (ap2 = hp2->h_addr_list; *ap2; ap2++) + if (memcmp (*ap1, *ap2, sizeof (struct in_addr)) == 0) + { + status = 1; + break; + } + } + } + else + status = 0; + + free (hp1); + return status; +} + +#ifdef TEST +void +print_host (struct hostent *hp) +{ + char **sp; + + if (hp) + { + printf ("official hostname: %s\n", hp->h_name); + printf ("aliases:\n"); + for (sp = hp->h_aliases; *sp; sp++) + printf (" %s\n", *sp); + printf ("IP addresses:\n"); + for (sp = hp->h_addr_list; *sp; sp++) + printf (" %s\n", inet_ntoa (*(struct in_addr *) *sp)); + } + else + printf ("Not host information\n"); +} + +int +main (int argc, char **argv) +{ + struct hostent *hp = gethostbyname (argv [1]); + struct hostent *cp; + struct in_addr addr; + + print_host (hp); + + if (hp) + { + cp = hostent_dup (hp); + print_host (cp); + free (cp); + } + printf ("127.0.0.1 == %s: %d\n", argv [1], + matchhostname ("127.0.0.1", argv [1])); + addr.s_addr = inet_addr(argv [2]); + printf ("%s\n", inet_ntoa (addr)); + cp = get_hostent ((const char *)&addr, sizeof(addr), AF_INET); + print_host (cp); + return 0; +} +#endif diff --git a/support/export/keys.c b/support/export/keys.c new file mode 100644 index 0000000..4814808 --- /dev/null +++ b/support/export/keys.c @@ -0,0 +1,72 @@ +/* + * keys.c Key management for nfsd. Currently, keys + * are kept in a single file only, but eventually, + * support for a key server should be added. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <sys/stat.h> +#include "nfslib.h" +#include "exportfs.h" +#include "xmalloc.h" + +struct keycache { + struct keycache * k_next; + struct nfskeyent k_data; +}; + +static struct keycache * keycache = NULL; +static time_t lastmod = 0; + +static void key_reload(void); + + +struct nfskey * +key_lookup(char *hname) +{ + struct keycache *kc; + + key_reload(); + + for (kc = keycache; kc; kc = kc->k_next) { +#if 0 + if (matchhostname(kc->k_data.k_hostname, hname)) +#else + if (!strcmp(kc->k_data.k_hostname, hname)) +#endif + return &kc->k_data.k_key; + } + + return NULL; +} + +static void +key_reload(void) +{ + struct stat stb; + struct keycache *cp; + struct nfskeyent *kp; + + if (stat(_PATH_NFSKEYS, &stb) >= 0 && stb.st_mtime == lastmod) + return; + + while (keycache) { + cp = keycache->k_next; + xfree(keycache); + keycache = cp; + } + + setnfskeyent(_PATH_NFSKEYS); + while ((kp = getnfskeyent()) != NULL) { + cp = (struct keycache *) xmalloc(sizeof(*cp)); + cp->k_data = *kp; + cp->k_next = keycache; + keycache = cp; + } + endnfskeyent(); + + lastmod = stb.st_mtime; +} diff --git a/support/export/mount.x b/support/export/mount.x new file mode 100644 index 0000000..f504e7c --- /dev/null +++ b/support/export/mount.x @@ -0,0 +1,345 @@ +%/* +% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for +% * unrestricted use provided that this legend is included on all tape +% * media and as a part of the software program in whole or part. Users +% * may copy or modify Sun RPC without charge, but are not authorized +% * to license or distribute it to anyone else except as part of a product or +% * program developed by the user or with the express written consent of +% * Sun Microsystems, Inc. +% * +% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE +% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR +% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. +% * +% * Sun RPC is provided with no support and without any obligation on the +% * part of Sun Microsystems, Inc. to assist in its use, correction, +% * modification or enhancement. +% * +% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE +% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC +% * OR ANY PART THEREOF. +% * +% * In no event will Sun Microsystems, Inc. be liable for any lost revenue +% * or profits or other special, indirect and consequential damages, even if +% * Sun has been advised of the possibility of such damages. +% * +% * Sun Microsystems, Inc. +% * 2550 Garcia Avenue +% * Mountain View, California 94043 +% */ + +%/* +% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc. +% */ +% +%/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */ + +/* + * Protocol description for the mount program + */ + +#ifdef RPC_HDR +%#ifndef _rpcsvc_mount_h +%#define _rpcsvc_mount_h +%#include <memory.h> +#endif + +const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */ +const MNTNAMLEN = 255; /* maximum bytes in a name argument */ +const FHSIZE = 32; /* size in bytes of a file handle */ + +/* + * The fhandle is the file handle that the server passes to the client. + * All file operations are done using the file handles to refer to a file + * or a directory. The file handle can contain whatever information the + * server needs to distinguish an individual file. + */ +typedef opaque fhandle[FHSIZE]; + +/* + * If a status of zero is returned, the call completed successfully, and + * a file handle for the directory follows. A non-zero status indicates + * some sort of error. The status corresponds with UNIX error numbers. + */ +union fhstatus switch (unsigned fhs_status) { +case 0: + fhandle fhs_fhandle; +default: + void; +}; + +/* + * The type dirpath is the pathname of a directory + */ +typedef string dirpath<MNTPATHLEN>; + +/* + * The type name is used for arbitrary names (hostnames, groupnames) + */ +typedef string name<MNTNAMLEN>; + +/* + * A list of who has what mounted + */ +typedef struct mountbody *mountlist; +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; + +/* + * A list of netgroups + */ +typedef struct groupnode *groups; +struct groupnode { + name gr_name; + groups gr_next; +}; + +/* + * A list of what is exported and to whom + */ +typedef struct exportnode *exports; +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; + +/* + * POSIX pathconf information + */ +struct ppathcnf { + int pc_link_max; /* max links allowed */ + short pc_max_canon; /* max line len for a tty */ + short pc_max_input; /* input a tty can eat all at once */ + short pc_name_max; /* max file name length (dir entry) */ + short pc_path_max; /* max path name length (/x/y/x/.. ) */ + short pc_pipe_buf; /* size of a pipe (bytes) */ + u_char pc_vdisable; /* safe char to turn off c_cc[i] */ + char pc_xxx; /* alignment padding; cc_t == char */ + short pc_mask[2]; /* validity and boolean bits */ +}; + +/* + * NFSv3 file handle + */ +const FHSIZE3 = 64; /* max size of NFSv3 file handle in bytes */ +typedef opaque fhandle3<FHSIZE3>; + +/* + * NFSv3 mount status + */ +enum mountstat3 { + MNT_OK = 0, /* no error */ + MNT3ERR_PERM = 1, /* not owner */ + MNT3ERR_NOENT = 2, /* no such file or directory */ + MNT3ERR_IO = 5, /* I/O error */ + MNT3ERR_ACCES = 13, /* Permission denied */ + MNT3ERR_NOTDIR = 20, /* Not a directory */ + MNT3ERR_INVAL = 22, /* Invalid argument */ + MNT3ERR_NAMETOOLONG = 63, /* File name too long */ + MNT3ERR_NOTSUPP = 10004,/* Operation not supported */ + MNT3ERR_SERVERFAULT = 10006 /* A failure on the server */ +}; + +/* + * NFSv3 mount result + */ +struct mountres3_ok { + fhandle3 fhandle; + int auth_flavors<>; +}; + +union mountres3 switch (mountstat3 fhs_status) { +case MNT_OK: + mountres3_ok mountinfo; /* File handle and supported flavors */ +default: + void; +}; + +program MOUNTPROG { + /* + * Version one of the mount protocol communicates with version two + * of the NFS protocol. The only connecting point is the fhandle + * structure, which is the same for both protocols. + */ + version MOUNTVERS { + /* + * Does no work. It is made available in all RPC services + * to allow server reponse testing and timing + */ + void + MOUNTPROC_NULL(void) = 0; + + /* + * If fhs_status is 0, then fhs_fhandle contains the + * file handle for the directory. This file handle may + * be used in the NFS protocol. This procedure also adds + * a new entry to the mount list for this client mounting + * the directory. + * Unix authentication required. + */ + fhstatus + MOUNTPROC_MNT(dirpath) = 1; + + /* + * Returns the list of remotely mounted filesystems. The + * mountlist contains one entry for each hostname and + * directory pair. + */ + mountlist + MOUNTPROC_DUMP(void) = 2; + + /* + * Removes the mount list entry for the directory + * Unix authentication required. + */ + void + MOUNTPROC_UMNT(dirpath) = 3; + + /* + * Removes all of the mount list entries for this client + * Unix authentication required. + */ + void + MOUNTPROC_UMNTALL(void) = 4; + + /* + * Returns a list of all the exported filesystems, and which + * machines are allowed to import it. + */ + exports + MOUNTPROC_EXPORT(void) = 5; + + /* + * Identical to MOUNTPROC_EXPORT above + */ + exports + MOUNTPROC_EXPORTALL(void) = 6; + } = 1; + + /* + * Version two of the mount protocol communicates with version two + * of the NFS protocol. + * The only difference from version one is the addition of a POSIX + * pathconf call. + */ + version MOUNTVERS_POSIX { + /* + * Does no work. It is made available in all RPC services + * to allow server reponse testing and timing + */ + void + MOUNTPROC_NULL(void) = 0; + + /* + * If fhs_status is 0, then fhs_fhandle contains the + * file handle for the directory. This file handle may + * be used in the NFS protocol. This procedure also adds + * a new entry to the mount list for this client mounting + * the directory. + * Unix authentication required. + */ + fhstatus + MOUNTPROC_MNT(dirpath) = 1; + + /* + * Returns the list of remotely mounted filesystems. The + * mountlist contains one entry for each hostname and + * directory pair. + */ + mountlist + MOUNTPROC_DUMP(void) = 2; + + /* + * Removes the mount list entry for the directory + * Unix authentication required. + */ + void + MOUNTPROC_UMNT(dirpath) = 3; + + /* + * Removes all of the mount list entries for this client + * Unix authentication required. + */ + void + MOUNTPROC_UMNTALL(void) = 4; + + /* + * Returns a list of all the exported filesystems, and which + * machines are allowed to import it. + */ + exports + MOUNTPROC_EXPORT(void) = 5; + + /* + * Identical to MOUNTPROC_EXPORT above + */ + exports + MOUNTPROC_EXPORTALL(void) = 6; + + /* + * POSIX pathconf info (Sun hack) + */ + ppathcnf + MOUNTPROC_PATHCONF(dirpath) = 7; + } = 2; + + /* + * Version 3 of the protocol is for NFSv3 + */ + version MOUNTVERS_NFSV3 { + /* + * Does no work. It is made available in all RPC services + * to allow server reponse testing and timing + */ + void + MOUNTPROC3_NULL(void) = 0; + + /* + * If fhs_status is 0, then fhs_fhandle contains the + * file handle for the directory. This file handle may + * be used in the NFS protocol. This procedure also adds + * a new entry to the mount list for this client mounting + * the directory. + * Unix authentication required. + */ + mountres3 + MOUNTPROC3_MNT(dirpath) = 1; + + /* + * Returns the list of remotely mounted filesystems. The + * mountlist contains one entry for each hostname and + * directory pair. + */ + mountlist + MOUNTPROC3_DUMP(void) = 2; + + /* + * Removes the mount list entry for the directory + * Unix authentication required. + */ + void + MOUNTPROC3_UMNT(dirpath) = 3; + + /* + * Removes all of the mount list entries for this client + * Unix authentication required. + */ + void + MOUNTPROC3_UMNTALL(void) = 4; + + /* + * Returns a list of all the exported filesystems, and which + * machines are allowed to import it. + */ + exports + MOUNTPROC3_EXPORT(void) = 5; + } = 3; +} = 100005; + +#ifdef RPC_HDR +%#endif /*!_rpcsvc_mount_h*/ +#endif diff --git a/support/export/nfsctl.c b/support/export/nfsctl.c new file mode 100644 index 0000000..6612a76 --- /dev/null +++ b/support/export/nfsctl.c @@ -0,0 +1,105 @@ +/* + * support/export/nfsctl.c + * + * Communicate export information to knfsd. + * + * Copyright (C) 1995 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <sys/stat.h> +#include <stdlib.h> +#include <string.h> +#include <ctype.h> +#include "nfslib.h" +#include "exportfs.h" +#include "xio.h" + +static int expsetup(struct nfsctl_export *exparg, nfs_export *exp); +static int cltsetup(struct nfsctl_client *cltarg, nfs_client *clp); + +int +export_export(nfs_export *exp) +{ + nfs_client * clp = exp->m_client; + struct nfsctl_export exparg; + struct nfsctl_client cltarg; + + if (!clp->m_exported) { + if (!cltsetup(&cltarg, clp)) + return 0; + if (nfsaddclient(&cltarg) < 0) + return 0; + clp->m_exported = 1; + } + if (!expsetup(&exparg, exp)) + return 0; + if (nfsexport(&exparg) < 0) + return 0; + exp->m_exported = 1; + return 1; +} + +int +export_unexport(nfs_export *exp) +{ + struct nfsctl_export exparg; + + if (!expsetup(&exparg, exp) || nfsunexport(&exparg) < 0) + return 0; + exp->m_exported = 0; + return 1; +} + +static void +str_tolower(char *s) +{ + for ( ; *s; s++) + if (isupper(*s)) + *s = tolower(*s); +} + +static int +cltsetup(struct nfsctl_client *cltarg, nfs_client *clp) +{ + int i; + + if (clp->m_type != MCL_FQDN) { + xlog(L_ERROR, "internal: can't export non-FQDN host"); + return 0; + } + memset(cltarg, 0, sizeof(*cltarg)); + strncpy(cltarg->cl_ident, clp->m_hostname, + sizeof (cltarg->cl_ident) - 1); + str_tolower(cltarg->cl_ident); + cltarg->cl_naddr = clp->m_naddr; + for (i = 0; i < cltarg->cl_naddr && i < NFSCLNT_ADDRMAX; i++) + cltarg->cl_addrlist[i] = clp->m_addrlist[i]; + + return 1; +} + +static int +expsetup(struct nfsctl_export *exparg, nfs_export *exp) +{ + nfs_client *clp = exp->m_client; + struct stat stb; + + if (stat(exp->m_export.m_path, &stb) < 0) + return 0; + + memset(exparg, 0, sizeof(*exparg)); + strncpy(exparg->ex_path, exp->m_export.m_path, + sizeof (exparg->ex_path) - 1); + strncpy(exparg->ex_client, clp->m_hostname, + sizeof (exparg->ex_client) - 1); + str_tolower(exparg->ex_client); + exparg->ex_flags = exp->m_export.e_flags; + exparg->ex_dev = stb.st_dev; + exparg->ex_ino = stb.st_ino; + exparg->ex_anon_uid = exp->m_export.e_anonuid; + exparg->ex_anon_gid = exp->m_export.e_anongid; + + return 1; +} diff --git a/support/export/rmtab.c b/support/export/rmtab.c new file mode 100644 index 0000000..44a0edc --- /dev/null +++ b/support/export/rmtab.c @@ -0,0 +1,79 @@ +/* + * support/export/rmntab.c + * + * Interface to the rmnt file. + * + */ + +#include "config.h" + +#include <stdlib.h> +#include <string.h> +#include <errno.h> +#include "xmalloc.h" +#include "misc.h" +#include "nfslib.h" +#include "exportfs.h" +#include "xio.h" +#include "xlog.h" + +int +rmtab_read(void) +{ + struct rmtabent *rep; + nfs_export *exp; + + setrmtabent("r"); + while ((rep = getrmtabent(1)) != NULL) { + exp = export_lookup(rep->r_client, rep->r_path); + if (!exp) { + struct exportent *xp; + struct hostent *hp; + int htype; + + htype = client_gettype(rep->r_client); + if (htype == MCL_FQDN + && (hp = gethostbyname (rep->r_client), hp) + && (hp = hostent_dup (hp), + xp = export_allowed (hp, rep->r_path))) { + strncpy (xp->e_hostname, rep->r_client, + sizeof (xp->e_hostname) - 1); + xp->e_hostname[sizeof (xp->e_hostname) -1] = '\0'; + exp = export_create(xp); + free (hp); + } + + if (!exp) + continue; + exp->m_mayexport = 1; + } + } + if (errno == EINVAL) { + /* Something goes wrong. We need to fix the rmtab + file. */ + int lockid; + FILE *fp; + if ((lockid = xflock(_PATH_RMTAB, "w")) < 0) + return -1; + rewindrmtabent(); + if (!(fp = fsetrmtabent(_PATH_RMTABTMP, "w"))) { + endrmtabent (); + xfunlock(lockid); + return -1; + } + while ((rep = getrmtabent(0)) != NULL) { + fputrmtabent(fp, rep); + } + if (rename(_PATH_RMTABTMP, _PATH_RMTAB) < 0) { + xlog(L_ERROR, "couldn't rename %s to %s", + _PATH_RMTABTMP, _PATH_RMTAB); + } + endrmtabent(); + fendrmtabent(fp); + xfunlock(lockid); + } + else { + endrmtabent(); + } + return 0; +} diff --git a/support/export/xtab.c b/support/export/xtab.c new file mode 100644 index 0000000..4289d7c --- /dev/null +++ b/support/export/xtab.c @@ -0,0 +1,133 @@ +/* + * support/export/xtab.c + * + * Interface to the xtab file. + * + * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> + */ + +#include "config.h" + +#include <sys/fcntl.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include "xmalloc.h" +#include "nfslib.h" +#include "exportfs.h" +#include "xio.h" +#include "xlog.h" + +static int +xtab_read(char *xtab, int is_export) +{ + struct exportent *xp; + nfs_export *exp; + int lockid; + + if ((lockid = xflock(xtab, "r")) < 0) + return 0; + setexportent(xtab, "r"); + while ((xp = getexportent()) != NULL) { + if (!(exp = export_lookup(xp->e_hostname, xp->e_path)) && + !(exp = export_create(xp))) { + continue; + } + if (is_export) { + exp->m_xtabent = 1; + exp->m_mayexport = 1; + } else + exp->m_exported = 1; + } + endexportent(); + xfunlock(lockid); + + return 0; +} + +int +xtab_mount_read(void) +{ + int fd; + if ((fd=open(_PATH_PROC_EXPORTS, O_RDONLY))>=0) { + close(fd); + return xtab_read(_PATH_PROC_EXPORTS, 0); + } else + return xtab_read(_PATH_XTAB, 0); +} + +int +xtab_export_read(void) +{ + return xtab_read(_PATH_ETAB, 1); +} + +static int +xtab_write(char *xtab, char *xtabtmp, int is_export) +{ + struct exportent xe; + nfs_export *exp; + int lockid, i; + + if ((lockid = xflock(xtab, "w")) < 0) { + xlog(L_ERROR, "can't lock %s for writing", xtab); + return 0; + } + setexportent(xtabtmp, "w"); + + for (i = 0; i < MCL_MAXTYPES; i++) { + for (exp = exportlist[i]; exp; exp = exp->m_next) { + if (is_export && !exp->m_xtabent) + continue; + if (!is_export && ! exp->m_exported) + continue; + + /* write out the export entry using the FQDN */ + xe = exp->m_export; + strncpy(xe.e_hostname, + exp->m_client->m_hostname, + sizeof (xe.e_hostname) - 1); + xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0'; + putexportent(&xe); + } + } + endexportent(); + + rename(xtabtmp, xtab); + + xfunlock(lockid); + + return 1; +} + +int +xtab_export_write() +{ + return xtab_write(_PATH_ETAB, _PATH_ETABTMP, 1); +} + +int +xtab_mount_write() +{ + return xtab_write(_PATH_XTAB, _PATH_XTABTMP, 0); +} + +void +xtab_append(nfs_export *exp) +{ + struct exportent xe; + int lockid; + + if ((lockid = xflock(_PATH_XTAB, "w")) < 0) + return; + setexportent(_PATH_XTAB, "a"); + xe = exp->m_export; + strncpy(xe.e_hostname, exp->m_client->m_hostname, + sizeof (xe.e_hostname) - 1); + xe.e_hostname[sizeof (xe.e_hostname) - 1] = '\0'; + putexportent(&xe); + endexportent(); + xfunlock(lockid); + exp->m_xtabent = 1; +} + |